Skip to content

Commit

Permalink
Added CSV Exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
eusonlito committed Sep 28, 2017
1 parent 8d04f1f commit eec5e01
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 29 deletions.
82 changes: 69 additions & 13 deletions src/Http/Controllers/ModelController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
namespace Anavel\Crud\Http\Controllers;

use ANavallaSuiza\Laravel\Database\Contracts\Manager\ModelManager;
use ANavallaSuiza\Laravel\Database\Repository\Eloquent\Repository;
use Anavel\Crud\Contracts\Abstractor\Model;
use Anavel\Crud\Contracts\Abstractor\ModelFactory as ModelAbstractorFactory;
use Anavel\Crud\Contracts\Controllers\CustomController;
use Anavel\Crud\Contracts\Form\Generator as FormGenerator;
use Anavel\Crud\Repository\Criteria\OrderByCriteria;
use Anavel\Crud\Repository\Criteria\SearchCriteria;
use Anavel\Crud\Repository\Criteria\WithCriteria;
use Anavel\Foundation\Http\Controllers\Controller;
use Anavel\Crud\Services\Export\Csv;
use App;
use Illuminate\Http\Request;

Expand All @@ -28,7 +31,9 @@ public function __construct(ModelAbstractorFactory $modelFactory, ModelManager $

private function authorizeMethod(Model $modelAbstractor, $methodName)
{
if (array_key_exists('authorize', $config = $modelAbstractor->getConfig()) && $config['authorize'] === true) {
$config = $modelAbstractor->getConfig();

if (array_key_exists('authorize', $config) && $config['authorize'] === true) {
$this->authorize($methodName, $modelAbstractor->getInstance());
}
}
Expand Down Expand Up @@ -58,25 +63,22 @@ private function customController(Model $modelAbstractor)
}

/**
* Display a listing of the resource.
* Prepare contents to be used
*
* @param Request $request
* @param string $model
* @param Model $modelAbstractor
* @param Repository $repository
*
* @return Response
* @return void
*/
public function index(Request $request, $model)
public function getIndexRequirements(Request $request, Model $modelAbstractor, Repository $repository)
{
$modelAbstractor = $this->modelFactory->getBySlug($model);

$this->authorizeMethod($modelAbstractor, 'adminIndex');

if ($customController = $this->customController($modelAbstractor)) {
return $customController->index($request, $model);
foreach ($modelAbstractor->getListFields()['main'] as $field) {
if (strpos($field->getName(), '.')) {
$repository->pushCriteria(new WithCriteria(preg_replace('/\.[^\.]+$/', '', $field->getName())));
}
}

$repository = $this->modelManager->getRepository($modelAbstractor->getModel());

if ($search = $request->input('search')) {
$searchByColumns = [];

Expand All @@ -91,13 +93,67 @@ public function index(Request $request, $model)
$direction = $request->input('direction') ?: 'desc';

$repository->pushCriteria(new OrderByCriteria($sort, ($direction === 'desc') ? true : false));
}

/**
* Display a listing of the resource.
*
* @param Request $request
* @param string $model
*
* @return Response
*/
public function index(Request $request, $model)
{
$modelAbstractor = $this->modelFactory->getBySlug($model);

$this->authorizeMethod($modelAbstractor, 'adminIndex');

if ($customController = $this->customController($modelAbstractor)) {
return $customController->index($request, $model);
}

$repository = $this->modelManager->getRepository($modelAbstractor->getModel());

$this->getIndexRequirements($request, $modelAbstractor, $repository);

return view('anavel-crud::pages.index', [
'abstractor' => $modelAbstractor,
'items' => $repository->paginate(config('anavel-crud.list_max_results')),
]);
}

/**
* Display a listing of the resource.
*
* @param Request $request
* @param string $model
*
* @return Response
*/
public function exportCsv(Request $request, $model)
{
$modelAbstractor = $this->modelFactory->getBySlug($model);

$this->authorizeMethod($modelAbstractor, 'exportCsv');

if ($customController = $this->customController($modelAbstractor)) {
return $customController->exportCsv($request, $model);
}

$repository = $this->modelManager->getRepository($modelAbstractor->getModel());

$this->getIndexRequirements($request, $modelAbstractor, $repository);

$csv = (string)(new Csv)->fromArray($repository->all()->toArray());

return response()->make($csv, 200, [
'Content-Encoding' => 'UTF-8',
'Content-Type' => 'application/octet-stream',
'Content-disposition' => 'attachment; filename='.$model.'.csv',
]);
}

/**
* Show the form for creating a new resource.
*
Expand Down
16 changes: 5 additions & 11 deletions src/Http/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ function () {
'uses' => 'ModelController@index',
]);

Route::get('{model}/export/csv', [
'as' => 'anavel-crud.model.export.csv',
'uses' => 'ModelController@exportCsv',
]);

Route::get('{model}/create', [
'as' => 'anavel-crud.model.create',
'uses' => 'ModelController@create',
Expand Down Expand Up @@ -46,16 +51,5 @@ function () {
'as' => 'anavel-crud.model.destroy',
'uses' => 'ModelController@destroy',
]);

// Batch actions
/*Route::put('{model}/batch', [
'as' => 'anavel-crud.model.batch-update',
'uses' => 'ModelController@batchUpdate'
]);
Route::delete('{model}/batch', [
'as' => 'anavel-crud.model.batch-delete',
'uses' => 'ModelController@batchDestroy'
]);*/
}
);
121 changes: 121 additions & 0 deletions src/Services/Export/Csv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

namespace Anavel\Crud\Services\Export;

class Csv
{
private $fp;
private $headers = [];
private $csv = '';

public function fromArray(array $data)
{
if (empty($data)) {
return '';
}

$this->open();

foreach ($data as $line) {
$this->headers($line);
}

$this->write($this->headers);

$fill = array_fill_keys($this->headers, '');

foreach ($data as $line) {
$this->write(array_merge($fill, $this->line($line)));
}

$this->close();

return $this;
}

public function __toString()
{
return $this->csv;
}

private function open()
{
// Use memory as file
$this->fp = fopen('php://memory', 'w');

// Add BOM to fix UTF-8 in Excel
fwrite($this->fp, chr(0xEF).chr(0xBB).chr(0xBF));
}

private function write(array $data)
{
fputcsv($this->fp, $data);
}

private function close()
{
rewind($this->fp);

$this->csv = stream_get_contents($this->fp);

fclose($this->fp);
}

private function headers(array $data, $prefix = null)
{
$prefix = $prefix ? ($prefix.'.') : '';

foreach ($data as $key => $value) {
$key = $prefix.$key;

if ($this->existsHeader($key)) {
continue;
}

$isArray = is_array($value);

if ($isArray && array_key_exists(0, $value)) {
continue;
}

if ($isArray) {
$this->headers($value, $key);
} elseif ($this->isValidHeader($key)) {
$this->headers[] = $key;
}
}
}

private function line(array $line, $prefix = null)
{
$data = [];
$prefix = $prefix ? ($prefix.'.') : '';

foreach ($line as $key => $value) {
$key = $prefix.$key;
$isArray = is_array($value);

if ($isArray && array_key_exists(0, $value)) {
continue;
}

if ($isArray) {
$data = array_merge($data, $this->line($value, $key));
} elseif ($this->existsHeader($key)) {
$data[$key] = trim(str_replace(["\n", "\r"], '', $value));
}
}

return $data;
}

private function isValidHeader($key)
{
return preg_match('/_id$/', $key) === 0;
}

private function existsHeader($key)
{
return in_array($key, $this->headers, true);
}
}
19 changes: 14 additions & 5 deletions views/pages/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,24 @@
</table>
</div>

@if ($items->total() > $items->perPage())
<div class="box-footer clearfix">
@if ($items->total())
<span class="label label-default">{{ $items->total() }} registros</span>

<div class="pull-right">
<a href="{{ route('anavel-crud.model.export.csv', $slug) }}" class="btn btn-default" style="margin-left: 20px">
Exportar a CSV
</a>
</div>
@endif

@if ($items->total() > $items->perPage())
{!! with(new Anavel\Crud\View\Presenters\Paginator($items))->render() !!}
@endif
</div>
@endif
</div>
@stop

@section('footer-scripts')
@parent
<script src="{{ asset('vendor/anavel-crud/js/modals.js') }}" type="text/javascript"></script>
@section('footer-scripts') @parent
<script src="{{ asset('vendor/anavel-crud/js/modals.js') }}" type="text/javascript"></script>
@stop

0 comments on commit eec5e01

Please sign in to comment.