From cebbee8445bec8517f8fef12c71c69abfbad9a42 Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Fri, 4 Aug 2017 09:37:52 +0800 Subject: [PATCH] Added file upload for project --- app/Entities/Projects/File.php | 20 ++++++ app/Entities/Projects/Project.php | 5 ++ app/Http/Controllers/Projects/FilesController.php | 77 ++++++++++++++++++++++ .../2017_08_03_235706_create_files_table.php | 37 +++++++++++ .../views/projects/features-export-html.blade.php | 6 +- resources/views/projects/files.blade.php | 58 ++++++++++++++++ .../views/projects/partials/nav-tabs.blade.php | 3 + routes/web/projects.php | 7 +- tests/Feature/Projects/UploadFilesTest.php | 38 +++++++++++ tests/TestCase.php | 8 +++ tests/Unit/Models/ProjectTest.php | 8 +++ 11 files changed, 263 insertions(+), 4 deletions(-) create mode 100644 app/Entities/Projects/File.php create mode 100644 app/Http/Controllers/Projects/FilesController.php create mode 100644 database/migrations/2017_08_03_235706_create_files_table.php create mode 100755 resources/views/projects/files.blade.php create mode 100644 tests/Feature/Projects/UploadFilesTest.php diff --git a/app/Entities/Projects/File.php b/app/Entities/Projects/File.php new file mode 100644 index 0000000..b18dcee --- /dev/null +++ b/app/Entities/Projects/File.php @@ -0,0 +1,20 @@ +morphTo(); + } + + public function project() + { + return $this->morphTo('fileable', Project::class); + } +} diff --git a/app/Entities/Projects/Project.php b/app/Entities/Projects/Project.php index 9166e39..c5563c3 100755 --- a/app/Entities/Projects/Project.php +++ b/app/Entities/Projects/Project.php @@ -82,4 +82,9 @@ class Project extends Model { return $overalProgress; } + public function files() + { + return $this->morphMany(File::class, 'fileable'); + } + } diff --git a/app/Http/Controllers/Projects/FilesController.php b/app/Http/Controllers/Projects/FilesController.php new file mode 100644 index 0000000..3960b10 --- /dev/null +++ b/app/Http/Controllers/Projects/FilesController.php @@ -0,0 +1,77 @@ + 'App\Entities\Projects\Project', + ]; + + public function index(Request $request, $fileableId) + { + $fileableType = $request->segment(1); // projects, features + $modelName = $this->getModelName($fileableType); + $modelShortName = $this->getModelShortName($modelName); + $model = $modelName::findOrFail($fileableId); + $files = $model->files; + + return view($fileableType.'.files', [$modelShortName => $model, 'files' => $files]); + } + + public function create(Request $request, $fileableId) + { + $fileableExist = array_search($request->get('fileable_type'), $this->fileableTypes); + + if ($fileableExist) { + $file = $this->proccessPhotoUpload($request->except('_token'), $request->get('fileable_type'), $fileableId); + + if ($file->exists) + flash()->success('Upload file berhasil.'); + else + flash()->error('Upload file gagal, coba kembali.'); + } else + flash()->error('Upload file gagal, coba kembali.'); + + return back(); + } + + private function proccessPhotoUpload($data, $fileableType, $fileableId) + { + // dd(get_class_methods($data['files'])); + $file = $data['files']; + // $fileName = md5(uniqid(rand(), true)).'.'.$file->getClientOriginalExtension(); + $fileName = $file->hashName(); + // dd($fileName); + + $fileData['fileable_id'] = $fileableId; + $fileData['fileable_type'] = $fileableType; + $fileData['filename'] = $fileName; + $fileData['title'] = $data['title']; + $fileData['description'] = $data['description']; + \DB::beginTransaction(); + // dd(is_dir(storage_path('app/public/files'))); + $file->storeAs('public/files', $fileName); + // $file->move(storage_path('app/public/files')); + $file = File::create($fileData); + \DB::commit(); + + return $file; + } + + + public function getModelName($fileableType) + { + return isset($this->fileableTypes[$fileableType]) ? $this->fileableTypes[$fileableType] : false; + } + + public function getModelShortName($modelName) + { + return strtolower((new \ReflectionClass($modelName))->getShortName()); + } +} diff --git a/database/migrations/2017_08_03_235706_create_files_table.php b/database/migrations/2017_08_03_235706_create_files_table.php new file mode 100644 index 0000000..6712f35 --- /dev/null +++ b/database/migrations/2017_08_03_235706_create_files_table.php @@ -0,0 +1,37 @@ +increments('id'); + $table->unsignedInteger('fileable_id'); + $table->string('fileable_type', 60); + $table->tinyInteger('type_id')->unsigned()->nullable(); + $table->string('filename', 60); + $table->string('title', 60); + $table->string('description')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('files'); + } +} diff --git a/resources/views/projects/features-export-html.blade.php b/resources/views/projects/features-export-html.blade.php index ca5a358..fc45327 100755 --- a/resources/views/projects/features-export-html.blade.php +++ b/resources/views/projects/features-export-html.blade.php @@ -17,15 +17,15 @@

{{ trans('project.features') }} {{ $project->name }}

@foreach($features as $key => $feature) -

{{ $feature->name }}

+

{{ 1 + $key }}. {{ $feature->name }}

- + @if ($feature->tasks->count()) - + diff --git a/resources/views/projects/files.blade.php b/resources/views/projects/files.blade.php new file mode 100755 index 0000000..53e5b5c --- /dev/null +++ b/resources/views/projects/files.blade.php @@ -0,0 +1,58 @@ +@extends('layouts.app') + +@section('title', trans('project.files') . ' | ' . $project->name) + +@section('content') +@include('projects.partials.breadcrumb',['title' => trans('project.files')]) + +

+ {{ $project->name }} {{ trans('project.files') }} +

+ +@include('projects.partials.nav-tabs') +
+
+
+
+

{{ trans('project.files') }}

+
+
{{ trans('app.description') }}
{{ trans('app.description') }}
{!! nl2br($feature->description) !!}
 
Sub Fitur {{ trans('app.description') }}
+ + + + + + + + @forelse($files as $key => $file) + + + + + + + @empty + + @endforelse + +
{{ trans('app.table_no') }}{{ trans('file.title') }}{{ trans('file.description') }}{{ trans('app.action') }}
{{ 1 + $key }}{{ $file->title }}{{ $file->description }}
{{ trans('file.empty') }}
+ + +
+
+

Upload new File

+
+ {!! Form::open(['route' => ['files.upload', $project->id], 'id' => 'upload-files', 'files' => true]) !!} + {{ Form::hidden('fileable_type', get_class($project)) }} + {!! FormField::file('files', ['label' => 'Upload File', 'placeholder' => 'Pilih File']) !!} + {!! FormField::text('title') !!} + {!! FormField::textarea('description') !!} + {!! Form::submit(trans('app.upload_files'), ['class' => 'btn btn-info']) !!} + {!! Form::close() !!} +
+
+
+ + + +@endsection \ No newline at end of file diff --git a/resources/views/projects/partials/nav-tabs.blade.php b/resources/views/projects/partials/nav-tabs.blade.php index 62dd77f..e22a456 100644 --- a/resources/views/projects/partials/nav-tabs.blade.php +++ b/resources/views/projects/partials/nav-tabs.blade.php @@ -12,5 +12,8 @@
  • {!! link_to_route('projects.subscriptions', trans('project.subscriptions'), [$project->id]) !!}
  • +
  • + {!! link_to_route('projects.files', trans('project.files'), [$project->id]) !!} +

  • \ No newline at end of file diff --git a/routes/web/projects.php b/routes/web/projects.php index 9744c42..00d8213 100644 --- a/routes/web/projects.php +++ b/routes/web/projects.php @@ -16,7 +16,6 @@ Route::group(['middleware' => ['web','role:admin'], 'namespace' => 'Projects'], /** * Features Routes */ - Route::get('projects/{id}/features/create', ['as'=>'features.create', 'uses'=>'FeaturesController@create']); Route::get('projects/{id}/features/add-from-other-project', ['as'=>'features.add-from-other-project', 'uses'=>'FeaturesController@addFromOtherProject']); Route::post('features/{id}/tasks-reorder', ['as'=>'features.tasks-reorder', 'uses'=>'FeaturesController@tasksReorder']); @@ -32,4 +31,10 @@ Route::group(['middleware' => ['web','role:admin'], 'namespace' => 'Projects'], Route::post('features/{id}/tasks', ['as'=>'tasks.store', 'uses'=>'TasksController@store']); Route::patch('task/{id}', ['as'=>'tasks.update', 'uses'=>'TasksController@update']); Route::delete('task/{id}', ['as'=>'tasks.destroy', 'uses'=>'TasksController@destroy']); + + /** + * Files Routes + */ + Route::get('projects/{project}/files', ['as' => 'projects.files', 'uses' => 'FilesController@index']); + Route::post('files/{fileable}', ['as' => 'files.upload', 'uses' => 'FilesController@create']); }); diff --git a/tests/Feature/Projects/UploadFilesTest.php b/tests/Feature/Projects/UploadFilesTest.php new file mode 100644 index 0000000..652cb8d --- /dev/null +++ b/tests/Feature/Projects/UploadFilesTest.php @@ -0,0 +1,38 @@ +adminUserSigningIn(); + $project = factory(Project::class)->create(['owner_id' => $user->id]); + $this->visit(route('projects.files', $project->id)); + $this->seeElement('form', ['id' => 'upload-files']); + $this->seeElement('input', ['id' => 'files']); + $this->seeElement('input', ['type' => 'submit', 'value' => trans('app.upload_files')]); + + $this->attach(storage_path('app/guitar-640.jpg'), 'files'); + $this->type('Judul file', 'title'); + $this->type('Deskripsi file yang diuplod.', 'description'); + $this->press(trans('app.upload_files')); + + $this->assertCount(1, $project->files); + + $this->seeInDatabase('files', [ + 'fileable_id' => $project->id, + 'fileable_type' => 'App\Entities\Projects\Project', + 'title' => 'Judul file', + 'description' => 'Deskripsi file yang diuplod.', + ]); + + $file = $project->files->first(); + $filePath = storage_path('app/public/files/' . $file->filename); + $this->assertFileExistsThenDelete($filePath, 'File doesn\'t exists.'); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index b7b20ce..4de66f8 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -51,4 +51,12 @@ class TestCase extends \Laravel\BrowserKitTesting\TestCase return $user; } + + protected function assertFileExistsThenDelete($filePath) + { + $this->assertTrue(file_exists($filePath)); + + unlink($filePath); + $this->assertFalse(file_exists($filePath)); + } } diff --git a/tests/Unit/Models/ProjectTest.php b/tests/Unit/Models/ProjectTest.php index 11d47e8..5668d4b 100644 --- a/tests/Unit/Models/ProjectTest.php +++ b/tests/Unit/Models/ProjectTest.php @@ -4,6 +4,7 @@ namespace Tests\Unit\Models; use App\Entities\Payments\Payment; use App\Entities\Projects\Feature; +use App\Entities\Projects\File; use App\Entities\Projects\Project; use App\Entities\Projects\Task; use App\Entities\Subscriptions\Subscription; @@ -124,4 +125,11 @@ class ProjectTest extends TestCase $this->assertEquals(0, $project->getFeatureOveralProgress()); } + + /** @test */ + public function it_has_many_files() + { + $project = factory(Project::class)->create(); + $this->assertTrue($project->files instanceOf Collection); + } }