openrat-cms

# OpenRat Content Management System
git clone http://git.code.weiherhei.de/openrat-cms.git
Log | Files | Refs

BaseObject.class.php (50373B)


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