Value.class.php (8798B)
1 <?php 2 namespace cms\model; 3 use cms\base\Configuration; 4 use cms\base\DB; 5 use cms\base\Startup; 6 use util\ArrayUtils; 7 use cms\generator\Publish; 8 use cms\macros\MacroRunner; 9 use \util\exception\ObjectNotFoundException; 10 use logger\Logger; 11 use util\exception\GeneratorException; 12 use util\Request; 13 use util\Text; 14 use util\Html; 15 use util\Http; 16 use util\Transformer; 17 use util\Code; 18 use util\cache\FileCache; 19 20 /** 21 * Darstellen einer Inhaltes 22 * 23 * @author Jan Dankert 24 */ 25 26 class Value extends ModelBase 27 { 28 /** 29 * ID of this value. 30 * @type Integer 31 */ 32 public $valueid=0; 33 34 /** 35 * Content ID. 36 * @var int 37 */ 38 public $contentid; 39 40 41 /** 42 * Linked object-id. 43 * @type Integer 44 */ 45 public $linkToObjectId=0; 46 47 /** 48 * textual value 49 * @type String 50 */ 51 public $text=''; 52 53 /** 54 * Number. 55 * @type Integer 56 */ 57 public $number=0; 58 59 60 /** 61 * Date. 62 * 63 * Saved as unix-timestamp 64 * 65 * @type Integer 66 */ 67 public $date=0; 68 69 /** 70 * file blob. 71 * 72 * @var string 73 */ 74 public $file = null; 75 76 /** 77 * TimeStamp of last change. 78 * @type Integer 79 */ 80 public $lastchangeTimeStamp; 81 82 /** 83 * user-Id of the user who created this value. 84 * 85 * @type Integer 86 */ 87 public $lastchangeUserId; 88 89 /** 90 * Name of user who created this value. 91 * 92 * This attribute is readonly. 93 * 94 * @type Integer 95 */ 96 public $lastchangeUserName; 97 98 /** 99 * Is this content active? 100 * 101 * Only 1 value (mostly the latest) in a content is active. 102 * 103 * @type Boolean 104 */ 105 public $active; 106 107 /** 108 * Is this content public available? 109 * @type boolean 110 */ 111 public $publish = false; 112 113 /** 114 * Format 115 * 116 * @var int 117 */ 118 public $format = null; 119 120 /** 121 * Constructor. 122 */ 123 function __construct() 124 { 125 } 126 127 128 129 130 /** 131 * Laden des aktuellen Inhaltes aus der Datenbank 132 */ 133 public function loadPublished() 134 { 135 $stmt = Db::sql( <<<SQL 136 SELECT *,{{user}}.fullname as lastchange_username 137 FROM {{value}} 138 LEFT JOIN {{user}} 139 ON {{user}}.id = {{value}}.lastchange_userid 140 WHERE contentid = {contentid} 141 AND publish = 1 142 SQL 143 ); 144 $stmt->setInt( 'contentid' ,$this->contentid); 145 146 $this->bindRow( $stmt->getRow() ); 147 } 148 149 150 private function bindRow( $row ) { 151 152 if ( $row ) // If found 153 { 154 $this->contentid = $row['contentid' ]; 155 $this->text = $row['text' ]; 156 $this->file = $row['file' ]; 157 $this->format = $row['format' ]; 158 $this->valueid = intval($row['id'] ); 159 $this->linkToObjectId = intval($row['linkobjectid']); 160 $this->number = intval($row['number' ]); 161 $this->date = intval($row['date' ]); 162 163 $storeValueAsBase64 = DB::get()->conf['base64']; 164 165 if ( $storeValueAsBase64 ) 166 $this->file = base64_decode( $this->file ); 167 168 $this->active = ( $row['active' ]=='1' ); 169 $this->publish = ( $row['publish']=='1' ); 170 171 $this->lastchangeTimeStamp = intval($row['lastchange_date' ]); 172 $this->lastchangeUserId = intval($row['lastchange_userid' ]); 173 $this->lastchangeUserName = $row['lastchange_username']; 174 } 175 } 176 177 178 /** 179 * Loading the last value from the database. 180 */ 181 public function load() 182 { 183 $stmt = Db::sql( <<<SQL 184 SELECT *,{{user}}.fullname as lastchange_username 185 FROM {{value}} 186 LEFT JOIN {{user}} 187 ON {{user}}.id = {{value}}.lastchange_userid 188 WHERE contentid = {contentid} 189 AND {{value}}.active = 1 190 SQL 191 ); 192 $stmt->setInt( 'contentid' ,$this->contentid); 193 194 $this->bindRow( $stmt->getRow() ); 195 } 196 197 198 /** 199 * Laden eines bestimmten Inhaltes aus der Datenbank 200 */ 201 function loadWithId( $valueid = null ) 202 { 203 $stmt = Db::sql( <<<SQL 204 SELECT {{value}}.*,{{user}}.fullname as lastchange_username 205 FROM {{value}} 206 LEFT JOIN {{user}} 207 ON {{user}}.id = {{value}}.lastchange_userid 208 WHERE {{value}}.id = {valueid} 209 SQL 210 ); 211 $stmt->setInt( 'valueid' ,$valueid ); 212 213 $this->bindRow( $stmt->getRow() ); 214 } 215 216 217 /** 218 * @see #save() 219 */ 220 protected function add() 221 { 222 // this is implemented in the save() method. 223 } 224 225 226 /** 227 * Saving the value. 228 * A value is always added, never overwritten. So we are doing an INSERT here. 229 */ 230 protected function save() 231 { 232 $stmt = Db::sql( <<<SQL 233 UPDATE {{value}} 234 SET active=0 235 WHERE contentid = {contentid} 236 SQL 237 ); 238 $stmt->setInt( 'contentid' ,$this->contentid ); 239 240 $stmt->execute(); 241 242 if ( $this->publish ) 243 { 244 // Wenn Inhalt sofort veroeffentlicht werden kann, dann 245 // alle anderen Inhalte auf nicht-veroeffentlichen stellen 246 $stmt = DB::sql( <<<SQL 247 UPDATE {{value}} 248 SET publish=0 249 WHERE contentid = {contentid} 250 SQL 251 ); 252 $stmt->setInt( 'contentid' ,$this->contentid ); 253 254 $stmt->execute(); 255 } 256 257 // Naechste ID aus Datenbank besorgen 258 $stmt = DB::sql('SELECT MAX(id) FROM {{value}}'); 259 $this->valueid = intval($stmt->getOne())+1; 260 261 $stmt = DB::sql( <<<SQL 262 INSERT INTO {{value}} 263 (id ,contentid ,linkobjectid ,text ,file ,number ,date ,format ,active,publish ,lastchange_date ,lastchange_userid ) 264 VALUES ({valueid},{contentid},{linkobjectid},{text},{file},{number},{date},{format},1 ,{publish},{lastchange_date},{lastchange_userid}) 265 SQL 266 ); 267 $stmt->setInt( 'valueid' ,$this->valueid ); 268 $stmt->setInt( 'contentid' ,$this->contentid ); 269 $stmt->setInt( 'format' ,$this->format ); 270 271 if ( intval($this->linkToObjectId)==0) 272 $stmt->setNull ( 'linkobjectid' ); 273 else $stmt->setInt ( 'linkobjectid',$this->linkToObjectId ); 274 275 if ( $this->text == '' ) 276 $stmt->setNull ( 'text' ); 277 else $stmt->setString( 'text',$this->text ); 278 279 if ( intval($this->number)==0) 280 $stmt->setNull ( 'number' ); 281 else $stmt->setInt ( 'number',$this->number ); 282 283 if ( intval($this->date)==0) 284 $stmt->setNull ( 'date' ); 285 else $stmt->setInt ( 'date',$this->date ); 286 287 $storeValueAsBase64 = DB::get()->conf['base64']; 288 289 if ( $this->file === null ) 290 $stmt->setNull ( 'file' ); 291 elseif( $storeValueAsBase64 ) 292 $stmt->setString( 'file',base64_encode($this->file) ); 293 else 294 $stmt->setString( 'file',$this->file ); 295 296 $stmt->setBoolean( 'publish' ,$this->publish ); 297 $stmt->setInt ( 'lastchange_date' ,Startup::now() ); 298 $user = Request::getUser(); 299 $stmt->setIntOrNull( 'lastchange_userid',$user?$user->userid:null ); // user may be null, if a guest is saving. 300 301 $stmt->execute(); 302 303 $this->pruneVersions(); 304 } 305 306 307 // Some default values for pruning content 308 const DEFAULT_PRUNE_AFTER_AGE = 10 * 365 * 24 * 60 * 60; // prune after 10 years 309 const DEFAULT_PRUNE_AFTER_VERSIONS = 100; // prune after reaching 100 versions 310 311 /** 312 * Automatic content pruning. 313 * 314 * Deletes old versions. 315 */ 316 private function pruneVersions() 317 { 318 $pruneConfig = Configuration::subset(['content','prune']); 319 320 if ( ! $pruneConfig->is('enabled',true) ) 321 return; // no pruning. 322 323 // First Step: Reading all value id. 324 $sql = DB::sql( <<<SQL 325 SELECT id FROM {{value}} 326 WHERE contentid = {contentid} 327 AND active = 0 328 AND publish = 0 329 ORDER BY id 330 SQL 331 ); 332 $sql->setInt( 'contentid' ,$this->contentid ); 333 $values = $sql->getCol(); 334 335 // Now deleting all outdated content. 336 $sql = DB::sql( <<<SQL 337 DELETE FROM {{value}} 338 WHERE contentid = {contentid} 339 AND active = 0 340 AND publish = 0 341 AND lastchange_date < {delete_before_date} 342 AND id < {delete_before_id} 343 SQL 344 ); 345 $sql->setInt( 'contentid' ,$this->contentid ); 346 $sql->setInt( 'delete_before_date' ,time() - $pruneConfig->getSeconds('age',self::DEFAULT_PRUNE_AFTER_AGE) ); 347 $sql->setInt( 'delete_before_id' ,intval(@$values[count($values)-$pruneConfig->get('versions',self::DEFAULT_PRUNE_AFTER_VERSIONS)]) ); 348 $sql->execute(); 349 } 350 351 352 353 /** 354 * Deleting (not possible). 355 */ 356 function delete() 357 { 358 // values cannot be deleted. 359 // only the whole content is able to be deleted, see class Content. 360 } 361 362 363 364 /** 365 * Ermittelt den unbearbeiteten, "rohen" Inhalt. 366 * 367 * @param int $elementTypeId 368 * @return mixed Inhalt 369 */ 370 public function getRawValue($elementTypeId) 371 { 372 switch( $elementTypeId ) 373 { 374 case Element::ELEMENT_TYPE_LINK: 375 return $this->linkToObjectId; 376 377 case Element::ELEMENT_TYPE_DATE; 378 return $this->date; 379 380 default: 381 return $this->text; 382 } 383 } 384 385 386 public function getName() 387 { 388 return "Value#".$this->valueid; 389 } 390 391 392 public function __toString() 393 { 394 return "Value: ".print_r($this,true); 395 } 396 397 398 399 public function getId() 400 { 401 return $this->valueid; 402 } 403 404 405 }