Skip to content
This repository has been archived by the owner on Jul 8, 2021. It is now read-only.

Commit

Permalink
Merge pull request #14 from viaativaweb/send_pvtl
Browse files Browse the repository at this point in the history
Added File Input in Forms.
  • Loading branch information
mcnamee authored Apr 26, 2019
2 parents 28cd581 + 552020d commit 4866311
Show file tree
Hide file tree
Showing 16 changed files with 205 additions and 31 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
}
],
"require": {
"pvtl/voyager-frontend": "~0.8.0",
"pvtl/voyager-frontend": "^0.9.1",
"tcg/voyager": "^1.1",
"guzzlehttp/guzzle": "~6.0"
},
Expand Down
1 change: 1 addition & 0 deletions config/voyager-forms.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
'checkbox' => 'Checkbox',
'select' => 'Select',
'radio' => 'Radio',
'file' => 'File'
],
];
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function up()
$table->integer('form_id');
$table->string('label')->nullable()->default(null);
$table->string('class')->nullable()->default(null);
$table->enum('type', ['text', 'number', 'email', 'text_area', 'checkbox', 'select', 'radio']);
$table->enum('type', ['text', 'number', 'email', 'text_area', 'checkbox', 'select', 'radio', 'file']);
$table->mediumText('options')->nullable()->default(null);
$table->boolean('required')->nullable()->default(false);
$table->integer('order')->default(10000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function up()
$table->mediumText('data');
$table->mediumText('mailto');
$table->string('ip_address');
$table->mediumText('files_keys')->nullable();
$table->timestamps();
});
}
Expand Down
2 changes: 1 addition & 1 deletion database/seeds/FormsDataRowsTableSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected function generatePermissions($table)
foreach ($columns as $key => $value) {
$dataRow = DataRow::firstOrNew(['data_type_id' => $dataType->id, 'field' => $value]);

if (!$dataRow->exists && $value !== 'id' && $value !== 'data') {
if (!$dataRow->exists && $value !== 'id' && $value !== 'data' && $value !== 'files_keys') {
$dataRow->fill([
'type' => 'text',
'display_name' => $value,
Expand Down
4 changes: 2 additions & 2 deletions resources/views/enquiries/email.blade.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box;">
<tbody>
@foreach ($enquiry as $key => $value)
@foreach ($enquiries as $key => $enquiry)
<tr>
<th align="left" width="25%" style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px; font-weight: bold;">
{{ str_replace('_', ' ', $key) }}
</th>

<td align="left" style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;">
{!! nl2br($value) !!}
{!! nl2br($enquiry) !!}
</td>
</tr>
@endforeach
Expand Down
15 changes: 15 additions & 0 deletions resources/views/enquiries/view.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@
@endforeach
</table>
</div> <!-- /.panel -->
<div class="panel panel-bordered">
<div class="panel-heading">
<h3 class="panel-title">Files Attached</h3>
</div> <!-- /.panel-heading -->

<table class="table">
@foreach($files as $file)
<tr>
<td>
<a href="{{$file['url']}}" target="_blank">{{$file['filename']}}</a>
</td>
</tr>
@endforeach
</table>
</div> <!-- /.panel -->
</div> <!-- /.col -->
</div> <!-- /.row -->
</div> <!-- /.page-content -->
Expand Down
1 change: 0 additions & 1 deletion resources/views/forms/edit-add.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ class="form-control"
<label for="type">Field Type</label>
<select class="form-control" name="type" id="type">
<option value="">-- Select --</option>

@foreach (config('voyager-forms.available_inputs') as $key => $value)
<option value="{{ $key }}">{{ $value }}</option>
@endforeach
Expand Down
10 changes: 9 additions & 1 deletion resources/views/forms/render.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<form id="{{ $form->title }}" action="{{ route('voyager.enquiries.submit', ['id' => $form->id]) }}" method="POST">
<form id="{{ $form->title }}" action="{{ route('voyager.enquiries.submit', ['id' => $form->id]) }}" method="POST" enctype="multipart/form-data">
{{ csrf_field() }}

@if (session('success'))
Expand Down Expand Up @@ -52,6 +52,14 @@
@endforeach
</fieldset>
@endif

@if ($input->type === 'file')
<label for="{{ $input->label }}">
{{ $input->label }}
<input type="file" name="{{ $input->label }}" accept="{{ $input->options }}" @if ($input->required) required @endif>
</label>
@endif

</div>
@endforeach

Expand Down
8 changes: 6 additions & 2 deletions resources/views/inputs/edit-add.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@
</div>
</div>

@if (in_array($input->type, ['checkbox', 'select', 'radio']))
@if (in_array($input->type, ['checkbox', 'select', 'radio', 'file']))
<div class="col-md-4 no-bottom-margin">
<div class="form-group">
<label for="options">Options <small>(Separated with ',')</small></label>
@if($input->type !== 'file')
<label for="options">Options <small>(Separated with ", ")</small></label>
@else
<label for="options">MIME types <small>(Eg. ".pdf,.zip")</small></label>
@endif
<input name="options" class="form-control" id="options" value="{{ $input->options }}"
required>
</div>
Expand Down
10 changes: 10 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
Route::post('sort', ['uses' => "InputController@sort", 'as' => 'sort']);
});

Route::group([
'as' => 'voyager.enquiries.',
'prefix' => 'admin/enquiries/',
'middleware' => ['web', 'admin.user'],
'namespace' => '\Pvtl\VoyagerForms\Http\Controllers'
], function () {
Route::get('{id}/file/{fileKey}', ['uses' => "EnquiryController@getFile", 'as' => 'file']);
});


/**
* Front-end Route/s
*/
Expand Down
11 changes: 11 additions & 0 deletions src/Enquiry.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Enquiry extends Model
'data',
'mailto',
'ip_address',
'files_keys'
];

public function form()
Expand All @@ -37,4 +38,14 @@ public function getDataAttribute($value)
{
return unserialize($value);
}

public function setFilesKeysAttribute($value)
{
$this->attributes['files_keys'] = serialize($value);
}

public function getFilesKeysAttribute($value)
{
return unserialize($value);
}
}
122 changes: 114 additions & 8 deletions src/Http/Controllers/EnquiryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

namespace Pvtl\VoyagerForms\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redirect;
use Pvtl\VoyagerForms\{
Form,
Enquiry,
Traits\DataType,
Mail\Enquiry as EnquiryMailable
};
use Pvtl\VoyagerFrontend\Helpers\ClassEvents;
use TCG\Voyager\Facades\Voyager;
use TCG\Voyager\Http\Controllers\VoyagerBaseController;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;

class EnquiryController extends VoyagerBaseController
{
Expand All @@ -21,10 +26,11 @@ class EnquiryController extends VoyagerBaseController
/**
* @param Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|void
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create(Request $request)
{
Voyager::canOrFail('add_enquiries');
$this->authorize('add', app(Enquiry::class));

return view('voyager-forms::enquiries.edit-add', [
'dataType' => $this->getDataType($request),
Expand All @@ -44,7 +50,13 @@ public function create(Request $request)
public function submit(Request $request)
{
$form = Form::findOrFail($request->id);
$formData = $request->except(['_token', 'id', 'g-recaptcha-response']);

// Get $formData and $filesKeys verifying the MIME of files.
$formDataAndFilesKeys = $this->getFormDataAndFilesKeys($form, $request);
if($formDataAndFilesKeys instanceof RedirectResponse){
return $formDataAndFilesKeys;
}
list($formData, $filesKeys) = $formDataAndFilesKeys;

// Check if reCAPTCHA is on & verify
if (setting('admin.google_recaptcha_site_key')) {
Expand Down Expand Up @@ -73,20 +85,23 @@ public function submit(Request $request)
? setting('site.title')
: 'Website';

// Upload the images files, update $formData to save the image directory and return all the file keys.

// Save the enquiry to the DB
$enquiry = Enquiry::create([
'form_id' => $form->id,
'data' => $formData,
'mailto' => $form->mailto,
'ip_address' => $_SERVER['REMOTE_ADDR'],
'files_keys' => $filesKeys
])->save();

// Debug/Preview the email
// return (new EnquiryMailable($form, $formData))->render();
// return (new EnquiryMailable($form, $formData, $filesKeys))->render();

// Send the email
Mail::to(array_map('trim', explode(',', $form->mailto)))
->send(new EnquiryMailable($form, $formData));
->send(new EnquiryMailable($form, $formData, $filesKeys));

return redirect()
->back()
Expand All @@ -97,27 +112,47 @@ public function submit(Request $request)
* @param Request $request
* @param $id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show(Request $request, $id)
{
Voyager::canOrFail('read_enquiries');
$this->authorize('read', app(Enquiry::class));

$enquiry = Enquiry::findOrFail($id);

//verify files and push in array your infos, unset the file path in data and update the data of $enquiry
$files = [];
$formData = $enquiry->data;
foreach ($enquiry->files_keys as $fileKey) {
if (isset($formData[$fileKey])) {
$files[] = [
'url' => route('voyager.enquiries.file', [
'id' => $enquiry->id,
'fileKey' => $fileKey
]),
'filename' => pathinfo($formData[$fileKey])['filename']
];
unset($formData[$fileKey]);
}
}
$enquiry->data = $formData;

return view('voyager-forms::enquiries.view', [
'dataType' => $this->getDataType($request),
'enquiry' => $enquiry,
'files' => $files
]);
}

/**
* @param Request $request
* @param $id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function edit(Request $request, $id)
{
Voyager::canOrFail('edit_enquiries');
$this->authorize('edit', app(Enquiry::class));

$enquiry = Enquiry::findOrFail($id);

Expand All @@ -130,10 +165,11 @@ public function edit(Request $request, $id)
* @param Request $request
* @param $id
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, $id)
{
Voyager::canOrFail('edit_enquiries');
$this->authorize('edit', app(Enquiry::class));

$dataType = $this->getDataType($request);

Expand All @@ -144,6 +180,29 @@ public function update(Request $request, $id)
]);
}

/**
* Download the file from enquiry
* @param $id
* @param $fileKey
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
public function getFile($id, $fileKey)
{

$this->authorize('browse', app(Enquiry::class));

$enquiry = Enquiry::findOrFail($id);
$formData = $enquiry->data;

//return download if file exists
if (isset($formData[$fileKey])) {
return Storage::download($formData[$fileKey]);
}
abort(404);

}


/**
* Verify the reCAPTCHA response with Google
* @param Request $request
Expand All @@ -165,4 +224,51 @@ protected function verifyCaptcha(Request $request)
->with('error', 'Unable to validate Google reCAPTCHA');
}
}

/**
* Get the Form Data and the Files Keys
* @param $form
* @param $request
* @return array With form data updated and files keys|\Illuminate\Http\RedirectResponse
*/
protected function getFormDataAndFilesKeys($form, $request)
{
$formData = $request->except(['_token', 'id', 'g-recaptcha-response']);
$filesKeys = [];

$mimes = $this->getMimesFromForm($form);

foreach ($request->files as $key => $data) {

//IDK WHY!!!, but the $data->storeAs(...) won't work...
//Hack to avoid error up
$data = $formData[$key];
if ($data->isValid()) {
$key_slug = Str::slug($key, '_');
$extension = $data->getClientOriginalExtension();

if(!in_array(".{$extension}", $mimes[$key_slug])){
return redirect()
->back()
->with('error', 'File(s) not Allowed');
}

$file_name = strtoupper(pathinfo($data->getClientOriginalName(), PATHINFO_FILENAME));
$timestamp = Carbon::now()->timestamp;
$filepath = $data->storeAs("forms/{$key_slug}", "{$file_name}_{$timestamp}.{$extension}");
$filesKeys[] = $key;
$formData[$key] = "{$filepath}";
}
}
return [$formData, $filesKeys];
}

protected function getMimesFromForm($form){
$mimes = [];
$inputs = $form->inputs()->where('type', 'file')->get();
foreach($inputs as $key => $input){
$mimes[Str::slug($input->label, '_')] = explode(',', $input->options);
}
return $mimes;
}
}
Loading

0 comments on commit 4866311

Please sign in to comment.