1<?php 2 3/** 4 * Copyright Intermesh 5 * 6 * This file is part of Group-Office. You should have received a copy of the 7 * Group-Office license along with Group-Office. See the file /LICENSE.TXT 8 * 9 * If you have questions write an e-mail to info@intermesh.nl 10 * 11 * @version $Id: File.php 7607 2011-09-01 15:40:20Z <<USERNAME>> $ 12 * @copyright Copyright Intermesh 13 * @author <<FIRST_NAME>> <<LAST_NAME>> <<EMAIL>>@intermesh.nl 14 */ 15 16namespace GO\Files\Model; 17 18use GO; 19use go\core\exception\NotFound; 20 21/** 22 * The File model 23 * 24 * @property int $id 25 * @property int $folder_id 26 * @property String $name 27 28 * @property int $locked_user_id 29 * @property int $status_id 30 * @property int $ctime 31 * @property int $mtime 32 * @property int $muser_id 33 * @property int $size 34 * @property int $user_id 35 * @property String $comments 36 * @property String $extension 37 * @property int $expire_time 38 * @property String $random_code 39 * @property String $content_expire_date 40 * 41 * @property String $thumbURL 42 * 43 * @property String $downloadUrl 44 * 45 * @property String $path 46 * @property \GO\Base\Fs\File $fsFile 47 * @property Folder $folder 48 * @property \GO\Base\Model\User $lockedByUser 49 * 50 * @property boolean $delete_when_expired 51 */ 52class File extends \GO\Base\Db\ActiveRecord implements \GO\Base\Mail\SwiftAttachableInterface { 53 54 use \go\core\orm\CustomFieldsTrait; 55 56 public static $deleteInDatabaseOnly=false; 57 58 private $_permissionLevel; 59 60 public static $trimOnSave = false; 61 62 /** 63 * Returns a static model of itself 64 * 65 * @param String $className 66 * @return File 67 */ 68 public static function model($className=__CLASS__) { 69 return parent::model($className); 70 } 71 72 /** 73 * Enable this function if you want this model to check the acl's automatically. 74 */ 75 public function aclField() { 76 return 'folder.acl_id'; 77 } 78 79 /** 80 * Returns the table name 81 */ 82 public function tableName() { 83 return 'fs_files'; 84 } 85 86 protected function getLocalizedName() { 87 return \GO::t("File", "files"); 88 } 89 90 public function customfieldsModel() { 91 return "GO\Files\Customfields\Model\File"; 92 } 93 94 public function hasLinks() { 95 return true; 96 } 97 98 protected function getCacheAttributes() { 99 100 $path = $this->path; 101 102 //Don't cache tickets files because there are permissions issues. Everyone has read access to the types but may not see other peoples files. 103 if(strpos($path, 'tickets/')===0){ 104 return false; 105 } 106 107 return array('name'=>$this->name, 'description'=>$path); 108 } 109 110 public function getLogMessage($action){ 111 return $this->path; 112 } 113 /** 114 * Here you can define the relations of this model with other models. 115 * See the parent class for a more detailed description of the relations. 116 */ 117 public function relations() { 118 return array( 119 'lockedByUser' => array('type' => self::BELONGS_TO, 'model' => 'GO\Base\Model\User', 'field' => 'locked_user_id'), 120 'folder' => array('type' => self::BELONGS_TO, 'model' => 'GO\Files\Model\Folder', 'field' => 'folder_id'), 121 'versions' => array('type'=>self::HAS_MANY, 'model'=>'GO\Files\Model\Version', 'field'=>'file_id', 'delete'=>true), 122 ); 123 } 124 125 public function getPermissionLevel(){ 126 127 if(\GO::$ignoreAclPermissions) 128 return \GO\Base\Model\Acl::MANAGE_PERMISSION; 129 130 if(!$this->aclField()) 131 return -1; 132 133 if(!\GO::user()) 134 return false; 135 136 //if($this->isNew && !$this->joinAclField){ 137 if(empty($this->{$this->aclField()}) && !$this->getIsJoinedAclField()){ 138 //the new model has it's own ACL but it's not created yet. 139 //In this case we will check the module permissions. 140 $module = $this->getModule(); 141 if($module=='base'){ 142 return \GO::user()->isAdmin() ? \GO\Base\Model\Acl::MANAGE_PERMISSION : false; 143 }else 144 return \GO::modules()->$module->permissionLevel; 145 146 }else 147 { 148 if(!isset($this->_permissionLevel)){ 149 150 $acl_id = $this->findAclId(); 151 if(!$acl_id){ 152 throw new \Exception("Could not find ACL for ".$this->className()." with pk: ".$this->pk); 153 } 154 155 $this->_permissionLevel=\GO\Base\Model\Acl::getUserPermissionLevel($acl_id);// model()->findByPk($acl_id)->getUserPermissionLevel(); 156 } 157 return $this->_permissionLevel; 158 } 159 160 } 161 162 protected function init() { 163 $this->columns['expire_time']['gotype'] = 'unixdate'; 164 $this->columns['content_expire_date']['gotype'] = 'unixdate'; 165 $this->columns['name']['required']=true; 166 parent::init(); 167 } 168 169 /** 170 * Check if a file is locked by another user. 171 * 172 * @return boolean 173 */ 174 public function isLocked(){ 175 return !empty($this->locked_user_id) && (!\GO::user() || $this->locked_user_id!=\GO::user()->id); 176 } 177 178 public function unlockAllowed(){ 179 return ($this->locked_user_id==\GO::user()->id || \GO::user()->isAdmin()) && $this->checkPermissionLevel(\GO\Base\Model\Acl::WRITE_PERMISSION); 180 } 181 182 public function getJsonData() { 183 $data = array( 184 'id' => $this->id, 185 'name' => $this->path, 186 'ctime' => \GO\Base\Util\Date::get_timestamp($this->ctime), 187 'mtime' => \GO\Base\Util\Date::get_timestamp($this->mtime), 188 'extension' => $this->extension, 189 'size' => $this->size, 190 'user_id' => $this->user_id, 191// 'type' => $this->type, 192 'folder_id' => $this->folder_id, 193 'type_id' => 'f:'.$this->id, 194 'path' => $this->path, 195 'locked' => $this->isLocked(), 196 'locked_user_id' => $this->locked_user_id, 197 'unlock_allowed' => $this->unlockAllowed(), 198 'expire_time' => $this->expire_time > 0 ? \GO\Base\Util\Date::get_timestamp($this->expire_time,false) : '', 199 'thumbs' => 0, 200 'thumb_url' => $this->getThumbURL() 201 ); 202 203 if(method_exists($this, "getCustomFields")) { 204 $data['customFields'] = $this->getCustomFields()->toArray(); 205 } 206 return $data; 207 } 208 209 /** 210 * 211 * @return \GO\Base\Fs\File 212 */ 213 private function _getOldFsFile(){ 214 215 if($this->isNew) 216 return $this->fsFile; 217 218 $filename = $this->isModified('name') ? $this->getOldAttributeValue('name') : $this->name; 219 if($this->isModified('folder_id')){ 220 //file will be moved so we need the old folder path. 221 $oldFolderId = $this->getOldAttributeValue('folder_id'); 222 $oldFolder = Folder::model()->findByPk($oldFolderId); 223 $oldRelPath = $oldFolder->path; 224 $oldPath = \GO::config()->file_storage_path . $oldRelPath . '/' . $filename; 225 226 }else{ 227 $oldPath = \GO::config()->file_storage_path . $this->folder->path.'/'.$filename; 228 } 229 return new \GO\Base\Fs\File($oldPath); 230 } 231 232 protected function beforeDelete() { 233 234 //blocked database check. We check this in the controller now. 235 if($this->isLocked() && !\GO::user()->isAdmin()) 236 throw new \Exception(\GO::t("File is locked", "files").': '.$this->path); 237 238 return parent::beforeDelete(); 239 } 240 241 /** 242 * Check the disk and user quota 243 * @param integer $newBytes amount of bytes that are added when check succeeds 244 * @return boolean true if the check passed and the file may be added 245 */ 246 public static function checkQuota($newBytes) { 247 $enoughQuota = true; 248 $userQuota = \GO::user()->getDiskQuota(); 249 250 if ($userQuota) { 251 $enoughQuota = \GO::user()->disk_usage + $newBytes <= $userQuota; 252 } 253 if ($enoughQuota && \GO::config()->quota > 0) { 254 $currentQuota = \GO::config()->get_setting('file_storage_usage'); 255 $enoughQuota = $currentQuota + $newBytes <= (\GO::config()->quota * 1024); 256 } 257 258 return $enoughQuota; 259 } 260 261 public function checkNormalization() { 262 if(!\go\core\util\StringUtil::isNormalized($this->name)) { 263 \GO::debug("Normalizing file $this->id to Unicode Form C"); 264 265 $name = \go\core\util\StringUtil::normalize($this->name); 266 267 if($this->getFsFile()->exists()) { 268 $this->getFsFile()->rename($name); 269 } 270 271 if(!$this->getIsNew()) { 272 go()->getDbConnection()->update('fs_files',['name' => $name], ['id' => $this->id])->execute(); 273 } 274 $this->name = $name; 275 } 276 } 277 278 protected function beforeSave() { 279 280 //Normalize UTF-8. ONly form D works on MacOS webdav! 281 $this->checkNormalization(); 282 283 //check permissions on the filesystem 284 if($this->isNew){ 285 286 if(is_null($this->folder->fsFolder)){ 287 throw new \Exception("Folder ".$this->folder->path." cannot be found on disk, please check this path manually."); 288 } 289 290 if(!$this->folder->fsFolder->isWritable()){ 291 throw new \Exception("Folder ".$this->folder->path." is read only on the filesystem. Please check the file system permissions (hint: chown -R www-data:www-data /home/groupoffice)"); 292 } 293 }else 294 { 295 if($this->isModified('name') || $this->isModified('folder_id')){ 296 if($this->_getOldFsFile()->exists() && !$this->_getOldFsFile()->isWritable()) 297 throw new \Exception("File ".$this->_getOldFsFile()->path ()." is read only on the filesystem. Please check the file system permissions (hint: chown -R www-data:www-data /home/groupoffice)"); 298 } 299 } 300 301 if($this->isNew || $this->isModified('name')){ 302 $existingFile = $this->folder->hasFile($this->name); 303 if($existingFile && $existingFile->id!=$this->id) 304 throw new \Exception(sprintf(\GO::t("Filename %s already exists", "files"), $this->path)); 305 } 306 307 if(!$this->isNew){ 308 309 if($this->isModified('name')){ 310 //rename filesystem file. 311 //throw new \Exception($this->getOldAttributeValue('name')); 312 $oldFsFile = $this->_getOldFsFile(); 313 if($oldFsFile->exists()) 314 $oldFsFile->rename($this->name); 315 316 $this->notifyUsers( 317 $this->folder_id, 318 FolderNotificationMessage::RENAME_FILE, 319 $this->folder->path . '/' . $this->getOldAttributeValue('name'), 320 $this->folder->path . '/' . $this->name 321 ); 322 } 323 324 if($this->isModified('folder_id')){ 325 if(!isset($oldFsFile)) 326 $oldFsFile = $this->_getOldFsFile(); 327 328 if (!$oldFsFile->move(new \GO\Base\Fs\Folder(\GO::config()->file_storage_path . dirname($this->path)))) 329 throw new \Exception("Could not rename folder on the filesystem"); 330 331 //get old folder objekt 332 $oldFolderId = $this->getOldAttributeValue('folder_id'); 333 $oldFolder = Folder::model()->findByPk($oldFolderId); 334 335 $this->notifyUsers( 336 array( 337 $this->getOldAttributeValue('folder_id'), 338 $this->folder_id 339 ), 340 FolderNotificationMessage::MOVE_FILE, 341 $oldFolder->path . '/' . $this->name, 342 $this->path 343 ); 344 } 345 } 346 347 if($this->isModified('locked_user_id')){ 348 $old_locked_user_id = $this->getOldAttributeValue('locked_user_id'); 349 if(!empty($old_locked_user_id) && $old_locked_user_id != \GO::user()->id && !\GO::user()->isAdmin()) 350 throw new \GO\Files\Exception\FileLocked(); 351 } 352 353 354 $this->extension = $this->fsFile->extension(); 355 //make sure extension is not too long 356 $this->cutAttributeLength("extension"); 357 358 $this->size = $this->fsFile->size(); 359 //$this->ctime = $this->fsFile->ctime(); 360 $this->mtime = $this->fsFile->mtime(); 361 362 363 364 return parent::beforeSave(); 365 } 366 367 protected function getPath() { 368 return $this->folder ? $this->folder->path . '/' . $this->name : $this->name; 369 } 370 371 public function getVirtualPath() { 372 return $this->folder->getVirtualPath() . '/' . $this->name; 373 } 374 375 protected function getFsFile() { 376 return new \GO\Base\Fs\File(\GO::config()->file_storage_path . $this->path); 377 } 378 379 private function _addQuota(){ 380 381 if($this->isModified('size') || $this->isNew) { 382 $sizeDiff = (int) $this->fsFile->size() - (int) $this->getOldAttributeValue('size'); 383 384// GO::debug("Adding quota: $sizeDiff for ".$this->folder->quotaUser->getName()); 385 if($this->folder->quotaUser){ 386 $this->folder->quotaUser->calculatedDiskUsage($sizeDiff)->save(true); //user quota 387 } 388 if(GO::config()->quota>0) { 389 GO::config()->save_setting("file_storage_usage", GO::config()->get_setting('file_storage_usage')+$sizeDiff); //system quota 390 } 391 } 392 393 } 394 395 private function _removeQuota(){ 396 if(\GO::config()->quota>0){ 397 \GO::debug("Removing quota: $this->size"); 398 \GO::config()->save_setting("file_storage_usage", \GO::config()->get_setting('file_storage_usage')-$this->size); 399 } 400 401 if($this->folder->quotaUser){ 402 $this->folder->quotaUser->calculatedDiskUsage (0-$this->size)->save(true); 403 } 404 405 } 406 407 public function checkPermissionLevel($level) { 408 409// var_dump($this->acl->description); 410 411 //If this folder belongs to a contact or project etc. then we only need write permission to delete it. 412 if($level == \GO\Base\Model\Acl::DELETE_PERMISSION && $this->folder->acl->usedIn != 'fs_folders.acl_id') { 413 $level = \GO\Base\Model\Acl::WRITE_PERMISSION; 414 } 415 416 return parent::checkPermissionLevel($level); 417 } 418 419 private function getOldFolder() { 420 return Folder::model()->findByPk($this->getOldAttributeValue('folder_id')); 421 } 422 423 424 public function checkOldPermissionLevel($level) { 425 //If this folder belongs to a contact or project etc. then we only need write permission to delete it. 426 if($level == \GO\Base\Model\Acl::DELETE_PERMISSION && $this->getOldFolder()->acl->usedIn != 'fs_folders.acl_id') { 427 $level = \GO\Base\Model\Acl::WRITE_PERMISSION; 428 } 429 return parent::checkOldPermissionLevel($level); 430 } 431 432 protected function afterSave($wasNew) { 433 $this->_addQuota(); 434 435 if ($wasNew) { 436 $this->notifyUsers( 437 $this->folder_id, 438 FolderNotificationMessage::ADD_FILE, 439 $this->name, 440 $this->folder->path 441 ); 442 } else { 443 if ($this->isModified() && !$this->isModified('name') && !$this->isModified('folder_id')) { 444 $this->notifyUsers( 445 $this->folder_id, 446 FolderNotificationMessage::UPDATE_FILE, 447 $this->path 448 ); 449 } 450 } 451 452 453 //touch the timestamp so it won't sync with the filesystem 454 if($this->isModified('folder_id')){ 455 456 GO::debug("touching parent"); 457 $this->folder->touch(); 458 459 $oldParent = \GO\Files\Model\Folder::model()->findByPk($this->getOldAttributeValue('folder_id')); 460 461 if($oldParent){ 462 GO::debug("touching old parent"); 463 $oldParent->touch(); 464 } 465 } 466 467 468 return parent::afterSave($wasNew); 469 } 470 471 public $customVersionPath = null; 472 public function getVersionStoragePath() { 473 if($this->customVersionPath!==null) { 474 return $this->customVersionPath; 475 } 476 return 'versioning/'.$this->id; 477 } 478 479 protected function afterDelete() { 480 481 $this->_removeQuota(); 482 483 if(!File::$deleteInDatabaseOnly) 484 $this->fsFile->delete(); 485 486 $versioningFolder = new \GO\Base\Fs\Folder(\GO::config()->file_storage_path.$this->getVersionStoragePath()); 487 $versioningFolder->delete(); 488 489 $this->notifyUsers( 490 $this->folder_id, 491 FolderNotificationMessage::DELETE_FILE, 492 $this->path 493 ); 494 495 return parent::afterDelete(); 496 } 497 498 /** 499 * The link that can be send in an e-mail as download link. 500 * 501 * @return StringHelper 502 */ 503 public function getEmailDownloadURL($html=true, $newExpireTime=false, $deleteWhenExpired=false) { 504 505 if($newExpireTime && $this->expire_time < $newExpireTime){ 506 if($this->expire_time <= time() || empty($this->random_code)) { 507 $this->random_code=\GO\Base\Util\StringHelper::randomPassword(11,'a-z,A-Z,0-9'); 508 } 509 $this->expire_time = $newExpireTime; 510 $this->delete_when_expired = $deleteWhenExpired; 511 $this->save(); 512 } 513 514 if (!empty($this->expire_time) && !empty($this->random_code)) { 515 return \GO::url('files/file/download', array('id'=>$this->id,'inline'=>'false','random_code'=>$this->random_code), false, $html, false); 516 } 517 } 518 519 520 /** 521 * The link to download the file. 522 * This function does not check the file download expire time and the random code 523 * 524 * @return StringHelper 525 */ 526 public function getDownloadURL($downloadAttachment=true, $relative=false) { 527 return \GO::url('files/file/download', array('id'=>$this->id, 'inline'=>$downloadAttachment?'false':'true'), $relative); 528 } 529 530 531 public function getThumbURL($urlParams=array("lw"=>480, "ph"=>270, "zc"=>0)) { 532 533 $urlParams['filemtime']=$this->mtime; 534 $urlParams['src']=$this->path; 535 536 if($this->extension=='svg'){ 537 return $this->getDownloadURL(false, true); 538 }else 539 { 540 return \GO::url('core/thumb', $urlParams); 541 } 542 } 543 544 /** 545 * Move a file to another folder 546 * 547 * @param Folder $destinationFolder 548 * @return boolean 549 */ 550 public function move($destinationFolder,$appendNumberToNameIfExists=false){ 551 552 $this->folder_id=$destinationFolder->id; 553 if($appendNumberToNameIfExists) 554 $this->appendNumberToNameIfExists(); 555 return $this->save(); 556 } 557 558 /** 559 * Just the let someone kow the file was opened 560 */ 561 public function open() { 562 $this->log('open'); 563 } 564 565 /** 566 * Adds some extra info to the loggin of files 567 * @param StringHelper $action the action to log 568 * @param boolean $save unused 569 * @return boolean if save was successful 570 */ 571 protected function log($action, $save=true, $modifiedCustomfieldAttrs = false) { 572 $log = parent::log($action, false, $modifiedCustomfieldAttrs); 573 if(empty($log)) 574 return false; 575 576 if($log === true) { 577 return true; 578 } 579 580 if($log->action=='update') { 581 $log->action = 'propedit'; 582 if($log->object->isModified('folder_id')) 583 $log->action='moved'; 584 if($log->object->isModified('name')) { 585 $log->action='renamed'; 586 $log->message = $log->object->getOldAttributeValue('name') . ' > ' . $log->message; 587 } 588 } 589 return $save ? $log->save() : $log; 590 } 591 592 /** 593 * Copy a file to another folder. 594 * 595 * @param Folder $destinationFolder 596 * @param StringHelper $newFileName. Leave blank to use the same name. 597 * @return File 598 */ 599 public function copy($destinationFolder, $newFileName=false, $appendNumberToNameIfExists=false){ 600 601 $copy = $this->duplicate(array('folder_id'=>$destinationFolder->id), false, true); 602 603 if($newFileName) 604 $copy->name=$newFileName; 605 606 if($appendNumberToNameIfExists) 607 $copy->appendNumberToNameIfExists(); 608 609 $this->fsFile->copy($copy->fsFile->parent(), $copy->name); 610 611 $copy->save(true); 612 613 return $copy; 614 } 615 616 /** 617 * Import a filesystem file into the database. 618 * 619 * @param \GO\Base\Fs\File $fsFile 620 * @return File 621 */ 622 public static function importFromFilesystem(\GO\Base\Fs\File $fsFile){ 623 624 $folderPath = str_replace(\GO::config()->file_storage_path,"",$fsFile->parent()->path()); 625 626 $folder = Folder::model()->findByPath($folderPath, true); 627 if(($file = $folder->hasFile($fsFile->name()))) { 628 return $file; 629 } 630 return $folder->addFile($fsFile->name()); 631 } 632 633 /** 634 * Replace filesystem file with given file. 635 * 636 * @param \GO\Base\Fs\File $fsFile 637 */ 638 public function replace(\GO\Base\Fs\File $fsFile, $isUploadedFile=false){ 639 640 if($this->isLocked()) 641 throw new \GO\Files\Exception\FileLocked(); 642// for safety allow replace action 643// if(!File::checkQuota($fsFile->size()-$this->size)) 644// throw new \GO\Base\Exception\InsufficientDiskSpace(); 645 if(!$this->isNew) 646 $this->log('edit'); 647 $this->saveVersion(); 648 649 if(!$fsFile->move($this->folder->fsFolder,$this->name, $isUploadedFile)){ 650 return false; 651 } 652 $fsFile->setDefaultPermissions(); 653 654 $old = $this->mtime; 655 $this->mtime = $this->fsFile->mtime(); 656 $this->save(); 657 658 $this->fireEvent('replace', array($this, $isUploadedFile)); 659 660 return true; 661 } 662 663 public function putContents($data){ 664// for safety allow replace actions 665// if(!File::checkQuota(strlen($data))) 666// throw new \GO\Base\Exception\InsufficientDiskSpace(); 667 668 $this->fsFile->putContents($data); 669 $old = $this->mtime; 670 $this->mtime = $this->fsFile->mtime(); 671 $this->save(); 672 } 673 674 /** 675 * Copy current file to the versioning system. 676 */ 677 public function saveVersion(){ 678 679 $this->version++; 680 681 $this->fireEvent('saveversion', array($this)); 682 683 if(\GO::config()->max_file_versions > -1){ 684 $version = new Version(); 685 $version->file_id = $this->id; 686 $version->size_bytes = $this->size; 687 $version->save(); 688 } 689 } 690 691 /** 692 * Find the file model by relative path. 693 * 694 * @param StringHelper $relpath Relative path from \GO::config()->file_storage_path 695 * @return File 696 */ 697 public function findByPath($relpath){ 698 $folder = Folder::model()->findByPath(dirname($relpath),false,array()); 699 if(!$folder) 700 return false; 701 else 702 { 703 return $folder->hasFile(\GO\Base\Fs\File::utf8Basename($relpath)); 704 } 705 } 706 707 /** 708 * Check if the file is an image. 709 * 710 * @return boolean 711 */ 712 public function isImage(){ 713 switch(strtolower($this->extension)){ 714 case 'ico': 715 case 'jpg': 716 case 'jpeg': 717 case 'png': 718 case 'gif': 719 case 'bmp': 720 case 'xmind': 721 case 'svg': 722 723 return true; 724 default: 725 return false; 726 } 727 } 728 729 730 731 /** 732 * Checks if a filename exists and renames it. 733 * 734 * @param StringHelper $filepath The complete path to the file 735 * @access public 736 * @return StringHelper New filename 737 */ 738 public function appendNumberToNameIfExists() 739 { 740 $dir = $this->folder->path; 741 $origName = $this->fsFile->nameWithoutExtension(); 742 $extension = $this->fsFile->extension(); 743 $x=1; 744 $newName=$this->name; 745 while($this->folder->hasFile($newName)) 746 { 747 $newName=$origName.' ('.$x.').'.$extension; 748 $x++; 749 } 750 $this->name=$newName; 751 return $this->name; 752 } 753 754 /** 755 * 756 * @param type $folder_id 757 * @param type $type 758 * @param type $arg1 759 * @param type $arg2 760 */ 761 public function notifyUsers($folder_id, $type, $arg1, $arg2 = '') { 762 FolderNotification::model()->storeNotification($folder_id, $type, $arg1, $arg2); 763 } 764 765 766 767 public function findRecent($start=false,$limit=false){ 768 $storeParams = \GO\Base\Db\FindParams::newInstance()->ignoreAcl(); 769 770 $joinSearchCacheCriteria = \GO\Base\Db\FindCriteria::newInstance() 771 ->addRawCondition('`t`.`id`', '`sc`.`entityId`') 772 ->addCondition('entityTypeId', $this->modelTypeId(),'=','sc'); 773 774 $storeParams->join(\GO\Base\Model\SearchCacheRecord::model()->tableName(), $joinSearchCacheCriteria, 'sc', 'INNER'); 775 776 777 $aclJoinCriteria = \GO\Base\Db\FindCriteria::newInstance() 778 ->addRawCondition('a.aclId', 'sc.aclId','=', false); 779 780 $aclWhereCriteria = \GO\Base\Db\FindCriteria::newInstance() 781 ->addInCondition("groupId", \GO\Base\Model\User::getGroupIds(\GO::user()->id),"a", false); 782 783 $storeParams->join(\GO\Base\Model\AclUsersGroups::model()->tableName(), $aclJoinCriteria, 'a', 'INNER'); 784 785 $storeParams->criteria(\GO\Base\Db\FindCriteria::newInstance() 786 ->addModel(Folder::model()) 787 ->mergeWith($aclWhereCriteria)); 788 789 $storeParams->group(array('t.id'))->order('mtime','DESC'); 790 791 $storeParams->getCriteria()->addCondition('mtime', \GO\Base\Util\Date::date_add(\GO\Base\Util\Date::clear_time(time()),-7),'>'); 792 793 if ($start!==false) 794 $storeParams->start($start); 795 if ($limit!==false) 796 $storeParams->limit($limit); 797 798 return $this->find($storeParams); 799 } 800 801 public function getHandlers(){ 802 $handlers=array(); 803 $classes = \GO\Files\FilesModule::getAllFileHandlers(); 804 foreach($classes as $class){ 805 806 $fileHandler = new $class; 807 if($fileHandler->fileIsSupported($this)){ 808 $handlers[]= $fileHandler; 809 } 810 } 811 812 return $handlers; 813 } 814 815 816 public static $defaultHandlers; 817 /** 818 * 819 * @return \GO\Files\Filehandler\FilehandlerInterface 820 */ 821 public function getDefaultHandler(){ 822 823 $ex = strtolower($this->extension); 824 825 if(!isset(self::$defaultHandlers[$ex])){ 826 $fh = FileHandler::model()->findByPk( 827 array('extension'=>$ex, 'user_id'=>\GO::user()->id)); 828 829 if($fh && class_exists($fh->cls)){ 830 self::$defaultHandlers[$ex]=new $fh->cls; 831 }else{ 832 $classes = \GO\Files\FilesModule::getAllFileHandlers(); 833 foreach($classes as $class){ 834 835// $fileHandler = new $class->name; 836 $fileHandler = new $class(); 837 if($fileHandler->isDefault($this)){ 838 self::$defaultHandlers[$ex]= $fileHandler; 839 break; 840 } 841 } 842 843 if(!isset(self::$defaultHandlers[$ex])) 844 self::$defaultHandlers[$ex]=new \GO\Files\Filehandler\Download(); 845 } 846 } 847 848 return self::$defaultHandlers[$ex]; 849 850 851 } 852 853 /** 854 * Returns this file as swift attachment 855 * 856 * @param string $altName 857 * @return Swift_Attachment 858 */ 859 public function getAttachment($altName = null) { 860 861 $fullPath = $this->getFsFile()->path(); 862 863 $attachment = \Swift_Attachment::fromPath($fullPath); 864 865 if($altName !== null){ 866 $attachment->setFilename($altName); 867 } 868 869 return $attachment; 870 } 871 872 /** 873 * @param GO\Base\Fs\File $outputFile 874 * @param string $format 875 * @throws NotFound 876 */ 877 public function convertTo(\GO\Base\Fs\File $outputFile, $format = 'pdf') 878 { 879 $converterModule = go()->getModule('business', 'fileconverter'); 880 if (!$converterModule) { 881 throw new NotFound('Converter module is not available'); 882 } 883 884 $service = \go\modules\business\fileconverter\Module::getAvailableService(); 885 $service->convert($this->fsFile, $outputFile, $format); 886 } 887} 888