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