File modules/cms/action/PageelementAction.class.php
Last commit: Wed Oct 14 01:41:42 2026 +0200 Jan Dankert Saving values with the new object-oriented ui objects.
1 <?php 2 3 namespace cms\action; 4 5 use cms\base\Language as L; 6 use cms\generator\PageContext; 7 use cms\generator\PageGenerator; 8 use cms\generator\Producer; 9 use cms\generator\Publisher; 10 use cms\generator\PublishOrder; 11 use cms\generator\ValueContext; 12 use cms\generator\ValueGenerator; 13 use cms\model\Content; 14 use cms\model\PageContent; 15 use cms\model\Permission; 16 use cms\model\BaseObject; 17 use cms\model\Element; 18 use cms\model\Folder; 19 use cms\model\Page; 20 use cms\model\Pageelement; 21 use cms\model\Project; 22 use cms\model\Template; 23 use cms\model\User; 24 use cms\model\Value; 25 use language\Messages; 26 use LogicException; 27 use util\ArrayUtils; 28 use util\Coordinates; 29 use util\exception\ClientException; 30 use util\exception\ObjectNotFoundException; 31 use util\exception\PublisherException; 32 use util\exception\SecurityException; 33 use util\exception\ValidationException; 34 use util\Html; 35 use util\Session; 36 use util\Text; 37 use util\Transformer; 38 39 // OpenRat Content Management System 40 // Copyright (C) 2002-2012 Jan Dankert, cms@jandankert.de 41 // 42 // This program is free software; you can redistribute it and/or 43 // modify it under the terms of the GNU General Public License 44 // as published by the Free Software Foundation; either version 2 45 // of the License, or (at your option) any later version. 46 // 47 // This program is distributed in the hope that it will be useful, 48 // but WITHOUT ANY WARRANTY; without even the implied warranty of 49 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 50 // GNU General Public License for more details. 51 // 52 // You should have received a copy of the GNU General Public License 53 // along with this program; if not, write to the Free Software 54 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 55 56 57 /** 58 * Action-Klasse zum Bearbeiten eines Seitenelementes 59 * @author $Author$ 60 * @version $Revision$ 61 * @package openrat.actions 62 */ 63 class PageelementAction extends BaseAction 64 { 65 /** 66 * Enthaelt das Seitenobjekt 67 * @type Page 68 */ 69 protected $page; 70 71 /** 72 * Enthaelt das Elementobjekt 73 * @type Element 74 */ 75 protected $element; 76 77 78 /** 79 * @type PageContent 80 */ 81 protected $pageContent; 82 83 84 85 /** 86 * Enth�lt den Inhalt 87 * 88 * @var Value 89 */ 90 var $value; 91 protected int|null $elementid; 92 93 94 /** 95 * Konstruktor 96 */ 97 function __construct() 98 { 99 parent::__construct(); 100 } 101 102 103 public function init() 104 { 105 106 $this->value = new Value(); 107 108 $id = $this->request->getRequiredText(RequestParams::PARAM_ID ); 109 $ids = explode('_',$id); 110 if ( count($ids) > 1 ) 111 { 112 list( $pageid, $elementid ) = $ids; 113 } 114 else 115 { 116 $pageid = $this->request->getId(); 117 $elementid = $this->request->getRequiredNumber('elementid'); 118 } 119 120 $this->page = new Page( $pageid ); 121 $this->page->load(); 122 123 if ( ! $this->page->isPersistent() ) 124 throw new ObjectNotFoundException("page not found"); 125 126 if ( $elementid != 0 ) 127 { 128 $this->elementid = $elementid; 129 $this->element = new Element( $elementid ); 130 } 131 132 if ( $languageId = $this->request->getLanguageId() ) { 133 134 $this->pageContent = new PageContent(); 135 $this->pageContent->pageId = $this->page->pageid; 136 $this->pageContent->elementId = $this->element->elementid; 137 $this->pageContent->languageid = $languageId; 138 $this->pageContent->load(); 139 } 140 141 $this->element->load(); 142 143 if ( $this->element->templateid != $this->page->templateid ) 144 throw new ClientException("Invalid combination of element ".$this->element->__toString()." and page ".$this->page->__toString()); 145 } 146 147 148 149 protected function createValueContext( $scheme ) { 150 151 $pageContext = new PageContext( $this->page->objectid,$scheme ); 152 153 if ( $languageId = $this->request->getLanguageId()) 154 $pageContext->languageId = $languageId; 155 156 if ( $modelId = $this->request->getModelId()) 157 $pageContext->modelId = $modelId; 158 159 if ( !$pageContext->languageId ) 160 $pageContext->languageId = $this->page->getProject()->getDefaultLanguageId(); 161 162 if ( !$pageContext->modelId ) 163 $pageContext->modelId = $this->page->getProject()->getDefaultModelId(); 164 165 $valueContext = new ValueContext( $pageContext ); 166 $valueContext->elementid = $this->element->elementid; 167 168 return $valueContext; 169 } 170 171 172 173 /** 174 * Verkn�pfung bearbeiten. 175 * 176 */ 177 protected function editLink() 178 { 179 $project = new Project($this->page->projectid); 180 $this->setTemplateVar('rootfolderid',$project->getRootObjectId() ); 181 182 // Ermitteln, welche Objekttypen verlinkt werden d�rfen. 183 $type = $this->element->subtype; 184 185 if ( substr($type,0,5) == 'image' ) 186 $type = 'file'; 187 188 if ( !in_array($type,array('file','page','link','folder')) ) 189 $types = array('file','page','link'); // Fallback: Der Link kann auf Seiten,Dateien und Verknüpfungen zeigen 190 else 191 $types = array($type); // gewünschten Typ verwenden 192 193 $oid = $this->value->linkToObjectId; 194 $name = ''; 195 196 if ( $oid ) { 197 $o = new BaseObject($oid); 198 $o->load(); 199 $name = $o->filename; 200 } 201 202 $this->setTemplateVar('objects' ,array() ); 203 $this->setTemplateVar('linkobjectid',$oid ); 204 $this->setTemplateVar('linkname' ,$name); 205 206 $this->setTemplateVar('types',implode(',',$types)); 207 } 208 209 210 /** 211 * Auswahlbox. 212 * 213 */ 214 protected function editSelect() 215 { 216 $this->setTemplateVar( 'items',$this->element->getSelectItems() ); 217 $this->setTemplateVar( 'text' ,$this->value->text ); 218 219 } 220 221 222 223 /** 224 * Einf�gen-Element. 225 * 226 */ 227 protected function editList() 228 { 229 $this->editInsert(); 230 } 231 232 233 234 /** 235 * Einf�gen-Element. 236 * 237 */ 238 protected function editInsert() 239 { 240 // Auswahl ueber alle Elementtypen 241 $objects = array(); 242 //Änderung der möglichen Types 243 $types = array('file','page','link'); 244 $objects[ 0 ] = \cms\base\Language::lang('LIST_ENTRY_EMPTY'); // Wert "nicht ausgewählt" 245 246 $project = new Project( $this->page->projectid ); 247 $folder = new Folder($project->getRootObjectId()); 248 $folder->load(); 249 250 //Auch Dateien dazu 251 foreach( $project->getAllObjectIds($types) as $id ) 252 { 253 $f = new Folder( $id ); 254 $f->load(); 255 256 $objects[ $id ] = \cms\base\Language::lang( $f->getType() ).': '; 257 $objects[ $id ] .= implode( ' » ',$f->parentObjectNames(false,true) ); 258 } 259 260 foreach( $project->getAllFolders() as $id ) 261 { 262 $f = new Folder( $id ); 263 $f->load(); 264 265 $objects[ $id ] = \cms\base\Language::lang( $f->getType() ).': '; 266 $objects[ $id ] .= implode( ' » ',$f->parentObjectNames(false,true) ); 267 } 268 269 asort( $objects ); // Sortieren 270 271 $this->setTemplateVar('objects' ,$objects); 272 $this->setTemplateVar('linkobjectid',$this->value->linkToObjectId); 273 274 } 275 276 277 278 /** 279 * Zahl bearbeiten. 280 * 281 */ 282 protected function editNumber() 283 { 284 $this->setTemplateVar('number',$this->value->number / pow(10,$this->element->decimals) ); 285 } 286 287 288 /** 289 * Date. 290 * 291 */ 292 protected function editDate() 293 { 294 $this->setTemplateVar('date',date('Y-m-d',$this->value->date )); 295 $this->setTemplateVar('time',date('H:i' ,$this->value->date )); 296 } 297 298 299 /** 300 * Ein Element der Seite bearbeiten 301 * 302 * Es wird ein Formular erzeugt, mit dem der Benutzer den Inhalt bearbeiten kann. 303 */ 304 protected function editLongtext() 305 { 306 if ( ($f = $this->request->getNumber('format')) !== null ) // beware: format may be 0, which is false 307 // Individual format from request. 308 $format = $f; 309 elseif ( $this->value->format != null ) 310 $format = $this->value->format; 311 else 312 // There is no saved value. Get the format from the template element. 313 $format = $this->element->format; 314 315 $this->setTemplateVar('format' ,$format ); 316 317 $this->setTemplateVar( 'editor',Element::getAvailableFormats()[ $format ] ); 318 319 $this->setTemplateVar( 'text',$this->linkifyOIDs( $this->value->text ) ); 320 } 321 322 323 protected function editData() { 324 $this->editText(); 325 } 326 327 protected function editCoord() { 328 $this->setTemplateVar('lat' ,$this->value->number >> 32 ); 329 $this->setTemplateVar('long',$this->value->number << 32 >> 32); 330 } 331 332 333 /** 334 * Ein Element der Seite bearbeiten 335 * 336 * Es wird ein Formular erzeugt, mit dem der Benutzer den Inhalt bearbeiten kann. 337 */ 338 protected function editText() 339 { 340 $this->setTemplateVar( 'text',$this->value->text ); 341 } 342 343 protected function editCheckbox() 344 { 345 $this->setTemplateVar( 'number',$this->value->number ); 346 } 347 348 protected function saveData() 349 { 350 $this->saveText(); 351 } 352 353 protected function saveCoord() 354 { 355 $value = new Value(); 356 $value->contentid = $this->pageContent->contentId; 357 358 if ( $linkTo = $this->request->getNumber('linkobjectid') ) 359 $value->linkToObjectId = $linkTo; 360 else { 361 $value->number = $this->request->getFloat('lat') << 32 | $this->request->getFloat('long'); 362 } 363 364 $this->afterSave($value); 365 } 366 367 /** 368 * Element speichern 369 * 370 * Der Inhalt eines Elementes wird abgespeichert 371 */ 372 protected function saveText() 373 { 374 $value = new Value(); 375 $value->contentid = $this->pageContent->contentId; 376 $value->load(); 377 378 if ( $linkObjectId = $this->request->getNumber('linkobjectid') ) 379 $value->linkToObjectId = $linkObjectId; 380 else 381 $value->text = $this->request->getRaw('text'); 382 383 $this->afterSave($value); 384 } 385 386 387 388 /** 389 * Nach dem Speichern weitere Dinge ausfuehren.<br> 390 * - Inhalt freigeben<br> 391 * - Seite veroeffentlichen<br> 392 * - Inhalt fuer andere Sprachen speichern<br> 393 * - Hinweis ueber erfolgtes Speichern ausgeben<br> 394 * <br> 395 * Nicht zu verwechseln mit <i>Aftershave</i> :) 396 * @param $value Value 397 * @throws \util\exception\ObjectNotFoundException 398 */ 399 protected function afterSave( $value ) 400 { 401 // Inhalt sofort freigegeben, wenn 402 // - Recht vorhanden 403 // - Freigabe gewuenscht 404 $value->publish = $this->page->hasRight( Permission::ACL_RELEASE ) && $this->request->isTrue('release'); 405 406 // Up-To-Date-Check 407 $content = new Content( $this->pageContent->contentId ); 408 $lastChangeTime = $content->getLastChangeSinceByAnotherUser( $this->request->getText('value_time'), $this->getCurrentUserId() ); 409 410 if ( $lastChangeTime ) 411 $this->addWarningFor( $this->value,Messages::CONCURRENT_VALUE_CHANGE, array('last_change_time'=>date(L::lang('DATE_FORMAT'),$lastChangeTime))); 412 413 // Inhalt speichern 414 $value->persist(); 415 416 // Wenn Inhalt in allen Sprachen gleich ist, dann wird der Inhalt 417 // fuer jede Sprache einzeln gespeichert. 418 if ( $this->element->allLanguages ) 419 { 420 $project = new Project( $this->page->projectid ); 421 foreach( $project->getLanguageIds() as $languageid ) 422 { 423 if ( $languageid != $this->pageContent->languageid ) { 424 $otherPageContent = clone $this->pageContent; 425 $otherPageContent->languageid = $languageid; 426 $otherPageContent->contentId = null; 427 $otherPageContent->load(); 428 if ( ! $otherPageContent->contentId ) 429 $otherPageContent->persist(); // create pagecontent if it does not exist. 430 431 $otherValue = clone $value; 432 $otherValue->contentid = $otherPageContent->contentId; 433 $otherValue->persist(); 434 } 435 } 436 } 437 438 $this->addNoticeFor( $this->page, Messages::SAVED); 439 440 $this->page->setTimestamp(); // "Letzte Aenderung" setzen 441 442 // Falls ausgewaehlt die Seite sofort veroeffentlichen 443 if ( $this->page->hasRight( Permission::ACL_PUBLISH ) && $this->request->isTrue('publish') ) 444 { 445 $this->publishPage(); 446 } 447 } 448 449 450 /** 451 * Element speichern 452 * 453 * Der Inhalt eines Elementes wird abgespeichert 454 */ 455 protected function saveLongtext() 456 { 457 $value = new Value(); 458 $value->contentid = $this->pageContent->contentId; 459 $value->load(); 460 461 if ( is_numeric($format = $this->request->getNumber('format')) ) 462 $value->format = $format; 463 else 464 // Fallback: Format of the element. 465 $value->format = $this->element->format; 466 467 $value->text = $this->compactOIDs( $this->request->getRaw('text') ); 468 469 $this->afterSave($value); 470 } 471 472 473 /** 474 * Element speichern 475 * 476 * Der Inhalt eines Elementes wird abgespeichert 477 */ 478 protected function saveDate() 479 { 480 $value = new Value(); 481 $value->contentid = $this->pageContent->contentId; 482 483 if ( $linkTo = $this->request->getNumber('linkobjectid') ) 484 $value->linkToObjectId = $linkTo; 485 else { 486 $value->date = strtotime( $this->request->getText( 'date' ).' '.$this->request->getText( 'time' ) ); 487 488 } 489 490 $this->afterSave($value); 491 } 492 493 494 495 /** 496 * Element speichern 497 * 498 * Der Inhalt eines Elementes wird abgespeichert 499 */ 500 protected function saveSelect() 501 { 502 $value = new Value(); 503 $value->contentid = $this->pageContent->contentId; 504 $value->load(); 505 506 $value->text = $this->request->getRequiredText('text'); 507 508 $this->afterSave($value); 509 } 510 511 512 513 /** 514 * Element speichern 515 * 516 * Der Inhalt eines Elementes wird abgespeichert 517 */ 518 protected function saveLink() 519 { 520 $value = new Value(); 521 $value->contentid = $this->pageContent->contentId; 522 523 $value->load(); 524 525 if ( $linkUrl = $this->request->getText('linkurl') ) 526 $value->linkToObjectId = $this->parseSimpleOID($linkUrl); 527 else 528 $value->linkToObjectId = $this->request->getNumber('linkobjectid'); 529 530 $this->afterSave($value); 531 } 532 533 534 535 /** 536 * Element speichern 537 * 538 * Der Inhalt eines Elementes wird abgespeichert 539 */ 540 protected function saveList() 541 { 542 $this->saveInsert(); 543 } 544 545 546 547 /** 548 * Element speichern 549 * 550 * Der Inhalt eines Elementes wird abgespeichert 551 */ 552 protected function saveInsert() 553 { 554 $value = new Value(); 555 $value->contentid = $this->pageContent->contentId; 556 $value->load(); 557 558 $value->linkToObjectId = intval($this->request->getText('linkobjectid')); 559 560 $this->afterSave($value); 561 } 562 563 564 565 protected function saveCheckbox() 566 { 567 $this->saveNumber(); 568 } 569 570 /** 571 * Element speichern 572 * 573 * Der Inhalt eines Elementes wird abgespeichert 574 */ 575 protected function saveNumber() 576 { 577 $value = new Value(); 578 $value->contentid = $this->pageContent->contentId; 579 580 581 if ( $linkTo = $this->request->getText('linkobjectid') ) 582 $value->linkToObjectId = $linkTo; 583 else 584 $value->number = $this->request->getText('number') * pow(10,$this->element->decimals); 585 586 $this->afterSave($value); 587 } 588 589 590 591 protected function linkifyOIDs( $text ) 592 { 593 $pageContext = new PageContext( $this->page->objectid, Producer::SCHEME_PREVIEW ); 594 $pageContext->modelId = 0; 595 $pageContext->languageId = $this->request->getNumber('languageid'); 596 597 $linkFormat = $pageContext->getLinkScheme(); 598 599 foreach( Text::parseOID($text) as $oid=>$t ) 600 { 601 $url = $linkFormat->linkToObject($this->page, (new BaseObject($oid))->load() ); 602 foreach( $t as $match) 603 $text = str_replace($match,$url,$text); 604 } 605 606 return $text; 607 } 608 609 610 protected function compactOIDs( $text ) 611 { 612 foreach( Text::parseOID($text) as $oid=>$t ) 613 { 614 foreach( $t as $match) 615 $text = str_replace($match,'?__OID__'.$oid.'__',$text); 616 } 617 618 return $text; 619 } 620 621 622 /** 623 * Gets the Object-Id from an string. 624 * 625 * @param $text 626 * @return int 627 */ 628 protected function parseSimpleOID($text ) 629 { 630 $treffer = Text::parseOID( $text ); 631 632 if ( isset($treffer[0])) 633 // Found an Object-Id. 634 return $treffer[0][0]; 635 else 636 return intval($text); 637 } 638 639 640 protected function publishPage() { 641 642 $project = $this->page->getProject(); 643 644 // Nothing is written to the session from this point. so we should free the session. 645 Session::close(); 646 647 $publisher = new Publisher( $project->projectid ); 648 649 foreach( $project->getModelIds() as $modelId ) { 650 651 652 foreach( $project->getLanguageIds() as $languageId ) { 653 654 $pageContext = new PageContext($this->page->objectid, Producer::SCHEME_PUBLIC); 655 $pageContext->modelId = $modelId; 656 $pageContext->languageId = $languageId; 657 658 $pageGenerator = new PageGenerator($pageContext); 659 660 $publisher->addOrderForPublishing(new PublishOrder($pageGenerator->getCache()->load()->getFilename(), $pageGenerator->getPublicFilename(), $this->page->lastchangeDate)); 661 $this->page->setPublishedTimestamp(); 662 } 663 } 664 665 try { 666 $publisher->publish(); 667 668 $this->addNoticeFor( $this->value,Messages::PUBLISHED,[], 669 implode("\n",$publisher->getDestinationFilenames() ) ); 670 671 } catch( PublisherException $e ) { 672 $this->addErrorFor( $this->value,Messages::PUBLISHED_ERROR,[],$e->getMessage() ); 673 } 674 675 } 676 677 678 679 /** 680 * Textual representation of a value. 681 * 682 * @param Value $value 683 * @param int $elementTypeId 684 * @return string 685 */ 686 protected function calculateValue(Value $value, $elementTypeId = 0) 687 { 688 switch( $elementTypeId ) { 689 case Element::ELEMENT_TYPE_DATETIME: 690 case Element::ELEMENT_TYPE_DATE: 691 case Element::ELEMENT_TYPE_WEEK: 692 case Element::ELEMENT_TYPE_MONTH: 693 if ( ! $value->date ) 694 return ''; 695 696 return date( \cms\base\Language::lang(Messages::DATE_FORMAT), $value->date ); 697 698 case Element::ELEMENT_TYPE_TEXT: 699 case Element::ELEMENT_TYPE_LONGTEXT: 700 case Element::ELEMENT_TYPE_SELECT: 701 case Element::ELEMENT_TYPE_SELECTS: 702 case Element::ELEMENT_TYPE_URL: 703 case Element::ELEMENT_TYPE_TEL: 704 case Element::ELEMENT_TYPE_COLOR: 705 case Element::ELEMENT_TYPE_TIME: 706 707 return $value->text; 708 709 case Element::ELEMENT_TYPE_LINK: 710 711 if ( ! $value->linkToObjectId ) 712 return ''; 713 714 $linkObject = new BaseObject( $value->linkToObjectId ); 715 $linkObject->load(); 716 $name = $linkObject->filename(); 717 718 return $name; 719 720 case Element::ELEMENT_TYPE_NUMBER: 721 return $value->number; 722 723 case Element::ELEMENT_TYPE_CHECKBOX: 724 return $value->number?'ON':'OFF'; 725 726 case Element::ELEMENT_TYPE_COORD: 727 $lat = $value->number >>32; 728 $long = $value->number <<32 >>32; 729 $coordinates = new Coordinates( $lat,$long ); 730 return $coordinates->format( Coordinates::FORMAT_WGS84_DEGREES); 731 732 default: 733 return ''; 734 } 735 } 736 737 738 /** 739 * User must have read rights to the page. 740 */ 741 public function checkAccess() { 742 if ( ! $this->page->hasRight( Permission::ACL_READ ) ) 743 throw new SecurityException(); 744 } 745 746 747 /** 748 * Get page contents. 749 * 750 * @return PageContent[] array of pagecontents of the page 751 * @throws ObjectNotFoundException 752 */ 753 protected function getContents() 754 { 755 $this->page->load(); 756 $this->element->load(); 757 758 return ArrayUtils::mapToNewArray( 759 $this->page->getProject()->getLanguages(), 760 function ( $languageId, $languageName ) { 761 $pageContent = new PageContent(); 762 $pageContent->languageid = $languageId; 763 $pageContent->elementId = $this->element->elementid; 764 $pageContent->pageId = $this->page->pageid; 765 $pageContent->load(); 766 return [ $pageContent->contentId => new Content( $pageContent->contentId ) ]; 767 } 768 ); 769 } 770 771 772 773 774 protected function ensureValueIdIsInAnyContent( $valueId ) 775 { 776 foreach ($this->getContents() as $content ) { 777 if ( in_array( $valueId,$content->getVersionList() ) ) 778 return; 779 } 780 781 throw new SecurityException('valueId is not valid in this context'); 782 } 783 784 protected function ensureContentIdIsPartOfPage( $contentId ) 785 { 786 if ( ! in_array( $contentId, array_keys($this->getContents()) ) ) 787 throw new SecurityException('content '.$contentId.' is not part of page #'.$this->page->objectid.' with contents '.print_r($this->getContents(),true) ); 788 } 789 790 }
Downloadmodules/cms/action/PageelementAction.class.php
History Wed, 14 Oct 2026 01:41:42 +0200 Jan Dankert Saving values with the new object-oriented ui objects. Tue, 13 Oct 2026 18:49:59 +0200 Jan Dankert New: Another action which returns an object instead of single output values. This should be the future, but it's a long way to refactore all old action methods... Tue, 14 Jan 2025 01:57:22 +0100 Jan Dankert New: Some new template element types like 'url','email','range','password','date','time', ...; New: datalists for input fields; Refactoring: Cleaner templates and actions for editing values; Mon, 22 Apr 2024 22:29:49 +0200 Jan Dankert Editing coordinates now possible. 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. Wed, 15 Feb 2023 00:33:05 +0100 Jan Dankert Fix: "format" is a numeric value. Wed, 15 Feb 2023 00:22:28 +0100 Jan Dankert Fix: Changing the Longtext format was not possible. Mon, 27 Jun 2022 02:54:38 +0200 Jan Dankert Fix: Editing of dates was broken, do not know why the code was missing up to now... Mon, 27 Jun 2022 02:22:50 +0200 Jan Dankert Fix: Saving links in PageallAction and PageelementAllAction. 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" Fri, 11 Mar 2022 12:26:33 +0100 dankert Fix: Catch error if something happens while publishing. Fri, 11 Mar 2022 10:41:42 +0100 dankert Fix: Typo Wed, 9 Mar 2022 13:28:52 +0100 dankert Refactoring: Checkbox values are always sent to the server. In the actions we must test the value with 'isTrue()' Sun, 5 Dec 2021 22:09:08 +0100 dankert Fix: The Diff function was broken. 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'. Sat, 27 Nov 2021 23:31:32 +0100 Jan Dankert Fix: Saving values for unauthenticated users. Sat, 27 Nov 2021 01:52:24 +0100 Jan Dankert New: Releasing and Restoring for file and template values. Sat, 27 Nov 2021 00:11:56 +0100 Jan Dankert New: History for files and templates. 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. Fri, 2 Apr 2021 00:18:39 +0200 Jan Dankert New: Translation for element formats. Sun, 14 Mar 2021 22:29:56 +0100 Jan Dankert Refactoring: Clearer access check. Sat, 6 Mar 2021 03:42:38 +0100 Jan Dankert New: Better permission checks. Sat, 27 Feb 2021 01:07:14 +0100 Jan Dankert Fix: Request-Id may contain '_'. Sat, 27 Feb 2021 00:29:39 +0100 Jan Dankert New: Set publishing date on publishing. Sat, 27 Feb 2021 00:09:56 +0100 Jan Dankert Fix: The id of PageelementAction is not a number. Fri, 26 Feb 2021 01:06:01 +0100 Jan Dankert Refactoring accessing the request parameter values. Mon, 4 Jan 2021 19:03:18 +0100 Jan Dankert Refactoring: ACL class is renamed to Permission, because most RBAC/DMAC concepts are calling it a permission. Thu, 19 Nov 2020 14:49:58 +0100 Jan Dankert Fix: Action::addNotice() is replaced by Action::addNoticeFor() Wed, 18 Nov 2020 01:46:36 +0100 Jan Dankert Refactoring of model classes: New method persist() and some other cleanups. Wed, 18 Nov 2020 00:18:10 +0100 Jan Dankert Refactoring Part 2: Removing all unnecessary methods in the action base classes. Tue, 17 Nov 2020 23:51:00 +0100 Jan Dankert Refactoring: Every Actionmethod has now its own class. Sat, 14 Nov 2020 22:02:21 +0100 Jan Dankert Fixed: Notices may display a message. Fri, 13 Nov 2020 23:24:54 +0100 Jan Dankert Using icons for the history view, this is much cleaner. Fri, 13 Nov 2020 21:27:57 +0100 Jan Dankert Clearer code for text diff, cleaned up the view. Fri, 13 Nov 2020 00:12:44 +0100 Jan Dankert Fixing Pagelement-History and Diff. Sat, 31 Oct 2020 13:54:19 +0100 Jan Dankert Cleanup: Use constants for session keys. Wed, 21 Oct 2020 23:32:47 +0200 Jan Dankert Load the objects before using attributes. Wed, 14 Oct 2020 23:49:54 +0200 Jan Dankert Refactoring: Creating the target instance with a Factory (Java style); Asynchronous publishing of files. Wed, 7 Oct 2020 23:01:31 +0200 Jan Dankert Cleanup: Refactored file seperator char with an unicode char. Fri, 2 Oct 2020 23:11:48 +0200 Jan Dankert Cleanup: No '.inputholder' any more, notices with links to objects. Tue, 29 Sep 2020 23:28:38 +0200 Jan Dankert Fix: Only warn, if another (!) user has changed a edited value. Tue, 29 Sep 2020 22:17:11 +0200 Jan Dankert Refactoring: Do not use global constants. Sat, 26 Sep 2020 04:03:53 +0200 Jan Dankert Refactoring: read language keys with a 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. Fri, 18 Sep 2020 23:04:13 +0200 Jan Dankert Refactoring: Renaming module "cms/publish" to "cms/generator" Fri, 18 Sep 2020 22:48:46 +0200 Jan Dankert Refactoring: Every project has 1 publishing target. Thu, 27 Aug 2020 00:32:27 +0200 Jan Dankert Cleanup: Remove unused template components page,tree; remove unused action method 'structure'. Sun, 23 Feb 2020 04:01:30 +0100 Jan Dankert Refactoring with Namespaces for the cms modules, part 1: moving.