openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

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( ' &raquo; ',$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( ' &raquo; ',$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 }