File modules/cms/model/Project.class.php
Last commit: Tue Oct 13 18:49:59 2026 +0200 Jan Dankert New: Another action which returns an object instead of single output values. This should be the future, but it's a long way to refactore all old action methods...
1 <?php 2 3 namespace cms\model; 4 5 use cms\base\DB; 6 use database\Database; 7 use logger\Logger; 8 use util\FileUtils; 9 use util\Request; 10 use util\Session; 11 12 13 /** 14 * Darstellen eines Projektes 15 * 16 * @author Jan Dankert 17 * @package openrat.objects 18 */ 19 class Project extends ModelBase 20 { 21 22 const FLAG_CUT_INDEX = 1; 23 const FLAG_CONTENT_NEGOTIATION = 2; 24 const FLAG_PUBLISH_FILE_EXTENSION = 4; 25 const FLAG_PUBLISH_PAGE_EXTENSION = 8; 26 const FLAG_LINK_ABSOLUTE = 16; 27 28 // Eigenschaften 29 public $projectid; 30 public $name; 31 public $target_dir; 32 public $ftp_url; 33 34 /** 35 * Hostname 36 * @var string 37 */ 38 public $url; 39 40 public $ftp_passive; 41 public $cmd_after_publish; 42 43 44 /** 45 * @var boolean 46 */ 47 public $content_negotiation = false; 48 49 /** 50 * Should links to index pages contain the filename? 51 * 52 * @var boolean 53 */ 54 public $cut_index = false; 55 56 /** 57 * Link to files with extension 58 * 59 * @var boolean 60 */ 61 public $publishFileExtension = true; 62 63 /** 64 * link to pages with extension 65 * @var boolean 66 */ 67 public $publishPageExtension = true; 68 69 public $linkAbsolute; 70 71 72 73 // Konstruktor 74 public function __construct( $projectid='' ) 75 { 76 if ( intval($projectid) != 0 ) 77 $this->projectid = $projectid; 78 } 79 80 81 private static $cache = array(); 82 83 /** 84 * @param $projectid 85 * @return Project 86 * @throws \util\exception\ObjectNotFoundException 87 */ 88 public static function create($projectid) 89 { 90 if ( empty( Project::$cache[ $projectid ] ) ) 91 { 92 $project = new Project( $projectid ); 93 94 Project::$cache[ $projectid ] = $project->load(); 95 } 96 return Project::$cache[ $projectid ]; 97 } 98 99 100 /** 101 * Stellt fest, ob die angegebene Projekt-Id existiert. 102 * @param $id int Projekt-Id 103 * @return boolean 104 * 105 */ 106 public function isAvailable($id ) 107 { 108 $db = \cms\base\DB::get(); 109 110 $sql = $db->sql('SELECT 1 FROM {{project}} '. 111 ' WHERE id={id}'); 112 $sql->setInt('id' ,$id ); 113 114 return intval($sql->getOne()) == 1; 115 } 116 117 118 /** 119 * Liefert alle verf?gbaren Projekte. 120 * @return array 121 */ 122 public static function getAllProjects() 123 { 124 $db = \cms\base\DB::get(); 125 $sql = $db->sql( 'SELECT id,name FROM {{project}} '. 126 ' ORDER BY name' ); 127 128 return $sql->getAssoc(); 129 } 130 131 132 // Liefert alle verf?gbaren Projekt-Ids 133 public function getAllProjectIds() 134 { 135 $db = \cms\base\DB::get(); 136 $sql = $db->sql( 'SELECT id FROM {{project}} '. 137 ' ORDER BY name' ); 138 139 return $sql->getCol(); 140 } 141 142 143 /** 144 * Liefert die Sprachen des Projektes. 145 * 146 * @return array Id->Name 147 */ 148 public function getLanguages() 149 { 150 $db = \cms\base\DB::get(); 151 152 $sql = $db->sql( 'SELECT id,name FROM {{language}}'. 153 ' WHERE projectid={projectid} '. 154 ' ORDER BY name' ); 155 $sql->setInt ('projectid',$this->projectid); 156 157 return $sql->getAssoc(); 158 } 159 160 161 /** 162 * Liefert die Sprachen des Projektes. 163 * 164 * @return Language[] 165 */ 166 public function getLanguageList() : array 167 { 168 $db = DB::get(); 169 170 $sql = $db->sql( <<<SQL 171 SELECT id FROM {{language}} 172 WHERE projectid={projectid} 173 ORDER BY name 174 SQL ); 175 $sql->setInt ('projectid',$this->projectid); 176 177 return array_map( function ($languageId) { 178 return new Language($languageId); 179 }, $sql->getCol()); 180 } 181 182 183 184 /** 185 * Get all tags 186 * @return array 187 */ 188 public function getTags() 189 { 190 $sql = Db::sql( <<<SQL 191 SELECT id,name 192 FROM {{tag}} 193 WHERE projectid = {projectid} 194 ORDER BY name 195 SQL 196 ); 197 $sql->setInt('projectid',$this->projectid); 198 199 return $sql->getAssoc(); 200 } 201 202 203 204 205 /** 206 * Liefert die Sprachen des Projektes. 207 * 208 * @return array Id->Name 209 */ 210 public function getLanguageISOCodes() 211 { 212 $db = \cms\base\DB::get(); 213 214 $sql = $db->sql( 'SELECT id,isocode FROM {{language}}'. 215 ' WHERE projectid={projectid} '. 216 ' ORDER BY isocode' ); 217 $sql->setInt ('projectid',$this->projectid); 218 219 return $sql->getAssoc(); 220 } 221 222 223 /** 224 * @return int[] 225 */ 226 public function getLanguageIds() 227 { 228 return array_keys( $this->getLanguages() ); 229 } 230 231 232 /** 233 * Liefert die Projektmodelle als Array mit ID->Name. 234 * 235 * @return array 236 */ 237 public function getModels() 238 { 239 $db = \cms\base\DB::get(); 240 241 $sql = $db->sql( 'SELECT id,name FROM {{projectmodel}}'. 242 ' WHERE projectid= {projectid} '. 243 ' ORDER BY name' ); 244 $sql->setInt ('projectid',$this->projectid); 245 246 return $sql->getAssoc(); 247 } 248 249 250 public function getModelIds() 251 { 252 return array_keys( $this->getModels() ); 253 } 254 255 256 public function getTemplateIds() 257 { 258 $db = \cms\base\DB::get(); 259 260 $sql = $db->sql( 'SELECT id FROM {{template}}'. 261 ' WHERE projectid= {projectid} ' ); 262 $sql->setInt ('projectid',$this->projectid); 263 264 return $sql->getCol(); 265 } 266 267 268 public function getTemplates() 269 { 270 $sql = Db::sql( 'SELECT id,name FROM {{template}}'. 271 ' WHERE projectid= {projectid} ' ); 272 $sql->setInt ('projectid',$this->projectid); 273 274 return $sql->getAssoc(); 275 } 276 277 278 /** 279 * Ermitteln des Wurzel-Ordners fuer dieses Projekt. 280 * 281 * Der Wurzelordner ist der einzige Ordnerhat in diesem 282 * Projekt, der kein Elternelement besitzt. 283 * 284 * @return Objekt-Id des Wurzelordners 285 */ 286 public function getRootObjectId() 287 { 288 $db = \cms\base\DB::get(); 289 290 $sql = $db->sql('SELECT id FROM {{object}}'. 291 ' WHERE parentid IS NULL'. 292 ' AND projectid={projectid}' ); 293 294 $sql->setInt('projectid',$this->projectid); 295 296 return( $sql->getOne() ); 297 } 298 299 300 301 // Laden 302 303 /** 304 * @throws \util\exception\ObjectNotFoundException 305 */ 306 public function load() 307 { 308 $sql = Db::sql( 'SELECT * FROM {{project}} '. 309 ' WHERE id={projectid}' ); 310 $sql->setInt( 'projectid',$this->projectid ); 311 312 $row = $sql->getRow(); 313 314 if ( empty($row) ) 315 throw new \util\exception\ObjectNotFoundException('project '.$this->projectid.' not found'); 316 317 $this->name = $row['name' ]; 318 $this->url = $row['url' ]; 319 $this->target_dir = $row['target_dir' ]; 320 $this->ftp_url = $row['ftp_url' ]; 321 $this->ftp_passive = $row['ftp_passive' ]; 322 $this->cmd_after_publish = $row['cmd_after_publish' ]; 323 $this->cut_index = $row['flags']&self::FLAG_CUT_INDEX; 324 $this->content_negotiation = $row['flags']&self::FLAG_CONTENT_NEGOTIATION; 325 $this->publishFileExtension = $row['flags']&self::FLAG_PUBLISH_FILE_EXTENSION; 326 $this->publishPageExtension = $row['flags']&self::FLAG_PUBLISH_PAGE_EXTENSION; 327 $this->linkAbsolute = $row['flags']&self::FLAG_LINK_ABSOLUTE; 328 329 return $this; 330 } 331 332 333 334 // Speichern 335 public function save() 336 { 337 $stmt = DB::sql( <<<SQL 338 UPDATE {{project}} 339 SET name = {name}, 340 target_dir = {target_dir}, 341 ftp_url = {ftp_url}, 342 ftp_passive = {ftp_passive}, 343 url = {url}, 344 flags = {flags}, 345 cmd_after_publish = {cmd_after_publish} 346 WHERE id= {projectid} 347 SQL 348 ); 349 350 $stmt->setString('ftp_url' ,$this->ftp_url ); 351 $stmt->setString('url' ,$this->url ); 352 $stmt->setString('name' ,$this->name ); 353 $stmt->setString('target_dir' ,$this->target_dir ); 354 $stmt->setInt ('ftp_passive' ,$this->ftp_passive ); 355 $stmt->setString('cmd_after_publish' ,$this->cmd_after_publish ); 356 357 $flags = 0; 358 if( $this->cut_index ) $flags |= self::FLAG_CUT_INDEX; 359 if( $this->content_negotiation ) $flags |= self::FLAG_CONTENT_NEGOTIATION; 360 if( $this->publishFileExtension) $flags |= self::FLAG_PUBLISH_FILE_EXTENSION; 361 if( $this->publishPageExtension) $flags |= self::FLAG_PUBLISH_PAGE_EXTENSION; 362 if( $this->linkAbsolute ) $flags |= self::FLAG_LINK_ABSOLUTE; 363 364 $stmt->setInt ('flags' ,$flags ); 365 $stmt->setInt ('projectid' ,$this->projectid ); 366 367 $stmt->execute(); 368 369 try 370 { 371 $rootFolder = new Folder( $this->getRootObjectId() ); 372 $rootFolder->load(); 373 $rootFolder->filename = $this->name; 374 $rootFolder->save(); 375 } 376 catch( \Exception $e ) 377 { 378 Logger::warn('Project '.$this->projectid.' has not a root folder'."\n".$e->getTraceAsString()); 379 } 380 } 381 382 383 /** 384 * Liefert alle Eigenschaften des Projektes. 385 */ 386 public function getProperties() 387 { 388 return parent::getProperties(); 389 } 390 391 392 /** 393 * Add a project to the database. 394 */ 395 public function add() 396 { 397 $db = \cms\base\DB::get(); 398 399 $sql = $db->sql('SELECT MAX(id) FROM {{project}}'); 400 $this->projectid = intval($sql->getOne())+1; 401 402 403 // Projekt hinzuf?gen 404 $sql = $db->sql( 'INSERT INTO {{project}} (id,name,target_dir,ftp_url,ftp_passive,cmd_after_publish,flags) '. 405 " VALUES( {projectid},{name},'','',0,'',0 ) " ); 406 $sql->setInt ('projectid',$this->projectid ); 407 $sql->setString('name' ,$this->name ); 408 409 $sql->execute(); 410 411 // Every projects needs a root folder. The root folder has no parent. 412 $folder = new Folder(); 413 $folder->projectid = $this->projectid; 414 $folder->filename = $this->name; 415 $folder->persist(); 416 } 417 418 419 // Projekt aus Datenbank entfernen 420 public function delete() 421 { 422 $db = \cms\base\DB::get(); 423 424 // Root-Ordner rekursiv samt Inhalten loeschen 425 $folder = new Folder( $this->getRootObjectId() ); 426 $folder->deleteAll(); 427 428 429 foreach( $this->getLanguageIds() as $languageid ) 430 { 431 $language = new Language( $languageid ); 432 $language->delete(); 433 } 434 435 436 foreach( $this->getTemplateIds() as $templateid ) 437 { 438 $template = new Template( $templateid ); 439 $template->delete(); 440 } 441 442 443 foreach( $this->getModelIds() as $modelid ) 444 { 445 $model = new Model( $modelid ); 446 $model->delete(); 447 } 448 449 450 // Deleting the project 451 $sql = $db->sql( 'DELETE FROM {{project}}'. 452 ' WHERE id= {projectid} ' ); 453 $sql->setInt( 'projectid',$this->projectid ); 454 $sql->execute(); 455 } 456 457 458 /** 459 * Liefert die Standard-Sprach-Id. If there is no default language, the first language-id will be used. 460 * @return String 461 */ 462 public function getDefaultLanguageId() 463 { 464 // ORDER BY deswegen, damit immer mind. eine Sprache 465 // gelesen wird 466 $sql = \cms\base\Db::sql( 'SELECT id FROM {{language}} '. 467 ' WHERE projectid={projectid}'. 468 ' ORDER BY is_default DESC, name ASC' ); 469 470 $sql->setInt('projectid',$this->projectid ); 471 472 return $sql->getOne(); 473 } 474 475 476 public function getDefaultModelId() 477 { 478 // ORDER BY deswegen, damit immer mind. eine Sprache 479 // gelesen wird 480 $sql = \cms\base\Db::sql( 'SELECT id FROM {{projectmodel}} '. 481 ' WHERE projectid={projectid}'. 482 ' ORDER BY is_default DESC' ); 483 $sql->setInt('projectid',$this->projectid ); 484 485 return $sql->getOne(); 486 } 487 488 489 490 /** 491 * Entfernt nicht mehr notwendige Inhalte aus dem Archiv. 492 */ 493 public function checkLimit() 494 { 495 // not necessary any more. 496 // this is done while saving a value! 497 } 498 499 500 501 /** 502 * Testet die Integrität der Datenbank. 503 * 504 * @return array activities (empty if nothing bad found) 505 */ 506 public function checkLostFiles() 507 { 508 $log = array(); 509 510 // Ordnerstruktur prüfen. 511 $stmt = \cms\base\Db::sql( <<<EOF 512 SELECT thistab.id FROM {{object}} AS thistab 513 LEFT JOIN {{object}} AS parenttab 514 ON parenttab.id = thistab.parentid 515 WHERE thistab.projectid={projectid} AND thistab.parentid IS NOT NULL AND parenttab.id IS NULL 516 EOF 517 ); 518 $stmt->setInt('projectid',$this->projectid); 519 520 $idList = $stmt->getCol(); 521 522 if ( count( $idList ) > 0 ) 523 { 524 $lostAndFoundFolder = new Folder(); 525 $lostAndFoundFolder->projectid = $this->projectid; 526 $lostAndFoundFolder->filename = "lostandfound"; 527 $lostAndFoundFolder->parentid = $this->getRootObjectId(); 528 $lostAndFoundFolder->persist(); 529 530 foreach( $idList as $id ) 531 { 532 $log[] = 'Lost file! Moving '.$id.' to lost+found.'; 533 $obj = new BaseObject( $id ); 534 $obj->setParentId( $lostAndFoundFolder->objectid ); 535 } 536 } 537 538 539 // Prüfe, ob die Verbindung Projekt->Template->Templatemodell->Projectmodell->Projekt konsistent ist. 540 $stmt = \cms\base\Db::sql( <<<EOF 541 SELECT DISTINCT projectid FROM {{projectmodel}} WHERE id IN (SELECT projectmodelid from {{templatemodel}} WHERE templateid in (SELECT id from {{template}} WHERE projectid={projectid})) 542 EOF 543 ); 544 $stmt->setInt('projectid',$this->projectid); 545 546 $idList = $stmt->getCol(); 547 548 if ( count( $idList ) > 1 ) 549 { 550 Logger::warn('Inconsistence found: Reference circle project<->template<->templatemodel<->projectmodel<->project is not consistent.'); 551 $log[] = 'Inconsistence found: Reference circle project<->template<->templatemodel<->projectmodel<->project is not consistent.'; 552 } 553 554 return $log; 555 } 556 557 558 559 /** 560 * Kopiert ein Projekt von einer Datenbank zu einer anderen.<br> 561 * <br> 562 * Alle Projektinhalte werden kopiert, die Fremdschluesselbeziehungen werden entsprechend angepasst.<br> 563 * <br> 564 * Alle Beziehungen zu Benutzern, z.B. "Zuletzt geaendert von", "angelegt von" sowie<br> 565 * alle Berechtigungsinformationen gehen verloren!<br> 566 * 567 * @param string $dbid_destination ID der Ziel-Datenbank 568 * @param string $name 569 */ 570 public function copy( $dbid_destination,$name='' ) 571 { 572 Logger::debug( 'Copying project '.$this->name.' to database '.$dbid_destination ); 573 574 $conf = \cms\base\Configuration::rawConfig(); 575 $zeit = date('Y-m-d\TH:i:sO'); 576 577 $db_src = \cms\base\DB::get(); 578 $db_dest = new Database( $conf['database'][$dbid_destination] ); 579 $db_dest->id = $dbid_destination; 580 $db_dest->start(); 581 582 $sameDB = ( $db_dest->id == $db_src->id ); 583 584 // ------------------------------------------------------- 585 $mapping = array(); 586 $ids = array('project' => array('foreign_keys'=>array(), 587 'primary_key' =>'id', 588 'unique_idx' =>'name', 589 'erase' =>array() 590 ), 591 'language' => array('foreign_keys'=>array('projectid'=>'project'), 592 'primary_key' =>'id' 593 ), 594 'projectmodel' => array('foreign_keys'=>array('projectid'=>'project'), 595 'primary_key' =>'id' 596 ), 597 'template' => array('foreign_keys'=>array('projectid'=>'project'), 598 'primary_key' =>'id' 599 ), 600 'object' => array('foreign_keys'=>array('projectid' =>'project' ), 601 'self_key' =>'parentid', 602 'primary_key' =>'id', 603 'erase' =>array('create_userid','lastchange_userid') 604 ), 605 'element' => array('foreign_keys'=>array('templateid' =>'template', 606 'folderobjectid' =>'object', 607 'default_objectid'=>'object' ), 608 'primary_key' =>'id' 609 ), 610 'templatemodel'=> array('foreign_keys'=>array('projectmodelid'=>'projectmodel', 611 'templateid' =>'template' ), 612 'primary_key' =>'id', 613 'replace' =>array('text'=>'element') 614 ), 615 'name' => array('foreign_keys'=>array('objectid' =>'object', 616 'languageid'=>'language' ), 617 'primary_key' =>'id' 618 ), 619 'page' => array('foreign_keys'=>array('objectid' =>'object', 620 'templateid'=>'template' ), 621 'primary_key' =>'id' 622 ), 623 'value' => array('foreign_keys'=>array('pageid' =>'page', 624 'languageid'=>'language', 625 'elementid'=>'element', 626 'linkobjectid'=>'object' ), 627 'erase' =>array('lastchange_userid'), 628 'replace' =>array('text'=>'object'), 629 'primary_key' =>'id' 630 ), 631 'link' => array('foreign_keys'=>array('objectid' =>'object', 632 'link_objectid'=>'object' ), 633 'primary_key' =>'id' 634 ), 635 'folder' => array('foreign_keys'=>array('objectid' =>'object' ), 636 'primary_key' =>'id' 637 ), 638 'file' => array('foreign_keys'=>array('objectid' =>'object' ), 639 'primary_key' =>'id', 640 'binary' =>'value' 641 ), 642 643 ); 644 645 if ( $sameDB ) 646 $ids['acl'] = array('foreign_keys'=>array('objectid' => 'object', 647 'languageid' => 'language' ), 648 'primary_key' =>'id' 649 ); 650 651 foreach( $ids as $tabelle=>$data ) 652 { 653 Logger::debug( 'Copying table '.$tabelle.' ...' ); 654 $mapping[$tabelle] = array(); 655 $idcolumn = $data['primary_key']; 656 657 // Naechste freie Id in der Zieltabelle ermitteln. 658 $stmt = $db_dest->sql( 'SELECT MAX('.$idcolumn.') FROM {t_'.$tabelle.'}'); 659 $maxid = intval($stmt->getOne()); 660 $nextid = $maxid; 661 662 // Zu �bertragende IDs ermitteln. 663 if ( count($data['foreign_keys'])==0 ) 664 { 665 $where = ' WHERE id='.$this->projectid; 666 } 667 else 668 { 669 foreach( $data['foreign_keys'] as $fkey_column=>$target_tabelle ) 670 { 671 $where = ' WHERE '.$fkey_column.' IN ('.join(array_keys($mapping[$target_tabelle]),',').')'; 672 break; 673 } 674 } 675 $stmt = $db_src->sql( 'SELECT '.$idcolumn.' FROM {t_'.$tabelle.'} '.$where); 676 677 foreach( $stmt->getCol() as $srcid ) 678 { 679 Logger::debug('Id '.$srcid.' of table '.$tabelle); 680 $mapping[$tabelle][$srcid] = ++$nextid; 681 682 $stmt = $db_src->sql( 'SELECT * FROM {t_'.$tabelle.'} WHERE id={id}'); 683 $stmt->setInt('id',$srcid); 684 $row = $stmt->getRow(); 685 686 // Wert des Prim�rschl�ssels �ndern. 687 $row[$idcolumn] = $mapping[$tabelle][$srcid]; 688 689 // Fremdschl�sselbeziehungen auf neue IDn korrigieren. 690 foreach( $data['foreign_keys'] as $fkey_column=>$target_tabelle) 691 { 692 Logger::debug($fkey_column.' '.$target_tabelle.' '.$row[$fkey_column]); 693 694 if ( intval($row[$fkey_column]) != 0 ) 695 $row[$fkey_column] = $mapping[$target_tabelle][$row[$fkey_column]]; 696 } 697 698 foreach( array_keys($row) as $key ) 699 { 700 if ( isset($data['unique_idx']) && $key == $data['unique_idx'] ) 701 { 702 // Nachschauen, ob es einen UNIQUE-Key in der Zieltabelle schon gibt. 703 $stmt = $db_dest->sql( 'SELECT 1 FROM {t_'.$tabelle.'} WHERE '.$key."='".$row[$key]."'"); 704 705 if ( intval($stmt->getOne()) == 1 ) 706 $row[$key] = $row[$key].$zeit; 707 708 } 709 710 if ( !$sameDB && isset($data['erase']) && in_array($key,$data['erase']) ) 711 $row[$key] = null; 712 713 if ( isset($data['self_key']) && $key == $data['self_key'] && intval($row[$key]) > 0 ) 714 $row[$key] = $row[$key]+$maxid; 715 } 716 717 if ( isset($data['replace']) ) 718 { 719 foreach( $data['replace'] as $repl_column=>$repl_tabelle) 720 foreach( $mapping[$repl_tabelle] as $oldid=>$newid) 721 { 722 $row[$repl_column] = str_replace('{'.$oldid.'}','{'.$newid.'}' ,$row[$repl_column]); 723 $row[$repl_column] = str_replace('"'.$oldid.'"','"'.$newid.'"' ,$row[$repl_column]); 724 $row[$repl_column] = str_replace('->'.$oldid ,'->"'.$newid.'"',$row[$repl_column]); 725 } 726 } 727 728 if ( isset($data['binary']) ) 729 { 730 if ( !$db_src->conf['base64'] && $db_dest->conf['base64'] ) 731 $row[$data['binary']] = base64_encode($row[$data['binary']]); 732 elseif ( $db_src->conf['base64'] && !$db_dest->conf['base64'] ) 733 $row[$data['binary']] = base64_decode($row[$data['binary']]); 734 } 735 736 // Daten in Zieltabelle einf�gen. 737 $stmt = $db_dest->sql( 'INSERT INTO {t_'.$tabelle.'} ('.join(array_keys($row),',').') VALUES({'.join(array_keys($row),'},{').'})',$dbid_destination); 738 foreach( $row as $key=>$value ) 739 { 740 if ( !$sameDB && isset($data['erase']) && in_array($key,$data['erase']) ) 741 $stmt->setNull($key); 742 else 743 { 744 if(is_bool($value)) 745 $stmt->setBoolean($key,$value); 746 elseif(is_int($value)) 747 $stmt->setInt($key,$value); 748 elseif(is_string($value)) 749 $stmt->setString($key,$value); 750 } 751 } 752 //$sql = $db->sql( 'INSERT INTO {t_'.$tabelle.'} ('.join(array_keys($row),',').') VALUES('.join($row,',').')',$dbid_destination); 753 $stmt->execute(); 754 } 755 756 if ( isset($data['self_key']) ) 757 { 758 foreach( $mapping[$tabelle] as $oldid=>$newid ) 759 { 760 $stmt = $db_dest->sql( 'UPDATE {t_'.$tabelle.'} SET '.$data['self_key'].'='.$newid.' WHERE '.$data['self_key'].'='.($oldid+$maxid),$dbid_destination ); 761 $stmt->execute(); 762 } 763 } 764 } 765 766 Logger::debug( 'Finished copying project' ); 767 768 $db_dest->commit(); 769 } 770 771 772 773 /** 774 * Ermittelt die Anzahl aller Objekte in diesem Projekt. 775 * @return int Anzahl 776 */ 777 public function countObjects() 778 { 779 $db = \cms\base\DB::get(); 780 $sql = $db->sql( 'SELECT COUNT(*) FROM {{object}} '. 781 ' WHERE projectid = {projectid}' ); 782 $sql->setInt( 'projectid', $this->projectid ); 783 784 return $sql->getOne(); 785 786 } 787 788 789 790 /** 791 * Ermittelt die Gr��e aller Dateien in diesem Projekt. 792 * @return int Summe aller Dateigroessen 793 */ 794 public function size() 795 { 796 $db = \cms\base\DB::get(); 797 798 $sql = $db->sql( <<<SQL 799 SELECT SUM(size) FROM {{file}} 800 LEFT JOIN {{object}} 801 ON {{file}}.objectid = {{object}}.id 802 WHERE projectid = {projectid} 803 SQL 804 ); 805 $sql->setInt( 'projectid', $this->projectid ); 806 807 return $sql->getOne(); 808 } 809 810 811 812 /** 813 * Liefert alle verf?gbaren Projekt-Ids 814 */ 815 public function info() 816 { 817 $info = array(); 818 819 $info['count_objects'] = $this->countObjects(); 820 $info['sum_filesize' ] = $this->size(); 821 822 823 return $info; 824 } 825 826 827 828 829 /** 830 * Ermittelt projektübergreifend die letzten Änderungen des angemeldeten Benutzers. 831 * 832 * @return array <string, unknown> 833 */ 834 public function getMyLastChanges() 835 { 836 837 $db = \cms\base\DB::get(); 838 839 840 $sql = $db->sql( <<<SQL 841 SELECT {{object}}.id as objectid, 842 {{object}}.filename as filename, 843 {{object}}.typeid as typeid, 844 {{object}}.lastchange_date as lastchange_date, 845 {{name}}.name as name 846 FROM {{object}} 847 LEFT JOIN {{name}} 848 ON {{name}}.objectid = {{object}}.id 849 AND {{name}}.languageid = {languageid} 850 LEFT JOIN {{project}} 851 ON {{object}}.projectid = {{project}}.id 852 WHERE {{object}}.projectid = {projectid} 853 AND {{object}}.lastchange_userid = {userid} 854 ORDER BY {{object}}.lastchange_date DESC; 855 SQL 856 ); 857 858 // Variablen setzen. 859 $sql->setInt( 'projectid', $this->projectid ); 860 861 $sql->setInt( 'languageid', 0 ); 862 863 $user = Request::getUser(); 864 $sql->setInt( 'userid', $user->userid ); 865 866 return $sql->getAll(); 867 } 868 869 870 /** 871 * Ermittelt projektübergreifend die letzten Änderungen. 872 * 873 * @return array 874 */ 875 public static function getAllLastChanges() 876 { 877 $db = \cms\base\DB::get(); 878 879 $sql = $db->sql( <<<SQL 880 SELECT {{object}}.id as objectid, 881 {{object}}.lastchange_date as lastchange_date, 882 {{object}}.filename as filename, 883 {{project}}.id as projectid, 884 {{project}}.name as projectname, 885 {{user}}.name as username, 886 {{user}}.id as userid, 887 {{user}}.mail as usermail, 888 {{user}}.fullname as userfullname 889 FROM {{object}} 890 LEFT JOIN {{project}} 891 ON {{object}}.projectid = {{project}}.id 892 LEFT JOIN {{user}} 893 ON {{user}}.id = {{object}}.lastchange_userid 894 ORDER BY {{object}}.lastchange_date DESC 895 LIMIT 50 896 SQL 897 ); 898 899 return $sql->getAll(); 900 } 901 902 903 904 /** 905 * Ermittelt die letzten Änderung im Projekt. 906 * @return array 907 */ 908 public function getLastChanges() 909 { 910 911 $db = \cms\base\DB::get(); 912 913 $sql = $db->sql( <<<SQL 914 SELECT {{object}}.id as objectid, 915 {{object}}.lastchange_date as lastchange_date, 916 {{object}}.filename as filename, 917 {{object}}.typeid as typeid, 918 {{name}}.name as name, 919 {{user}}.name as username, 920 {{user}}.id as userid, 921 {{user}}.mail as usermail, 922 {{user}}.fullname as userfullname 923 FROM {{object}} 924 LEFT JOIN {{name}} 925 ON {{name}}.objectid = {{object}}.id 926 AND {{name}}.languageid = {languageid} 927 LEFT JOIN {{user}} 928 ON {{user}}.id = {{object}}.lastchange_userid 929 WHERE {{object}}.projectid = {projectid} 930 ORDER BY {{object}}.lastchange_date DESC 931 SQL 932 ); 933 934 // Variablen setzen. 935 $sql->setInt( 'projectid', $this->projectid ); 936 937 $languageid = $this->getDefaultLanguageId(); 938 $sql->setInt( 'languageid', $languageid ); 939 940 return $sql->getAll(); 941 } 942 943 /** 944 * Timeline 945 * 946 * @return array <string, unknown> 947 */ 948 public function getValueChanges( $fromDate ) 949 { 950 $sql = Db::sql( <<<SQL 951 SELECT {{value}}.lastchange_date as lastchange_date, 952 {{value}}.lastchange_userid as userid, 953 {{value}}.linkobjectid as linkobjectid, 954 {{value}}.text as linkobjectid, 955 {{value}}.number as linkobjectid, 956 {{value}}.date as date, 957 {{value}}.format as format, 958 {{value}}.id as valueid 959 FROM {{value}} 960 LEFT JOIN {{templatemodel}} 961 ON {{value}}.contentid = {{templatemodel}}.contentid 962 LEFT JOIN {{pagecontent}} 963 ON {{pagecontent}}.contentid = {{templatemodel}}.contentid 964 LEFT JOIN {{file}} 965 ON {{file}}.contentid = {{templatemodel}}.contentid 966 WHERE {{value}}.lastchange_userid = {userid} AND 967 {{value}}.lastchange_date >= {fromdate} 968 ORDER BY {{value}}.lastchange_date DESC 969 SQL 970 ); 971 972 $sql->setInt( 'projectid', $this->projectid ); 973 $sql->setInt( 'fromdate' , $fromDate ); 974 975 return $sql->getAll(); 976 977 } 978 /** 979 * Timeline 980 * 981 * @return array <string, unknown> 982 */ 983 public static function getAllValueChanges( $fromDate ) 984 { 985 $sql = Db::sql( <<<SQL 986 SELECT {{value}}.lastchange_date as lastchange_date, 987 {{value}}.lastchange_userid as userid, 988 {{value}}.linkobjectid as linkobjectid, 989 {{value}}.text as linkobjectid, 990 {{value}}.number as linkobjectid, 991 {{value}}.date as date, 992 {{value}}.format as format, 993 {{value}}.id as valueid 994 FROM {{value}} 995 LEFT JOIN {{templatemodel}} 996 ON {{value}}.contentid = {{templatemodel}}.contentid 997 LEFT JOIN {{pagecontent}} 998 ON {{pagecontent}}.contentid = {{templatemodel}}.contentid 999 LEFT JOIN {{file}} 1000 ON {{file}}.contentid = {{templatemodel}}.contentid 1001 WHERE {{value}}.lastchange_date >= {fromdate} 1002 ORDER BY {{value}}.lastchange_date DESC 1003 SQL 1004 ); 1005 1006 $sql->setInt( 'fromdate', $fromDate ); 1007 1008 return $sql->getAll(); 1009 1010 } 1011 1012 1013 1014 /** 1015 * Timeline 1016 * 1017 * @return array <string, unknown> 1018 */ 1019 public function getMyValueChanges( $fromDate ) 1020 { 1021 $sql = Db::sql( <<<SQL 1022 SELECT {{value}}.lastchange_date as lastchange_date, 1023 {{value}}.lastchange_userid as userid, 1024 {{value}}.linkobjectid as linkobjectid, 1025 {{value}}.text as linkobjectid, 1026 {{value}}.number as linkobjectid, 1027 {{value}}.date as date, 1028 {{value}}.format as format, 1029 {{value}}.id as valueid 1030 FROM {{value}} 1031 LEFT JOIN {{templatemodel}} 1032 ON {{value}}.contentid = {{templatemodel}}.contentid 1033 LEFT JOIN {{pagecontent}} 1034 ON {{pagecontent}}.contentid = {{templatemodel}}.contentid 1035 LEFT JOIN {{file}} 1036 ON {{file}}.contentid = {{templatemodel}}.contentid 1037 WHERE {{value}}.lastchange_userid = {userid} AND 1038 {{value}}.lastchange_date >= {fromdate} 1039 ORDER BY {{value}}.lastchange_date DESC 1040 SQL 1041 ); 1042 1043 $user = Request::getUser(); 1044 $sql->setInt( 'userid' , $user->userid ); 1045 $sql->setInt( 'fromdate', $fromDate ); 1046 1047 return $sql->getAll(); 1048 1049 } 1050 1051 /** 1052 * Ermittelt alle Objekte vom gew�nschten Typ, die sic in 1053 * diesem Projekt befinden. 1054 * 1055 * @see objectClasses/Object#getAllObjectIds() 1056 * @param array types Array 1057 * @return array Liste von Object-Ids 1058 */ 1059 public function getAllObjectIds( $types=array('folder','page','link','file','image','url','text') ) 1060 { 1061 $stmt = \cms\base\Db::sql( <<<SQL 1062 SELECT id FROM {{object}} 1063 WHERE projectid={projectid} 1064 AND ( typeid ={is_folder} 1065 OR typeid ={is_file} 1066 OR typeid ={is_image} 1067 OR typeid ={is_text} 1068 OR typeid ={is_page} 1069 OR typeid ={is_link} 1070 OR typeid ={is_url} ) 1071 ORDER BY orderid ASC 1072 SQL 1073 ); 1074 1075 $stmt->setInt('projectid',$this->projectid ); 1076 $stmt->setInt('is_folder',in_array('folder',$types)?BaseObject::TYPEID_FOLDER:0); 1077 $stmt->setInt('is_file' ,in_array('file' ,$types)?BaseObject::TYPEID_FILE :0); 1078 $stmt->setInt('is_image' ,in_array('image' ,$types)?BaseObject::TYPEID_IMAGE :0); 1079 $stmt->setInt('is_text' ,in_array('text' ,$types)?BaseObject::TYPEID_TEXT :0); 1080 $stmt->setInt('is_page' ,in_array('page' ,$types)?BaseObject::TYPEID_PAGE :0); 1081 $stmt->setInt('is_link' ,in_array('link' ,$types)?BaseObject::TYPEID_LINK :0); 1082 $stmt->setInt('is_url' ,in_array('url' ,$types)?BaseObject::TYPEID_URL :0); 1083 1084 return( $stmt->getCol() ); 1085 } 1086 1087 1088 /** 1089 * Liefert die Ids aller Ordner in diesem Projekt. 1090 * 1091 * @return array 1092 */ 1093 public function getAllFolders() 1094 { 1095 $stmt = DB::sql( <<<SQL 1096 SELECT id FROM {{object}} 1097 WHERE typeid={typeid} 1098 AND projectid={projectid} 1099 SQL 1100 ); 1101 $stmt->setInt( 'typeid' ,BaseObject::TYPEID_FOLDER ); 1102 $stmt->setInt( 'projectid',$this->projectid ); 1103 1104 return( $stmt->getCol() ); 1105 } 1106 1107 1108 /** 1109 * @return array 1110 */ 1111 public function getAllFlatFolders() { 1112 1113 $folders = array(); 1114 1115 foreach( $this->getAllFolders() as $id ) 1116 { 1117 $o = new BaseObject( $id ); 1118 $o->load(); 1119 1120 $folders[ $id ] = ''; 1121 if ( !$o->isRoot() ) 1122 { 1123 $f = new Folder( $o->parentid ); 1124 $f->load(); 1125 $names = $f->parentObjectNames(true,true); 1126 foreach( $names as $fid=>$name ) 1127 $names[$fid] = \util\Text::maxLength($name,15,'..',STR_PAD_BOTH); 1128 $folders[ $id ] = implode( \util\Text::FILE_SEP,$names ); 1129 $folders[ $id ] .= \util\Text::FILE_SEP; 1130 } 1131 $folders[ $id ] .= $o->getName(); 1132 } 1133 1134 asort( $folders ); // Sortieren 1135 1136 return $folders; 1137 } 1138 1139 public function getName() 1140 { 1141 return $this->name; 1142 } 1143 1144 1145 /** 1146 * Cleans up the target url. 1147 */ 1148 public function getCleanTarget() 1149 { 1150 $target = parse_url( $this->target_dir ); 1151 1152 $scheme = isset($target['scheme']) ? $target['scheme'] . '://' : ''; 1153 if ( empty($scheme) ) 1154 $scheme = 'file:/'; 1155 1156 $host = isset($target['host']) ? $target['host'] : ''; 1157 $port = isset($target['port']) ? ':' . $target['port'] : ''; 1158 $user = isset($target['user']) ? $target['user'] : ''; 1159 $pass = isset($target['pass']) ? ':' . $target['pass'] : ''; 1160 $pass = ($user || $pass) ? "$pass@" : ''; 1161 $path = isset($target['path']) ? $target['path'] : ''; 1162 $query = isset($target['query']) ? '?' . $target['query'] : ''; 1163 $fragment = isset($target['fragment']) ? '#' . $target['fragment'] : ''; 1164 1165 return "$scheme$user$pass$host$port$path$query$fragment"; 1166 } 1167 1168 1169 1170 public function getId() 1171 { 1172 return $this->projectid; 1173 } 1174 1175 1176 } 1177
Downloadmodules/cms/model/Project.class.php
History Tue, 13 Oct 2026 18:49:59 +0200 Jan Dankert New: Another action which returns an object instead of single output values. This should be the future, but it's a long way to refactore all old action methods... Mon, 6 Jan 2025 22:48:11 +0100 Jan Dankert New: Now it is possible to remove and create new login/api token for a user; new API authorization with the authorization scheme "api". 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. Sat, 2 Jul 2022 00:37:22 +0200 Jan Dankert Fix: Public Filename must consider the filename style. Mon, 25 Apr 2022 03:26:21 +0200 Jan Dankert New: New Project may be created with sample data. 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. Fri, 11 Mar 2022 11:32:38 +0100 dankert New: Edit all languages for a page element. Sun, 5 Dec 2021 22:26:39 +0100 dankert Fixed a type in template source of new projects. Sun, 5 Dec 2021 20:33:24 +0100 dankert Cleanup: Removed unusable properties from class 'Value' and 'BaseObject'. Sun, 5 Dec 2021 15:33:29 +0100 dankert Cleanup: Removed unusable properties from class 'Value'. Sun, 7 Mar 2021 00:10:20 +0100 Jan Dankert Refactoring: Hopefully more performance while accessing the database resultsets. Wed, 18 Nov 2020 01:46:36 +0100 Jan Dankert Refactoring of model classes: New method persist() and some other cleanups. Sat, 14 Nov 2020 22:02:21 +0100 Jan Dankert Fixed: Notices may display a message. Sun, 1 Nov 2020 03:08:55 +0100 Jan Dankert Replaced the calls to "Configuration::rawConfig()" with the OO style calls; Cleanup LoginAction. Mon, 26 Oct 2020 23:09:24 +0100 Jan Dankert Cleanup UI for adding templates and adding projects. Wed, 7 Oct 2020 23:01:31 +0200 Jan Dankert Cleanup: Refactored file seperator char with an unicode char. 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 10:32:02 +0200 Jan Dankert Refactoring: No global $conf array any more. Sat, 26 Sep 2020 03:03:47 +0200 Jan Dankert Refactoring: less global functions. Sat, 26 Sep 2020 02:26:39 +0200 Jan Dankert Refactoring: No global functions any more, the database object is read from the Db class. Wed, 23 Sep 2020 01:04:05 +0200 Jan Dankert Cleanup of deprecated methods and deprecated class attributes. Mon, 21 Sep 2020 22:48:59 +0200 Jan Dankert Complexe refactoring: Moving all generation logic from the model (Value,Page,File) to generators classes. Fri, 18 Sep 2020 22:48:46 +0200 Jan Dankert Refactoring: Every project has 1 publishing target. Sun, 23 Feb 2020 04:01:30 +0100 Jan Dankert Refactoring with Namespaces for the cms modules, part 1: moving.