first commit
This commit is contained in:
135
admin/class/Export/ExportData.php
Normal file
135
admin/class/Export/ExportData.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace Export;
|
||||
|
||||
/**
|
||||
* ExportData is the base class for exporters to specific file formats. See other
|
||||
* classes below.
|
||||
*
|
||||
* php-export-data by Eli Dickinson, http://github.com/elidickinson/php-export-data
|
||||
*/
|
||||
abstract class ExportData
|
||||
{
|
||||
protected $exportTo; // Set in constructor to one of 'browser', 'file', 'string'
|
||||
protected $stringData; // stringData so far, used if export string mode
|
||||
protected $tempFile; // handle to temp file (for export file mode)
|
||||
protected $tempFilename; // temp file name and path (for export file mode)
|
||||
public $filename; // file mode: the output file name; browser mode: file name for download; string mode: not used
|
||||
protected $encoding;
|
||||
|
||||
public function __construct($exportTo = 'browser', $filename = 'exportdata')
|
||||
{
|
||||
if (!in_array($exportTo, ['browser', 'file', 'string'])) {
|
||||
throw new Exception("{$exportTo} is not a valid ExportData export type");
|
||||
}
|
||||
$this->exportTo = $exportTo;
|
||||
$this->filename = $filename;
|
||||
}
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
global $cfg;
|
||||
switch ($this->exportTo) {
|
||||
case 'browser':
|
||||
$this->sendHttpHeaders();
|
||||
break;
|
||||
case 'string':
|
||||
$this->stringData = '';
|
||||
break;
|
||||
case 'file':
|
||||
$this->tempFilename = tempnam($cfg['Path']['data'], 'exportdata');
|
||||
$this->tempFile = fopen($this->tempFilename, 'w');
|
||||
break;
|
||||
}
|
||||
|
||||
$this->write($this->generateHeader());
|
||||
}
|
||||
|
||||
public function addRow($row)
|
||||
{
|
||||
$this->write($this->generateRow($row));
|
||||
}
|
||||
|
||||
public function loadOrdersData($order_ids)
|
||||
{
|
||||
foreach ($order_ids as $id) {
|
||||
$this->addRow($this->getOrder($id));
|
||||
}
|
||||
}
|
||||
|
||||
public function finalize()
|
||||
{
|
||||
$this->write($this->generateFooter());
|
||||
|
||||
switch ($this->exportTo) {
|
||||
case 'browser':
|
||||
flush();
|
||||
break;
|
||||
case 'string':
|
||||
// do nothing
|
||||
break;
|
||||
case 'file':
|
||||
// close temp file and move it to correct location
|
||||
fclose($this->tempFile);
|
||||
rename($this->tempFilename, $this->filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function getString()
|
||||
{
|
||||
return $this->stringData;
|
||||
}
|
||||
|
||||
abstract public function sendHttpHeaders();
|
||||
|
||||
protected function write($data)
|
||||
{
|
||||
if (!empty($data)) {
|
||||
switch ($this->exportTo) {
|
||||
case 'browser':
|
||||
echo $data;
|
||||
break;
|
||||
case 'string':
|
||||
$this->stringData .= $data;
|
||||
break;
|
||||
case 'file':
|
||||
fwrite($this->tempFile, $data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateHeader()
|
||||
{
|
||||
// can be overridden by subclass to return any data that goes at the top of the exported file
|
||||
}
|
||||
|
||||
protected function generateFooter()
|
||||
{
|
||||
// can be overridden by subclass to return any data that goes at the bottom of the exported file
|
||||
}
|
||||
|
||||
// In subclasses generateRow will take $row array and return string of it formatted for export type
|
||||
abstract protected function generateRow($row);
|
||||
|
||||
protected function getOrder($id)
|
||||
{
|
||||
$order = new \Order();
|
||||
|
||||
$order->createFromDB($id);
|
||||
$order->fetchItems();
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
public function setCoding($encoding)
|
||||
{
|
||||
$this->encoding = $encoding;
|
||||
}
|
||||
|
||||
public function encodeData($string)
|
||||
{
|
||||
return iconv('utf-8', $this->encoding.'//TRANSLIT', $string);
|
||||
}
|
||||
}
|
||||
26
admin/class/Export/ExportDataCSV.php
Normal file
26
admin/class/Export/ExportDataCSV.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Export;
|
||||
|
||||
/**
|
||||
* ExportDataCSV - Exports to CSV (comma separated value) format.
|
||||
*/
|
||||
class ExportDataCSV extends ExportData
|
||||
{
|
||||
public function generateRow($row)
|
||||
{
|
||||
foreach ($row as $key => $value) {
|
||||
// Escape inner quotes and wrap all contents in new quotes.
|
||||
// Note that we are using \" to escape double quote not ""
|
||||
$row[$key] = '"'.str_replace('"', '\"', $value).'"';
|
||||
}
|
||||
|
||||
return implode(',', $row)."\n";
|
||||
}
|
||||
|
||||
public function sendHttpHeaders()
|
||||
{
|
||||
header('Content-type: text/csv');
|
||||
header('Content-Disposition: attachment; filename='.basename($this->filename));
|
||||
}
|
||||
}
|
||||
156
admin/class/Export/ExportDataDBF.php
Normal file
156
admin/class/Export/ExportDataDBF.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace Export;
|
||||
|
||||
use XBase\Record;
|
||||
use XBase\WritableTable;
|
||||
|
||||
/**
|
||||
* Own class for DBF export.
|
||||
*/
|
||||
class ExportDataDBF extends ExportData
|
||||
{
|
||||
/**
|
||||
* @var WritableTable
|
||||
*/
|
||||
private $table;
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
global $cfg;
|
||||
|
||||
$this->tempFilename = $cfg['Path']['data'].'export_data.dbf';
|
||||
|
||||
$this->table = WritableTable::create($this->tempFilename, $this->columnDefs(), $this->tempFilename);
|
||||
}
|
||||
|
||||
public function finalize()
|
||||
{
|
||||
$this->sendHttpHeaders();
|
||||
$this->table->close();
|
||||
|
||||
readfile($this->tempFilename);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $order \Order
|
||||
*/
|
||||
public function generateRow($order)
|
||||
{
|
||||
$row_pointer = $this->table->appendRecord();
|
||||
|
||||
$this->appendToRow($row_pointer, $order);
|
||||
|
||||
$this->table->writeRecord();
|
||||
}
|
||||
|
||||
public function sendHttpHeaders()
|
||||
{
|
||||
header('Content-Type: application/x-dbase; charset='.$this->encoding);
|
||||
header('Content-Disposition: attachment; filename="'.$this->filename.'"');
|
||||
header('Expires: 0');
|
||||
header('Pragma: no-cache');
|
||||
}
|
||||
|
||||
protected function columnDefs()
|
||||
{
|
||||
/* FIXME: dodělat zbytek a přesměrovat DBF z export_sracka sem */
|
||||
return [
|
||||
['DATUM_VYST', Record::DBFFIELD_TYPE_DATE], // datum vystavení
|
||||
// ['DATUM_SPL', DBFFIELD_TYPE_DATE], //prázdné
|
||||
// ['DOKLAD_1', DBFFIELD_TYPE_CHAR, 12], //aby tam bylo fčíslo objednávky např. f11521
|
||||
// ['TYP_ZAP', DBFFIELD_TYPE_CHAR, 1], //hodnota P
|
||||
// ['ZNAK_UCT', DBFFIELD_TYPE_CHAR, 5], //prázdné
|
||||
// ['SYMBOLY', DBFFIELD_TYPE_CHAR, 20], //včísloobjednávky např. v11521
|
||||
// ['PAR_ZNAK', DBFFIELD_TYPE_CHAR, 12], //to samé jako DOKLAD_1 např. f11521
|
||||
// ['BANK_UCET', DBFFIELD_TYPE_CHAR, 44], //prázdné
|
||||
// ['SPEC_SYMB', DBFFIELD_TYPE_CHAR, 10], //prázdné
|
||||
// ['POPIS_TEXT', DBFFIELD_TYPE_CHAR, 30], //libovolný text - např. prodej eshop-objednávka 11521
|
||||
// ['DRUH_UCT', DBFFIELD_TYPE_CHAR, 5], //hodnota PZ
|
||||
// ['MENA', DBFFIELD_TYPE_CHAR, 3], //buď Kč nebo EUR
|
||||
// ['CELKEM_KC', DBFFIELD_TYPE_NUMERIC, 8, 2], //celková částka dokladu včetně DPH v Kč
|
||||
// ['CELKEMCIZI', DBFFIELD_TYPE_NUMERIC, 8, 2], //celková částka dokladu v EUR - prodej na Slovensko?
|
||||
// ['KURZ', DBFFIELD_TYPE_NUMERIC, 5, 3], //kurz pro přepočet
|
||||
// ['DATUM_DPH', DBFFIELD_TYPE_DATE], //datum DPH = datum vystavení
|
||||
// ['TYP_DPH', DBFFIELD_TYPE_CHAR, 5], //hodnota U
|
||||
// ['ZAKL_DPH_Z', DBFFIELD_TYPE_NUMERIC, 8, 2], //Částka bez daně v základní sazbě
|
||||
// ['DPH_Z', DBFFIELD_TYPE_NUMERIC, 8, 2], //Daň s azba 21 %
|
||||
// ['ZAKL_DPH_S', DBFFIELD_TYPE_NUMERIC, 8, 2], //Částka bez daně ve snížené sazbě
|
||||
// ['DPH_S', DBFFIELD_TYPE_NUMERIC, 8, 2], //Daň s azba 15 %
|
||||
// ['TYPMIMODPH', DBFFIELD_TYPE_CHAR, 1], //prázdné
|
||||
// ['CASTKAMIMO', DBFFIELD_TYPE_NUMERIC, 8, 2], //prázdné
|
||||
// ['STREDISKO', DBFFIELD_TYPE_CHAR, 5], //PRÁZDNÉ
|
||||
// ['vykon', DBFFIELD_TYPE_CHAR, 5], //prázdné
|
||||
// ['zakazka', DBFFIELD_TYPE_CHAR, 5], //prázdné
|
||||
// ['POZNAMKA', DBFFIELD_TYPE_CHAR, 150], //sem naimportovat jméno a příjmění a město kupujícího JAN NOVAK TURNOV
|
||||
// ['FIRMA', DBFFIELD_TYPE_CHAR, 30], // Firma
|
||||
// ['JMENO', DBFFIELD_TYPE_CHAR, 30], //Jmeno
|
||||
// ['PRIJMENI', DBFFIELD_TYPE_CHAR, 30], //Prijmeni
|
||||
// ['ICO', DBFFIELD_TYPE_CHAR, 15], //ICO
|
||||
// ['DIC', DBFFIELD_TYPE_CHAR, 20], //DIC
|
||||
//
|
||||
// ['ZAKAZNIK', DBFFIELD_TYPE_CHAR, 80], //Prijmeni nebo firma
|
||||
// ['ULICE', DBFFIELD_TYPE_CHAR, 50], //Adresa
|
||||
// ['MESTO', DBFFIELD_TYPE_CHAR, 30], //Adresa
|
||||
// ['PSC', DBFFIELD_TYPE_CHAR, 10], //Adresa
|
||||
// ['ZEME', DBFFIELD_TYPE_CHAR, 30], //Adresa
|
||||
//
|
||||
// ['STAV', DBFFIELD_TYPE_CHAR, 10], // STORNO/PRODEJ
|
||||
// ['DATUM_SPLAT', DBFFIELD_TYPE_DATE], //datum splatnosti
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $row_pointer Record
|
||||
* @param $order \Order
|
||||
*/
|
||||
protected function appendToRow($row_pointer, $order)
|
||||
{
|
||||
/* FIXME: dodělat zbytek a přesměrovat DBF z export_sracka sem */
|
||||
if ($order->date_handle) {
|
||||
$row_pointer->setObjectByName('DATUM_VYST', $order->date_handle->format('Ymd')); // datum vystavení
|
||||
}
|
||||
// $r->setObjectByName("DATUM_SPL", $row['DBFFIELD_TYPE_DATE']); //prázdné
|
||||
// $row_pointer->setObjectByName('DOKLAD_1', $order['order_no']); //aby tam bylo fčíslo objednávky např. f11521
|
||||
// $row_pointer->setObjectByName('TYP_ZAP', 'P'); //hodnota P
|
||||
// $row_pointer->setObjectByName('ZNAK_UCT', ''); //prázdné
|
||||
// $row_pointer->setObjectByName('SYMBOLY', $order['id']); //včísloobjednávky např. v11521
|
||||
// $row_pointer->setObjectByName('PAR_ZNAK', $order['order_no']); //to samé jako DOKLAD_1 např. f11521
|
||||
// $row_pointer->setObjectByName('BANK_UCET', ''); //prázdné
|
||||
// $row_pointer->setObjectByName('SPEC_SYMB', ''); //prázdné
|
||||
// $row_pointer->setObjectByName('POPIS_TEXT', $encode('Objednávka: ').$order['id']); //libovolný text - např. prodej eshop-objednávka 11521
|
||||
// $row_pointer->setObjectByName('DRUH_UCT', 'PZ'); //hodnota PZ
|
||||
// $row_pointer->setObjectByName('MENA', $encode('Kč')); //buď Kč nebo EUR
|
||||
// $row_pointer->setObjectByName('CELKEM_KC', $total_price); //celková částka dokladu včetně DPH v Kč
|
||||
// $row_pointer->setObjectByName('CELKEMCIZI', 0); //celková částka dokladu v EUR - prodej na Slovensko?
|
||||
// $row_pointer->setObjectByName('KURZ', 0); //kurz pro přepočet
|
||||
// $row_pointer->setObjectByName('DATUM_DPH', strtotime($order['date_handle'])); //datum DPH = datum vystavení
|
||||
// $row_pointer->setObjectByName('TYP_DPH', 'U'); //hodnota U
|
||||
// $row_pointer->setObjectByName('ZAKL_DPH_Z', $taxes['21']); //Částka bez daně v základní sazbě
|
||||
// $row_pointer->setObjectByName('DPH_Z', $taxes['21']->mul(toDecimal(0.21))); //Daň sazba 21 %
|
||||
// $row_pointer->setObjectByName('ZAKL_DPH_S', $taxes['15']); //Částka bez daně ve snížené sazbě
|
||||
// $row_pointer->setObjectByName('DPH_S', $taxes['15']->mul(toDecimal(0.15))); //Částka bez daně ve snížené sazbě
|
||||
// $row_pointer->setObjectByName('TYPMIMODPH', ''); //prázdné
|
||||
// $row_pointer->setObjectByName('CASTKAMIMO', $taxes['0']); //prázdné
|
||||
// $row_pointer->setObjectByName('STREDISKO', ''); //PRÁZDNÉ
|
||||
// $row_pointer->setObjectByName('vykon', ''); //prázdné
|
||||
// $row_pointer->setObjectByName('zakazka', ''); //prázdné
|
||||
// $row_pointer->setObjectByName('POZNAMKA', "{$order['invoice_name']} {$order['invoice_surname']}, {$order['invoice_city']}"); //sem naimportovat jméno a příjmění a město kupujícího JAN NOVAK TURNOV
|
||||
// $row_pointer->setObjectByName('FIRMA', $order['invoice_firm']); // Firma
|
||||
// $row_pointer->setObjectByName('JMENO', $order['invoice_name']); //Jmeno
|
||||
// $row_pointer->setObjectByName('PRIJMENI', $order['invoice_surname']); //Prijmeni
|
||||
//
|
||||
// $row_pointer->setObjectByName('ICO', $order['invoice_ico']); //ICO
|
||||
// $row_pointer->setObjectByName('DIC', $order['invoice_dic']); //DIC
|
||||
//
|
||||
// $row_pointer->setObjectByName('ZAKAZNIK', $order['invoice_firm'] ? $order['invoice_firm'] : "{$order['invoice_name']} {$order['invoice_surname']}"); //Prijmeni nebo firma
|
||||
// $row_pointer->setObjectByName('ULICE', $order['invoice_street']);
|
||||
// $row_pointer->setObjectByName('MESTO', $order['invoice_city']);
|
||||
// $row_pointer->setObjectByName('PSC', $order['invoice_zip']);
|
||||
// $row_pointer->setObjectByName('ZEME', $order['invoice_country']);
|
||||
//
|
||||
// $row_pointer->setObjectByName('STAV', $order['status_storno'] ? 'STORNO' : 'PRODEJ'); // STORNO/PRODEJ
|
||||
// $row_pointer->setObjectByName('DATUM_SPLAT', strtotime($order['date_due']));
|
||||
}
|
||||
}
|
||||
125
admin/class/Export/ExportDataDBFUcto.php
Normal file
125
admin/class/Export/ExportDataDBFUcto.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace Export;
|
||||
|
||||
use XBase\Record;
|
||||
|
||||
/**
|
||||
* Own class for DBF export.
|
||||
*/
|
||||
class ExportDataDBFUcto extends ExportDataDBF
|
||||
{
|
||||
protected function columnDefs()
|
||||
{
|
||||
return [
|
||||
['Veta', Record::DBFFIELD_TYPE_NUMERIC, 6, 0], // datum vystavení
|
||||
['DatumVyst', Record::DBFFIELD_TYPE_DATE], // datum vystavení
|
||||
['DatumSpl', Record::DBFFIELD_TYPE_DATE], // datum splatnosti
|
||||
['Datum', Record::DBFFIELD_TYPE_DATE], // datum zaplacení - většinou prázdné
|
||||
|
||||
['Doklad', Record::DBFFIELD_TYPE_CHAR, 30], // Doklad
|
||||
['DokladKH', Record::DBFFIELD_TYPE_CHAR, 20],
|
||||
['TypD', Record::DBFFIELD_TYPE_CHAR, 3],
|
||||
['Text', Record::DBFFIELD_TYPE_CHAR, 30], // text
|
||||
['Druh', Record::DBFFIELD_TYPE_CHAR, 3], // klic do ciselniku druhu
|
||||
['Firma', Record::DBFFIELD_TYPE_CHAR, 5], // cislo firmy v adresari ucta
|
||||
['Ico', Record::DBFFIELD_TYPE_CHAR, 10], // ico firmy
|
||||
['Vykon', Record::DBFFIELD_TYPE_CHAR, 5], // klic do ciselniku vykonu
|
||||
|
||||
['Plat', Record::DBFFIELD_TYPE_CHAR, 1], // platba: B-banka, H-hotovos
|
||||
['Celkem', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // celkova castka
|
||||
|
||||
['DatumDPH', Record::DBFFIELD_TYPE_DATE], // datum zd. pl
|
||||
['DatumKH', Record::DBFFIELD_TYPE_DATE],
|
||||
|
||||
['BezDaneZ', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // dph
|
||||
['DphZ', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // dph
|
||||
['BezDaneS', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // dph
|
||||
['DphS', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // dph
|
||||
['BezDaneS2', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // dph
|
||||
['DphS2', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // dph
|
||||
['BezDaneO', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // dph
|
||||
['Zaloha', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // dph
|
||||
|
||||
['Prikaz', Record::DBFFIELD_TYPE_LOGICAL], // nevyplnovat, vyber pro prikaz k uhrade
|
||||
['DatumPrik', Record::DBFFIELD_TYPE_DATE], // nevyplnovat, datum pro prikaz k uhrade
|
||||
|
||||
['Pozn', Record::DBFFIELD_TYPE_MEMO], // poznámka (memo)
|
||||
['Ozn', Record::DBFFIELD_TYPE_LOGICAL], // označené věty
|
||||
|
||||
['Měna2', Record::DBFFIELD_TYPE_CHAR, 3], // Měna2
|
||||
['Kč2', Record::DBFFIELD_TYPE_FLOATING, 11, 2], // Kč2
|
||||
|
||||
['Naz0', Record::DBFFIELD_TYPE_CHAR, 30], // označené věty
|
||||
['Dic0', Record::DBFFIELD_TYPE_CHAR, 14], // označené věty
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $row_pointer Record
|
||||
* @param $order \Order
|
||||
*/
|
||||
protected function appendToRow($row_pointer, $order)
|
||||
{
|
||||
// $row_pointer->setObjectByName('Veta', '');
|
||||
$row_pointer->setObjectByName('DatumVyst', $order->date_handle ? strtotime($order->date_handle->format('Ymd')) : '');
|
||||
// $row_pointer->setObjectByName('DatumPrik', '');
|
||||
|
||||
/* TODO: dořešit due_days, nejlíp na order */
|
||||
$row_pointer->setObjectByName('DatumSpl', ($order->date_handle) ? strtotime($order->date_handle->modify('+14 days')->format('Ymd')) : '');
|
||||
// $row_pointer->setObjectByName('Datum', '');
|
||||
$row_pointer->setObjectByName('Doklad', 'f/'.$order->order_no);
|
||||
$row_pointer->setObjectByName('DokladKH', $order->order_no);
|
||||
$row_pointer->setObjectByName('TypD', ' ');
|
||||
$row_pointer->setObjectByName('Text', $this->encodeData($order->invoice_firm ? $order->invoice_firm : $order->invoice_name.' '.$order->invoice_surname));
|
||||
$row_pointer->setObjectByName('Druh', 'PZ ');
|
||||
$row_pointer->setObjectByName('Firma', ' ');
|
||||
$row_pointer->setObjectByName('Ico', strtoupper($order->invoice_ico));
|
||||
$row_pointer->setObjectByName('Vykon', ' ');
|
||||
|
||||
$pay_type = $order->getDeliveryType()->getPayment();
|
||||
|
||||
if ($pay_type && $pay_type->getPayMethod() == \Payment::METHOD_CASH) {
|
||||
$pay_type = 'H';
|
||||
} else {
|
||||
$pay_type = 'B';
|
||||
}
|
||||
|
||||
$row_pointer->setObjectByName('Plat', $this->encodeData($pay_type));
|
||||
$row_pointer->setObjectByName('Celkem', !$order->status_storno ? $order->total_price->printFloatValue(2) : 0);
|
||||
|
||||
/* TODO: datum zd. plneni */
|
||||
$row_pointer->setObjectByName('DatumDPH', $order->date_handle ? strtotime($order->date_handle->format('Ymd')) : '');
|
||||
// $row_pointer->setObjectByName('DatumKH', '');
|
||||
|
||||
if (!empty($order->vats[21]) && !$order->status_storno) {
|
||||
$row_pointer->setObjectByName('BezDaneZ', $order->vats[21]['total_price_without_vat']->printFloatValue(2));
|
||||
$row_pointer->setObjectByName('DphZ', $order->vats[21]['tax']['value_vat']->printFloatValue(2));
|
||||
} else {
|
||||
$row_pointer->setObjectByName('BezDaneZ', 0);
|
||||
$row_pointer->setObjectByName('DphZ', 0);
|
||||
}
|
||||
|
||||
// if (!empty($order->vats[15])) {
|
||||
// $row_pointer->setObjectByName('BezDaneS', $order->vats[15]['total_price_without_vat']->printFloatValue(2));
|
||||
// $row_pointer->setObjectByName('DphS', $order->vats[15]['tax']['value_vat']->printFloatValue(2));
|
||||
// } else {
|
||||
// $row_pointer->setObjectByName('BezDaneS', 0);
|
||||
// $row_pointer->setObjectByName('DphS', 0);
|
||||
// }
|
||||
|
||||
// $row_pointer->setObjectByName('BezDaneS2', 0);
|
||||
// $row_pointer->setObjectByName('DphS2', 0);
|
||||
// $row_pointer->setObjectByName('BezDaneO', 0);
|
||||
// $row_pointer->setObjectByName('Zaloha', 0);
|
||||
|
||||
$row_pointer->setObjectByName('Prikaz', false);
|
||||
// $row_pointer->setObjectByName('DatumPrik', 0);
|
||||
// $row_pointer->setObjectByName('Pozn', '');
|
||||
$row_pointer->setObjectByName('Ozn', false);
|
||||
$row_pointer->setObjectByName('Měna2', ' ');
|
||||
// $row_pointer->setObjectByName('Kč2', $order->currency_rate);
|
||||
$row_pointer->setObjectByName('Naz0', ' ');
|
||||
$row_pointer->setObjectByName('Dic0', strtoupper($order->invoice_dic));
|
||||
}
|
||||
}
|
||||
110
admin/class/Export/ExportDataExcel.php
Normal file
110
admin/class/Export/ExportDataExcel.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Export;
|
||||
|
||||
/**
|
||||
* ExportDataExcel exports data into an XML format (spreadsheetML) that can be
|
||||
* read by MS Excel 2003 and newer as well as OpenOffice.
|
||||
*
|
||||
* Creates a workbook with a single worksheet (title specified by
|
||||
* $title).
|
||||
*
|
||||
* Note that using .XML is the "correct" file extension for these files, but it
|
||||
* generally isn't associated with Excel. Using .XLS is tempting, but Excel 2007 will
|
||||
* throw a scary warning that the extension doesn't match the file type.
|
||||
*
|
||||
* Based on Excel XML code from Excel_XML (http://github.com/oliverschwarz/php-excel)
|
||||
* by Oliver Schwarz
|
||||
*/
|
||||
class ExportDataExcel extends ExportData
|
||||
{
|
||||
public const XmlHeader = "<?xml version=\"1.0\" encoding=\"%s\"?\>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:html=\"http://www.w3.org/TR/REC-html40\">";
|
||||
public const XmlFooter = '</Workbook>';
|
||||
|
||||
public $encoding = 'UTF-8'; // encoding type to specify in file.
|
||||
// Note that you're on your own for making sure your data is actually encoded to this encoding
|
||||
public $title = 'Sheet1'; // title for Worksheet
|
||||
|
||||
public function generateHeader()
|
||||
{
|
||||
// workbook header
|
||||
$output = stripslashes(sprintf(self::XmlHeader, $this->encoding))."\n";
|
||||
|
||||
// Set up styles
|
||||
$output .= "<Styles>\n";
|
||||
$output .= "<Style ss:ID=\"sDT\"><NumberFormat ss:Format=\"Short Date\"/></Style>\n";
|
||||
$output .= "</Styles>\n";
|
||||
|
||||
// worksheet header
|
||||
$output .= sprintf("<Worksheet ss:Name=\"%s\">\n <Table>\n", htmlentities($this->title));
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function generateFooter()
|
||||
{
|
||||
$output = '';
|
||||
|
||||
// worksheet footer
|
||||
$output .= " </Table>\n</Worksheet>\n";
|
||||
|
||||
// workbook footer
|
||||
$output .= self::XmlFooter;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function generateRow($row)
|
||||
{
|
||||
$output = '';
|
||||
$output .= " <Row>\n";
|
||||
foreach ($row as $k => $v) {
|
||||
$output .= $this->generateCell($v);
|
||||
}
|
||||
$output .= " </Row>\n";
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function generateCell($item)
|
||||
{
|
||||
$output = '';
|
||||
$style = '';
|
||||
|
||||
// Tell Excel to treat as a number. Note that Excel only stores roughly 15 digits, so keep
|
||||
// as text if number is longer than that.
|
||||
if (preg_match("/^-?\d+(?:[.,]\d+)?$/", $item) && (strlen($item) < 15)) {
|
||||
$type = 'Number';
|
||||
}
|
||||
// Sniff for valid dates; should look something like 2010-07-14 or 7/14/2010 etc. Can
|
||||
// also have an optional time after the date.
|
||||
//
|
||||
// Note we want to be very strict in what we consider a date. There is the possibility
|
||||
// of really screwing up the data if we try to reformat a string that was not actually
|
||||
// intended to represent a date.
|
||||
elseif (preg_match("/^(\d{1,2}|\d{4})[\/\-]\d{1,2}[\/\-](\d{1,2}|\d{4})([^\d].+)?$/", $item)
|
||||
&& ($timestamp = strtotime($item))
|
||||
&& ($timestamp > 0)
|
||||
&& ($timestamp < strtotime('+500 years'))) {
|
||||
$type = 'DateTime';
|
||||
$item = strftime('%Y-%m-%dT%H:%M:%S', $timestamp);
|
||||
$style = 'sDT'; // defined in header; tells excel to format date for display
|
||||
} else {
|
||||
$type = 'String';
|
||||
}
|
||||
|
||||
$item = str_replace(''', ''', htmlspecialchars($item, ENT_QUOTES));
|
||||
$output .= ' ';
|
||||
$output .= $style ? "<Cell ss:StyleID=\"{$style}\">" : '<Cell>';
|
||||
$output .= sprintf('<Data ss:Type="%s">%s</Data>', $type, $item);
|
||||
$output .= "</Cell>\n";
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function sendHttpHeaders()
|
||||
{
|
||||
header('Content-Type: application/vnd.ms-excel; charset='.$this->encoding);
|
||||
header('Content-Disposition: inline; filename="'.basename($this->filename).'"');
|
||||
}
|
||||
}
|
||||
26
admin/class/Export/ExportDataTSV.php
Normal file
26
admin/class/Export/ExportDataTSV.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Export;
|
||||
|
||||
/**
|
||||
* ExportDataTSV - Exports to TSV (tab separated value) format.
|
||||
*/
|
||||
class ExportDataTSV extends ExportData
|
||||
{
|
||||
public function generateRow($row)
|
||||
{
|
||||
foreach ($row as $key => $value) {
|
||||
// Escape inner quotes and wrap all contents in new quotes.
|
||||
// Note that we are using \" to escape double quote not ""
|
||||
$row[$key] = '"'.str_replace('"', '\"', $value).'"';
|
||||
}
|
||||
|
||||
return implode("\t", $row)."\n";
|
||||
}
|
||||
|
||||
public function sendHttpHeaders()
|
||||
{
|
||||
header('Content-type: text/tab-separated-values');
|
||||
header('Content-Disposition: attachment; filename='.basename($this->filename));
|
||||
}
|
||||
}
|
||||
412
admin/class/class.AdminBarMenu.php
Normal file
412
admin/class/class.AdminBarMenu.php
Normal file
@@ -0,0 +1,412 @@
|
||||
<?php
|
||||
|
||||
use KupShop\AdminBundle\AdminRegister\AdminRegisterLocator;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
|
||||
class AdminBarMenu
|
||||
{
|
||||
protected $customMenuItems = [];
|
||||
|
||||
protected $menu = [
|
||||
[
|
||||
'name' => 'administration',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'leadpage',
|
||||
'left' => 'blank', 'right' => 's=board.php',
|
||||
],
|
||||
[
|
||||
'name' => 'shopStore',
|
||||
'left' => 's=menu.php&type=shopStore', 'right' => 's=board.php&type=shopStore',
|
||||
],
|
||||
[
|
||||
'name' => 'newWindow',
|
||||
'script' => 'newWindow();',
|
||||
],
|
||||
[
|
||||
'name' => 'logout',
|
||||
'script' => 'logout(0)',
|
||||
],
|
||||
[
|
||||
'name' => 'adminEdit',
|
||||
'script' => "nw('adminEdit')",
|
||||
],
|
||||
[
|
||||
'name' => 'htmlComponents',
|
||||
/* 'left' => 's=menu.php&type=htmlComponents', */ 'right' => 's=board.php&type=htmlComponents',
|
||||
],
|
||||
[
|
||||
'name' => 'chooseLanguage',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'czech',
|
||||
'href' => 'admin-change-language/czech',
|
||||
],
|
||||
[
|
||||
'name' => 'english',
|
||||
'href' => 'admin-change-language/english',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'productsMenu',
|
||||
'left' => 's=menu.php&type=products', 'right' => 's=list.php&type=products',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'products',
|
||||
'left' => 's=menu.php&type=products', 'right' => 's=list.php&type=products',
|
||||
],
|
||||
[
|
||||
'name' => 'productsMassModification',
|
||||
'left' => 'blank', 'right' => 's=list.php&type=productsMassModification',
|
||||
],
|
||||
[
|
||||
'name' => 'parameters',
|
||||
'left' => 's=menu.php&type=parameters', 'right' => 's=list.php&type=parameters',
|
||||
],
|
||||
[
|
||||
'name' => 'productsVarLabels',
|
||||
'left' => 's=menu.php&type=productsVarLabels', 'right' => 's=list.php&type=productsVarLabels',
|
||||
],
|
||||
[
|
||||
'name' => 'sections',
|
||||
'left' => 's=menu.php&type=sections', 'right' => 's=list.php&type=sections',
|
||||
],
|
||||
[
|
||||
'name' => 'producers',
|
||||
'left' => 's=menu.php&type=producers', 'right' => 's=list.php&type=producers',
|
||||
],
|
||||
[
|
||||
'name' => 'templatesMenu',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'templates',
|
||||
'left' => 's=menu.php&type=templates', 'right' => 's=list.php&type=templates',
|
||||
],
|
||||
[
|
||||
'name' => 'templatesCategories',
|
||||
'left' => 's=menu.php&type=templatesCategories', 'right' => 's=list.php&type=templatesCategories',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'reviews',
|
||||
'left' => 's=menu.php&type=reviews', 'right' => 's=list.php&type=reviews&type_list=ShowNotConfirmed',
|
||||
],
|
||||
[
|
||||
'name' => 'productsRelatedTypes',
|
||||
'left' => 's=menu.php&type=productsRelatedTypes', 'right' => 's=list.php&type=productsRelatedTypes',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'ordersMenu',
|
||||
'left' => 's=menu.php&type=orders', 'right' => 's=list.php&type=orders',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'orders',
|
||||
'left' => 's=menu.php&type=orders', 'right' => 's=list.php&type=orders',
|
||||
],
|
||||
[
|
||||
'name' => 'users',
|
||||
'left' => 's=menu.php&type=users', 'right' => 's=list.php&type=users',
|
||||
],
|
||||
[
|
||||
'name' => 'usersGroups',
|
||||
'left' => 's=menu.php&type=usersGroups', 'right' => 's=list.php&type=usersGroups',
|
||||
],
|
||||
|
||||
[
|
||||
'name' => 'ordersMassProcess',
|
||||
'left' => 's=menu.php&type=ordersMassProcess', 'right' => 's=list.php&type=ordersMassProcess',
|
||||
],
|
||||
|
||||
[
|
||||
'name' => 'old_pos',
|
||||
'script' => "nw('old_pos')",
|
||||
],
|
||||
|
||||
[
|
||||
'name' => 'orderPayment',
|
||||
'left' => 's=menu.php&type=orderPayment', 'right' => null,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'stockMenu',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'stockIn',
|
||||
'left' => 's=menu.php&type=stockIn', 'right' => 's=list.php&type=stockIn',
|
||||
],
|
||||
[
|
||||
'name' => 'suppliers',
|
||||
'left' => 's=menu.php&type=suppliers', 'right' => 's=list.php&type=suppliers',
|
||||
],
|
||||
[
|
||||
'name' => 'stockInMissing',
|
||||
'left' => 's=menu.php&type=stockInMissing', 'right' => 's=list.php&type=stockInMissing&fromNav=1',
|
||||
],
|
||||
[
|
||||
'name' => 'productsOfSuppliers',
|
||||
'left' => 's=menu.php&type=productsOfSuppliers', 'right' => 's=list.php&type=productsOfSuppliers',
|
||||
],
|
||||
[
|
||||
'name' => 'ordersOfSuppliers',
|
||||
'left' => 's=menu.php&type=ordersOfSuppliers', 'right' => 's=list.php&type=ordersOfSuppliers',
|
||||
],
|
||||
|
||||
[
|
||||
'name' => 'inventory',
|
||||
'left' => 's=menu.php&type=inventory', 'right' => 's=list.php&type=inventory',
|
||||
],
|
||||
|
||||
[
|
||||
'name' => 'productsPrices',
|
||||
'left' => 's=menu.php&type=productsPrices', 'right' => 's=list.php&type=productsPrices',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'contentMenu',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'menu',
|
||||
'left' => 's=menu.php&type=menu', 'right' => 's=list.php&type=menu',
|
||||
],
|
||||
[
|
||||
'name' => 'sliders',
|
||||
'left' => 's=menu.php&type=sliders', 'right' => 's=list.php&type=sliders',
|
||||
],
|
||||
[
|
||||
'name' => 'articlesMenu',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'articles',
|
||||
'left' => 's=menu.php&type=articles', 'right' => 's=list.php&type=articles',
|
||||
],
|
||||
[
|
||||
'name' => 'artsections',
|
||||
'left' => 's=menu.php&type=artsections', 'right' => 's=list.php&type=artsections',
|
||||
],
|
||||
[
|
||||
'name' => 'artauthors',
|
||||
'left' => 's=menu.php&type=artauthors', 'right' => 's=list.php&type=artauthors',
|
||||
],
|
||||
[
|
||||
'name' => 'articlesTags',
|
||||
'left' => 's=menu.php&type=articlesTags', 'right' => 's=list.php&type=articlesTags',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'sellers',
|
||||
'left' => 's=menu.php&type=sellers', 'right' => 's=list.php&type=sellers',
|
||||
],
|
||||
[
|
||||
'name' => 'photos',
|
||||
'left' => 's=menu.php&type=photos', 'right' => 's=list.php&type=photos',
|
||||
],
|
||||
[
|
||||
'name' => 'fileBrowser',
|
||||
'script' => 'nw(\'kcfinder\', \'all\')',
|
||||
],
|
||||
/*[
|
||||
'name' => 'fileBrowser',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'browseImages',
|
||||
'script' => 'nw(\'kcfinder\')',
|
||||
],
|
||||
[
|
||||
'name' => 'browseFiles',
|
||||
'script' => 'nw(\'kcfinder\', \'other\')',
|
||||
],
|
||||
],
|
||||
],*/
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'toolsMenu',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'dbbackup',
|
||||
'left' => 's=menu.php&type=dbbackup', 'right' => 's=list.php&type=dbbackup',
|
||||
],
|
||||
|
||||
[
|
||||
'name' => 'stats',
|
||||
'left' => 'blank', 'right' => 's=board.php&type=stats',
|
||||
],
|
||||
[
|
||||
'name' => 'export',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'export_products',
|
||||
'left' => 's=menu.php&type=export', 'right' => 's=board.php&type=export_products',
|
||||
],
|
||||
[
|
||||
'name' => 'export_selling_products',
|
||||
'left' => 's=menu.php&type=export', 'right' => 's=board.php&type=export_selling_products',
|
||||
],
|
||||
[
|
||||
'name' => 'export_orders',
|
||||
'left' => 's=menu.php&type=export', 'right' => 's=board.php&type=export_orders',
|
||||
],
|
||||
[
|
||||
'name' => 'export_users',
|
||||
'left' => 's=menu.php&type=export', 'right' => 's=board.php&type=export_users',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'import',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'import-generic',
|
||||
'right' => 's=import.generic.php',
|
||||
],
|
||||
[
|
||||
'name' => 'import_automatic',
|
||||
'left' => 's=menu.php&type=automatic_import', 'right' => 's=list.php&type=automatic_import',
|
||||
],
|
||||
[
|
||||
'name' => 'import-xml_feed',
|
||||
'script' => "nw('import.xml_feed')",
|
||||
],
|
||||
[
|
||||
'name' => 'import-xml_feed_new',
|
||||
'script' => "nw('import.xml_feed_new')",
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'cleaning',
|
||||
'script' => "nw('cleaning')",
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'settingsMenu',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'admins',
|
||||
'left' => 's=menu.php&type=admins', 'right' => 's=list.php&type=admins',
|
||||
],
|
||||
[
|
||||
'name' => 'settings',
|
||||
'script' => "nw('settings')",
|
||||
],
|
||||
[
|
||||
'name' => 'emails',
|
||||
'script' => "nw('emails')",
|
||||
],
|
||||
[
|
||||
'name' => 'delivery',
|
||||
'submenu' => [
|
||||
[
|
||||
'name' => 'delivery_type',
|
||||
'left' => 's=menu.php&type=delivery', 'right' => 's=list.php&type=delivery',
|
||||
],
|
||||
[
|
||||
'name' => 'deliveryDelivery',
|
||||
'left' => 's=menu.php&type=deliveryDelivery', 'right' => 's=list.php&type=deliveryDelivery',
|
||||
],
|
||||
[
|
||||
'name' => 'deliveryPayment',
|
||||
'left' => 's=menu.php&type=deliveryPayment', 'right' => 's=list.php&type=deliveryPayment',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'vats',
|
||||
'left' => 's=menu.php&type=vats', 'right' => 's=list.php&type=vats',
|
||||
],
|
||||
[
|
||||
'name' => 'priceLevels',
|
||||
'left' => 's=menu.php&type=pricelevels', 'right' => 's=list.php&type=pricelevels',
|
||||
],
|
||||
[
|
||||
'name' => 'fulltext',
|
||||
'script' => "nw('fulltext')",
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function getMenu(): array
|
||||
{
|
||||
$userRights = new UserRights();
|
||||
/** @var \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher */
|
||||
$dispatcher = ServiceContainer::getService('event_dispatcher');
|
||||
$event = new \KupShop\KupShopBundle\Event\CreateMenuEvent($this, $userRights);
|
||||
$dispatcher->dispatch($event, \KupShop\KupShopBundle\Event\CreateMenuEvent::COMPLETING_TREE);
|
||||
$adminRegisterLocator = ServiceContainer::getService(AdminRegisterLocator::class);
|
||||
foreach ($adminRegisterLocator->getMenu() as $menu => $items) {
|
||||
foreach ($items as $item) {
|
||||
$this->addItem($menu, $item);
|
||||
}
|
||||
}
|
||||
$this->sortMenu($this->menu);
|
||||
|
||||
return $this->menu;
|
||||
}
|
||||
|
||||
private function sortMenu(&$menu)
|
||||
{
|
||||
foreach ($menu as $pos => &$item) {
|
||||
if (is_array($item) && array_key_exists('submenu', $item)) {
|
||||
$this->sortMenu($item['submenu']);
|
||||
}
|
||||
|
||||
if (is_array($item) && array_key_exists('position', $item)) {
|
||||
$menuItem = [$menu[$pos]];
|
||||
unset($menu[$pos]);
|
||||
array_splice($menu, $item['position'], 0, $menuItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addItem($menuName, $item, &$menu = null, $index = 0)
|
||||
{
|
||||
if (!$menu) {
|
||||
$menu = &$this->menu;
|
||||
}
|
||||
// / new
|
||||
$menuNames = $this->getMenuNames($menuName);
|
||||
$maxIndex = count($menuNames) - 1;
|
||||
foreach ($menu as &$menuItem) {
|
||||
if ($menuItem['name'] == $menuNames[$index]) {
|
||||
if ($index == $maxIndex) {
|
||||
$menuItem['submenu'][] = $item;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
$result = $this->addItem($menuName, $item, $menuItem['submenu'], ++$index);
|
||||
if ($result) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create root menu item if $menuItem was not found
|
||||
$menu[] = $item;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getMenuNames($menuName)
|
||||
{
|
||||
$names = explode('/', $menuName);
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
public function setMenu(array $menu)
|
||||
{
|
||||
$this->menu = $menu;
|
||||
}
|
||||
}
|
||||
31
admin/class/class.AdminListSortable.php
Normal file
31
admin/class/class.AdminListSortable.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
trait AdminListSortable
|
||||
{
|
||||
public function saveList($item, $table, $columns = 'position', $extra_where = '', $id_column = 'id')
|
||||
{
|
||||
if ($item['direction'] == 'down') {
|
||||
$item['position']++;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$column = reset($columns);
|
||||
} else {
|
||||
$column = $columns;
|
||||
}
|
||||
|
||||
$columns = join(', ', (array) $columns);
|
||||
|
||||
sqlQuery("UPDATE {$table} SET {$column}={$column}+1 WHERE {$column} >= {$item['position']}{$extra_where}");
|
||||
|
||||
sqlQuery("UPDATE {$table} SET {$column}={$item['position']} WHERE {$id_column}={$item['id']}{$extra_where}");
|
||||
|
||||
$this->saveAllPositions($column, $columns, $extra_where, $table);
|
||||
}
|
||||
|
||||
public function saveAllPositions($column, $columns, mixed $extraWhere, ?string $table = null): void
|
||||
{
|
||||
$table ??= $this->tableName;
|
||||
sqlQuery("SELECT @i := -1; UPDATE {$table} SET {$column} = (select @i := @i + 1) WHERE 1{$extraWhere} ORDER BY {$columns}");
|
||||
}
|
||||
}
|
||||
95
admin/class/class.Base.php
Normal file
95
admin/class/class.Base.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: hanz
|
||||
* Date: 29.4.14
|
||||
* Time: 14:49s.
|
||||
*/
|
||||
class Base
|
||||
{
|
||||
protected $smarty;
|
||||
protected $template;
|
||||
|
||||
public function init_smarty()
|
||||
{
|
||||
$this->smarty = createSmarty(true, true);
|
||||
}
|
||||
|
||||
public function getTemplate()
|
||||
{
|
||||
if (empty($this->template)) {
|
||||
throw new Exception('Empty template name');
|
||||
}
|
||||
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
public function setTemplate($name)
|
||||
{
|
||||
$this->template = $name;
|
||||
}
|
||||
|
||||
public static function getClassName()
|
||||
{
|
||||
$className = explode('\\', get_called_class());
|
||||
|
||||
return end($className);
|
||||
}
|
||||
|
||||
public function display()
|
||||
{
|
||||
$this->smarty->display($this->getTemplate());
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$acn = getVal('acn');
|
||||
if ($acn) {
|
||||
$action = 'handle'.ucfirst($acn);
|
||||
if (method_exists($this, $action)) {
|
||||
call_user_func([$this, $action]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
// Process POSTEd values
|
||||
$this->handle();
|
||||
|
||||
// Collect template variables
|
||||
$vars = $this->collectVariables();
|
||||
|
||||
// Init templating system
|
||||
$this->init_smarty();
|
||||
|
||||
// Assign template variables to template
|
||||
$this->assign_($vars);
|
||||
|
||||
// Render template
|
||||
$this->display();
|
||||
}
|
||||
|
||||
protected function collectVariables()
|
||||
{
|
||||
return $this->get_vars();
|
||||
}
|
||||
|
||||
protected function get_vars()
|
||||
{
|
||||
return [
|
||||
'view' => $this,
|
||||
];
|
||||
}
|
||||
|
||||
public function getPageHandler()
|
||||
{
|
||||
return getVal('s');
|
||||
}
|
||||
|
||||
public function assign_($array)
|
||||
{
|
||||
$this->smarty->assign($array);
|
||||
}
|
||||
}
|
||||
271
admin/class/class.BaseAdminPhotos.php
Normal file
271
admin/class/class.BaseAdminPhotos.php
Normal file
@@ -0,0 +1,271 @@
|
||||
<?php
|
||||
|
||||
class BaseAdminPhotos extends Frame
|
||||
{
|
||||
use DatabaseCommunication;
|
||||
|
||||
protected $template = 'adminPhotos.tpl';
|
||||
protected $relation_table_name;
|
||||
protected $photo_type;
|
||||
protected $tablefield;
|
||||
protected $photo_nametype;
|
||||
protected $photo_admin_name;
|
||||
protected $copy_from;
|
||||
|
||||
public function get_vars()
|
||||
{
|
||||
$vars = parent::get_vars();
|
||||
|
||||
$pageVars = getVal('body', $vars, []);
|
||||
|
||||
$acn = $this->getAction();
|
||||
$ID = $this->getID();
|
||||
$pageVars['acn'] = $acn;
|
||||
$pageVars['s'] = getVal('s');
|
||||
|
||||
$SQL = sqlQuery("SELECT ph.id, ph.descr,ph.source, ph.image_2, MAX(php.show_in_lead) as show_in_lead, ph.date,
|
||||
MAX(php.position) as position, ph.data as data, ph.date_update
|
||||
FROM photos AS ph, {$this->relation_table_name} AS php
|
||||
WHERE ph.id=php.id_photo AND php.{$this->tablefield}=:id
|
||||
GROUP BY ph.id
|
||||
ORDER BY position ASC", ['id' => $ID]); // , php.date_added ASC;
|
||||
|
||||
$photos = [];
|
||||
foreach ($SQL as $row) {
|
||||
$row['IDph'] = $row['id'];
|
||||
$row['img'] = getImage($row['id'], $row['image_2'], $row['source'], $this->photo_type, $row['descr'], strtotime($row['date_update']));
|
||||
$row['width'] = ($row['img']['width'] <= 200) ? $row['img']['width'] : 200;
|
||||
$this->unserializeCustomData($row);
|
||||
if (findModule('products_variations_photos') && $this->relation_table_name == 'photos_products_relation') {
|
||||
$row['varSel'] = [];
|
||||
$SQLp = sqlQuery("SELECT id_variation FROM {$this->relation_table_name} pp WHERE pp.id_photo=:id_photo AND pp.{$this->tablefield}=:ID AND pp.id_variation IS NOT NULL", ['id_photo' => $row['IDph'], 'ID' => $ID]);
|
||||
foreach ($SQLp as $rowp) {
|
||||
$row['varSel'][] = $rowp['id_variation'];
|
||||
}
|
||||
if (empty($row['varSel'])) {
|
||||
$row['varSel'] = ['-1'];
|
||||
}
|
||||
}
|
||||
|
||||
$photos[] = $row;
|
||||
}
|
||||
$pageVars['photos'] = $photos;
|
||||
|
||||
if (findModule('products_variations_photos') && $this->relation_table_name == 'photos_products_relation') {
|
||||
$variations = ['-1' => 'Žádná přiřazená varianta'];
|
||||
if (findModule('products_variations_photos')) {
|
||||
$SQLv = sqlQuery("SELECT id, title
|
||||
FROM products_variations pv
|
||||
WHERE pv.{$this->tablefield}=:ID", ['ID' => $ID]);
|
||||
while (($row = sqlFetchAssoc($SQLv)) !== false) {
|
||||
$variations[$row['id']] = $row['title'];
|
||||
}
|
||||
}
|
||||
$pageVars['variations'] = $variations;
|
||||
}
|
||||
$pageVars['ID'] = $ID;
|
||||
$pageVars['tablefield'] = $this->tablefield;
|
||||
$pageVars['copy_from'] = $this->copy_from;
|
||||
$pageVars['photo_nametype'] = $this->photo_nametype;
|
||||
$pageVars['search_field'] = $this->search_field;
|
||||
|
||||
$vars['body'] = $pageVars;
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
global $cfg;
|
||||
parent::handle();
|
||||
$ID = $this->getID();
|
||||
if (getVal('data') && $ID) {
|
||||
if (findModule('products_variations_photos') && $this->relation_table_name == 'photos_products_relation') {
|
||||
$photoVariations = getVal('id_variation', null, []);
|
||||
|
||||
foreach ($photoVariations as $IDph => $variations) {
|
||||
sqlQuery("DELETE FROM {$this->relation_table_name} WHERE id_photo=:IDph AND {$this->tablefield} = :ID", ['ID' => $ID, 'IDph' => $IDph]);
|
||||
|
||||
foreach ($variations as $variation) {
|
||||
$insert = [
|
||||
'id_photo' => $IDph,
|
||||
$this->tablefield => $ID,
|
||||
'date_added' => 'NOW()',
|
||||
];
|
||||
|
||||
if ($variation > 0) {
|
||||
$insert['id_variation'] = $variation;
|
||||
} else { // maze to duplicity z databaze
|
||||
sqlQuery("DELETE FROM {$this->relation_table_name} WHERE id_photo=:IDph AND {$this->tablefield} = :ID", ['ID' => $ID, 'IDph' => $IDph]);
|
||||
}
|
||||
|
||||
sqlQueryBuilder()->insert($this->relation_table_name)
|
||||
->directValues($insert)->onDuplicateKeyUpdate([])->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data = getVal('data', null, []);
|
||||
$pos = 0;
|
||||
foreach ($data as $id => $photo) {
|
||||
if (!empty($photo['delete']) || !$id) {
|
||||
if ($id > 0) {
|
||||
$this->handleDeleteRelationPhoto($id);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$values = ['position' => $pos++];
|
||||
if (isset($cfg['Photo']['kind']) && $this->tablefield == 'id_product') {
|
||||
$values['show_in_lead'] = $photo['show_in_lead'];
|
||||
}
|
||||
$this->serializeCustomData($photo);
|
||||
$this->updateSQL('photos', $photo, ['id' => $id], ['position', 'show_in_lead']);
|
||||
$this->updateSQL($this->relation_table_name, $values, [$this->tablefield => $ID, 'id_photo' => $id]);
|
||||
}
|
||||
|
||||
Photos::checkLeadPhoto($this->relation_table_name, $this->tablefield, $ID);
|
||||
|
||||
$this->returnOK('Uloženo');
|
||||
}
|
||||
if (!empty($_FILES)) {
|
||||
global $cfg;
|
||||
|
||||
sqlGetConnection()->transactional(function () use ($ID) {
|
||||
$img = new Photos($this->photo_admin_name ?: lcfirst($this->photo_nametype));
|
||||
$img->newImage();
|
||||
|
||||
// uploadovat velky obrazek
|
||||
$img->uploadPhotoOrVideo($_FILES['qqfile'], ($_REQUEST['qqfilename'] ?? false) ? $_REQUEST['qqfilename'] : '');
|
||||
|
||||
// ID nove fotky
|
||||
$IDph = $img->getID();
|
||||
|
||||
if ($this->photo_nametype == 'Product') {
|
||||
$img->{"insert{$this->photo_nametype}Relation"}($IDph, $ID, 'N', 'Y');
|
||||
} else {
|
||||
$img->insertRelation($this->relation_table_name, $IDph, $this->tablefield, $ID, 'N');
|
||||
}
|
||||
});
|
||||
|
||||
header('Content-type: text/plain');
|
||||
exit('{"success":true}');
|
||||
}
|
||||
}
|
||||
|
||||
public function handleDeleteRelationPhoto($IDph)
|
||||
{
|
||||
$IDpr = $this->getID();
|
||||
|
||||
sqlQuery("DELETE FROM {$this->relation_table_name} WHERE id_photo='{$IDph}' AND {$this->tablefield}=:IDpr", ['IDpr' => $IDpr]);
|
||||
}
|
||||
|
||||
public function handleDeletePhoto()
|
||||
{
|
||||
$IDph = getVal('IDph');
|
||||
|
||||
sqlQuery('DELETE FROM photos WHERE id=:IDph', ['IDph' => $IDph]);
|
||||
|
||||
$this->returnOK();
|
||||
}
|
||||
|
||||
public function handleInsertPhoto()
|
||||
{
|
||||
$errors = [];
|
||||
$data = getVal('data');
|
||||
$id_photos = explode(',', $data['id_photo']);
|
||||
$count = sqlQueryBuilder()->select('COUNT(*)')
|
||||
->from($this->relation_table_name)
|
||||
->where(\Query\Operator::equals([$this->tablefield => $this->getID()]))
|
||||
->execute()
|
||||
->fetchColumn();
|
||||
foreach ($id_photos as $id_photo) {
|
||||
$data = [
|
||||
$this->tablefield => $this->getID(),
|
||||
'id_photo' => $id_photo,
|
||||
'date_added' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
if (empty($data['id_photo'])) {
|
||||
$this->returnError('Nevybrána žádna fotografie!');
|
||||
}
|
||||
|
||||
if (sqlQueryBuilder()->select('COUNT(*)')
|
||||
->from($this->relation_table_name)
|
||||
->where(\Query\Operator::equals(['id_photo' => $id_photo, $this->tablefield => $data[$this->tablefield]]))
|
||||
->execute()
|
||||
->fetchColumn()) {
|
||||
$errors[] = "Fotografie s ID {$data['id_photo']} je již přiřazena!";
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$this->insertSQL($this->relation_table_name, $data);
|
||||
} catch (Exception $e) {
|
||||
switch (intval($e->getPrevious()->errorInfo[1])) {
|
||||
case 1062:
|
||||
$errors[] = "Fotografie s ID {$data['id_photo']} je již přiřazena!";
|
||||
// no break
|
||||
default:
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateSQL(
|
||||
$this->relation_table_name,
|
||||
['position' => $count, 'show_in_lead' => $count == 0 ? 'Y' : 'N'],
|
||||
[$this->tablefield => $data[$this->tablefield], 'id_photo' => $data['id_photo']]
|
||||
);
|
||||
$count++;
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->returnError(join(' ', $errors));
|
||||
}
|
||||
|
||||
$this->returnOK();
|
||||
}
|
||||
|
||||
public function handleCopyPhotos()
|
||||
{
|
||||
$data = getVal('data');
|
||||
$data['ID'] = $this->getID();
|
||||
|
||||
$data['count'] = returnSQLResult("SELECT COUNT(*) FROM {$this->relation_table_name} WHERE {$this->tablefield}=:field", ['field' => $this->getID()]);
|
||||
|
||||
sqlQuery("REPLACE INTO {$this->relation_table_name}
|
||||
(id_photo, {$this->tablefield}, date_added, show_in_lead, position)
|
||||
SELECT id_photo, :ID, NOW(), 'N', position+:count
|
||||
FROM {$this->relation_table_name}
|
||||
WHERE {$this->tablefield}=:{$this->tablefield}", $data);
|
||||
|
||||
Photos::checkLeadPhoto($this->relation_table_name, $this->tablefield, $this->getID());
|
||||
|
||||
$this->returnOK('Obrázky byly zkopírovány');
|
||||
}
|
||||
|
||||
public function handleMovePhoto()
|
||||
{
|
||||
$item = getVal('moved_item');
|
||||
|
||||
if (!empty($item)) {
|
||||
Photos::checkLeadPhoto($this->relation_table_name, $this->tablefield, $item[$this->tablefield]);
|
||||
|
||||
sqlQuery("UPDATE {$this->relation_table_name} SET position=position+1000 WHERE position >= :position AND {$this->tablefield}=:id", ['id' => $item[$this->tablefield], 'position' => $item['position']]);
|
||||
|
||||
sqlQuery("UPDATE {$this->relation_table_name} SET position=:position WHERE id_photo=:id_photo AND {$this->tablefield}=:id", ['id' => $item[$this->tablefield], 'position' => $item['position'], 'id_photo' => $item['id_photo']]);
|
||||
|
||||
Photos::checkLeadPhoto($this->relation_table_name, $this->tablefield, $item[$this->tablefield]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function checkPhotos($table, $id_field, $id_photo)
|
||||
{
|
||||
$sql = sqlQuery("SELECT {$id_field} FROM {$table} WHERE id_photo=:idph", ['idph' => $id_photo]);
|
||||
$array = sqlFetchAll($sql, [$id_field => $id_field]);
|
||||
sqlQuery("DELETE FROM {$table} WHERE id_photo=:idph", ['idph' => $id_photo]);
|
||||
|
||||
foreach ($array as $ID) {
|
||||
Photos::checkLeadPhoto($table, $id_field, $ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
51
admin/class/class.BaseAdminSectionsRelations.php
Normal file
51
admin/class/class.BaseAdminSectionsRelations.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
use KupShop\AdminBundle\Util\AdminSectionTree;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
|
||||
class BaseAdminSectionsRelations extends \Frame
|
||||
{
|
||||
protected $template = 'sectionsRelations.tpl';
|
||||
|
||||
protected AdminSectionTree $adminSectionTree;
|
||||
|
||||
protected string $label;
|
||||
protected string $tableName;
|
||||
protected string $column;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->adminSectionTree = ServiceContainer::getService(AdminSectionTree::class);
|
||||
}
|
||||
|
||||
public function get_vars()
|
||||
{
|
||||
$vars = parent::get_vars();
|
||||
|
||||
$pageVars['tree'] = $this->adminSectionTree->getCategories();
|
||||
$pageVars['category0'] = $this->adminSectionTree->getCategory0();
|
||||
$pageVars['selected'] = $this->adminSectionTree->getSelected($this->getID(), $this->tableName, $this->label, $this->column);
|
||||
$this->adminSectionTree->getOpened($pageVars['tree']);
|
||||
$pageVars['opened'] = $this->adminSectionTree->opened;
|
||||
|
||||
$vars['body'] = $pageVars;
|
||||
$vars['body']['data']['id'] = $this->getID();
|
||||
$vars['body']['ID'] = $this->getID();
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
parent::handle();
|
||||
|
||||
if (getVal('isSubmitted')) {
|
||||
$this->handleSubmit();
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleSubmit(): void
|
||||
{
|
||||
throw new \RuntimeException('Not implemented!');
|
||||
}
|
||||
}
|
||||
556
admin/class/class.ExportProducts.php
Normal file
556
admin/class/class.ExportProducts.php
Normal file
@@ -0,0 +1,556 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: hanz
|
||||
* Date: 9/2/15
|
||||
* Time: 8:30 AM.
|
||||
*/
|
||||
|
||||
use KupShop\AdminBundle\Exception\ExportException;
|
||||
use KupShop\AdminBundle\Util\ActivityLog;
|
||||
use KupShop\CatalogBundle\Section\SectionTree;
|
||||
use KupShop\CatalogBundle\Util\ProductsFilterSpecs;
|
||||
use KupShop\KupShopBundle\Config;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\KupShopBundle\Util\Excel\ExcelGenerator;
|
||||
use KupShop\StoresBundle\Query\StoresQuery;
|
||||
use KupShop\StoresBundle\Utils\StoresInStore;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
use Query\Operator;
|
||||
use Query\QueryBuilder;
|
||||
|
||||
class ExportProducts
|
||||
{
|
||||
use \KupShop\AdminBundle\Util\CategoryTree;
|
||||
|
||||
public function getFile()
|
||||
{
|
||||
while (ob_get_level()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
increaseMemoryLimit(1024);
|
||||
ini_set('max_execution_time', '600');
|
||||
|
||||
$filename = 'Products-'.date('Y-m-d_H-i').'.xlsx';
|
||||
try {
|
||||
$this->checkItemsCount();
|
||||
$generator = new ExcelGenerator();
|
||||
$this->defineHeader();
|
||||
$generator->generateExcel($this->getHeader(), $this->getData(), $filename);
|
||||
} catch (ExportException $e) {
|
||||
redirect('launch.php?s=board.php&type=export_products&ErrStr='.urlencode($e->getMessage()));
|
||||
} catch (Exception $exception) {
|
||||
$sentry = getRaven();
|
||||
$sentry->captureException($exception);
|
||||
}
|
||||
|
||||
addActivityLog(
|
||||
ActivityLog::SEVERITY_NOTICE,
|
||||
ActivityLog::TYPE_COMMUNICATION,
|
||||
sprintf('Export produktů: %s', $filename)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
protected $fields = 'p.id,p.campaign, p.title, p.guarantee, pr.name as producer, p.short_descr, p.long_descr,
|
||||
ps.id_section, v.vat, p.discount, p.show_in_feed, p.max_cpc, p.parameters, p.delivery_time, p.pieces_sold,
|
||||
p.meta_title, p.meta_description, p.meta_keywords, GROUP_CONCAT(DISTINCT pa.link) AS attachments, p.date_added,
|
||||
p.figure, pv.figure figure_variation,
|
||||
COALESCE(pv.width, p.width) as width,
|
||||
COALESCE(pv.height, p.height) as height,
|
||||
COALESCE(pv.depth, p.depth) as depth';
|
||||
|
||||
protected $column_names = [
|
||||
'code' => ['name' => 'Kód'],
|
||||
'title' => ['name' => 'Název'],
|
||||
'campaign' => ['name' => 'kampaně'],
|
||||
'producer' => ['name' => 'Výrobce'],
|
||||
'supplier_code' => ['name' => 'Kód dodavatele'],
|
||||
'section' => ['name' => 'Sekce'],
|
||||
'short_descr' => ['name' => 'Anotace'],
|
||||
'long_descr' => ['name' => 'Popis'],
|
||||
'parameters' => ['name' => 'Parametry'],
|
||||
'photo' => ['name' => 'Fotografie'],
|
||||
'vat' => ['name' => 'Sazba DPH', 'type' => DataType::TYPE_NUMERIC],
|
||||
'price_without_vat' => ['name' => 'cena bez DPH [Kč]', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.00'],
|
||||
'price_with_vat' => ['name' => 'cena s DPH [Kč]', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.00'],
|
||||
'discount' => ['name' => 'sleva [%]', 'type' => DataType::TYPE_NUMERIC],
|
||||
'price_for_discount' => ['name' => 'cena pro slevu', 'type' => DataType::TYPE_NUMERIC],
|
||||
'discount_price_without_vat' => ['name' => 'cena po slevě bez DPH [Kč]', 'type' => DataType::TYPE_NUMERIC],
|
||||
'discount_price_with_vat' => ['name' => 'cena po slevě s DPH [Kč]', 'type' => DataType::TYPE_NUMERIC],
|
||||
'in_store' => ['name' => 'skladem [ks]', 'type' => DataType::TYPE_NUMERIC],
|
||||
'in_store_min' => ['name' => 'Minimálně skladem [ks]', 'type' => DataType::TYPE_NUMERIC],
|
||||
'delivery_time' => ['name' => 'Dostupnost', 'type' => DataType::TYPE_NUMERIC],
|
||||
'guarantee' => ['name' => 'záruka [měs.]', 'type' => DataType::TYPE_NUMERIC],
|
||||
'show_in_feed' => ['name' => 'Zobrazovat ve srovnávačích'],
|
||||
'max_cpc' => ['name' => 'cena za proklik [Kč]', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.00'],
|
||||
'ean' => ['name' => 'Kód EAN'],
|
||||
'pieces_sold' => ['name' => 'Počet prodaných kusů', 'type' => DataType::TYPE_NUMERIC, 'format' => '0'],
|
||||
'id' => ['name' => 'ID produktu', 'type' => DataType::TYPE_NUMERIC],
|
||||
'meta_title' => ['name' => 'SEO Titulek'],
|
||||
'meta_description' => ['name' => 'SEO Popis'],
|
||||
'attachments' => ['name' => 'Přílohy'],
|
||||
'weight' => ['name' => 'Hmotnost', 'type' => DataType::TYPE_NUMERIC],
|
||||
'width' => ['name' => 'Šířka', 'type' => DataType::TYPE_NUMERIC],
|
||||
'height' => ['name' => 'Výška', 'type' => DataType::TYPE_NUMERIC],
|
||||
'depth' => ['name' => 'Hloubka', 'type' => DataType::TYPE_NUMERIC],
|
||||
'date_added' => ['name' => 'Datum vytvoření', 'type' => DataType::TYPE_ISO_DATE, 'format' => NumberFormat::FORMAT_DATE_DDMMYYYY],
|
||||
'figure' => ['name' => 'Viditelné - produkt'],
|
||||
'figure_variation' => ['name' => 'Viditelné - varianta'],
|
||||
];
|
||||
|
||||
public function addFields($fields)
|
||||
{
|
||||
$this->fields = $this->fields.$fields;
|
||||
}
|
||||
|
||||
public function getFields()
|
||||
{
|
||||
return $this->column_names;
|
||||
}
|
||||
|
||||
public function getHeader($array = null)
|
||||
{
|
||||
if (!$array) {
|
||||
$array = $this->getFields();
|
||||
}
|
||||
|
||||
$fields = [];
|
||||
|
||||
foreach ($array as $key => $field) {
|
||||
if (array_key_exists('sub', $field)) {
|
||||
foreach ($field['sub'] as $subkey => $subfield) {
|
||||
$fields[$subkey] = $subfield;
|
||||
}
|
||||
} else {
|
||||
$fields[$key] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
protected function checkItemsCount()
|
||||
{
|
||||
$data = $this->prepareQuery()->execute();
|
||||
|
||||
$items_count = $data->rowCount();
|
||||
if ($items_count == 0) {
|
||||
throw new ExportException('Export se nepodařil, protože zadanému filtru neodpovídá žádná položka');
|
||||
}
|
||||
}
|
||||
|
||||
protected function prepareQuery(): QueryBuilder
|
||||
{
|
||||
$qb = $this->getBaseQueryBuilder();
|
||||
|
||||
if (findModule(Modules::PRODUCTS, Modules::SUB_NOTE)) {
|
||||
if (findModule(Modules::PRODUCTS_VARIATIONS)) {
|
||||
$qb->addSelect('COALESCE(pv.note, p.note) as note');
|
||||
} else {
|
||||
$qb->addSelect('p.note');
|
||||
}
|
||||
}
|
||||
|
||||
if (findModule('products', 'price_common')) {
|
||||
$qb->addSelect('p.price_common');
|
||||
}
|
||||
|
||||
if (findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY)) {
|
||||
if (findModule('products_variations')) {
|
||||
$qb->addSelect('COALESCE(pv.price_buy, p.price_buy) as price_buy');
|
||||
} else {
|
||||
$qb->addSelect('p.price_buy');
|
||||
}
|
||||
}
|
||||
|
||||
if (findModule(Modules::PRODUCTS, Modules::SUB_WEIGHT)) {
|
||||
if (findModule(Modules::PRODUCTS_VARIATIONS)) {
|
||||
$qb->addSelect('COALESCE(pv.weight, p.weight) as weight');
|
||||
} else {
|
||||
$qb->addSelect('p.weight as weight');
|
||||
}
|
||||
}
|
||||
|
||||
$qb->joinVariationsOnProducts();
|
||||
$qb->addSelect('COALESCE(pv.id, 0) as id_variation');
|
||||
if (findModule('products_variations')) {
|
||||
if (findModule('products_variations', 'variationCode')) {
|
||||
$qb->addSelect('COALESCE(pv.code, p.code) as code');
|
||||
} else {
|
||||
$qb->addSelect('p.code as code');
|
||||
}
|
||||
|
||||
$qb->addSelect('COALESCE(pv.ean, p.ean) as ean, COALESCE(pv.price, p.price) as price_without_vat,
|
||||
COALESCE(pv.in_store, p.in_store) as in_store');
|
||||
|
||||
if (findModule(\Modules::MISSING_PRODUCTS)) {
|
||||
$qb->addSelect('COALESCE(pv.in_store_min, p.in_store_min) as in_store_min');
|
||||
}
|
||||
|
||||
$qb->addSelect("GROUP_CONCAT(DISTINCT CONCAT(pvc.id_label, ':', pvc.id_value) SEPARATOR ';') as `variation_combination`");
|
||||
$qb->leftJoin('p', 'products_variations_combination', 'pvc', 'pv.id=pvc.id_variation');
|
||||
|
||||
$qb->addGroupBy('pv.id');
|
||||
} else {
|
||||
$qb->addSelect('p.code as code, p.ean as ean, p.price as price_without_vat, p.in_store as in_store');
|
||||
}
|
||||
|
||||
if (findModule('photos')) {
|
||||
$qb->addSelect("(SELECT GROUP_CONCAT(CONCAT(ph.source, ph.image_2) SEPARATOR ';') FROM photos_products_relation as ppr
|
||||
LEFT JOIN photos as ph ON ph.id=ppr.id_photo WHERE ppr.id_product=p.id ORDER BY ppr.position ASC ) as photos");
|
||||
}
|
||||
|
||||
$filterSpecs = null;
|
||||
$productsFilterSpecs = ServiceContainer::getService(ProductsFilterSpecs::class);
|
||||
$filter = getval('filter');
|
||||
if ($filter) {
|
||||
$filterSpecs = $productsFilterSpecs->getSpecs($filter);
|
||||
if ($filterSpecs) {
|
||||
$qb->andWhere($filterSpecs);
|
||||
}
|
||||
}
|
||||
|
||||
if (findModule(Modules::SUPPLIERS)) {
|
||||
if (findModule(Modules::PRODUCTS_VARIATIONS)) {
|
||||
$qb->addSelect('pos.code as supplier_code')
|
||||
->leftJoin('pv', 'products_of_suppliers', 'pos', 'p.id = pos.id_product AND pv.id <=> pos.id_variation');
|
||||
} else {
|
||||
$qb->addSelect('pos.code as supplier_code')
|
||||
->leftJoin('p', 'products_of_suppliers', 'pos', 'p.id=pos.id_product');
|
||||
}
|
||||
}
|
||||
|
||||
if (findModule(\Modules::PRICE_HISTORY)) {
|
||||
$qb->addSelect('p.price_for_discount as price_for_discount');
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
protected function getProducts(): Generator
|
||||
{
|
||||
$qb = $this->prepareQuery();
|
||||
|
||||
$limit = 5000;
|
||||
$from = 0;
|
||||
|
||||
do {
|
||||
$qb->setFirstResult($from);
|
||||
$qb->setMaxResults($limit);
|
||||
$batch = $qb->execute();
|
||||
yield $batch;
|
||||
$from = $from + $limit;
|
||||
} while ($batch->rowCount() == $limit);
|
||||
}
|
||||
|
||||
protected function getBaseQueryBuilder(): Query\QueryBuilder
|
||||
{
|
||||
return sqlQueryBuilder()->select($this->fields)
|
||||
->fromProducts()
|
||||
->leftJoin('p', 'producers', 'pr', 'p.producer = pr.id')
|
||||
->joinVatsOnProducts()
|
||||
->leftJoin('p', 'products_in_sections', 'ps', 'p.id = ps.id_product')
|
||||
->leftJoin('p', 'attachments', 'pa', 'pa.id_product = p.id')
|
||||
->groupBy('p.id');
|
||||
}
|
||||
|
||||
protected function defineHeader()
|
||||
{
|
||||
$parameters = [];
|
||||
$variants = [];
|
||||
$pricelists = [];
|
||||
|
||||
if (findModule(Modules::PRODUCTS, Modules::SUB_NOTE)) {
|
||||
$this->column_names['note']['name'] = 'Poznámka';
|
||||
}
|
||||
|
||||
if (findModule('products', 'price_common')) {
|
||||
$this->column_names['price_common'] = ['name' => 'Škrtlá cena [Kč]', 'type' => DataType::TYPE_NUMERIC];
|
||||
}
|
||||
|
||||
if (findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY)) {
|
||||
$this->column_names['price_buy'] = ['name' => 'Nákupní cena', 'type' => DataType::TYPE_NUMERIC];
|
||||
}
|
||||
if (findModule(Modules::STORES) && $this->isExportOptionEnabled('exportStoresInStore')) {
|
||||
$this->column_names['in_store']['sub']['in_store'] = $this->column_names['in_store'];
|
||||
foreach (ServiceContainer::getService(StoresInStore::class)->getStoresNames() as $key => $name) {
|
||||
$this->column_names['in_store']['sub']['store'.$key.'_in_store'] = ['name' => 'sklad '.$name, 'type' => DataType::TYPE_NUMERIC];
|
||||
}
|
||||
}
|
||||
$SQL = sqlQuery('SELECT pvc.id_label, pvcl.label, pvc.id_value, pvcv.value
|
||||
FROM products_variations_combination AS pvc
|
||||
LEFT JOIN products_variations_choices_labels AS pvcl ON pvc.id_label=pvcl.id
|
||||
LEFT JOIN products_variations_choices_values AS pvcv ON pvc.id_label = pvcv.id_label AND pvc.id_value = pvcv.id
|
||||
GROUP BY pvc.id_value');
|
||||
foreach ($SQL as $row) {
|
||||
$variants['var'.$row['id_label']][$row['id_value']] = $row['value'];
|
||||
$this->column_names['variants']['sub']['var'.$row['id_label']]['name'] = 'Varianta: '.$row['label'];
|
||||
}
|
||||
if (findModule('products_parameters') && $this->isExportOptionEnabled('exportParameters')) {
|
||||
$iterParams = sqlQuery('SELECT pp.id_parameter, pp.value_list, pp.value_char, pp.value_float, p.name, p.value_type
|
||||
FROM parameters_products AS pp
|
||||
LEFT JOIN parameters AS p ON p.id=pp.id_parameter
|
||||
LEFT JOIN parameters_list AS pl ON pl.id=pp.value_list
|
||||
GROUP BY pl.id, p.id
|
||||
ORDER BY p.id');
|
||||
foreach ($iterParams as $row) {
|
||||
$this->column_names['prod_parameters']['sub']['par'.$row['id_parameter']]['name'] = 'Parametr: '.$row['name'];
|
||||
$parameters['par'.$row['id_parameter']] = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!findModule(\Modules::PRICE_HISTORY)) {
|
||||
unset($this->column_names['price_for_discount']);
|
||||
}
|
||||
|
||||
if (!findModule(\Modules::MISSING_PRODUCTS)) {
|
||||
unset($this->column_names['in_store_min']);
|
||||
}
|
||||
|
||||
if (findModule(Modules::PRICELISTS) && ($exportPricelists = $this->getExportOptions()['exportPricelists'] ?? null)) {
|
||||
$exportPricelists = array_filter($exportPricelists);
|
||||
if ($exportPricelists) {
|
||||
$pricelists = sqlQueryBuilder()->select('CONCAT("pl", id), id, name, currency')->from('pricelists')
|
||||
->where(Operator::inIntArray($exportPricelists, 'id'))
|
||||
->execute()->fetchAllAssociativeIndexed();
|
||||
foreach ($pricelists as $key => $row) {
|
||||
$name = 'Ceník: '.$row['name'];
|
||||
$this->column_names['prod_pricelists']['sub'][$key] = ['name' => $name.": cena bez DPH ({$row['currency']})", 'type' => DataType::TYPE_NUMERIC];
|
||||
$this->column_names['prod_pricelists']['sub'][$key.'discount'] = ['name' => $name.': sleva (%)', 'type' => DataType::TYPE_NUMERIC];
|
||||
if (findModule(\Modules::PRICE_HISTORY)) {
|
||||
$this->column_names['prod_pricelists']['sub'][$key.'price_for_discount'] = ['name' => $name.": cena pro slevu ({$row['currency']})", 'type' => DataType::TYPE_NUMERIC];
|
||||
}
|
||||
$this->column_names['prod_pricelists']['sub'][$key.'final'] = ['name' => $name.": finální cena bez DPH ({$row['currency']})", 'type' => DataType::TYPE_NUMERIC];
|
||||
$this->column_names['prod_pricelists']['sub'][$key.'final_with_vat'] = ['name' => $name.": finální cena s DPH ({$row['currency']})", 'type' => DataType::TYPE_NUMERIC];
|
||||
}
|
||||
}
|
||||
}
|
||||
$maxPhotos = sqlQueryBuilder()
|
||||
->select('COUNT(ppr.id_photo) as cnt')
|
||||
->from('photos_products_relation', 'ppr')
|
||||
->groupBy('ppr.id_product')
|
||||
->orderBy('cnt', 'DESC')
|
||||
->setMaxResults(1)
|
||||
->execute()
|
||||
->fetchColumn();
|
||||
for ($i = 1; $i <= $maxPhotos; $i++) {
|
||||
$this->column_names['photos']['sub']['photo'.$i]['name'] = 'Fotografie '.$i;
|
||||
}
|
||||
|
||||
return ['variants' => $variants, 'parameters' => $parameters ?? [], 'pricelists' => $pricelists ?? []];
|
||||
}
|
||||
|
||||
protected function getData(): Generator
|
||||
{
|
||||
$cfg = Config::get();
|
||||
$sectionTree = ServiceContainer::getService(SectionTree::class);
|
||||
$fromHeader = $this->defineHeader();
|
||||
$variants = $fromHeader['variants'];
|
||||
$parameters = $fromHeader['parameters'];
|
||||
|
||||
foreach ($this->getProducts() as $batch) {
|
||||
$sheet = [];
|
||||
$foto = [];
|
||||
$idProducts = [];
|
||||
$idVariations = [];
|
||||
foreach ($batch as $row) {
|
||||
$idProduct = $row['id'];
|
||||
$idVariation = $row['id_variation'];
|
||||
$row['price_with_vat'] = toDecimal($row['price_without_vat'])->addVat(toDecimal($row['vat']))->printFloatValue(2);
|
||||
$row['discount_price_without_vat'] = toDecimal($row['price_without_vat'])->addDiscount($row['discount'])->printFloatValue(4);
|
||||
$row['discount_price_with_vat'] = toDecimal($row['price_with_vat'])->addDiscount($row['discount'])->printFloatValue(2);
|
||||
$row['section'] = $sectionTree->getFullPath($row['id_section']);
|
||||
|
||||
$row['campaign'] = join(', ', array_map(function ($char) use ($cfg) {
|
||||
return getVal($char, $cfg['Products']['Flags'], ['plural' => $char])['plural'];
|
||||
}, explode(',', $row['campaign'])));
|
||||
|
||||
$attachments = $row['attachments'] ? explode(',', $row['attachments']) : [];
|
||||
$attachments = array_map(function ($el) use ($cfg) {
|
||||
return rtrim($cfg['Addr']['full'], '/').trim($el);
|
||||
}, array_filter($attachments, function ($el) { return !empty(trim($el)); }));
|
||||
$row['attachments'] = join(', ', $attachments);
|
||||
|
||||
$fotorow = [];
|
||||
$output_row = [];
|
||||
foreach ($this->column_names as $key => $name) {
|
||||
if ($key == 'variants') {
|
||||
$combination = null;
|
||||
if (!empty($row['variation_combination'])) {
|
||||
$variation_combination = explode(';', $row['variation_combination']);
|
||||
foreach ($variation_combination as $item) {
|
||||
$variation = explode(':', $item);
|
||||
$combination['var'.$variation[0]] = $variation[1]; // id_label => id_value
|
||||
}
|
||||
}
|
||||
foreach ($name['sub'] ?? [] as $id_label => $label) {
|
||||
if ($combination) {
|
||||
if (array_key_exists($id_label, $combination)) {
|
||||
$output_row[$id_label] = $variants[$id_label][$combination[$id_label]];
|
||||
} else {
|
||||
$output_row[$id_label] = '';
|
||||
}
|
||||
} else {
|
||||
$output_row[$id_label] = '';
|
||||
}
|
||||
}
|
||||
} elseif ($key == 'photos') {
|
||||
$photos = explode(';', $row['photos'] ?? '');
|
||||
foreach ($name['sub'] as $pkey => $pvalue) {
|
||||
$photoIndex = str_replace('photo', '', $pkey) - 1;
|
||||
if (!empty($photos[$photoIndex])) {
|
||||
$fotorow[$pkey] = $cfg['Addr']['full'].'data/photos/'.$photos[$photoIndex];
|
||||
} else {
|
||||
$fotorow[$pkey] = '';
|
||||
}
|
||||
}
|
||||
} elseif ($key == 'in_store') {
|
||||
if (findModule(Modules::STORES) && $this->isExportOptionEnabled('exportStoresInStore')) {
|
||||
foreach ($name['sub'] as $subkey => $label) {
|
||||
if (!empty($row[$subkey])) {
|
||||
$output_row[$subkey] = (float) $row[$subkey];
|
||||
} else {
|
||||
$output_row[$subkey] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!empty($row[$key])) {
|
||||
$output_row[$key] = (float) $row[$key];
|
||||
} else {
|
||||
$output_row[$key] = 0;
|
||||
}
|
||||
}
|
||||
} elseif (!empty($row[$key])) {
|
||||
$output_row[$key] = mb_strcut($row[$key], 0, 32767);
|
||||
} elseif ($key == 'prod_parameters') {
|
||||
foreach ($name['sub'] as $subkey => $label) {
|
||||
$output_row[$subkey] = '';
|
||||
}
|
||||
} elseif ($key == 'prod_pricelists') {
|
||||
foreach ($name['sub'] as $subkey => $label) {
|
||||
$output_row[$subkey] = null;
|
||||
}
|
||||
} else {
|
||||
$output_row[$key] = null;
|
||||
}
|
||||
}
|
||||
$idProducts[] = $idProduct;
|
||||
if ($idVariation) {
|
||||
$idVariations[$idProduct][] = $idVariation;
|
||||
} else {
|
||||
$idVariations[$idProduct] = null;
|
||||
}
|
||||
$sheet[$idProduct][$idVariation] = $output_row;
|
||||
$foto[$idProduct][$idVariation] = $fotorow;
|
||||
}
|
||||
if (findModule('products_parameters') && $this->isExportOptionEnabled('exportParameters')) {
|
||||
$parqb = sqlQueryBuilder()->select('pp.id_parameter, pp.id_product, GROUP_CONCAT(COALESCE(pl.value, pp.value_char, pp.value_float) ORDER BY pl.position,pl.id) as parvalue')
|
||||
->from('parameters_products', 'pp')
|
||||
->leftJoin('pp', 'parameters_list', 'pl', 'pl.id=pp.value_list')
|
||||
->where(Operator::inIntArray($idProducts, 'pp.id_product'))
|
||||
->groupBy('pp.id_parameter, pp.id_product')
|
||||
->orderBy('pp.id_product')
|
||||
->execute();
|
||||
|
||||
foreach ($parqb as $par) {
|
||||
foreach ($sheet[$par['id_product']] as &$row) {
|
||||
$row['par'.$par['id_parameter']] = $par['parvalue'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (findModule(Modules::STORES) && $this->isExportOptionEnabled('exportStoresInStore')) {
|
||||
$filter = getVal('filter');
|
||||
$storeIds = null;
|
||||
if (isset($filter['stores'])) {
|
||||
$storeIds = $filter['stores'];
|
||||
}
|
||||
|
||||
$storeQuery = sqlQueryBuilder()
|
||||
->select('p.id id_product, pv.id id_variation')
|
||||
->fromProducts()
|
||||
->joinVariationsOnProducts()
|
||||
->andWhere(Operator::inIntArray($idProducts, 'p.id'))
|
||||
->andWhere(StoresQuery::addStoresInStoreAmounts($storeIds, addMinQuantity: false));
|
||||
|
||||
if (!empty($filter['variations'])) {
|
||||
// ad limit for variations based on filter[variations]
|
||||
$idVariations = sqlQueryBuilder()
|
||||
->select('id_variation')
|
||||
->from('products_variations_combination')
|
||||
->andWhere(Operator::inIntArray($filter['variations'], 'id_value'))
|
||||
->execute()->fetchFirstColumn();
|
||||
|
||||
$storeQuery->andWhere(Operator::inIntArray($idVariations, 'pv.id'));
|
||||
}
|
||||
|
||||
foreach ($storeQuery->execute() as $storesRow) {
|
||||
$id_product = $storesRow['id_product'];
|
||||
$id_variation = $storesRow['id_variation'] ?? 0;
|
||||
|
||||
unset($storesRow['id_product'], $storesRow['id_variation']);
|
||||
|
||||
foreach ($storesRow as $key => $value) {
|
||||
$sheet[$id_product][$id_variation][$key] = intval($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($pricelists = $fromHeader['pricelists']) {
|
||||
$plIDs = implode(',', array_column($pricelists, 'id'));
|
||||
// pouze data (ceny a slevy) vyplnene v ceniku, neni potreba COALESCE(prlv.price, pv.price, prlp.price, p.price) atd. jako na FE
|
||||
$plqb = sqlQueryBuilder()
|
||||
->select('p.id as id_product, pv.id as id_variation, v.vat, prl.id as id_pricelist,
|
||||
COALESCE(prlv.price, prlp.price, pv.price, p.price) as price, COALESCE(prlv.discount, prlp.discount) as discount')
|
||||
->fromProducts()->joinVariationsOnProducts()
|
||||
->leftJoin('p', 'vats', 'v', 'v.id = p.vat')
|
||||
->leftJoin('p', 'pricelists', 'prl', "prl.id IN ({$plIDs})")
|
||||
->leftJoin('p', 'pricelists_products', 'prlp', 'prl.id = prlp.id_pricelist AND prlp.id_product = p.id AND prlp.id_variation IS NULL')
|
||||
->leftJoin('p', 'pricelists_products', 'prlv', 'prl.id = prlv.id_pricelist AND prlv.id_product = p.id AND prlv.id_variation = pv.id')
|
||||
->andWhere(\Query\Product::productsAndVariationsIds($idVariations))
|
||||
->groupBy('p.id, pv.id, prl.id');
|
||||
|
||||
if (findModule(\Modules::PRICE_HISTORY)) {
|
||||
$plqb->addSelect(['COALESCE(prlv.price_for_discount, prlp.price_for_discount, pv.price_for_discount, p.price_for_discount) as price_for_discount']);
|
||||
}
|
||||
|
||||
foreach ($plqb->execute() as $pl_row) {
|
||||
$id_product = $pl_row['id_product'];
|
||||
$id_variation = $pl_row['id_variation'] ?? 0;
|
||||
$col = 'pl'.$pl_row['id_pricelist'];
|
||||
$sheet[$id_product][$id_variation][$col] = $pl_row['price'];
|
||||
$sheet[$id_product][$id_variation][$col.'discount'] = $pl_row['discount'];
|
||||
if (findModule(\Modules::PRICE_HISTORY)) {
|
||||
$sheet[$id_product][$id_variation][$col.'price_for_discount'] = $pl_row['price_for_discount'];
|
||||
}
|
||||
if ($pl_row['price']) {
|
||||
$sheet[$id_product][$id_variation][$col.'final'] = $pl_row['price'];
|
||||
if ($pl_row['discount']) {
|
||||
$sheet[$id_product][$id_variation][$col.'final'] = $pl_row['price'] * (100 - $pl_row['discount']) / 100;
|
||||
}
|
||||
$sheet[$id_product][$id_variation][$col.'final_with_vat'] = toDecimal($sheet[$id_product][$id_variation][$col.'final'] * ((100 + $pl_row['vat']) / 100))->printFloatValue(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($sheet as $idProd => $product) {
|
||||
foreach ($product as $idVar => $variant) {
|
||||
yield array_merge($variant, $foto[$idProd][$idVar] ?? []);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isExportOptionEnabled(string $option): bool
|
||||
{
|
||||
return ($this->getExportOptions()[$option] ?? false) === 'Y';
|
||||
}
|
||||
|
||||
private function getExportOptions(): array
|
||||
{
|
||||
return getVal('options', null, []);
|
||||
}
|
||||
}
|
||||
240
admin/class/class.Frame.php
Normal file
240
admin/class/class.Frame.php
Normal file
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
|
||||
use KupShop\I18nBundle\Util\TranslationUtil;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
|
||||
#[AllowDynamicProperties]
|
||||
class Frame extends Base
|
||||
{
|
||||
protected $ID;
|
||||
protected $errors = [];
|
||||
protected $htmlErrors = [];
|
||||
|
||||
public function get_vars()
|
||||
{
|
||||
$vars = parent::get_vars();
|
||||
|
||||
$ErrStr = getVal('ErrStr');
|
||||
if (!empty($ErrStr)) {
|
||||
$this->errors[] = $ErrStr;
|
||||
}
|
||||
|
||||
$vars['ErrStr'] = join(',', $this->getErrors());
|
||||
|
||||
if ($vars['ErrStr'] && $vars['ErrStr'] != translate('saved', 'status')) {
|
||||
header('admin-error: '.urlencode(mb_strcut($vars['ErrStr'], 0, 1024)));
|
||||
}
|
||||
|
||||
if (!empty($this->getHTMLErrors())) {
|
||||
$error = '';
|
||||
foreach ($this->getHTMLErrors() as $HTMLError) {
|
||||
$error .= '<p>'.$HTMLError.'</p>';
|
||||
}
|
||||
header('admin-html-error: '.urlencode(mb_strcut($error, 0, 1024)));
|
||||
}
|
||||
|
||||
$OkStr = getVal('OkStr');
|
||||
if (!empty($OkStr)) {
|
||||
$vars['OkStr'] = $OkStr;
|
||||
}
|
||||
|
||||
if (!empty($this->getHTMLErrors())) {
|
||||
$vars['htmlErrors'] = $this->getHTMLErrors();
|
||||
}
|
||||
|
||||
$header = getVal('header', $vars, []);
|
||||
|
||||
$header['date'] = date('Ymd');
|
||||
|
||||
if (getVal('hdrType') != null) {
|
||||
$header['hdrType'] = getVal('hdrType');
|
||||
}
|
||||
|
||||
$header['refresh'] = getVal('refresh');
|
||||
|
||||
$vars['header'] = $header;
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function tryRights($acn = '')
|
||||
{
|
||||
// Musim mit budto prava na pozadovanou akci, nebo READ prava
|
||||
if (!UserRights::hasRights($this->getRightsType(), $acn) && !UserRights::hasRights($this->getRightsType(), 'READ')) {
|
||||
throw new AccessDeniedException('');
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRightsType()
|
||||
{
|
||||
$type = getVal('s');
|
||||
if (!$type || $type == 'list.php') {
|
||||
$type = getVal('type');
|
||||
|
||||
if (!$type) {
|
||||
$type = lcfirst($this->getClassName());
|
||||
}
|
||||
} else {
|
||||
$type = substr($type, 0, -4);
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
protected function getAction()
|
||||
{
|
||||
if (empty($this->action)) {
|
||||
$acn = getVal('acn');
|
||||
if (empty($acn)) {
|
||||
$acn = 'add';
|
||||
}
|
||||
$this->action = $acn;
|
||||
}
|
||||
|
||||
return $this->action;
|
||||
}
|
||||
|
||||
protected function getID()
|
||||
{
|
||||
if (empty($this->ID)) {
|
||||
$ID = getVal('ID');
|
||||
/*if(empty($ID))
|
||||
logError(__FILE__, __LINE__, "Empty ID");*/
|
||||
$this->setID($ID);
|
||||
}
|
||||
|
||||
return $this->ID;
|
||||
}
|
||||
|
||||
public function setID($id)
|
||||
{
|
||||
$this->ID = $id;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return substr(getVal('s'), 0, -4);
|
||||
}
|
||||
|
||||
public function returnError($ErrStr, $parentRefresh = '', $ID = null)
|
||||
{
|
||||
if (empty($ID)) {
|
||||
$ID = $this->getID();
|
||||
}
|
||||
if ($parentRefresh) {
|
||||
if ($refresh = getVal('refresh')) {
|
||||
$parentRefresh = "&refresh={$refresh}";
|
||||
} else {
|
||||
$parentRefresh = '&refresh=parent';
|
||||
}
|
||||
}
|
||||
if (getVal('autoclose')) {
|
||||
$parentRefresh .= '&refresh=close';
|
||||
}
|
||||
$type = getVal('type');
|
||||
if ($type) {
|
||||
$parentRefresh .= '&type='.$type;
|
||||
}
|
||||
redirect("launch.php?s={$this->getName()}.php&acn=edit{$parentRefresh}&flap=".getVal('flap')."&ID={$ID}&ErrStr=".urlencode($ErrStr));
|
||||
}
|
||||
|
||||
public function addError($ErrStr = null)
|
||||
{
|
||||
$this->errors[] = $ErrStr;
|
||||
}
|
||||
|
||||
public function addHTMLError($error)
|
||||
{
|
||||
$this->htmlErrors[] = $error;
|
||||
}
|
||||
|
||||
public function getHTMLErrors()
|
||||
{
|
||||
return array_unique($this->htmlErrors);
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return array_unique($this->errors);
|
||||
}
|
||||
|
||||
public function returnOK($ErrStr = null, $parentRefresh = false, $params = [])
|
||||
{
|
||||
if (empty($ErrStr)) {
|
||||
$this->returnError($GLOBALS['txt_str']['status']['saved'], true);
|
||||
}
|
||||
|
||||
if ($parentRefresh) {
|
||||
$params['refresh'] = 'parent';
|
||||
}
|
||||
|
||||
if (getVal('type')) {
|
||||
$params['type'] = getVal('type');
|
||||
}
|
||||
|
||||
if (getVal('flap')) {
|
||||
$params['flap'] = getVal('flap');
|
||||
}
|
||||
|
||||
$params['OkStr'] = $ErrStr;
|
||||
|
||||
if (empty($params['acn'])) {
|
||||
$params['acn'] = 'edit';
|
||||
}
|
||||
|
||||
return $this->redirect($params);
|
||||
}
|
||||
|
||||
public function redirect($params = [])
|
||||
{
|
||||
$params = array_merge($_GET, $params);
|
||||
|
||||
return redirect('launch.php?'.http_build_query($params));
|
||||
}
|
||||
|
||||
public function unserializeCustomData(&$data)
|
||||
{
|
||||
if (!isset($data['data'])) {
|
||||
$data['data'] = [];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_string($data['data'])) {
|
||||
$data['data'] = json_decode($data['data'], true);
|
||||
}
|
||||
|
||||
if (!is_array($data['data']) && !is_object($data['data'])) {
|
||||
$data['data'] = [];
|
||||
}
|
||||
}
|
||||
|
||||
public function serializeCustomData(&$data)
|
||||
{
|
||||
if (empty($data['data'])) {
|
||||
$data['data'] = null;
|
||||
} else {
|
||||
$data['data'] = json_encode($data['data']);
|
||||
}
|
||||
}
|
||||
|
||||
protected function isDuplicate()
|
||||
{
|
||||
return getVal('Duplicate');
|
||||
}
|
||||
|
||||
protected function getTranslationUtil(): ?TranslationUtil
|
||||
{
|
||||
if (!findModule(\Modules::TRANSLATIONS)) {
|
||||
return null;
|
||||
}
|
||||
static $translationUtil;
|
||||
|
||||
if (!$translationUtil) {
|
||||
$translationUtil = ServiceContainer::getService(TranslationUtil::class);
|
||||
}
|
||||
|
||||
return $translationUtil;
|
||||
}
|
||||
}
|
||||
28
admin/class/class.Menu.php
Normal file
28
admin/class/class.Menu.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
class Menu extends Frame
|
||||
{
|
||||
public function getTemplate()
|
||||
{
|
||||
if (!($template = $this->template)) {
|
||||
$template = './menu/'.getVal('type').'.tpl';
|
||||
}
|
||||
|
||||
if ($this->smarty->templateExists($template)) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
return './menu.tpl';
|
||||
}
|
||||
|
||||
public function get_vars()
|
||||
{
|
||||
$vars = parent::get_vars();
|
||||
|
||||
return array_merge($vars, [
|
||||
'dateToday' => date('Y-m-d'),
|
||||
'dateFrom' => date('Y-m-d', time() - (14 * 86400)),
|
||||
'type' => getVal('type'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
0
admin/class/class.OrdersMassProcess.php
Normal file
0
admin/class/class.OrdersMassProcess.php
Normal file
390
admin/class/class.StockInImport.php
Normal file
390
admin/class/class.StockInImport.php
Normal file
@@ -0,0 +1,390 @@
|
||||
<?php
|
||||
|
||||
use KupShop\AdminBundle\Util\StockInProductOfSupplierService;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\KupShopBundle\Util\Functional\Mapping;
|
||||
use Query\Operator;
|
||||
|
||||
class StockInImport
|
||||
{
|
||||
use DatabaseCommunication;
|
||||
|
||||
public $type;
|
||||
|
||||
public $errors = [];
|
||||
public $default_settings = [
|
||||
'type' => 'xlsx',
|
||||
'fields' => [0 => 'code', 1 => 'name', 2 => 'quantity', 3 => 'ean', 4 => 'price', 5 => 'supplier_code'],
|
||||
'search_in_products' => true,
|
||||
'isdoc_search_in_ean' => true,
|
||||
'encoding' => 'UTF-8',
|
||||
'skip' => '1',
|
||||
'piece_price' => true,
|
||||
'default' => true,
|
||||
];
|
||||
public $supplier_settings;
|
||||
protected $separator = ';';
|
||||
protected $skip = 0;
|
||||
protected $encoding;
|
||||
protected $fields = [];
|
||||
protected $stock_in;
|
||||
protected $check_file_name = false;
|
||||
protected $only_visible = false;
|
||||
protected $search_in_products = false;
|
||||
protected $multiple = 1;
|
||||
protected $cut_code;
|
||||
protected $ignore_code = false;
|
||||
|
||||
protected $stockInIndex;
|
||||
protected StockInProductOfSupplierService $stockInProductOfSupplierService;
|
||||
|
||||
public function __construct($stock_in, $stockInIndex = 'invoice')
|
||||
{
|
||||
$this->stock_in = $stock_in;
|
||||
$this->supplier_settings = sqlQueryBuilder()->select('s.import_settings')
|
||||
->from('suppliers', 's')
|
||||
->where(Operator::equals(['id' => $stock_in['id_supplier']]))
|
||||
->execute()
|
||||
->fetchColumn();
|
||||
$this->stockInIndex = $stockInIndex;
|
||||
|
||||
/* @var StockInProductOfSupplierService $supplierService */
|
||||
$this->stockInProductOfSupplierService = ServiceContainer::getService(StockInProductOfSupplierService::class);
|
||||
}
|
||||
|
||||
public function load_supplier_settings()
|
||||
{
|
||||
$settings = $this->supplier_settings != null ? json_decode($this->supplier_settings, true) : $this->default_settings;
|
||||
if ($this->supplier_settings && json_last_error()) {
|
||||
throw new Exception('Nelze nacist nastaveni importu: '.json_last_error_msg());
|
||||
}
|
||||
foreach ((array) $settings as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function import($file)
|
||||
{
|
||||
if ($this->check_file_name) {
|
||||
$name = pathinfo($file['name'], PATHINFO_FILENAME);
|
||||
|
||||
if ($name != $this->stock_in['code']) {
|
||||
return $this->add_error("Nesedí jméno souboru s číslem faktury: {$name} != {$this->stock_in['code']}");
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($file['tmp_name'])) {
|
||||
return $this->add_error('Nebyl nahrán žádný soubor!');
|
||||
}
|
||||
|
||||
$method = "import_{$this->type}";
|
||||
|
||||
sqlStartTransaction();
|
||||
|
||||
$ret = $this->$method($file['tmp_name']);
|
||||
|
||||
sqlFinishTransaction();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function import_isdoc($file)
|
||||
{
|
||||
$xml = simplexml_load_file($file);
|
||||
|
||||
$factorage = [
|
||||
'date_issued' => (string) $xml->IssueDate,
|
||||
'note' => (string) $xml->note,
|
||||
'date_expiration' => (string) $xml->PaymentMeans->Payment->Details->PaymentDueDate,
|
||||
'total_price' => (string) $xml->LegalMonetaryTotal->TaxExclusiveAmount,
|
||||
];
|
||||
if (!$this->ignore_code) {
|
||||
$factorage['code'] = (string) $xml->ID;
|
||||
}
|
||||
|
||||
$this->updateSQL(
|
||||
'stock_in',
|
||||
$factorage,
|
||||
[
|
||||
'id' => $this->stock_in['id'],
|
||||
]
|
||||
);
|
||||
|
||||
foreach ($xml->InvoiceLines->InvoiceLine as $invoiceLine) {
|
||||
$item = [
|
||||
'code' => (string) $invoiceLine->Item->SellersItemIdentification->ID,
|
||||
'name' => (string) $invoiceLine->Item->Description,
|
||||
'quantity' => (string) $invoiceLine->InvoicedQuantity,
|
||||
'price' => (string) $invoiceLine->LineExtensionAmount,
|
||||
'vat' => (string) $invoiceLine->ClassifiedTaxCategory->Percent,
|
||||
];
|
||||
|
||||
if ($this->isdoc_search_in_ean ?? false) {
|
||||
$ean = array_filter([
|
||||
(int) $invoiceLine->Item->CatalogueItemIdentification->ID ?? '', // tady by mel byt EAN dle dokumentace
|
||||
(int) $invoiceLine->Item->SellersItemIdentification->ID ?? '', // nekdo ma EAN tady
|
||||
]);
|
||||
if ($ean) {
|
||||
$ean = (count($ean) == 1 ? reset($ean) : $ean);
|
||||
$item['ean'] = $ean;
|
||||
}
|
||||
}
|
||||
|
||||
if ($item['quantity'] < 0) {
|
||||
$item['price'] = (string) $invoiceLine->UnitPrice;
|
||||
}
|
||||
|
||||
$this->add_item($item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function import_isdocx($file)
|
||||
{
|
||||
$za = new ZipArchive();
|
||||
$res = $za->open($file);
|
||||
if ($res !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// finds the first .isdoc file and returns it or false
|
||||
$findIsdoc = function ($zipArchive) {
|
||||
// loop through all files in zip
|
||||
for ($i = 0; $i < $zipArchive->numFiles; $i++) {
|
||||
$stat = $zipArchive->statIndex($i);
|
||||
|
||||
// if extension is .isdoc return the filename
|
||||
if (preg_match('/(.*\.isdoc)/', $stat['name']) === 1) {
|
||||
return $stat['name'];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
$fileName = 'zip://'.$file.'#'.$findIsdoc($za);
|
||||
$za->close();
|
||||
|
||||
return $this->import_isdoc($fileName);
|
||||
}
|
||||
|
||||
public function fopen_convert($fileName)
|
||||
{
|
||||
$fc = iconv($this->encoding, 'utf-8', file_get_contents($fileName));
|
||||
$handle = fopen('php://memory', 'rw');
|
||||
fwrite($handle, $fc);
|
||||
fseek($handle, 0);
|
||||
|
||||
return $handle;
|
||||
}
|
||||
|
||||
public function import_xlsx($file)
|
||||
{
|
||||
$xlsx = new AutomaticImportTransform($file);
|
||||
$data = $xlsx->GetXml();
|
||||
|
||||
$i = 0;
|
||||
foreach ($data->item as $row) {
|
||||
if ($i < $this->skip) {
|
||||
$i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$arr = json_decode(json_encode($row), true)['col'];
|
||||
$arr = array_pad($arr, count($this->fields), null);
|
||||
$item = array_combine($this->fields, array_slice($arr, 0, count($this->fields)));
|
||||
|
||||
// kontrola prázdného řádku
|
||||
if (!empty($item) && !is_array($item['quantity'])) {
|
||||
$this->add_item($item);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function import_csv($file)
|
||||
{
|
||||
if ($this->encoding) {
|
||||
$file = $this->fopen_convert($file);
|
||||
} else {
|
||||
$file = fopen($file, 'r');
|
||||
}
|
||||
|
||||
if (!$file) {
|
||||
exit('Nelze načíst soubor');
|
||||
}
|
||||
|
||||
$count = count($this->fields);
|
||||
|
||||
while ($this->skip-- > 0) {
|
||||
fgetcsv($file, null, $this->separator);
|
||||
}
|
||||
|
||||
while ($row = fgetcsv($file, null, $this->separator)) {
|
||||
$row = array_combine($this->fields, array_slice($row, 0, $count));
|
||||
$this->add_item($row);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function add_item($item)
|
||||
{
|
||||
/*
|
||||
* Funkce na uříznutí X počtu znaků z kodu. Stačí zadat v importu/exportu "cut" = 'začátek';'konec'
|
||||
* */
|
||||
if ($this->cut_code) {
|
||||
$cut = explode(';', $this->cut_code);
|
||||
$item['code'] = substr($item['code'], $cut[0], $cut[1] ?? (strlen($item['code']) - $cut[0]));
|
||||
}
|
||||
|
||||
$mapping = [];
|
||||
if (!empty($item['code'])) {
|
||||
$mapping = ['code' => $item['code']];
|
||||
}
|
||||
if (!empty($item['ean'])) {
|
||||
$mapping['ean'] = $item['ean'];
|
||||
}
|
||||
|
||||
if (!empty($mapping)) {
|
||||
$qb = sqlQueryBuilder()->select('pos.id_product', 'pos.id_variation', 'pos.import_multiplier', 'p.vat as id_vat')
|
||||
->from('products_of_suppliers', 'pos')
|
||||
->leftJoin('pos', 'products', 'p', 'pos.id_product=p.id')
|
||||
->where(Operator::equals(['pos.id_supplier' => $this->stock_in['id_supplier']]));
|
||||
if ($this->only_visible) {
|
||||
$qb->andWhere(Operator::equals(['p.figure' => 'Y']));
|
||||
}
|
||||
|
||||
$operators = array_map(function ($key, $value) {
|
||||
if (is_array($value)) {
|
||||
return Operator::inIntArray($value, "pos.{$key}");
|
||||
}
|
||||
|
||||
return Operator::equals(["pos.{$key}" => $value]);
|
||||
}, array_keys($mapping), $mapping);
|
||||
$qb->andWhere(Operator::orX($operators));
|
||||
|
||||
$product = $qb->execute()->fetch();
|
||||
|
||||
if (!$product && $this->search_in_products) {
|
||||
$qb = sqlQueryBuilder()->select('p.id AS id_product, pv.id AS id_variation')
|
||||
->fromProducts()
|
||||
->joinVariationsOnProducts();
|
||||
|
||||
$productsMapping = array_merge(
|
||||
Mapping::mapKeys($mapping, function ($key, $value) {return ["p.{$key}", $value]; }),
|
||||
Mapping::mapKeys($mapping, function ($key, $value) {return ["pv.{$key}", $value]; })
|
||||
);
|
||||
if (isset($productsMapping['pv.code']) && !findModule(Modules::PRODUCTS_VARIATIONS, Modules::SUB_CODE)) {
|
||||
unset($productsMapping['pv.code']);
|
||||
}
|
||||
|
||||
$operators = array_map(function ($key, $value) {
|
||||
if (is_array($value)) {
|
||||
return Operator::inStringArray($value, $key);
|
||||
}
|
||||
|
||||
return Operator::equals([$key => $value]);
|
||||
}, array_keys($productsMapping), $productsMapping);
|
||||
$qb->andWhere(Operator::orX($operators));
|
||||
|
||||
if ($this->only_visible) {
|
||||
$qb->andWhere(Operator::equals(['p.figure' => 'Y']));
|
||||
}
|
||||
$product = $qb->execute()->fetch();
|
||||
|
||||
if ($product) {
|
||||
$product['import_multiplier'] = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$product = null;
|
||||
$mapping['code'] = translate('unknown');
|
||||
$mapping['ean'] = translate('unknown');
|
||||
}
|
||||
|
||||
if (!$product || $product['import_multiplier'] == 0) {
|
||||
$product = ['id_product' => null, 'id_variation' => null, 'name' => "{$item['name']} (kód: {$mapping['code']}, ean: {$mapping['ean']})", 'import_multiplier' => 1, 'id_vat' => 0];
|
||||
} else {
|
||||
$product['name'] = null;
|
||||
}
|
||||
|
||||
$product['id_stock_in'] = $this->stock_in['id'];
|
||||
|
||||
$product['quantity'] = round((float) $item['quantity'] * (float) $product['import_multiplier'] * (float) $this->multiple);
|
||||
|
||||
$product['vat'] = empty($item['vat']) ? getVat($product['id_vat']) : $item['vat'];
|
||||
|
||||
if (empty($item['price']) && !empty($item['price_with_vat'])) {
|
||||
$price = toDecimal($this->preparePrice($item['price_with_vat']))->removeVat($product['vat']);
|
||||
} else {
|
||||
$price = toDecimal($this->preparePrice($item['price']));
|
||||
}
|
||||
|
||||
// if isset price multiplier
|
||||
if (isset($this->stock_in['multiplier'])) {
|
||||
$price = $price->mul(toDecimal($this->stock_in['multiplier']));
|
||||
}
|
||||
|
||||
unset($product['id_vat']);
|
||||
|
||||
if (isset($this->piece_price)) {
|
||||
$product['price'] = $price;
|
||||
} else {
|
||||
$product['price'] = $product['quantity'] > 0 ? $price->div(toDecimal($product['quantity'])) : $price;
|
||||
}
|
||||
|
||||
if ($this->insertSQL('stock_in_items', $product, ['import_multiplier']) <= 0) {
|
||||
return $this->add_error('Cannot add '.print_r($product, true));
|
||||
}
|
||||
|
||||
if ($product['id_product'] > 0 && !in_array($this->stockInIndex, ['future', 'preorder'])) {
|
||||
$prod = new Product($product['id_product']);
|
||||
$prod->storeIn($product['id_variation'], $product['quantity']);
|
||||
}
|
||||
|
||||
$product['supplier_code'] = !empty($item['supplier_code']) ? trim($item['supplier_code']) : null;
|
||||
$stockInData = getVal('data');
|
||||
|
||||
try {
|
||||
$this->stockInProductOfSupplierService->updateOrInsertProductSupplier($product, $stockInData);
|
||||
} catch (Exception|\Doctrine\DBAL\Driver\Exception) {
|
||||
$this->add_error("Nepodařilo se uložit kód dodavatele '{$item['code']}' položky: {$item['name']}");
|
||||
}
|
||||
}
|
||||
|
||||
private function add_error($string)
|
||||
{
|
||||
$this->errors[] = $string;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('json_last_error_msg')) {
|
||||
function json_last_error_msg()
|
||||
{
|
||||
switch (json_last_error()) {
|
||||
case JSON_ERROR_NONE:
|
||||
return 'No errors';
|
||||
case JSON_ERROR_DEPTH:
|
||||
return 'Maximum stack depth exceeded';
|
||||
case JSON_ERROR_STATE_MISMATCH:
|
||||
return 'Underflow or the modes mismatch';
|
||||
case JSON_ERROR_CTRL_CHAR:
|
||||
return 'Unexpected control character found';
|
||||
case JSON_ERROR_SYNTAX:
|
||||
return 'Syntax error, malformed JSON';
|
||||
case JSON_ERROR_UTF8:
|
||||
return 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
||||
default:
|
||||
return 'Unknown error';
|
||||
}
|
||||
}
|
||||
}
|
||||
742
admin/class/class.UserRights.php
Normal file
742
admin/class/class.UserRights.php
Normal file
@@ -0,0 +1,742 @@
|
||||
<?php
|
||||
|
||||
use KupShop\AdminBundle\AdminRegister\AdminRegisterLocator;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
|
||||
class UserRights
|
||||
{
|
||||
private static $adminRegisterLocator;
|
||||
|
||||
public static function getAdminRegisterLocator(): AdminRegisterLocator
|
||||
{
|
||||
if (!isset(self::$adminRegisterLocator)) {
|
||||
self::$adminRegisterLocator = ServiceContainer::getService(AdminRegisterLocator::class);
|
||||
}
|
||||
|
||||
return self::$adminRegisterLocator;
|
||||
}
|
||||
|
||||
public static function hasRights($type, $specific = '')
|
||||
{
|
||||
$item = self::getAdminRegisterLocator()->getPermissions($type) ?? getVal($type, self::$rights);
|
||||
|
||||
if (!$item) {
|
||||
// logError(__FILE__, __LINE__, "Nonexisting user right: $type");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!empty($item['superadmin']) && !isSuperuser()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($item['modules']) || !empty($item['submodules'])) {
|
||||
$allow = false;
|
||||
foreach ($item['modules'] ?? [] as $module) {
|
||||
if (findModule($module)) {
|
||||
$allow |= true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($item['submodules'] ?? [] as $module => $submodule) {
|
||||
if (findModule($module, $submodule)) {
|
||||
$allow |= true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$allow) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($item['rights'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($item['rights'] as $right) {
|
||||
if (substr($right, -1) == '_') {
|
||||
if (findRight($right.$specific)) {
|
||||
return true;
|
||||
}
|
||||
} elseif (findRight($right)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isOnlySuperadmin($type)
|
||||
{
|
||||
$item = self::getAdminRegisterLocator()->getPermissions($type) ?? getVal($type, self::$rights);
|
||||
if (!$item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($item['superadmin']) && $item['superadmin'] === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function addRights($list, $rights = [])
|
||||
{
|
||||
self::$rights[$list] = $rights;
|
||||
}
|
||||
|
||||
protected static $rights = [
|
||||
'productsRelatedTypes' => [
|
||||
'submodules' => [
|
||||
Modules::PRODUCTS_RELATED => Modules::SUB_TYPES,
|
||||
],
|
||||
'superadmin' => true,
|
||||
],
|
||||
'products' => [
|
||||
'modules' => [
|
||||
'products',
|
||||
],
|
||||
'rights' => [
|
||||
'PROD_',
|
||||
],
|
||||
],
|
||||
'productsMassModification' => [
|
||||
'modules' => [
|
||||
'products',
|
||||
],
|
||||
'rights' => [
|
||||
'PROD_EDIT',
|
||||
'PROD_ERASE',
|
||||
],
|
||||
],
|
||||
'parameters' => [
|
||||
'modules' => [
|
||||
'products_parameters',
|
||||
],
|
||||
'rights' => [
|
||||
'PARAM',
|
||||
],
|
||||
],
|
||||
'productsVarLabels' => [
|
||||
'modules' => [
|
||||
'products_variations',
|
||||
],
|
||||
'rights' => [
|
||||
'VARIANT_LABELS',
|
||||
],
|
||||
],
|
||||
'sections' => [
|
||||
'modules' => [
|
||||
'products_sections',
|
||||
],
|
||||
'rights' => [
|
||||
'SEC_',
|
||||
],
|
||||
],
|
||||
'producers' => [
|
||||
'modules' => [
|
||||
'producers',
|
||||
],
|
||||
'rights' => [
|
||||
'PRODCR',
|
||||
],
|
||||
],
|
||||
'orders' => [
|
||||
'modules' => [
|
||||
'orders',
|
||||
],
|
||||
'rights' => [
|
||||
'ORDER_',
|
||||
],
|
||||
],
|
||||
'ProductsSerialNumbers' => [
|
||||
'modules' => [
|
||||
'products_serial_numbers',
|
||||
'stock_in',
|
||||
],
|
||||
'rights' => [
|
||||
'PSERNUM',
|
||||
],
|
||||
],
|
||||
'ProductsBatches' => [
|
||||
'modules' => [
|
||||
Modules::PRODUCTS_BATCHES,
|
||||
Modules::WAREHOUSE,
|
||||
],
|
||||
'rights' => [
|
||||
'PBATCHES',
|
||||
],
|
||||
],
|
||||
'users' => [
|
||||
'modules' => [
|
||||
'eshop_users',
|
||||
],
|
||||
'rights' => [
|
||||
'USR_',
|
||||
],
|
||||
],
|
||||
|
||||
'discounts' => [
|
||||
'modules' => [
|
||||
'order_discount',
|
||||
],
|
||||
'rights' => [
|
||||
'DISCNT',
|
||||
],
|
||||
],
|
||||
'ordersMassProcess' => [
|
||||
'modules' => [
|
||||
'orders_mass_process',
|
||||
],
|
||||
'rights' => [
|
||||
'ORDER',
|
||||
],
|
||||
],
|
||||
'photos' => [
|
||||
'modules' => [
|
||||
'photos',
|
||||
],
|
||||
'rights' => [
|
||||
'PHOTOS_',
|
||||
],
|
||||
],
|
||||
'fileBrowser' => [
|
||||
'rights' => [
|
||||
'FILE_BROWSER_USE',
|
||||
],
|
||||
],
|
||||
'stockIn' => [
|
||||
'modules' => [
|
||||
'stock_in',
|
||||
],
|
||||
'rights' => [
|
||||
'INSTORE_STOCKIN',
|
||||
],
|
||||
],
|
||||
'suppliers' => [
|
||||
'modules' => [
|
||||
'products_suppliers',
|
||||
'automatic_import',
|
||||
'suppliers',
|
||||
],
|
||||
'rights' => [
|
||||
'INSTORE_STOCKIN',
|
||||
],
|
||||
],
|
||||
'stockInMissing' => [
|
||||
'modules' => [
|
||||
'missing_products',
|
||||
],
|
||||
'rights' => [
|
||||
'INSTORE_MISSING',
|
||||
],
|
||||
],
|
||||
'InfoPanelList' => [
|
||||
'modules' => [
|
||||
],
|
||||
'rights' => [
|
||||
'INFOPANEL',
|
||||
],
|
||||
],
|
||||
'shopStore' => [
|
||||
'modules' => [
|
||||
],
|
||||
'rights' => [
|
||||
'MODULOVNA',
|
||||
],
|
||||
],
|
||||
'ReturnDelivery' => [
|
||||
'modules' => [
|
||||
],
|
||||
'rights' => [
|
||||
'RETURNS',
|
||||
],
|
||||
],
|
||||
'LabelsList' => [
|
||||
'modules' => [
|
||||
Modules::LABELS,
|
||||
],
|
||||
'rights' => [
|
||||
'LABELS',
|
||||
],
|
||||
],
|
||||
|
||||
'templatesMenu' => [
|
||||
'modules' => [
|
||||
'templates',
|
||||
],
|
||||
'rights' => [
|
||||
'PRODUCT_TEMPLATES',
|
||||
],
|
||||
],
|
||||
'BonusProgramExchange' => [
|
||||
'submodules' => [
|
||||
Modules::BONUS_PROGRAM => Modules::SUB_POINTS_EXCHANGE,
|
||||
],
|
||||
'rights' => [
|
||||
'BONUS_PROGRAM_EXCHANGE',
|
||||
],
|
||||
],
|
||||
|
||||
'Sales' => [
|
||||
'modules' => [
|
||||
Modules::SALES,
|
||||
],
|
||||
'rights' => [
|
||||
'SALES',
|
||||
],
|
||||
],
|
||||
|
||||
'productsOfSuppliers' => [
|
||||
'modules' => [
|
||||
'stock_in',
|
||||
'products_suppliers',
|
||||
'suppliers',
|
||||
],
|
||||
'rights' => [
|
||||
'INSTORE_STOCKIN',
|
||||
],
|
||||
],
|
||||
'inventory' => [
|
||||
'modules' => [
|
||||
'inventory',
|
||||
],
|
||||
'rights' => [
|
||||
'INVENTORY',
|
||||
],
|
||||
],
|
||||
'productsPrices' => [
|
||||
'submodules' => [
|
||||
Modules::PRODUCTS => Modules::SUB_PRICE_BUY,
|
||||
],
|
||||
'rights' => [
|
||||
'INVENTORY',
|
||||
],
|
||||
],
|
||||
'stockManual' => [
|
||||
'modules' => [
|
||||
'stock_in',
|
||||
],
|
||||
'rights' => [
|
||||
'INSTORE_STOCKIN',
|
||||
],
|
||||
],
|
||||
'pages' => [
|
||||
'modules' => [
|
||||
'menulinks',
|
||||
],
|
||||
'rights' => [
|
||||
'MENU_LINKS',
|
||||
],
|
||||
],
|
||||
'menu' => [
|
||||
'modules' => [
|
||||
'menulinks',
|
||||
],
|
||||
'rights' => [
|
||||
'MENU_LINKS',
|
||||
],
|
||||
],
|
||||
'sliders' => [
|
||||
'modules' => [
|
||||
'sliders',
|
||||
],
|
||||
'rights' => [
|
||||
'SLIDERS',
|
||||
],
|
||||
],
|
||||
'articles' => [
|
||||
'modules' => [
|
||||
'articles',
|
||||
],
|
||||
'rights' => [
|
||||
'ART_',
|
||||
],
|
||||
],
|
||||
'artsections' => [
|
||||
'modules' => [
|
||||
'articles_sections',
|
||||
],
|
||||
'rights' => [
|
||||
'ART_SEC_',
|
||||
],
|
||||
],
|
||||
'articlesTags' => [
|
||||
'modules' => [
|
||||
'articles',
|
||||
],
|
||||
'rights' => [
|
||||
'ART_',
|
||||
],
|
||||
],
|
||||
'artauthors' => [
|
||||
'modules' => [
|
||||
Modules::ARTICLES_AUTHORS,
|
||||
],
|
||||
'rights' => [
|
||||
'ART_AUTH_',
|
||||
],
|
||||
],
|
||||
'dbbackup' => [
|
||||
'modules' => [
|
||||
'dbbackup',
|
||||
],
|
||||
'rights' => [
|
||||
'OTH_BACKUP_',
|
||||
],
|
||||
],
|
||||
'stats' => [
|
||||
'modules' => [
|
||||
'stats',
|
||||
],
|
||||
'rights' => [
|
||||
'STAT',
|
||||
],
|
||||
],
|
||||
'import-generic' => [
|
||||
'modules' => [
|
||||
'products',
|
||||
],
|
||||
'rights' => [
|
||||
'IMPRT',
|
||||
],
|
||||
],
|
||||
'import_automatic' => [
|
||||
'modules' => [
|
||||
'automatic_import',
|
||||
],
|
||||
'rights' => [
|
||||
'IMPRT',
|
||||
],
|
||||
],
|
||||
'import-xml_feed' => [
|
||||
'modules' => [
|
||||
'products',
|
||||
],
|
||||
'rights' => [
|
||||
'IMPRT',
|
||||
],
|
||||
'superadmin' => true,
|
||||
],
|
||||
'import-xml_feed_new' => [
|
||||
'modules' => [
|
||||
'products',
|
||||
],
|
||||
'rights' => [
|
||||
'IMPRT',
|
||||
],
|
||||
// 'superadmin' => true,
|
||||
],
|
||||
'orderPayment' => [
|
||||
'modules' => [
|
||||
'order_payment',
|
||||
],
|
||||
'rights' => [
|
||||
'ORDER_PAYMENT',
|
||||
'POS_',
|
||||
],
|
||||
],
|
||||
'admins' => [
|
||||
'modules' => [
|
||||
],
|
||||
'rights' => [
|
||||
'OTH_ADM_',
|
||||
],
|
||||
],
|
||||
'settings' => [
|
||||
'modules' => [
|
||||
],
|
||||
'rights' => [
|
||||
'OTH_SET_',
|
||||
],
|
||||
],
|
||||
'delivery_type' => [
|
||||
'modules' => [
|
||||
'eshop_delivery',
|
||||
],
|
||||
'rights' => [
|
||||
'DELVR',
|
||||
],
|
||||
],
|
||||
'deliveryDelivery' => [
|
||||
'modules' => [
|
||||
'eshop_delivery',
|
||||
],
|
||||
'rights' => [
|
||||
'DELVR',
|
||||
],
|
||||
],
|
||||
'deliveryPayment' => [
|
||||
'modules' => [
|
||||
'eshop_delivery',
|
||||
],
|
||||
'rights' => [
|
||||
'DELVR',
|
||||
],
|
||||
],
|
||||
'vats' => [
|
||||
'modules' => [
|
||||
'products',
|
||||
],
|
||||
'rights' => [
|
||||
'VAT',
|
||||
],
|
||||
],
|
||||
'priceLevels' => [
|
||||
'modules' => [
|
||||
'price_levels',
|
||||
],
|
||||
'rights' => [
|
||||
'PRICELEVELS',
|
||||
],
|
||||
],
|
||||
'currencies' => [
|
||||
'modules' => [
|
||||
'currencies',
|
||||
],
|
||||
'rights' => [
|
||||
'CURRENCY',
|
||||
],
|
||||
],
|
||||
'automatic_import' => [
|
||||
'modules' => [
|
||||
'automatic_import',
|
||||
],
|
||||
'rights' => [
|
||||
'IMPRT',
|
||||
],
|
||||
],
|
||||
'export_orders' => [
|
||||
'modules' => [
|
||||
'orders',
|
||||
],
|
||||
'rights' => [
|
||||
'EXPRT',
|
||||
],
|
||||
],
|
||||
'export_products' => [
|
||||
'modules' => [
|
||||
'export',
|
||||
],
|
||||
'rights' => [
|
||||
'EXPRT',
|
||||
],
|
||||
],
|
||||
'export_selling_products' => [
|
||||
'modules' => [
|
||||
'orders',
|
||||
],
|
||||
'rights' => [
|
||||
'EXPRT',
|
||||
],
|
||||
],
|
||||
'export_users' => [
|
||||
'modules' => [
|
||||
'eshop_users',
|
||||
],
|
||||
'rights' => [
|
||||
'EXPRT',
|
||||
],
|
||||
],
|
||||
'ordersOfSuppliers' => [
|
||||
'modules' => [
|
||||
'orders_of_suppliers',
|
||||
],
|
||||
'rights' => [
|
||||
'INSTORE_STOCKIN',
|
||||
],
|
||||
// 'superadmin' => true,
|
||||
],
|
||||
'replacement' => [
|
||||
'modules' => [
|
||||
'replacement',
|
||||
],
|
||||
'rights' => [
|
||||
'ORDER_',
|
||||
],
|
||||
],
|
||||
'templates' => [
|
||||
'modules' => [
|
||||
'templates',
|
||||
],
|
||||
'rights' => [
|
||||
'PROD_',
|
||||
],
|
||||
],
|
||||
'templatesCategories' => [
|
||||
'modules' => [
|
||||
'templates',
|
||||
],
|
||||
'rights' => [
|
||||
'PROD_',
|
||||
],
|
||||
],
|
||||
'templatesProducts' => [
|
||||
'modules' => [
|
||||
'templates',
|
||||
],
|
||||
'rights' => [
|
||||
'PROD_',
|
||||
],
|
||||
],
|
||||
'pos' => [
|
||||
'rights' => [
|
||||
'POS_',
|
||||
],
|
||||
'modules' => [
|
||||
'new_pos',
|
||||
],
|
||||
],
|
||||
'old_pos' => [
|
||||
'rights' => [
|
||||
'POS_',
|
||||
],
|
||||
'modules' => [
|
||||
'pos',
|
||||
],
|
||||
],
|
||||
'usersGroups' => [
|
||||
'modules' => [
|
||||
'eshop_users',
|
||||
],
|
||||
'rights' => [
|
||||
'USER_GROUPS',
|
||||
],
|
||||
],
|
||||
'cleaning' => [
|
||||
'superadmin' => true,
|
||||
],
|
||||
'htmlComponents' => [
|
||||
'superadmin' => true,
|
||||
],
|
||||
'languageCheckAdmin' => [
|
||||
'superadmin' => true,
|
||||
],
|
||||
'balikonos' => [
|
||||
'rights' => [
|
||||
'ORDER_',
|
||||
],
|
||||
'modules' => [
|
||||
'balikonos',
|
||||
],
|
||||
],
|
||||
'balikobot' => [
|
||||
'rights' => [
|
||||
'BALIKOBOT',
|
||||
],
|
||||
],
|
||||
'BalikonosOrders' => [
|
||||
'rights' => [
|
||||
'ORDER_',
|
||||
],
|
||||
'modules' => [
|
||||
'balikonos',
|
||||
],
|
||||
],
|
||||
'restrictions' => [
|
||||
'rights' => [
|
||||
'RESTR',
|
||||
],
|
||||
'modules' => [
|
||||
'restrictions',
|
||||
],
|
||||
],
|
||||
'reviews' => [
|
||||
'rights' => [
|
||||
'REVIEWS',
|
||||
],
|
||||
'modules' => [
|
||||
'reviews',
|
||||
],
|
||||
],
|
||||
'sellers' => [
|
||||
'rights' => [
|
||||
'SELLERS',
|
||||
],
|
||||
'modules' => [
|
||||
'sellers',
|
||||
'sellers_old',
|
||||
],
|
||||
],
|
||||
'margins' => [
|
||||
'rights' => [
|
||||
'MARGINS',
|
||||
],
|
||||
'modules' => [
|
||||
'margins',
|
||||
],
|
||||
],
|
||||
'preOrders' => [
|
||||
'rights' => [
|
||||
'ORDER_',
|
||||
],
|
||||
],
|
||||
'emails' => [
|
||||
'modules' => [
|
||||
'orders',
|
||||
'forms',
|
||||
],
|
||||
'rights' => [
|
||||
'OTH_EMAILS_',
|
||||
],
|
||||
],
|
||||
'fulltext' => [
|
||||
'modules' => [
|
||||
'eshop_search',
|
||||
],
|
||||
'rights' => [
|
||||
'FULLTEXT_SEARCH',
|
||||
],
|
||||
],
|
||||
'translate' => [
|
||||
'rights' => [
|
||||
'TRANSLATE_',
|
||||
],
|
||||
],
|
||||
'translationsStats' => [
|
||||
'rights' => [
|
||||
'TRANSLATE_',
|
||||
],
|
||||
],
|
||||
'countries' => [
|
||||
'rights' => [
|
||||
'COUNTRY',
|
||||
],
|
||||
],
|
||||
'languages' => [
|
||||
'superadmin' => true,
|
||||
'rights' => [
|
||||
'LANGUAGE',
|
||||
],
|
||||
],
|
||||
'feeds' => [
|
||||
'modules' => [
|
||||
'feeds',
|
||||
],
|
||||
'rights' => [
|
||||
'FEEDS',
|
||||
],
|
||||
],
|
||||
'pricelist' => [
|
||||
'rights' => [
|
||||
'PRICELISTS',
|
||||
],
|
||||
],
|
||||
'invoices' => [
|
||||
'modules' => [
|
||||
'invoices',
|
||||
],
|
||||
'rights' => [
|
||||
'ORDER_INVOICE', // fakturovat objednavky
|
||||
'INVOICE', // spravovat fakturacni rady
|
||||
],
|
||||
],
|
||||
'LlmPrompt' => [
|
||||
'modules' => [
|
||||
'llm',
|
||||
],
|
||||
'rights' => [
|
||||
'LLM_',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
735
admin/class/class.Window.php
Normal file
735
admin/class/class.Window.php
Normal file
@@ -0,0 +1,735 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use KupShop\AdminBundle\Admin\Actions\ActionsLocator;
|
||||
use KupShop\AdminBundle\Event\WindowTabsEvent;
|
||||
use KupShop\AdminBundle\Util\ActivityLog;
|
||||
use KupShop\AdminBundle\Util\WindowTabLocator;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\KupShopBundle\Util\Logging\SentryLogger;
|
||||
use Query\Operator;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class Window extends Frame
|
||||
{
|
||||
use DatabaseCommunication;
|
||||
|
||||
public const RIGHT_DELETE = 'delete';
|
||||
public const RIGHT_DUPLICATE = 'duplicate';
|
||||
public const RIGHT_SAVE = 'save';
|
||||
|
||||
protected $nameField = 'name';
|
||||
|
||||
protected $fields = [];
|
||||
protected $defaults = [];
|
||||
protected $required = [];
|
||||
protected $types = [];
|
||||
protected $uniques;
|
||||
protected $tableName;
|
||||
|
||||
// Type of item to display on web
|
||||
protected $show_on_web;
|
||||
|
||||
protected $action;
|
||||
protected $ID;
|
||||
protected $type;
|
||||
|
||||
protected $tabs;
|
||||
protected $custom_data;
|
||||
|
||||
protected $processedData;
|
||||
|
||||
public function getTemplate()
|
||||
{
|
||||
if (empty($this->template)) {
|
||||
$name = lcfirst($this->getClassName());
|
||||
|
||||
return "window/{$name}.tpl";
|
||||
}
|
||||
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
public function createSQLFields($tablename)
|
||||
{
|
||||
$defaults = [];
|
||||
$required = [];
|
||||
$fields = [];
|
||||
$types = [];
|
||||
|
||||
$conn = $this->getDbalConnection();
|
||||
$tm = $conn->getSchemaManager();
|
||||
|
||||
$columns = $tm->listTableColumns($tablename);
|
||||
foreach ($columns as $column) {
|
||||
$name = $column->getName();
|
||||
$fields[] = $name;
|
||||
$defaults[$name] = $column->getDefault();
|
||||
$required[$name] = ($column->getNotNull() && is_null($defaults[$name]));
|
||||
$types[$name] = $column->getType()->getName();
|
||||
}
|
||||
|
||||
$this->defaults = array_merge($defaults, $this->defaults);
|
||||
$this->required = array_merge($required, $this->required);
|
||||
$this->fields = array_merge($fields, $this->fields);
|
||||
$this->types = array_merge($types, $this->types);
|
||||
}
|
||||
|
||||
protected function collectVariables()
|
||||
{
|
||||
$acn = $this->getAction();
|
||||
|
||||
if ($acn == 'erased') {
|
||||
return self::get_vars();
|
||||
}
|
||||
|
||||
return $this->get_vars();
|
||||
}
|
||||
|
||||
public function get_vars()
|
||||
{
|
||||
$vars = parent::get_vars();
|
||||
|
||||
$acn = $this->getAction();
|
||||
|
||||
$pageVars = [
|
||||
'acn' => $acn,
|
||||
];
|
||||
|
||||
$ID = $this->getID();
|
||||
|
||||
if (($acn == 'edit' && !empty($ID)) || $acn == 'add') {
|
||||
if ($acn == 'edit' || ($acn == 'add' && $this->isDuplicate() && !empty($ID))) {
|
||||
$pageVars['data'] = $this->getObject();
|
||||
|
||||
if (getVal('Submit')) {
|
||||
$data = $this->getProcessedData();
|
||||
$pageVars['data'] = array_merge($pageVars['data'], $data);
|
||||
}
|
||||
|
||||
if (!empty($this->isDuplicate())) {
|
||||
$this->getFields();
|
||||
$this->duplicateObject($pageVars['data']);
|
||||
$pageVars['duplicate'] = true;
|
||||
}
|
||||
} elseif ($acn == 'add') {
|
||||
$pageVars['data'] = $this->createObject();
|
||||
}
|
||||
}
|
||||
|
||||
$vars['type'] = $this->getType();
|
||||
|
||||
$flap = getVal('flap', null, 1);
|
||||
$vars['header']['flap'] = empty($flap) ? 1 : $flap;
|
||||
$vars['header']['flap_next'] = getVal('flap_next');
|
||||
$vars['header']['force_resize'] = getVal('force_resize');
|
||||
|
||||
$vars['tabs'] = $this->getTabs();
|
||||
|
||||
$vars['body'] = $pageVars;
|
||||
|
||||
$vars['actionsLocator'] = ServiceContainer::getService(ActionsLocator::class);
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
protected function getType()
|
||||
{
|
||||
if (empty($this->type)) {
|
||||
$type = getVal('s');
|
||||
if (!$type) {
|
||||
$type = lcfirst($this->getClassName());
|
||||
} else {
|
||||
$type = substr($type, 0, -4);
|
||||
}
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function translateType()
|
||||
{
|
||||
// try to translate type to czech/english
|
||||
$type = $this->getType();
|
||||
|
||||
// preferred:
|
||||
// e.g. $txt_str['deliveryPriceLists']['navigation'] = 'Ceníky dopravy'
|
||||
if ($typeName = translate('navigation', $type, true)) {
|
||||
return $typeName;
|
||||
}
|
||||
|
||||
// e.g. $txt_str['navigation']['deliveryDelivery'] = 'Dopravy'
|
||||
if ($typeName = translate($type, 'navigation', true)) {
|
||||
return $typeName;
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
protected function getFields()
|
||||
{
|
||||
if (empty($this->fields)) {
|
||||
$this->createSQLFields($this->getTableName());
|
||||
}
|
||||
}
|
||||
|
||||
protected function getUniques($table = null)
|
||||
{
|
||||
if (!is_null($this->uniques)) {
|
||||
return $this->uniques;
|
||||
}
|
||||
|
||||
if (empty($table)) {
|
||||
$table = $this->getTableName();
|
||||
}
|
||||
|
||||
$conn = $this->getDbalConnection();
|
||||
$tm = $conn->getSchemaManager();
|
||||
|
||||
$indexes = $tm->listTableIndexes($table);
|
||||
|
||||
$this->uniques = [$this->nameField => true];
|
||||
foreach ($indexes as $index) {
|
||||
if ($index->isUnique() == true && $index->getName() != 'PRIMARY') {
|
||||
if (isset($index->getColumns()[1])) {
|
||||
$this->uniques[$index->getColumns()[1]] = true;
|
||||
} else {
|
||||
$this->uniques[$index->getName()] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->uniques;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
$data = getVal('data', null, []);
|
||||
|
||||
if (!empty($data)) {
|
||||
$data['ID'] = getVal('ID');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** Process all POSTed data from form. Transform data to SQL fields array */
|
||||
public function processFormData()
|
||||
{
|
||||
return $this->getData();
|
||||
}
|
||||
|
||||
final public function getProcessedData()
|
||||
{
|
||||
if (isset($this->processedData)) {
|
||||
return $this->processedData;
|
||||
}
|
||||
|
||||
return $this->processedData = $this->processFormData();
|
||||
}
|
||||
|
||||
public function setCustomData($data)
|
||||
{
|
||||
$this->updateSQL($this->getTableName(), [
|
||||
'data' => empty($data) ? null : json_encode($data),
|
||||
], ['id' => $this->getID()]);
|
||||
|
||||
// reset custom data cache
|
||||
$this->custom_data = null;
|
||||
}
|
||||
|
||||
public function getCustomData()
|
||||
{
|
||||
if (empty($this->custom_data)) {
|
||||
$object = $this->getObject();
|
||||
$this->unserializeCustomData($object);
|
||||
$this->custom_data = $object['data'];
|
||||
}
|
||||
|
||||
return $this->custom_data;
|
||||
}
|
||||
|
||||
public function getTableName()
|
||||
{
|
||||
if (empty($this->tableName)) {
|
||||
$this->tableName = strtolower($this->getClassName());
|
||||
}
|
||||
|
||||
return $this->tableName;
|
||||
}
|
||||
|
||||
private function duplicateObject(&$data)
|
||||
{
|
||||
$uniques = $this->getUniques();
|
||||
foreach ($uniques as $key => $value) {
|
||||
if (isset($data[$key])) {
|
||||
if ($this->required[$key] == false) {
|
||||
$data[$key] = null;
|
||||
} else {
|
||||
$data[$key] = stringCopy(trim($data[$key]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function createObject()
|
||||
{
|
||||
$data = $this->getData();
|
||||
|
||||
return array_merge($this->defaults, $data);
|
||||
}
|
||||
|
||||
protected function getObject()
|
||||
{
|
||||
$object = $this->fetchObject($this->getTableName(), $this->getID());
|
||||
if (!$object && $this->getAction() !== 'add') {
|
||||
$errStr = sprintf(translate('errorNotFound', 'base'), $this->translateType(), $this->getID());
|
||||
throw new NotFoundHttpException($errStr);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function getObjectData()
|
||||
{
|
||||
return $this->getObject();
|
||||
}
|
||||
|
||||
// Vypisovani aktivit
|
||||
protected function activityMessage($name, array $additionalData = [])
|
||||
{
|
||||
$acn = $this->getAction();
|
||||
if ($acn == 'add') {
|
||||
addActivityLog(ActivityLog::SEVERITY_NOTICE, ActivityLog::TYPE_CHANGE, sprintf(translate('activityAdded'), $name),
|
||||
[
|
||||
...ActivityLog::addObjectData([$this->getID() => $name], $this->getType()),
|
||||
...$additionalData,
|
||||
]);
|
||||
} elseif ($acn == 'edit') {
|
||||
addActivityLog(ActivityLog::SEVERITY_NOTICE, ActivityLog::TYPE_CHANGE, sprintf(translate('activityEdited'), $name),
|
||||
[
|
||||
...ActivityLog::addObjectData([$this->getID() => $name], $this->getType()),
|
||||
...$additionalData,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getAdditionalActivityData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
$acn = $this->getAction();
|
||||
$ID = $this->getID();
|
||||
|
||||
if ($acn == 'add') {
|
||||
$this->tryRights('ADD');
|
||||
}
|
||||
if ($acn == 'edit') {
|
||||
$this->tryRights('EDIT');
|
||||
}
|
||||
|
||||
if ((($acn == 'edit' && (strlen($ID) > 0)) || $acn == 'add') && getVal('Submit')) {
|
||||
$data = $this->getProcessedData();
|
||||
$missing = $this->checkRequired($data);
|
||||
if (!$missing) {
|
||||
$activityAdditionalData = $this->getAdditionalActivityData();
|
||||
$SQL = $this->handleUpdate();
|
||||
if ($SQL) {
|
||||
if ((empty($this->getErrors()) && empty($this->getHTMLErrors())) || $acn == 'add') {
|
||||
if (isset($data[$this->nameField])) {
|
||||
$this->activityMessage($data[$this->nameField], $activityAdditionalData);
|
||||
}
|
||||
$this->returnOK();
|
||||
}
|
||||
} else {
|
||||
$ErrStr = getTextString('status', 'scripterror');
|
||||
$this->returnError($ErrStr);
|
||||
}
|
||||
} else {
|
||||
$ErrStr = getTextString('base', 'errorNotAllValid');
|
||||
$ErrStr .= join(',', $missing);
|
||||
$this->addError($ErrStr);
|
||||
}
|
||||
} elseif ($acn == 'erase' && !empty($ID)) {
|
||||
$this->tryRights('ERASE');
|
||||
$this->handleDelete();
|
||||
} else {
|
||||
$this->handleTabs();
|
||||
parent::handle();
|
||||
}
|
||||
} catch (Doctrine\DBAL\DBALException $e) {
|
||||
$this->handleException($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function handleException($e)
|
||||
{
|
||||
if (intval($e->getPrevious()->errorInfo[1]) === 1062) {
|
||||
$ErrStr = 'Duplicitní ';
|
||||
$badFields = $this->getBadValues($this->getTableName(), ['id' => $this->ID]);
|
||||
foreach ($badFields as $value) {
|
||||
$ErrStr .= '{'.$value.'} ';
|
||||
}
|
||||
|
||||
if (!$badFields) {
|
||||
$ErrStr = "Duplicitní záznam: \n".$e->getMessage();
|
||||
}
|
||||
|
||||
$this->addError($ErrStr);
|
||||
} elseif (intval($e->getPrevious()->getCode()) === 45000) {
|
||||
$msg = $e->getPrevious()->getMessage();
|
||||
$this->addError(mb_substr($msg, mb_strpos($msg, 'EAN')));
|
||||
} elseif (in_array(intval($e->getPrevious()->getErrorCode()), [1205, 1213])) {
|
||||
$this->addError('Chyba při zpracování požadavku. Zkuste to prosím znovu.');
|
||||
$sentryLogger = ServiceContainer::getService(SentryLogger::class);
|
||||
$data = json_encode($this->getAllSQLProcesses());
|
||||
$sentryLogger->captureException(new Exception('Deadlock v administraci!', 1205, $e), ['extra' => ['processes' => $data]]);
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
// Kontroluje, jestli v datech z formulare jsou vsechny povinne polozky
|
||||
public function checkRequired($data)
|
||||
{
|
||||
$this->getFields();
|
||||
$required = [];
|
||||
foreach ($data as $key => $value) {
|
||||
if (!is_array($value)) {
|
||||
$value = trim($value);
|
||||
}
|
||||
if (isset($this->required[$key])
|
||||
&& $this->required[$key] == true
|
||||
&& $value === ''
|
||||
&& ((@$this->types[$key] != 'string' && @$this->types[$key] != 'simple_array' && @$this->types[$key] != 'text') || $key == $this->nameField)
|
||||
) {
|
||||
$required[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $required;
|
||||
}
|
||||
|
||||
// Obecna funkce pro update & insert
|
||||
public function handleUpdate()
|
||||
{
|
||||
$acn = $this->getAction();
|
||||
$SQL = null;
|
||||
|
||||
if ($acn == 'add') {
|
||||
$sqlFields = $this->getSQLFields();
|
||||
$this->insertSQL($this->getTableName(), $sqlFields);
|
||||
$SQL = true;
|
||||
if (empty($ID)) {
|
||||
if (isset($sqlFields['id'])) {
|
||||
$this->setID($sqlFields['id']);
|
||||
} else {
|
||||
$this->setID(sqlInsertID());
|
||||
}
|
||||
}
|
||||
} elseif ($acn == 'edit') {
|
||||
$sqlFields = $this->getSQLFields();
|
||||
$this->updateSQL($this->getTableName(), $sqlFields, ['id' => $this->getID()]);
|
||||
|
||||
if (isset($sqlFields['id'])) {
|
||||
$this->setID($sqlFields['id']);
|
||||
}
|
||||
|
||||
$SQL = true;
|
||||
}
|
||||
|
||||
// reset custom data cache
|
||||
$this->custom_data = null;
|
||||
|
||||
$this->handleTabs(true);
|
||||
|
||||
return $SQL;
|
||||
}
|
||||
|
||||
public function forceUpdate()
|
||||
{
|
||||
try {
|
||||
// get actual action
|
||||
$action = $this->getAction();
|
||||
|
||||
// change action to edit
|
||||
$this->action = 'edit';
|
||||
// do update
|
||||
$_REQUEST['Submit'] = 'OK';
|
||||
$this->createSQLFields($this->getTableName());
|
||||
$result = $this->handleUpdate();
|
||||
// return action
|
||||
$this->action = $action;
|
||||
|
||||
return $result;
|
||||
} catch (Doctrine\DBAL\DBALException $e) {
|
||||
$this->handleException($e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getIdFromDatabase($field)
|
||||
{
|
||||
$id = returnSQLResult('SELECT id FROM '.getTableName($this->getTableName())." WHERE {$field[0]}='{$field[1]}' ");
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function getSQLFields($data = null, $fields = null, $defaults = null, $types = null)
|
||||
{
|
||||
if ($data == null) {
|
||||
$data = $this->getProcessedData();
|
||||
}
|
||||
|
||||
if ($fields == null) {
|
||||
$fields = $this->fields;
|
||||
}
|
||||
|
||||
if ($defaults == null) {
|
||||
$defaults = $this->defaults;
|
||||
}
|
||||
|
||||
if ($types == null) {
|
||||
$types = $this->types;
|
||||
}
|
||||
|
||||
$sqlField = [];
|
||||
foreach ($fields as $row) {
|
||||
if (array_key_exists($row, $data) && !is_array($data[$row])) {
|
||||
if (!is_null($data[$row])) {
|
||||
$data[$row] = trim($data[$row]);
|
||||
}
|
||||
|
||||
if (array_key_exists($row, $types)) {
|
||||
$type = $types[$row];
|
||||
if (($type == Type::DECIMAL) || ($type == Type::FLOAT)) {
|
||||
$this->preparePrice($data[$row]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data[$row]) && ($data[$row] === '') && (@$defaults[$row] === null) && @!$this->required[$row]) {
|
||||
$sqlField[$row] = null;
|
||||
} else {
|
||||
$sqlField[$row] = $data[$row];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sqlField;
|
||||
}
|
||||
|
||||
// Smazani polozky
|
||||
public function handleDelete()
|
||||
{
|
||||
if ($this->nameField) {
|
||||
$name = sqlQueryBuilder()->select($this->nameField)->from($this->getTableName())
|
||||
->andWhere(Operator::equals(['id' => $this->getID()]))
|
||||
->execute()->fetchOne();
|
||||
if ($logMessage = translate('activityDeleted', $this->getType(), true)) {
|
||||
$logMessage = sprintf($logMessage, $name);
|
||||
} else {
|
||||
$logMessage = translate('activityDeleted', 'status'); // 'Deleted %s: %s'
|
||||
$logMessage = sprintf($logMessage, $this->getType(), $name);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$res = sqlQueryBuilder()->delete($this->getTableName())
|
||||
->andWhere(Operator::equals(['id' => $this->getID()]))
|
||||
->execute();
|
||||
if ($res && !empty($logMessage)) {
|
||||
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_CHANGE, $logMessage);
|
||||
}
|
||||
} catch (Doctrine\DBAL\DBALException $e) {
|
||||
switch (intval($e->getPrevious()->errorInfo[1])) {
|
||||
case 1451:
|
||||
$ErrStr = 'Tento objekt je použit a nelze ho smazat.';
|
||||
$this->returnError($ErrStr);
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->handleException($e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new \KupShop\KupShopBundle\Exception\RedirectException("launch.php?s={$this->getName()}.php&acn=erased");
|
||||
}
|
||||
|
||||
public function hasRights($name = null)
|
||||
{
|
||||
switch ($name) {
|
||||
case self::RIGHT_DUPLICATE:
|
||||
if ($this->getAction() == 'edit' && $this->getID() != null) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case self::RIGHT_SAVE:
|
||||
// Kdyz mam READ a nemam EDIT, tak nezobrazim save button
|
||||
if (UserRights::hasRights($this->getRightsType(), 'READ') && !UserRights::hasRights($this->getRightsType(), 'EDIT')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getBadValues($table = null, $rowIdentifier = [])
|
||||
{
|
||||
if (!empty($table)) {
|
||||
$uniques = $this->getUniques($table);
|
||||
} else {
|
||||
$table = $this->getTableName();
|
||||
$uniques = [];
|
||||
}
|
||||
|
||||
$where = '';
|
||||
foreach ($rowIdentifier as $key => $value) {
|
||||
$where .= " AND {$key}!=:{$key}";
|
||||
}
|
||||
|
||||
$data = $this->getData();
|
||||
$badFields = [];
|
||||
foreach ($uniques as $key => $value) {
|
||||
if ($value) {
|
||||
if (isset($data[$key])) {
|
||||
$SQL = returnSQLResult('SELECT COUNT(*) FROM '.getTableName($table)." WHERE {$key}=:{$key} {$where}",
|
||||
array_merge($data, $rowIdentifier));
|
||||
if ($SQL > 0) {
|
||||
$badFields[] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $badFields;
|
||||
}
|
||||
|
||||
public function redirect($params = [])
|
||||
{
|
||||
parent::redirect(array_merge(['ID' => $this->getID(), 'acn' => 'edit'], $params));
|
||||
}
|
||||
|
||||
public function getShowOnWeb()
|
||||
{
|
||||
if ($this->show_on_web == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->getID() === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ['type' => $this->show_on_web, 'id' => $this->getID()];
|
||||
}
|
||||
|
||||
public function getNameField()
|
||||
{
|
||||
return $this->nameField;
|
||||
}
|
||||
|
||||
public function handleTabs($update = false)
|
||||
{
|
||||
$tabs = $this->getTabs();
|
||||
foreach ($tabs as $tab) {
|
||||
$tab->setID($this->getID());
|
||||
|
||||
if ($update) {
|
||||
$tab->handleUpdate();
|
||||
// reset custom data cache
|
||||
$this->custom_data = null;
|
||||
} else {
|
||||
$tab->handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return WindowTabs.
|
||||
*/
|
||||
protected function getTabs()
|
||||
{
|
||||
if (!is_null($this->tabs)) {
|
||||
return $this->tabs;
|
||||
}
|
||||
|
||||
$windowTabLocator = ServiceContainer::getService(WindowTabLocator::class, 0);
|
||||
|
||||
$dispatcher = ServiceContainer::getService('event_dispatcher');
|
||||
$tabsEvent = new WindowTabsEvent();
|
||||
$dispatcher->dispatch($tabsEvent, WindowTabsEvent::NAME_PREFIX.$this->getType());
|
||||
|
||||
$tabs = array_merge(
|
||||
$windowTabLocator ? $windowTabLocator->getTabs($this->getType()) : [],
|
||||
$tabsEvent->getTabs()
|
||||
);
|
||||
|
||||
foreach ($tabs as &$tab) {
|
||||
$tab->setWindow($this);
|
||||
}
|
||||
|
||||
return $this->tabs = $tabs;
|
||||
}
|
||||
|
||||
public function handleGetActionSnippet()
|
||||
{
|
||||
$actionName = getVal('action');
|
||||
/** @var $massActionsLocator ActionsLocator */
|
||||
$actionsLocator = ServiceContainer::getService(ActionsLocator::class);
|
||||
$action = $actionsLocator->getServiceByActionClassName($actionName);
|
||||
$smarty = createSmarty(true, true);
|
||||
$smarty->assign($action->getVars());
|
||||
$smarty->display($action->getTemplate());
|
||||
exit;
|
||||
}
|
||||
|
||||
public function handleExecuteAction()
|
||||
{
|
||||
$actionName = getVal('action');
|
||||
/** @var $massActionsLocator ActionsLocator */
|
||||
$actionsLocator = ServiceContainer::getService(ActionsLocator::class);
|
||||
$action = $actionsLocator->getServiceByActionClassName($actionName);
|
||||
$action->setWindow($this);
|
||||
$data = $this->getData();
|
||||
$result = $action->execute($data, getVal('config', $_POST, []), $this->getType());
|
||||
if ($result->isSuccessful()) {
|
||||
if ($result->getHTMLMessage()) {
|
||||
$this->action = 'edit';
|
||||
$this->addHTMLError($result->getHTMLMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$params = ['action' => null];
|
||||
if ($result->getRedirect()) {
|
||||
$params = array_merge($params, $result->getRedirect());
|
||||
}
|
||||
$this->returnOK(!empty($result->getMsg()) ? $result->getMsg() : ('Akce ['.$action->getName().'] byla provedena.'),
|
||||
false,
|
||||
$params);
|
||||
} else {
|
||||
$this->redirect(['acn' => 'edit',
|
||||
'action' => null,
|
||||
'ErrStr' => !empty($result->getMsg()) ? $result->getMsg() : ('Akce ['.$action->getName().'] se nezdařila.')]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getAllSQLProcesses()
|
||||
{
|
||||
return sqlQuery('SHOW FULL PROCESSLIST')->fetchAllAssociative();
|
||||
}
|
||||
}
|
||||
22
admin/class/smarty_plugins/function.find_module.php
Normal file
22
admin/class/smarty_plugins/function.find_module.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {find_module} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: finding module
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_find_module($params, &$smarty)
|
||||
{
|
||||
return findModule($params['name']);
|
||||
}
|
||||
29
admin/class/smarty_plugins/function.find_right.php
Normal file
29
admin/class/smarty_plugins/function.find_right.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {find_right} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: finding rights
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_find_right($params, &$smarty)
|
||||
{
|
||||
$var = null;
|
||||
$name = '';
|
||||
extract($params);
|
||||
if (empty($name)) {
|
||||
throw new InvalidArgumentException('find_right: \'name\' parameter empty');
|
||||
}
|
||||
|
||||
return findRight($name, $var);
|
||||
}
|
||||
27
admin/class/smarty_plugins/function.get_named_vats.php
Normal file
27
admin/class/smarty_plugins/function.get_named_vats.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\OrderingBundle\Util\Order\OrderInfo;
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
function smarty_function_get_named_vats($params, &$smarty)
|
||||
{
|
||||
if (!isset($params['vats'])) {
|
||||
throw new InvalidArgumentException('Parameter \'vats\' is required!');
|
||||
}
|
||||
if (!is_array($params['vats'])) {
|
||||
throw new InvalidArgumentException('Parameter \'vats\' must be of type array!');
|
||||
}
|
||||
|
||||
$orderInfo = ServiceContainer::getService(OrderInfo::class);
|
||||
|
||||
$namedVats = $orderInfo->getNamedVats($params['vats']);
|
||||
|
||||
if (!empty($params['assign'])) {
|
||||
$smarty->assign($params['assign'], $namedVats);
|
||||
} else {
|
||||
return $namedVats;
|
||||
}
|
||||
}
|
||||
28
admin/class/smarty_plugins/function.get_statuses.php
Normal file
28
admin/class/smarty_plugins/function.get_statuses.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {get_statuses} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: get statuses
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_get_statuses($params, &$smarty)
|
||||
{
|
||||
$statuses = getStatuses($params['name']);
|
||||
|
||||
if (!empty($params['assign'])) {
|
||||
$smarty->assign($params['assign'], $statuses);
|
||||
} else {
|
||||
return $statuses;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {get_statuses} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: get statuses
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_get_today_selled_items($params, &$smarty)
|
||||
{
|
||||
$last_item = end($params['items']);
|
||||
|
||||
if (empty($last_item['date'])) {
|
||||
return $params['items'];
|
||||
}
|
||||
|
||||
$last_datetime = (new DateTime($last_item['date']))->modify('-1 hours');
|
||||
|
||||
$items = [];
|
||||
foreach ($params['items'] as $item) {
|
||||
$datetime = new DateTime($item['date']);
|
||||
if ($last_datetime < $datetime) {
|
||||
$items[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($items)) {
|
||||
return $params['items'];
|
||||
}
|
||||
|
||||
if (!empty($params['assign'])) {
|
||||
$smarty->assign($params['assign'], $items);
|
||||
} else {
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
23
admin/class/smarty_plugins/function.get_user.php
Normal file
23
admin/class/smarty_plugins/function.get_user.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {get_user} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: get_user<br>
|
||||
* Purpose: get User ID
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
function smarty_function_get_user($params, &$smarty)
|
||||
{
|
||||
if (!empty($GLOBALS['adminID'])) {
|
||||
return $GLOBALS['adminID'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
function smarty_function_helpscout_beacon_identity()
|
||||
{
|
||||
$admin = getAdminUser();
|
||||
|
||||
return json_encode([
|
||||
'name' => $admin['name'] ?? $admin['login'],
|
||||
'email' => $admin['email'],
|
||||
'company' => getShopUniqueName(),
|
||||
'signature' => hash_hmac(
|
||||
'sha256',
|
||||
$admin['email'],
|
||||
'MjodsaAdWfVlVXSiOnas0qgE7CQzbRrdjTEEXLR0RUY='
|
||||
),
|
||||
]);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
function smarty_function_insert_autocomplete_form($params, $smarty)
|
||||
{
|
||||
static $instance = 0;
|
||||
|
||||
$defaults = [
|
||||
'instance' => $instance,
|
||||
];
|
||||
|
||||
$params = array_merge($defaults, $params);
|
||||
|
||||
$requiredParams = ['type', 'searchInput', 'inputName', 'items'];
|
||||
foreach ($requiredParams as $requiredParam) {
|
||||
if (!array_key_exists($requiredParam, $params)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Missing required parameter "%s"', $requiredParam)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
echo $smarty->_subTemplateRender('autocomplete-form/'.$params['type'].'.tpl', $smarty->cache_id, $smarty->compile_id, 0, null, $params, 0, false);
|
||||
|
||||
$instance++;
|
||||
}
|
||||
118
admin/class/smarty_plugins/function.insert_calendar.php
Normal file
118
admin/class/smarty_plugins/function.insert_calendar.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {insert_calendar} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: insert calendar to field
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $template template object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_insert_calendar($params, $template)
|
||||
{
|
||||
$selector = null;
|
||||
$format = 'date';
|
||||
$figureFormat = true;
|
||||
$czechformat = '';
|
||||
$used = false;
|
||||
|
||||
extract($params);
|
||||
|
||||
if (empty($selector)) {
|
||||
throw new InvalidArgumentException('insert_calendar: \'selector\' parameter empty');
|
||||
}
|
||||
|
||||
echo openCalenderButton($selector, $format, $figureFormat, $czechformat, $used);
|
||||
}
|
||||
|
||||
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
|
||||
function openCalenderButton($selector, $dateFormat, $figureFormat = true, $czechformat = null, $param_used = false)
|
||||
{
|
||||
global $cfg;
|
||||
|
||||
static $used = false;
|
||||
|
||||
$used = $used || $param_used;
|
||||
|
||||
/*$format = "dd-mm-yy";
|
||||
$timeFormat = "";
|
||||
|
||||
if ($dateFormat == 'datetime')
|
||||
$timeFormat = "hh:mm:ss";
|
||||
*/
|
||||
|
||||
// if (!empty($czechformat)){
|
||||
$format = calendarDateFormat();
|
||||
$timeFormat = '';
|
||||
if ($dateFormat == 'datetime') {
|
||||
$timeFormat = calendarTimeFormat();
|
||||
}
|
||||
// }
|
||||
|
||||
$ret = "<script>
|
||||
$(function(){
|
||||
openCalenderIFrame('{$selector}', '{$format}', '{$timeFormat}');
|
||||
});
|
||||
</script>";
|
||||
|
||||
if (!$used) {
|
||||
$used = true;
|
||||
$ret .= '<script src="./static/js/jquery.datetimepicker.js"></script>';
|
||||
$ret .= '<script src="./static/js/jquery-ui.datepicker-cs.js"></script>';
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function calendarDateFormat()
|
||||
{
|
||||
$dbcfg = Settings::getDefault();
|
||||
|
||||
switch ($dbcfg['date_format']) {
|
||||
case '%e.%c.%y':
|
||||
return 'd.m.y';
|
||||
break;
|
||||
case '%d.%m.%Y':
|
||||
return 'dd.mm.yy';
|
||||
break;
|
||||
case '%d/%m/%Y':
|
||||
return 'dd/mm/yy';
|
||||
break;
|
||||
case '%d/%m/%y':
|
||||
return 'dd/mm/y';
|
||||
break;
|
||||
case '%e.%c.%Y':
|
||||
default:
|
||||
return 'd.m.yy';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function calendarTimeFormat()
|
||||
{
|
||||
$dbcfg = Settings::getDefault();
|
||||
|
||||
switch ($dbcfg['time_format']) {
|
||||
case '%k:%i:%s':
|
||||
return 'h:mm:ss';
|
||||
break;
|
||||
case '%H:%i':
|
||||
return 'hh:mm';
|
||||
break;
|
||||
case '%k:%i':
|
||||
return 'h:mm';
|
||||
break;
|
||||
case '%H:%i:%s':
|
||||
default:
|
||||
return 'hh:mm:ss';
|
||||
break;
|
||||
}
|
||||
}
|
||||
59
admin/class/smarty_plugins/function.insert_file_browse.php
Normal file
59
admin/class/smarty_plugins/function.insert_file_browse.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {insert_file_browse} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: insert file browser
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $template template object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_insert_file_browse($params, $template)
|
||||
{
|
||||
static $inserted = false;
|
||||
if (!$inserted) {
|
||||
?>
|
||||
<script src="/web/bundles/cksourceckfinder/ckfinder/ckfinder.js"></script>
|
||||
<script type="application/javascript">
|
||||
CKFinder.config({connectorPath: '/ckfinder/connector'});
|
||||
CKFinder.basePath = '/web/bundles/cksourceckfinder/ckfinder/';
|
||||
//############### BROWSE FILES #####################//
|
||||
$(document).on('click', '[data-file-browse]', function () {
|
||||
var $input = $(this).closest('.input-group').find('input');
|
||||
if (!$input)
|
||||
return true;
|
||||
|
||||
CKFinder.popup({
|
||||
language: 'cs',
|
||||
resourceType: 'Soubory',
|
||||
chooseFiles: true,
|
||||
width: 800,
|
||||
height: 600,
|
||||
onInit: function (finder) {
|
||||
finder.config.resourceType = 'Soubory';
|
||||
finder.on('files:choose', function (evt) {
|
||||
var file = evt.data.files.first();
|
||||
$input.val(decodeURIComponent(file.getUrl()));
|
||||
$input.change();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
$inserted = true;
|
||||
} ?>
|
||||
<a class="btn btn-primary btn-sm" data-file-browse href="#" title="<?php echo getTextString('products', 'findFile'); ?>">
|
||||
<span class="glyphicon glyphicon-folder-open"></span>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
45
admin/class/smarty_plugins/function.insert_llm_button.php
Normal file
45
admin/class/smarty_plugins/function.insert_llm_button.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {insert_llm_button} plugin.
|
||||
*
|
||||
* Purpose: Insert llm button
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty template object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_insert_llm_button($params, $smarty)
|
||||
{
|
||||
if (!findModule(Modules::LLM)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$textObjectUtil = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(\KupShop\LLMBundle\Util\TextObjectUtil::class);
|
||||
|
||||
$params['actions'] = [];
|
||||
|
||||
foreach ($textObjectUtil->getObjectLabelPrompts($params['type']) as $id => $prompt) {
|
||||
$json = [
|
||||
'entityType' => $params['entityType'] ?? substr(getVal('s'), 0, -4),
|
||||
'entityId' => $params['entityId'] ?? getVal('ID'),
|
||||
'target' => $params['target'],
|
||||
'promptId' => $id,
|
||||
'objectLabel' => $params['type'] ?? '',
|
||||
'title' => $prompt->getTitle(),
|
||||
];
|
||||
|
||||
$params['actions'][] = [
|
||||
'id' => $id,
|
||||
'title' => $prompt->getTitle(),
|
||||
'json' => $json,
|
||||
];
|
||||
}
|
||||
|
||||
echo $smarty->_subTemplateRender('llm/text-dropdown.tpl', $smarty->cache_id, $smarty->compile_id, 0, null, $params, 0, false);
|
||||
}
|
||||
37
admin/class/smarty_plugins/function.insert_wysiwyg.php
Normal file
37
admin/class/smarty_plugins/function.insert_wysiwyg.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {insert_wysiwyg} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: insert wysiwyg editor
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty template object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_insert_wysiwyg($params, $smarty)
|
||||
{
|
||||
static $index = 0;
|
||||
|
||||
$defaults = [
|
||||
'type' => 'BasicTable',
|
||||
'index' => $index,
|
||||
];
|
||||
|
||||
$params = array_merge($defaults, $params);
|
||||
|
||||
if (empty($params['target'])) {
|
||||
throw new InvalidArgumentException('insert_wysiwyg: \'target\' parameter empty');
|
||||
}
|
||||
|
||||
echo $smarty->_subTemplateRender('utils/wysiwyg.tpl', $smarty->cache_id, $smarty->compile_id, 0, null, $params, 0, false);
|
||||
|
||||
$index++;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
function smarty_function_print_delivery_settings($params, &$smarty)
|
||||
{
|
||||
if (!empty($params['template'])) {
|
||||
$_smarty_tpl_vars = $smarty->tpl_vars;
|
||||
echo $smarty->_subTemplateRender($params['template'], $smarty->cache_id, $smarty->compile_id, 0, null, $params, 0, false);
|
||||
$smarty->tpl_vars = $_smarty_tpl_vars;
|
||||
}
|
||||
|
||||
if (!empty($params['assign'])) {
|
||||
$smarty->assign($params['assign'], $params);
|
||||
}
|
||||
}
|
||||
52
admin/class/smarty_plugins/function.print_select.php
Normal file
52
admin/class/smarty_plugins/function.print_select.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {print_select} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: print select
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_print_select($params, &$smarty)
|
||||
{
|
||||
$name = '';
|
||||
$var = [];
|
||||
$selected = '';
|
||||
$param = '';
|
||||
$class = 'selecter';
|
||||
$keep_value = false;
|
||||
|
||||
extract($params);
|
||||
|
||||
if (!is_array($selected)) {
|
||||
$selected = [$selected => true];
|
||||
}
|
||||
|
||||
if ($keep_value) {
|
||||
foreach ($selected as $key => $value) {
|
||||
if (!array_key_exists($key, $var)) {
|
||||
$var[$key] = $key;
|
||||
}
|
||||
}
|
||||
} ?>
|
||||
<select class="<?php echo $class; ?>" data-filter-type="<?php echo (strpos($param, 'multiple') !== false) ? 'multiselect' : 'select'; ?>" name="<?php echo $name; ?>" <?php echo $param; ?>>
|
||||
<?php
|
||||
foreach ($var as $index => $value) {
|
||||
?>
|
||||
<option value="<?php echo $index; ?>"
|
||||
<?php echo (isset($selected[$index]) && ($selected[$index] || $selected[$index] == '0')) ? 'selected' : ''; ?>>
|
||||
<?php echo $value; ?>
|
||||
</option>
|
||||
<?php
|
||||
} ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
71
admin/class/smarty_plugins/function.print_toggle.php
Normal file
71
admin/class/smarty_plugins/function.print_toggle.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {print_toggle} plugin.
|
||||
*
|
||||
* Type: function<br>
|
||||
* Name: url<br>
|
||||
* Purpose: print toggle with hidden button for get Y/N value
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_print_toggle($params, &$smarty)
|
||||
{
|
||||
$name = null;
|
||||
$nameRaw = null;
|
||||
$disabled = null;
|
||||
$class = '';
|
||||
$attrs = '';
|
||||
$value = null;
|
||||
$numeric = false;
|
||||
$onOff = false;
|
||||
|
||||
extract($params);
|
||||
|
||||
if (empty($name) && empty($nameRaw)) {
|
||||
throw new InvalidArgumentException('print_toggle: \'name\' parameter empty');
|
||||
}
|
||||
|
||||
if (is_null($value)) {
|
||||
$data = $smarty->getTemplateVars('body');
|
||||
|
||||
if (!empty($data['data'])) {
|
||||
$data = $data['data'];
|
||||
}
|
||||
|
||||
$value = getVal($name, $data);
|
||||
}
|
||||
|
||||
$class .= ' toggle';
|
||||
|
||||
if ($disabled) {
|
||||
$attrs .= ' disabled ';
|
||||
}
|
||||
|
||||
if ($value == 'Y' || $value == '1') {
|
||||
$attrs .= 'checked="checked" ';
|
||||
}
|
||||
|
||||
$attrName = $name ? "data[{$name}]" : $nameRaw;
|
||||
|
||||
if ($onOff) {
|
||||
$valueTrue = 'ON';
|
||||
$valueFalse = 'OFF';
|
||||
} else {
|
||||
$valueTrue = $numeric ? 1 : 'Y';
|
||||
$valueFalse = $numeric ? 0 : 'N';
|
||||
}
|
||||
|
||||
$ret = "<input type='hidden' name='{$attrName}' value='{$valueFalse}'/>
|
||||
<label class='{$class}'><input name='{$attrName}' type='checkbox' {$attrs} value='{$valueTrue}'/>
|
||||
<span class=\"handle\"></span></label>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
19
admin/class/smarty_plugins/modifier.format_datee.php
Normal file
19
admin/class/smarty_plugins/modifier.format_datee.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {format_date} function plugin.
|
||||
*/
|
||||
function smarty_modifier_format_date($string, $value = null)
|
||||
{
|
||||
if (empty($string)) {
|
||||
return '';
|
||||
} else {
|
||||
$datetime = new DateTime($string);
|
||||
}
|
||||
|
||||
return $datetime->format(Settings::getDateFormat());
|
||||
}
|
||||
25
admin/class/smarty_plugins/modifier.format_datetime.php
Normal file
25
admin/class/smarty_plugins/modifier.format_datetime.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {format_datetime} function plugin.
|
||||
*/
|
||||
function smarty_modifier_format_datetime($string, $value = null)
|
||||
{
|
||||
if ($string == '-0001-11-30') {
|
||||
return '00-00-0000';
|
||||
} elseif ($string instanceof \DateTime) {
|
||||
$datetime = $string;
|
||||
} elseif (empty($string)) {
|
||||
return '';
|
||||
} else {
|
||||
$datetime = new DateTime($string);
|
||||
}
|
||||
|
||||
$format = Settings::getDateFormat().' '.Settings::getTimeFormat();
|
||||
|
||||
return $datetime->format($format);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smarty {format_editable_price} function plugin.
|
||||
*
|
||||
* @param Decimal $decimal - value to format
|
||||
* @param null $precision - how many decimal places to use. Use negative numbers to pretty print rounded values (strip trailing zeros)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_modifier_format_editable_price(Decimal $decimal, $precision = null)
|
||||
{
|
||||
return $decimal->printFloatValue($precision ?: 2);
|
||||
}
|
||||
Reference in New Issue
Block a user