File modules/cms/model/BaseObject.class.php

Last commit: Sun Dec 8 20:56:47 2024 +0100	Jan Dankert	New: Users are now able to store bookmarks.
1 <?php 2 3 4 namespace cms\model; 5 6 use cms\base\Configuration; 7 use cms\base\DB; 8 use cms\base\Startup; 9 use cms\generator\Publisher; 10 use util\ArrayUtils; 11 use util\Request; 12 use util\text\variables\VariableResolver; 13 use util\YAML; 14 15 /** 16 * Base class for all objects in the content tree. 17 * 18 * @author Jan Dankert 19 */ 20 class BaseObject extends ModelBase 21 { 22 const TYPEID_FOLDER = 1; 23 const TYPEID_FILE = 2; 24 const TYPEID_PAGE = 3; 25 const TYPEID_LINK = 4; 26 const TYPEID_URL = 5; 27 const TYPEID_IMAGE = 6; 28 const TYPEID_TEXT = 7; 29 const TYPEID_ALIAS = 8; 30 const TYPEID_SCRIPT = 9; 31 32 33 /** 34 * Unique ID of this base object. 35 * 36 * @type Integer 37 */ 38 public $objectid; 39 40 /** 41 * Parent-Id. 42 * 43 * Object-Id of the folder, which this objects belongs to. 44 * 45 * Is 0 in case of the root folder. 46 * 47 * @see #isRoot() 48 * @type Integer 49 */ 50 public $parentid = null; 51 52 /** Filename. 53 * 54 * Technical filename of this object without any extension. This name must be unique in a folder. 55 * 56 * @type String 57 */ 58 public $filename = ''; 59 60 61 /** Zeitpunkt der Erstellung. Die Variable beinhaltet den Unix-Timestamp. 62 * @type Integer 63 */ 64 var $createDate; 65 66 /** Zeitpunkt der letzten Aenderung. Die Variable beinhaltet den Unix-Timestamp. 67 * @type Integer 68 */ 69 var $lastchangeDate; 70 71 /** Benutzer, welcher dieses Objekt erstellt hat. 72 * @type User 73 */ 74 public $createUser; 75 76 /** Benutzer, welcher dieses Objekt zuletzt geaendert hat. 77 * @type User 78 */ 79 public $lastchangeUser; 80 81 /** 82 * Benutzer, der das Objekt zuletzt veröffentlicht hat. 83 * @var User 84 */ 85 public $publishedUser; 86 /** 87 * Zeitpunkt der letzten Veröffentlichung. 88 * @var Integer 89 */ 90 public $publishedDate; 91 92 93 /** 94 * Valid from. 95 * 96 * This is a unix-timestamp. 97 * 98 * @var int 99 */ 100 public $validFromDate; 101 102 /** 103 * Valid to. 104 * 105 * This is a unix-timestamp. 106 * 107 * @var int 108 */ 109 public $validToDate; 110 111 /** 112 * Kennzeichen, ob Objekt ein Ordner ist 113 * @type Boolean 114 */ 115 var $isFolder = false; 116 117 /** 118 * Kennzeichen, ob Objekt eine binaere Datei ist 119 * @type Boolean 120 */ 121 var $isFile = false; 122 123 /** 124 * Kennzeichen, ob Objekt ein Bild ist 125 * @type Boolean 126 */ 127 var $isImage = false; 128 129 /** 130 * Kennzeichen, ob Objekt ein Text ist 131 * @type Boolean 132 */ 133 var $isText = false; 134 135 /** 136 * Kennzeichen, ob Objekt eine Seite ist 137 * @type Boolean 138 */ 139 var $isPage = false; 140 141 /** 142 * Kennzeichen, ob Objekt eine Verknuepfung (Link) ist 143 * @type Boolean 144 */ 145 var $isLink = false; 146 147 /** 148 * Kennzeichen, ob Objekt eine Verknuepfung (Url) ist 149 * @type Boolean 150 */ 151 var $isUrl = false; 152 153 /** 154 * Kennzeichen, ob Objekt ein Alias ist 155 * @type Boolean 156 */ 157 var $isAlias = false; 158 159 /** 160 * Kennzeichen, ob Objekt ein Alias ist 161 * @type Boolean 162 */ 163 var $isScript = false; 164 165 /** 166 * Kennzeichnet den Typ dieses Objektes. 167 * Muss den Inhalt OR_FILE, OR_FOLDER, OR_PAGE oder OR_LINK haben. 168 * Vorbelegung mit <code>null</code>. 169 * @type Integer 170 */ 171 var $type = null; 172 173 174 /** 175 * Projekt-ID 176 * @see Project 177 * @type Integer 178 */ 179 public $projectid; 180 181 182 public $typeid; 183 184 private $aclMask = null; 185 private $parentfolders = array(); 186 187 /** 188 * @type String 189 */ 190 public $settings; 191 192 /** 193 * Strategy for publishing objects. 194 * @var Publisher 195 */ 196 public $publisher; 197 198 /** <strong>Konstruktor</strong> 199 * F?llen des neuen Objektes mit Init-Werten 200 * Es werden die Standardwerte aus der Session benutzt, um 201 * Sprach-ID, Projektmodell-Id und Projekt-ID zu setzen 202 * 203 * @param Integer Objekt-ID (optional) 204 */ 205 function __construct($objectid = '') 206 { 207 if ( is_numeric($objectid) ) 208 { 209 $this->objectid = $objectid; 210 } 211 } 212 213 214 /** 215 * Kompletten Dateinamen des Objektes erzeugen 216 * @return String 217 */ 218 public function full_filename() 219 { 220 $path = $this->path(); 221 222 if ($path != '') 223 $path.= '/'; 224 225 $path.= $this->filename(); 226 227 return $path; 228 } 229 230 /** 231 * Pruefen einer Berechtigung zu diesem Objekt 232 */ 233 public function hasRight( $type ) 234 { 235 if ( is_null($this->aclMask) ) 236 { 237 $user = Request::getUser(); 238 239 $this->aclMask = 0; 240 241 if ( ! $user ) { 242 // Anonymous 243 244 $sql = Db::sql( <<<SQL 245 SELECT * FROM {{acl}} 246 WHERE objectid={objectid} 247 AND type = {guest} 248 SQL 249 ); 250 251 $sql->setInt ( 'objectid' ,$this->objectid ); 252 $sql->setInt ( 'guest' ,Permission::TYPE_GUEST ); 253 254 foreach($sql->getAll() as $row ) 255 { 256 $permission = new Permission(); 257 $permission->setDatabaseRow( $row ); 258 259 $this->aclMask |= $permission->getMask(); 260 } 261 262 } 263 264 elseif ( $user->isAdmin ) 265 { 266 // Administrators got all rights 267 $this->aclMask = Permission::ACL_ALL; 268 } 269 else 270 { 271 // Normal user 272 $this->aclMask = 0; 273 274 $sqlGroupClause = $user->getGroupClause(); 275 $sql = Db::sql( <<<SQL 276 SELECT * FROM {{acl}} 277 WHERE objectid={objectid} 278 /*--AND ( languageid={languageid} OR languageid IS NULL )*/ 279 AND ( type = {user} AND userid={userid} 280 OR type = {group} AND $sqlGroupClause 281 OR type = {all} 282 OR type = {guest} 283 ) 284 SQL 285 ); 286 287 $sql->setInt ( 'objectid' ,$this->objectid ); 288 $sql->setInt ( 'userid' ,$user->userid ); 289 $sql->setInt ( 'user' ,Permission::TYPE_USER ); 290 $sql->setInt ( 'group' ,Permission::TYPE_GROUP); 291 $sql->setInt ( 'all' ,Permission::TYPE_AUTH ); 292 $sql->setInt ( 'guest' ,Permission::TYPE_GUEST ); 293 294 foreach($sql->getAll() as $row ) 295 { 296 $permission = new Permission(); 297 $permission->setDatabaseRow( $row ); 298 299 $this->aclMask |= $permission->getMask(); 300 } 301 } 302 } 303 304 if ( Startup::readonly() ) 305 // System is readonly. 306 // The maximum permission is readonly. 307 $this->aclMask = Permission::ACL_READ && $this->aclMask; 308 309 // Ermittelte Maske auswerten 310 return $this->aclMask & $type; 311 } 312 313 314 /** 315 * Get the type name. 316 * 317 * @return String type of object, f.e. 'folder','file','page', ... 318 */ 319 function getType() 320 { 321 $mapTypeIdToName = [ 322 self::TYPEID_FOLDER => 'folder', 323 self::TYPEID_FILE => 'file' , 324 self::TYPEID_PAGE => 'page' , 325 self::TYPEID_LINK => 'link' , 326 self::TYPEID_URL => 'url' , 327 self::TYPEID_IMAGE => 'image' , 328 self::TYPEID_TEXT => 'text' , 329 self::TYPEID_ALIAS => 'alias' , 330 self::TYPEID_SCRIPT => 'script', 331 ]; 332 333 return @$mapTypeIdToName[ $this->getTypeid() ] ?: 'unknown typeid '.$this->getTypeid(); 334 } 335 336 337 /** 338 * Eigenschaften des Objektes. Kann durch Unterklassen erweitert werden. 339 * @return array 340 */ 341 public function getProperties() 342 { 343 return [ 344 'id' =>$this->objectid, 345 'objectid' =>$this->objectid, 346 'parentid' =>$this->parentid, 347 'filename' =>$this->filename, 348 'create_date' =>$this->createDate, 349 'create_user' =>$this->createUser->getProperties(), 350 'lastchange_date' =>$this->lastchangeDate, 351 'lastchange_user' =>$this->lastchangeUser->getProperties(), 352 'published_date' =>$this->publishedDate, 353 'published_user' =>$this->publishedUser->getProperties(), 354 'isFolder' =>$this->isFolder, 355 'isFile' =>$this->isFile, 356 'isImage' =>$this->isImage, 357 'isText' =>$this->isText, 358 'isScript' =>$this->isScript, 359 'isLink' =>$this->isLink, 360 'isUrl' =>$this->isUrl, 361 'isPage' =>$this->isPage, 362 'isRoot' =>$this->isRoot(), 363 'projectid' =>$this->projectid, 364 'settings' =>$this->settings, 365 'valid_from_date' =>$this->validFromDate, 366 'valid_to_date' =>$this->validToDate, 367 'type' =>$this->getType() 368 ]; 369 } 370 371 372 /** 373 * Ermitteln des physikalischen Dateipfades, in dem sich das Objekt befindet 374 * @return String Pfadangabe, z.B. 'pfad/zu/objekt' 375 */ 376 public function path() 377 { 378 $alias = $this->getAlias(); 379 380 if ( $alias ) 381 $folder = new Folder($alias->parentid); 382 else 383 $folder = new Folder($this->parentid); 384 385 return implode('/', $folder->parentObjectFileNames(false, true)); 386 } 387 388 389 390 /** 391 * Creates a slug url out of the filename. 392 * 393 * @param $filename String Name 394 * @return string 395 */ 396 public static function urlify( $filename ) 397 { 398 $slug = $filename; 399 400 // The hard method to replace UTF-8-chars with their alphanumeric replacement. 401 $replacements = array( 402 // German umlauts 403 "\xc3\x84" => 'ae', 404 "\xc3\xa4" => 'ae', 405 "\xc3\x9c" => 'ue', 406 "\xc3\xbc" => 'ue', 407 "\xc3\x96" => 'oe', 408 "\xc3\xb6" => 'oe', 409 "\xc3\x9f" => 'ss', 410 "\xe2\x82\xac" => 'eur', 411 // Francais 412 "\xc3\xa0" => 'a', 413 "\xc3\xa1" => 'a', 414 "\xc3\xa2" => 'a', 415 "\xc3\xa3" => 'a', 416 "\xc3\xa5" => 'a', 417 "\xc3\xa6" => 'ae', 418 "\xc3\xa7" => 'c', 419 "\xc3\xa8" => 'e', 420 "\xc3\xa9" => 'e', 421 "\xc3\xaa" => 'e', 422 "\xc3\xab" => 'e', 423 "\xc3\xac" => 'i', 424 "\xc3\xad" => 'i', 425 "\xc3\xae" => 'i', 426 "\xc3\xaf" => 'i', 427 "\xc3\xb2" => 'o', 428 "\xc3\xb3" => 'o', 429 "\xc3\xb4" => 'o', 430 "\xc3\xb5" => 'o', 431 "\xc3\xb8" => 'o', 432 "\xc3\xb9" => 'u', 433 "\xc3\xba" => 'u', 434 "\xc3\xbb" => 'u', 435 "\xc3\xbd" => 'y', 436 "\xc3\xbf" => 'y', 437 "\xc3\x80" => 'a', 438 "\xc3\x81" => 'a', 439 "\xc3\x82" => 'a', 440 "\xc3\x83" => 'a', 441 "\xc3\x85" => 'a', 442 "\xc3\x86" => 'ae', 443 "\xc3\x87" => 'c', 444 "\xc3\x88" => 'e', 445 "\xc3\x89" => 'e', 446 "\xc3\x8a" => 'e', 447 "\xc3\x8b" => 'e', 448 "\xc3\x8c" => 'i', 449 "\xc3\x8d" => 'i', 450 "\xc3\x8e" => 'i', 451 "\xc3\x8f" => 'i', 452 "\xc3\x92" => 'o', 453 "\xc3\x93" => 'o', 454 "\xc3\x94" => 'o', 455 "\xc3\x95" => 'o', 456 "\xc3\x98" => 'o', 457 "\xc3\x99" => 'u', 458 "\xc3\x9a" => 'u', 459 "\xc3\x9b" => 'u', 460 "\xc3\x9d" => 'y', 461 ); 462 463 $slug = str_replace(array_keys($replacements), array_values($replacements), $slug); 464 465 // 2nd try is to use iconv with the current locale. 466 if ( function_exists('iconv') ) { 467 Language::setLocale(Configuration::subset('language')->get('language_code', 'en')); 468 // iconv is buggy on alpine 3 and does not support TRANSLIT. So we have to catch the error here. 469 $converted = @iconv('utf-8', 'ascii//TRANSLIT', $slug); 470 if ( $converted !== false ) 471 $slug = $converted; 472 } 473 // now replace every unpleasant char with a hyphen. 474 $slug = preg_replace('/[^A-Za-z0-9-]+/', '-', $slug); 475 476 // trim and lowercase. 477 $slug = trim($slug, '-'); 478 $slug = strtolower($slug); 479 480 return $slug; 481 } 482 483 484 485 public function getParentFolderId() 486 { 487 $alias = $this->getAlias(); 488 if ( $alias ) 489 return $alias->parentid; 490 else 491 return $this->parentid; 492 } 493 494 495 /** 496 * Ermitteln des Dateinamens und Rueckgabe desselben 497 * @return String Dateiname 498 */ 499 public function filename() 500 { 501 $filenameConfig = Configuration::subset('filename'); 502 503 $filename = $this->filename; 504 505 $alias = $this->getAlias(); 506 507 if ( $alias ) 508 $filename = $alias->filename; 509 510 if ( $filenameConfig->is('edit',true) && $filename != '' && $filename != $this->objectid ) 511 { 512 // do not change the filename here - otherwise there is a danger of filename collisions. 513 return $filename; 514 } 515 516 // Filename is not edited, so we are generating a pleasant filename. 517 switch( $filenameConfig->get('style','short' ) ) 518 { 519 case 'longid': 520 // Eine etwas laengere ID als Dateinamen benutzen 521 return base_convert(str_pad($this->objectid,6,'a'),11,10); 522 break; 523 524 case 'longalpha': 525 // Eine etwas laengere ID als Dateinamen benutzen 526 return base_convert(str_pad($this->objectid,6,'a'),11,36); 527 break; 528 529 case 'short': 530 // As shortly as possible 531 // Examples: 532 // 1 -> 1 533 // 10 -> a 534 return base_convert($this->objectid,10,36); 535 536 case 'md5': // Removed, because collisions are possible. 537 case 'title': // Not possible any more because of the collision danger 538 case 'ss': // Old storyserver crap (removed) 539 case 'id': 540 default: 541 // Taking the object id as filename. 542 return $this->objectid; 543 544 } 545 } 546 547 548 549 /** 550 * Stellt fest, ob das Objekt mit der angegebenen Id existiert. 551 */ 552 public static function available( $objectid ) 553 { 554 $db = \cms\base\DB::get(); 555 556 // Vielleicht k�nnen wir uns den DB-Zugriff auch ganz sparen. 557 if ( !is_numeric($objectid) || $objectid <= 0 ) 558 return false; // Objekt-Id ung�ltig. 559 560 $sql = $db->sql('SELECT 1 FROM {{object}} '. 561 ' WHERE id={objectid}'); 562 $sql->setInt('objectid' , $objectid ); 563 564 return intval($sql->getOne()) == 1; 565 } 566 567 568 /** 569 * Lesen der Eigenschaften aus der Datenbank 570 * Es werden 571 * - die sprachunabh?ngigen Daten wie Dateiname, Typ sowie Erstellungs- und ?nderungsdatum geladen 572 * - die sprachabh?ngigen Daten wie Name und Beschreibung geladen 573 * @throws \util\exception\ObjectNotFoundException 574 */ 575 function objectLoad() 576 { 577 $db = \cms\base\DB::get(); 578 579 $stmt = $db->sql( <<<SQL 580 SELECT {{object}}.*, 581 lastchangeuser.name as lastchange_username, 582 lastchangeuser.fullname as lastchange_userfullname, 583 lastchangeuser.mail as lastchange_usermail, 584 publisheduser.name as published_username, 585 publisheduser.fullname as published_userfullname, 586 publisheduser.mail as published_usermail, 587 createuser.name as create_username, 588 createuser.fullname as create_userfullname, 589 createuser.mail as create_usermail 590 FROM {{object}} 591 LEFT JOIN {{user}} as lastchangeuser 592 ON {{object}}.lastchange_userid=lastchangeuser.id 593 LEFT JOIN {{user}} as publisheduser 594 ON {{object}}.published_userid=publisheduser.id 595 LEFT JOIN {{user}} as createuser 596 ON {{object}}.create_userid=createuser.id 597 WHERE {{object}}.id={objectid} 598 SQL 599 ); 600 $stmt->setInt('objectid' , $this->objectid ); 601 602 $row = $stmt->getRow(); 603 604 if (count($row) == 0) 605 throw new \util\exception\ObjectNotFoundException('object '.$this->objectid.' not found'); 606 607 $this->setDatabaseRow( $row ); 608 } 609 610 611 /** 612 * Lesen der Eigenschaften aus der Datenbank 613 * Es werden 614 * - die sprachunabhaengigen Daten wie Dateiname, Typ sowie Erstellungs- und Aenderungsdatum geladen 615 */ 616 function objectLoadRaw() 617 { 618 $db = \cms\base\DB::get(); 619 620 $sql = $db->sql('SELECT * FROM {{object}}'. 621 ' WHERE {{object}}.id={objectid}'); 622 $sql->setInt('objectid' , $this->objectid ); 623 $row = $sql->getRow(); 624 625 if (count($row) == 0) 626 throw new \util\exception\ObjectNotFoundException('objectid not found: '.$this->objectid); 627 628 $this->parentid = $row['parentid' ]; 629 $this->filename = $row['filename' ]; 630 $this->projectid = $row['projectid']; 631 632 $this->createDate = $row['create_date' ]; 633 $this->createUser = $row['create_userid' ]; 634 $this->lastchangeDate = $row['lastchange_date' ]; 635 $this->lastchangeUser = $row['lastchange_userid']; 636 637 $this->isFolder = ( $row['typeid'] == self::TYPEID_FOLDER ); 638 $this->isFile = ( $row['typeid'] == self::TYPEID_FILE ); 639 $this->isImage = ( $row['typeid'] == self::TYPEID_IMAGE ); 640 $this->isText = ( $row['typeid'] == self::TYPEID_TEXT ); 641 $this->isPage = ( $row['typeid'] == self::TYPEID_PAGE ); 642 $this->isLink = ( $row['typeid'] == self::TYPEID_LINK ); 643 $this->isUrl = ( $row['typeid'] == self::TYPEID_URL ); 644 $this->isAlias = ( $row['typeid'] == self::TYPEID_ALIAS ); 645 $this->isScript = ( $row['typeid'] == self::TYPEID_SCRIPT ); 646 647 } 648 649 650 /** 651 * Is this the root object in a project? 652 * 653 * @return bool 654 */ 655 public function isRoot() { 656 657 return ! $this->parentid; 658 } 659 660 /** 661 * Setzt die Eigenschaften des Objektes mit einer Datenbank-Ergebniszeile 662 * 663 * @param array Ergebniszeile aus Datenbanktabelle 664 */ 665 public function setDatabaseRow( $row ) 666 { 667 if ( count($row)==0 ) 668 throw new \LogicException('setDatabaseRow() got empty array, oid='.$this->objectid); 669 670 $this->parentid = $row['parentid' ]; 671 $this->projectid = $row['projectid']; 672 $this->filename = $row['filename' ]; 673 $this->orderid = $row['orderid' ]; 674 675 $this->createDate = $row['create_date' ]; 676 $this->lastchangeDate = $row['lastchange_date']; 677 $this->publishedDate = $row['published_date' ]; 678 679 $this->validFromDate = $row['valid_from' ]; 680 $this->validToDate = $row['valid_to' ]; 681 682 $this->createUser = new User(); 683 $this->createUser->userid = $row['create_userid' ]; 684 if ( !empty($row['create_username']) ) 685 { 686 $this->createUser->name = $row['create_username' ]; 687 $this->createUser->fullname = $row['create_userfullname' ]; 688 $this->createUser->mail = $row['create_usermail' ]; 689 } 690 691 $this->lastchangeUser = new User(); 692 $this->lastchangeUser->userid = $row['lastchange_userid' ]; 693 694 if ( !empty($row['lastchange_username']) ) 695 { 696 $this->lastchangeUser->name = $row['lastchange_username' ]; 697 $this->lastchangeUser->fullname = $row['lastchange_userfullname']; 698 $this->lastchangeUser->mail = $row['lastchange_usermail' ]; 699 } 700 701 $this->publishedUser = new User(); 702 $this->publishedUser->userid = $row['published_userid' ]; 703 704 if ( !empty($row['published_username']) ) 705 { 706 $this->publishedUser->name = $row['published_username' ]; 707 $this->publishedUser->fullname = $row['published_userfullname']; 708 $this->publishedUser->mail = $row['published_usermail' ]; 709 } 710 711 $this->typeid = $row['typeid']; 712 713 $this->isFolder = ( $row['typeid'] == self::TYPEID_FOLDER ); 714 $this->isFile = ( $row['typeid'] == self::TYPEID_FILE ); 715 $this->isImage = ( $row['typeid'] == self::TYPEID_IMAGE ); 716 $this->isText = ( $row['typeid'] == self::TYPEID_TEXT ); 717 $this->isPage = ( $row['typeid'] == self::TYPEID_PAGE ); 718 $this->isLink = ( $row['typeid'] == self::TYPEID_LINK ); 719 $this->isUrl = ( $row['typeid'] == self::TYPEID_URL ); 720 $this->isAlias = ( $row['typeid'] == self::TYPEID_ALIAS ); 721 $this->isScript = ( $row['typeid'] == self::TYPEID_SCRIPT ); 722 723 $this->settings = $row['settings']; 724 } 725 726 727 728 /** 729 * Laden des Objektes 730 */ 731 public function load() 732 { 733 self::objectLoad(); 734 return $this; 735 } 736 737 738 /** 739 * Eigenschaften des Objektes in Datenbank speichern 740 */ 741 public function save() 742 { 743 $this->setTimestamp(); 744 $this->checkFilename(); 745 746 $stmt = Db::sql( <<<SQL 747 UPDATE {{object}} SET 748 parentid = {parentid}, 749 filename = {filename}, 750 valid_from = {validFrom}, 751 valid_to = {validTo}, 752 settings = {settings} 753 WHERE id={objectid} 754 SQL 755 ); 756 757 758 if ( ! $this->parentid ) 759 $stmt->setNull('parentid'); 760 else 761 $stmt->setInt ('parentid',$this->parentid ); 762 763 764 $user = Request::getUser(); 765 $this->lastchangeUser = $user; 766 $this->lastchangeDate = Startup::now(); 767 $stmt->setString('filename' , $this->filename ); 768 $stmt->setString('settings' , $this->settings ); 769 $stmt->setInt ('validFrom', $this->validFromDate ); 770 $stmt->setInt ('validTo' , $this->validToDate ); 771 $stmt->setInt ('objectid' , $this->objectid ); 772 773 774 $stmt->execute(); 775 776 $this->setTimestamp(); 777 } 778 779 780 781 /** 782 * Aenderungsdatum auf Systemzeit setzen 783 */ 784 public function setTimestamp() 785 { 786 $db = \cms\base\DB::get(); 787 788 $sql = $db->sql('UPDATE {{object}} SET '. 789 ' lastchange_date = {time} ,'. 790 ' lastchange_userid = {userid} '. 791 ' WHERE id={objectid}'); 792 793 $user = Request::getUser(); 794 $this->lastchangeUser = $user; 795 $this->lastchangeDate = Startup::now(); 796 $userid = $this->lastchangeUser ? $this->lastchangeUser->userid : null; 797 798 $sql->setIntOrNull('userid' ,$userid ); 799 $sql->setInt ('objectid',$this->objectid ); 800 $sql->setInt ('time' ,$this->lastchangeDate ); 801 802 $sql->execute(); 803 804 } 805 806 807 public function setCreationTimestamp() 808 { 809 $db = \cms\base\DB::get(); 810 811 $sql = $db->sql('UPDATE {{object}} SET '. 812 ' create_date = {time} '. 813 ' WHERE id={objectid}'); 814 815 $sql->setInt ('objectid',$this->objectid ); 816 $sql->setInt ('time' ,$this->createDate ); 817 818 $sql->execute(); 819 } 820 821 822 public function setPublishedTimestamp() 823 { 824 $db = \cms\base\DB::get(); 825 826 $sql = $db->sql('UPDATE {{object}} SET '. 827 ' published_date = {time} ,'. 828 ' published_userid = {userid} '. 829 ' WHERE id={objectid}'); 830 831 $user = Request::getUser(); 832 $this->publishedUser = $user; 833 $this->publishedDate = Startup::now(); 834 835 $sql->setInt ('userid' ,$this->publishedUser->userid ); 836 $sql->setInt ('objectid',$this->objectid ); 837 $sql->setInt ('time' ,$this->publishedDate ); 838 839 $sql->execute(); 840 } 841 842 843 844 /** 845 * Objekt loeschen. Es muss sichergestellt sein, dass auch das Unterobjekt geloeschet wird. 846 * Diese Methode wird daher normalerweise nur vom Unterobjekt augerufen 847 * @access protected 848 */ 849 public function delete() 850 { 851 $db = \cms\base\DB::get(); 852 853 $sql = DB::sql( <<<SQL 854 UPDATE {{element}} 855 SET default_objectid=NULL 856 WHERE default_objectid={objectid} 857 SQL 858 ); 859 $sql->setInt('objectid',$this->objectid); 860 $sql->execute(); 861 862 $sql = $db->sql( <<<'SQL' 863 UPDATE {{value}} 864 SET linkobjectid=NULL 865 WHERE linkobjectid={objectid} 866 SQL 867 ); 868 $sql->setInt('objectid',$this->objectid); 869 $sql->execute(); 870 871 $sql = $db->sql( <<<'SQL' 872 UPDATE {{link}} 873 SET link_objectid=NULL 874 WHERE link_objectid={objectid} 875 SQL 876 ); 877 $sql->setInt('objectid',$this->objectid); 878 $sql->execute(); 879 880 881 // Objekt-Namen l?schen 882 $sql = $db->sql(<<<'SQL' 883 DELETE FROM {{name}} 884 WHERE objectid={objectid} 885 SQL 886 ); 887 $sql->setInt('objectid', $this->objectid); 888 $sql->execute(); 889 890 // Aliases löschen. 891 $sql = Db::sql(<<<'SQL' 892 DELETE FROM {{alias}} 893 WHERE objectid={objectid} 894 SQL 895 ); 896 $sql->setInt('objectid', $this->objectid); 897 $sql->execute(); 898 899 // ACLs loeschen 900 $this->deleteAllACLs(); 901 902 903 // Delete Tags from objects 904 $sql = Db::sql(<<<'SQL' 905 DELETE FROM {{tag_object}} 906 WHERE objectid={objectid} 907 SQL 908 ); 909 $sql->setInt('objectid', $this->objectid); 910 $sql->execute(); 911 912 // Delete bookmarks. 913 $sql = Db::sql(<<<'SQL' 914 DELETE FROM {{bookmark}} 915 WHERE objectid={objectid} 916 SQL 917 ); 918 $sql->setInt('objectid', $this->objectid); 919 $sql->execute(); 920 921 922 // Objekt l?schen 923 $sql = $db->sql(<<<'SQL' 924 DELETE FROM {{object}} 925 WHERE id={objectid} 926 SQL 927 ); 928 $sql->setInt('objectid', $this->objectid); 929 $sql->execute(); 930 931 $this->objectid = null; 932 } 933 934 /** 935 * Get all Tags for this object. 936 * 937 * @return String[] 938 */ 939 public function getTags() 940 { 941 $sql = DB::sql( <<<SQL 942 SELECT {{tag}}.id,{{tag}}.name 943 FROM {{tag_object}} 944 LEFT JOIN {{tag}} 945 ON {{tag_object}}.tagid = {{tag}}.id 946 WHERE objectid={objectid} 947 SQL 948 ); 949 $sql->setInt('objectid',$this->objectid ); 950 951 return $sql->getAssoc(); 952 } 953 954 955 /** 956 * Objekt hinzufuegen. 957 * 958 * Standardrechte und vom Elternobjekt vererbbare Berechtigungen werden gesetzt. 959 */ 960 protected function add() 961 { 962 // Neue Objekt-Id bestimmen 963 $sql = Db::sql(<<<'SQL' 964 SELECT MAX(id) FROM {{object}} 965 SQL 966 ); 967 $this->objectid = intval($sql->getOne())+1; 968 969 $this->checkFilename(); 970 $sql = Db::sql(<<<SQL 971 INSERT INTO {{object}} 972 (id,parentid,projectid,filename,orderid,create_date,create_userid,lastchange_date,lastchange_userid,typeid,settings) 973 VALUES( {objectid},{parentid},{projectid},{filename},{orderid},{time},{createuserid},{createtime},{userid},{typeid},'' ) 974 SQL 975 ); 976 977 $user = Request::getUser(); 978 $currentUserId = $user ? $user->userid : 0; 979 980 if ( !$this->parentid ) 981 $sql->setNull('parentid'); 982 else 983 $sql->setInt ('parentid',$this->parentid ); 984 985 $sql->setInt ('objectid' , $this->objectid ); 986 $sql->setString('filename' , $this->filename ); 987 $sql->setString('projectid', $this->projectid); 988 $sql->setInt ('orderid' , 99999 ); 989 $sql->setInt ('time' , Startup::now() ); 990 991 $sql->setInt ('createuserid' , $currentUserId ); 992 $sql->setInt ('createtime' , Startup::now() ); 993 $sql->setInt ('userid' , $currentUserId ); 994 995 $sql->setInt( 'typeid',$this->getTypeid()); 996 997 $sql->execute(); 998 999 $this->grantToActualUser(); // Is this a good idea? don't know ... 1000 $this->inheritPermissions(); 1001 } 1002 1003 1004 /** 1005 * Set permissions for the actual user for the just added object. 1006 * 1007 * @return void 1008 */ 1009 private function grantToActualUser() { 1010 1011 $user = Request::getUser(); 1012 1013 if ( $user ) { // User logged in? 1014 1015 $permission = new Permission(); 1016 $permission->type = Permission::TYPE_USER; 1017 $permission->userid = $user->userid; 1018 $permission->objectid = $this->objectid; 1019 1020 $permission->read = true; 1021 $permission->write = true; 1022 $permission->prop = true; 1023 $permission->delete = true; 1024 $permission->grant = true; 1025 1026 $permission->create_file = true; 1027 $permission->create_page = true; 1028 $permission->create_folder = true; 1029 $permission->create_link = true; 1030 1031 $permission->persist(); 1032 } 1033 } 1034 1035 1036 /** 1037 * Inherit permissions from parent folder. 1038 * 1039 * @return void 1040 */ 1041 private function inheritPermissions() { 1042 $parent = new BaseObject( $this->parentid ); 1043 1044 foreach( $parent->getAllAclIds() as $aclid ) 1045 { 1046 $permission = new Permission( $aclid ); 1047 $permission->load(); 1048 1049 if ( $permission->transmit ) // ACL is vererbbar, also kopieren. 1050 { 1051 $permission->aclid = null; 1052 $permission->objectid = $this->objectid; 1053 $permission->persist(); // ... und hinzufuegen. 1054 } 1055 } 1056 } 1057 1058 /** 1059 * Pruefung auf Gueltigkeit des Dateinamens 1060 */ 1061 private function checkFilename() 1062 { 1063 if ( empty($this->filename) ) 1064 $this->filename = $this->objectid; 1065 1066 if ( $this->isRoot() ) // Beim Root-Ordner ist es egal, es gibt nur einen. 1067 return; 1068 1069 if ( !$this->filenameIsUnique( $this->filename ) ) 1070 { 1071 // Append some string to filename. 1072 $this->filename = $this->filename.'-'.base_convert(time(), 10, 36); 1073 } 1074 } 1075 1076 1077 /** 1078 * Stellt fest, dass der Dateiname im aktuellen Ordner kein weiteres Mal vorkommt. 1079 * Dies muss vor dem Speichern geprüft werden, ansonsten erfolgt eine Index-Verletzung 1080 * und der Datensatz kann nicht gespeichert werde. 1081 * 1082 * @param $filename 1083 * @return bool 1084 */ 1085 private function filenameIsUnique( $filename ) 1086 { 1087 $sql = Db::sql( <<<SQL 1088 SELECT COUNT(*) FROM {{object}} 1089 WHERE parentid={parentid} AND filename={filename} 1090 AND NOT id = {objectid} 1091 SQL 1092 ); 1093 1094 $sql->setString('parentid', $this->parentid); 1095 $sql->setString('filename', $filename ); 1096 $sql->setString('objectid', $this->objectid); 1097 1098 1099 return( intval($sql->getOne()) == 0 ); 1100 } 1101 1102 1103 function getAllAclIds() 1104 { 1105 $db = \cms\base\DB::get(); 1106 1107 $sql = $db->sql( <<<'SQL' 1108 SELECT id FROM {{acl}} 1109 WHERE objectid={objectid} 1110 ORDER BY userid,groupid ASC 1111 SQL 1112 ); 1113 $sql->setInt('objectid' ,$this->objectid); 1114 1115 return $sql->getCol(); 1116 } 1117 1118 1119 /** 1120 * Ermitteln aller Berechtigungsstufen. 1121 */ 1122 function getRelatedAclTypes() 1123 { 1124 return( array('read','write','delete','prop','release','publish','create_folder','create_file','create_page','create_link','grant','transmit') ); 1125 } 1126 1127 1128 /** 1129 * Ermitteln aller Berechtigungsstufen. 1130 */ 1131 function getAssocRelatedAclTypes() 1132 { 1133 $types = array(); 1134 1135 foreach( $this->getRelatedAclTypes() as $t ) 1136 $types[$t] = true; 1137 1138 return $types; 1139 } 1140 1141 /** 1142 * Entfernen aller ACLs zu diesem Objekt 1143 * @access private 1144 */ 1145 private function deleteAllACLs() 1146 { 1147 foreach( $this->getAllAclIds() as $aclid ) 1148 { 1149 $permission = new Permission( $aclid ); 1150 $permission->load(); 1151 $permission->delete(); 1152 } 1153 } 1154 1155 1156 1157 /** 1158 * Reihenfolge-Sequenznr. dieses Objektes neu speichern 1159 * die Nr. wird sofort in der Datenbank gespeichert. 1160 * 1161 * @param Integer neue Sequenz-Nr. 1162 */ 1163 public function setOrderId( $orderid ) 1164 { 1165 $sql = Db::sql('UPDATE {{object}} '.' SET orderid={orderid}'.' WHERE id={objectid}'); 1166 $sql->setInt('objectid', $this->objectid); 1167 $sql->setInt('orderid', $orderid); 1168 1169 $sql->execute(); 1170 } 1171 1172 1173 /** 1174 * Reads all direct children of this object. 1175 */ 1176 protected function getChildren() 1177 { 1178 $stmt = Db::sql(<<<SQL 1179 1180 SELECT id FROM {{object}} 1181 WHERE parentid={objectid} 1182 ORDER BY orderid ASC 1183 SQL 1184 ); 1185 1186 $stmt->setInt( 'objectid' ,$this->objectid ); 1187 1188 return $stmt->getCol(); 1189 } 1190 1191 1192 /** 1193 * Reads all descendants. 1194 * 1195 */ 1196 public function getAllDescendantsIds() 1197 { 1198 $descendantIds = array(); 1199 1200 foreach( $this->getChildren() as $id ) 1201 { 1202 $descendantIds[] = $id; 1203 1204 $baseObject = new BaseObject( $id ); 1205 $descendantIds = array_merge( $descendantIds, $baseObject->getAllDescendantsIds() ); 1206 } 1207 1208 return $descendantIds; 1209 } 1210 /** 1211 * ?bergeordnete Objekt-ID dieses Objektes neu speichern 1212 * die Nr. wird sofort in der Datenbank gespeichert. 1213 * 1214 * @param Integer ?bergeordnete Objekt-ID 1215 */ 1216 public function setParentId( $parentid ) 1217 { 1218 1219 $descendantsIds = $this->getAllDescendantsIds(); 1220 1221 if ( in_array($parentid,$descendantsIds) || $parentid == $this->objectid ) 1222 throw new \LogicException('new parent may not be a descendant of this node.'); 1223 1224 $db = \cms\base\DB::get(); 1225 1226 $sql = $db->sql('UPDATE {{object}} '.' SET parentid={parentid}'.' WHERE id={objectid}'); 1227 $sql->setInt('objectid', $this->objectid); 1228 $sql->setInt('parentid', $parentid); 1229 1230 $sql->execute(); 1231 } 1232 1233 1234 /** 1235 * Get all References to this object 1236 * @return array 1237 */ 1238 public function getDependentObjectIds() 1239 { 1240 $stmt = DB::sql( <<<SQL 1241 1242 SELECT {{page}}.objectid FROM {{value}} 1243 LEFT JOIN {{pagecontent}} 1244 ON {{value}}.contentid = {{pagecontent}}.contentid 1245 LEFT JOIN {{page}} 1246 ON {{pagecontent}}.pageid = {{page}}.id 1247 WHERE linkobjectid={myobjectid1} 1248 UNION 1249 SELECT objectid FROM {{link}} 1250 WHERE link_objectid={myobjectid2} 1251 SQL 1252 ); 1253 $stmt->setInt( 'myobjectid1',$this->objectid ); 1254 $stmt->setInt( 'myobjectid2',$this->objectid ); 1255 1256 return $stmt->getCol(); 1257 } 1258 1259 1260 1261 1262 /** 1263 * Liefert die Link-Ids, die auf das aktuelle Objekt verweisen. 1264 * @return array Liste der gefundenen Objekt-IDs 1265 * @see BaseObject#getDependentObjectIds 1266 */ 1267 public function getLinksToMe() 1268 { 1269 $db = \cms\base\DB::get(); 1270 1271 $sql = $db->sql( 'SELECT objectid FROM {{link}} '. 1272 ' WHERE link_objectid={myid}' ); 1273 $sql->setInt ( 'myid' ,$this->objectid ); 1274 1275 return $sql->getCol(); 1276 } 1277 1278 private function getTypeid() 1279 { 1280 if ($this->isFolder) return self::TYPEID_FOLDER; 1281 if ($this->isFile ) return self::TYPEID_FILE; 1282 if ($this->isImage ) return self::TYPEID_IMAGE; 1283 if ($this->isText ) return self::TYPEID_TEXT; 1284 if ($this->isPage ) return self::TYPEID_PAGE; 1285 if ($this->isLink ) return self::TYPEID_LINK; 1286 if ($this->isUrl ) return self::TYPEID_URL; 1287 if ($this->isAlias ) return self::TYPEID_ALIAS; 1288 if ($this->isScript ) return self::TYPEID_SCRIPT; 1289 } 1290 1291 1292 /** 1293 * Local Settings. 1294 * 1295 * @return array 1296 */ 1297 public function getSettings() 1298 { 1299 $settings = YAML::parse($this->settings); 1300 1301 $resolver = new VariableResolver(); 1302 $resolver->namespaceSeparator = ':'; 1303 1304 // Resolve config variables. 1305 $resolver->addResolver('config', function ($var) { 1306 $conf = Configuration::Conf()->getConfig(); 1307 return ArrayUtils::getSubValue($conf,explode('.',$var) ); 1308 }); 1309 1310 $settings = $resolver->resolveVariablesInArray( $settings ); 1311 1312 return $settings; 1313 } 1314 1315 /** 1316 * Inherited Settings. 1317 * 1318 * @return array 1319 */ 1320 public function getTotalSettings() 1321 { 1322 $totalSettings = array(); 1323 1324 // cumulate settings of parent objects 1325 $parentIds = array_keys( $this->parentObjectFileNames(true, false) ); 1326 foreach( $parentIds as $id ) 1327 { 1328 $parentObject = new BaseObject( $id ); 1329 $parentObject->objectLoad(); 1330 $totalSettings = array_merge($totalSettings,$parentObject->getSettings()); 1331 } 1332 1333 // add settings from this base object. 1334 $totalSettings = array_merge($totalSettings,$this->getSettings()); 1335 1336 return $totalSettings; 1337 } 1338 1339 1340 1341 /** 1342 * Liefert alle übergeordneten Ordner. 1343 * 1344 * @param bool $with_root Mit Root-Folder? 1345 * @param bool $with_self Mit dem aktuellen Ordner? 1346 * @return array 1347 */ 1348 public function parentObjectFileNames( $with_root = false, $with_self = false ) 1349 { 1350 $foid = $this->objectid; 1351 $idCache = array(); 1352 1353 while( intval($foid)!=0 ) 1354 { 1355 $sql = Db::sql( <<<SQL 1356 1357 SELECT parentid,id,filename 1358 FROM {{object}} 1359 WHERE {{object}}.id={parentid} 1360 1361 SQL 1362 ); 1363 $sql->setInt('parentid' ,$foid ); 1364 1365 $row = $sql->getRow(); 1366 1367 if ( in_array($row['id'],$idCache)) 1368 throw new \LogicException('fatal: parent-rekursion in object-id: '.$this->objectid.', double-parent-id: '.$row['id']); 1369 else 1370 $idCache[] = $row['id']; 1371 1372 $this->addParentfolder( $row['id'],$row['filename'] ); 1373 $foid = $row['parentid']; 1374 } 1375 1376 1377 $this->checkParentFolders($with_root,$with_self); 1378 1379 return $this->parentfolders; 1380 } 1381 1382 public function parentObjectNames( $with_root = false, $with_self = false ) 1383 { 1384 $foid = $this->objectid; 1385 $idCache = array(); 1386 1387 while( intval($foid)!=0 ) 1388 { 1389 $sql = Db::sql( <<<SQL 1390 SELECT {{object}}.parentid,{{object}}.id,{{object}}.filename FROM {{object}} 1391 WHERE {{object}}.id={parentid} 1392 SQL 1393 ); 1394 $sql->setInt('parentid' ,$foid ); 1395 1396 $row = $sql->getRow(); 1397 1398 if ( in_array($row['id'],$idCache)) 1399 throw new \LogicException('fatal: parent-rekursion in object-id: '.$this->objectid.', double-parent-id: '.$row['id']); 1400 else 1401 $idCache[] = $row['id']; 1402 1403 $this->addParentfolder( $row['id'],$row['filename'] ); 1404 $foid = $row['parentid']; 1405 } 1406 1407 $this->checkParentFolders($with_root,$with_self); 1408 1409 return $this->parentfolders; 1410 } 1411 1412 1413 private function addParentFolder( $id,$filename='' ) 1414 { 1415 $name = $filename; 1416 1417 if ( empty($name) ) 1418 $name = "($id)"; 1419 1420 if ( intval($id) != 0 ) 1421 $this->parentfolders[ $id ] = $name; 1422 } 1423 1424 1425 private function checkParentFolders( $with_root, $with_self ) 1426 { 1427 // Reihenfolge umdrehen 1428 $this->parentfolders = array_reverse($this->parentfolders,true); 1429 1430 // Ordner ist bereits hoechster Ordner 1431 // if ( count($this->parentfolders) == 2 && $this->isRoot && $with_root && $with_self ) 1432 // { 1433 // array_pop ( $this->parentfolders ); 1434 // return; 1435 // } 1436 1437 1438 if ( !$with_root && !empty($this->parentfolders) ) 1439 { 1440 $keys = array_keys( $this->parentfolders ); 1441 unset( $this->parentfolders[$keys[0]] ); 1442 } 1443 1444 if ( !$with_self && !empty($this->parentfolders) ) 1445 { 1446 $keys = array_keys( $this->parentfolders ); 1447 unset( $this->parentfolders[$keys[count($keys)-1]] ); 1448 } 1449 } 1450 1451 1452 /** 1453 * Liefert das Projekt-Objekt. 1454 * 1455 * @return Project 1456 * @throws \util\exception\ObjectNotFoundException 1457 */ 1458 public function getProject() { 1459 return Project::create( $this->projectid ); 1460 } 1461 1462 1463 1464 1465 /** 1466 * Es werden Objekte mit einem bestimmten Namen ermittelt 1467 * @param String Suchbegriff 1468 * @return array Liste der gefundenen Objekt-IDs 1469 */ 1470 public static function getObjectIdsByFileName( $text ) 1471 { 1472 $db = \cms\base\DB::get(); 1473 1474 $sql = $db->sql( 'SELECT id FROM {{object}} '. 1475 ' WHERE filename LIKE {filename}'. 1476 ' ORDER BY lastchange_date DESC' ); 1477 $sql->setString( 'filename','%'.$text.'%' ); 1478 1479 return $sql->getCol(); 1480 } 1481 1482 1483 /** 1484 * Es werden Objekte mit einem Namen ermittelt 1485 * @param String Suchbegriff 1486 * @return array Liste der gefundenen Objekt-IDs 1487 */ 1488 public static function getObjectIdsByName( $text ) 1489 { 1490 $db = \cms\base\DB::get(); 1491 1492 $sql = $db->sql( 'SELECT {{object}}.id FROM {{object}} '. 1493 ' LEFT JOIN {{name}} '. 1494 ' ON {{object}}.id={{name}}.objectid'. 1495 ' WHERE {{name}}.name LIKE {name}'. 1496 ' ORDER BY lastchange_date DESC' ); 1497 $sql->setString( 'name' ,'%'.$text.'%' ); 1498 1499 return $sql->getCol(); 1500 } 1501 1502 1503 /** 1504 * Es werden Objekte mit einer Beschreibung ermittelt 1505 * @param String Suchbegriff 1506 * @return array Liste der gefundenen Objekt-IDs 1507 */ 1508 public static function getObjectIdsByDescription( $text ) 1509 { 1510 $db = \cms\base\DB::get(); 1511 1512 $sql = $db->sql( 'SELECT {{object}}.id FROM {{object}} '. 1513 ' LEFT JOIN {{name}} '. 1514 ' ON {{object}}.id={{name}}.objectid'. 1515 ' WHERE {{name}}.descr LIKE {desc}'. 1516 ' ORDER BY lastchange_date DESC' ); 1517 $sql->setString( 'desc' ,'%'.$text.'%' ); 1518 1519 return $sql->getCol(); 1520 } 1521 1522 1523 /** 1524 * Es werden Objekte mit einer UserId ermittelt 1525 * @param Integer Benutzer-Id der Erstellung 1526 * @return array Liste der gefundenen Objekt-IDs 1527 */ 1528 public static function getObjectIdsByCreateUserId( $userid ) 1529 { 1530 $db = \cms\base\DB::get(); 1531 1532 $sql = $db->sql( 'SELECT id FROM {{object}} '. 1533 ' WHERE create_userid={userid}'. 1534 ' ORDER BY lastchange_date DESC' ); 1535 $sql->setInt ( 'userid' ,$userid ); 1536 1537 return $sql->getCol(); 1538 } 1539 1540 1541 /** 1542 * Es werden Objekte mit einer UserId ermittelt 1543 * @param Integer Benutzer-Id der letzten ?nderung 1544 * @return array Liste der gefundenen Objekt-IDs 1545 */ 1546 public static function getObjectIdsByLastChangeUserId( $userid ) 1547 { 1548 $db = \cms\base\DB::get(); 1549 1550 $sql = $db->sql( 'SELECT id FROM {{object}} '. 1551 ' WHERE lastchange_userid={userid}'. 1552 ' ORDER BY lastchange_date DESC' ); 1553 $sql->setInt ( 'userid' ,$userid ); 1554 1555 return $sql->getCol(); 1556 } 1557 1558 1559 /** 1560 * Stellt fest, ob das Objekt gueltig ist. 1561 */ 1562 public function isValid() 1563 { 1564 $now = time(); 1565 1566 return 1567 ($this->validFromDate == null || $this->validFromDate < $now) && 1568 ($this->validToDate == null || $this->validToDate > $now); 1569 1570 } 1571 1572 public function __toString() 1573 { 1574 return 'Object-Id '.$this->objectid.' (type='.$this->getType().',filename='.$this->filename. ')'; 1575 } 1576 1577 1578 /** 1579 * Liefert alle Name-Objekte. 1580 * @return Name[] 1581 * @throws \util\exception\ObjectNotFoundException 1582 */ 1583 public function getNames() 1584 { 1585 $names = array(); 1586 1587 foreach( $this->getProject()->getLanguages() as $languageId=>$languageName ) 1588 { 1589 $name = new Name(); 1590 $name->objectid = $this->objectid; 1591 $name->languageid = $languageId; 1592 $name->load(); 1593 1594 $names[] = $name; 1595 } 1596 1597 return $names; 1598 } 1599 1600 1601 /** 1602 * Liefert alle Name-Objekte. 1603 * @return Name 1604 * @throws \util\exception\ObjectNotFoundException 1605 */ 1606 public function getNameForLanguage( $languageId ) 1607 { 1608 $name = new Name(); 1609 $name->objectid = $this->objectid; 1610 $name->languageid = $languageId; 1611 $name->load(); 1612 1613 return $name; 1614 } 1615 1616 1617 /** 1618 * @return Name 1619 */ 1620 public function getDefaultName() 1621 { 1622 $languageId = $this->getProject()->getDefaultLanguageId(); 1623 1624 $defaultName = $this->getNameForLanguage( $languageId ); 1625 1626 if ( ! $defaultName->name ) 1627 $defaultName->name = $this->filename; 1628 1629 return $defaultName; 1630 } 1631 1632 1633 /** 1634 * Name of the object. If not exist, the filename will be used. 1635 * @return string Name 1636 */ 1637 public function getName() 1638 { 1639 $name = $this->getDefaultName()->name; 1640 1641 if ( empty($name)) 1642 $name = $this->filename; 1643 1644 return $name; 1645 } 1646 1647 1648 /** 1649 * Speichert Namen und Beschreibung für alle Sprachen. Das ist bei der Neuanlage von Objekten ganz praktisch. 1650 * 1651 * @param $nam string 1652 * @param $description string 1653 */ 1654 public function setNameForAllLanguages($nam, $description) 1655 { 1656 foreach( $this->getProject()->getLanguages() as $languageId=>$languageName ) 1657 { 1658 $name = new Name(); 1659 $name->objectid = $this->objectid; 1660 $name->languageid = $languageId; 1661 $name->load(); 1662 1663 $name->name = $nam; 1664 $name->description = $description; 1665 1666 $name->persist(); 1667 } 1668 1669 } 1670 1671 1672 /** 1673 * Returns the effective alias. If no alias exists, the actual object is returned. 1674 * 1675 * @return BaseObject 1676 */ 1677 public function getEffectiveAlias() { 1678 1679 $alias = $this->getAlias(); 1680 if ( $alias ) 1681 return $alias; 1682 else 1683 return $this; 1684 } 1685 1686 1687 1688 /** 1689 * The Alias for this Object or <code>null</code>. 1690 * 1691 * @return Alias|null 1692 * @deprecated use #getAliasForLanguage 1693 */ 1694 public function getAlias() 1695 { 1696 $alias = $this->getAliasForLanguage( $this->getProject()->getDefaultLanguageId() ); 1697 1698 if ( !$alias->isPersistent() ) 1699 $alias = $this->getAliasForLanguage( null ); 1700 1701 if ( !$alias->isPersistent() ) 1702 return null; // no alias found 1703 1704 return $alias; 1705 } 1706 1707 1708 /** 1709 * Creates an Alias for a specific language. 1710 * @param int $languageid could be null for the default alias. 1711 * @return Alias 1712 * @throws \util\exception\ObjectNotFoundException 1713 */ 1714 public function getAliasForLanguage( $languageid ) 1715 { 1716 $alias = new Alias(); 1717 $alias->projectid = $this->projectid; 1718 $alias->linkedObjectId = $this->objectid; 1719 $alias->languageid = $languageid; 1720 $alias->load(); 1721 1722 return $alias; 1723 } 1724 1725 1726 1727 public function isPersistent() 1728 { 1729 return intval( $this->objectid ) > 0; 1730 } 1731 1732 1733 /** 1734 * Gets the file size 1735 * @return int 1736 */ 1737 public function getSize() 1738 { 1739 return 0; 1740 } 1741 1742 1743 public function mimeType() 1744 { 1745 return ""; 1746 } 1747 1748 1749 public function getId() 1750 { 1751 return $this->objectid; 1752 } 1753 1754 1755 public function copyNamesFrom($sourceObjectId ) { 1756 1757 $sourceObject = new BaseObject( $sourceObjectId ); 1758 foreach ( $sourceObject->getNames() as $name ) { 1759 1760 if ( $name->isPersistent() ) { 1761 1762 $copiedName = new Name(); 1763 $copiedName->name = $name->name; 1764 $copiedName->description = $name->description; 1765 $copiedName->languageid = $name->languageid; 1766 $copiedName->objectid = $this->objectid; 1767 $copiedName->persist(); 1768 } 1769 } 1770 } 1771 } 1772 1773 1774
Download modules/cms/model/BaseObject.class.php
History Sun, 8 Dec 2024 20:56:47 +0100 Jan Dankert New: Users are now able to store bookmarks. Thu, 16 Feb 2023 22:57:35 +0100 Jan Dankert New: More functions (adding, deleting) for tags. Thu, 16 Feb 2023 01:04:38 +0100 Jan Dankert New: Tags for base objects. Tue, 14 Feb 2023 00:23:13 +0100 Jan Dankert New filters: Robots (for robots.txt) and Sitemap. Sun, 29 Jan 2023 00:20:21 +0100 Jan Dankert New node type "Script". Sat, 25 Jun 2022 14:26:33 +0200 Jan Dankert New: Many Enhancements for the internal script language: More access to the data structure of pages, folders, templates, ... Sun, 5 Jun 2022 22:14:24 +0200 Jan Dankert Some fixups: New Icons; better support classes for DSL. 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. Mon, 7 Feb 2022 21:44:42 +0100 dankert New: Authenticate API users with the HTTP authorization header. Mon, 6 Dec 2021 22:33:10 +0100 dankert Some fixes for deleting objects. 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'. Fri, 3 Dec 2021 23:27:44 +0100 dankert New: Only allowed methods are shown in the dropdown menu; Some security enhancements. Wed, 17 Nov 2021 23:39:22 +0100 Jan Dankert Fix: Reading descendent pages with the content id. Tue, 9 Nov 2021 01:21:55 +0100 Jan Dankert Fix: iconv is broken on alpine 3. Tue, 9 Mar 2021 09:17:27 +0100 Jan Dankert New: Show all links ('references') to the current object. Sun, 7 Mar 2021 00:10:20 +0100 Jan Dankert Refactoring: Hopefully more performance while accessing the database resultsets. Sat, 6 Mar 2021 02:50:20 +0100 Jan Dankert New: Enable actions for guest users. Sat, 6 Mar 2021 02:31:06 +0100 Jan Dankert Fix: Inheriting rights was missing. Sat, 6 Mar 2021 02:09:25 +0100 Jan Dankert New: Allow permissions for guests only. Mon, 4 Jan 2021 23:14:09 +0100 Jan Dankert New: Groups may contain subgroups. Users within a group inherit the permissions of all parent groups. 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. 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 00:12:44 +0100 Jan Dankert Fixing Pagelement-History and Diff. Sun, 1 Nov 2020 03:08:55 +0100 Jan Dankert Replaced the calls to "Configuration::rawConfig()" with the OO style calls; Cleanup LoginAction. Sun, 1 Nov 2020 00:36:50 +0100 Jan Dankert Refactoring: Only using the configuration object. Wed, 21 Oct 2020 23:32:47 +0200 Jan Dankert Load the objects before using attributes. Fri, 2 Oct 2020 23:11:48 +0200 Jan Dankert Cleanup: No '.inputholder' any more, notices with links to objects. Tue, 29 Sep 2020 22:17:11 +0200 Jan Dankert Refactoring: Do not use global constants. Sat, 26 Sep 2020 18:46:36 +0200 Jan Dankert Now compatible with PHP 5.4 again. Sat, 26 Sep 2020 12:20:43 +0200 Jan Dankert Refactoring: No global variables like $SESS any more. All constants are capsulated by classes. Sat, 26 Sep 2020 10:32:02 +0200 Jan Dankert Refactoring: No global $conf array any more. 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. 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. Wed, 13 May 2020 23:29:44 +0200 Jan Dankert Refactoring: New Variable Resolver with support for namespaces, default values and nested value expressions. Sun, 23 Feb 2020 04:01:30 +0100 Jan Dankert Refactoring with Namespaces for the cms modules, part 1: moving.