File modules/cms/action/PageelementAction.class.php

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