Files
xstore/inc/Hura8/System/Controller/aExcelDownloadController.php
2025-10-04 11:46:59 +07:00

345 lines
11 KiB
PHP

<?php
/**
* Created by Glee Ltd.
* User: Hieu
* Date: 20-Aug-19
* Time: 11:16 AM
* Description:
*/
namespace Hura8\System\Controller;
use Hura8\Interfaces\iExcelDownload;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
abstract class aExcelDownloadController implements iExcelDownload
{
protected static $column_names = [
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM',
'AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ',
//...
];
protected $work_sheet_title = "Danh sách"; //
protected $export_file_name = '';
/* @var $objExcel Spreadsheet */
protected $objExcel;
/* @var $currentActiveSheet Worksheet */
protected $currentActiveSheet;
protected $client_excel_col_config = [
/*"A" => array(
'name' => 'ID Sản phẩm Web',
'width' => '10',
'data_field_name' => 'id',
),
"B" => array(
'name' => 'Mã kho (SKU)',
'width' => '10',
'data_field_name' => 'storeSKU',
),*/
//...
];
protected $field_column_mappings = [
//'name' => "A",
//'price' => "B",
];
private $header_row_index = 2;
// hold cach for some operations
protected $cache = [];
protected $format_item_middlewares = []; // list of middleware object to format item
public function __construct($client_config_file_name='', $export_file_name='', $work_sheet_title = '')
{
if($client_config_file_name) {
$this->setColumnConfigUseConfigFile($client_config_file_name);
}
$this->export_file_name = ($export_file_name) ?: "file_".CURRENT_TIME;
$this->work_sheet_title = ($work_sheet_title) ?: "Danh sách";
}
protected function setColumnConfigUseConfigFile($client_config_file_name) {
//this from a config file for each client
$client_config_file = "config/client/excel/".$client_config_file_name;
if( ! file_exists(ROOT_DIR .'/'. $client_config_file)) {
die("Please create config file: ".$client_config_file);
}
$client_fields_config = include ROOT_DIR .'/'. $client_config_file;
// auto add excel column names based on fields' index
$this->client_excel_col_config = $this->_make_columns(array_values($client_fields_config));
// create field-col map
$this->createFieldColumnMappings();
}
private function createFieldColumnMappings() {
$field_column_mappings = [];
foreach ($this->client_excel_col_config as $column_name => $_prop) {
$field_column_mappings[$_prop['data_field_name']] = $column_name;
}
$this->field_column_mappings = $field_column_mappings;
}
public function setColumnConfigManually(array $col_config) {
$this->client_excel_col_config = $this->_make_columns($col_config);
// create field-col map
$this->createFieldColumnMappings();
}
protected function _make_columns($fields_config) {
$new_array = [];
$total_names = sizeof(static::$column_names);
foreach ($fields_config as $index => $config) {
if($index >= $total_names) break;
$new_array[static::$column_names[$index]] = $config;
}
return $new_array;
}
public function start(array $options = [
"debug_mode" => '', // show-item-list
"excelOption" => [],
"sheetOption" => [],
"sheetStartRowNumber" => 3,
"sheetHeaderRowNumber" => 2,
"getItemListOption" => [
"brand" => [],
"category" => [],
"page" => 1,
"limit" => 100,
],
"exportFileOption" => [],
]) {
$debug_mode = $options['debug_mode'] ?? false;
// debug mode
if($debug_mode) {
// show item list
if($debug_mode == 'show-item-list') {
$item_list = $this->getItemList($options['getItemListOption']);
print_r($item_list);
}
// show formatted list
if($debug_mode == 'show-formatted-list') {
$item_list = $this->formatItemList( $this->getItemList($options['getItemListOption']) );
print_r($item_list);
}
return true;
}
// setup
if(isset($options['sheetHeaderRowNumber']) && $options['sheetHeaderRowNumber']) {
$this->header_row_index = $options['sheetHeaderRowNumber'];
}
$this->createExcelObject($options['excelOption'] ?? []);
$this->createActiveSheet(0, $options['sheetOption'] ?? []);
// num beforeWriteList
$this->beforeWriteList();
// fetch all items and write till the end
$has_fetch_all_items = false;
$start_row = (isset($options["sheetStartRowNumber"])) ? $options["sheetStartRowNumber"] : 3;
$item_list = $this->formatItemList( $this->getItemList($options['getItemListOption']) );
//debug_var($item_list);
//exit;
$has_fetch_all_items = true;
$this->writeItemsToExcel($start_row, $item_list);
/*$getItemListOption = $options['getItemListOption'];
$pageIndex = 0;
while (!$has_fetch_all_items) {
// run from page 1->end
$pageIndex += 1;
$getItemListOption["page"] = $pageIndex;
$item_list = $this->getItemList($getItemListOption);
// flag
if(!sizeof($item_list)) {
$has_fetch_all_items = true;
}
// else, start write
$last_row = $this->writeItemsToExcel($start_row, $item_list);
// update $start_row
$start_row = $last_row;// + 1
}*/
// export
if($has_fetch_all_items) {
$this->getExcelFile($options['exportFileOption']);
}
return true;
}
// abstract methods
protected function beforeWriteList() { }
abstract protected function getItemList(array $options);
abstract protected function defaultFormatItemInfo(array $item_info, $index =0);
protected function registerFormatItemInfoMiddleware($middleware_ojb) {
$this->format_item_middlewares[] = $middleware_ojb;
}
protected function formatItemInfo(array $item_info, $index = 0) {
// apply middleware
if(sizeof($this->format_item_middlewares)) {
foreach ($this->format_item_middlewares as $_middleware) {
$item_info = call_user_func($_middleware, $item_info);
}
} else {
$item_info = $this->defaultFormatItemInfo($item_info, $index);
}
return $item_info;
}
protected function createExcelObject(array $options)
{
// Create new Spreadsheet object
$this->objExcel = new Spreadsheet();
// Set properties
$this->objExcel->getProperties()->setCreator("Hurasoft");
$this->objExcel->getProperties()->setLastModifiedBy("Hurasoft");
$this->objExcel->getProperties()->setTitle("Excel Document");
$this->objExcel->getProperties()->setSubject("Excel Document");
$this->objExcel->getProperties()->setDescription("Tao file excel");
}
protected function createActiveSheet($sheet_index = 0, array $options=[]) {
// Create a first sheet, representing sales data
$this->objExcel->setActiveSheetIndex($sheet_index);
$this->currentActiveSheet = $this->objExcel->getActiveSheet();
$this->currentActiveSheet->setCellValueExplicit('A1', $this->work_sheet_title, DataType::TYPE_STRING);
$this->currentActiveSheet->getStyle('A1')->getFont()->setSize(16);
$this->currentActiveSheet->getStyle('A1')->getFont()->setBold(true);
// Set header row
$row_index = $this->header_row_index;
foreach ($this->client_excel_col_config as $col_name => $_prop) {
$col_width = (isset($_prop['width']) && intval($_prop['width']) > 0) ? intval($_prop['width']) : 15;
$this->currentActiveSheet->getColumnDimension($col_name)->setWidth($col_width);
$this->currentActiveSheet->setCellValueExplicit($col_name. $row_index, $_prop["name"], DataType::TYPE_STRING);
$this->currentActiveSheet->getStyle($col_name . $row_index)->getFont()->setBold(true);
}
}
protected function formatItemList(array $item_list)
{
$new_list = [];
foreach ( $item_list as $index => $item_info ) {
$new_list[$index] = $this->formatItemInfo($item_info, $index);
}
return $new_list;
}
protected function writeItemsToExcel($start_row = 1, array $item_list=[])
{
$write_row = $start_row;
foreach ( $item_list as $index => $item_info ) {
// write each field to its corresponding columns
foreach ($item_info as $_field => $_value) {
if( !isset($this->field_column_mappings[$_field])) continue;
if(is_array($_value)) $_value = serialize($_value);
$write_column = $this->field_column_mappings[$_field];
$this->currentActiveSheet->setCellValueExplicit($write_column . $write_row, $_value, DataType::TYPE_STRING);
$this->currentActiveSheet->getStyle($write_column . $write_row)->getAlignment()->setWrapText(true);
}
// next rows
$write_row += 1;
}
// get the last row
return $write_row;
}
protected function getExcelFile(array $options)
{
// write to a local file
$local_file = $options['local_file'] ?? '';
if($local_file) {
$this->_save_to_file($local_file);
return true;
}
// default: export to browser to download
$this->_export_to_browser();
return true;
}
protected function cleanUp(){
// clean up
$this->objExcel->disconnectWorksheets();
unset($this->objExcel);
}
protected function _save_to_file($file_path){
// delete old file if exist
if(file_exists($file_path)) {
@unlink($file_path);
}
$writer = new Xlsx($this->objExcel);
$writer->save($file_path);
$this->cleanUp();
}
protected function _export_to_browser(){
// Rename sheet
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="'.$this->export_file_name.'.xlsx"');
header('Cache-Control: max-age=0');
$writer = new Xlsx($this->objExcel);
ob_end_clean();
$writer->save('php://output');
$this->cleanUp();
exit();
}
}