1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-15 07:33:04 +01:00
invoiceninja/app/Models/Document.php

427 lines
11 KiB
PHP
Raw Normal View History

2017-01-30 20:40:43 +01:00
<?php
namespace App\Models;
2016-03-23 03:23:45 +01:00
2016-03-23 20:41:05 +01:00
use DB;
2017-01-30 20:40:43 +01:00
use Illuminate\Support\Facades\Storage;
2016-03-23 03:23:45 +01:00
/**
2017-01-30 20:40:43 +01:00
* Class Document.
*/
2016-03-23 03:23:45 +01:00
class Document extends EntityModel
{
2016-08-09 08:48:41 +02:00
/**
* @return mixed
*/
public function getEntityType()
{
return ENTITY_DOCUMENT;
}
/**
* @var array
*/
protected $fillable = [
'invoice_id',
'expense_id',
2017-07-20 21:45:10 +02:00
'is_default',
2019-01-30 12:00:26 +01:00
'ticket_id',
];
/**
* @var array
*/
public static $extraExtensions = [
'jpg' => 'jpeg',
'tif' => 'tiff',
];
/**
* @var array
*/
public static $allowedMimes = [// 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',
2016-06-05 17:50:41 +02:00
'application/msword',
'application/excel', 'application/vnd.ms-excel', 'application/x-excel', 'application/x-msexcel',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2017-01-30 20:40:43 +01:00
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/postscript', 'image/svg+xml',
'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.ms-powerpoint',
];
/**
* @var array
*/
public static $types = [
'png' => [
'mime' => 'image/png',
],
'ai' => [
'mime' => 'application/postscript',
],
'svg' => [
'mime' => 'image/svg+xml',
],
'jpeg' => [
'mime' => 'image/jpeg',
],
'tiff' => [
'mime' => 'image/tiff',
],
'pdf' => [
'mime' => 'application/pdf',
],
'gif' => [
'mime' => 'image/gif',
],
'psd' => [
'mime' => 'image/vnd.adobe.photoshop',
],
'txt' => [
'mime' => 'text/plain',
],
'doc' => [
'mime' => 'application/msword',
],
'xls' => [
'mime' => 'application/vnd.ms-excel',
],
'ppt' => [
'mime' => 'application/vnd.ms-powerpoint',
],
'xlsx' => [
'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
],
'docx' => [
'mime' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
],
'pptx' => [
'mime' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
],
];
/**
* @param array $attributes
2017-01-30 20:40:43 +01:00
*
* @return $this
*/
2016-03-23 03:23:45 +01:00
public function fill(array $attributes)
{
parent::fill($attributes);
2017-01-30 17:05:31 +01:00
if (empty($this->attributes['disk'])) {
2016-03-23 20:41:05 +01:00
$this->attributes['disk'] = env('DOCUMENT_FILESYSTEM', 'documents');
2016-03-23 03:23:45 +01:00
}
2016-03-23 03:23:45 +01:00
return $this;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
2016-03-23 03:23:45 +01:00
public function account()
{
return $this->belongsTo('App\Models\Account');
}
/**
* @return mixed
*/
2016-03-23 03:23:45 +01:00
public function user()
{
return $this->belongsTo('App\Models\User')->withTrashed();
2016-03-23 03:23:45 +01:00
}
/**
* @return mixed
*/
2016-03-23 03:23:45 +01:00
public function expense()
{
return $this->belongsTo('App\Models\Expense')->withTrashed();
}
2019-01-30 12:00:26 +01:00
/**
* @return mixed
*/
public function ticket()
{
return $this->belongsTo('App\Models\Ticket')->withTrashed();
}
/**
* @return mixed
*/
2016-03-23 03:23:45 +01:00
public function invoice()
{
return $this->belongsTo('App\Models\Invoice')->withTrashed();
}
/**
* @return mixed
*/
2017-01-30 17:05:31 +01:00
public function getDisk()
{
2017-01-30 20:40:43 +01:00
return Storage::disk(! empty($this->disk) ? $this->disk : env('DOCUMENT_FILESYSTEM', 'documents'));
2016-03-23 03:23:45 +01:00
}
/**
* @param $value
*/
2016-03-23 03:23:45 +01:00
public function setDiskAttribute($value)
{
2017-01-30 20:40:43 +01:00
$this->attributes['disk'] = $value ? $value : env('DOCUMENT_FILESYSTEM', 'documents');
2016-03-23 03:23:45 +01:00
}
/**
* @return null|string
*/
2017-01-30 17:05:31 +01:00
public function getDirectUrl()
{
2016-03-23 20:41:05 +01:00
return static::getDirectFileUrl($this->path, $this->getDisk());
}
/**
* @return null|string
*/
2017-01-30 17:05:31 +01:00
public function getDirectPreviewUrl()
{
2017-01-30 20:40:43 +01:00
return $this->preview ? static::getDirectFileUrl($this->preview, $this->getDisk(), true) : null;
2016-03-23 20:41:05 +01:00
}
/**
* @param $path
* @param $disk
* @param bool $prioritizeSpeed
2017-01-30 20:40:43 +01:00
*
* @throws \OpenCloud\Common\Exceptions\NoNameError
2017-01-30 20:40:43 +01:00
*
* @return null|string
*/
2017-01-30 17:05:31 +01:00
public static function getDirectFileUrl($path, $disk, $prioritizeSpeed = false)
{
2016-03-23 03:23:45 +01:00
$adapter = $disk->getAdapter();
2016-03-23 20:41:05 +01:00
$fullPath = $adapter->applyPathPrefix($path);
2017-01-30 17:05:31 +01:00
if ($adapter instanceof \League\Flysystem\AwsS3v3\AwsS3Adapter) {
2016-03-23 20:41:05 +01:00
$client = $adapter->getClient();
$command = $client->getCommand('GetObject', [
'Bucket' => $adapter->getBucket(),
2017-01-30 20:40:43 +01:00
'Key' => $fullPath,
2016-03-23 20:41:05 +01:00
]);
return (string) $client->createPresignedRequest($command, '+10 minutes')->getUri();
2017-01-30 20:40:43 +01:00
} elseif (! $prioritizeSpeed // Rackspace temp URLs are slow, so we don't use them for previews
2016-03-23 20:41:05 +01:00
&& $adapter instanceof \League\Flysystem\Rackspace\RackspaceAdapter) {
$secret = env('RACKSPACE_TEMP_URL_SECRET');
2017-01-30 17:05:31 +01:00
if ($secret) {
2016-03-23 20:41:05 +01:00
$object = $adapter->getContainer()->getObject($fullPath);
2017-01-30 17:05:31 +01:00
if (env('RACKSPACE_TEMP_URL_SECRET_SET')) {
2016-03-23 20:41:05 +01:00
// Go ahead and set the secret too
$object->getService()->getAccount()->setTempUrlSecret($secret);
}
2016-03-23 20:41:05 +01:00
$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);
2017-01-30 20:40:43 +01:00
2016-03-23 20:41:05 +01:00
return sprintf('%s?temp_url_sig=%s&temp_url_expires=%d', $url, $hash, $expiry);
}
}
2016-03-23 03:23:45 +01:00
return null;
}
/**
* @return mixed
*/
2017-01-30 17:05:31 +01:00
public function getRaw()
{
2016-03-23 03:23:45 +01:00
$disk = $this->getDisk();
2016-03-23 03:23:45 +01:00
return $disk->get($this->path);
}
2018-04-17 20:12:10 +02:00
/**
* @return mixed
*/
public function getRawCached()
{
$key = 'image:' . $this->path;
if ($image = cache($key)) {
// do nothing
} else {
$image = $this->getRaw();
cache([$key => $image], 120);
}
return $image;
}
/**
* @return mixed
*/
2017-01-30 17:05:31 +01:00
public function getStream()
{
2016-03-24 01:46:09 +01:00
$disk = $this->getDisk();
2016-03-24 01:46:09 +01:00
return $disk->readStream($this->path);
}
/**
* @return mixed
*/
2017-01-30 17:05:31 +01:00
public function getRawPreview()
{
2016-03-23 20:41:05 +01:00
$disk = $this->getDisk();
2016-03-23 20:41:05 +01:00
return $disk->get($this->preview);
}
/**
* @return \Illuminate\Contracts\Routing\UrlGenerator|string
*/
2017-01-30 17:05:31 +01:00
public function getUrl()
{
2016-05-01 21:30:39 +02:00
return url('documents/'.$this->public_id.'/'.$this->name);
2016-03-23 03:23:45 +01:00
}
2019-01-30 12:00:26 +01:00
public function getClientDocUrl()
{
return url('client/tickets/documents/'.$this->public_id.'/'.$this->name);
}
/**
* @param $invitation
2017-01-30 20:40:43 +01:00
*
* @return \Illuminate\Contracts\Routing\UrlGenerator|string
*/
2017-01-30 17:05:31 +01:00
public function getClientUrl($invitation)
{
2016-05-01 21:30:39 +02:00
return url('client/documents/'.$invitation->invitation_key.'/'.$this->public_id.'/'.$this->name);
2016-03-24 02:25:33 +01:00
}
2018-02-13 11:06:50 +01:00
public function getProposalUrl()
{
if (! $this->is_proposal || ! $this->document_key) {
return '';
}
return url('proposal/image/'. $this->account->account_key . '/' . $this->document_key . '/' . $this->name);
}
/**
* @return bool
*/
2017-01-30 17:05:31 +01:00
public function isPDFEmbeddable()
{
return $this->type == 'jpeg' || $this->type == 'png' || $this->preview;
}
/**
* @return \Illuminate\Contracts\Routing\UrlGenerator|null|string
*/
2017-01-30 17:05:31 +01:00
public function getVFSJSUrl()
{
2017-01-30 20:40:43 +01:00
if (! $this->isPDFEmbeddable()) {
2017-01-30 17:05:31 +01:00
return null;
}
2017-01-30 20:40:43 +01:00
2016-05-01 21:30:39 +02:00
return url('documents/js/'.$this->public_id.'/'.$this->name.'.js');
2016-03-23 23:40:42 +01:00
}
/**
* @return \Illuminate\Contracts\Routing\UrlGenerator|null|string
*/
2017-01-30 17:05:31 +01:00
public function getClientVFSJSUrl()
{
2017-01-30 20:40:43 +01:00
if (! $this->isPDFEmbeddable()) {
2017-01-30 17:05:31 +01:00
return null;
}
2017-01-30 20:40:43 +01:00
2016-05-01 21:30:39 +02:00
return url('client/documents/js/'.$this->public_id.'/'.$this->name.'.js');
2016-03-23 23:40:42 +01:00
}
/**
* @return \Illuminate\Contracts\Routing\UrlGenerator|null|string
*/
2017-01-30 17:05:31 +01:00
public function getPreviewUrl()
{
2017-01-30 20:40:43 +01:00
return $this->preview ? url('documents/preview/'.$this->public_id.'/'.$this->name.'.'.pathinfo($this->preview, PATHINFO_EXTENSION)) : null;
2016-03-23 20:41:05 +01:00
}
2019-01-30 12:00:26 +01:00
public function getClientPreviewUrl()
{
return $this->preview ? url('client/tickets/documents/preview/'.$this->public_id.'/'.$this->name.'.'.pathinfo($this->preview, PATHINFO_EXTENSION)) : null;
}
/**
* @return array
*/
2016-03-23 03:23:45 +01:00
public function toArray()
{
$array = parent::toArray();
2017-01-30 17:05:31 +01:00
if (empty($this->visible) || in_array('url', $this->visible)) {
$array['url'] = $this->getUrl();
2019-01-30 12:00:26 +01:00
$array['client_doc_url'] = $this->getClientDocUrl();
$array['client_preview_url'] = $this->getClientPreviewUrl();
2017-01-30 17:05:31 +01:00
}
2019-01-30 12:00:26 +01:00
2017-01-30 17:05:31 +01:00
if (empty($this->visible) || in_array('preview_url', $this->visible)) {
$array['preview_url'] = $this->getPreviewUrl();
}
2016-03-23 03:23:45 +01:00
return $array;
}
/**
* @return mixed
*/
2017-01-30 17:05:31 +01:00
public function cloneDocument()
{
2017-01-30 20:40:43 +01:00
$document = self::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;
}
2018-04-11 22:18:01 +02:00
public function scopeProposalImages($query)
{
return $query->whereIsProposal(1);
}
2016-03-23 20:41:05 +01:00
}
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();
2017-01-30 20:40:43 +01:00
if (! $same_path_count) {
2016-03-23 20:41:05 +01:00
$document->getDisk()->delete($document->path);
}
2017-01-30 17:05:31 +01:00
if ($document->preview) {
2016-03-23 20:41:05 +01:00
$same_preview_count = DB::table('documents')
->where('documents.account_id', '=', $document->account_id)
->where('documents.preview', '=', $document->preview)
->where('documents.disk', '=', $document->disk)
->count();
2017-01-30 20:40:43 +01:00
if (! $same_preview_count) {
2016-03-23 20:41:05 +01:00
$document->getDisk()->delete($document->preview);
}
}
});