diff --git a/app/Http/Controllers/DocumentController.php b/app/Http/Controllers/DocumentController.php index 03b1ffa917..4b7718bfd8 100644 --- a/app/Http/Controllers/DocumentController.php +++ b/app/Http/Controllers/DocumentController.php @@ -27,16 +27,15 @@ class DocumentController extends BaseController public function get($publicId) { $document = Document::scope($publicId) - ->withTrashed() ->firstOrFail(); if(!$this->checkViewPermission($document, $response)){ return $response; } - $public_url = $document->getPublicUrl(); - if($public_url){ - return redirect($public_url); + $direct_url = $document->getDirectUrl(); + if($direct_url){ + return redirect($direct_url); } @@ -46,9 +45,34 @@ class DocumentController extends BaseController return $response; } + public function getPreview($publicId) + { + $document = Document::scope($publicId) + ->firstOrFail(); + + if(!$this->checkViewPermission($document, $response)){ + return $response; + } + + if(empty($document->preview)){ + return Response::view('error', array('error'=>'Preview does not exist!'), 404); + } + + $direct_url = $document->getDirectPreviewUrl(); + if($direct_url){ + return redirect($direct_url); + } + + $extension = pathinfo($document->preview, PATHINFO_EXTENSION); + $response = Response::make($document->getRawPreview(), 200); + $response->header('content-type', Document::$extensions[$extension]); + + return $response; + } + public function postUpload() { - if (!Auth::user()->account->isPro()) { + if (!Utils::isPro()) { return; } diff --git a/app/Http/routes.php b/app/Http/routes.php index f9156ffc84..6a4970194c 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -133,6 +133,7 @@ Route::group(['middleware' => 'auth:user'], function() { Route::post('recurring_invoices/bulk', 'InvoiceController@bulk'); Route::get('document/{public_id}/{filename?}', 'DocumentController@get'); + Route::get('document/preview/{public_id}/{filename?}', 'DocumentController@getPreview'); Route::post('document', 'DocumentController@postUpload'); Route::get('quotes/create/{client_id?}', 'QuoteController@create'); @@ -428,7 +429,8 @@ if (!defined('CONTACT_EMAIL')) { define('MAX_IFRAME_URL_LENGTH', 250); define('MAX_LOGO_FILE_SIZE', 200); // KB define('MAX_FAILED_LOGINS', 10); - define('DEFAULT_MAX_DOCUMENT_SIZE', 10000);// KB + define('MAX_DOCUMENT_SIZE', env('MAX_DOCUMENT_SIZE', 10000));// KB + define('DOCUMENT_PREVIEW_SIZE', env('DOCUMENT_PREVIEW_SIZE', 150));// pixels define('DEFAULT_FONT_SIZE', 9); define('DEFAULT_HEADER_FONT', 1);// Roboto define('DEFAULT_BODY_FONT', 1);// Roboto diff --git a/app/Models/Account.php b/app/Models/Account.php index 26e1e0f6b7..4f8b6834ba 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -6,6 +6,7 @@ use Session; use DateTime; use Event; use Cache; +use Document; use App; use File; use App\Events\UserSettingsChanged; @@ -393,7 +394,7 @@ class Account extends Eloquent } public function getLogoDisk(){ - return Storage::disk(env('LOGO_DISK', 'logos')); + return Storage::disk(env('LOGO_FILESYSTEM', 'logos')); } protected function calculateLogoDetails(){ @@ -442,7 +443,7 @@ class Account extends Eloquent } } - return null; + Document::getDirectFileUrl($this->logo, $this->getDisk()); } public function getToken($name) diff --git a/app/Models/Document.php b/app/Models/Document.php index 8f1a01448f..f342d1ff08 100644 --- a/app/Models/Document.php +++ b/app/Models/Document.php @@ -1,7 +1,7 @@ 'image/png', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', 'pdf' => 'application/pdf', 'gif' => 'image/gif' ); @@ -16,32 +18,27 @@ class Document extends EntityModel public static $types = array( 'image/png' => array( 'extension' => 'png', - 'image' => true, ), 'image/jpeg' => array( 'extension' => 'jpeg', - 'image' => true, + ), + 'image/tiff' => array( + 'extension' => 'tiff', ), 'image/gif' => array( 'extension' => 'gif', - 'image' => true, ), 'application/pdf' => array( 'extension' => 'pdf', ), ); - // Expenses - use SoftDeletes; - - protected $dates = ['deleted_at']; - public function fill(array $attributes) { parent::fill($attributes); if(empty($this->attributes['disk'])){ - $this->attributes['disk'] = env('LOGO_DISK', 'documents'); + $this->attributes['disk'] = env('DOCUMENT_FILESYSTEM', 'documents'); } return $this; @@ -68,17 +65,53 @@ class Document extends EntityModel } public function getDisk(){ - return Storage::disk(!empty($this->disk)?$this->disk:env('LOGO_DISK', 'documents')); + return Storage::disk(!empty($this->disk)?$this->disk:env('DOCUMENT_FILESYSTEM', 'documents')); } public function setDiskAttribute($value) { - $this->attributes['disk'] = $value?$value:env('LOGO_DISK', 'documents'); + $this->attributes['disk'] = $value?$value:env('DOCUMENT_FILESYSTEM', 'documents'); } - public function getPublicUrl(){ - $disk = $this->getDisk(); + 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; } @@ -89,14 +122,49 @@ class Document extends EntityModel return $disk->get($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 getPreviewUrl(){ + return $this->preview?url('document/preview/'.$this->public_id.'/'.$this->name.'.'.pathinfo($this->preview, PATHINFO_EXTENSION)):null; + } + public function toArray() { $array = parent::toArray(); $array['url'] = $this->getUrl(); + $array['preview_url'] = $this->getPreviewUrl(); return $array; } -} \ No newline at end of file +} + +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); + } + } + +}); \ No newline at end of file diff --git a/app/Models/EntityModel.php b/app/Models/EntityModel.php index aa6544e52f..53bb1d0d1a 100644 --- a/app/Models/EntityModel.php +++ b/app/Models/EntityModel.php @@ -24,9 +24,14 @@ class EntityModel extends Eloquent Utils::fatalError(); } - $lastEntity = $className::withTrashed() - ->scope(false, $entity->account_id) - ->orderBy('public_id', 'DESC') + if(method_exists($className, 'withTrashed')){ + $lastEntity = $className::withTrashed() + ->scope(false, $entity->account_id); + } else { + $lastEntity = $className::scope(false, $entity->account_id); + } + + $lastEntity = $lastEntity->orderBy('public_id', 'DESC') ->first(); if ($lastEntity) { diff --git a/app/Ninja/Repositories/DocumentRepository.php b/app/Ninja/Repositories/DocumentRepository.php index 97bd375007..8697a23262 100644 --- a/app/Ninja/Repositories/DocumentRepository.php +++ b/app/Ninja/Repositories/DocumentRepository.php @@ -5,7 +5,7 @@ use Utils; use Response; use App\Models\Document; use App\Ninja\Repositories\BaseRepository; -use Intervention\Image\Facades\Image; +use Intervention\Image\ImageManager; use Session; class DocumentRepository extends BaseRepository @@ -20,8 +20,6 @@ class DocumentRepository extends BaseRepository { return Document::scope() ->with('user') - ->withTrashed() - ->where('is_deleted', '=', false) ->get(); } @@ -72,48 +70,80 @@ class DocumentRepository extends BaseRepository $documentType = Document::$extensions[$extension]; $filePath = $uploaded->path(); - $fileContents = null; $name = $uploaded->getClientOriginalName(); - if(filesize($filePath)/1000 > env('MAX_DOCUMENT_SIZE', DEFAULT_MAX_DOCUMENT_SIZE)){ + if(filesize($filePath)/1000 > MAX_DOCUMENT_SIZE){ return Response::json([ 'error' => 'File too large', 'code' => 400 ], 400); } - if($documentType == 'image/gif'){ - // Convert gif to png - $img = Image::make($filePath); - - $fileContents = (string) $img->encode('png'); - $documentType = 'image/png'; - $name = pathinfo($name)['filename'].'.png'; - } - $documentTypeData = Document::$types[$documentType]; - - $hash = $fileContents?sha1($fileContents):sha1_file($filePath); + $hash = sha1_file($filePath); $filename = \Auth::user()->account->account_key.'/'.$hash.'.'.$documentTypeData['extension']; $document = Document::createNew(); $disk = $document->getDisk(); if(!$disk->exists($filename)){// Have we already stored the same file - $disk->put($filename, $fileContents?$fileContents:file_get_contents($filePath)); + $disk->put($filename, file_get_contents($filePath)); + } + + // This is an image; check if we need to create a preview + if(in_array($documentType, array('image/jpeg','image/png','image/gif','image/bmp','image/tiff'))){ + $makePreview = false; + $imageSize = getimagesize($filePath); + $imgManagerConfig = array(); + if(in_array($documentType, array('image/gif','image/bmp','image/tiff'))){ + // Needs to be converted + $makePreview = true; + } else { + if($imageSize[0] > DOCUMENT_PREVIEW_SIZE || $imageSize[1] > DOCUMENT_PREVIEW_SIZE){ + $makePreview = true; + } + } + + if($documentType == 'image/bmp' || $documentType == 'image/tiff'){ + if(!class_exists('Imagick')){ + // Cant't read this + $makePreview = false; + } else { + $imgManagerConfig['driver'] = 'imagick'; + } + } + + if($makePreview){ + $previewType = 'jpg'; + if(in_array($documentType, array('image/png','image/gif','image/bmp','image/tiff'))){ + // Has transparency + $previewType = 'png'; + } + + $document->preview = \Auth::user()->account->account_key.'/'.$hash.'.'.$documentTypeData['extension'].'.x'.DOCUMENT_PREVIEW_SIZE.'.'.$previewType; + if(!$disk->exists($document->preview)){ + // We haven't created a preview yet + $imgManager = new ImageManager($imgManagerConfig); + + $img = $imgManager->make($filePath); + $img->fit(DOCUMENT_PREVIEW_SIZE, DOCUMENT_PREVIEW_SIZE, function ($constraint) { + $constraint->upsize(); + }); + + $previewContent = (string) $img->encode($previewType); + $disk->put($document->preview, $previewContent); + } + } } $document->path = $filename; $document->type = $documentType; - $document->size = $fileContents?strlen($fileContents):filesize($filePath); + $document->size = filesize($filePath); $document->name = substr($name, -255); - if(!empty($documentTypeData['image'])){ - $imageSize = getimagesize($filePath); - if($imageSize){ - $document->width = $imageSize[0]; - $document->height = $imageSize[1]; - } + if(!empty($imageSize)){ + $document->width = $imageSize[0]; + $document->height = $imageSize[1]; } $document->save(); diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index a2b94af80e..d69df1e2ae 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -399,7 +399,8 @@ class InvoiceRepository extends BaseRepository $invoice->invoice_items()->forceDelete(); } - foreach ($data['documents'] as $document_id){ + $document_ids = !empty($data['documents'])?array_map('intval', $data['documents']):array();; + foreach ($document_ids as $document_id){ $document = Document::scope($document_id)->first(); if($document && !$checkSubPermissions || $document->canEdit()){ $document->invoice_id = $invoice->id; @@ -408,7 +409,7 @@ class InvoiceRepository extends BaseRepository } foreach ($invoice->documents as $document){ - if(!in_array($document->id, $data['documents'])){ + if(!in_array($document->public_id, $document_ids)){ // Removed if(!$checkSubPermissions || $document->canEdit()){ $document->delete(); diff --git a/composer.json b/composer.json index 45e6e18726..9a52431d45 100644 --- a/composer.json +++ b/composer.json @@ -66,7 +66,9 @@ "maatwebsite/excel": "~2.0", "ezyang/htmlpurifier": "~v4.7", "cerdic/css-tidy": "~v1.5", - "asgrim/ofxparser": "^1.1" + "asgrim/ofxparser": "^1.1", + "league/flysystem-aws-s3-v3": "~1.0", + "league/flysystem-rackspace": "~1.0" }, "require-dev": { "phpunit/phpunit": "~4.0", diff --git a/composer.lock b/composer.lock index 6ce01e65ba..74b6ceefec 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "e5e8524886bd38794a15e406acc3745a", - "content-hash": "6b3f343959ba3f330c425325574dfe28", + "hash": "aa7451471a31552d5d6dce491ec20272", + "content-hash": "d70446a01a12bb41eece33b979adc975", "packages": [ { "name": "agmscode/omnipay-agms", @@ -321,6 +321,86 @@ ], "time": "2015-12-11 11:08:57" }, + { + "name": "aws/aws-sdk-php", + "version": "3.17.1", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "f8c0cc9357e10896a5c57104f2c79d1b727d97d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f8c0cc9357e10896a5c57104f2c79d1b727d97d0", + "reference": "f8c0cc9357e10896a5c57104f2c79d1b727d97d0", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~5.3|~6.0.1|~6.1", + "guzzlehttp/promises": "~1.0", + "guzzlehttp/psr7": "~1.0", + "mtdowling/jmespath.php": "~2.2", + "php": ">=5.5" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-json": "*", + "ext-openssl": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "ext-spl": "*", + "nette/neon": "^2.3", + "phpunit/phpunit": "~4.0|~5.0", + "psr/cache": "^1.0" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Aws\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "time": "2016-03-22 19:19:22" + }, { "name": "barryvdh/laravel-debugbar", "version": "v2.2.0", @@ -579,7 +659,7 @@ "laravel" ], "abandoned": "OpenSkill/Datatable", - "time": "2015-04-29 07:00:36" + "time": "2015-11-23 21:33:41" }, { "name": "classpreloader/classpreloader", @@ -3056,6 +3136,100 @@ ], "time": "2016-03-14 21:54:11" }, + { + "name": "league/flysystem-aws-s3-v3", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", + "reference": "595e24678bf78f8107ebc9355d8376ae0eb712c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/595e24678bf78f8107ebc9355d8376ae0eb712c6", + "reference": "595e24678bf78f8107ebc9355d8376ae0eb712c6", + "shasum": "" + }, + "require": { + "aws/aws-sdk-php": "^3.0.0", + "league/flysystem": "~1.0", + "php": ">=5.5.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "^2.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\AwsS3v3\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for the AWS S3 SDK v3.x", + "time": "2015-11-19 08:44:16" + }, + { + "name": "league/flysystem-rackspace", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-rackspace.git", + "reference": "ba877e837f5dce60e78a0555de37eb9bfc7dd6b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-rackspace/zipball/ba877e837f5dce60e78a0555de37eb9bfc7dd6b9", + "reference": "ba877e837f5dce60e78a0555de37eb9bfc7dd6b9", + "shasum": "" + }, + "require": { + "league/flysystem": "~1.0", + "php": ">=5.4.0", + "rackspace/php-opencloud": "~1.16" + }, + "require-dev": { + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\Rackspace\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for Rackspace", + "time": "2016-03-11 12:13:42" + }, { "name": "league/fractal", "version": "0.13.0", @@ -3585,6 +3759,33 @@ ], "time": "2015-07-14 19:53:54" }, + { + "name": "mikemccabe/json-patch-php", + "version": "0.1.0", + "source": { + "type": "git", + "url": "https://github.com/mikemccabe/json-patch-php.git", + "reference": "b3af30a6aec7f6467c773cd49b2d974a70f7c0d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikemccabe/json-patch-php/zipball/b3af30a6aec7f6467c773cd49b2d974a70f7c0d4", + "reference": "b3af30a6aec7f6467c773cd49b2d974a70f7c0d4", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "mikemccabe\\JsonPatch\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "description": "Produce and apply json-patch objects", + "time": "2015-01-05 21:19:54" + }, { "name": "monolog/monolog", "version": "1.18.1", @@ -3707,6 +3908,61 @@ ], "time": "2016-01-26 21:23:30" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "192f93e43c2c97acde7694993ab171b3de284093" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/192f93e43c2c97acde7694993ab171b3de284093", + "reference": "192f93e43c2c97acde7694993ab171b3de284093", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "JmesPath\\": "src/" + }, + "files": [ + "src/JmesPath.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "time": "2016-01-05 18:25:05" + }, { "name": "nesbot/carbon", "version": "1.21.0", @@ -5906,6 +6162,63 @@ ], "time": "2016-03-09 05:03:14" }, + { + "name": "rackspace/php-opencloud", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/rackspace/php-opencloud.git", + "reference": "d6b71feed7f9e7a4b52e0240a79f06473ba69c8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rackspace/php-opencloud/zipball/d6b71feed7f9e7a4b52e0240a79f06473ba69c8c", + "reference": "d6b71feed7f9e7a4b52e0240a79f06473ba69c8c", + "shasum": "" + }, + "require": { + "guzzle/guzzle": "~3.8", + "mikemccabe/json-patch-php": "~0.1", + "php": ">=5.4", + "psr/log": "~1.0" + }, + "require-dev": { + "apigen/apigen": "~4.0", + "fabpot/php-cs-fixer": "1.0.*@dev", + "jakub-onderka/php-parallel-lint": "0.*", + "phpspec/prophecy": "~1.4", + "phpunit/phpunit": "4.3.*", + "satooshi/php-coveralls": "0.6.*@dev" + }, + "type": "library", + "autoload": { + "psr-0": { + "OpenCloud": [ + "lib/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Jamie Hannaford", + "email": "jamie.hannaford@rackspace.com", + "homepage": "https://github.com/jamiehannaford" + } + ], + "description": "PHP SDK for Rackspace/OpenStack APIs", + "keywords": [ + "Openstack", + "nova", + "opencloud", + "rackspace", + "swift" + ], + "time": "2016-01-29 10:34:57" + }, { "name": "samvaughton/omnipay-barclays-epdq", "version": "2.2.0", diff --git a/config/filesystems.php b/config/filesystems.php index d0c683352b..da16e0e167 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -62,7 +62,7 @@ return [ 'driver' => 's3', 'key' => env('S3_KEY', ''), 'secret' => env('S3_SECRET', ''), - 'region' => env('S3_REGION', ''), + 'region' => env('S3_REGION', 'us-east-1'), 'bucket' => env('S3_BUCKET', ''), ], @@ -72,7 +72,7 @@ return [ 'key' => env('RACKSPACE_KEY', ''), 'container' => env('RACKSPACE_CONTAINER', ''), 'endpoint' => env('RACKSPACE_ENDPOINT', 'https://identity.api.rackspacecloud.com/v2.0/'), - 'region' => env('RACKSPACE_REGION', 'https://identity.api.rackspacecloud.com/v2.0/'), + 'region' => env('RACKSPACE_REGION', 'IAD'), 'url_type' => env('RACKSPACE_URL_TYPE', 'publicURL') ], diff --git a/database/migrations/2016_03_22_168362_add_documents.php b/database/migrations/2016_03_22_168362_add_documents.php index 811fb3a1a5..f37ab0e859 100644 --- a/database/migrations/2016_03_22_168362_add_documents.php +++ b/database/migrations/2016_03_22_168362_add_documents.php @@ -28,6 +28,7 @@ class AddDocuments extends Migration { $t->unsignedInteger('invoice_id')->nullable(); $t->unsignedInteger('expense_id')->nullable(); $t->string('path'); + $t->string('preview'); $t->string('name'); $t->string('type'); $t->string('disk'); @@ -36,7 +37,6 @@ class AddDocuments extends Migration { $t->unsignedInteger('height')->nullable(); $t->timestamps(); - $t->softDeletes(); $t->foreign('account_id')->references('id')->on('accounts'); $t->foreign('user_id')->references('id')->on('users'); diff --git a/resources/views/invoices/edit.blade.php b/resources/views/invoices/edit.blade.php index 59c662ccb5..0a9810d416 100644 --- a/resources/views/invoices/edit.blade.php +++ b/resources/views/invoices/edit.blade.php @@ -932,7 +932,7 @@ }, acceptedFiles:{!! json_encode(implode(',',array_keys(\App\Models\Document::$types))) !!}, addRemoveLinks:true, - maxFileSize:{{floatval(env('MAX_DOCUMENT_SIZE', DEFAULT_MAX_DOCUMENT_SIZE)/1000)}}, + maxFileSize:{{floatval(MAX_DOCUMENT_SIZE/1000)}}, dictDefaultMessage:{!! json_encode(trans('texts.document_upload_message')) !!} }); dropzone.on("addedfile",handleDocumentAdded); @@ -948,7 +948,7 @@ public_id:document.public_id(), status:Dropzone.SUCCESS, accepted:true, - url:document.url(), + url:document.preview_url()||document.url(), mock:true, index:i }; @@ -956,7 +956,7 @@ dropzone.emit('addedfile', mockFile); dropzone.emit('complete', mockFile); if(document.type().match(/image.*/)){ - dropzone.emit('thumbnail', mockFile, document.url()); + dropzone.emit('thumbnail', mockFile, document.preview_url()||document.url()); } dropzone.files.push(mockFile); }