1<?php 2 3// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps 4// phpcs:disable PSR2.Methods.MethodDeclaration.Underscore 5 6use dokuwiki\Extension\SyntaxPlugin; 7use dokuwiki\File\PageResolver; 8 9/** 10 * Renderer for preparing data for embedding 11 * 12 * Based on the text and markdown renderers 13 * 14 * @todo table handling is not perfect 15 * @author Michael Hamann <michael@content-space.de> 16 * @author Todd Augsburger <todd@rollerorgans.com> 17 * @author i-net software <tools@inetsoftware.de> 18 * @link https://www.dokuwiki.org/plugin:text 19 * @link https://www.dokuwiki.org/plugin:dw2markdown 20 */ 21class renderer_plugin_aichat extends Doku_Renderer_xhtml 22{ 23 /** @var array The stack of list types */ 24 private $listMode = []; 25 26 /** @var int Number of table columns */ 27 private $tableColumns = 0; 28 29 /** @inheritdoc */ 30 public function getFormat() 31 { 32 return 'aichat'; 33 } 34 35 /** @inheritdoc */ 36 public function startSectionEdit($start, $data, $title = null) 37 { 38 } 39 40 /** @inheritdoc */ 41 public function finishSectionEdit($end = null, $hid = null) 42 { 43 } 44 45 /** 46 * @inheritdoc 47 * Use specific text support if available, otherwise use xhtml renderer and strip tags 48 */ 49 public function plugin($name, $data, $state = '', $match = '') 50 { 51 /** @var SyntaxPlugin $plugin */ 52 $plugin = plugin_load('syntax', $name); 53 if ($plugin === null) return; 54 55 if ( 56 !$plugin->render($this->getFormat(), $this, $data) && 57 !$plugin->render('text', $this, $data) && 58 !$plugin->render('markdown', $this, $data) 59 ) { 60 // plugin does not support any of the text formats, so use stripped-down xhtml 61 $tmpData = $this->doc; 62 $this->doc = ''; 63 if ($plugin->render('xhtml', $this, $data) && ($this->doc !== '')) { 64 $pluginoutput = $this->doc; 65 $this->doc = $tmpData . DOKU_LF . trim(strip_tags($pluginoutput)) . DOKU_LF; 66 } else { 67 $this->doc = $tmpData; 68 } 69 } 70 } 71 72 /** @inheritdoc */ 73 public function document_start() 74 { 75 global $ID; 76 77 $this->doc = ''; 78 $metaheader = []; 79 $metaheader['Content-Type'] = 'text/plain; charset=utf-8'; 80 $meta = []; 81 $meta['format']['aichat'] = $metaheader; 82 p_set_metadata($ID, $meta); 83 } 84 85 /** @inheritdoc */ 86 public function document_end() 87 { 88 $this->doc = preg_replace("/(\r?\n){3,}/", "\n\n", $this->doc); 89 $this->doc = ltrim($this->doc); // remove leading space and empty lines 90 } 91 92 /** @inheritdoc */ 93 public function header($text, $level, $pos, $returnonly = false) 94 { 95 $this->doc .= str_repeat("#", $level) . ' ' . $text . DOKU_LF; 96 } 97 98 /** @inheritdoc */ 99 public function section_open($level) 100 { 101 $this->doc .= DOKU_LF; 102 } 103 104 /** @inheritdoc */ 105 public function section_close() 106 { 107 $this->doc .= DOKU_LF; 108 } 109 110 /** @inheritdoc */ 111 public function cdata($text) 112 { 113 $this->doc .= $text; 114 } 115 116 /** @inheritdoc */ 117 public function p_open() 118 { 119 $this->doc .= DOKU_LF; 120 } 121 122 /** @inheritdoc */ 123 public function p_close() 124 { 125 $this->doc .= DOKU_LF; 126 } 127 128 /** @inheritdoc */ 129 public function linebreak() 130 { 131 $this->doc .= DOKU_LF . DOKU_LF; 132 } 133 134 /** @inheritdoc */ 135 public function hr() 136 { 137 $this->doc .= '----' . DOKU_LF; 138 } 139 140 /** @inheritdoc */ 141 public function strong_open() 142 { 143 } 144 145 /** @inheritdoc */ 146 public function strong_close() 147 { 148 } 149 150 /** @inheritdoc */ 151 public function emphasis_open() 152 { 153 } 154 155 /** @inheritdoc */ 156 public function emphasis_close() 157 { 158 } 159 160 /** @inheritdoc */ 161 public function underline_open() 162 { 163 } 164 165 /** @inheritdoc */ 166 public function underline_close() 167 { 168 } 169 170 /** @inheritdoc */ 171 public function monospace_open() 172 { 173 } 174 175 /** @inheritdoc */ 176 public function monospace_close() 177 { 178 } 179 180 /** @inheritdoc */ 181 public function subscript_open() 182 { 183 } 184 185 /** @inheritdoc */ 186 public function subscript_close() 187 { 188 } 189 190 /** @inheritdoc */ 191 public function superscript_open() 192 { 193 } 194 195 /** @inheritdoc */ 196 public function superscript_close() 197 { 198 } 199 200 /** @inheritdoc */ 201 public function deleted_open() 202 { 203 } 204 205 /** @inheritdoc */ 206 public function deleted_close() 207 { 208 } 209 210 /** @inheritdoc */ 211 public function footnote_open() 212 { 213 $this->doc .= ' (('; 214 } 215 216 /** @inheritdoc */ 217 public function footnote_close() 218 { 219 $this->doc .= '))'; 220 } 221 222 /** @inheritdoc */ 223 public function listu_open($classes = null) 224 { 225 if ($this->listMode === []) { 226 $this->doc .= DOKU_LF; 227 } 228 $this->listMode[] = '*'; 229 } 230 231 /** @inheritdoc */ 232 public function listu_close() 233 { 234 array_pop($this->listMode); 235 if ($this->listMode === []) { 236 $this->doc .= DOKU_LF; 237 } 238 } 239 240 /** @inheritdoc */ 241 public function listo_open($classes = null) 242 { 243 if ($this->listMode === []) { 244 $this->doc .= DOKU_LF; 245 } 246 $this->listMode[] = '1.'; 247 } 248 249 /** @inheritdoc */ 250 public function listo_close() 251 { 252 array_pop($this->listMode); 253 if ($this->listMode === []) { 254 $this->doc .= DOKU_LF; 255 } 256 } 257 258 /** @inheritdoc */ 259 public function listitem_open($level, $node = false) 260 { 261 $this->doc .= str_repeat(' ', $level * 2) . $this->listMode[count($this->listMode) - 1]; 262 } 263 264 /** @inheritdoc */ 265 public function listitem_close() 266 { 267 } 268 269 270 /** @inheritdoc */ 271 public function listcontent_open() 272 { 273 } 274 275 /** @inheritdoc */ 276 public function listcontent_close() 277 { 278 $this->doc .= DOKU_LF; 279 } 280 281 /** @inheritdoc */ 282 public function unformatted($text) 283 { 284 $this->doc .= $text; 285 } 286 287 /** @inheritdoc */ 288 public function quote_open() 289 { 290 $this->doc .= '>>>'; 291 } 292 293 /** @inheritdoc */ 294 public function quote_close() 295 { 296 $this->doc .= '<<<' . DOKU_LF; 297 } 298 299 /** @inheritdoc */ 300 public function preformatted($text) 301 { 302 $this->code($text); 303 } 304 305 /** @inheritdoc */ 306 public function file($text, $language = null, $filename = null, $options = null) 307 { 308 $this->code($text, $language, $filename, $options); 309 } 310 311 /** @inheritdoc */ 312 public function code($text, $language = null, $filename = null, $options = null) 313 { 314 $this->doc .= DOKU_LF . '```' . ($language ?? '') . DOKU_LF . trim($text) . DOKU_LF . '```' . DOKU_LF; 315 } 316 317 /** @inheritdoc */ 318 public function acronym($acronym) 319 { 320 if (array_key_exists($acronym, $this->acronyms)) { 321 $title = $this->acronyms[$acronym]; 322 $this->doc .= $acronym . ' (' . $title . ')'; 323 } else { 324 $this->doc .= $acronym; 325 } 326 } 327 328 /** @inheritdoc */ 329 public function smiley($smiley) 330 { 331 $this->doc .= $smiley; 332 } 333 334 /** @inheritdoc */ 335 public function entity($entity) 336 { 337 if (array_key_exists($entity, $this->entities)) { 338 $this->doc .= $this->entities[$entity]; 339 } else { 340 $this->doc .= $entity; 341 } 342 } 343 344 /** @inheritdoc */ 345 public function multiplyentity($x, $y) 346 { 347 $this->doc .= $x . 'x' . $y; 348 } 349 350 /** @inheritdoc */ 351 public function singlequoteopening() 352 { 353 global $lang; 354 $this->doc .= $lang['singlequoteopening']; 355 } 356 357 /** @inheritdoc */ 358 public function singlequoteclosing() 359 { 360 global $lang; 361 $this->doc .= $lang['singlequoteclosing']; 362 } 363 364 /** @inheritdoc */ 365 public function apostrophe() 366 { 367 global $lang; 368 $this->doc .= $lang['apostrophe']; 369 } 370 371 /** @inheritdoc */ 372 public function doublequoteopening() 373 { 374 global $lang; 375 $this->doc .= $lang['doublequoteopening']; 376 } 377 378 /** @inheritdoc */ 379 public function doublequoteclosing() 380 { 381 global $lang; 382 $this->doc .= $lang['doublequoteclosing']; 383 } 384 385 /** @inheritdoc */ 386 public function camelcaselink($link, $returnonly = false) 387 { 388 $this->internallink($link, $link); 389 } 390 391 /** @inheritdoc */ 392 public function locallink($hash, $name = null, $returnonly = false) 393 { 394 $name = $this->_getLinkTitle($name, $hash, $isImage); 395 $this->doc .= $name; 396 } 397 398 /** @inheritdoc */ 399 public function internallink($id, $name = null, $search = null, $returnonly = false, $linktype = 'content') 400 { 401 global $ID; 402 // default name is based on $id as given 403 $default = $this->_simpleTitle($id); 404 $resolver = new PageResolver($ID); 405 $id = $resolver->resolveId($id); 406 407 $name = $this->_getLinkTitle($name, $default, $isImage, $id, $linktype); 408 if ($returnonly) { 409 return $name; 410 } 411 $this->doc .= $name; 412 return null; 413 } 414 415 /** @inheritdoc */ 416 public function externallink($url, $name = null, $returnonly = false) 417 { 418 $title = $this->_getLinkTitle($name, $url, $isImage); 419 if ($title != $url) { 420 $this->doc .= "[$title]($url)"; 421 } else { 422 $this->doc .= $title; 423 } 424 } 425 426 /** @inheritdoc */ 427 public function interwikilink($match, $name, $wikiName, $wikiUri, $returnonly = false) 428 { 429 $this->doc .= $this->_getLinkTitle($name, $wikiUri, $isImage); 430 } 431 432 /** @inheritdoc */ 433 public function windowssharelink($url, $name = null, $returnonly = false) 434 { 435 $this->doc .= $this->_getLinkTitle($name, $url, $isImage); 436 } 437 438 /** @inheritdoc */ 439 public function emaillink($address, $name = null, $returnonly = false) 440 { 441 $name = $this->_getLinkTitle($name, '', $isImage); 442 $address = html_entity_decode(obfuscate($address), ENT_QUOTES, 'UTF-8'); 443 if (empty($name)) { 444 $name = $address; 445 } 446 $this->doc .= $name; 447 } 448 449 /** @inheritdoc */ 450 public function internalmedia( 451 $src, 452 $title = null, 453 $align = null, 454 $width = null, 455 $height = null, 456 $cache = null, 457 $linking = null, 458 $return = false 459 ) { 460 $this->doc .= $title; 461 } 462 463 /** @inheritdoc */ 464 public function externalmedia( 465 $src, 466 $title = null, 467 $align = null, 468 $width = null, 469 $height = null, 470 $cache = null, 471 $linking = null, 472 $return = false 473 ) { 474 $this->doc .= $title; 475 } 476 477 /** @inheritdoc */ 478 public function rss($url, $params) 479 { 480 } 481 482 /** @inheritdoc */ 483 public function table_open($maxcols = null, $numrows = null, $pos = null, $classes = null) 484 { 485 } 486 487 /** @inheritdoc */ 488 public function table_close($pos = null) 489 { 490 $this->doc .= DOKU_LF; 491 } 492 493 /** @inheritdoc */ 494 public function tablethead_open() 495 { 496 $this->tableColumns = 0; 497 $this->doc .= DOKU_LF; // . '|'; 498 } 499 500 /** @inheritdoc */ 501 public function tablethead_close() 502 { 503 $this->doc .= '|' . str_repeat('---|', $this->tableColumns) . DOKU_LF; 504 } 505 506 /** @inheritdoc */ 507 public function tabletbody_open() 508 { 509 } 510 511 /** @inheritdoc */ 512 public function tabletbody_close() 513 { 514 } 515 516 /** @inheritdoc */ 517 public function tabletfoot_open() 518 { 519 } 520 521 /** @inheritdoc */ 522 public function tabletfoot_close() 523 { 524 } 525 526 /** @inheritdoc */ 527 public function tablerow_open($classes = null) 528 { 529 } 530 531 /** @inheritdoc */ 532 public function tablerow_close() 533 { 534 $this->doc .= '|' . DOKU_LF; 535 } 536 537 /** @inheritdoc */ 538 public function tableheader_open($colspan = 1, $align = null, $rowspan = 1, $classes = null) 539 { 540 $this->doc .= str_repeat('|', $colspan); 541 $this->tableColumns += $colspan; 542 } 543 544 /** @inheritdoc */ 545 public function tableheader_close() 546 { 547 } 548 549 /** @inheritdoc */ 550 public function tablecell_open($colspan = 1, $align = null, $rowspan = 1, $classes = null) 551 { 552 $this->doc .= str_repeat('|', $colspan); 553 } 554 555 /** @inheritdoc */ 556 public function tablecell_close() 557 { 558 } 559 560 /** @inheritdoc */ 561 public function _getLinkTitle($title, $default, &$isImage, $id = null, $linktype = 'content') 562 { 563 $isImage = false; 564 if (is_array($title)) { 565 $isImage = true; 566 if (!is_null($default) && ($default != $title['title'])) 567 return $default . " " . $title['title']; 568 else return $title['title']; 569 } elseif (is_null($title) || trim($title) == '') { 570 if (useHeading($linktype) && $id) { 571 $heading = p_get_first_heading($id); 572 if ($heading) { 573 return $this->_xmlEntities($heading); 574 } 575 } 576 return $this->_xmlEntities($default); 577 } else { 578 return $this->_xmlEntities($title); 579 } 580 } 581 582 /** @inheritdoc */ 583 public function _xmlEntities($string) 584 { 585 return $string; // nothing to do for text 586 } 587 588 /** @inheritdoc */ 589 public function _formatLink($link) 590 { 591 if (!empty($link['name'])) { 592 return $link['name']; 593 } elseif (!empty($link['title'])) { 594 return $link['title']; 595 } 596 return $link['url']; 597 } 598} 599