File modules/cms/model/Value.class.php
Last commit: Sun Jan 29 00:20:21 2023 +0100 Jan Dankert New node type "Script".
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 // If the value is stored in BASE64 we must decode it now. 164 $valueIsStoredAsBase64 = DB::get()->conf['base64']; 165 166 if ( $valueIsStoredAsBase64 ) 167 $this->file = base64_decode( $this->file ); 168 169 $this->active = ( $row['active' ]=='1' ); 170 $this->publish = ( $row['publish']=='1' ); 171 172 $this->lastchangeTimeStamp = intval($row['lastchange_date' ]); 173 $this->lastchangeUserId = intval($row['lastchange_userid' ]); 174 $this->lastchangeUserName = $row['lastchange_username']; 175 } 176 } 177 178 179 /** 180 * Loading the last value from the database. 181 */ 182 public function load() 183 { 184 $stmt = Db::sql( <<<SQL 185 SELECT *,{{user}}.fullname as lastchange_username 186 FROM {{value}} 187 LEFT JOIN {{user}} 188 ON {{user}}.id = {{value}}.lastchange_userid 189 WHERE contentid = {contentid} 190 AND {{value}}.active = 1 191 SQL 192 ); 193 $stmt->setInt( 'contentid' ,$this->contentid); 194 195 $this->bindRow( $stmt->getRow() ); 196 } 197 198 199 /** 200 * Laden eines bestimmten Inhaltes aus der Datenbank 201 */ 202 function loadWithId( $valueid = null ) 203 { 204 $stmt = Db::sql( <<<SQL 205 SELECT {{value}}.*,{{user}}.fullname as lastchange_username 206 FROM {{value}} 207 LEFT JOIN {{user}} 208 ON {{user}}.id = {{value}}.lastchange_userid 209 WHERE {{value}}.id = {valueid} 210 SQL 211 ); 212 $stmt->setInt( 'valueid' ,$valueid ); 213 214 $this->bindRow( $stmt->getRow() ); 215 } 216 217 218 /** 219 * @see #save() 220 */ 221 protected function add() 222 { 223 // this is implemented in the save() method. 224 } 225 226 227 /** 228 * Saving the value. 229 * A value is always added, never overwritten. So we are doing an INSERT here. 230 */ 231 protected function save() 232 { 233 $stmt = Db::sql( <<<SQL 234 UPDATE {{value}} 235 SET active=0 236 WHERE contentid = {contentid} 237 SQL 238 ); 239 $stmt->setInt( 'contentid' ,$this->contentid ); 240 241 $stmt->execute(); 242 243 if ( $this->publish ) 244 { 245 // Wenn Inhalt sofort veroeffentlicht werden kann, dann 246 // alle anderen Inhalte auf nicht-veroeffentlichen stellen 247 $stmt = DB::sql( <<<SQL 248 UPDATE {{value}} 249 SET publish=0 250 WHERE contentid = {contentid} 251 SQL 252 ); 253 $stmt->setInt( 'contentid' ,$this->contentid ); 254 255 $stmt->execute(); 256 } 257 258 // Naechste ID aus Datenbank besorgen 259 $stmt = DB::sql('SELECT MAX(id) FROM {{value}}'); 260 $this->valueid = intval($stmt->getOne())+1; 261 262 $stmt = DB::sql( <<<SQL 263 INSERT INTO {{value}} 264 (id ,contentid ,linkobjectid ,text ,file ,number ,date ,format ,active,publish ,lastchange_date ,lastchange_userid ) 265 VALUES ({valueid},{contentid},{linkobjectid},{text},{file},{number},{date},{format},1 ,{publish},{lastchange_date},{lastchange_userid}) 266 SQL 267 ); 268 $stmt->setInt( 'valueid' ,$this->valueid ); 269 $stmt->setInt( 'contentid' ,$this->contentid ); 270 $stmt->setInt( 'format' ,$this->format ); 271 272 if ( intval($this->linkToObjectId)==0) 273 $stmt->setNull ( 'linkobjectid' ); 274 else $stmt->setInt ( 'linkobjectid',$this->linkToObjectId ); 275 276 if ( $this->text == '' ) 277 $stmt->setNull ( 'text' ); 278 else $stmt->setString( 'text',$this->text ); 279 280 if ( intval($this->number)==0) 281 $stmt->setNull ( 'number' ); 282 else $stmt->setInt ( 'number',$this->number ); 283 284 if ( intval($this->date)==0) 285 $stmt->setNull ( 'date' ); 286 else $stmt->setInt ( 'date',$this->date ); 287 288 289 if ( $this->file === null ) 290 $stmt->setNull ( 'file' ); 291 else { 292 $storeValueAsBase64 = DB::get()->conf['base64']; 293 294 if( $storeValueAsBase64 ) { 295 $stmt->setString( 'file' ,base64_encode($this->file) ); 296 } 297 else { 298 $stmt->setString( 'file' ,$this->file ); 299 } 300 } 301 302 $stmt->setBoolean( 'publish' ,$this->publish ); 303 $stmt->setInt ( 'lastchange_date' ,Startup::now() ); 304 $user = Request::getUser(); 305 $stmt->setIntOrNull( 'lastchange_userid',$user?$user->userid:null ); // user may be null, if a guest is saving. 306 307 $stmt->execute(); 308 309 $this->pruneVersions(); 310 } 311 312 313 // Some default values for pruning content 314 const DEFAULT_PRUNE_AFTER_AGE = 10 * 365 * 24 * 60 * 60; // prune after 10 years 315 const DEFAULT_PRUNE_AFTER_VERSIONS = 100; // prune after reaching 100 versions 316 317 /** 318 * Automatic content pruning. 319 * 320 * Deletes old versions. 321 */ 322 private function pruneVersions() 323 { 324 $pruneConfig = Configuration::subset(['content','prune']); 325 326 if ( ! $pruneConfig->is('enabled',true) ) 327 return; // no pruning. 328 329 // First Step: Reading all value id. 330 $sql = DB::sql( <<<SQL 331 SELECT id FROM {{value}} 332 WHERE contentid = {contentid} 333 AND active = 0 334 AND publish = 0 335 ORDER BY id 336 SQL 337 ); 338 $sql->setInt( 'contentid' ,$this->contentid ); 339 $values = $sql->getCol(); 340 341 // Now deleting all outdated content. 342 $sql = DB::sql( <<<SQL 343 DELETE FROM {{value}} 344 WHERE contentid = {contentid} 345 AND active = 0 346 AND publish = 0 347 AND lastchange_date < {delete_before_date} 348 AND id < {delete_before_id} 349 SQL 350 ); 351 $sql->setInt( 'contentid' ,$this->contentid ); 352 $sql->setInt( 'delete_before_date' ,time() - $pruneConfig->getSeconds('age',self::DEFAULT_PRUNE_AFTER_AGE) ); 353 $sql->setInt( 'delete_before_id' ,intval(@$values[count($values)-$pruneConfig->get('versions',self::DEFAULT_PRUNE_AFTER_VERSIONS)]) ); 354 $sql->execute(); 355 } 356 357 358 359 /** 360 * Deleting (not possible). 361 */ 362 function delete() 363 { 364 // values cannot be deleted. 365 // only the whole content is able to be deleted, see class Content. 366 } 367 368 369 370 /** 371 * Ermittelt den unbearbeiteten, "rohen" Inhalt. 372 * 373 * @param int $elementTypeId 374 * @return mixed Inhalt 375 */ 376 public function getRawValue($elementTypeId) 377 { 378 switch( $elementTypeId ) 379 { 380 case Element::ELEMENT_TYPE_LINK: 381 return $this->linkToObjectId; 382 383 case Element::ELEMENT_TYPE_DATE; 384 return $this->date; 385 386 default: 387 return $this->text; 388 } 389 } 390 391 392 public function getName() 393 { 394 return "Value#".$this->valueid; 395 } 396 397 398 public function __toString() 399 { 400 return "Value: ".print_r($this,true); 401 } 402 403 404 405 public function getId() 406 { 407 return $this->valueid; 408 } 409 410 411 }
Downloadmodules/cms/model/Value.class.php
History Sun, 29 Jan 2023 00:20:21 +0100 Jan Dankert New node type "Script". Fri, 15 Apr 2022 14:51:22 +0200 dankert Refactoring: User,Config and Database info is now stored in the Request, because so there is no session required for clients which are using Basic Authorization. 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 18:34:26 +0100 Jan Dankert Fix: Load contentid while value is loaded. 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 01:22:31 +0100 Jan Dankert Fix: Creating and reading files. Tue, 9 Nov 2021 00:35:42 +0100 Jan Dankert Fixes: Reading and writing template sources with the new content table. Mon, 8 Nov 2021 01:05:19 +0100 Jan Dankert Refactoring: Reading values from the new content table. Sun, 7 Mar 2021 00:10:20 +0100 Jan Dankert Refactoring: Hopefully more performance while accessing the database resultsets. Tue, 23 Feb 2021 22:59:12 +0100 Jan Dankert New: Use a default value from a linked page. Fri, 8 Jan 2021 22:01:28 +0100 Jan Dankert New: Implementing cache directory tag standard (CACHEDIR.TAG) and using a cleaner logic to detect the directory for temporary files. Wed, 18 Nov 2020 01:46:36 +0100 Jan Dankert Refactoring of model classes: New method persist() and some other cleanups. Fri, 13 Nov 2020 23:41:58 +0100 Jan Dankert Cleaned database statements. Fri, 13 Nov 2020 23:24:54 +0100 Jan Dankert Using icons for the history view, this is much cleaner. Fri, 13 Nov 2020 00:12:44 +0100 Jan Dankert Fixing Pagelement-History and Diff. Sun, 1 Nov 2020 00:36:50 +0100 Jan Dankert Refactoring: Only using the configuration object. 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:26:55 +0200 Jan Dankert Refactoring: read configuration values with a class. Sat, 26 Sep 2020 03:03:47 +0200 Jan Dankert Refactoring: less global functions. Sat, 26 Sep 2020 02:26:39 +0200 Jan Dankert Refactoring: No global functions any more, the database object is read from the Db 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" Sat, 29 Aug 2020 03:23:06 +0200 Jan Dankert Refactoring: Improved Exception-Handling; New: Generating pages using a page context which considers page aliases. Sun, 23 Feb 2020 04:49:34 +0100 Jan Dankert Refactoring with Namespaces for the cms modules, part 2. Sun, 23 Feb 2020 04:01:30 +0100 Jan Dankert Refactoring with Namespaces for the cms modules, part 1: moving.