Nayjest/Grids

View on GitHub
src/Components/ExcelExport.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

namespace Nayjest\Grids\Components;

use Event;
use Illuminate\Pagination\Paginator;
use Illuminate\Foundation\Application;
use Maatwebsite\Excel\Classes\LaravelExcelWorksheet;
use Maatwebsite\Excel\Excel;
use Maatwebsite\Excel\Writers\LaravelExcelWriter;
use Nayjest\Grids\Components\Base\RenderableComponent;
use Nayjest\Grids\Components\Base\RenderableRegistry;
use Nayjest\Grids\DataProvider;
use Nayjest\Grids\DataRow;
use Nayjest\Grids\FieldConfig;
use Nayjest\Grids\Grid;

/**
 * Class ExcelExport
 *
 * The component provides control for exporting data to excel.
 *
 * @author: Alexander Hofmeister
 * @package Nayjest\Grids\Components
 */
class ExcelExport extends RenderableComponent
{
    const NAME = 'excel_export';
    const INPUT_PARAM = 'xls';
    const DEFAULT_ROWS_LIMIT = 5000;

    protected $template = '*.components.excel_export';
    protected $name = ExcelExport::NAME;
    protected $render_section = RenderableRegistry::SECTION_END;
    protected $rows_limit = self::DEFAULT_ROWS_LIMIT;
    protected $extension = 'xls';

    /**
     * @var string
     */
    protected $output;

    /**
     * @var string
     */
    protected $fileName;

    /**
     * @var string
     */
    protected $sheetName;

    protected $ignored_columns = [];

    protected $is_hidden_columns_exported = false;

    protected $on_file_create;

    protected $on_sheet_create;

    /**
     * @param Grid $grid
     * @return null|void
     */
    public function initialize(Grid $grid)
    {
        parent::initialize($grid);
        Event::listen(Grid::EVENT_PREPARE, function (Grid $grid) {
            if ($this->grid !== $grid) {
                return;
            }
            if ($grid->getInputProcessor()->getValue(static::INPUT_PARAM, false)) {
                $this->renderExcel();
            }
        });
    }

    /**
     * Sets name of exported file.
     * 
     * @param string $name
     * @return $this
     */
    public function setFileName($name)
    {
        $this->fileName = $name;
        return $this;
    }

    /**
     * Returns name of exported file.
     * 
     * @return string
     */
    public function getFileName()
    {
        return $this->fileName ?: $this->grid->getConfig()->getName();
    }

    /**
     * @param string $name
     * @return $this
     */
    public function setSheetName($name)
    {
        $this->sheetName = $name;
        return $this;
    }

    /**
     * @return string
     */
    public function getSheetName()
    {
        return $this->sheetName;
    }

    /**
     * @param string $name
     * @return $this
     */
    public function setExtension($name)
    {
        $this->extension = $name;
        return $this;
    }

    /**
     * @return string
     */
    public function getExtension()
    {
        return $this->extension;
    }

    /**
     * @return int
     */
    public function getRowsLimit()
    {
        return $this->rows_limit;
    }

    /**
     * @param int $limit
     *
     * @return $this
     */
    public function setRowsLimit($limit)
    {
        $this->rows_limit = $limit;
        return $this;
    }

    protected function resetPagination(DataProvider $provider)
    {
        if (version_compare(Application::VERSION, '5.0.0', '<')) {
            $provider->getPaginationFactory()->setPageName('page_unused');
        } else {
            Paginator::currentPageResolver(function () {
                return 1;
            });
        }
        $provider->setPageSize($this->getRowsLimit());
        $provider->setCurrentPage(1);
    }

    /**
     * @param FieldConfig $column
     * @return bool
     */
    protected function isColumnExported(FieldConfig $column)
    {
        return !in_array($column->getName(), $this->getIgnoredColumns())
            && ($this->isHiddenColumnsExported() || !$column->isHidden());
    }

    /**
     * @internal
     * @return array
     */
    public function getData()
    {
        // Build array
        $exportData = [];
        /** @var $provider DataProvider */
        $provider = $this->grid->getConfig()->getDataProvider();

        $exportData[] = $this->getHeaderRow();

        $this->resetPagination($provider);
        $provider->reset();

        /** @var DataRow $row */
        while ($row = $provider->getRow()) {
            $output = [];
            foreach ($this->grid->getConfig()->getColumns() as $column) {
                if ($this->isColumnExported($column)) {
                    $output[] = $this->escapeString($column->getValue($row));
                }
            }
            $exportData[] = $output;
        }

        return $exportData;
    }

    protected function renderExcel()
    {
        /** @var Excel $excel */
        $excel = app('excel');

        if (!method_exists($excel, 'create')) {
            throw new \RuntimeException('U are most likely using Maatwebsite/Excel v3 or newer. Use PhpSpreadsheetExport component instead');
        }

        $excel
            ->create($this->getFileName(), $this->getOnFileCreate())
            ->export($this->getExtension());
    }

    protected function escapeString($str)
    {
        return str_replace('"', '\'', strip_tags(html_entity_decode($str)));
    }

    protected function getHeaderRow()
    {
        $output = [];
        foreach ($this->grid->getConfig()->getColumns() as $column) {
            if ($this->isColumnExported($column)) {
                $output[] = $this->escapeString($column->getLabel());
            }
        }
        return $output;
    }

    /**
     * @return string[]
     */
    public function getIgnoredColumns()
    {
        return $this->ignored_columns;
    }

    /**
     * @param string[] $ignoredColumns
     * @return $this
     */
    public function setIgnoredColumns(array $ignoredColumns)
    {
        $this->ignored_columns = $ignoredColumns;
        return $this;
    }

    /**
     * @return boolean
     */
    public function isHiddenColumnsExported()
    {
        return $this->is_hidden_columns_exported;
    }

    /**
     * @param bool $isHiddenColumnsExported
     * @return $this
     */
    public function setHiddenColumnsExported($isHiddenColumnsExported)
    {
        $this->is_hidden_columns_exported = $isHiddenColumnsExported;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getOnFileCreate()
    {
        if ($this->on_file_create === null) {
            $this->on_file_create = function (LaravelExcelWriter $excel) {
                $excel->sheet($this->getSheetName(), $this->getOnSheetCreate());
            };
        }
        return $this->on_file_create;
    }

    /**
     * @param callable $onFileCreate
     *
     * @return $this
     */
    public function setOnFileCreate($onFileCreate)
    {
        $this->on_file_create = $onFileCreate;
        return $this;
    }

    /**
     * @return callable
     */
    public function getOnSheetCreate()
    {
        if ($this->on_sheet_create === null) {
            $this->on_sheet_create = function (LaravelExcelWorksheet $sheet) {
                $sheet->fromArray($this->getData(), null, 'A1', false, false);
            };
        }
        return $this->on_sheet_create;
    }

    /**
     * @param callable $onSheetCreate
     *
     * @return $this
     */
    public function setOnSheetCreate($onSheetCreate)
    {
        $this->on_sheet_create = $onSheetCreate;
        return $this;
    }
}