File modules/cms/generator/ValueGenerator.class.php

Last commit: Wed Apr 17 00:34:07 2024 +0200	Jan Dankert	New: Inputfields for coordinates; coordinates are stored in the now 64bit-number-field of the value.
1 <?php 2 3 4 namespace cms\generator; 5 6 7 use cms\base\Configuration; 8 use cms\base\Configuration as C; 9 use cms\base\DB; 10 use cms\base\Startup; 11 use cms\generator\dsl\CMSDslInterpreter; 12 use cms\generator\dsl\DslCms; 13 use cms\generator\dsl\DslConsole; 14 use cms\generator\dsl\DslDocument; 15 use cms\generator\dsl\DslHttp; 16 use cms\generator\dsl\DslJson; 17 use cms\generator\dsl\DslObject; 18 use cms\generator\dsl\DslPage; 19 use cms\generator\dsl\DslPageContext; 20 use cms\generator\dsl\DslProject; 21 use cms\generator\dsl\DslWrite; 22 use cms\macros\MacroRunner; 23 use cms\model\BaseObject; 24 use cms\model\Element; 25 use cms\model\File; 26 use cms\model\Folder; 27 use cms\model\Image; 28 use cms\model\Language; 29 use cms\model\Link; 30 use cms\model\Page; 31 use cms\model\PageContent; 32 use cms\model\Project; 33 use cms\model\Template; 34 use cms\model\Value; 35 use dsl\DslException; 36 use dsl\standard\Data; 37 use logger\Logger; 38 use util\Code; 39 use util\exception\GeneratorException; 40 use util\exception\ObjectNotFoundException; 41 use util\exception\PublisherException; 42 use util\Html; 43 use util\Http; 44 use util\Request; 45 use util\Text; 46 use util\Transformer; 47 use util\YAML; 48 49 50 /** 51 * Generates a value. 52 */ 53 class ValueGenerator extends BaseGenerator 54 { 55 56 const CODE_PHP = 'php'; 57 const CODE_SCRIPT = 'js'; 58 const CODE_MUSTACHE = 'mustache'; 59 60 const INFO_DB_ID = 'db_id'; 61 const INFO_DB_NAME = 'db_name'; 62 const INFO_PROJECT_ID = 'project_id'; 63 const INFO_PROJECT_NAME = 'project_name'; 64 const INFO_LANGUAGE_ID = 'language_id'; 65 const INFO_LANGUAGE_ISO = 'language_iso'; 66 const INFO_LANGUAGE_NAME = 'language_name'; 67 const INFO_PAGE_ID = 'page_id'; 68 const INFO_PAGE_NAME = 'page_name'; 69 const INFO_PAGE_DESC = 'page_desc'; 70 const INFO_PAGE_FULLFILENAME = 'page_fullfilename'; 71 const INFO_PAGE_FILENAME = 'page_filename'; 72 const INFO_PAGE_EXTENSION = 'page_extension'; 73 const INFO_EDIT_URL = 'edit_url'; 74 const INFO_EDIT_FULLURL = 'edit_fullurl'; 75 const INFO_LASTCHANGE_USER_USERNAME = 'lastch_user_username'; 76 const INFO_LASTCHANGE_USER_FULLNAME = 'lastch_user_fullname'; 77 const INFO_LASTCHANGE_USER_MAIL = 'lastch_user_mail'; 78 const INFO_LASTCHANGE_USER_DESC = 'lastch_user_desc'; 79 const INFO_LASTCHANGE_USER_TEL = 'lastch_user_tel'; 80 const INFO_CREATION_USER_USERNAME = 'create_user_username'; 81 const INFO_CREATION_FULLNAME = 'create_user_fullname'; 82 const INFO_CREATION_MAIL = 'create_user_mail'; 83 const INFO_CREATION_DESC = 'create_user_desc'; 84 const INFO_CREATION_TEL = 'create_user_tel'; 85 const INFO_ACT_USERNAME = 'act_user_username'; 86 const INFO_ACT_FULLNAME = 'act_user_fullname'; 87 const INFO_ACT_MAIL = 'act_user_mail'; 88 const INFO_ACT_DESC = 'act_user_desc'; 89 const INFO_ACT_TEL = 'act_user_tel'; 90 const INFO_PUB_USERNAME = 'pub_user_username'; 91 const INFO_PUB_FULLNAME = 'pub_user_fullname'; 92 const INFO_PUB_MAIL = 'pub_user_mail'; 93 const INFO_PUB_DESC = 'pub_user_desc'; 94 const INFO_PUB_TEL = 'pub_user_tel'; 95 const INFO_FILENAME = 'filename'; 96 const INFO_FULL_FILENAME = 'full_filename'; 97 98 const COORD_OLC = 'olc'; 99 const COORD_COORDINATES = 'coordinates'; 100 101 const INFO_DATE_PUBLISHED = 'date_published'; 102 const INFO_DATE_SAVED = 'date_saved'; 103 const INFO_DATE_CREATED = 'date_created'; 104 105 const INSERT_ESI = 'esi'; 106 const INSERT_SSI = 'ssi'; 107 const INSERT_INLINE = 'inline'; 108 109 110 const LINK_FILE_ = 'file'; 111 const LINK_IMAGE = 'image'; 112 const LINK_IMAGE_DATE_URI = 'image_data_uri'; 113 const LINK_PAGE = 'page'; 114 const LINK_FOLDER = 'folder'; 115 const LINK_LINK = 'link'; 116 117 const LINKINFO_WIDTH = 'width'; 118 const LINKINFO_HEIGHT = 'height'; 119 const LINKINFO_ID = 'id'; 120 const LINKINFO_NAME = 'name'; 121 const LINKINFO_DESCRIPTION = 'description'; 122 const LINKINFO_MIME_TYPE = 'mime_type'; 123 124 125 /** 126 * Constructor. 127 * 128 * @param $valueContext ValueContext 129 */ 130 public function __construct($valueContext ) 131 { 132 $this->context = $valueContext; 133 } 134 135 136 137 protected function generate() 138 { 139 return $this->generateValue(); 140 } 141 142 143 144 145 /** 146 * Generating a page value. 147 * 148 * @return string 149 */ 150 private function generateValue() 151 { 152 $pageContext = $this->context->pageContext; 153 $page = new Page( $pageContext->objectId ); 154 $page->load(); 155 156 $element = new Element( $this->context->elementid ); 157 $element->load(); 158 159 $pageContent = new PageContent(); 160 161 $pageContent->pageId = $page->pageid; 162 $pageContent->elementId = $this->context->elementid; 163 $pageContent->languageid = $pageContext->languageId; 164 $pageContent->load(); 165 166 $value = new Value(); 167 $value->contentid = $pageContent->contentId; 168 169 if ( $this->context->scheme == Producer::SCHEME_PREVIEW ) 170 $value->load(); 171 else 172 $value->loadPublished(); 173 174 if ( ! $this->isValueHasContent( $value,$element ) ) 175 { 176 $pageForDefaultValue = $page->getPageAsDefault(); 177 178 if ( $pageForDefaultValue ) { 179 180 $pageContext = clone $this->context->pageContext; 181 $pageContext->objectId = $pageForDefaultValue->objectid; 182 183 $valueContext = clone $this->context; 184 $valueContext->pageContext = $pageContext; 185 186 $generator = new ValueGenerator( $valueContext ); 187 188 return $generator->getCache()->get(); 189 } 190 } 191 192 $inhalt = ''; 193 194 switch( $element->typeid ) 195 { 196 case Element::ELEMENT_TYPE_INSERT: 197 198 $objectid = $value->linkToObjectId; 199 200 if ( ! $objectid ) 201 $objectid = $element->defaultObjectId; 202 203 if ( ! BaseObject::available( $objectid) ) 204 break; 205 206 $inhalt = $this->generatePageValue( $pageContext,$element,$objectid ); 207 208 if ( false&& $value->publisher->isSimplePreview() ) 209 { 210 $inhalt = strip_tags( $inhalt ); 211 $inhalt = str_replace( "\n",'',$inhalt ); 212 $inhalt = str_replace( "\r",'',$inhalt ); 213 } 214 215 break; 216 217 218 case Element::ELEMENT_TYPE_LINK: 219 220 $objectid = $value->linkToObjectId; 221 if ( intval($objectid) == 0 ) 222 $objectid = $element->defaultObjectId; 223 224 if ( $objectid==0 ) 225 { 226 // Link noch nicht gefuellt 227 $inhalt = ''; 228 } 229 elseif ( ! BaseObject::available($objectid) ) 230 { 231 $inhalt = /*$value->publisher->isSimplePreview()?'-':*/''; 232 } 233 elseif ( /*$value->publisher->isSimplePreview()*/false ) 234 { 235 $o = new BaseObject( $objectid ); 236 $o->load(); 237 $inhalt = $o->filename; 238 } 239 elseif ($element->subtype == self::LINK_IMAGE_DATE_URI ) 240 { 241 $context = new FileContext( $objectid,Producer::SCHEME_PUBLIC ); 242 $generator = new FileGenerator( $context ); 243 $file = new File($objectid); 244 $file->load(); 245 $inhalt = 'data:'.$generator->getMimeType().';base64,'.base64_encode($generator->getCache()->get()); 246 } 247 else 248 { 249 $sourcePage = new Page( $pageContext->sourceObjectId ); // the source page 250 $target = new BaseObject( $objectid ); 251 $target->load(); 252 253 $filteredValue = $this->filterValue( new DslObject($target), $element->code ); 254 255 if ( is_string($filteredValue) ) { 256 $inhalt = $filteredValue; 257 } 258 else { 259 $linkScheme = $pageContext->getLinkScheme(); 260 $inhalt = $linkScheme->linkToObject( $sourcePage, $target ); 261 } 262 } 263 264 break; 265 266 267 case Element::ELEMENT_TYPE_COPY: 268 269 list($linkElementName,$targetElementName) = explode('%',$element->name.'%'); 270 271 if ( empty($targetElementName) ) 272 break; 273 274 // TODO: missing element-id 275 $element = new Element(); 276 $element->name = $linkElementName; 277 $element->load(); 278 279 if ( intval($element->elementid)==0 ) 280 break; 281 282 // TODO: does not work 283 $linkValue = new Value(); 284 $linkValue->load(); 285 286 if ( !BaseObject::available( $linkValue->linkToObjectId ) ) 287 break; 288 289 $linkedPage = new Page( $linkValue->linkToObjectId ); 290 $linkedPage->load(); 291 292 $linkedPageTemplate = new Template( $linkedPage->templateid ); 293 $targetElementId = array_search( $targetElementName, $linkedPageTemplate->getElementNames() ); 294 295 if ( intval($targetElementId)==0 ) 296 break; 297 298 $valueContext = new ValueContext( $pageContext ); 299 $valueContext->elementid = $targetElementId; 300 301 $value = new ValueGenerator($valueContext); 302 $inhalt = $value->getCache()->get(); 303 304 break; 305 306 307 case Element::ELEMENT_TYPE_LINKINFO: 308 309 @list( $linkElementName, $name ) = explode('%',$element->name); 310 if ( is_null($name) ) 311 break; 312 313 $template = new Template( $page->templateid ); 314 $elementId = array_search( $linkElementName, $template->getElementNames() ); 315 316 $linkedElement = new Element($elementId); 317 $linkedElement->load(); 318 319 $pageContent = new PageContent(); 320 $pageContent->pageId = $page->pageid; 321 $pageContent->languageid = $pageContext->languageId; 322 $pageContent->elementId = $elementId; 323 $pageContent->load(); 324 325 $linkValue = new Value(); 326 $linkValue->contentid = $pageContent->contentId; 327 $linkValue->load(); 328 329 $objectid = $linkValue->linkToObjectId; 330 331 if ( intval($objectid) == 0 ) 332 $objectid = $element->defaultObjectId; 333 334 if ( !BaseObject::available( $objectid ) ) 335 break; 336 337 $linkedObject = new BaseObject( $objectid ); 338 $linkedObject->load(); 339 340 switch( $linkedElement->subtype ) 341 { 342 case self::LINKINFO_WIDTH: 343 $f = new Image( $objectid ); 344 $f->load(); 345 if ( $f->typeid == BaseObject::TYPEID_IMAGE ) 346 { 347 $f->getImageSize(); 348 $inhalt = $f->width; 349 } 350 unset($f); 351 break; 352 353 case self::LINKINFO_HEIGHT: 354 $f = new Image( $objectid ); 355 $f->load(); 356 if ( $f->typeid == BaseObject::TYPEID_IMAGE ) 357 { 358 $f->getImageSize(); 359 $inhalt = $f->height; 360 } 361 unset($f); 362 break; 363 364 case self::LINKINFO_ID: 365 $inhalt = $objectid; 366 break; 367 368 case self::LINKINFO_NAME: 369 $inhalt = $linkedObject->getDefaultName()->getName(); 370 break; 371 372 case self::LINKINFO_DESCRIPTION: 373 $inhalt = $linkedObject->getDefaultName()->description; 374 break; 375 376 case self::INFO_CREATION_DESC: 377 $user = $linkedObject->createUser; 378 try 379 { 380 $user->load(); 381 $inhalt = $user->desc; 382 } 383 catch( ObjectNotFoundException $e ) 384 { 385 } 386 break; 387 388 case self::INFO_CREATION_FULLNAME: 389 $user = $linkedObject->createUser; 390 try 391 { 392 $user->load(); 393 $inhalt = $user->fullname; 394 } 395 catch( ObjectNotFoundException $e ) 396 { 397 } 398 break; 399 400 case self::INFO_CREATION_MAIL: 401 $user = $linkedObject->createUser; 402 try 403 { 404 $user->load(); 405 $inhalt = $user->mail; 406 } 407 catch( ObjectNotFoundException $e ) 408 { 409 } 410 break; 411 412 case self::INFO_CREATION_TEL: 413 $user = $linkedObject->createUser; 414 try 415 { 416 $user->load(); 417 $inhalt = $user->tel; 418 } 419 catch( ObjectNotFoundException $e ) 420 { 421 } 422 break; 423 424 case self::INFO_CREATION_USER_USERNAME: 425 $user = $linkedObject->createUser; 426 try 427 { 428 $user->load(); 429 $inhalt = $user->name; 430 } 431 catch( ObjectNotFoundException $e ) 432 { 433 } 434 break; 435 436 case self::INFO_LASTCHANGE_USER_DESC: 437 $user = $linkedObject->lastchangeUser; 438 try 439 { 440 $user->load(); 441 $inhalt = $user->desc; 442 } 443 catch( ObjectNotFoundException $e ) 444 { 445 } 446 break; 447 448 case self::INFO_LASTCHANGE_USER_FULLNAME: 449 $user = $linkedObject->lastchangeUser; 450 try 451 { 452 $user->load(); 453 $inhalt = $user->fullname; 454 } 455 catch( ObjectNotFoundException $e ) 456 { 457 } 458 break; 459 460 case self::INFO_LASTCHANGE_USER_MAIL: 461 $user = $linkedObject->lastchangeUser; 462 try 463 { 464 $user->load(); 465 $inhalt = $user->mail; 466 } 467 catch( ObjectNotFoundException $e ) 468 { 469 } 470 break; 471 472 case self::INFO_LASTCHANGE_USER_TEL: 473 $user = $linkedObject->lastchangeUser; 474 try 475 { 476 $user->load(); 477 $inhalt = $user->tel; 478 } 479 catch( ObjectNotFoundException $e ) 480 { 481 } 482 483 break; 484 485 case self::INFO_LASTCHANGE_USER_USERNAME: 486 $user = $linkedObject->lastchangeUser; 487 try 488 { 489 $user->load(); 490 $inhalt = $user->name; 491 } 492 catch( ObjectNotFoundException $e ) 493 { 494 } 495 break; 496 497 case self::LINKINFO_MIME_TYPE: 498 if ( $linkedObject->isFile || $linkedObject->isImage || $linkedObject->isText ) 499 { 500 $context = new FileContext( $objectid,Producer::SCHEME_PUBLIC ); 501 $generator = new FileGenerator( $context ); 502 $inhalt = $generator->getMimeType(); 503 unset($f); 504 } 505 break; 506 507 case self::INFO_FILENAME: 508 $inhalt = $linkedObject->filename(); 509 break; 510 511 case self::INFO_FULL_FILENAME: 512 $inhalt = $linkedObject->full_filename(); 513 break; 514 515 default: 516 $inhalt = ''; 517 Logger::warn('Subtype \''.$linkedElement->subtype.'\' for element \''.$linkedElement.'\' not implemented'); // should not happen 518 } 519 520 break; 521 522 case Element::ELEMENT_TYPE_LINKDATE: 523 524 @list( $linkElementName, $name ) = explode('%',$element->name); 525 if ( is_null($name) ) 526 break; 527 528 $template = new Template( $page->templateid ); 529 $elementId = array_search( $linkElementName, $template->getElementNames() ); 530 531 $element = new Element($elementId); 532 $element->load(); 533 534 $pageContent = new PageContent(); 535 $pageContent->pageId = $page->pageid; 536 $pageContent->languageid = $pageContext->languageId; 537 $pageContent->elementId = $elementId; 538 $pageContent->load(); 539 540 $linkValue = new Value(); 541 $linkValue->contentid = $pageContent->contentId; 542 $linkValue->load(); 543 544 $objectid = $linkValue->linkToObjectId; 545 546 if ( intval($objectid) == 0 ) 547 $objectid = $element->defaultObjectId; 548 549 if ( !BaseObject::available( $objectid ) ) 550 break; 551 552 $linkedObject = new BaseObject( $objectid ); 553 $linkedObject->load(); 554 555 556 switch( $element->subtype ) 557 { 558 case self::INFO_DATE_PUBLISHED: 559 // START_TIME wird zu Beginn im Controller gesetzt. 560 // So erh�lt jede Datei das gleiche Ver�ffentlichungsdatum. 561 $date = Startup::getStartTime(); 562 break; 563 564 case self::INFO_DATE_SAVED: 565 $date = $linkedObject->lastchangeDate; 566 break; 567 568 case self::INFO_DATE_CREATED: 569 $date = $linkedObject->createDate; 570 break; 571 572 default: 573 Logger::warn('element:'.$element->name.', '. 574 'type:'.$element->typeid.', '. 575 'unknown subtype:'.$element->subtype); 576 $date = Startup::getStartTime(); 577 } 578 579 if ( strpos($element->dateformat,'%')!==FALSE ) 580 $inhalt = strftime( $element->dateformat,$date ); 581 else 582 $inhalt = date ( $element->dateformat,$date ); 583 584 $inhalt = $this->filterValue( $inhalt, $element->code ); 585 586 break; 587 588 case Element::ELEMENT_TYPE_LONGTEXT: 589 case Element::ELEMENT_TYPE_TEXT: 590 case Element::ELEMENT_TYPE_SELECT: 591 592 $inhalt = $value->text; 593 $format = $value->format; 594 595 // Wenn Inhalt leer, dann versuchen, den Inhalt der Default-Sprache zu laden. 596 if ( $inhalt == '' && Configuration::subset(['content','language'])->is('use_default_language',true) ) 597 { 598 $project = new Project($page->projectid); 599 600 $otherPageContent = new PageContent(); 601 $otherPageContent->elementId = $pageContent->elementId; 602 $otherPageContent->pageId = $pageContent->pageId; 603 $otherPageContent->languageid = $project->getDefaultLanguageId(); 604 $otherPageContent->load(); 605 606 if ( $otherPageContent->isPersistent() ) { 607 $otherValue = new Value(); 608 $otherValue->contentid = $pageContent->contentId; 609 $otherValue->load(); 610 $inhalt = $otherValue->text; 611 } 612 } 613 614 // Wenn Inhalt leer, dann Vorbelegung verwenden 615 if ( $inhalt == '' ) { 616 617 $inhalt = $element->defaultText; 618 $format = $element->format; 619 } 620 621 // Wenn HTML nicht erlaubt und Wiki-Formatierung aktiv, dann einfache HTML-Tags in Wiki umwandeln 622 $pageIsHtml = $this->isHtml( (new PageGenerator( $this->context->pageContext ))->getMimeType()); 623 624 // 625 switch( $format ) 626 { 627 case Element::ELEMENT_FORMAT_TEXT: 628 case Element::ELEMENT_FORMAT_HTML: 629 630 if ( !$element->html ) 631 { 632 // HTML not allowed. 633 $inhalt = Text::encodeHtml( $inhalt ); 634 $inhalt = Text::encodeHtmlSpecialChars( $inhalt ); 635 } 636 637 break; 638 639 case Element::ELEMENT_FORMAT_WIKI: 640 641 $wikiConfig = C::subset('editor')->subset('wiki'); 642 643 if ( $wikiConfig->is('convert_bbcode',false ) ) 644 $inhalt = Text::bbCode2Wiki( $inhalt ); 645 646 if ( !$element->html && $wikiConfig->is('convert_html',true) && $pageIsHtml) 647 $inhalt = Text::html2Wiki( $inhalt ); 648 649 $transformer = new Transformer(); 650 $transformer->text = $inhalt; 651 $transformer->page = $page; 652 $transformer->pageContext = $pageContext; 653 $transformer->element = $element; 654 655 $transformer->transform(); 656 $inhalt = $transformer->text; 657 break; 658 659 case Element::ELEMENT_FORMAT_MARKDOWN: 660 661 $mdConfig = C::Conf()->subset('editor')->subset('markdown'); 662 663 $parser = new \util\Parsedown(); 664 $parser->setUrlsLinked( $mdConfig->is('urls-linked',true)); 665 $parser->setMarkupEscaped( !$element->html ); 666 667 $inhalt = $parser->parse( $inhalt ); 668 break; 669 670 default: 671 throw new \LogicException('Unknown format: '.$value->format ); 672 } 673 674 /*if ( $value->publisher->isSimplePreview() ) 675 { 676 // Simple Preview with bare text. 677 $inhalt = strip_tags( $inhalt ); 678 $inhalt = str_replace( "\n",'',$inhalt ); 679 $inhalt = str_replace( "\r",'',$inhalt ); 680 }*/ 681 682 // "__OID__nnn__" ersetzen durch einen richtigen Link 683 foreach( Text::parseOID($inhalt) as $oid=>$t ) 684 { 685 $linkFormat = $pageContext->getLinkScheme(); 686 $target = new BaseObject($oid); 687 $target->load(); 688 689 $sourcePage = new Page( $pageContext->sourceObjectId ); 690 $url = $linkFormat->linkToObject($sourcePage,$target); 691 692 foreach( $t as $match ) 693 $inhalt = str_replace($match,$url,$inhalt); 694 } 695 696 switch ($element->typeid) { 697 698 case Element::ELEMENT_TYPE_TEXT: 699 case Element::ELEMENT_TYPE_LONGTEXT: 700 701 $inhalt = $this->filterValue($inhalt, $element->code); 702 break; 703 704 case Element::ELEMENT_TYPE_SELECT: 705 // not for selects, because the code contains the select items. 706 default: 707 } 708 709 break; 710 711 712 // Zahl 713 // 714 // wird im entsprechenden Format angezeigt. 715 case Element::ELEMENT_TYPE_CHECKBOX: 716 717 $inhalt = boolval($value->number); 718 719 $inhalt = $this->filterValue( $inhalt, $element->code ); 720 721 break; 722 723 case Element::ELEMENT_TYPE_NUMBER: 724 725 726 if ( $value->number == 0 ) 727 { 728 // Zahl ist gleich 0, dann Default-Text 729 $inhalt = $element->defaultText; 730 break; 731 } 732 733 $number = $value->number / pow(10,$element->decimals); 734 $inhalt = number_format( $number,$element->decimals,$element->decPoint,$element->thousandSep ); 735 736 737 $inhalt = $this->filterValue( $inhalt, $element->code ); 738 739 break; 740 741 742 // Datum 743 case Element::ELEMENT_TYPE_DATE: 744 745 $date = $value->date; 746 747 if ( intval($date) == 0 ) 748 { 749 // Datum wurde noch nicht eingegeben 750 $inhalt = $element->defaultText; 751 break; 752 } 753 754 // Datum gemaess Elementeinstellung formatieren 755 if ( strpos($element->dateformat,'%')!==FALSE ) 756 $inhalt = strftime( $element->dateformat,$date ); 757 else 758 $inhalt = date ( $element->dateformat,$date ); 759 760 $inhalt = $this->filterValue( $inhalt, $element->code ); 761 762 break; 763 764 765 // Programmcode (PHP) 766 case Element::ELEMENT_TYPE_CODE: 767 768 switch( $element->subtype ) { 769 case self::CODE_PHP: 770 // Die Ausführung von benutzer-erzeugtem PHP-Code kann in der 771 // Konfiguration aus Sicherheitsgründen deaktiviert sein. 772 if ( Configuration::subset('security')->is('disable_dynamic_code',false) ) 773 { 774 Logger::warn("Execution of dynamic code elements is disabled by configuration. Set security/disable_dynamic_code to true to allow this"); 775 break; 776 } 777 778 $page->load(); 779 780 // Das Ausführen geschieht über die Klasse "Code". 781 // In dieser wird der Code in eine Datei geschrieben und 782 // von dort eingebunden. 783 $code = new Code(); 784 $code->setPageContext($this->context->pageContext ); 785 $code->code = $element->code; 786 787 ob_start(); 788 789 // Jetzt ausfuehren des temporaeren PHP-Codes 790 $code->execute(); 791 792 $output = ob_get_contents(); 793 ob_end_clean(); 794 795 // Ausgabe ermitteln. 796 $inhalt = $output; 797 break; 798 799 case self::CODE_SCRIPT: 800 $executor = new CMSDslInterpreter(); 801 $executor->setPageContext( $pageContext ); 802 803 try { 804 $executor->runCode( $element->code ); 805 } 806 catch( DslException $e ) { 807 Logger::info( $e ); 808 809 throw new GeneratorException('Script error'."\n".Text::makeLineNumbers($element->code),$e); 810 } 811 812 // Ausgabe ermitteln. 813 $inhalt = $executor->getOutput(); 814 815 break; 816 case self::CODE_MUSTACHE: 817 // TODO 818 default: 819 } 820 821 822 break; 823 824 825 // Makros (dynamische Klassen) 826 case Element::ELEMENT_TYPE_DYNAMIC: 827 828 /*if ( $value->publisher->isSimplePreview() ) 829 break;*/ 830 831 $page->load(); 832 $macroName = $element->subtype; 833 $macroSettings = $element->getDynamicParameters(); 834 835 $runner = new MacroRunner(); 836 try { 837 $inhalt .= $runner->executeMacro( $macroName, $macroSettings,$page, $pageContext ); 838 } 839 catch( \Exception $e ) { 840 throw new GeneratorException("Macro '".$macroName."' could not executed",$e); 841 } 842 843 // Wenn HTML-Ausgabe, dann Sonderzeichen in HTML �bersetzen 844 if ( $this->isHtml( (new PageGenerator( $this->context->pageContext ))->getMimeType())) 845 $inhalt = Text::encodeHtmlSpecialChars( $inhalt ); 846 847 break; 848 849 850 // Info-Feld als Datum 851 case Element::ELEMENT_TYPE_INFODATE: 852 853 /*if ( $value->publisher->isSimplePreview() ) 854 break;*/ 855 856 switch( $element->subtype ) 857 { 858 case self::INFO_DATE_PUBLISHED: 859 // START_TIME wird zu Beginn im Controller gesetzt. 860 // So erh�lt jede Datei das gleiche Ver�ffentlichungsdatum. 861 $date = Startup::getStartTime(); 862 break; 863 864 case self::INFO_DATE_SAVED: 865 $date = $page->lastchangeDate; 866 break; 867 868 case self::INFO_DATE_CREATED: 869 $date = $page->createDate; 870 break; 871 872 default: 873 throw new PublisherException('element:'.$element->name.', '. 874 'type:'.$element->type.', '. 875 'unknown subtype:'.$element->subtype); 876 /*if ( !$value->publisher->isPublic() ) 877 $inhalt = \cms\base\Language::lang('ERROR_IN_ELEMENT');*/ 878 } 879 880 if ( strpos($element->dateformat,'%')!==FALSE ) 881 $inhalt = strftime( $element->dateformat,$date ); 882 else 883 $inhalt = date ( $element->dateformat,$date ); 884 885 $inhalt = $this->filterValue( $inhalt, $element->code ); 886 887 break; 888 889 890 // Info-Feld 891 case Element::ELEMENT_TYPE_INFO: 892 893 /*if ( $value->publisher->isSimplePreview() ) 894 break;*/ 895 896 switch( $element->subtype ) 897 { 898 case self::INFO_DB_ID: 899 $inhalt = DB::get()->id; 900 break; 901 case self::INFO_DB_NAME: 902 $inhalt = @DB::get()->getLabel(); 903 break; 904 case self::INFO_PROJECT_ID: 905 $inhalt = $page->projectid; 906 break; 907 case self::INFO_PROJECT_NAME: 908 $inhalt = Project::create( $page->projectid )->load()->name; 909 break; 910 case self::INFO_LANGUAGE_ID: 911 $inhalt = $pageContext->languageId; 912 break; 913 case self::INFO_LANGUAGE_ISO: 914 $language = new Language( $pageContext->languageId ); 915 $language->load(); 916 $inhalt = $language->isoCode; 917 break; 918 case self::INFO_LANGUAGE_NAME: 919 $language = new Language( $pageContext->languageId ); 920 $language->load(); 921 $inhalt = $language->name; 922 break; 923 case self::INFO_PAGE_ID: 924 $inhalt = $page->objectid; 925 break; 926 case self::INFO_PAGE_NAME: 927 $inhalt = $page->getNameForLanguage( $pageContext->languageId )->name; 928 break; 929 case self::INFO_PAGE_DESC: 930 $inhalt = $page->getNameForLanguage( $pageContext->languageId )->description; 931 break; 932 case self::INFO_PAGE_FULLFILENAME: 933 $inhalt = $this->getPublicFilename(); 934 break; 935 case self::INFO_PAGE_FILENAME: 936 $inhalt = $page->filename(); 937 break; 938 case self::INFO_PAGE_EXTENSION: 939 $inhalt = ''; 940 break; 941 case self::INFO_EDIT_URL: 942 $raw = true; 943 $inhalt = Html::locationUrl('page',$page->objectid ); 944 break; 945 case self::INFO_EDIT_FULLURL: 946 $raw = true; 947 $inhalt = Http::getServer(); 948 949 $inhalt .= Html::locationUrl('page',$page->objectid ); 950 break; 951 case self::INFO_LASTCHANGE_USER_USERNAME: 952 $user = $page->lastchangeUser; 953 if ( $user->userid ) 954 $user->load(); 955 $inhalt = $user->name; 956 break; 957 case self::INFO_LASTCHANGE_USER_FULLNAME: 958 $user = $page->lastchangeUser; 959 if ( $user->userid ) 960 $user->load(); 961 $inhalt = $user->fullname; 962 break; 963 case self::INFO_LASTCHANGE_USER_MAIL: 964 $user = $page->lastchangeUser; 965 if ( $user->userid ) 966 $user->load(); 967 $inhalt = $user->mail; 968 break; 969 case self::INFO_LASTCHANGE_USER_DESC: 970 $user = $page->lastchangeUser; 971 if ( $user->userid ) 972 $user->load(); 973 $inhalt = $user->desc; 974 break; 975 case self::INFO_LASTCHANGE_USER_TEL: 976 $user = $page->lastchangeUser; 977 if ( $user->userid ) 978 $user->load(); 979 $inhalt = $user->tel; 980 break; 981 982 case self::INFO_CREATION_USER_USERNAME: 983 $user = $page->createUser; 984 if ( $user->userid ) 985 $user->load(); 986 $inhalt = $user->name; 987 break; 988 case self::INFO_CREATION_FULLNAME: 989 $user = $page->createUser; 990 if ( $user->userid ) 991 $user->load(); 992 $inhalt = $user->fullname; 993 break; 994 case self::INFO_CREATION_MAIL: 995 $user = $page->createUser; 996 if ( $user->userid ) 997 $user->load(); 998 $inhalt = $user->mail; 999 break; 1000 case self::INFO_CREATION_DESC: 1001 $user = $page->createUser; 1002 if ( $user->userid ) 1003 $user->load(); 1004 $inhalt = $user->desc; 1005 break; 1006 case self::INFO_CREATION_TEL: 1007 $user = $page->createUser; 1008 if ( $user->userid ) 1009 $user->load(); 1010 $inhalt = $user->tel; 1011 break; 1012 1013 case self::INFO_ACT_USERNAME: 1014 $user = Request::getUser(); 1015 if ( $user ) 1016 $inhalt = $user->name; 1017 break; 1018 case self::INFO_ACT_FULLNAME: 1019 $user = Request::getUser(); 1020 if ( $user ) 1021 $inhalt = $user->fullname; 1022 break; 1023 case self::INFO_ACT_MAIL: 1024 $user = Request::getUser(); 1025 if ( $user ) 1026 $inhalt = $user->mail; 1027 break; 1028 case self::INFO_ACT_DESC: 1029 $user = Request::getUser(); 1030 if ( $user ) 1031 $inhalt = $user->desc; 1032 break; 1033 case self::INFO_ACT_TEL: 1034 $user = Request::getUser(); 1035 if ( $user ) 1036 $inhalt = $user->tel; 1037 break; 1038 default: 1039 Logger::warn('element:'.$element->name.', '. 1040 'type:'.$element->getTypeName().', '. 1041 'unknown subtype:'.$element->subtype); 1042 // Keine Fehlermeldung in erzeugte Seite schreiben. 1043 } 1044 1045 break; 1046 1047 case Element::ELEMENT_TYPE_COORD: 1048 $inhalt = $value->text; 1049 $inhalt = $this->filterValue( $inhalt, $element->code ); 1050 1051 break; 1052 1053 case Element::ELEMENT_TYPE_DATA: 1054 1055 try { 1056 $data = YAML::parse( $value->text ); 1057 } catch ( \Exception $e ) { 1058 if ( $this->context->pageContext->scheme == Producer::SCHEME_PREVIEW ) 1059 $inhalt = 'Invalid YAML: '.$e->getMessage(); 1060 break; 1061 } 1062 1063 $inhalt = $this->filterValue( new Data($data), $element->code ); 1064 1065 if ( is_array($inhalt) ) 1066 $inhalt = YAML::dump( $inhalt ); 1067 1068 break; 1069 default: 1070 // this should never happen in production. 1071 // inform the user. 1072 throw new GeneratorException( 'Error in element '.$element->name.': '. 1073 'unknown type: '.$element->typeid.''); 1074 1075 } 1076 1077 1078 switch( $element->typeid ) 1079 { 1080 case Element::ELEMENT_TYPE_LONGTEXT: 1081 case Element::ELEMENT_TYPE_TEXT: 1082 case Element::ELEMENT_TYPE_SELECT: 1083 1084 if ( Configuration::subset('publish')->is('encode_utf8_in_html') ) 1085 // Wenn HTML-Ausgabe, dann UTF-8-Zeichen als HTML-Code uebersetzen 1086 if ( $this->isHtml( (new PageGenerator( $this->context->pageContext ))->getMimeType()) ) 1087 $inhalt = Text::translateutf8tohtml($inhalt); 1088 break; 1089 1090 default: 1091 } 1092 1093 1094 1095 if ( $this->context->pageContext->scheme == Producer::SCHEME_PREVIEW && $element->withIcon && $this->isHtml( (new PageGenerator( $this->context->pageContext ))->getMimeType()) ) 1096 { 1097 // Anklickbaren Link voranstellen. 1098 $iconLink = '<a href="javascript:parent.Openrat.Workbench.openNewAction(\''.$element->name.'\',\'pageelement\',\''.$page->objectid.'_'.$element->elementid.'\');" title="'.$element->desc.'">&rarr;<i class="or-image-icon or-image-icon--el-'.$element->getTypeName().'"></i></a>'; 1099 $inhalt = $iconLink.$inhalt; 1100 } 1101 1102 return $inhalt; 1103 } 1104 1105 1106 /** 1107 * Determines if the value has meaningful content 1108 * 1109 * @param $value Value 1110 */ 1111 protected function isValueHasContent( $value,$element ) { 1112 1113 return in_array($element->typeid,[ 1114 Element::ELEMENT_TYPE_TEXT, 1115 Element::ELEMENT_TYPE_LONGTEXT, 1116 Element::ELEMENT_TYPE_SELECT, 1117 Element::ELEMENT_TYPE_DATA, 1118 ]) && $value->text != '' && $value->text != null || 1119 in_array($element->typeid,[ 1120 Element::ELEMENT_TYPE_COORD, 1121 Element::ELEMENT_TYPE_NUMBER 1122 ]) && $value->number != null || 1123 in_array($element->typeid,[ 1124 Element::ELEMENT_TYPE_LINK, 1125 Element::ELEMENT_TYPE_INSERT, 1126 ]) && $value->linkToObjectId != null && $value->linkToObjectId != 0 || 1127 in_array($element->typeid,[ 1128 Element::ELEMENT_TYPE_DATE, 1129 ]) && $value->date != null && $value->date != 0 || 1130 in_array($element->typeid,[ 1131 Element::ELEMENT_TYPE_CODE, 1132 Element::ELEMENT_TYPE_COPY, 1133 Element::ELEMENT_TYPE_DYNAMIC, 1134 Element::ELEMENT_TYPE_INFO, 1135 Element::ELEMENT_TYPE_INFODATE, 1136 Element::ELEMENT_TYPE_LINKDATE, 1137 Element::ELEMENT_TYPE_LINKINFO, 1138 ]); 1139 } 1140 1141 1142 /** 1143 * A pure value does not have a public filename. Therefor, this method returns nothing. 1144 * @return string 1145 */ 1146 public function getPublicFilename() 1147 { 1148 return null; 1149 } 1150 1151 1152 /** 1153 * @return string always blank 1154 */ 1155 public function getMimeType() 1156 { 1157 return ''; // Values does not have a mime type. 1158 } 1159 1160 1161 protected function isHtml( $mimeType ) 1162 { 1163 return $mimeType == 'text/html'; 1164 } 1165 1166 /** 1167 * @param $inhalt mixed 1168 * @param $code string 1169 * @return mixed|string 1170 */ 1171 protected function filterValue( $inhalt, $code) 1172 { 1173 $executor = new CMSDslInterpreter(); 1174 1175 $executor->setPageContext( $this->context->pageContext ); 1176 $executor->setValue( $inhalt ); 1177 1178 try { 1179 $executor->runCode( $code ); 1180 $result = $executor->getOutput(); 1181 } 1182 catch( DslException $e ) { 1183 Logger::info($e); 1184 throw new GeneratorException('Script error in filter'."\n".Text::makeLineNumbers($code),$e); 1185 } 1186 1187 if ( $result != null ) 1188 return $result; 1189 else 1190 return $inhalt; 1191 } 1192 1193 /** 1194 * @param $pageContext PageContext 1195 * @param $element Element 1196 * @param $oid integer 1197 * @return string 1198 */ 1199 protected function generatePageValue($pageContext, $element, $oid ) { 1200 1201 $o = new BaseObject( $oid ); 1202 $o->load(); 1203 1204 switch( $o->typeid ) 1205 { 1206 case BaseObject::TYPEID_FOLDER: 1207 $f = new Folder( $oid ); 1208 $value = ''; 1209 foreach( $f->getObjectIds() as $childOid ) { 1210 $value .= $this->generatePageValue( $pageContext,$element,$childOid ); 1211 } 1212 return $value; 1213 1214 case BaseObject::TYPEID_PAGE: 1215 1216 $subtype = $element->subtype; 1217 if ( $pageContext->scheme == Producer::SCHEME_PREVIEW ) 1218 $subtype = null; // In preview the SSI/ESI are not available. 1219 1220 switch( $subtype ) 1221 { 1222 case ValueGenerator::INSERT_INLINE: 1223 default: 1224 1225 $newPageContext = clone $pageContext; 1226 $newPageContext->objectId = $oid; 1227 $pageGenerator = new PageGenerator( $newPageContext ); 1228 1229 return $pageGenerator->getCache()->get(); 1230 1231 case ValueGenerator::INSERT_SSI: 1232 $linkScheme = $pageContext->getLinkScheme(); 1233 return '<!--#include virtual="'.$linkScheme->linkToObject( new BaseObject($pageContext->sourceObjectId),(new BaseObject($oid))->load()).'" -->'; 1234 1235 case ValueGenerator::INSERT_ESI: 1236 $linkScheme = $pageContext->getLinkScheme(); 1237 return '<esi:include src="'.$linkScheme->linkToObject( new BaseObject($pageContext->sourceObjectId),(new BaseObject($oid))->load()).'"/>'; 1238 } 1239 1240 case BaseObject::TYPEID_LINK: 1241 $l = new Link( $oid ); 1242 $l->load(); 1243 1244 return $this->generatePageValue( $pageContext,$element,$l->linkedObjectId ); 1245 default: 1246 return ''; 1247 } 1248 1249 } 1250 1251 }
Download modules/cms/generator/ValueGenerator.class.php
History Wed, 17 Apr 2024 00:34:07 +0200 Jan Dankert New: Inputfields for coordinates; coordinates are stored in the now 64bit-number-field of the value. Fri, 17 Feb 2023 02:02:18 +0100 Jan Dankert Refactoring: Script-context should be the same in all environments; New: DslPdf for creating PDF with scriptbox ;) Sat, 28 Jan 2023 20:02:35 +0100 Jan Dankert Fix: Always throw an exception if the scriptbox fails. Sat, 28 Jan 2023 19:10:47 +0100 Jan Dankert New: Templates may be rendered as Mustache, Script and Script template. Fri, 1 Jul 2022 23:28:42 +0200 Jan Dankert Fix: Correct Filterung of links. Fri, 1 Jul 2022 19:30:30 +0200 Jan Dankert New: Data Object for accessing data trees Mon, 27 Jun 2022 01:11:02 +0200 Jan Dankert New: Secure Flag for Script Interpreter which is enabled by default. Mon, 27 Jun 2022 00:40:42 +0200 Jan Dankert New: Marker interface 'Scriptable', Proxy class for MQTT, help() method in Scripts. Sun, 26 Jun 2022 12:51:07 +0200 Jan Dankert New: DSL can be controlled by flags; support for error messages; support for negativ numbers. Sat, 25 Jun 2022 14:26:33 +0200 Jan Dankert New: Many Enhancements for the internal script language: More access to the data structure of pages, folders, templates, ... Tue, 14 Jun 2022 23:41:16 +0200 Jan Dankert Fix: A method is really better here... Tue, 14 Jun 2022 23:31:49 +0200 Jan Dankert Fix: Do not declare function twice. Maybe a method would be better here... Tue, 14 Jun 2022 01:11:09 +0200 Jan Dankert New: Support for ESI templates; some bugfixes while generating the 'insert' element type. Sun, 12 Jun 2022 05:27:30 +0200 Jan Dankert New: MQTT support in DSL. Sun, 5 Jun 2022 22:14:24 +0200 Jan Dankert Some fixups: New Icons; better support classes for DSL. Thu, 2 Jun 2022 01:50:05 +0200 Jan Dankert Refactoring: DSL Interpreter is now using a write buffer Thu, 2 Jun 2022 01:04:54 +0200 Jan Dankert New: Element type "checkbox" Wed, 1 Jun 2022 01:05:34 +0200 Jan Dankert New: Element types for "coordinates" and "data" Wed, 1 Jun 2022 00:11:40 +0200 Jan Dankert New: DSL as a filter for number values Tue, 31 May 2022 00:32:27 +0200 Jan Dankert New: More context objects for the DSL Sun, 29 May 2022 01:13:27 +0200 Jan Dankert New: DSL with support for functions Sat, 28 May 2022 18:00:13 +0200 Jan Dankert New: DSL with a much better syntax parsing and support for assignments, conditions, ... Thu, 26 May 2022 10:14:42 +0200 Jan Dankert New: Catch Exception from DSLInterpreter. Wed, 25 May 2022 22:47:17 +0200 Jan Dankert New: DSL (domain specific language) for code elements. The old way with PHP code ist not sandboxed and unsecure. This approach is a minimalistic, javascript-like, scripting engine. For now only simple function calls are possible, for example: alert("example"); Fri, 15 Apr 2022 14:51:22 +0200 dankert Refactoring: User,Config and Database info is now stored in the Request, because so there is no session required for clients which are using Basic Authorization. Fri, 11 Mar 2022 12:00:23 +0100 dankert Fix: Typo in PageContext. Sun, 13 Feb 2022 19:39:49 +0100 dankert Refactoring: Special output type "preview" for previewing pages and files. Sun, 5 Dec 2021 20:33:24 +0100 dankert Cleanup: Removed unusable properties from class 'Value' and 'BaseObject'. Sun, 5 Dec 2021 15:33:29 +0100 dankert Cleanup: Removed unusable properties from class 'Value'. Tue, 9 Nov 2021 23:52:56 +0100 Jan Dankert Some fixes for reading content from the new content table. Tue, 9 Nov 2021 00:35:42 +0100 Jan Dankert Fixes: Reading and writing template sources with the new content table. Sun, 14 Mar 2021 02:14:31 +0100 Jan Dankert Fix: The public filename of files must contain their path... Sun, 14 Mar 2021 01:33:16 +0100 Jan Dankert Fix: Transformer should not throw an exception if any linktarget could not be found. Fix: SearchIndex must use the correct pageContext. Thu, 4 Mar 2021 03:39:25 +0100 Jan Dankert New: Separate edit action for images and texts. Thu, 4 Mar 2021 02:24:45 +0100 Jan Dankert New: The calculation of the mime types should be done in the generators. Sat, 27 Feb 2021 02:40:09 +0100 Jan Dankert Fix: Use the sourceObjectId from the pageContext for links. Sat, 27 Feb 2021 02:10:16 +0100 Jan Dankert Fix: Using the correct object-id for generating the page. Thu, 25 Feb 2021 01:22:10 +0100 Jan Dankert New: Edit all page elements in 1 view. Tue, 23 Feb 2021 22:59:12 +0100 Jan Dankert New: Use a default value from a linked page. Mon, 30 Nov 2020 09:57:36 +0100 Jan Dankert Fix: aborting transaction before changing the database connection; Refactoring: Cleanup databases Thu, 19 Nov 2020 14:53:31 +0100 Jan Dankert Using warn() instead of error() Sun, 1 Nov 2020 03:08:55 +0100 Jan Dankert Replaced the calls to "Configuration::rawConfig()" with the OO style calls; Cleanup LoginAction. Wed, 7 Oct 2020 23:28:20 +0200 Jan Dankert Fix: Langauge keys must not contain the '-'. Sat, 26 Sep 2020 13:11:23 +0200 Jan Dankert Refactoring: No global variables any more. All constants are capsulated by classes. Sat, 26 Sep 2020 12:20:43 +0200 Jan Dankert Refactoring: No global variables like $SESS any more. All constants are capsulated by classes. Sat, 26 Sep 2020 10:32:02 +0200 Jan Dankert Refactoring: No global $conf array any more. Sat, 26 Sep 2020 04:26:55 +0200 Jan Dankert Refactoring: read configuration values with a class. Sat, 26 Sep 2020 04:03:53 +0200 Jan Dankert Refactoring: read language keys with a class. Sat, 26 Sep 2020 02:26:39 +0200 Jan Dankert Refactoring: No global functions any more, the database object is read from the Db class. Wed, 23 Sep 2020 01:04:05 +0200 Jan Dankert Cleanup of deprecated methods and deprecated class attributes. Mon, 21 Sep 2020 23:44:23 +0200 Jan Dankert Fixing editing of values. Mon, 21 Sep 2020 22:48:59 +0200 Jan Dankert Complexe refactoring: Moving all generation logic from the model (Value,Page,File) to generators classes.