1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7 8//this script may only be included - so its better to die if called directly. 9if (strpos($_SERVER["SCRIPT_NAME"], basename(__FILE__)) !== false) { 10 header("location: index.php"); 11 exit; 12} 13 14include_once('lib/smarty_tiki/block.self_link.php'); 15 16$toolbarPickerIndex = -1; 17 18abstract class Toolbar 19{ 20 protected $wysiwyg; 21 protected $icon; 22 protected $iconname; 23 protected $label; 24 protected $type; 25 26 private $requiredPrefs = []; 27 28 public static function getTag($tagName, $wysiwyg = false, $is_html = false) // {{{ 29 { 30 global $section; 31 //we detect sheet first because it has unique buttons 32 if ($section == 'sheet' && $tag = ToolbarSheet::fromName($tagName)) { 33 return $tag; 34 } elseif ($wysiwyg && $tag = ToolbarCkOnly::fromName($tagName, $is_html)) { 35 return $tag; 36 } elseif ($tag = Toolbar::getCustomTool($tagName)) { 37 return $tag; 38 } elseif ($tag = ToolbarInline::fromName($tagName)) { 39 return $tag; 40 } elseif ($tag = ToolbarBlock::fromName($tagName)) { 41 return $tag; 42 } elseif ($tag = ToolbarLineBased::fromName($tagName)) { 43 return $tag; 44 } elseif ($tag = ToolbarWikiplugin::fromName($tagName)) { 45 return $tag; 46 } elseif ($tag = ToolbarPicker::fromName($tagName)) { 47 return $tag; 48 } elseif ($tag = ToolbarDialog::fromName($tagName)) { 49 return $tag; 50 } elseif ($tagName == 'fullscreen') { 51 return new ToolbarFullscreen; 52 } elseif ($tagName == 'tikiimage') { 53 return new ToolbarFileGallery; 54 } elseif ($tagName == 'tikifile') { 55 return new ToolbarFileGalleryFile; 56 } elseif ($tagName == 'help') { 57 return new ToolbarHelptool; 58 } elseif ($tagName == 'switcheditor') { 59 return new ToolbarSwitchEditor; 60 } elseif ($tagName == 'admintoolbar') { 61 return new ToolbarAdmin; 62 } elseif ($tagName == '-') { 63 return new ToolbarSeparator; 64 } elseif ($tagName == '|') { 65 return new ToolbarSpacer; 66 } 67 } // }}} 68 69 public static function getList($include_custom = true) // {{{ 70 { 71 global $tikilib; 72 $parserlib = TikiLib::lib('parser'); 73 $plugins = $parserlib->plugin_get_list(); 74 75 foreach ($plugins as & $name) { 76 $name = "wikiplugin_$name"; 77 } 78 79 if ($include_custom) { 80 $custom = Toolbar::getCustomList(); 81 $plugins = array_merge($plugins, $custom); 82 } 83 84 return array_unique( 85 array_merge( 86 [ 87 '-', 88 '|', 89 'bold', 90 'italic', 91 'underline', 92 'strike', 93 'code', 94 'sub', 95 'sup', 96 'tikilink', 97 'link', 98 'anchor', 99 'color', 100 'bgcolor', 101 'center', 102 'table', 103 'rule', 104 'pagebreak', 105 'box', 106 'email', 107 'h1', 108 'h2', 109 'h3', 110 'titlebar', 111 'pastlink', 112 'toc', 113 'list', 114 'numlist', 115 'specialchar', 116 'smiley', 117 'templates', 118 'cut', 119 'copy', 120 'paste', 121 'pastetext', 122 'pasteword', 123 'print', 124 'spellcheck', 125 'undo', 126 'redo', 127 'find', 128 'replace', 129 'selectall', 130 'removeformat', 131 'showblocks', 132 'left', 133 'right', 134 'full', 135 'indent', 136 'outdent', 137 'unlink', 138 'style', 139 'fontname', 140 'fontsize', 141 'format', 142 'source', 143 'fullscreen', 144 'help', 145 'tikiimage', 146 'tikifile', 147 'switcheditor', 148 'autosave', 149 'admintoolbar', 150 'nonparsed', 151 'bidiltr', 152 'bidirtl', 153 'screencapture', 154 'image', 155 156 'sheetsave', // spreadsheet ones 157 'addrow', 158 'addrowmulti', 159 'addrowbefore', 160 'deleterow', 161 'addcolumn', 162 'addcolumnbefore', 163 'deletecolumn', 164 'addcolumnmulti', 165 'sheetgetrange', 166 'sheetfind', 167 'sheetrefresh', 168 'sheetclose', 169 170 'objectlink', 171 'tikitable', 172 ], 173 $plugins 174 ) 175 ); 176 } // }}} 177 178 public static function getCustomList() 179 { 180 181 global $prefs; 182 if (isset($prefs['toolbar_custom_list'])) { 183 $custom = @unserialize($prefs['toolbar_custom_list']); 184 sort($custom); 185 } else { 186 $custom = []; 187 } 188 189 return $custom; 190 } 191 192 public static function getCustomTool($name) 193 { 194 global $prefs; 195 if (isset($prefs["toolbar_tool_$name"])) { 196 $data = unserialize($prefs["toolbar_tool_$name"]); 197 $tag = Toolbar::fromData($name, $data); 198 return $tag; 199 } else { 200 return null; 201 } 202 } 203 204 public static function isCustomTool($name) 205 { 206 global $prefs; 207 return isset($prefs["toolbar_tool_$name"]); 208 } 209 210 public static function saveTool($name, $label, $icon = 'img/icons/shading.png', $token = '', $syntax = '', $type = 'Inline', $plugin = '') 211 { 212 global $tikilib; 213 214 $name = strtolower(TikiLib::remove_non_word_characters_and_accents($name)); 215 $standard_names = Toolbar::getList(false); 216 $custom_list = Toolbar::getCustomList(); 217 if (in_array($name, $standard_names)) { // don't allow custom tools with the same name as standard ones 218 $c = 1; 219 while (in_array($name . '_' . $c, $custom_list)) { 220 $c++; 221 } 222 $name = $name . '_' . $c; 223 } 224 225 $prefName = "toolbar_tool_$name"; 226 $data = ['name' => $name, 'label' => $label, 'token' => $token, 'syntax' => $syntax, 'type' => $type, 'plugin' => $plugin]; 227 228 if (strpos($icon, 'img/icons/') !== false) { 229 $data['icon'] = $icon; 230 } else { 231 $data['iconname'] = $icon; 232 } 233 234 $tikilib->set_preference($prefName, serialize($data)); 235 236 if (! in_array($name, $custom_list)) { 237 $custom_list[] = $name; 238 $tikilib->set_preference('toolbar_custom_list', serialize($custom_list)); 239 } 240 } 241 242 public static function deleteTool($name) 243 { 244 global $prefs, $tikilib; 245 246 $name = strtolower($name); 247 248 $prefName = "toolbar_tool_$name"; 249 if (isset($prefs[$prefName])) { 250 $tikilib->delete_preference($prefName); 251 252 $list = []; 253 if (isset($prefs['toolbar_custom_list'])) { 254 $list = unserialize($prefs['toolbar_custom_list']); 255 } 256 if (in_array($name, $list)) { 257 $list = array_diff($list, [$name]); 258 $tikilib->set_preference('toolbar_custom_list', serialize($list)); 259 } 260 } 261 } 262 263 public static function deleteAllCustomTools() 264 { 265 $tikilib = TikiLib::lib('tiki'); 266 267 $tikilib->query('DELETE FROM `tiki_preferences` WHERE `name` LIKE \'toolbar_tool_%\''); 268 $tikilib->delete_preference('toolbar_custom_list'); 269 } 270 271 272 public static function fromData($tagName, $data) 273 { 274 // {{{ 275 276 $tag = null; 277 278 switch ($data['type']) { 279 case 'Inline': 280 $tag = new ToolbarInline(); 281 $tag->setSyntax($data['syntax']); 282 break; 283 case 'Block': 284 $tag = new ToolbarBlock(); 285 $tag->setSyntax($data['syntax']); 286 break; 287 case 'LineBased': 288 $tag = new ToolbarLineBased(); 289 $tag->setSyntax($data['syntax']); 290 break; 291 case 'Picker': 292 $tag = new ToolbarPicker(); 293 break; 294 case 'Separator': 295 $tag = new ToolbarSeparator(); 296 break; 297 case 'Spacer': 298 $tag = new ToolbarSpacer(); 299 break; 300 case 'CkOnly': 301 $tag = new ToolbarCkOnly($tagName); 302 break; 303 case 'Fullscreen': 304 $tag = new ToolbarFullscreen(); 305 break; 306 case 'TextareaResize': 307 $tag = new ToolbarTextareaResize(); 308 break; 309 case 'Helptool': 310 $tag = new ToolbarHelptool(); 311 break; 312 case 'FileGallery': 313 $tag = new ToolbarFileGallery(); 314 break; 315 case 'Wikiplugin': 316 if (! isset($data['plugin'])) { 317 $data['plugin'] = ''; 318 } 319 $tag = ToolbarWikiplugin::fromName('wikiplugin_' . $data['plugin']); 320 if (empty($tag)) { 321 $tag = new ToolbarWikiplugin(); 322 } 323 break; 324 default: 325 $tag = new ToolbarInline(); 326 break; 327 } 328 329 $tag->setLabel($data['label']) 330 ->setWysiwygToken($data['token']) 331 ->setIconName(! empty($data['iconname']) ? $data['iconname'] : 'help') 332 ->setIcon(! empty($data['icon']) ? $data['icon'] : 'img/icons/shading.png') 333 ->setType($data['type']); 334 335 return $tag; 336 } // }}} 337 338 abstract function getWikiHtml($areaId); 339 340 function isAccessible() // {{{ 341 { 342 global $prefs; 343 344 foreach ($this->requiredPrefs as $prefName) { 345 if (! isset($prefs[$prefName]) || $prefs[$prefName] != 'y') { 346 return false; 347 } 348 } 349 350 return true; 351 } // }}} 352 353 protected function addRequiredPreference($prefName) // {{{ 354 { 355 $this->requiredPrefs[] = $prefName; 356 } // }}} 357 358 protected function setIcon($icon) // {{{ 359 { 360 $this->icon = $icon; 361 362 return $this; 363 } // }}} 364 365 protected function setIconName($iconname) // {{{ 366 { 367 $this->iconname = $iconname; 368 369 return $this; 370 } // }}} 371 372 protected function setLabel($label) // {{{ 373 { 374 $this->label = $label; 375 376 return $this; 377 } // }}} 378 379 protected function setWysiwygToken($token) // {{{ 380 { 381 $this->wysiwyg = $token; 382 383 return $this; 384 } // }}} 385 386 protected function setSyntax($syntax) // {{{ 387 { 388 return $this; 389 } // }}} 390 391 protected function setType($type) // {{{ 392 { 393 $this->type = $type; 394 395 return $this; 396 } // }}} 397 398 function getIcon() // {{{ 399 { 400 return $this->icon; 401 } // }}} 402 403 function getLabel() // {{{ 404 { 405 return $this->label; 406 } // }}} 407 408 function getWysiwygToken($areaId) // {{{ 409 { 410 return $this->wysiwyg; 411 } // }}} 412 413 414 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 415 { 416 return null; 417 } // }}} 418 419 function getSyntax($areaId) // {{{ 420 { 421 return ''; 422 } // }}} 423 424 function getType() // {{{ 425 { 426 return $this->type; 427 } // }}} 428 429 function getIconHtml() // {{{ 430 { 431 if (! empty($this->iconname)) { 432 $iname = $this->iconname; 433 } elseif (! empty($this->icon)) { 434 $headerlib = TikiLib::lib('header'); 435 return '<img src="' . htmlentities($headerlib->convert_cdn($this->icon), ENT_QUOTES, 'UTF-8') . '" alt="' 436 . htmlentities($this->getLabel(), ENT_QUOTES, 'UTF-8') . '" title=":' 437 . htmlentities($this->getLabel(), ENT_QUOTES, 'UTF-8') . '" class="tips bottom icon">'; 438 } else { 439 $iname = 'help'; 440 } 441 $smarty = TikiLib::lib('smarty'); 442 $smarty->loadPlugin('smarty_function_icon'); 443 return smarty_function_icon(['name' => $iname, 'ititle' => ':' 444 . htmlentities($this->getLabel(), ENT_QUOTES, 'UTF-8'), 'iclass' => 'tips bottom'], $smarty->getEmptyInternalTemplate()); 445 } // }}} 446 447 function getSelfLink($click, $title, $class) 448 { 449 // {{{ 450 global $prefs; 451 $smarty = TikiLib::lib('smarty'); 452 $params = []; 453 $params['_onclick'] = $click . (substr($click, strlen($click) - 1) != ';' ? ';' : '') . 'return false;'; 454 $params['_class'] = 'toolbar btn btn-sm px-2 tips bottom' . (! empty($class) ? ' ' . $class : ''); 455 $params['_ajax'] = 'n'; 456 $content = $title; 457 if ($this->iconname) { 458 $params['_icon_name'] = $this->iconname; 459 $colon = $prefs['javascript_enabled'] === 'y' ? ':' : ''; 460 $params['_title'] = $colon . $title; 461 } else { 462 $params['_icon'] = $this->icon; 463 } 464 465 if (strpos($class, 'qt-plugin') !== false && ($this->iconname == 'plugin' 466 || $this->icon == 'img/icons/plugin.png')) { 467 $params['_menu_text'] = 'y'; 468 $params['_menu_icon'] = 'y'; 469 } 470 $smarty->loadPlugin('smarty_block_self_link'); 471 return smarty_block_self_link($params, $content, $smarty->getEmptyInternalTemplate()); 472 } // }}} 473 474 protected function setupCKEditorTool($js, $name, $label = '', $icon = '') 475 { 476 if (empty($label)) { 477 $label = $name; 478 } 479 $label = addcslashes($label, "'"); 480 TikiLib::lib('header')->add_js( 481 <<< JS 482if (typeof window.CKEDITOR !== "undefined" && !window.CKEDITOR.plugins.get("{$name}")) { 483 window.CKEDITOR.config.extraPlugins += (window.CKEDITOR.config.extraPlugins ? ',{$name}' : '{$name}' ); 484 window.CKEDITOR.plugins.add( '{$name}', { 485 init : function( editor ) { 486 var command = editor.addCommand( '{$name}', new window.CKEDITOR.command( editor , { 487 modes: { wysiwyg:1 }, 488 exec: function (editor, data) { 489 {$js} 490 }, 491 canUndo: false 492 })); 493 editor.ui.addButton( '{$name}', { 494 label : '{$label}', 495 command : '{$name}', 496 icon: editor.config._TikiRoot + '{$icon}' 497 }); 498 } 499 }); 500} 501JS 502 , 503 10 504 ); 505 } 506} 507 508class ToolbarSeparator extends Toolbar 509{ 510 function __construct() // {{{ 511 { 512 $this->setWysiwygToken('-') 513 ->setIcon('img/separator.gif') 514 ->setType('Separator'); 515 } // }}} 516 517 function getWikiHtml($areaId) // {{{ 518 { 519 return '|'; 520 } // }}} 521} 522 523class ToolbarSpacer extends Toolbar 524{ 525 function __construct() // {{{ 526 { 527 $this->setWysiwygToken('|') 528 ->setIcon('img/trans.png') 529 ->setType('Spacer'); 530 } // }}} 531 532 function getWikiHtml($areaId) // {{{ 533 { 534 return '||'; 535 } // }}} 536} 537 538class ToolbarCkOnly extends Toolbar 539{ 540 function __construct($token, $icon = '', $iconname = '') // {{{ 541 { 542 if (empty($icon)) { 543 $img_path = 'img/ckeditor/' . strtolower($token) . '.png'; 544 if (is_file($img_path)) { 545 $icon = $img_path; 546 } else { 547 $icon = 'img/icons/shading.png'; 548 } 549 } 550 $this->setWysiwygToken($token) 551 ->setIcon($icon) 552 ->setIconName($iconname) 553 ->setType('CkOnly'); 554 } // }}} 555 556 public static function fromName($name, $is_html) // {{{ 557 { 558 global $prefs; 559 560 switch ($name) { 561 case 'templates': 562 if ($prefs['feature_wiki_templates'] === 'y') { 563 return new self('Templates'); 564 } else { 565 return null; 566 } 567 case 'cut': 568 return new self('Cut', null, 'scissors'); 569 case 'copy': 570 return new self('Copy', null, 'copy'); 571 case 'paste': 572 return new self('Paste', null, 'paste'); 573 case 'pastetext': 574 return new self('PasteText', null, 'paste'); 575 case 'pasteword': 576 return new self('PasteFromWord', null, 'paste'); 577 case 'print': 578 return new self('Print', null, 'print'); 579 case 'spellcheck': 580 return new self('SpellChecker', null, 'ok'); 581 case 'undo': 582 return new self('Undo', null, 'undo'); 583 case 'redo': 584 return new self('Redo', null, 'repeat'); 585 case 'selectall': 586 return new self('SelectAll', null, 'selectall'); 587 case 'removeformat': 588 return new self('RemoveFormat', null, 'erase'); 589 case 'showblocks': 590 return new self('ShowBlocks', null, 'box'); 591 case 'left': 592 return new self('JustifyLeft', null, 'align-left'); 593 case 'right': 594 return new self('JustifyRight', null, 'align-right'); 595 case 'full': 596 return new self('JustifyBlock', null, 'align-justify'); 597 case 'indent': 598 return new self('Indent', null, 'indent'); 599 case 'outdent': 600 return new self('Outdent', null, 'outdent'); 601 case 'style': 602 return new self('Styles'); 603 case 'fontname': 604 return new self('Font'); 605 case 'fontsize': 606 return new self('FontSize'); 607 case 'format': 608 return new self('Format'); 609 case 'source': 610 global $tikilib, $user, $page; 611 $p = $prefs['wysiwyg_htmltowiki'] == 'y' ? 'tiki_p_wiki_view_source' : 'tiki_p_use_HTML'; 612 if ($tikilib->user_has_perm_on_object($user, $page, 'wiki page', $p)) { 613 return new self('Source', null, 'code_file'); 614 } else { 615 return null; 616 } 617 case 'autosave': 618 return new self('autosave', 'img/ckeditor/ajaxSaveDirty.gif', 'floppy'); 619 case 'inlinesave': 620 return new self('Inline save', 'img/ckeditor/ajaxSaveDirty.gif'); 621 case 'inlinecancel': 622 return new self('Inline cancel', 'img/icons/cross.png'); 623 case 'sub': 624 return new self('Subscript', null, 'subscript'); 625 case 'sup': 626 return new self('Superscript', null, 'subscript'); 627 case 'anchor': 628 return new self('Anchor', null, 'anchor'); 629 case 'bidiltr': 630 return new self('BidiLtr', null, 'arrow-right'); 631 case 'bidirtl': 632 return new self('BidiRtl', null, 'arrow-left'); 633 case 'image': 634 return new self('Image', null, 'image'); 635 case 'table': 636 return $is_html ? new self('Table') : null; 637 case 'link': 638 return $is_html ? new self('Link') : null; 639 case 'unlink': 640 return new self('Unlink', null, 'unlink'); 641 } 642 } // }}} 643 644 function getWikiHtml($areaId) // {{{ 645 { 646 return null; 647 } // }}} 648 649 function getWysiwygToken($areaId) 650 { 651 if ($this->wysiwyg === 'Image') { // cke's own image tool 652 global $prefs; 653 $headerlib = TikiLib::lib('header'); 654 // can't do upload the cke way yet 655 $url = 'tiki-list_file_gallery.php?galleryId=' . $prefs['home_file_gallery'] . '&filegals_manager=fgal_picker'; 656 $headerlib->add_js('if (typeof window.CKEDITOR !== "undefined") {window.CKEDITOR.config.filebrowserBrowseUrl = "' . $url . '"}', 5); 657 } 658 return $this->wysiwyg; 659 } 660 661 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 662 { 663 switch ($this->wysiwyg) { 664 case 'autosave': 665 case 'Copy': 666 case 'Cut': 667 case 'Format': 668 case 'JustifyLeft': 669 case 'Paste': 670 case 'PasteText': 671 case 'PasteFromWord': 672 case 'Redo': 673 case 'RemoveFormat': 674 case 'ShowBlocks': 675 case 'Source': 676 case 'Undo': 677 case 'Unlink': 678 return $this->wysiwyg; 679 break; 680 default: 681 return null; 682 } 683 } // }}} 684 685 function getLabel() // {{{ 686 { 687 return $this->wysiwyg; 688 } // }}} 689 690 function getIconHtml() // {{{ for admin page 691 { 692 693 if (! empty($this->iconname)) { 694 $smarty = TikiLib::lib('smarty'); 695 $smarty->loadPlugin('smarty_function_icon'); 696 return smarty_function_icon(['name' => $this->iconname, 'ititle' => ':' 697 . htmlentities($this->getLabel(), ENT_QUOTES, 'UTF-8'), 'iclass' => 'tips bottom'], $smarty->getEmptyInternalTemplate()); 698 } 699 if ((! empty($this->icon) && $this->icon !== 'img/icons/shading.png') || in_array($this->label, ['Autosave'])) { 700 return parent::getIconHtml(); 701 } 702 703 global $prefs; 704 $skin = $prefs['wysiwyg_toolbar_skin']; 705 $headerlib = TikiLib::lib('header'); 706 $headerlib->add_cssfile('vendor_bundled/vendor/ckeditor/ckeditor/skins/' . $skin . '/editor.css'); 707 $cls = strtolower($this->wysiwyg); 708 $headerlib->add_css( 709 'span.cke_skin_' . $skin . ' {border: none;background: none;padding:0;margin:0;}' . 710 '.toolbars-admin .row li.toolbar > span.cke_skin_' . $skin . ' {display: inline-block;}' 711 ); 712 return '<span class="cke_skin_' . $skin 713 . '"><a class="cke_button cke_ltr" style="margin-top:-5px"><span class="cke_button__' 714 . htmlentities($cls, ENT_QUOTES, 'UTF-8') . '_icon"' . 715 ' title="' . htmlentities($this->getLabel(), ENT_QUOTES, 'UTF-8') . '">' . 716 '<span class="cke_icon"> </span>' . 717 '</span></a></span>'; 718 } // }}} 719} 720 721class ToolbarInline extends Toolbar 722{ 723 protected $syntax; 724 725 public static function fromName($tagName) // {{{ 726 { 727 switch ($tagName) { 728 case 'bold': 729 $label = tra('Bold'); 730 $icon = tra('img/icons/text_bold.png'); 731 $iconname = 'bold'; 732 $wysiwyg = 'Bold'; 733 $syntax = '__text__'; 734 break; 735 case 'italic': 736 $label = tra('Italic'); 737 $icon = tra('img/icons/text_italic.png'); 738 $iconname = 'italic'; 739 $wysiwyg = 'Italic'; 740 $syntax = "''text''"; 741 break; 742 case 'underline': 743 $label = tra('Underline'); 744 $icon = tra('img/icons/text_underline.png'); 745 $iconname = 'underline'; 746 $wysiwyg = 'Underline'; 747 $syntax = "===text==="; 748 break; 749 case 'strike': 750 $label = tra('Strikethrough'); 751 $icon = tra('img/icons/text_strikethrough.png'); 752 $iconname = 'strikethrough'; 753 $wysiwyg = 'Strike'; 754 $syntax = '--text--'; 755 break; 756 case 'code': 757 $label = tra('Code'); 758 $icon = tra('img/icons/page_white_code.png'); 759 $iconname = 'code'; 760 $wysiwyg = 'Code'; 761 $syntax = '-+text+-'; 762 break; 763 case 'nonparsed': 764 $label = tra('Non-parsed (wiki syntax does not apply)'); 765 $icon = tra('img/icons/noparse.png'); 766 $iconname = 'ban'; 767 $wysiwyg = null; 768 $syntax = '~np~text~/np~'; 769 break; 770 default: 771 return; 772 } 773 774 $tag = new self; 775 $tag->setLabel($label) 776 ->setWysiwygToken($wysiwyg) 777 ->setIconName(! empty($iconname) ? $iconname : 'help') 778 ->setIcon(! empty($icon) ? $icon : 'img/icons/shading.png') 779 ->setSyntax($syntax) 780 ->setType('Inline'); 781 782 return $tag; 783 } // }}} 784 785 function getSyntax($areaId) // {{{ 786 { 787 return $this->syntax; 788 } // }}} 789 790 function setSyntax($syntax) // {{{ 791 { 792 $this->syntax = $syntax; 793 794 return $this; 795 } // }}} 796 797 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 798 { 799 return $this->getWysiwygToken($areaId); 800 } // }}} 801 802 function getWikiHtml($areaId) // {{{ 803 { 804 if ($this->syntax == '~np~text~/np~') { // closing ~/np~ tag breaks toolbar when inside nested plugins 805 return $this->getSelfLink( 806 'insertAt(\'' . $areaId . '\', \'~np~text~\'+\'/np~\');', 807 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 808 'qt-inline' 809 ); 810 } else { 811 return $this->getSelfLink( 812 'insertAt(\'' . $areaId . '\', \'' . addslashes(htmlentities($this->syntax, ENT_COMPAT, 'UTF-8')) . '\');', 813 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 814 'qt-inline' 815 ); 816 } 817 } // }}} 818} 819 820class ToolbarBlock extends ToolbarInline // Will change in the future 821{ 822 protected $syntax; 823 824 public static function fromName($tagName) // {{{ 825 { 826 global $prefs; 827 828 $label = null; 829 $wysiwyg = null; 830 $syntax = null; 831 832 switch ($tagName) { 833 case 'center': 834 $label = tra('Align Center'); 835 $iconname = 'align-center'; 836 $wysiwyg = 'JustifyCenter'; 837 if ($prefs['feature_use_three_colon_centertag'] == 'y') { 838 $syntax = ":::text:::"; 839 } else { 840 $syntax = "::text::"; 841 } 842 break; 843 case 'rule': 844 $label = tra('Horizontal Bar'); 845 $iconname = 'horizontal-rule'; 846 $wysiwyg = 'HorizontalRule'; 847 $syntax = '---'; 848 break; 849 case 'pagebreak': 850 $label = tra('Page Break'); 851 $iconname = 'page-break'; 852 $wysiwyg = 'PageBreak'; 853 $syntax = '...page...'; 854 break; 855 case 'box': 856 $label = tra('Box'); 857 $iconname = 'box'; 858 $wysiwyg = 'Box'; 859 $syntax = '^text^'; 860 break; 861 case 'email': 862 $label = tra('Email'); 863 $iconname = 'envelope'; 864 $wysiwyg = null; 865 $syntax = '[mailto:email@example.com|text]'; 866 break; 867 case 'h1': 868 case 'h2': 869 case 'h3': 870 $label = tra('Heading') . ' ' . $tagName{1}; 871 $iconname = $tagName; 872 $wysiwyg = null; 873 $syntax = str_repeat('!', $tagName{1}) . ' text'; 874 break; 875 case 'titlebar': 876 $label = tra('Title bar'); 877 $iconname = 'title'; 878 $wysiwyg = null; 879 $syntax = '-=text=-'; 880 break; 881 case 'toc': 882 $label = tra('Table of contents'); 883 $iconname = 'book'; 884 $wysiwyg = 'TOC'; 885 $syntax = '{maketoc}'; 886 break; 887 default: 888 return; 889 } 890 891 $tag = new self; 892 $tag->setLabel($label) 893 ->setWysiwygToken($wysiwyg) 894 ->setIconName(! empty($iconname) ? $iconname : 'help') 895 ->setSyntax($syntax) 896 ->setType('Block'); 897 898 return $tag; 899 } // }}} 900 901 function getWikiHtml($areaId) // {{{ 902 { 903 if ($this->syntax == '...page...') { // for some reason breaks toolbar when inside nested plugins 904 return $this->getSelfLink( 905 'insertAt(\'' . $areaId . '\', \'...\'+\'page\'+\'...\');', 906 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 907 'qt-block' 908 ); 909 } else { 910 return $this->getSelfLink( 911 'insertAt(\'' . $areaId . '\', \'' . addslashes(htmlentities($this->syntax, ENT_COMPAT, 'UTF-8')) . '\', true);', 912 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 913 'qt-block' 914 ); 915 } 916 } // }}} 917} 918 919class ToolbarLineBased extends ToolbarInline // Will change in the future 920{ 921 protected $syntax; 922 923 public static function fromName($tagName) // {{{ 924 { 925 switch ($tagName) { 926 case 'list': 927 $label = tra('Bullet List'); 928 $iconname = 'list'; 929 $wysiwyg = 'BulletedList'; 930 $syntax = '* text'; 931 break; 932 case 'numlist': 933 $label = tra('Numbered List'); 934 $iconname = 'list-numbered'; 935 $wysiwyg = 'NumberedList'; 936 $syntax = '# text'; 937 break; 938 case 'indent': 939 global $prefs; 940 return null; 941 break; 942 default: 943 return null; 944 } 945 946 $tag = new self; 947 $tag->setLabel($label) 948 ->setWysiwygToken($wysiwyg) 949 ->setIconName(! empty($iconname) ? $iconname : 'help') 950 ->setSyntax($syntax) 951 ->setType('LineBased'); 952 953 return $tag; 954 } // }}} 955 956 function getWikiHtml($areaId) // {{{ 957 { 958 return $this->getSelfLink( 959 'insertAt(\'' . $areaId . '\', \'' . addslashes(htmlentities($this->syntax, ENT_COMPAT, 'UTF-8')) . '\', true, true);', 960 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 961 'qt-line' 962 ); 963 } // }}} 964} 965 966 967class ToolbarPicker extends Toolbar 968{ 969 private $list; 970 private $name; 971 972 public static function fromName($tagName) // {{{ 973 { 974 global $section, $prefs; 975 $headerlib = TikiLib::lib('header'); 976 977 $tool_prefs = []; 978 $styleType = ''; 979 980 switch ($tagName) { 981 case 'specialchar': 982 $wysiwyg = 'SpecialChar'; 983 $label = tra('Special Characters'); 984 $iconname = 'keyboard'; 985 // Line taken from DokuWiki + some added chars for Tiki 986 $list = explode(' ', 'À à Á á  â à ã Ä ä Ǎ ǎ Ă ă Å å Ā ā Ą ą Æ æ Ć ć Ç ç Č č Ĉ ĉ Ċ ċ Ð đ ð Ď ď È è É é Ê ê Ë ë Ě ě Ē ē Ė ė Ę ę Ģ ģ Ĝ ĝ Ğ ğ Ġ ġ Ĥ ĥ Ì ì Í í Î î Ï ï Ǐ ǐ Ī ī İ ı Į į Ĵ ĵ Ķ ķ Ĺ ĺ Ļ ļ Ľ ľ Ł ł Ŀ ŀ Ń ń Ñ ñ Ņ ņ Ň ň Ò ò Ó ó Ô ô Õ õ Ö ö Ǒ ǒ Ō ō Ő ő Œ œ Ø ø Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ş ş Š š Ŝ ŝ Ţ ţ Ť ť Ù ù Ú ú Û û Ü ü Ǔ ǔ Ŭ ŭ Ū ū Ů ů ǖ ǘ ǚ ǜ Ų ų Ű ű Ŵ ŵ Ý ý Ÿ ÿ Ŷ ŷ Ź ź Ž ž Ż ż Þ þ ß Ħ ħ ¿ ¡ ¢ £ ¤ ¥ € ¦ § ª ¬ ¯ ° ± ÷ ‰ ¼ ½ ¾ ¹ ² ³ µ ¶ † ‡ · • º ∀ ∂ ∃ Ə ə ∅ ∇ ∈ ∉ ∋ ∏ ∑ ‾ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ ⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ◊ ℘ ℑ ℜ ℵ ♠ ♣ ♥ ♦ ★ ☆ ☎ ☚ ☛ ☜ ☝ ☞ ☟ ☹ ☺ ✔ ✘ × „ “ ” ‚ ‘ ’ « » ‹ › — – … ← ↑ → ↓ ↔ ⇐ ⇑ ⇒ ⇓ ⇔ © ™ ® ′ ″ @ % ~ | [ ] { } * #'); 987 $list = array_combine($list, $list); 988 break; 989 case 'smiley': 990 $wysiwyg = 'Smiley'; 991 $label = tra('Smileys'); 992 $iconname = 'smile'; 993 $rawList = [ 'biggrin', 'confused', 'cool', 'cry', 'eek', 'evil', 'exclaim', 'frown', 'idea', 'lol', 'mad', 'mrgreen', 'neutral', 'question', 'razz', 'redface', 'rolleyes', 'sad', 'smile', 'surprised', 'twisted', 'wink', 'arrow', 'santa' ]; 994 $tool_prefs[] = 'feature_smileys'; 995 996 $list = []; 997 foreach ($rawList as $smiley) { 998 $tra = htmlentities(tra($smiley), ENT_QUOTES, 'UTF-8'); 999 $list["(:$smiley:)"] = '<img src="' . $headerlib->convert_cdn('img/smiles/icon_' . $smiley . '.gif') . '" alt="' . $tra . '" title="' . $tra . '" width="15" height="15" />'; 1000 } 1001 1002 break; 1003 case 'color': 1004 $wysiwyg = 'TextColor'; 1005 $label = tra('Foreground color'); 1006 $iconname = 'font-color'; 1007 $rawList = []; 1008 $styleType = 'color'; 1009 1010 $hex = ['0', '3', '6', '8', '9', 'C', 'F']; 1011 $count_hex = count($hex); 1012 1013 for ($r = 0; $r < $count_hex; $r += 2) { // red 1014 for ($g = 0; $g < $count_hex; $g += 2) { // green 1015 for ($b = 0; $b < $count_hex; $b += 2) { // blue 1016 $color = $hex[$r] . $hex[$g] . $hex[$b]; 1017 $rawList[] = $color; 1018 } 1019 } 1020 } 1021 1022 $list = []; 1023 foreach ($rawList as $color) { 1024 $list["~~#$color:text~~"] = "<span style='background-color: #$color' title='#$color' /> </span>"; 1025 } 1026 1027 if ($section == 'sheet') { 1028 $list['reset'] = "<span title=':" . tra("Reset Colors") . "' class='toolbars-picker-reset' reset='true'>" . tra("Reset") . "</span>"; 1029 } 1030 1031 break; 1032 1033 case 'bgcolor': 1034 $label = tra('Background Color'); 1035 $iconname = 'background-color'; 1036 $wysiwyg = 'BGColor'; 1037 $styleType = 'background-color'; 1038 $rawList = []; 1039 1040 $hex = ['0', '3', '6', '8', '9', 'C', 'F']; 1041 $count_hex = count($hex); 1042 1043 for ($r = 0; $r < $count_hex; $r += 2) { // red 1044 for ($g = 0; $g < $count_hex; $g += 2) { // green 1045 for ($b = 0; $b < $count_hex; $b += 2) { // blue 1046 $color = $hex[$r] . $hex[$g] . $hex[$b]; 1047 $rawList[] = $color; 1048 } 1049 } 1050 } 1051 1052 $list = []; 1053 foreach ($rawList as $color) { 1054 $list["~~black,#$color:text~~"] = "<span style='background-color: #$color' title='#$color' /> </span>"; 1055 } 1056 if ($section == 'sheet') { 1057 $list['reset'] = "<span title='" . tra("Reset Colors") . "' class='toolbars-picker-reset' reset='true'>" . tra("Reset") . "</span>"; 1058 } 1059 1060 break; 1061 1062 default: 1063 return; 1064 } 1065 1066 $tag = new self; 1067 $tag->setWysiwygToken($wysiwyg) 1068 ->setLabel($label) 1069 ->setIconName(! empty($iconname) ? $iconname : 'help') 1070 ->setList($list) 1071 ->setType('Picker') 1072 ->setName($tagName) 1073 ->setStyleType($styleType); 1074 1075 foreach ($tool_prefs as $pref) { 1076 $tag->addRequiredPreference($pref); 1077 } 1078 1079 global $toolbarPickerIndex; 1080 ++$toolbarPickerIndex; 1081 $tag->index = $toolbarPickerIndex; 1082 ToolbarPicker::setupJs(); 1083 1084 return $tag; 1085 } // }}} 1086 1087 function setName($name) // {{{ 1088 { 1089 $this->name = $name; 1090 1091 return $this; 1092 } // }}} 1093 1094 1095 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 1096 { 1097 switch ($this->wysiwyg) { 1098 case 'BGColor': 1099 case 'TextColor': 1100 case 'SpecialChar': 1101 return $this->wysiwyg; 1102 break; 1103 default: 1104 return null; 1105 } 1106 } // }}} 1107 1108 1109 function setList($list) // {{{ 1110 { 1111 $this->list = $list; 1112 1113 return $this; 1114 } // }}} 1115 1116 protected function setSyntax($syntax) // {{{ 1117 { 1118 $this->syntax = $syntax; 1119 1120 return $this; 1121 } // }}} 1122 1123 public function getSyntax($areaId = '$areaId') 1124 { 1125 global $section; 1126 if ($section == 'sheet') { 1127 return 'displayPicker( this, \'' . $this->name . '\', \'' . $areaId . '\', true, \'' . $this->styleType . '\' )'; // is enclosed in double quotes later 1128 } else { 1129 return 'displayPicker( this, \'' . $this->name . '\', \'' . $areaId . '\' )'; // is enclosed in double quotes later 1130 } 1131 } 1132 1133 private static function setupJs() 1134 { 1135 1136 static $pickerAdded = false; 1137 1138 if (! $pickerAdded) { 1139 TikiLib::lib('header')->add_jsfile('lib/jquery_tiki/tiki-toolbars.js'); 1140 $pickerAdded = true; 1141 } 1142 } 1143 1144 function getWikiHtml($areaId) // {{{ 1145 { 1146 global $prefs; 1147 $headerlib = TikiLib::lib('header'); 1148 $headerlib->add_js("if (! window.pickerData) { window.pickerData = {}; } window.pickerData['$this->name'] = " . str_replace('\/', '/', json_encode($this->list)) . ";"); 1149 1150 return $this->getSelfLink( 1151 $this->getSyntax($areaId), 1152 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 1153 'qt-picker' 1154 ); 1155 } // }}} 1156 1157 protected function setStyleType($type) // {{{ 1158 { 1159 $this->styleType = $type; 1160 1161 return $this; 1162 } // }}} 1163} 1164 1165class ToolbarDialog extends Toolbar 1166{ 1167 private $list; 1168 private $index; 1169 private $name; 1170 1171 public static function fromName($tagName) // {{{ 1172 { 1173 global $prefs; 1174 1175 $tool_prefs = []; 1176 1177 switch ($tagName) { 1178 case 'tikilink': 1179 $label = tra('Wiki Link'); 1180 $iconname = 'link'; 1181 $icon = tra('img/icons/page_link.png'); 1182 $wysiwyg = ''; // cke link dialog now adapted for wiki links 1183 $list = [tra("Wiki Link"), 1184 '<label for="tbWLinkDesc">' . tra("Show this text") . '</label>', 1185 '<input type="text" id="tbWLinkDesc" class="ui-widget-content ui-corner-all" style="width: 98%" />', 1186 '<label for="tbWLinkPage">' . tra("Link to this page") . '</label>', 1187 '<input type="text" id="tbWLinkPage" class="ui-widget-content ui-corner-all" style="width: 98%" />', 1188 $prefs['wikiplugin_alink'] == 'y' ? '<label for="tbWLinkAnchor">' . tra("Anchor") . ':</label>' : '', 1189 $prefs['wikiplugin_alink'] == 'y' ? '<input type="text" id="tbWLinkAnchor" class="ui-widget-content ui-corner-all" style="width: 98%" />' : '', 1190 $prefs['feature_semantic'] == 'y' ? '<label for="tbWLinkRel">' . tra("Semantic relation") . ':</label>' : '', 1191 $prefs['feature_semantic'] == 'y' ? '<input type="text" id="tbWLinkRel" class="ui-widget-content ui-corner-all" style="width: 98%" />' : '', 1192 '{"open": function () { dialogInternalLinkOpen(area_id); }, 1193 "buttons": { "' . tra("Cancel") . '": function() { dialogSharedClose(area_id,this); },' . 1194 '"' . tra("Insert") . '": function() { dialogInternalLinkInsert(area_id,this); }}}' 1195 ]; 1196 1197 break; 1198 case 'objectlink': 1199 $types = TikiLib::lib('unifiedsearch')->getSupportedTypes(); 1200 $options = ''; 1201 foreach ($types as $type => $title) { 1202 $options .= '<option value="' . $type . '">' . $title . '</option>'; 1203 } 1204 $label = tra('Object Link'); 1205 $iconname = 'link-external-alt'; 1206 $icon = tra('img/icons/page_link.png'); 1207 $wysiwyg = 'Object Link'; 1208 1209 $smarty = TikiLib::lib('smarty'); 1210 $smarty->loadPlugin('smarty_function_object_selector'); 1211 $object_selector = smarty_function_object_selector([ 1212 '_id' => 'tbOLinkObjectSelector', 1213 '_class' => 'ui-widget-content ui-corner-all', 1214 // '_format' => '{title}', 1215 '_filter' => ['type' => ''], 1216 '_parent' => 'tbOLinkObjectType', 1217 '_parentkey' => 'type', 1218 ], $smarty->getEmptyInternalTemplate()); 1219 1220 $list = [tra('Object Link'), 1221 '<label for="tbOLinkDesc">' . tra("Show this text") . '</label>', 1222 '<input type="text" id="tbOLinkDesc" />', 1223 '<label for="tbOLinkObjectType">' . tra("Types of object") . '</label>', 1224 '<select id="tbOLinkObjectType" class="ui-widget-content ui-corner-all" style="width: 98%">' . 1225 '<option value="*">' . tra('All') . '</option>' . 1226 $options . 1227 '</select>', 1228 '<label for="tbOLinkObjectSelector">' . tra("Link to this object") . '</label>', 1229 $object_selector, 1230 // '<input type="text" id="tbOLinkObjectSelector" class="ui-widget-content ui-corner-all" style="width: 98%" />', 1231 '{"open": function () { dialogObjectLinkOpen(area_id); }, 1232 "buttons": { "' . tra("Cancel") . '": function() { dialogSharedClose(area_id,this); },' . 1233 '"' . tra("Insert") . '": function() { dialogObjectLinkInsert(area_id,this); }}}' 1234 ]; 1235 1236 break; 1237 case 'link': 1238 $wysiwyg = 'Link'; 1239 $label = tra('External Link'); 1240 $iconname = 'link-external'; 1241 $icon = tra('img/icons/world_link.png'); 1242 $list = [tra('External Link'), 1243 '<label for="tbLinkDesc">' . tra("Show this text") . '</label>', 1244 '<input type="text" id="tbLinkDesc" class="ui-widget-content ui-corner-all" style="width: 98%" />', 1245 '<label for="tbLinkURL">' . tra("link to this URL") . '</label>', 1246 '<input type="text" id="tbLinkURL" class="ui-widget-content ui-corner-all" style="width: 98%" />', 1247 '<label for="tbLinkRel">' . tra("Relation") . ':</label>', 1248 '<input type="text" id="tbLinkRel" class="ui-widget-content ui-corner-all" style="width: 98%" />', 1249 $prefs['cachepages'] == 'y' ? '<br /><label for="tbLinkNoCache" style="display:inline;">' . tra("No cache") . ':</label>' : '', 1250 $prefs['cachepages'] == 'y' ? '<input type="checkbox" id="tbLinkNoCache" class="ui-widget-content ui-corner-all" />' : '', 1251 '{"width": 300, "open": function () { dialogExternalLinkOpen( area_id ) }, 1252 "buttons": { "' . tra("Cancel") . '": function() { dialogSharedClose(area_id,this); },' . 1253 '"' . tra("Insert") . '": function() { dialogExternalLinkInsert(area_id,this) }}}' 1254 ]; 1255 break; 1256 1257 case 'table': 1258 case 'tikitable': 1259 $iconname = 'table'; 1260 $icon = tra('img/icons/table.png'); 1261 $wysiwyg = 'Table'; 1262 $label = tra('Table Builder'); 1263 $list = [tra('Table Builder'), 1264 '{"open": function () { dialogTableOpen(area_id,this); }, 1265 "width": 320, "buttons": { "' . tra("Cancel") . '": function() { dialogSharedClose(area_id,this); },' . 1266 '"' . tra("Insert") . '": function() { dialogTableInsert(area_id,this); }}}' 1267 ]; 1268 break; 1269 1270 case 'find': 1271 $icon = tra('img/icons/find.png'); 1272 $iconname = 'search'; 1273 $wysiwyg = 'Find'; 1274 $label = tra('Find Text'); 1275 $list = [tra('Find Text'), 1276 '<label>' . tra("Search") . ':</label>', 1277 '<input type="text" id="tbFindSearch" class="ui-widget-content ui-corner-all" />', 1278 '<label for="tbFindCase" style="display:inline;">' . tra("Case Insensitivity") . ':</label>', 1279 '<input type="checkbox" id="tbFindCase" checked="checked" class="ui-widget-content ui-corner-all" />', 1280 '<p class="description">' . tra("Note: Uses regular expressions") . '</p>', // TODO add option to not 1281 '{"open": function() { dialogFindOpen(area_id); },' . 1282 '"buttons": { "' . tra("Close") . '": function() { dialogSharedClose(area_id,this); },' . 1283 '"' . tra("Find") . '": function() { dialogFindFind(area_id); }}}' 1284 ]; 1285 1286 break; 1287 1288 case 'replace': 1289 $icon = tra('img/icons/text_replace.png'); 1290 $iconname = 'repeat'; 1291 $wysiwyg = 'Replace'; 1292 $label = tra('Text Replace'); 1293 $tool_prefs[] = 'feature_wiki_replace'; 1294 1295 $list = [tra('Text Replace'), 1296 '<label for="tbReplaceSearch">' . tra("Search") . ':</label>', 1297 '<input type="text" id="tbReplaceSearch" class="ui-widget-content ui-corner-all" />', 1298 '<label for="tbReplaceReplace">' . tra("Replace") . ':</label>', 1299 '<input type="text" id="tbReplaceReplace" class="ui-widget-content ui-corner-all clearfix" />', 1300 '<label for="tbReplaceCase" style="display:inline;">' . tra("Case Insensitivity") . ':</label>', 1301 '<input type="checkbox" id="tbReplaceCase" checked="checked" class="ui-widget-content ui-corner-all" />', 1302 '<br /><label for="tbReplaceAll" style="display:inline;">' . tra("Replace All") . ':</label>', 1303 '<input type="checkbox" id="tbReplaceAll" checked="checked" class="ui-widget-content ui-corner-all" />', 1304 '<p class="description">' . tra("Note: Uses regular expressions") . '</p>', // TODO add option to not 1305 '{"open": function() { dialogReplaceOpen(area_id); },' . 1306 '"buttons": { "' . tra("Close") . '": function() { dialogSharedClose(area_id,this); },' . 1307 '"' . tra("Replace") . '": function() { dialogReplaceReplace(area_id); }}}' 1308 ]; 1309 1310 break; 1311 1312 default: 1313 return; 1314 } 1315 1316 $tag = new self; 1317 $tag->name = $tagName; 1318 $tag->setWysiwygToken($wysiwyg) 1319 ->setLabel($label) 1320 ->setIconName(! empty($iconname) ? $iconname : 'help') 1321 ->setIcon(! empty($icon) ? $icon : 'img/icons/shading.png') 1322 ->setList($list) 1323 ->setType('Dialog'); 1324 1325 foreach ($tool_prefs as $pref) { 1326 $tag->addRequiredPreference($pref); 1327 } 1328 1329 global $toolbarDialogIndex; 1330 ++$toolbarDialogIndex; 1331 $tag->index = $toolbarDialogIndex; 1332 1333 ToolbarDialog::setupJs(); 1334 1335 return $tag; 1336 } // }}} 1337 1338 function setList($list) // {{{ 1339 { 1340 $this->list = $list; 1341 1342 return $this; 1343 } // }}} 1344 1345 protected function setSyntax($syntax) // {{{ 1346 { 1347 $this->syntax = $syntax; 1348 1349 return $this; 1350 } // }}} 1351 1352 public function getSyntax($areaId = '$areaId') 1353 { 1354 return 'displayDialog( this, ' . $this->index . ', \'' . $areaId . '\')'; 1355 } 1356 1357 static function setupJs() 1358 { 1359 TikiLib::lib('header')->add_jsfile('lib/jquery_tiki/tiki-toolbars.js'); 1360 } 1361 1362 function getWikiHtml($areaId) // {{{ 1363 { 1364 $headerlib = TikiLib::lib('header'); 1365 $headerlib->add_js("if (! window.dialogData) { window.dialogData = {}; } window.dialogData[$this->index] = " 1366 . json_encode($this->list) . ";", 1 + $this->index); 1367 1368 return $this->getSelfLink( 1369 $this->getSyntax($areaId), 1370 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 1371 'qt-picker' 1372 ); 1373 } // }}} 1374 1375 function getWysiwygToken($areaId) // {{{ 1376 { 1377 if (! empty($this->wysiwyg)) { 1378 TikiLib::lib('header')->add_js( 1379 "window.dialogData[$this->index] = " . json_encode($this->list) . ";", 1380 1 + $this->index 1381 ); 1382 $syntax = str_replace('\'' . $areaId . '\'', 'editor.name', $this->getSyntax($areaId)); 1383 $this->setupCKEditorTool($syntax, $this->wysiwyg, $this->label, $this->icon); 1384 } 1385 return $this->wysiwyg; 1386 } // }}} 1387 1388 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 1389 { 1390 switch ($this->name) { 1391 case 'tikilink': 1392 $this->wysiwyg = 'tikilink'; 1393 break; 1394 case 'objectlink': 1395 $this->wysiwyg = 'objectlink'; 1396 break; 1397 case 'table': 1398 $this->wysiwyg = 'tikitable'; 1399 break; 1400 case 'link': 1401 $this->wysiwyg = 'externallink'; 1402 break; 1403 default: 1404 return $this->wysiwyg; 1405 } 1406 1407 return $this->getWysiwygToken($areaId); 1408 } // }}} 1409} 1410 1411class ToolbarFullscreen extends Toolbar 1412{ 1413 function __construct() // {{{ 1414 { 1415 $this->setLabel(tra('Full-screen edit')) 1416 ->setIconName('fullscreen') 1417 ->setWysiwygToken('Maximize') 1418 ->setType('Fullscreen'); 1419 } // }}} 1420 1421 function getWikiHtml($areaId) // {{{ 1422 { 1423 1424 return $this->getSelfLink( 1425 'toggleFullScreen(\'' . $areaId . '\');return false;', 1426 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 1427 'qt-fullscreen' 1428 ); 1429 } // }}} 1430 1431 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 1432 { 1433 return $this->getWysiwygToken($areaId); 1434 } // }}} 1435} 1436 1437class ToolbarHelptool extends Toolbar 1438{ 1439 function __construct() // {{{ 1440 { 1441 $this->setLabel(tra('Wiki Help')) 1442 ->setIcon('img/icons/help.png') 1443 ->setType('Helptool'); 1444 } // }}} 1445 1446 function getWikiHtml($areaId) // {{{ 1447 { 1448 global $section; 1449 1450 $smarty = TikiLib::lib('smarty'); 1451 $servicelib = TikiLib::lib('service'); 1452 1453 $params = ['controller' => 'edit', 'action' => 'help', 'modal' => 1]; 1454 $params['wiki'] = 1; 1455 $params['plugins'] = 1; 1456 $params['areaId'] = $areaId; 1457 1458 if ($GLOBALS['section'] == 'sheet') { 1459 $params['sheet'] = 1; 1460 } 1461 1462 $smarty->loadPlugin('smarty_function_icon'); 1463 $icon = smarty_function_icon(['name' => 'help'], $smarty->getEmptyInternalTemplate()); 1464 $url = $servicelib->getUrl($params); 1465 $help = tra('Help'); 1466 1467 return "<a title=\":$help\" class=\"toolbar btn btn-sm px-2 qt-help tips bottom\" href=\"$url\" data-toggle=\"modal\" data-target=\"#bootstrap-modal\">$icon</a>"; 1468 } // }}} 1469 1470 function getWysiwygToken($areaId) // {{{ 1471 { 1472 global $section; 1473 1474 $servicelib = TikiLib::lib('service'); 1475 1476 $params = ['controller' => 'edit', 'action' => 'help', 'modal' => 1]; 1477 $params['wysiwyg'] = 1; 1478 $params['plugins'] = 1; 1479 1480 if ($section == 'sheet') { 1481 $params['sheet'] = 1; 1482 } 1483 1484 // multiple ckeditors share the same toolbar commands, so area_id (editor.name) must be added when clicked 1485 $params['areaId'] = ''; // this must be last param 1486 1487 $this->setLabel(tra('WYSIWYG Help')); 1488 $this->setIconName('help'); 1489 $name = 'tikihelp'; 1490 1491 $js = '$.openModal({show: true, remote: "' . $servicelib->getUrl($params) . '" + editor.name});'; 1492 1493 $this->setupCKEditorTool($js, $name, $this->label, $this->icon); 1494 1495 return $name; 1496 } 1497 1498 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 1499 { 1500 return $this->getWysiwygToken($areaId); 1501 } // }}} 1502} 1503 1504class ToolbarFileGallery extends Toolbar 1505{ 1506 private $name; 1507 1508 function __construct() // {{{ 1509 { 1510 $this->setLabel(tra('Choose or upload images')) 1511 ->setIconName('image') 1512 ->setIcon(tra('img/icons/pictures.png')) 1513 ->setWysiwygToken('tikiimage') 1514 ->setType('FileGallery') 1515 ->addRequiredPreference('feature_filegals_manager'); 1516 } // }}} 1517 1518 function getSyntax($areaId) 1519 { 1520 global $prefs; 1521 $smarty = TikiLib::lib('smarty'); 1522 if ($prefs['fgal_elfinder_feature'] !== 'y' || $prefs['fgal_elfinder_on_toolbar'] !== 'y') { 1523 $smarty->loadPlugin('smarty_function_filegal_manager_url'); 1524 return 'openFgalsWindow(\'' . htmlentities(smarty_function_filegal_manager_url(['area_id' => $areaId], $smarty->getEmptyInternalTemplate())) . '\', true);'; 1525 } else { 1526 TikiLib::lib('header')->add_jq_onready( 1527 'window.handleFinderInsertAt = function (file, elfinder, area_id) { 1528 $.getJSON($.service("file_finder", "finder"), { cmd: "tikiFileFromHash", hash: file.hash }, 1529 function (data) { 1530 $(window).data("elFinderDialog").dialog("close"); 1531 $($(window).data("elFinderDialog")).remove(); 1532 $(window).data("elFinderDialog", null); 1533 window.insertAt(area_id, data.wiki_syntax); 1534 return false; 1535 } 1536 ); 1537 };' 1538 ); 1539 $smarty->loadPlugin('smarty_function_ticket'); 1540 return ' 1541 var area_id = (typeof editor === \'undefined\' ? \'' . $areaId . '\' : editor.name); 1542 openElFinderDialog( 1543 this, 1544 { 1545 defaultGalleryId: ' . (empty($prefs['home_file_gallery']) ? $prefs['fgal_root_id'] : $prefs['home_file_gallery']) . ', 1546 deepGallerySearch: true, 1547 ticket: \'' . smarty_function_ticket(['mode' => 'get'], $smarty) . '\', 1548 getFileCallback: function(file,elfinder) { 1549 window.handleFinderInsertAt(file,elfinder,area_id); 1550 }, 1551 eventOrigin:this, 1552 uploadCallback: function (data) { 1553 if (data.data.added.length === 1 && confirm(tr(\'Do you want to use this file in your page?\'))) { 1554 window.handleFinderInsertAt(data.data.added[0],window.elFinder,area_id); 1555 } 1556 } 1557 } 1558 );'; 1559 } 1560 } 1561 1562 function getWikiHtml($areaId) // {{{ 1563 { 1564 return $this->getSelfLink($this->getSyntax($areaId), htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 'qt-filegal'); 1565 } // }}} 1566 1567 function getWysiwygToken($areaId) // {{{ 1568 { 1569 if (! empty($this->wysiwyg)) { 1570 $this->name = $this->wysiwyg; // temp 1571 $exec_js = str_replace('&', '&', $this->getSyntax($areaId)); // odd? 1572 1573 $this->setupCKEditorTool($exec_js, $this->name, $this->label, $this->icon); 1574 } 1575 return $this->wysiwyg; 1576 } // }}} 1577 1578 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 1579 { 1580 return $this->getWysiwygToken($areaId); 1581 } // }}} 1582 1583 function isAccessible() // {{{ 1584 { 1585 return parent::isAccessible(); 1586 } // }}} 1587} 1588 1589class ToolbarFileGalleryFile extends ToolbarFileGallery 1590{ 1591 1592 function __construct() // {{{ 1593 { 1594 $this->setLabel(tra('Choose or upload files')) 1595 ->setIconName('upload') 1596 ->setWysiwygToken('tikifile') 1597 ->setType('FileGallery') 1598 ->addRequiredPreference('feature_filegals_manager'); 1599 } // }}} 1600 1601 function getSyntax($areaId) 1602 { 1603 $smarty = TikiLib::lib('smarty'); 1604 $smarty->loadPlugin('smarty_function_filegal_manager_url'); 1605 return 'openFgalsWindow(\'' . htmlentities(smarty_function_filegal_manager_url(['area_id' => $areaId], $smarty->getEmptyInternalTemplate())) 1606 . '&insertion_syntax=file\', true);'; 1607 } 1608} 1609 1610class ToolbarSwitchEditor extends Toolbar 1611{ 1612 private $name; 1613 function __construct() // {{{ 1614 { 1615 $this->setLabel(tra('Switch Editor (wiki or WYSIWYG)')) 1616 ->setIconName('pencil') 1617 ->setIcon(tra('img/icons/pencil_go.png')) 1618 ->setWysiwygToken('tikiswitch') 1619 ->setType('SwitchEditor') 1620 ->addRequiredPreference('feature_wysiwyg'); 1621 } // }}} 1622 1623 function getWikiHtml($areaId) // {{{ 1624 { 1625 return $this->getSelfLink( 1626 'switchEditor(\'wysiwyg\', $(this).parents(\'form\')[0]);', 1627 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 1628 'qt-switcheditor' 1629 ); 1630 } // }}} 1631 1632 function getWysiwygToken($areaId) // {{{ 1633 { 1634 global $prefs; 1635 if (! empty($this->wysiwyg)) { 1636 $this->name = $this->wysiwyg; // temp 1637 1638 if ($prefs['feature_wysiwyg'] == 'y' && $prefs['wysiwyg_optional'] == 'y') { 1639 $js = "switchEditor('wiki', $('#$areaId').parents('form')[0]);"; 1640 $this->setupCKEditorTool($js, $this->name, $this->label, $this->icon); 1641 } 1642 } 1643 return $this->wysiwyg; 1644 } // }}} 1645 1646 1647 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 1648 { 1649 return $this->getWysiwygToken($areaId); 1650 } // }}} 1651 1652 1653 function isAccessible() // {{{ 1654 { 1655 global $tiki_p_edit_switch_mode; 1656 1657 return parent::isAccessible() && 1658 ! isset($_REQUEST['hdr']) && // or in section edit 1659 $tiki_p_edit_switch_mode === 'y'; // or no perm (new in 7.1) 1660 } // }}} 1661 1662/* function getLabel() // {{{ 1663 { 1664 return $this->label; 1665 } // }}} 1666*/ 1667} 1668 1669 1670class ToolbarAdmin extends Toolbar 1671{ 1672 private $name; 1673 function __construct() // {{{ 1674 { 1675 $this->setLabel(tra('Admin Toolbars')) 1676 ->setIconName('wrench') 1677 ->setIcon(tra('img/icons/wrench.png')) 1678 ->setWysiwygToken('admintoolbar') 1679 ->setType('admintoolbar'); 1680 //->addRequiredPreference('feature_wysiwyg'); 1681 } // }}} 1682 1683 function getWikiHtml($areaId) // {{{ 1684 { 1685 return $this->getSelfLink( 1686 'admintoolbar();', 1687 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 1688 'qt-admintoolbar' 1689 ); 1690 } // }}} 1691 1692 function getWysiwygToken($areaId) // {{{ 1693 { 1694 global $prefs; 1695 if (! empty($this->wysiwyg)) { 1696 $this->name = $this->wysiwyg; // temp 1697 1698 if ($prefs['feature_wysiwyg'] == 'y') { 1699 $js = "admintoolbar();"; 1700 $this->setupCKEditorTool($js, $this->name, $this->label, $this->icon); 1701 } 1702 } 1703 return $this->wysiwyg; 1704 } // }}} 1705 1706 1707 function getWysiwygWikiToken($areaId) // {{{ // wysiwyg_htmltowiki 1708 { 1709 return $this->getWysiwygToken($areaId); 1710 } // }}} 1711} 1712 1713class ToolbarWikiplugin extends Toolbar 1714{ 1715 private $pluginName; 1716 1717 public static function fromName($name) // {{{ 1718 { 1719 global $tikilib; 1720 $parserlib = TikiLib::lib('parser'); 1721 1722 if (substr($name, 0, 11) == 'wikiplugin_') { 1723 $name = substr($name, 11); 1724 if ($info = $parserlib->plugin_info($name)) { 1725 $tag = new self; 1726 $tag->setLabel(str_ireplace('wikiplugin_', '', $info['name'])) 1727 ->setWysiwygToken(str_replace(' ', '_', $info['name'])) 1728 ->setPluginName($name) 1729 ->setType('Wikiplugin'); 1730 1731 if (! empty($info['iconname'])) { 1732 $tag->setIconName($info['iconname']); 1733 } elseif (! empty($info['icon'])) { 1734 $tag->setIcon($info['icon']); 1735 } else { 1736 $tag->setIcon('img/icons/plugin.png'); 1737 } 1738 1739 TikiLib::lib('header')->add_jsfile('lib/jquery_tiki/tiki-toolbars.js'); 1740 1741 return $tag; 1742 } 1743 } 1744 } // }}} 1745 1746 function setPluginName($name) // {{{ 1747 { 1748 $this->pluginName = $name; 1749 1750 return $this; 1751 } // }}} 1752 1753 function getPluginName() // {{{ 1754 { 1755 return $this->pluginName; 1756 } // }}} 1757 1758 function isAccessible() // {{{ 1759 { 1760 global $tikilib; 1761 $parserlib = TikiLib::lib('parser'); 1762 $dummy_output = ''; 1763 return parent::isAccessible() && $parserlib->plugin_enabled($this->pluginName, $dummy_output); 1764 } // }}} 1765 1766 private static function getToken($name) // {{{ 1767 { 1768 switch ($name) { 1769 case 'flash': 1770 return 'Flash'; 1771 } 1772 } // }}} 1773 1774 function getWikiHtml($areaId) // {{{ 1775 { 1776 return $this->getSelfLink( 1777 'popupPluginForm(\'' . $areaId . '\',\'' . $this->pluginName . '\')', 1778 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 1779 'qt-plugin' 1780 ); 1781 } // }}} 1782 function getWysiwygToken($areaId, $add_js = true) // {{{ 1783 { 1784 if (! empty($this->wysiwyg) && $add_js) { 1785 $js = "popupPluginForm(editor.name,'{$this->pluginName}');"; 1786 //CKEditor needs image icons so get legacy plugin icons for the toolbar 1787 if (! $this->icon && ! empty($this->iconname)) { 1788 $iconsetlib = TikiLib::lib('iconset'); 1789 $legacy = $iconsetlib->loadFile('themes/base_files/iconsets/legacy.php'); 1790 if (array_key_exists($this->iconname, $legacy['icons'])) { 1791 $iconinfo = $legacy['icons'][$this->iconname]; 1792 } elseif (in_array($this->iconname, $legacy['defaults'])) { 1793 $iconinfo['id'] = $this->iconname; 1794 } 1795 if (isset($iconinfo)) { 1796 $prepend = isset($iconinfo['prepend']) ? $iconinfo['prepend'] : 'img/icons/'; 1797 $append = isset($iconinfo['append']) ? $iconinfo['append'] : '.png'; 1798 $iconpath = $prepend . $iconinfo['id'] . $append; 1799 } else { 1800 $iconpath = 'img/icons/plugin.png'; 1801 } 1802 } 1803 $this->setupCKEditorTool($js, $this->wysiwyg, $this->label, $iconpath); 1804 } 1805 return $this->wysiwyg; 1806 } // }}} 1807 1808 function getWysiwygWikiToken($areaId, $add_js = true) // {{{ // wysiwyg_htmltowiki 1809 { 1810 switch ($this->pluginName) { 1811 case 'img': 1812 $this->wysiwyg = 'wikiplugin_img'; // don't use ckeditor's html image dialog 1813 break; 1814 default: 1815 } 1816 1817 return $this->getWysiwygToken($areaId, $add_js); 1818 } // }}} 1819} 1820 1821class ToolbarSheet extends Toolbar 1822{ 1823 protected $syntax; 1824 1825 public static function fromName($tagName) // {{{ 1826 { 1827 switch ($tagName) { 1828 case 'sheetsave': 1829 $label = tra('Save Sheet'); 1830 $iconname = 'floppy'; 1831 $syntax = ' 1832 $("#saveState").hide(); 1833 $.sheet.saveSheet($.sheet.tikiSheet, function() { 1834 $.sheet.manageState($.sheet.tikiSheet, true); 1835 });'; 1836 break; 1837 case 'addrow': 1838 $label = tra('Add row after selection or to the end if no selection'); 1839 $icon = tra('img/icons/sheet_row_add.png'); 1840 $syntax = 'sheetInstance.controlFactory.addRow();'; // add row after end to workaround bug in jquery.sheet.js 1.0.2 1841 break; // TODO fix properly for 5.1 1842 case 'addrowmulti': 1843 $label = tra('Add multiple rows after selection or to the end if no selection'); 1844 $icon = tra('img/icons/sheet_row_add_multi.png'); 1845 $syntax = 'sheetInstance.controlFactory.addRowMulti();'; 1846 break; 1847 case 'addrowbefore': 1848 $label = tra('Add row before selection or to end if no selection'); 1849 $icon = tra('img/icons/sheet_row_add.png'); 1850 $syntax = 'sheetInstance.controlFactory.addRow(null, true);'; // add row after end to workaround bug in jquery.sheet.js 1.0.2 1851 break; 1852 case 'deleterow': 1853 $label = tra('Delete selected row'); 1854 $icon = tra('img/icons/sheet_row_delete.png'); 1855 $syntax = 'sheetInstance.deleteRow();'; 1856 break; 1857 case 'addcolumn': 1858 $label = tra('Add column after selection or to the end if no selection'); 1859 $icon = tra('img/icons/sheet_col_add.png'); 1860 $syntax = 'sheetInstance.controlFactory.addColumn();'; // add col before current or at end if none selected 1861 break; 1862 case 'deletecolumn': 1863 $label = tra('Delete selected column'); 1864 $icon = tra('img/icons/sheet_col_delete.png'); 1865 $syntax = 'sheetInstance.deleteColumn();'; 1866 break; 1867 case 'addcolumnmulti': 1868 $label = tra('Add multiple columns after selection or to the end if no selection'); 1869 $icon = tra('img/icons/sheet_col_add_multi.png'); 1870 $syntax = 'sheetInstance.controlFactory.addColumnMulti();'; 1871 break; 1872 case 'addcolumnbefore': 1873 $label = tra('Add column before selection or to the end if no selection'); 1874 $icon = tra('img/icons/sheet_col_add.png'); 1875 $syntax = 'sheetInstance.controlFactory.addColumn(null, true);'; // add col before current or at end if none selected 1876 break; 1877 case 'sheetgetrange': 1878 $label = tra('Get Cell Range'); 1879 $icon = tra('img/icons/sheet_get_range.png'); 1880 $syntax = 'sheetInstance.getTdRange(null, sheetInstance.obj.formula().val()); return false;'; 1881 break; 1882 case 'sheetfind': 1883 $label = tra('Find'); 1884 $iconname = 'search'; 1885 $syntax = 'sheetInstance.cellFind();'; 1886 break; 1887 case 'sheetrefresh': 1888 $label = tra('Refresh calculations'); 1889 $iconname = 'refresh'; 1890 $syntax = 'sheetInstance.calc();'; 1891 break; 1892 case 'sheetclose': 1893 $label = tra('Finish editing'); 1894 $iconname = 'delete'; 1895 $syntax = '$.sheet.manageState(sheetInstance.obj.parent(), true);'; // temporary workaround TODO properly 1896 break; 1897 case 'bold': 1898 $label = tra('Bold'); 1899 $iconname = 'bold'; 1900 $wysiwyg = 'Bold'; 1901 $syntax = 'sheetInstance.cellStyleToggle("styleBold");'; 1902 break; 1903 case 'italic': 1904 $label = tra('Italic'); 1905 $iconname = 'italic'; 1906 $wysiwyg = 'Italic'; 1907 $syntax = 'sheetInstance.cellStyleToggle("styleItalics");'; 1908 break; 1909 case 'underline': 1910 $label = tra('Underline'); 1911 $iconname = 'underline'; 1912 $wysiwyg = 'Underline'; 1913 $syntax = 'sheetInstance.cellStyleToggle("styleUnderline");'; 1914 break; 1915 case 'strike': 1916 $label = tra('Strikethrough'); 1917 $iconname = 'strikethrough'; 1918 $wysiwyg = 'Strike'; 1919 $syntax = 'sheetInstance.cellStyleToggle("styleLineThrough");'; 1920 break; 1921 case 'center': 1922 $label = tra('Align Center'); 1923 $iconname = 'align-center'; 1924 $syntax = 'sheetInstance.cellStyleToggle("styleCenter");'; 1925 break; 1926 default: 1927 return; 1928 } 1929 1930 $tag = new self; 1931 $tag->setLabel($label) 1932 ->setSyntax($syntax) 1933 ->setType('Sheet'); 1934 if (! empty($iconname)) { 1935 $tag->setIconName(! empty($iconname) ? $iconname : 'help'); 1936 } 1937 if (! empty($icon)) { 1938 $tag->setIcon(! empty($icon) ? $icon : 'img/icons/shading.png'); 1939 } 1940 1941 return $tag; 1942 } // }}} 1943 1944 function getSyntax($areaId) // {{{ 1945 { 1946 return $this->syntax; 1947 } // }}} 1948 1949 protected function setSyntax($syntax) // {{{ 1950 { 1951 $this->syntax = $syntax; 1952 1953 return $this; 1954 } // }}} 1955 1956 function getWikiHtml($areaId) // {{{ 1957 { 1958 return $this->getSelfLink( 1959 addslashes(htmlentities($this->syntax, ENT_COMPAT, 'UTF-8')), 1960 htmlentities($this->label, ENT_QUOTES, 'UTF-8'), 1961 'qt-sheet' 1962 ); 1963 } // }}} 1964} 1965 1966 1967 1968class ToolbarsList 1969{ 1970 private $lines = []; 1971 private $wysiwyg = false; 1972 private $is_html = false; 1973 1974 private function __construct() 1975 { 1976 } 1977 1978 /*** 1979 * @param array $params params from smarty_function_toolbars 1980 * @param array $tags_to_hide list of tools not to show 1981 * @return ToolbarsList 1982 */ 1983 public static function fromPreference($params, $tags_to_hide = []) // {{{ 1984 { 1985 global $tikilib; 1986 1987 $global = $tikilib->get_preference('toolbar_global' . ($params['comments'] === 'y' ? '_comments' : '')); 1988 $local = $tikilib->get_preference('toolbar_' . $params['section'] . ($params['comments'] === 'y' ? '_comments' : ''), $global); 1989 1990 foreach ($tags_to_hide as $name) { 1991 $local = str_replace($name, '', $local); 1992 } 1993 if ($params['section'] === 'wysiwyg_plugin') { // quick fix to prevent nested wysiwyg plugins (messy) 1994 $local = str_replace('wikiplugin_wysiwyg', '', $local); 1995 } 1996 1997 $local = str_replace([',,', '|,', ',|', ',/', '/,'], [',', '|', '|', '/', '/'], $local); 1998 1999 return self::fromPreferenceString($local, $params); 2000 } // }}} 2001 2002 public static function fromPreferenceString($string, $params) // {{{ 2003 { 2004 global $toolbarPickerIndex; 2005 $toolbarPickerIndex = -1; 2006 $list = new self; 2007 $list->wysiwyg = (isset($params['_wysiwyg']) && $params['_wysiwyg'] === 'y'); 2008 $list->is_html = ! empty($params['_is_html']); 2009 2010 $string = preg_replace('/\s+/', '', $string); 2011 2012 foreach (explode('/', $string) as $line) { 2013 $bits = explode('|', $line); 2014 if (count($bits) > 1) { 2015 $list->addLine(explode(',', $bits[0]), explode(',', $bits[1])); 2016 } else { 2017 $list->addLine(explode(',', $bits[0])); 2018 } 2019 } 2020 2021 return $list; 2022 } // }}} 2023 2024 public function addTag($name, $unique = false) 2025 { 2026 if ($unique && $this->contains($name)) { 2027 return false; 2028 } 2029 $this->lines[count($this->lines) - 1][0][0][] = Toolbar::getTag($name); 2030 return true; 2031 } 2032 2033 public function insertTag($name, $unique = false) 2034 { 2035 if ($unique && $this->contains($name)) { 2036 return false; 2037 } 2038 array_unshift($this->lines[0][0][0], Toolbar::getTag($name)); 2039 return true; 2040 } 2041 2042 private function addLine(array $tags, array $rtags = []) // {{{ 2043 { 2044 $elements = []; 2045 $j = count($rtags) > 0 ? 2 : 1; 2046 2047 for ($i = 0; $i < $j; $i++) { 2048 $group = []; 2049 $elements[$i] = []; 2050 2051 if ($i == 0) { 2052 $thetags = $tags; 2053 } else { 2054 $thetags = $rtags; 2055 } 2056 foreach ($thetags as $tagName) { 2057 if ($tagName === '-' || $tagName === '|') { 2058 if (count($group)) { 2059 $elements[$i][] = $group; 2060 $group = []; 2061 } 2062 } else { 2063 if (( $tag = Toolbar::getTag($tagName, $this->wysiwyg, $this->is_html) ) 2064 && $tag->isAccessible() ) { 2065 $group[] = $tag; 2066 } 2067 } 2068 } 2069 2070 if (count($group)) { 2071 $elements[$i][] = $group; 2072 } 2073 } 2074 if (count($elements)) { 2075 $this->lines[] = $elements; 2076 } 2077 } // }}} 2078 2079 function getWysiwygArray($areaId, $isHtml = true) // {{{ 2080 { 2081 $lines = []; 2082 foreach ($this->lines as $line) { 2083 $lineOut = []; 2084 2085 foreach ($line as $bit) { 2086 foreach ($bit as $group) { 2087 $group_count = 0; 2088 foreach ($group as $tag) { 2089 if ($isHtml) { 2090 if ($token = $tag->getWysiwygToken($areaId)) { 2091 $lineOut[] = $token; 2092 $group_count++; 2093 } 2094 } else { 2095 if ($token = $tag->getWysiwygWikiToken($areaId)) { 2096 $lineOut[] = $token; 2097 $group_count++; 2098 } 2099 } 2100 } 2101 if ($group_count) { // don't add separators for empty groups 2102 $lineOut[] = '-'; 2103 } 2104 } 2105 } 2106 2107 $lineOut = array_slice($lineOut, 0, -1); 2108 2109 if (count($lineOut)) { 2110 $lines[] = [$lineOut]; 2111 } 2112 } 2113 2114 return $lines; 2115 } // }}} 2116 2117 function getWikiHtml($areaId, $comments = '') // {{{ 2118 { 2119 global $tiki_p_admin, $tiki_p_admin_toolbars, $section, $prefs; 2120 $headerlib = TikiLib::lib('header'); 2121 $smarty = TikiLib::lib('smarty'); 2122 $html = ''; 2123 2124 $c = 0; 2125 foreach ($this->lines as $line) { 2126 $lineHtml = ''; 2127 $right = ''; 2128 if (count($line) == 1) { 2129 $line[1] = []; 2130 } 2131 2132 // $line[0] is left part, $line[1] right floated section 2133 for ($bitx = 0, $bitxcount_line = count($line); $bitx < $bitxcount_line; $bitx++) { 2134 $lineBit = ''; 2135 2136 /*if ($c == 0 && $bitx == 1 && ($tiki_p_admin == 'y' or $tiki_p_admin_toolbars == 'y')) { 2137 $params = array('_script' => 'tiki-admin_toolbars.php', '_onclick' => 'needToConfirm = true;', '_class' => 'toolbar', '_icon' => 'wrench', '_ajax' => 'n'); 2138 if (isset($comments) && $comments == 'y') 2139 $params['comments'] = 'on'; 2140 if (isset($section)) 2141 $params['section'] = $section; 2142 $content = tra('Admin Toolbars'); 2143 $right .= smarty_block_self_link($params, $content, $smarty); 2144 }*/ 2145 2146 foreach ($line[$bitx] as $group) { 2147 $groupHtml = ''; 2148 foreach ($group as $tag) { 2149 $groupHtml .= $tag->getWikiHtml($areaId); 2150 } 2151 2152 if (! empty($groupHtml)) { 2153 $param = ' class="toolbar-list"'; 2154 $lineBit .= "<span$param>$groupHtml</span>"; 2155 } 2156 if ($bitx == 1) { 2157 if (! empty($right)) { 2158 $right = '<span class="toolbar-list">' . $right . '</span>'; 2159 } 2160 $lineHtml = "<div class='helptool-admin float-right'>$lineBit $right</div>" . $lineHtml; 2161 } else { 2162 $lineHtml = $lineBit; 2163 } 2164 } 2165 2166 // adding admin icon if no right part - messy - TODO better 2167 if ($c == 0 && empty($lineBit) && ! empty($right)) { 2168 $lineHtml .= "<div class='helptool-admin float-right'>$right</div>"; 2169 } 2170 } 2171 if (! empty($lineHtml)) { 2172 $html .= "<div>$lineHtml</div>"; 2173 } 2174 $c++; 2175 } 2176 2177 return $html; 2178 } // }}} 2179 2180 function contains($name) 2181 { 2182 // {{{ 2183 foreach ($this->lines as $line) { 2184 foreach ($line as $group) { 2185 foreach ($group as $tags) { 2186 foreach ($tags as $tag) { 2187 if ($tag->getLabel() == $name) { 2188 return true; 2189 } 2190 } 2191 } 2192 } 2193 } 2194 return false; 2195 } // }}} 2196} 2197 2198 2199/** 2200 * Definition of the CKE Toolbar Combos 2201 */ 2202class ToolbarCombos 2203{ 2204 2205 /** 2206 * Get the content of the format combo 2207 * 2208 * Valid toolbar types are: 2209 * - 'html': WYSIWYG-HTML 2210 * - 'wiki': Visual Wiki 2211 * 2212 * @param string $tb_type The CKE toolbar type 2213 */ 2214 static function getFormatTags($tb_type) 2215 { 2216 switch ($tb_type) { 2217 case 'wiki': 2218 return 'p;h1;h2;h3;h4;h5;h6'; 2219 break; 2220 case 'html': 2221 default: 2222 return 'p;h1;h2;h3;h4;h5;h6;pre;address;div'; // CKE default 2223 } 2224 } 2225} 2226