mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 10:17:33 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			263 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php namespace App\Models;
 | |
| 
 | |
| use Illuminate\Support\Facades\Storage;
 | |
| use DB;
 | |
| use Auth;
 | |
| 
 | |
| class Document extends EntityModel
 | |
| {
 | |
|     public static $extraExtensions = array(
 | |
|         'jpg' => 'jpeg',
 | |
|         'tif' => 'tiff',
 | |
|     );
 | |
|     
 | |
|     public static $allowedMimes = array(// Used by Dropzone.js; does not affect what the server accepts
 | |
|         'image/png', 'image/jpeg', 'image/tiff', 'application/pdf', 'image/gif', 'image/vnd.adobe.photoshop', 'text/plain',
 | |
|         'application/zip', 'application/msword',
 | |
|         'application/excel', 'application/vnd.ms-excel', 'application/x-excel', 'application/x-msexcel', 
 | |
|         'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
 | |
|         'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet','application/postscript', 'image/svg+xml',
 | |
|         'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.ms-powerpoint',
 | |
|     );
 | |
|     
 | |
|     public static $types = array(
 | |
|         'png' => array(
 | |
|             'mime' => 'image/png',
 | |
|         ),
 | |
|         'ai' => array(
 | |
|             'mime' => 'application/postscript',
 | |
|         ),
 | |
|         'svg' => array(
 | |
|             'mime' => 'image/svg+xml',
 | |
|         ),
 | |
|         'jpeg' => array(
 | |
|             'mime' => 'image/jpeg',
 | |
|         ),
 | |
|         'tiff' => array(
 | |
|             'mime' => 'image/tiff',
 | |
|         ),
 | |
|         'pdf' => array(
 | |
|             'mime' => 'application/pdf',
 | |
|         ),
 | |
|         'gif' => array(
 | |
|             'mime' => 'image/gif',
 | |
|         ),
 | |
|         'psd' => array(
 | |
|             'mime' => 'image/vnd.adobe.photoshop',
 | |
|         ),
 | |
|         'txt' => array(
 | |
|             'mime' => 'text/plain',
 | |
|         ),
 | |
|         'zip' => array(
 | |
|             'mime' => 'application/zip',
 | |
|         ),
 | |
|         'doc' => array(
 | |
|             'mime' => 'application/msword',
 | |
|         ),
 | |
|         'xls' => array(
 | |
|             'mime' => 'application/vnd.ms-excel',
 | |
|         ),
 | |
|         'ppt' => array(
 | |
|             'mime' => 'application/vnd.ms-powerpoint',
 | |
|         ),
 | |
|         'xlsx' => array(
 | |
|             'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
 | |
|         ),
 | |
|         'docx' => array(
 | |
|             'mime' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
 | |
|         ),
 | |
|         'pptx' => array(
 | |
|             'mime' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
 | |
|         ),
 | |
|     );
 | |
|     
 | |
|     public function fill(array $attributes)
 | |
|     {
 | |
|         parent::fill($attributes);
 | |
|         
 | |
|         if(empty($this->attributes['disk'])){
 | |
|             $this->attributes['disk'] = env('DOCUMENT_FILESYSTEM', 'documents');
 | |
|         }
 | |
|         
 | |
|         return $this;
 | |
|     }
 | |
|     
 | |
|     public function account()
 | |
|     {
 | |
|         return $this->belongsTo('App\Models\Account');
 | |
|     }
 | |
| 
 | |
|     public function user()
 | |
|     {
 | |
|         return $this->belongsTo('App\Models\User');
 | |
|     }
 | |
| 
 | |
|     public function expense()
 | |
|     {
 | |
|         return $this->belongsTo('App\Models\Expense')->withTrashed();
 | |
|     }
 | |
| 
 | |
|     public function invoice()
 | |
|     {
 | |
|         return $this->belongsTo('App\Models\Invoice')->withTrashed();
 | |
|     }
 | |
|     
 | |
|     public function getDisk(){
 | |
|         return Storage::disk(!empty($this->disk)?$this->disk:env('DOCUMENT_FILESYSTEM', 'documents'));
 | |
|     }
 | |
| 
 | |
|     public function setDiskAttribute($value)
 | |
|     {
 | |
|         $this->attributes['disk'] = $value?$value:env('DOCUMENT_FILESYSTEM', 'documents');
 | |
|     }
 | |
|     
 | |
|     public function getDirectUrl(){
 | |
|         return static::getDirectFileUrl($this->path, $this->getDisk());
 | |
|     }
 | |
|     
 | |
|     public function getDirectPreviewUrl(){
 | |
|         return $this->preview?static::getDirectFileUrl($this->preview, $this->getDisk(), true):null;
 | |
|     }
 | |
|     
 | |
|     public static function getDirectFileUrl($path, $disk, $prioritizeSpeed = false){
 | |
|         $adapter = $disk->getAdapter();
 | |
|         $fullPath = $adapter->applyPathPrefix($path);
 | |
|         
 | |
|         if($adapter instanceof \League\Flysystem\AwsS3v3\AwsS3Adapter) {
 | |
|             $client = $adapter->getClient();
 | |
|             $command = $client->getCommand('GetObject', [
 | |
|                 'Bucket' => $adapter->getBucket(),
 | |
|                 'Key'    => $fullPath
 | |
|             ]);
 | |
| 
 | |
|             return (string) $client->createPresignedRequest($command, '+10 minutes')->getUri();
 | |
|         } else if (!$prioritizeSpeed // Rackspace temp URLs are slow, so we don't use them for previews
 | |
|                    && $adapter instanceof \League\Flysystem\Rackspace\RackspaceAdapter) {
 | |
|             $secret = env('RACKSPACE_TEMP_URL_SECRET');
 | |
|             if($secret){
 | |
|                 $object = $adapter->getContainer()->getObject($fullPath);
 | |
|                 
 | |
|                 if(env('RACKSPACE_TEMP_URL_SECRET_SET')){
 | |
|                     // Go ahead and set the secret too
 | |
|                     $object->getService()->getAccount()->setTempUrlSecret($secret);
 | |
|                 }            
 | |
|                 
 | |
|                 $url = $object->getUrl();
 | |
|                 $expiry = strtotime('+10 minutes');
 | |
|                 $urlPath = urldecode($url->getPath());
 | |
|                 $body = sprintf("%s\n%d\n%s", 'GET', $expiry, $urlPath);
 | |
|                 $hash = hash_hmac('sha1', $body, $secret);
 | |
|                 return sprintf('%s?temp_url_sig=%s&temp_url_expires=%d', $url, $hash, $expiry);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return null;
 | |
|     }
 | |
|     
 | |
|     public function getRaw(){
 | |
|         $disk = $this->getDisk();
 | |
|         
 | |
|         return $disk->get($this->path);
 | |
|     }
 | |
|     
 | |
|     public function getStream(){
 | |
|         $disk = $this->getDisk();
 | |
|         
 | |
|         return $disk->readStream($this->path);
 | |
|     }
 | |
|     
 | |
|     public function getRawPreview(){
 | |
|         $disk = $this->getDisk();
 | |
|         
 | |
|         return $disk->get($this->preview);
 | |
|     }
 | |
|     
 | |
|     public function getUrl(){
 | |
|         return url('document/'.$this->public_id.'/'.$this->name);
 | |
|     }
 | |
|     
 | |
|     public function getClientUrl($invitation){
 | |
|         return url('client/document/'.$invitation->invitation_key.'/'.$this->public_id.'/'.$this->name);
 | |
|     }
 | |
|     
 | |
|     public function isPDFEmbeddable(){
 | |
|         return $this->type == 'jpeg' || $this->type == 'png' || $this->preview;
 | |
|     }
 | |
|     
 | |
|     public function getVFSJSUrl(){
 | |
|         if(!$this->isPDFEmbeddable())return null;
 | |
|         return url('document/js/'.$this->public_id.'/'.$this->name.'.js');
 | |
|     }
 | |
|     
 | |
|     public function getClientVFSJSUrl(){
 | |
|         if(!$this->isPDFEmbeddable())return null;
 | |
|         return url('client/document/js/'.$this->public_id.'/'.$this->name.'.js');
 | |
|     }
 | |
|     
 | |
|     public function getPreviewUrl(){
 | |
|         return $this->preview?url('document/preview/'.$this->public_id.'/'.$this->name.'.'.pathinfo($this->preview, PATHINFO_EXTENSION)):null;
 | |
|     }
 | |
|     
 | |
|     public function toArray()
 | |
|     {
 | |
|         $array = parent::toArray();
 | |
|         
 | |
|         if(empty($this->visible) || in_array('url', $this->visible))$array['url'] = $this->getUrl();
 | |
|         if(empty($this->visible) || in_array('preview_url', $this->visible))$array['preview_url'] = $this->getPreviewUrl();
 | |
|         
 | |
|         return $array;
 | |
|     }
 | |
|     
 | |
|     public function cloneDocument(){
 | |
|         $document = Document::createNew($this);
 | |
|         $document->path = $this->path;
 | |
|         $document->preview = $this->preview;
 | |
|         $document->name = $this->name;
 | |
|         $document->type = $this->type;
 | |
|         $document->disk = $this->disk;
 | |
|         $document->hash = $this->hash;
 | |
|         $document->size = $this->size;
 | |
|         $document->width = $this->width;
 | |
|         $document->height = $this->height;
 | |
|         
 | |
|         return $document;
 | |
|     }
 | |
|     
 | |
|     public static function canCreate(){
 | |
|         return true;
 | |
|     }
 | |
|     
 | |
|     public static function canViewItem($document){
 | |
|         if(Auth::user()->hasPermission('view_all'))return true;
 | |
|         if($document->expense){
 | |
|             if($document->expense->invoice)return $document->expense->invoice->canView();
 | |
|             return $document->expense->canView();
 | |
|         }
 | |
|         if($document->invoice)return $document->invoice->canView();
 | |
|         return Auth::user()->id == $item->user_id;
 | |
|     }
 | |
| }
 | |
| 
 | |
| Document::deleted(function ($document) {
 | |
|     $same_path_count = DB::table('documents')
 | |
|         ->where('documents.account_id', '=', $document->account_id)
 | |
|         ->where('documents.path', '=', $document->path)
 | |
|         ->where('documents.disk', '=', $document->disk)
 | |
|         ->count();
 | |
|     
 | |
|     if(!$same_path_count){
 | |
|         $document->getDisk()->delete($document->path);
 | |
|     }
 | |
|     
 | |
|     if($document->preview){
 | |
|         $same_preview_count = DB::table('documents')
 | |
|             ->where('documents.account_id', '=', $document->account_id)
 | |
|             ->where('documents.preview', '=', $document->preview)
 | |
|             ->where('documents.disk', '=', $document->disk)
 | |
|             ->count();
 | |
|         if(!$same_preview_count){
 | |
|             $document->getDisk()->delete($document->preview);
 | |
|         }
 | |
|     }
 | |
|     
 | |
| }); |