first commit

This commit is contained in:
2025-08-02 16:30:27 +02:00
commit 23646bfcee
14851 changed files with 1750626 additions and 0 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
.php text eol=lf

11
.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
/vendor
/vendor-cache
/vendor-shared
/node_modules
/.php-cs-fixer.cache
/.php-cs-fixer.shop.cache
/.twig-cs-fixer.cache
*.bak
*po~
/admin/static/build/
.DS_Store

4
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,4 @@
include:
- project: kupshop/ci
file: gitlab-ci-engine.yml
ref: master

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "smarty"]
path = jquery/bootflat_v2
url = git@github.com:bootflat/bootflat.github.io.git

15
.htaccess Normal file
View File

@@ -0,0 +1,15 @@
#Caching
#php_flag zlib.output_compression on
#SetOutputFilter DEFLATE
ExpiresActive on
ExpiresDefault "access plus 8 hours"
ExpiresByType text/html "now"
ExpiresByType text/xml "now"
ExpiresByType text/css "access plus 8 hours"
ExpiresByType text/plain "access plus 8 hours"
ExpiresByType application/x-javascript "access plus 8 hours"
ExpiresByType image/png "access plus 8 hours"
ExpiresByType image/jpeg "access plus 8 hours"

2
.npmrc Normal file
View File

@@ -0,0 +1,2 @@
@kupshop:registry = "https://gitlab.wpj.cz/api/v4/packages/npm/"
//gitlab.wpj.cz/:_authToken=${CI_JOB_TOKEN}

15
.php-cs-fixer.config.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
return (new PhpCsFixer\Config())
->setParallelConfig(new PhpCsFixer\Runner\Parallel\ParallelConfig(4))
->setRules(
[
'@Symfony' => true,
'phpdoc_no_access' => false, // Destroys Restler API
'yoda_style' => false,
'increment_style' => false,
'single_line_throw' => false,
'explicit_string_variable' => true,
'fully_qualified_strict_types' => false,
]
);

21
.php-cs-fixer.dist.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__.'/admin')
->in(__DIR__.'/bundles')
->in(__DIR__.'/class')
->in(__DIR__.'/tests')
->in(__DIR__.'/upgrade')
->in(__DIR__.'/web')
->in(__DIR__.'/bin')
->in(__DIR__.'/socket')
->exclude('PHPExcel')
->exclude('XBase')
->exclude('highcharts')
->exclude('phpxbase')
->exclude('xmlrpc');
$config = require_once __DIR__.'/.php-cs-fixer.config.php';
return $config
->setFinder($finder);

34
.php-cs-fixer.shop.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in('admin');
if (file_exists('./include')) {
$finder->in('include');
}
if (file_exists('./bundles')) {
$finder->in('bundles');
}
if (file_exists('./app')) {
$finder->in('app');
}
if (file_exists('./src')) {
$finder->in('src');
}
$finder2 = PhpCsFixer\Finder::create()
->in('.')
->depth('== 0');
$files = new AppendIterator();
$files->append($finder->getIterator());
$files->append($finder2->getIterator());
$config = require_once __DIR__.'/.php-cs-fixer.config.php';
return $config
->setFinder($files)
->setCacheFile('./engine/.php-cs-fixer.shop.cache');

15
.prettierignore Normal file
View File

@@ -0,0 +1,15 @@
.idea
node_modules
dist
build
**/ComponentsBundle/
vendor
*.d.ts
**/views/components/
*.config.ts
wpj.*.ts
WpjComponentLoader.ts
WpjConfig.ts
**/interfaces/
query.tsx
query.ts

9
.prettierrc.mjs Normal file
View File

@@ -0,0 +1,9 @@
import wpjPrettierConfig from '@kupshop/prettier-config-wpj';
/**
* @type {import("prettier").Config}
*/
export default {
...wpjPrettierConfig,
tabWidth: 3,
}

116
admin/SplitOrder.php Normal file
View File

@@ -0,0 +1,116 @@
<?php
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\OrderingBundle\Util\Order\OrderItemEditTrait;
use KupShop\OrderingBundle\Util\Order\OrderUtil;
use Query\Operator;
class SplitOrder extends Window
{
use DatabaseCommunication;
use OrderItemEditTrait;
public function get_vars()
{
$vars = parent::get_vars();
$ID = $this->getID();
$order = $this->prepareOrder($ID);
$vars['products'] = $order->fetchItems();
$vars['order'] = $order;
$vars['body']['data']['id'] = $ID;
return $vars;
}
public function handleUpdate()
{
$ID_OLD = $this->getID();
$ID_NEW = null;
$data = $this->getData();
$order_old = $this->prepareOrder($ID_OLD);
$order_new = null;
if (findModule(\Modules::ORDER_PAYMENT) && abs($order_old->getPayments()) > 1) {
// Uhrazenou objednávku již nelze rozdělit
$this->returnError('Objednávku nelze rozdělit, protože k ní existuje platba, která doposud nebyla vrácena! Nejprve vraťte platby.');
}
if (intval($order_old['storno']) == 1) {
// Stornovanou objednávku již nelze rozdělit
$this->returnError(getTextString('SplitOrder', 'errorCanceledCantEdit'));
}
$order_new = sqlGetConnection()->transactional(function () use ($data, $ID_OLD, $order_old, $order_new, $ID_NEW) {
$orderUtil = ServiceContainer::getService(OrderUtil::class);
$order_new = $orderUtil->copyOrder($ID_OLD, ['status_payed', 'status_dispatch', 'status_storno']);
sqlQueryBuilder()->update('orders')->directValues(['date_created' => $order_old['date_created']->format('Y-m-d H:i:s')])
->where(Operator::equals(['id' => $order_new['id']]))->execute();
$ID_NEW = $order_new['id'];
$order_items = sqlQueryBuilder()->select('*')
->from('order_items')
->where(Operator::equals(['id_order' => $ID_OLD]))
->execute()
->fetchAll();
foreach ($order_items as $item_old) {
$get_item = $data['items'][$item_old['id']];
if (floatval($get_item['pieces_new']) > 0) {
$old_pcs = $item_old['pieces'] - $get_item['pieces_new'];
if ($old_pcs == 0) {
// na novou objednávku přesunout celou položku
sqlQueryBuilder()->update('order_items')
->directValues(['id_order' => $ID_NEW])
->where(Operator::equals(['id' => $item_old['id']]))
->execute();
} else {
// na novou objednávku přesunout část položek a přepočítat
$item_new_data = $item_old;
$item_new_data['id_order'] = $ID_NEW;
$item_new_data['pieces'] = $get_item['pieces_new'];
$item_new_data['pieces_reserved'] = $get_item['pieces_new'];
$item_new_data['total_price'] = $get_item['pieces_new'] * $item_old['piece_price'];
unset($item_new_data['id'], $item_new_data['pohoda_id']);
sqlQueryBuilder()->insert('order_items')
->directValues($item_new_data)
->execute();
// z původní objednávky odebrat část položek a přepočítat
sqlQueryBuilder()->update('order_items')
->directValues([
'pieces' => $item_old['pieces'] - $get_item['pieces_new'],
'pieces_reserved' => $item_old['pieces_reserved'] - $get_item['pieces_new'],
'total_price' => $item_old['piece_price'] * ($item_old['pieces'] - $get_item['pieces_new']),
])
->where(Operator::equals(['id' => $item_old['id']]))
->execute();
}
}
}
$order_old->recalculate();
$order_new->recalculate();
return $order_new;
});
writeDownActivity(sprintf(getTextString('SplitOrder', 'activitySplit'), $order_old['order_no'], $order_new['order_no']));
$order_old->logHistory(sprintf(getTextString('SplitOrder', 'splitOldNote'), $order_new['order_no']));
$order_new->logHistory(sprintf(getTextString('SplitOrder', 'splitNewNote'), $order_old['order_no']));
$this->redirect(['s' => 'orders.php', 'ID' => $order_new['id'], 'acn' => 'edit', 'force_resize' => 1, 'reload_parent' => 1]);
}
public function prepareOrder($orderId)
{
$order = new Order();
$order->createFromDB($orderId);
return $order;
}
}
return SplitOrder::class;

84
admin/adminEdit.php Normal file
View File

@@ -0,0 +1,84 @@
<?php
$main_class = 'AdminEdit';
class AdminEdit extends Window
{
protected $tableName = 'admins';
public function handleUpdate()
{
if (getVal('Submit')) {
$data = $this->getData();
global $adminID;
$admPassOld = $data['admPassOld'];
$admPass1 = $data['admPass1'];
$admPass2 = $data['admPass2'];
$error = 0;
// nova hesla se musi rovnat
if ($admPass1 != $admPass2) {
$error = 1;
// Zadané heslo a kontrolní heslo se neshodují
$ErrStr = translate('errorPasswNotEqual');
}
if (strlen($admPass1) < 6) {
$error = 15;
$ErrStr = translate('errorPasswLength');
}
// kontrola puvodniho hesla
$qb = sqlQueryBuilder()->select('id', 'login', 'password', 'OLD_PASSWORD(:admPassOld) AS passwGet')
->from('admins')
->where(\Query\Operator::equals(['id' => $adminID]))
->setParameter('admPassOld', $admPassOld)
->setMaxResults(1)
->execute();
if ($qb->rowCount() == 1) {
$log = $qb->fetch();
$admName = $log['login'];
if (($log['passwGet'] != $log['password']) && (password_verify($admPassOld, $log['password']) == false)) {
$error = 1;
// Zadané současné heslo není správné
$ErrStr = translate('errorBadPassw');
}
}
if ($error == 0) {
$new_hash = password_hash($admPass1, PASSWORD_BCRYPT);
if ($this->updateSQL('admins', ['password' => $new_hash], ['id' => $adminID])) {
$ErrStr = urlencode(sprintf(translate('activityPasswEdited'), $admName));
writeDownActivity(sprintf(translate('activityPasswEdited'), $admName));
} else {
$ErrStr = translate('scripterror', 'status');
}
redirect('launch.php?s=adminEdit.php&acn=passw&ErrStr='.$ErrStr);
} else {
redirect('launch.php?s=adminEdit.php&acn=passw&ErrStr='.urlencode($ErrStr));
}
}
return parent::handleUpdate();
}
public function getData()
{
$data = parent::getData();
$data['email'] = getAdminUser()['email'];
return $data;
}
protected function getID()
{
return getAdminUser()['id'];
}
protected function getAction()
{
return 'edit';
}
}

342
admin/admins.php Normal file
View File

@@ -0,0 +1,342 @@
<?php
// ##############################################################
global $cfg;
// ##############################################################
use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\AdminBundle\Util\LegacyAdminCredentials;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use Query\Operator;
$main_class = 'Admins';
class Admins extends Window
{
use DatabaseCommunication;
protected $nameField = 'login';
protected $required = ['login' => true];
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$ID = $this->getID();
$acn = $this->getAction();
$pageVars['data']['data'] = $pageVars['data']['data'] ?? null;
$this->unserializeCustomData($pageVars['data']);
$vars['body'] = $pageVars;
return $vars;
}
public function getObject()
{
$data = parent::getObject();
if ($data['privilege'] == 'ALL_RIGHTS') {
$data['all_rights'] = 'Y';
} else {
$data['all_rights'] = 'N';
}
return $data;
}
public function getData()
{
$data = parent::getData();
$acn = $this->getAction();
if (getVal('Submit') && $acn != 'passw') {
$data['date_valid'] = $this->prepareDateTime($data['date_valid']);
if ($data['all_rights'] == 'Y') {
$data['privilege'] = 'ALL_RIGHTS';
} else {
$data['privilege'] = '';
foreach ($data as $key => $row) {
if ($row == 'ON') {
$data['privilege'] .= $key.'|';
}
}
$data['privilege'] = substr($data['privilege'], 0, -1);
}
}
if ($acn == 'add' && !getVal('Submit')) {
$data['privilege'] = '';
$data['date_reg'] = date('Y-m-d H:i');
$data['active'] = 'Y';
}
$data['data'] = $data['custom_data'] ?? [];
$this->serializeCustomData($data);
return $data;
}
public function updatePass($password, $id)
{
$new_hash = password_hash($password, PASSWORD_BCRYPT);
$this->updateSQL('admins', ['password' => $new_hash], ['id' => $id]);
return $new_hash;
}
public function handleImpersonate(): void
{
if (!findRight('OTH_ADM_EDIT')) {
$this->returnError('Nedostatečená práva');
}
$legacyAdminCredentials = ServiceContainer::getService(LegacyAdminCredentials::class);
$newAdmin = $legacyAdminCredentials->getAdminById(
(int) $this->getID()
);
addActivityLog(
ActivityLog::SEVERITY_NOTICE,
ActivityLog::TYPE_SECURITY,
sprintf(translate('impersonateLogMessage'), $newAdmin['login'])
);
$legacyAdminCredentials->setLoginSession($this->getID());
$this->redirect(['acn' => 'erased3']);
}
public function handlePassw()
{
if (getVal('Submit')) {
$data = $this->getData();
global $adminID;
$admPassOld = $data['admPassOld'];
$admPass1 = $data['admPass1'];
$admPass2 = $data['admPass2'];
if (!empty($admPassOld) && !empty($admPass1) && !empty($admPass2)) {
$error = 0;
// nova hesla se musi rovnat
if ($admPass1 != $admPass2) {
$error = 1;
// Zadané heslo a kontrolní heslo se neshodují
$ErrStr = translate('errorPasswNotEqual');
}
// kontrola puvodniho hesla
$SQL = sqlQuery("SELECT id, login, password, OLD_PASSWORD('".$admPassOld."') AS passwGet
FROM ".getTableName('admins')."
WHERE id='".$adminID."'
LIMIT 1");
if (sqlNumRows($SQL) == 1) {
$log = sqlFetchArray($SQL);
$admName = $log['login'];
if (($log['passwGet'] != $log['password']) && (password_verify($admPassOld, $log['password']) == false)) {
$error = 1;
// Zadané současné heslo není správné
$ErrStr = translate('errorBadPassw');
}
}
sqlFreeResult($SQL);
if ($error == 0) {
/*$SQL = sqlQuery("UPDATE ".getTableName("admins")."
SET password=OLD_PASSWORD('".$admPass1."') WHERE id='".$adminID."' ");
*/
$new_hash = password_hash($admPass1, PASSWORD_BCRYPT);
$this->updateSQL('admins', ['password' => $new_hash], ['id' => $adminID]);
if ($SQL) {
$ErrStr = urlencode(translate('saved', 'status'));
writeDownActivity(sprintf(translate('activityPasswEdited'), $admName));
redirect('launch.php?s=admins.php&acn=passw&ErrStr='.$ErrStr);
} else {
$ErrStr = translate('scripterror', 'status');
}
} else {
redirect('launch.php?s=admins.php&acn=passw&ErrStr='.urlencode($ErrStr));
}
} else {
$ErrStr = translate('errorNotAllValidPassw');
redirect('launch.php?s=admins.php&acn=passw&ErrStr='.urlencode($ErrStr));
}
}
// die($ErrStr);
}
public function handleUpdate()
{
$SQL = parent::handleUpdate();
if ($SQL) {
$IDadm = $this->getID();
$data = $this->getData();
if (!empty($data['pass'])) {
/*sqlQuery("UPDATE ".getTableName("admins")."
SET password=OLD_PASSWORD('{$data['pass']}')
WHERE id='{$IDadm}' ");
*/
$new_hash = password_hash($data['pass'], PASSWORD_BCRYPT);
$this->updateSQL('admins', ['password' => $new_hash], ['id' => $IDadm]);
}
// ####################################################
// UPRAVA PRAV ADMINA KE CLANKUM
if (isset($data['ArtAuthors'])) {
if (findModule('articles')) {
// smazat vsechny radky
sqlQuery('DELETE FROM '.getTableName('articles_authors_admins')."
WHERE id_admin='".$IDadm."' ", '@');
if ($data['ArtAuthors'][0] != 0) {
$no = count($data['ArtAuthors']);
for ($i = 0; $i < $no; $i++) {
sqlQuery('INSERT INTO '.getTableName('articles_authors_admins')."
SET id_admin='".$IDadm."', id_auth='".$data['ArtAuthors'][$i]."' ");
}
}
}
}
// ####################################################
// UPRAVA PRAV ADMINA K SEKCIM CLANKU
if (isset($data['ArtSections'])) {
if (findModule('articles_sections')) {
// smazat vsechny radky
sqlQuery('DELETE FROM '.getTableName('articles_branches_admins')."
WHERE id_admin='".$IDadm."' ", '@');
if ($data['ArtSections'][0] != 0) {
$no = count($data['ArtSections']);
for ($i = 0; $i < $no; $i++) {
sqlQuery('INSERT INTO '.getTableName('articles_branches_admins')."
SET id_admin='".$IDadm."', id_branch='".$data['ArtSections'][$i]."' ");
}
}
}
}
// ####################################################
}
return $SQL;
}
public function handleDelete()
{
$IDadm = $this->getID();
if (!findRight('OTH_ADM_ERASE')) {
redirect('launch.php?s=error.php&id=1');
}
global $adminID;
if ($adminID != $IDadm) {
writeDownActivity(sprintf(translate('activityDeleted'), returnSQLResult('SELECT login
FROM '.getTableName('admins')."
WHERE id='".$IDadm."' ")));
$SQL = sqlQuery('DELETE FROM '.getTableName('admins')." WHERE id='{$IDadm}' ");
redirect('launch.php?s=admins.php&acn=erased');
} else {
// Nemůžete smazat administrátora, pod kterým jste právě přihlášen
$ErrStr = translate('errorCantDeleteActive');
redirect('launch.php?s=admins.php&acn=edit&ID='.$IDadm.'&ErrStr='.$ErrStr);
}
}
public function articlesSections($topCat)
{
$data = [];
$SQL = sqlQuery('SELECT ab.id, ab.name
FROM '.getTableName('articles_branches')." AS ab
WHERE ab.top_branch='".$topCat."'
ORDER BY ab.name ASC");
$ID = $this->getID();
foreach ($SQL as $key => $row) {
$data[$key]['id'] = $row['id'];
$data[$key]['level'] = $topCat;
$data[$key]['selected'] = returnSQLResult('SELECT Count(id_admin)
FROM '.getTableName('articles_branches_admins')."
WHERE id_admin='".$ID."' AND id_branch='".$row['id']."' LIMIT 1 ");
$data[$key]['name'] = $row['name'];
$data[$key]['submenu'] = $this->articlesSections($row['id']);
}
return $data;
}
public function handleSendPassword()
{
global $dbcfg, $cfg;
$ID = $this->getID();
$admin = sqlFetch($this->selectSQL('admins', ['id' => $ID]));
$password = $this->generatePassword(10);
$admin['password'] = $password;
$new_hash = password_hash($password, PASSWORD_BCRYPT);
$this->updateSQL('admins', ['password' => $new_hash], ['id' => $ID]);
if (!isset($cfg['Menu']['wpj_toolbar'])) {
$cfg['Menu']['wpj_toolbar'] = null;
}
$admin_url = getVal('admin_url', $cfg['Menu']['wpj_toolbar'], 'admin/');
$smarty = createSmarty(false, true);
$smarty->assign(['admin' => $admin, 'admin_url' => $admin_url]);
$content = $smarty->fetch(findTemplate('email/password_generate.tpl'));
if (SendMail($dbcfg->shop_email, $admin['email'], 'Nové heslo do administrace '.substr($cfg['Addr']['print'], 0, -1), $content, 'text/html')) {
$this->returnOK('Heslo bylo úspěšně zasláno na email');
} else {
$this->returnError('Heslo se nepodařilo odeslat, zkuste to prosím znovu');
}
}
public function generatePassword($length = 8)
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$count = mb_strlen($chars);
for ($i = 0, $result = ''; $i < $length; $i++) {
$index = rand(0, $count - 1);
$result .= mb_substr($chars, $index, 1);
}
return $result;
}
public function handlePrintHashLogin()
{
$ID = $this->getID();
$admin = sqlQueryBuilder()->select('*')->from('admins')->where(Operator::equals(['id' => $ID]))->execute()->fetch();
if (empty($admin['token'])) {
$this->returnError('Nejdříve musíte vygenerovat přihlašovací token!');
}
$smarty = createSmarty(true, true);
$smarty->assign([
'login' => $admin['login'],
'code' => $admin['token'],
]);
$smarty->display('window/adminsPrintHashLogin.tpl');
exit;
}
public function generateAdminToken(): string
{
return ServiceContainer::getService(\KupShop\KupShopBundle\Util\System\TokenGenerator::class)->generate(16);
}
}

233
admin/ajax.php Normal file
View File

@@ -0,0 +1,233 @@
<?php
use KupShop\KupShopBundle\Config;
use Query\Operator;
class AdminAjax
{
/** @var \Query\QueryBuilder */
public $qb;
private $search;
public function __construct()
{
$this->qb = sqlQueryBuilder();
}
public function run()
{
header('Content-type: application/json');
$type = getVal('type');
$limit = getVal('limit', null, 100);
if ($limit < 0) {
$limit = 999999;
}
$this->qb->setMaxResults($limit);
return $this->handle($type);
}
public function handle($type)
{
$method = 'handle'.ucfirst($type);
if (method_exists($this, $method)) {
return $this->$method();
}
return $this->fallback($type);
}
public function handleOrder()
{
$orderId = getVal('id_order');
$result = false;
if (!empty($orderId)) {
$result = sqlQueryBuilder()->select('o.*')
->from('orders', 'o')
->where(Operator::equals(['o.id' => $orderId]))
->execute()->fetch();
}
if (!$result) {
$result = [];
}
return json_encode($result);
}
public function handlePositionsOverSupply()
{
if (findModule(Modules::WAREHOUSE)) {
sqlQueryBuilder()->update('warehouse_products')
->directValues(['over_supply' => getVal('value')])
->andWhere(Operator::equalsNullable([
'id_position' => getVal('id_position'),
'id_product' => getVal('id_product'),
'id_variation' => getVal('id_variation') ?: null,
]))->execute();
return getVal('value') == 'Y';
}
return false;
}
public function handleProduct_info()
{
$cfg = Config::get();
$qb = $this->qb
->select('v.vat as vat, COALESCE(pv.in_store, p.in_store) as quantity, COALESCE(pv.ean, p.ean) as ean, COALESCE(pv.price, p.price) as price, p.discount as discount');
if (!empty($cfg['Modules']['products_variations']['variationCode'])) {
$qb->addSelect(' COALESCE(pv.code, p.code) as code');
} else {
$qb->addSelect(' p.code as code');
}
if (findModule('products', 'weight')) {
if (findModule('products_variations')) {
$qb->addSelect(' COALESCE(pv.weight, p.weight) as weight');
} else {
$qb->addSelect(' p.weight as weight');
}
}
if (findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY)) {
if (findModule(Modules::PRODUCTS_VARIATIONS)) {
$qb->addSelect('COALESCE(pv.price_buy, p.price_buy) as price_buy');
} else {
$qb->addSelect('p.price_buy as price_buy');
}
}
$qb->from('products', 'p')
->leftJoin('p', 'products_variations', 'pv', 'p.id=pv.id_product')
->leftJoin('p', 'vats', 'v', 'p.vat=v.id');
if (!getVal('id_product')) {
exit;
}
$id_product = intval(getVal('id_product'));
$id_variation = intval(getVal('id_variation'));
$qb->where(Operator::equals(['p.id' => $id_product]));
if ($id_variation > 0) {
$qb->andWhere(Operator::equals(['pv.id' => $id_variation]));
}
$products = $qb->execute()->fetchAll();
$user_id = getVal('user_id');
if (findModule(Modules::PRICE_LEVELS) && $user_id) {
$user = User::createFromId($user_id);
if ($price_level_id = $user->getUserPricelevelId()) {
$plService = KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(\KupShop\KupShopBundle\Context\PriceLevelContext::class);
$plService->activate($price_level_id);
}
}
if (getVal('currency')) {
$currencyContext = KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(\KupShop\KupShopBundle\Context\CurrencyContext::class);
$currencyContext->activate(getVal('currency'));
}
$result = [];
foreach ($products as $product) {
$PRICE_ARRAY = formatCustomerPrice($product['price'], $product['discount'], $product['vat'], $_GET['id_product']);
$price_with_vat = $PRICE_ARRAY['value_without_vat_no_rounding']->addVat($product['vat']);
$price_with_vat = roundPrice($price_with_vat);
$product['price'] = $price_with_vat->removeVat($product['vat'])->asFloat();
if (findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY)) {
$product['price_buy_with_vat'] = toDecimal($product['price_buy'])->addVat($product['vat'])->value(4);
}
$product['price_with_vat'] = $price_with_vat->asFloat();
$result[] = $product;
}
return json_encode($result);
}
public function prepareSearchFields($fields)
{
return get_search_query($this->search, $fields);
}
public function prepareSearch($search)
{
return sqlFormatInput(trim($search));
}
public function getResult()
{
return json_encode($this->qb->execute()->fetchAll());
}
public function fallback($type)
{
$limit = getVal('limit', null, 100);
$group = null;
$where = ' 1 ';
$result = [];
$data = [];
if ($limit < 0) {
$limit = 999999;
}
switch ($type) {
case 'product_of_suppliers_info':
$fields = 'pos.code code, pos.id_supplier id_supplier';
$from = getTableName('products_of_suppliers').' pos';
if (empty($_GET['id_product'])) {
exit;
}
$id_product = intval($_GET['id_product']);
$id_variation = intval($_GET['id_variation']);
$where = "pos.id_product={$id_product}";
if (!empty($_GET['id_supplier'])) {
$id_supplier = intval($_GET['id_supplier']);
$where .= " AND pos.id_supplier={$id_supplier}";
}
if (!empty($id_variation)) {
$where .= " AND pos.id_variation={$id_variation}";
}
break;
}
if ($where) {
$where = " WHERE {$where} ";
}
if ($group) {
$where .= " GROUP BY {$group} ";
}
$SQL = sqlQuery("SELECT {$fields}
FROM {$from}
{$where} LIMIT {$limit}", $data);
$result = array_merge($result, $SQL->fetchAll());
return json_encode($result);
}
}
echo (new AdminAjax())->run();

107
admin/artauthors.php Normal file
View File

@@ -0,0 +1,107 @@
<?php
use KupShop\AdminBundle\AdminBlocksTrait;
use KupShop\AdminBundle\Util\BlocksHistory;
use KupShop\ContentBundle\Util\BlocksTrait;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
class Artauthors extends Window
{
use BlocksTrait;
use AdminBlocksTrait;
protected $tableName = 'articles_authors';
protected $show_on_web = 'articlesAuthor';
private BlocksHistory $blocksHistory;
public function __construct()
{
$this->defaults = ['date_reg' => date('d-m-Y H:i'),
'active' => 'Y',
'sex' => 'M',
'top_branch' => '0',
];
$this->blocksHistory = ServiceContainer::getService(BlocksHistory::class);
}
public function getData()
{
$data = parent::getData();
if (!empty($data['date_reg'])) {
$data['date_reg'] = $this->prepareDate($data['date_reg']);
}
if (!empty($data['date_borned'])) {
$data['date_borned'] = $this->prepareDate($data['date_borned']);
}
return $data;
}
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
if (!empty($pageVars['data']['photo'])) {
$pageVars['data']['photo'] = @getImage($this->getID(), $pageVars['data']['photo'], '../articles_authors/', 'articles_authors', dateUpdate: strtotime($pageVars['data']['date_update']));
}
$vars['body'] = $pageVars;
if (isset($pageVars['data']['id_block'])) {
$vars['body']['data']['blocks'] = $this->getBlocks($pageVars['data']['id_block']);
$vars['body']['data']['blocks_history'] = $this->blocksHistory->getBlocksHistory($pageVars['data']['id_block']);
}
return $vars;
}
public function handleUpdate()
{
$SQL = parent::handleUpdate();
$ID = $this->getID();
if (!empty($_FILES['picture']['name'])) {
$img = new Photos('articles_authors');
$img->newImage($ID);
$img->uploadImage($_FILES['picture'], strtolower(substr(strrchr($_FILES['picture']['name'], '.'), 0)));
if ($img->checkFileType()) {
$img->insertImageIntoDB();
} else {
$this->returnError(getTextString('producers', 'errorBadPhoto'));
}
unset($img);
}
if ($this->getAction() == 'edit') {
// historii je treba ulozit jeste pred ulozenim bloku
$this->blocksHistory->saveBlocksHistory(getVal('blocks', $this->getData(), []));
}
$this->saveBlocks($this->getData(), $ID, 'articles_authors');
return $SQL;
}
public function handleErasephoto()
{
$ID = getVal('ID');
// sqlQuery("DELETE FROM ".getTableName("photos")." WHERE id='$IDsec'");
// ########################################################################
$img = new Photos('articles_authors');
$img->newImage($ID);
$img->deletePhoto();
unset($img);
// ########################################################################
$this->returnOK('Fotografie byla smazána');
}
}
return Artauthors::class;

23
admin/articles.photos.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
$main_class = 'ArticlesPhotos';
class ArticlesPhotos extends BaseAdminPhotos
{
use DatabaseCommunication;
use \KupShop\ContentBundle\Util\BlocksTrait;
protected $relation_table_name = 'photos_articles_relation';
protected $photo_type = 4;
protected $tablefield = 'id_art';
protected $photo_nametype = 'Article';
protected $copy_from = 'z článku';
protected $search_field = 'article';
public function handleMovePhoto()
{
parent::handleMovePhoto();
$this->updateBlocksPhotosPositions($this->getID(), 'articles', $this->tablefield);
}
}

440
admin/articles.php Normal file
View File

@@ -0,0 +1,440 @@
<?php
namespace Admin;
use KupShop\AdminBundle\AdminBlocksTrait;
use KupShop\AdminBundle\Util\AdminSectionTree;
use KupShop\AdminBundle\Util\BlocksHistory;
use KupShop\ContentBundle\Util\BlocksTrait;
use KupShop\I18nBundle\Translations\ArticlesTranslation;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\StringUtil;
use Query\Operator;
class Articles extends \Window
{
use BlocksTrait;
use AdminBlocksTrait;
protected $tableName = 'articles';
protected $template = 'window/articles.tpl';
protected $nameField = 'title';
protected $show_on_web = 'article';
/** @var BlocksHistory */
private $blocksHistory;
private AdminSectionTree $adminSectionTree;
public function __construct()
{
$this->blocksHistory = ServiceContainer::getService(BlocksHistory::class);
$this->adminSectionTree = ServiceContainer::getService(AdminSectionTree::class);
}
public function articlesSections($topCat, $Pos = 0, $ignored = null)
{
$SQL = sqlQueryBuilder()
->select('ab.id, ab.name, ab.descr, ab.figure')
->from('articles_branches', 'ab')
->where(\Query\Operator::equalsNullable(['ab.top_branch' => $topCat]))
->orderBy('ab.name', 'ASC')
->execute();
$data = [];
foreach ($SQL as $key => $row) {
if ($ignored == null || $ignored != $row['id']) {
$data[$key]['id'] = $row['id'];
$data[$key]['title'] = $row['name'];
$data[$key]['figure'] = $row['figure'];
$data[$key]['level'] = $Pos;
$data[$key]['submenu'] = $this->articlesSections($row['id'], $Pos + 1, $ignored = null);
}
}
return $data;
}
public function createObject()
{
$data = parent::createObject();
return $data;
}
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$ID = $this->getID();
$acn = $this->getAction();
if (!empty($ID)) {
$pageVars['tree'] = $this->articlesSections(null);
$pageVars['selected'] = $this->adminSectionTree->getSelected($this->getID(), 'articles_relation', 'id_art', 'id_branch');
$this->adminSectionTree->getOpened($pageVars['tree']);
$pageVars['opened'] = $this->adminSectionTree->opened;
$pageVars['articleURL'] = path('kupshop_content_articles_article_1', [
'IDa' => $ID,
'slug' => StringUtil::slugify($pageVars['data']['title']),
]);
$SQL = sqlQuery('SELECT id_auth
FROM '.getTableName('articles_authors_relation')."
WHERE id_art='".$ID."' ");
foreach ($SQL as $row) {
$pageVars['dbAuth'][$row['id_auth']] = 1;
}
$SQL = sqlQuery('SELECT id_branch
FROM '.getTableName('articles_branches_admins')."
WHERE id_admin='".$GLOBALS['adminID']."' ");
$pageVars['permittedBranches'] = [];
foreach ($SQL as $row) {
$pageVars['permittedBranches'][$row['id_branch']] = 'ENABLED';
}
// -----------------------------------------------------------------
// zjistit povolene autory
$SQL = sqlQuery('SELECT id_auth
FROM '.getTableName('articles_authors_admins')."
WHERE id_admin='".$GLOBALS['adminID']."' ");
$pageVars['permittedAuthors'] = [];
foreach ($SQL as $row) {
$pageVars['permittedAuthors'][$row['id_auth']] = 'ENABLED';
}
if ($acn == 'edit') {
$strSections = '';
$strAuthors = '';
// kdyz jsou nejake povolene sekce
if (count($pageVars['permittedBranches']) > 0) {
foreach ($pageVars['permittedBranches'] as $key => $value) {
if ($strSections != '') {
$strSections .= ' OR ';
}
$strSections .= "ar.id_branch='".$key."'";
}
$no = returnSQLResult('SELECT COUNT(*)
FROM '.getTableName('articles').' AS a, '.getTableName('articles_relation')." AS ar
WHERE a.id='".$ID."' AND a.id=ar.id_art AND (".$strSections.') ');
if (intval($no) == 0) {
$acn = 'disabled';
// redirect("launch.php?s=error.php&id=1");
}
}
// kdyz jsou nejaci povoleni autori
if (count($pageVars['permittedAuthors']) > 0) {
foreach ($pageVars['permittedAuthors'] as $key => $value) {
if ($strAuthors != '') {
$strAuthors .= ' OR ';
}
$strAuthors .= "aar.id_auth='".$key."'";
}
$no = returnSQLResult('SELECT COUNT(*)
FROM '.getTableName('articles').' AS a, '.getTableName('articles_authors_relation')." AS aar
WHERE a.id='".$ID."' AND a.id=aar.id_art AND (".$strAuthors.') ');
if (intval($no) == 0) {
$acn = 'disabled';
// redirect("launch.php?s=error.php&id=1");
}
}
if ($pageVars['data']['id_block']) {
$pageVars['data']['blocks_history'] = $this->blocksHistory->getBlocksHistory($pageVars['data']['id_block']);
}
}
foreach ($pageVars['tree'] as $key => $row) {
if (count($pageVars['permittedBranches']) > 0 && !array_key_exists($row['id'], $pageVars['permittedBranches']) == true) {
$pageVars['disabled'][$key] = true;
}
}
$pageVars['data']['photos'] = sqlQueryBuilder()->select('id_photo')->from('photos_articles_relation')
->where(\Query\Operator::equals(['id_art' => $this->getID()]))
->orderBy('position')->execute()->fetchAll();
$tags = sqlQueryBuilder()
->select('at.id, at.tag')
->from('articles_tags_relation', 'atr')
->leftJoin('atr', 'articles_tags', 'at', 'at.id = atr.id_tag')
->where(\Query\Operator::equals(['atr.id_article' => $ID]))
->execute()->fetchAll();
$pageVars['data']['tags'] = array_combine(array_column($tags, 'id'), array_column($tags, 'tag'));
$authors = sqlQueryBuilder()
->select('id_auth as id')
->from('articles_authors_relation')
->where(Operator::equals(['id_art' => $ID]))
->execute()->fetchAll();
$pageVars['data']['authors'] = array_combine(array_column($authors, 'id'), array_column($authors, 'id'));
// related articles
$relatedQb = sqlQueryBuilder()
->select('ar.id_article_related as value, ar.position, a.title as label')
->from('articles_related', 'ar')
->join('ar', 'articles', 'a', 'a.id = ar.id_article_related')
->where(Operator::equals(['ar.id_article' => $ID]))
->orderBy('ar.position')
->groupBy('ar.id_article, ar.id_article_related');
if (findModule(\Modules::ARTICLES_RELATED_TYPES)) {
$relatedQb->addSelect('ar.type')
->addSelect('GROUP_CONCAT(ar.type) as types');
}
$pageVars['articles_related'] = [];
foreach ($relatedQb->execute() as $relatedKey => $relatedItem) {
$pageVars['articles_related'][$relatedKey] = $relatedItem;
if (!empty($relatedItem['types'])) {
$relatedItem['types'] = array_map('intval', explode(',', $relatedItem['types']));
}
}
$pageVars['related_additional_data'] = [
'articlesRelatedTypes' => $this->getArticlesRelatedTypes(),
];
}
$pageVars['acn'] = $acn;
$pageVars['articleTranslationsFigure'] = $this->getTranslationUtil()?->getTranslationsFigure(ArticlesTranslation::class, $this->getID());
$this->unserializeCustomData($pageVars['data']);
$vars['body'] = $pageVars;
return $vars;
}
public function getData()
{
$data = parent::getData();
$acn = $this->getAction();
if (getVal('Submit')) {
$data['date'] = $this->prepareDateTime($data['date']);
$data['date_created'] = $this->prepareDateTime($data['date_created']);
$this->serializeCustomData($data);
$data['url'] = trim($data['url'] ?? '', '/');
if (findModule('seo')) {
if (empty($data['meta_title_changed'])) {
$data['meta_title'] = '';
}
}
}
if ($acn == 'add') {
$data['figure'] = empty($data['figure']) ? 'Y' : $data['figure'];
$data['seen'] = '0';
$data['type'] = empty($data['type']) ? 'A' : $data['type'];
$data['rating_value'] = '0';
$data['rating_voted'] = '0';
$data['comments'] = 'Y';
$data['tags'] = [];
$data['article_body'] = [];
}
return $data;
}
public function getObject()
{
$data = parent::getObject();
$ID = $this->getID();
$data['show_in_lead'] = 'N';
$no = returnSQLResult('SELECT COUNT(*)
FROM photos_articles_relation
WHERE id_art=:id AND show_in_lead="Y"', ['id' => $ID]);
if ($no == 0) {
$data['show_in_lead'] = 'Y';
}
if ($data['id_block'] === null) {
$data['blocks'] = [];
} else {
$data['blocks'] = $this->getBlocks($data['id_block']);
}
return $data;
}
public function handleUpdate()
{
$data = $this->getData();
$SQL = parent::handleUpdate();
if ($SQL) {
$ID = $this->getID();
// SAVE BLOCKS
if (!empty($data)) {
if ($this->getAction() == 'edit') {
// historii je treba ulozit jeste pred ulozenim bloku
$this->blocksHistory->saveBlocksHistory(getVal('blocks', $data, []));
}
$this->saveBlocks($data, $this->getID(), 'articles');
$this->updateBlocksPhotosPositions($this->getID(), 'articles', 'id_art');
}
// ############################################
// # ZARAZENI DO SEKCI
if (findModule('articles_sections') || findModule('news')) {
sqlQuery('DELETE FROM '.getTableName('articles_relation')."
WHERE id_art='".$ID."' ");
if (isset($_POST['sec'])) {
$no = count($_POST['sec']);
if ($no > 0) {
foreach ($_POST['sec'] as $key => $value) {
if (!empty($key)) {
sqlQuery('INSERT INTO '.getTableName('articles_relation')."
SET id_art='".$ID."', id_branch='".$key."' ");
}
}
unset($key, $value);
}
}
}
// ############################################
// # ZAPSANI AUTORU
$this->deleteSQL('articles_authors_relation', ['id_art' => $ID]);
if (!empty($data['authors'])) {
foreach (array_unique($data['authors']) as $authorId) {
$this->insertSQL('articles_authors_relation', ['id_art' => $ID, 'id_auth' => $authorId]);
}
}
// ############################################
// Save related articles
$this->deleteSQL('articles_related', ['id_article' => $ID]);
foreach ($data['articles_related'] ?? [] as $related) {
if (!empty($related['delete'])) {
continue;
}
if (findModule(\Modules::ARTICLES_RELATED_TYPES)) {
$types = $related['type'] ?? [];
if (empty($types)) {
$types = [$this->getArticlesRelatedTypes()[0]['id']];
}
foreach ($types as $type) {
sqlQueryBuilder()
->insert('articles_related')
->directValues(
[
'id_article' => $ID,
'id_article_related' => $related['id_article'],
'position' => $related['position'],
'type' => $type,
]
)->execute();
}
} else {
sqlQueryBuilder()
->insert('articles_related')
->directValues(
[
'id_article' => $ID,
'id_article_related' => $related['id_article'],
'position' => $related['position'],
]
)->execute();
}
}
// Save tags
$this->deleteSQL('articles_tags_relation', ['id_article' => $ID]);
if (!empty($data['tags'])) {
foreach (array_unique($data['tags']) as $id_tag) {
$this->insertSQL('articles_tags_relation', ['id_article' => $ID, 'id_tag' => $id_tag]);
}
}
// Save translations figure
$this->getTranslationUtil()?->updateTranslationsFigure(ArticlesTranslation::class, $this->getID(), $data['translation_figure'] ?? []);
if (!empty($data['products'])) {
foreach ($data['products'] as $id => $item) {
$item['id'] = intval($id);
if (!empty($item['delete']) || !$id) {
if ($id > 0) {
$this->deleteSQL('products_in_articles', ['id_product' => $item['id_product'], 'id_article' => $ID]);
}
continue;
}
try {
if ($id < 0) {
$this->insertSQL('products_in_articles', ['id_product' => $item['id_product'], 'id_article' => $ID]);
}
} catch (Doctrine\DBAL\DBALException $e) {
if (intval($e->getPrevious()->errorInfo[1]) == '1062') {
$this->returnError('Produkt je již k tomuto článku přidán!');
}
}
}
$this->returnOK();
}
}
return $SQL;
}
public function handleDelete()
{
$IDa = $this->getID();
$object = $this->getObject();
writeDownActivity('smazán článek: '.
returnSQLResult('SELECT title
FROM '.getTableName('articles')."
WHERE id='".$IDa."' "));
sqlQuery('DELETE FROM '.getTableName('photos_articles')."
WHERE id_art='".$IDa."' ");
sqlQuery('DELETE FROM '.getTableName('articles_relation')."
WHERE id_art='".$IDa."' ");
sqlQuery('DELETE FROM '.getTableName('articles_authors_relation')."
WHERE id_art='".$IDa."' ");
sqlQuery('DELETE FROM '.getTableName('articles')."
WHERE id='".$IDa."' ");
$this->removeBlocks($object['id_block']);
redirect('launch.php?s=articles.php&acn=erased&refresh=parent&ErrStr='.urlencode('Článek byl odstraněn.'));
}
private function getArticlesRelatedTypes(): array
{
if (!findModule(\Modules::ARTICLES_RELATED_TYPES)) {
return [];
}
return sqlQueryBuilder()
->select('id, name')
->from('articles_related_types')
->orderBy('id', 'ASC')
->execute()->fetchAllAssociative();
}
}
return Articles::class;

9
admin/articlesTags.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
class ArticlesTags extends Window
{
protected $tableName = 'articles_tags';
protected $nameField = 'tag';
}
return ArticlesTags::class;

135
admin/artsections.php Normal file
View File

@@ -0,0 +1,135 @@
<?php
class Artsections extends Window
{
protected $tableName = 'articles_branches';
protected $show_on_web = 'articlesSection';
public function __construct()
{
$this->defaults = ['date' => date('Y-m-d H:i'),
'behaviour' => '1',
'orderby' => 'date',
'orderdir' => 'ASC',
'top_branch' => null,
];
}
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$acn = $this->getAction();
$ID = $this->getID();
$pageVars['tree'] = $this->articlesSections(null, 0, $ID);
if ($acn == 'remove') {
$SQL = sqlQuery('SELECT * FROM '.getTableName('articles_branches')." WHERE id='{$ID}' ");
foreach ($SQL as $row) {
$pageVars['data'] = $row;
}
$pageVars['acn'] = 'erase';
}
$vars['body'] = $pageVars;
return $vars;
}
public function getData()
{
$data = parent::getData();
if (isset($data['template'])) {
$data['template'] = !preg_match('/^[a-zA-Z0-9_\-.]+$/', $data['template']) ? null : $data['template'];
}
if (isset($data['items_per_page'])) {
$data['items_per_page'] = empty($data['items_per_page']) || !is_numeric($data['items_per_page']) ? null : (int) $data['items_per_page'];
}
if (empty($data['top_branch'])) {
$data['top_branch'] = null;
}
return $data;
}
public function handleUpdate()
{
clearCache('article-sections-', true);
$newBranchId = $_POST['data']['top_branch'] ?? null;
$childrenIds = $this->getDescendantCategories($this->getID());
if (in_array($newBranchId, $childrenIds)) {
$this->returnError('Nelze zvolit jako nadřazenou sekci některou z podsekcí!');
}
return parent::handleUpdate();
}
public function getDescendantCategories($topBranch): array
{
return sqlFetchAll(sqlQuery(
'WITH RECURSIVE cte (level, id) AS (
SELECT 0, SR1.top_branch
FROM articles_branches SR1
WHERE SR1.top_branch = :top_branch
UNION ALL
SELECT cte.level + 1, SR2.id
FROM articles_branches SR2
INNER JOIN cte ON (cte.id = SR2.top_branch)
WHERE cte.level < 50
)
SELECT id
FROM cte ORDER BY level', ['top_branch' => $topBranch]), ['id' => 'id']);
}
public function handleDelete()
{
clearCache('article-sections-', true);
$IDsec = $this->getID();
$IDsecSel = getVal('IDsecSel');
if ($IDsecSel > 0) {
@sqlQuery('UPDATE '.getTableName('articles_relation')."
SET id_branch='".$IDsecSel."'
WHERE id_branch='".$IDsec."' ");
} elseif ($IDsecSel == 0) {
@sqlQuery('DELETE
FROM '.getTableName('articles_relation')."
WHERE id_branch='".$IDsec."' ");
}
$SQL = @sqlQuery('DELETE
FROM '.getTableName('articles_branches')."
WHERE id='".$IDsec."' ");
writeDownActivity(sprintf(translate('activityDeleted'), $IDsec));
redirect('launch.php?s=artsections.php&acn=erased&ErrStr='.urlencode(translate('note_5')));
}
public function articlesSections($topCat, $Pos = 0, $ignored = null)
{
$SQL = sqlQueryBuilder()
->select('ab.id, ab.name, ab.descr, ab.figure')
->from('articles_branches', 'ab')
->where(\Query\Operator::equalsNullable(['ab.top_branch' => $topCat]))
->orderBy('ab.name', 'ASC')
->execute();
$data = [];
foreach ($SQL as $key => $row) {
if ($ignored == null || $ignored != $row['id']) {
$data[$key]['id'] = $row['id'];
$data[$key]['title'] = $row['name'];
$data[$key]['figure'] = $row['figure'];
$data[$key]['level'] = $Pos;
$data[$key]['submenu'] = $this->articlesSections($row['id'], $Pos + 1, $ignored = null);
}
}
return $data;
}
}
$artsections = new Artsections();
$artsections->run();

2005
admin/autocomplete.php Normal file

File diff suppressed because it is too large Load Diff

268
admin/automatic_import.php Normal file
View File

@@ -0,0 +1,268 @@
<?php
class AutomaticImports extends Window
{
protected $tableName = 'import';
protected $template = 'window/automatic_import.tpl';
public function get_vars()
{
$ID = $this->getID();
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$acn = $this->getAction();
if ($acn == 'edit' || ($acn == 'add' && $this->isDuplicate() && !empty($ID))) {
$SQL = sqlQuery('SELECT s.*
FROM '.getTableName('import')." s
WHERE s.id='".$ID."' ");
if (sqlNumRows($SQL) == 1) {
$pageVars['data'] = sqlFetchArray($SQL);
if ($acn == 'add' && $this->isDuplicate() && !empty($ID)) {
$pageVars['data']['name'] = stringCopy(trim($pageVars['data']['name']));
}
$pageVars['data']['local_file'] = $GLOBALS['cfg']['Path']['data'].'/tmp/autoimport_'.$ID;
if (empty($pageVars['data']['source']) && file_exists($pageVars['data']['local_file'])) {
$pageVars['data']['source_type'] = 'upload';
} else {
$pageVars['data']['source_type'] = 'url';
}
}
} elseif ($acn == 'add') {
$pageVars['data']['source_type'] = 'upload';
$pageVars['data']['source'] = '';
$pageVars['data']['type'] = AutomaticImport::TYPE_XML;
$pageVars['data']['interval'] = 1;
$pageVars['data']['delete_old'] = null;
$pageVars['data']['modify_in_store'] = 1;
$pageVars['data']['pair'] = 1;
$pageVars['data']['local_file'] = null;
}
$sql = sqlQuery('SELECT id, name FROM '.getTableName('suppliers'));
foreach ($sql as $row) {
$pageVars['suppliers'][$row['id']] = $row['name'];
}
$pageVars['automatic_import'] = AutomaticImport::$types;
if (file_exists($pageVars['data']['local_file'])) {
$pageVars['data']['local_file_time'] = date('d.m.Y H:i:s', filemtime($pageVars['data']['local_file']));
}
$pageVars['choices'] = ['1' => 'u produktu/varianty'];
if (findModule(\Modules::PRODUCTS_SUPPLIERS) || findModule(\Modules::SUPPLIERS)) {
$pageVars['choices']['0'] = 'u dodavatele';
}
$pageVars['add_new'] = [
'0' => 'Pouze aktualizovat stávající',
'1' => 'Přidat nové i aktualizovat stávající',
'2' => 'Pouze přidat nové',
'3' => 'Přidat a aktualizovat pouze varianty',
];
$pageVars['pair'] = ['0' => 'Ne', '1' => 'Ano'];
if (findModule('products_suppliers') && !empty($pageVars['data']['id_supplier'])) {
$pageVars['products_of_suppliers'] = returnSQLResult('SELECT COUNT(*) FROM '.getTableName('products_of_suppliers')." pos WHERE pos.id_supplier='{$pageVars['data']['id_supplier']}'");
}
$vars['type'] = 'automatic_import';
$vars['body'] = $pageVars;
return $vars;
}
// protected function getData()
// {
// $data = parent::getData();
//
// $data['transformation'] = $this->prettyXml($data['transformation']);
//
// return $data;
// }
//
// function prettyXml($string)
// {
// $domxml = new DOMDocument('1.0');
// $domxml->preserveWhiteSpace = false;
// $domxml->formatOutput = true;
//
// /* @var $xml SimpleXMLElement */
// $domxml->loadXML($string);
// return $domxml->saveXML();
// }
public function handle()
{
$ID = $this->getID();
ini_set('memory_limit', '1024M');
$synchronize = getVal('synchronize');
$synchronize_try = getVal('synchronize_try');
if ((!empty($synchronize) || !empty($synchronize_try)) && !empty($ID)) {
// $errors = error_reporting(E_ALL|E_STRICT);
$import = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(\KupShop\AdminBundle\Util\AutomaticImport::class);
$import->setData($ID);
if (getVal('dumpXmlBefore') || getVal('dumpXmlAfter')) {
if (!$import->parseParams()) {
exit($import->error);
}
if (!$import->getSourceFile()) {
exit($import->error);
}
if (!$import->getXML()) {
exit($import->error);
}
if (getVal('dumpXmlBefore')) {
exit($import->dumpXML());
}
if (!$import->transformXML()) {
exit($import->error);
}
exit($import->dumpXML());
}
if (!$import->process(!empty($synchronize_try))) {
redirect('launch.php?s=automatic_import.php&acn=edit&refresh=parent&ID='.$ID.'&ErrStr='.urlencode("Chyba importu: {$import->error}"));
}
$import->deleteOldProducts();
$import->showUpdatedProducts();
// presmerovani
if (empty($synchronize_try)) {
$smarty = createSmarty(true, true);
$smarty->assign(Window::get_vars());
$smarty->assign([
'ID' => $this->getID(),
'import' => $import,
'view' => $this,
]);
$columns = $import->getDebugData();
$updatedProducts = array_filter($import->updatedCreatedProducts ?? [], function ($product) {
return $product['status'] != 'ignorován';
});
$smarty->assign(['updatedProducts' => $updatedProducts]);
$smarty->assign($columns);
$smarty->display('window/import.result.tpl');
if (in_array('import_error', $columns['columns'])) {
$number = 0;
foreach ($columns['products'] as $product) {
if (!empty($product['import_error'])) {
$number++;
}
}
writeDownActivity('Pozor: Auto. import - počet neúspěšně importovaných souborů:'.$number);
}
exit;
/*$ret = "";
$ret .= "Načteno {$import->stats['products']} produktů\\n";
$ret .= "Načteno {$import->stats['variations']} variant\\n";
$ret .= "Vytvořeno {$import->stats['products_created']} produktů\\n";
$ret .= "Vytvořeno {$import->stats['variations_created']} variant\\n";
$ret .= "Aktualizováno {$import->stats['products_updated']} produktů\\n";
$ret .= "Aktualizováno {$import->stats['variations_updated']} variant\\n";
$ret .= "Smazáno ".count($import->stats['deleted'])." starých produktů/variant\\n";
//$ret .= "Smazáno ".count($import->stats['variations_deleted'])." starých variant\\n";
redirect("launch.php?s=automatic_import.php&acn=edit&refresh=parent&ID=".$ID."&ErrStr=".urlencode($ret));*/
} else {
$smarty = createSmarty(true, true);
$smarty->assign(Frame::get_vars());
$smarty->assign([
'data' => $this->getData(),
'ID' => $this->getID(),
'import' => $import,
'view' => $this,
'all' => getVal('all'),
]);
$smarty->assign($import->getDebugData());
$smarty->display('window/automatic_import.dump.tpl');
exit;
}
// error_reporting($errors);
}
parent::handle();
}
public function handleUpdate()
{
$data = $this->getData();
$ID = $this->getID();
$acn = $this->getAction();
$SQL = parent::handleUpdate();
if ($SQL) {
if ($acn == 'add') {
$ID = sqlInsertID();
}
if (!empty($_FILES['source_file']) && is_uploaded_file($_FILES['source_file']['tmp_name'])) {
$data['local_file'] = $GLOBALS['cfg']['Path']['data'].'/tmp/autoimport_'.$ID;
if (!move_uploaded_file($_FILES['source_file']['tmp_name'], $data['local_file'])) {
$ErrStr = 'Nelze přesunout uploadovaný soubor.';
}
}
}
return $SQL;
}
public function handleDownload()
{
$ID = $this->getID();
$type = returnSqlResult('SELECT type
FROM '.getTableName('import')." s
WHERE s.id='{$ID}' ");
$file = $GLOBALS['cfg']['Path']['data'].'/tmp/autoimport_'.$ID;
if (!file_exists($file)) {
$this->returnError('Soubor neexistuje');
}
switch ($type) {
case AutomaticImport::TYPE_XML:
$contentType = 'application/pdf';
$extension = 'pdf';
break;
case AutomaticImport::TYPE_CSV:
$contentType = 'text/csv';
$extension = 'csv';
break;
case AutomaticImport::TYPE_XLS:
$contentType = 'application/vnd.ms-excel';
$extension = 'xls';
break;
default:
$contentType = 'application/octet-stream';
$extension = 'bin';
}
header("Content-type: {$contentType}");
header("Content-Disposition: attachment; filename=\"automatic_import_{$ID}.{$extension}\"");
readfile($file);
exit;
}
}
return AutomaticImports::class;

55
admin/barcode.php Normal file
View File

@@ -0,0 +1,55 @@
<?php
if (!class_exists(Picqer\Barcode\BarcodeGeneratorPNG::class)) {
// HACK superhack, ale jinak to nejde, je to kvuli kompatibilite, nekteri to volaji
// naprimo z /engine aby to bylo bez loginu pres admin
chdir(str_replace('engine/admin/barcode.php', '', $_SERVER['SCRIPT_FILENAME']));
if (file_exists('./config/config.php')) {
require_once './config/config.php';
} else {
require_once './include/config.php';
}
require_once './include/functions.php';
require_once './engine/web/common.php';
}
$type = 'int25';
if (!empty($_GET['type'])) {
$type = $_GET['type'];
}
if ($type == 'ean13') {
$_GET['oID'] = sprintf('%013d', intval($_GET['oID']));
}
$height = 60;
if (!empty($_GET['height'])) {
$height = $_GET['height'];
}
$size = $_GET['size'] ?? 1;
$show_value = ($_GET['showValue'] ?? '') !== 'false';
// Convert to BarcodeGenerator
$generator = new Picqer\Barcode\BarcodeGeneratorPNG();
switch ($type) {
case 'int25':
$type = $generator::TYPE_INTERLEAVED_2_5;
break;
case 'ean13':
$type = $generator::TYPE_EAN_13;
break;
case 'code39':
$type = $generator::TYPE_CODE_39;
break;
case 'code128':
$type = $generator::TYPE_CODE_128;
break;
}
$result = $generator->getBarcode($_GET['oID'], $type, $size + 1, $height);
header('Content-Type: image/png');
echo $result;

20
admin/board.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
global $cfg, $type;
use KupShop\AdminBundle\Util\AdminClassLocator;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
$type = getVal('type', null, 'index');
$className = $type;
$adminClassLocator = ServiceContainer::getService(AdminClassLocator::class);
$classPath = $adminClassLocator->getClassPath('board/board.'.$className.'.php');
if (file_exists($classPath)) {
$list = $adminClassLocator->createClass($classPath, $className);
$list->run();
} else {
$err = "Neexistující board {$type}";
throw new Exception('Neexistující board '.$type);
}

View File

@@ -0,0 +1,9 @@
<?php
// ##############################################################
$main_class = 'ExportOrdersBoard';
class ExportOrdersBoard extends Frame
{
protected $template = 'board/export_orders.tpl';
}

View File

@@ -0,0 +1,19 @@
<?php
// ##############################################################
$main_class = 'ExportProductsBoard';
class ExportProductsBoard extends Frame
{
protected $template = 'board/export_products.tpl';
public function handle()
{
if (getVal('Submit')) {
$export = new ExportProducts();
$export->getFile();
exit('Done');
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
// ##############################################################
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
$main_class = 'ExportSellingProducts';
class ExportSellingProducts extends Frame
{
protected $template = 'board/export_selling_products.tpl';
public function handle()
{
if (getVal('Submit')) {
$export = ServiceContainer::getService(\KupShop\AdminBundle\Util\Export\ExportProductsSelling::class);
$export->exportXLS();
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
use KupShop\AdminBundle\Util\Export\ExportUsers;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
class ExportUsersBoard extends Frame
{
protected $template = 'board/export_users.tpl';
public function handle()
{
if (getVal('Submit')) {
$export = ServiceContainer::getService(ExportUsers::class);
$export->exportXLSX();
}
}
}
return ExportUsersBoard::class;

View File

@@ -0,0 +1,88 @@
<?php
use KupShop\KupShopBundle\Context\DomainContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\OrderingBundle\Util\Order\OrderInfo;
use Query\Operator;
$main_class = 'IndexBoard';
class IndexBoard extends Frame
{
protected $template = 'board/index.tpl';
public function get_vars()
{
$vars = parent::get_vars();
$stats = [];
$today = new DateTime('today');
$todayRange = new \Range($today->format('Y-m-d 00:00:00'), $today->format('Y-m-d 23:59:59'));
$orders = sqlQueryBuilder()->select('COUNT(id)')
->from('orders')
->andWhere('status_storno=0')
->andWhere(Operator::between('date_created', $todayRange))
->andWhere(Operator::not(Operator::equals(['source' => OrderInfo::ORDER_SOURCE_RETURNS])));
$stats['today_orders'] = $orders->execute()->fetchOne();
$total_price = (findModule(Modules::CURRENCIES) ? 'total_price * currency_rate' : 'total_price');
$orders->select("SUM({$total_price})");
$stats['today_price'] = $orders->execute()->fetchOne();
$stats['unfinished_orders'] = returnSQLResult("SELECT COUNT(*) FROM orders WHERE status='0' AND status_storno='0'");
$stats['total_products'] = returnSQLResult('SELECT COUNT(*) FROM products');
$yesterday = (new DateTime('yesterday'))->format('Y-m-d H:i:s');
$stats['errors_critical'] = sqlQueryBuilder()->select('COUNT(*)')
->from('report_activities')
->where('date > :date')
->andWhere(Operator::equals(['severity' => 'error']))
->andWhere(Operator::not(Operator::equals(['type' => 'sync'])))
->setParameter('date', getAdminUser()['date_check_error'] ?? $yesterday)
->execute()->fetchColumn();
$stats['errors_sync'] = sqlQueryBuilder()->select('COUNT(*)')
->from('report_activities')
->where('date > :date')
->andWhere(Operator::equals(['severity' => 'error']))
->andWhere(Operator::equals(['type' => 'sync']))
->setParameter('date', getAdminUser()['date_check_error'] ?? $yesterday)
->execute()->fetchColumn();
$stats['errors_recommendation'] = sqlQueryBuilder()->select('COUNT(*)')
->from('report_activities')
->where('date > :date')
->andWhere(Operator::equals(['severity' => 'recommendation']))
->setParameter('date', $yesterday)
->execute()->fetchColumn();
$links = [];
$mainDomain = Contexts::get(DomainContext::class)->getSupported()[0];
$domain = join('.', array_slice(explode('.', $mainDomain), -2));
if (strpos($domain, 'kupshop.cz') !== false || strpos($domain, 'wpj.biz') !== false || strpos($domain, 'wpj.cloud') !== false || strpos($domain, 'wpjshop.cz') !== false) {
$domain = join('.', array_slice(explode('.', $mainDomain), -3));
}
$hash = md5(date('Y-m-d').'wpj_wpj');
$hash = base64_encode(json_encode(['url' => 'https://'.$domain, 'hash' => $hash]));
$links['klient'] = "https://klient.wpj.cz/list/{$hash}";
$vars['stats'] = $stats;
$vars['links'] = $links;
if (isAutoDeploy()) {
$vars['deploy_time'] = filemtime(__FILE__);
}
$vars['changelog_time'] = getAdminUser()['date_check_changelog'] ?? (new DateTime('yesterday'))->format('c');
return $vars;
}
}

View File

@@ -0,0 +1,178 @@
<?php
$main_class = 'usersImport';
class UsersImport extends Frame
{
use DatabaseCommunication;
protected $template = 'board/usersImport.tpl';
protected $errs = [];
protected $info = [];
protected $added_users = [];
public function get_vars()
{
$vars = parent::get_vars();
$vars['errs'] = $this->errs;
$vars['info'] = $this->info;
$vars['added_users'] = $this->added_users;
return $vars;
}
public function handle()
{
$try = getVal('Try');
$execute = getVal('Execute');
global $cfg;
if (!empty($execute) || (!empty($try))) {
if (!empty($_FILES['file']['tmp_name'])) {
$path = $cfg['Path']['data'].'tmp/users_import.xsl';
move_uploaded_file($_FILES['file']['tmp_name'], $path);
// Increase memory for large files
ini_set('memory_limit', '512M');
$import = new AutomaticImportTransform($path);
$users_array = $import->LoadBinfileAsArray();
/*
* A = jméno
* B = přijmení
* C = společnost
* D = email
* E = telefon
* F = ulice
* G = město
* H = země
* I = psč
* J = skupiny
* K = newsletter
* L = ICO
* M = DIC
* N = delivery name
* O = delivery surname
* P = delivery firm
* Q = delivery street
* R = delivery city
* S = delivery zip
* T = delivery_country
*/
$errs = [];
$added = 0;
$price_levels = sqlFetchAll(sqlQueryBuilder()->select('id, name')->from('price_levels')->execute(), ['id' => 'name']);
foreach (reset($users_array) as $index => $user) {
if ($index == 1) {
continue;
}
if (!empty($user['D'])) {
if (filter_var($user['D'], FILTER_VALIDATE_EMAIL)) {
$groups = [];
if (!empty($user['K'])) {
$groups = explode(';', str_replace(' ', '', $user['K']));
}
$fields = ['figure' => 'N'];
if (!empty($user['A'])) {
$fields['name'] = $user['A'];
}
if (!empty($user['B'])) {
$fields['surname'] = $user['B'];
}
if (!empty($user['C'])) {
$fields['firm'] = $user['C'];
}
if (!empty($user['E'])) {
$fields['phone'] = $user['E'];
}
if (!empty($user['F'])) {
$fields['street'] = $user['F'];
}
if (!empty($user['G'])) {
$fields['city'] = $user['G'];
}
if (!empty($user['H'])) {
$fields['zip'] = $user['H'];
}
if (!empty($user['I'])) {
$fields['state'] = $user['I'];
}
if (!empty($user['J'])) {
$fields['country'] = $user['J'];
}
if (!empty($user['L'])) {
$fields['get_news'] = ($user['L'] == 'ano') ? 'Y' : 'N';
}
if (!empty($user['M'])) {
$fields['ico'] = $user['M'];
}
if (!empty($user['N'])) {
$fields['dic'] = $user['N'];
}
if (!empty($user['O'])) {
$fields['delivery_name'] = $user['O'];
}
if (!empty($user['P'])) {
$fields['delivery_surname'] = $user['P'];
}
if (!empty($user['Q'])) {
$fields['delivery_firm'] = $user['Q'];
}
if (!empty($user['R'])) {
$fields['delivery_street'] = $user['R'];
}
if (!empty($user['S'])) {
$fields['delivery_city'] = $user['S'];
}
if (!empty($user['T'])) {
$fields['delivery_zip'] = $user['T'];
}
if (!empty($user['U'])) {
$fields['delivery_state'] = $user['U'];
}
if (!empty($user['V'])) {
$fields['delivery_country'] = $user['V'];
}
$price_level = null;
if (!empty($user['W'])) { // cenová hladina
$price_level = array_search(trim($user['W']), $price_levels);
}
if (empty($try)) {
$confirmed = false;
if (getVal('newsletter_confirm')) {
$confirmed = true;
}
$user['id'] = addUserEmail($user['D'], $groups, $fields, $confirmed);
if ($price_level) {
sqlQuery("REPLACE INTO users_dealer_price_level (id_user, id_price_level)
VALUES ('{$user['id']}', '{$price_level}')");
}
} else {
$fields['email'] = $user['D'];
$fields['groups'] = $groups;
$fields['price_level'] = ($price_level ? $price_level.' - '.$user['W'] : '');
$this->added_users[] = $fields;
}
++$added;
} else {
$errs[$index] = "Nevalidní email {$user['D']}";
}
} else {
$errs[$index] = 'Prázdný email - uživatel nemůže být přidán';
}
}
$info['test'] = !empty($try) ? 1 : 2;
$info['added'] = $added;
$this->info = $info;
$this->errs = $errs;
}
}
}
}

View File

@@ -0,0 +1,28 @@
<?php
$main_class = 'usersUnsubscribe';
class usersUnsubscribe extends Frame
{
use DatabaseCommunication;
protected $template = 'board/usersUnsubscribe.tpl';
public function handle()
{
$emails = getVal('emails');
$emails = array_filter(preg_split('/[\s;,]/i', mb_strtolower($emails)));
if ($emails) {
$count = sqlQueryBuilder()->update('users')
->set('get_news', '"N"')
->set('date_updated', 'NOW()')
->set('date_unsubscribe', 'NOW()')
->where(Query\Operator::inStringArray($emails, 'email'))
->execute();
$this->returnOK("Odhlášeno {$count} uživatelů");
}
}
}

47
admin/checktimeout.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
class Checktimeout extends Window
{
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
if (getVal('frame')) {
$this->setTemplate('window/checktimeoutFrame.tpl');
} else {
$this->setTemplate('window/checktimeoutWindow.tpl');
}
$session = ServiceContainer::getService('session');
$pageVars['expiry'] = $session->get('_expiry');
$pageVars['time'] = time();
$vars['body'] = $pageVars;
return $vars;
}
public function handle()
{
}
public function hasRights($name = null)
{
switch ($name) {
case Window::RIGHT_SAVE:
case Window::RIGHT_DELETE:
case Window::RIGHT_DUPLICATE:
return false;
default:
return parent::hasRights($name);
}
}
}
$checktimeout = new Checktimeout();
$checktimeout->run();

View 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);
}
}

View 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));
}
}

View 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']));
}
}

View 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));
}
}

View 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('&#039;', '&apos;', 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).'"');
}
}

View 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));
}
}

View 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;
}
}

View 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}");
}
}

View 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);
}
}

View 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);
}
}
}

View 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!');
}
}

View 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
View 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;
}
}

View 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'),
]);
}
}

View File

View 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';
}
}
}

View 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_',
],
],
];
}

View 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();
}
}

View 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']);
}

View 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);
}

View 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;
}
}

View 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;
}
}

View File

@@ -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;
}
}

View 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 '';
}
}

View File

@@ -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='
),
]);
}

View File

@@ -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++;
}

View 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;
}
}

View 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
}

View 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);
}

View 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++;
}

View File

@@ -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);
}
}

View 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
}

View 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;
}

View 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());
}

View 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);
}

View File

@@ -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);
}

549
admin/cleaning.php Normal file
View File

@@ -0,0 +1,549 @@
<?php
use KupShop\AdminBundle\Util\Script\ScriptLocator;
use KupShop\CatalogBundle\Search\FulltextInterface;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Event\CronEvent;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
$main_class = 'Cleaning';
class Cleaning extends Window
{
public $success = 0;
public $failed = 0;
// Cache
public function handleCacheImages()
{
global $cfg;
foreach (glob($cfg['Path']['data'].'tmp/[0-9]*/*/*.*') as $file) {
if (@unlink($file)) {
$this->success++;
} else {
$this->failed++;
}
}
$path = realpath($cfg['Path']['data'].'tmp/');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
$folders = [];
foreach ($objects as $path => $object) {
$folder_name = substr($path, strrpos($path, '/') + 1, strlen($path));
if (ctype_digit($folder_name) && strlen($folder_name) == 1) {
$folders[] = $path;
}
}
$folders = array_reverse($folders);
foreach ($folders as $folder) {
@rmdir($folder);
}
}
public function handleImageVersionUpgrade()
{
$dbcfg = Settings::getDefault();
$lastImageVersion = $dbcfg->loadValue('image_version');
$dbcfg->saveValue('image_version', $lastImageVersion ? $lastImageVersion + 1 : 2);
$dbcfg->clearCache();
$this->success++;
}
public function handleCacheSections()
{
clearCache('sections', true);
$this->success++;
}
public function handleCacheRuntime()
{
clearCache('', true);
$this->success++;
}
public function handleCacheTemplates()
{
global $cfg;
foreach (glob($cfg['Path']['data'].'tmp/templates/*') as $file) {
if (@unlink($file)) {
$this->success++;
} else {
$this->failed++;
}
}
}
public function handleCacheFeeds()
{
global $cfg;
foreach (glob($cfg['Path']['data'].'tmp/feed_*_*') as $file) {
if (@unlink($file)) {
$this->success++;
} else {
$this->failed++;
}
}
}
public function handleCacheSitemap()
{
$cfg = Config::get();
foreach (glob($cfg['Path']['data'].'tmp/sitemap*') as $file) {
if (@unlink($file)) {
$this->success++;
} else {
$this->failed++;
}
}
}
public function handleCacheStatic()
{
global $cfg;
foreach (glob($cfg['Path']['data'].'tmp/cache/*') as $file) {
if (@unlink($file)) {
$this->success++;
} else {
$this->failed++;
}
}
$this->handleCacheRuntime();
}
// Photos
public function getImagesUnused()
{
$SQL = sqlQuery('SELECT id
FROM photos p
LEFT JOIN photos_products_relation ppr ON p.id = ppr.id_photo
LEFT JOIN photos_articles_relation ppa ON p.id = ppa.id_photo
LEFT JOIN photos_menu_relation par ON p.id = par.id_photo
LEFT JOIN photos_blocks_relation blo ON p.id = blo.id_photo
LEFT JOIN photos_blocks_new_relation bln ON p.id = bln.id_photo
LEFT JOIN photos_sections_relation psr ON p.id = psr.id_photo
WHERE ppr.id_product IS NULL AND ppa.id_art IS NULL AND par.id_menu IS NULL
AND blo.id_block IS NULL AND bln.id_block IS NULL AND psr.id_section IS NULL');
$files = sqlFetchAll($SQL);
return $files;
}
public function handleCacheImagesType()
{
if (($type = getVal('type')) !== null) {
$this->clearImageTypeCache($type);
}
}
// clear cache only of defined photo type
public function clearImageTypeCache($type)
{
$cfg = Config::get();
if (!isset($cfg['Photo']['id_to_type'][$type])) {
return;
}
foreach (glob($cfg['Path']['data'].'tmp/'.$type.'/*/*.*') as $file) {
if (@unlink($file)) {
$this->success++;
} else {
$this->failed++;
}
}
$path = realpath($cfg['Path']['data'].'tmp/'.$type.'/');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
$folders = [];
foreach ($objects as $path => $object) {
$folder_name = substr($path, strrpos($path, '/') + 1, strlen($path));
if (ctype_digit($folder_name) && strlen($folder_name) == 1) {
$folders[] = $path;
}
}
$folders = array_reverse($folders);
foreach ($folders as $folder) {
@rmdir($folder);
}
}
public function handleImagesUnused()
{
$files = $this->getImagesUnused();
$img = new Photos('product');
foreach ($files as $file) {
if ($img->erasePhoto($file['id'])) {
$this->success++;
} else {
$this->failed++;
}
}
}
public function getImagesFiles()
{
global $cfg;
$dir = $cfg['Path']['photos'];
$dirIterator = new RecursiveDirectoryIterator($dir, FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_PATHNAME | FilesystemIterator::SKIP_DOTS);
$dirIterator = new RecursiveCallbackFilterIterator($dirIterator, function ($current, $key, $iterator) use ($dir) {
// Avoid sliders folder
if ($key === $dir.'sliders') {
return false;
}
return true;
});
$files = iterator_to_array(new RecursiveIteratorIterator($dirIterator));
$db_images = sqlQuery('SELECT CONCAT(:dir, source, image_2) AS path FROM `photos`', ['dir' => $dir]);
$db_images = sqlFetchAll($db_images, ['path' => 'path']);
$files = array_filter($files, function ($file) use ($db_images) {
return !isset($db_images[$file]);
});
return $files;
}
public function handleImagesFiles()
{
$files = $this->getImagesFiles();
foreach ($files as $file) {
if (@unlink($file)) {
$this->success++;
} else {
$this->failed++;
}
}
}
public function handleImagesCorrupted()
{
global $cfg;
$db_images = sqlQuery('SELECT CONCAT(:dir, source, image_2) AS path, id FROM `photos`', ['dir' => $cfg['Path']['photos']]);
$corrupted_id = [];
foreach ($db_images as $file) {
if (!file_exists($file['path']) || filesize($file['path']) <= 0/* && wpj_open_image($source) */) {
$corrupted_id[] = $file['id'];
$this->success++;
}
}
if (!empty($corrupted_id)) {
sqlQuery('DELETE FROM `photos` WHERE id IN ('.join(', ', $corrupted_id).')');
}
}
public function getImagesMissingMain()
{
return sqlFetchAll(sqlQuery('SELECT id_product FROM photos_products_relation GROUP BY id_product HAVING MAX(show_in_lead)=\'N\''), 'id_product');
}
public function handleImagesMissingMain()
{
$IDs = $this->getImagesMissingMain();
foreach ($IDs as $id_product => $_) {
Photos::checkLeadPhoto('photos_products_relation', 'id_product', $id_product);
}
}
// Products
public function handleProductsAll()
{
$this->success = $this->deleteSQL('products', ['1' => '1']);
}
public function handleProductsAnnotation()
{
foreach (sqlQuery('SELECT id, short_descr FROM products') as $product) {
$product['short_descr'] = trim(html_entity_decode(strip_tags($product['short_descr'])));
$this->success += $this->updateSQL('products', $product, ['id' => $product['id']], ['id']);
}
if (findModule(\Modules::TRANSLATIONS)) {
foreach (sqlQuery('SELECT id, short_descr FROM products_translations') as $product) {
$product['short_descr'] = trim(html_entity_decode(strip_tags($product['short_descr'])));
$this->success += $this->updateSQL('products_translations', $product, ['id' => $product['id']], ['id']);
}
}
}
public function handleProductsDescriptions()
{
foreach (sqlQuery('SELECT id, short_descr, long_descr FROM products') as $product) {
$product['short_descr'] = trim(html_entity_decode(strip_tags($product['short_descr'])));
$product['long_descr'] = trim(html_entity_decode(strip_tags($product['long_descr'])));
$this->success += $this->updateSQL('products', $product, ['id' => $product['id']], ['id']);
}
}
// Parameters
public function handleParameters()
{
$this->success = $this->deleteSQL('parameters', ['1' => '1']);
}
public function handleParametersValues()
{
$this->success = $this->deleteSQL('parameters_list', ['1' => '1']);
}
// Sections
public function handleSections()
{
$this->success = $this->deleteSQL('sections', ['(id = 0)' => 'FALSE']);
clearCache('sections', true);
}
public function handleSectionsEmpty()
{
$SQL = sqlQuery('DELETE s FROM sections s
LEFT JOIN products_in_sections ps ON ps.id_section = s.id
LEFT JOIN sections_relation sr ON sr.id_topsection = s.id
WHERE ps.id_product IS NULL AND sr.id_section IS NULL
AND s.id <> 0 ');
$this->success = sqlNumRows($SQL);
MenuSectionTree::invalidateCache();
clearCache('sections', true);
}
// Producers
public function handleProducers()
{
$this->success = $this->deleteSQL('producers', ['1' => '1']);
}
// Orders
public function handleOrders()
{
$this->success = $this->deleteSQL('orders', ['1' => '1']);
}
// Articles
public function handleArticles()
{
$this->success = $this->deleteSQL('articles', ['1' => '1']);
}
// Users
public function handleUsers()
{
$this->success = $this->deleteSQL('users', ['1' => '1']);
}
// Variations
public function handleVariationsDuplicates()
{
$duplicates = sqlQuery('SELECT t.id_product, GROUP_CONCAT(t.id ORDER BY t.id SEPARATOR \',\') id_variations
FROM (
SELECT pv.id, pv.id_product, GROUP_CONCAT(pvc.id_value ORDER BY pvc.id_value SEPARATOR \'-\') vals
FROM products_variations pv
JOIN products_variations_combination pvc ON pv.id = pvc.id_variation
GROUP BY pv.id
) AS t
GROUP BY t.id_product, t.vals
HAVING COUNT(*) > 1');
foreach ($duplicates as $duplicate) {
$variations = explode(',', $duplicate['id_variations']);
array_shift($variations);
$this->success += sqlQueryBuilder()->delete('products_variations')->where(\Query\Operator::inIntArray($variations, 'id'))->execute();
}
}
public function handleRegenerateVariationsTitles()
{
Variations::updateTitle();
}
public function handleFulltextUpdate()
{
$fulltext = ServiceContainer::getService(FulltextInterface::class);
$contextManager = ServiceContainer::getService(ContextManager::class);
$languages = $fulltext->getFulltextLanguages();
if ($lang = getVal('fulltext_language')) {
$languages = [$lang => $languages[$lang]];
}
foreach ($languages as $language => $_) {
$contextManager->activateContexts([LanguageContext::class => $language], function () use ($fulltext) {
$fulltext->updateIndex(getVal('fulltext_index'));
$this->success++;
});
}
}
// Reviews
public function handleReviewsImport()
{
$reviews = ServiceContainer::getService(\KupShop\CatalogBundle\Util\ReviewsUtil::class);
$this->success = $reviews->importReviews();
if ($reviews->getError()) {
$this->returnError($reviews->getError());
}
}
public function handleReviewsAutoConfirm()
{
$reviews = ServiceContainer::getService(\KupShop\CatalogBundle\Util\ReviewsUtil::class);
$this->success = $reviews->autoConfirm();
}
public function handleCronFrequent()
{
$this->handleCron('FREQUENT');
}
public function handleCronNormal()
{
$this->handleCron('NORMAL');
}
public function handleCronExpensive()
{
$this->handleCron('EXPENSIVE');
}
protected function handleCron(string $type)
{
/** @var \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher */
$dispatcher = ServiceContainer::getService('event_dispatcher');
$event = new CronEvent($type);
$dispatcher->dispatch($event, constant('KupShop\KupShopBundle\Event\CronEvent::RUN_'.$type));
}
public function handleRunScript()
{
$script = getVal('script');
if ($script) {
ServiceContainer::getService(ScriptLocator::class)->runScript($script, getVal('script_parameters'));
exit("\n============ DONE ==============");
}
}
public function getCounts()
{
global $cfg;
$counts = [];
// Cache
$counts['cacheImages'] = ['count' => count(glob($cfg['Path']['data'].'tmp/*/*/*.*'))];
$counts['cacheSections'] = ['count' => 1];
$counts['cacheTemplates'] = ['count' => count(glob($cfg['Path']['data'].'tmp/templates/*'))];
$counts['cacheStatic'] = ['count' => count(glob($cfg['Path']['data'].'tmp/cache/*'))];
// Photos
$files = $this->getImagesUnused();
$counts['imagesUnused'] = ['count' => count($files), 'links' => array_map(function ($file) {
return "javascript:nw('photos', {$file['id']})";
}, array_slice($files, 0, 10, true) + array_slice($files, -10, 10, true))];
$files = $this->getImagesFiles();
$counts['imagesFiles'] = ['count' => count($files), 'links' => array_slice($files, 0, 10, true) + array_slice($files, -10, 10, true)];
$images = $this->getImagesMissingMain();
$counts['imagesMissingMain'] = ['count' => count($images)];
return $counts;
}
public function get_vars()
{
$vars = parent::get_vars();
if (getVal('calculate')) {
$vars['counts'] = $this->getCounts();
}
$vars['scripts'] = ServiceContainer::getService(ScriptLocator::class)->getScripts();
$indexes = ServiceContainer::getService(FulltextInterface::class)->getIndexTypes();
$vars['fulltext']['indexes'] = array_combine($indexes, $indexes);
return $vars;
}
public function handle()
{
ini_set('max_execution_time', 600);
ini_set('memory_limit', '512M');
parent::handle();
if (getVal('acn') != 'edit' && getVal('acn') != 'add') {
$this->returnOK("Upraveno {$this->success} položek. Selhalo {$this->failed} položek");
}
}
// Do not try to handle exceptions - hides some DB errors
public function handleException($e)
{
throw $e;
}
public function hasRights($name = null)
{
switch ($name) {
case Window::RIGHT_SAVE:
case Window::RIGHT_DELETE:
case Window::RIGHT_DUPLICATE:
return false;
default:
return parent::hasRights($name);
}
}
public function handleDiscounts()
{
$SQL = sqlQuery('DELETE FROM discounts
WHERE condition_type != \'generate_coupon\'');
$this->success = sqlNumRows($SQL);
}
public function handleAllDiscounts()
{
$this->success = $this->deleteSQL('discounts', ['1' => '1']);
}
// Variation labels
public function handleLabels()
{
$this->success = $this->deleteSQL('products_variations_choices_labels', ['1' => '1']);
}
public function handleLabelsEmpty()
{
$SQL = sqlQuery('DELETE vl FROM products_variations_choices_labels vl
LEFT JOIN products_variations_combination pvc ON pvc.id_label = vl.id
WHERE pvc.id_variation IS NULL');
$this->success = sqlNumRows($SQL);
}
}

97
admin/common.php Normal file
View File

@@ -0,0 +1,97 @@
<?php
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
header('Cache-Control: no-cache');
header('Pragma: no-cache');
header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
// //////////////////// SOUBOR COMMON.PHP
// zacit pocitat cas provadeni skriptu
setStartTime();
// ################################################################
// SESSION
// ################################################################
$session = ServiceContainer::getService('session');
$session->start();
// ################################################################
// ERROR REPORTING
// ################################################################
set_error_handler('error_handler');
// ################################################################
// URCENI, KTERE STRANKY JSOU VOLNE PRISTUPNE
// ################################################################
if (!isset($_GET['s'])) {
$_GET['s'] = null;
}
// ################################################################
// jestlize se jedna o verejnou stranku, nevyzadovat zalogovanisada
if (!isset($publicArea)) {
$legacyAdminCredentials = ServiceContainer::getService(\KupShop\AdminBundle\Util\LegacyAdminCredentials::class);
$legacyAdminCredentials->setAdminGlobalVars(function () {
redirect('index.php?error=4&url='.urlencode($_SERVER['REQUEST_URI']));
});
if (isSuperuser()) {
ini_set('display_errors', '1');
}
}
// ################################################################
// SMARTY TEMPLATES
// ################################################################
$ctrl = [];
$ctrl['admin'] = true;
$ctrl['logged'] = false;
$ctrl['currUrl'] = [
'Abs' => $cfg['Addr']['full'].$_SERVER['REQUEST_URI'],
'Rel' => $_SERVER['REQUEST_URI'],
];
$userContext = ServiceContainer::getService(UserContext::class);
$userContext->forceEmpty();
$txt_str = [];
// ################################################################
// VOLBA JAZYKA
// ################################################################
loadLanguage('base');
// ################################################################
// ZISKANI NASTAVENI Z DATABAZE
// ################################################################
$dbcfg = Settings::getDefault();
// prevedeni aktivnich modulu pro SMARTY
$cfg['module'] = [];
foreach ($cfg['Modules'] as $index => $module) {
if (is_numeric($index)) {
$cfg['module'][$module] = true;
} else {
$cfg['module'][$index] = true;
}
}
if (findModule('currencies')) {
$currencyContext = ServiceContainer::getService(CurrencyContext::class);
$currencyContext->activate($currencyContext->getDefaultId());
if (empty($ctrl['currency'])) {
$ctrl['currency'] = $dbcfg['currency'];
}
}

7
admin/connection.php Normal file
View File

@@ -0,0 +1,7 @@
<?php
// pripojeni k databazi
$cfg['Connection']['link'] = sqlConnect($cfg['Connection']['host'],
$cfg['Connection']['user'],
$cfg['Connection']['password'],
$cfg['Connection']['database']);

347
admin/dbbackup.php Normal file
View File

@@ -0,0 +1,347 @@
<?php
ini_set('memory_limit', '5G');
global $cfg;
if (!findRight('OTH_BACKUP_ADD') && !findRight('OTH_BACKUP_EDIT') && !findRight('OTH_BACKUP_ERASE')) {
redirect('launch.php?s=error.php&id=1');
}
$acn = getVal('acn');
$dbBackup = getVal('dbBackup');
if (empty($acn)) {
$acn = 'show';
}
set_time_limit(6000);
ignore_user_abort(true);
if ($acn == 'do' && !empty($dbBackup)) {
$do = getVal('do');
if ($do == 'erase') {
if (!findRight('OTH_BACKUP_ERASE')) {
redirect('launch.php?s=error.php&id=1');
}
// funkce na ukladani zalohy do souboru
function eraseBackup($filename, &$ErrStr)
{
global $cfg;
if (@unlink($cfg['Path']['db_backup'].$filename)) {
$ErrStr = 'Záloha databáze byla odstraněna.';
return true;
} else {
$ErrStr = 'Stala se chyba při odstraňování databáze - nepodařilo se smazat soubor.';
return false;
}
}
if (file_exists($cfg['Path']['db_backup'].$dbBackup)) {
// pokusit se poprve smazat DB zalohu
if (!eraseBackup($dbBackup, $ErrStr)) {
// snazi se napravit chybu
@chmod($cfg['Path']['db_backup'], octdec(777));
// snazi se napravit chybu
@chmod($cfg['Path']['db_backup'].$dbBackup, octdec(777));
if (!eraseBackup($dbBackup, $ErrStr)) {
// zalogovat chybu
logError(__FILE__, __LINE__, 'Chyba odstraneni zalohy databaze: '.$cfg['Path']['db_backup'].$dbBackup);
}
} else {
writeDownActivity('záloha DB - příkaz smazat zálohu '.$dbBackup);
}
} else {
$ErrStr = 'Požadovaný soubor se zálohou databáze nebyl nalezen.';
}
redirect('launch.php?s=list.php&type=dbbackup&ErrStr='.urlencode($ErrStr));
} elseif ($do == 'restore') {
if (!findRight('OTH_BACKUP_REFRESH') || isLive()) {
redirect('launch.php?s=error.php&id=1');
}
set_time_limit(0);
ob_implicit_flush(1);
while (ob_get_level()) {
ob_end_clean();
}
echo 'Obnovuji zálohu databáze...';
$crlf = "\r\n";
$lines = iterateBzipLines($cfg['Path']['db_backup'].$dbBackup);
$sql = [];
$next = true;
$count = 0;
foreach ($lines as $line) {
$count++;
if ($count >= 1000) {
$count = 0;
echo '.';
}
$wrow = trim($line);
if (substr($wrow, 0, 1) == '#') {
$wrow = $line = '';
}
if (substr($wrow, 0, 2) == '--') {
$wrow = $line = '';
}
if ($next) {
$sql[] = $line;
} else {
$sql[count($sql) - 1] .= $line;
}
if (substr($wrow, -1) == ';') {
$next = true;
} else {
$next = false;
}
}
// delete all tables
$tables = sqlQuery('SHOW TABLES')->fetchAll();
if ($tables) {
$tables = array_map(function ($value) {
return reset($value);
}, $tables);
sqlQuery('SET FOREIGN_KEY_CHECKS=0;');
foreach ($tables as $table) {
sqlQuery("DROP TABLE `{$table}`");
}
sqlQuery('SET FOREIGN_KEY_CHECKS=1;');
}
$errNo = 0;
$errStr = '';
foreach ($sql as $query) {
$count++;
if ($count >= 1000) {
$count = 0;
echo '.';
}
$query = trim($query);
if ($query) {
$SQL = sqlQuery($query);
if (!$SQL) {
$errNo++;
$errStr .= $query;
} else {
$SQL->free();
}
}
}
if ($errNo == 0) {
$ErrStr = 'Databáze byla obnovena ze zálohy.';
} else {
// zalogovat chybu
logError(__FILE__,
__LINE__,
'Chyba obnovy zalohy databaze: '.
$cfg['Path']['db_backup'].$dbBackup."\r\nchybných SQL příkazů: ".$errNo);
$ErrStr = 'Vyskytly se chyby při ukládání. Celkem chybných SQL příkazů: '.$errNo;
}
writeDownActivity('záloha DB - příkaz obnovit zálohu '.$dbBackup);
redirect('launch.php?s=list.php&type=dbbackup&ErrStr='.urlencode($ErrStr));
} elseif ($do = 'rename') {
$newName = getVal('new_name');
if ($newName) {
$newName = createScriptURL_Text($newName);
preg_match('/.sql(.bz2)?/i', $dbBackup, $matches);
$ext = $matches[0];
rename($cfg['Path']['db_backup'].$dbBackup,
$cfg['Path']['db_backup'].$newName.$ext);
$ErrStr = 'Záloha byla přejmenována';
redirect('launch.php?s=list.php&type=dbbackup&ErrStr='.urlencode($ErrStr));
}
}
}
// funkce na ukladani zalohy do souboru
function saveBackup($filename, &$ErrStr)
{
global $cfg;
$fp = bzopen($cfg['Path']['db_backup'].$filename, 'w');
if ($fp) {
return $fp;
} else {
$ErrStr = 'Chyba při ukládání do souboru.';
return null;
}
}
if ($acn == 'add') {
if (!findRight('OTH_BACKUP_ADD')) {
redirect('launch.php?s=error.php&id=1');
}
ini_set('display_errors', '1');
$filename = getVal('name');
if (!$filename) {
if (empty($return)) {
$filename = 'db'.date('Y-m-d_H-i-s').'.sql.bz2';
} elseif ($return == 'logout') {
$filename = 'logout_backup.sql.bz2';
}
} else {
$filename = createScriptURL_Text($filename).'.sql.bz2';
}
// pokusit se poprve ulozit DB zalohu
$ErrStr = null;
$fp = saveBackup($filename, $ErrStr);
if (!$fp) {
// snazi se napravit chybu
@chmod($cfg['Path']['db_backup'], octdec(777));
// snazi se napravit chybu
@chmod($cfg['Path']['db_backup'].$dbBackup, octdec(777));
$fp = saveBackup($filename, $ErrStr);
if (!$fp) {
// zalogovat chybu
logError(__FILE__, __LINE__, 'Chyba ukladani zalohy databaze: '.$cfg['Path']['db_backup'].$filename);
return false;
}
}
$params = [
'compress' => Ifsnop\Mysqldump\Mysqldump::BZIP2,
'add-drop-table' => true,
'single-transaction' => true,
'disable-foreign-keys-check' => true,
'add-locks' => false,
'lock-tables' => false,
'skip-triggers' => true,
];
$dump = new Ifsnop\Mysqldump\Mysqldump(
"mysql:host={$cfg['Connection']['host']};dbname={$cfg['Connection']['database']}",
$cfg['Connection']['user'],
$cfg['Connection']['password'],
$params
);
try {
// Prepare blank backup file
$filename = realpath($cfg['Path']['db_backup']).'/'.$filename;
unlink($filename);
// prepare for streaming
set_time_limit(0);
ob_implicit_flush(1);
while (ob_get_level()) {
ob_end_clean();
}
$dump->setInfoHook(function ($type, $data) {
if (isSuperuser()) {
echo "<br>{$data['name']}: {$data['rowCount']}";
} else {
echo '.';
}
});
echo 'Vytvářím zálohu...';
$dump->start($filename);
$ErrStr .= 'Databáze byla v pořádku uložena.';
} catch (Exception $e) {
$ErrStr .= 'Chyba při ukládání do souboru: '.$e->getMessage();
}
if (empty($return)) {
redirect('launch.php?s=list.php&type=dbbackup&ErrStr='.urlencode($ErrStr));
} elseif ($return == 'logout') {
redirect('launch.php?s=logout.php');
}
}
// download db backup
if ($acn == 'download') {
$filename = getVal('file');
if ($filename) {
downloadBackup($filename);
}
}
// upload db backup for wpjadmin
if ($acn == 'upload' && isSuperuser()) {
$file = $_FILES['upload_db'];
if ($file) {
if ($file['type'] == 'application/x-bzip' || pathinfo($file['name'], PATHINFO_EXTENSION) == 'bz2') {
uploadBackup($file);
} else {
$ErrStr = "Nepodporovaný formát {$file['type']}!";
redirect('launch.php?s=list.php&type=dbbackup&ErrStr='.urlencode($ErrStr));
}
}
}
function uploadBackup($file)
{
$cfg = \KupShop\KupShopBundle\Config::get();
$targetLocation = $cfg['Path']['db_backup'].$file['name'];
if (move_uploaded_file($file['tmp_name'], $targetLocation)) {
$ErrStr = 'Záloha databáze byla nahrána';
redirect('launch.php?s=list.php&type=dbbackup&ErrStr='.urlencode($ErrStr));
}
}
function downloadBackup($filename)
{
$cfg = \KupShop\KupShopBundle\Config::get();
$file = $cfg['Path']['db_backup'].$filename;
header('Content-Description: File Transfer');
header('Content-Type: application/x-bzip');
header('Content-Disposition: attachment; filename='.basename($file).'');
readfile($file);
exit;
}
function iterateBzipLines($file)
{
$fp = bzopen($file, 'r');
$data = '';
while (!feof($fp)) {
$data .= bzread($fp, 4096);
$row = preg_split("/(\r\n|\n)/", $data);
$lines = count($row);
foreach ($row as $index => $line) {
// Detect last row
if ($index == $lines - 1) {
$data = $line;
break;
}
yield $line;
}
}
yield $data;
bzclose($fp);
}

219
admin/deliveryDelivery.php Normal file
View File

@@ -0,0 +1,219 @@
<?php
$main_class = 'DeliveryTypesDelivery';
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\CountryContext;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
class DeliveryTypesDelivery extends Window
{
protected $tableName = 'delivery_type_delivery';
/** @var CurrencyContext */
private $currencyContext;
private $countryContext;
private $contextManager;
private $delivery;
protected $required = ['price' => true];
public function __construct()
{
$this->currencyContext = ServiceContainer::getService(CurrencyContext::class);
$this->countryContext = ServiceContainer::getService(CountryContext::class);
$this->contextManager = ServiceContainer::getService(ContextManager::class);
}
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$vat = getAdminVat()['value'];
$dbcfg = Settings::getDefault();
$pageVars['data']['priceWithVat'] = $dbcfg['prod_prefer_price_vat'] == 'Y' || $dbcfg['prod_prefer_price_vat'] == 'F';
if (isset($pageVars['data']) && !empty($pageVars['data']['price']) && $pageVars['data']['priceWithVat']) {
$pageVars['data']['price'] = toDecimal($pageVars['data']['price'])->mul(toDecimal(1 + ($vat / 100)));
}
if (!empty($pageVars['data']['price_registered'])) {
$pageVars['data']['price_registered'] *= 1 + ($vat / 100);
}
if (!empty($pageVars['data']['countries'])) {
$pageVars['data']['countries'] = json_decode($pageVars['data']['countries']);
}
if (findModule('delivery_pricelist')) {
$pageVars['deliveryPricelists'] = $this->getDeliveryPricelists();
}
$pageVars['data']['currencies'] = $this->currencyContext->getAll();
if ($this->getAction() == 'add') {
$pageVars['data']['currency'] = $this->currencyContext->getDefaultId();
}
$pageVars['data']['template'] = $this->getDeliveryObject()->getAdminWindowTemplate();
$pageVars['data']['custom_data'] = $this->getCustomData();
$vars['body'] = $pageVars;
return $vars;
}
private function getDeliveryPricelists()
{
/** @var \Doctrine\ORM\EntityManager $em */
$em = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService('doctrine.orm.entity_manager');
$repository = $em->getRepository(\KupShop\DeliveryPriceListBundle\Entity\PriceList::class);
return $repository->findAll();
}
protected function getObject()
{
$data = parent::getObject();
$data['photo_array'] = $this->getDeliveryObject()->getPhoto();
return $data;
}
public function getData()
{
global $cfg;
$data = parent::getData();
if (getVal('Submit')) {
$data['price'] = $this->prepareVatPrice($data['price']);
$data['price_registered'] = $this->prepareVatPrice($data['price_registered']);
if (!empty($data['price_buy'])) {
$data['price_buy'] = $this->prepareVatPrice($data['price_buy']);
}
if (!empty($data['countries']) && count(array_diff(array_keys($this->countryContext->getAll()), $data['countries'])) != 0) {
$data['countries'] = json_encode($data['countries']);
} else {
$data['countries'] = null;
}
if ($widgetOptions = $data['custom_data']['widget_options'] ?? false) {
if (is_array($widgetOptions)) {
$data['custom_data']['widget_options'] = $widgetOptions;
} else {
$data['custom_data']['widget_options'] = json_decode($widgetOptions, true);
if (json_last_error()) {
$this->returnError(sprintf(
'%s: %s',
translate('widgetOptions', 'deliveryDelivery', true, true),
json_last_error_msg(),
));
}
}
} else {
unset($data['custom_data']['widget_options']);
}
if (empty($data['custom_data']['users_groups'])) {
unset($data['custom_data']['users_groups_invert']);
}
}
$delivery = Delivery::getClass($data['class'] ?? null);
$custom_data = $delivery->processAdminWindowData($data['custom_data'] ?? []);
$oldCustomData = $this->getCustomData();
if (isset($oldCustomData['restrictions'])) {
$custom_data['restrictions'] = $oldCustomData['restrictions']; // preserve restrictions - already saved in DeliveryRestrictions tab
}
if (isset($oldCustomData['balikobot'])) {
$custom_data['balikobot'] = $oldCustomData['balikobot']; // preserve balikobot - already saved in BalikobotDeliveryTab
}
$this->setCustomData($custom_data);
return $data;
}
public function handleUpdate()
{
$data = $this->getData();
$SQL = parent::handleUpdate();
clearCache('freeDelivery_', true);
if (findModule('delivery_pricelist')) {
// Pricelist id update
if ($SQL) {
if (!empty($data['pricelist']['id_pricelist'])) {
$pricelistId = $data['pricelist']['id_pricelist'];
if ($pricelistId == 'null') {
$pricelistId = null;
}
$this->updateSQL($this->getTableName(), ['id_pricelist' => $pricelistId], ['id' => $this->getID()]);
}
}
}
// Add photo
$img = new Photos('delivery');
$img->newImage($this->getID());
if (!empty($_FILES['photo']['name'])) {
$img->uploadImage($_FILES['photo']);
if ($img->checkFileType()) {
$img->insertImageIntoDB();
} else {
$this->addError(getTextString('producers', 'errorBadPhoto'));
}
}
// Clear delivery thumbnail
$img->clearThumbnails([9]);
return $SQL;
}
public function handleDelete()
{
// Delete photo
$img = new Photos('delivery');
$img->newImage($this->getID());
$img->deletePhoto(false);
parent::handleDelete();
}
public function handleErasephoto()
{
// ########################################################################
$img = new Photos('delivery');
$img->newImage($this->getID());
$img->deletePhoto();
// ########################################################################
$this->returnOK();
}
public function getDeliveryObject()
{
if (!$this->delivery) {
$data = parent::getObject();
$this->delivery = Delivery::getClass($data['class'] ?? null);
if ($this->getID()) {
$this->delivery->createFromArray($data);
}
}
return $this->delivery;
}
}

159
admin/deliveryPayment.php Normal file
View File

@@ -0,0 +1,159 @@
<?php
$main_class = 'DeliveryTypesPayment';
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\OrderingBundle\Exception\PaymentConfigurationException;
class DeliveryTypesPayment extends Window
{
protected $tableName = 'delivery_type_payment';
/** @var CurrencyContext */
private $currencyContext;
private ?Payment $payment = null;
public function __construct()
{
$this->currencyContext = ServiceContainer::getService(CurrencyContext::class);
}
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$payments = Payment::listClasses();
$payments[''] = 'Žádná';
foreach ($payments as $class => $payment) {
$payments[$class] = $payment;
}
$pageVars['payments'] = $payments;
$dbcfg = Settings::getDefault();
$pageVars['data']['priceWithVat'] = $dbcfg['prod_prefer_price_vat'] == 'Y' || $dbcfg['prod_prefer_price_vat'] == 'F';
if (!empty($pageVars['data']['price']) && $pageVars['data']['priceWithVat']) {
$pageVars['data']['price'] *= 1 + (getAdminVat()['value'] / 100);
}
$pageVars['data']['currencies'] = $this->currencyContext->getAll();
$this->unserializeCustomData($pageVars['data']);
$vars['body'] = $pageVars;
return $vars;
}
protected function getObject()
{
$data = parent::getObject();
if ($obj = $this->getPaymentObject()) {
$data['photo_array'] = $obj->getPhoto($data['photo'], $data['date_updated']);
} elseif (!empty($data['photo'])) {
// When no payment type specified
$data['photo_array'] = getImage(
$this->getID(),
basename($data['photo']),
dirname($data['photo']),
8,
$data['name'],
strtotime($data['date_updated']),
);
}
return $data;
}
public function getData()
{
$data = parent::getData();
if (getVal('Submit')) {
if ($data['priceWithVat'] && $data['price'] > 0) {
$data['price'] = $data['price'] / (1 + (getAdminVat()['value'] / 100));
}
if (!empty($data['price_buy'])) {
$data['price_buy'] = $this->prepareVatPrice($data['price_buy']);
}
}
if (!empty($data['class'])) {
try {
$payment = Payment::getClass($data['class']);
} catch (PaymentConfigurationException $e) {
$this->returnError($e->getMessage());
}
$data['data'] = $payment->processAdminWindowData($data['data'] ?? []);
}
$this->serializeCustomData($data);
return $data;
}
public function handleUpdate()
{
$SQL = parent::handleUpdate();
// Add photo
if (!empty($_FILES['photo']['name'])) {
$img = new Photos('payment');
$img->newImage($this->getID());
$img->uploadImage($_FILES['photo']);
if ($img->checkFileType()) {
$img->insertImageIntoDB();
} else {
$this->addError(getTextString('producers', 'errorBadPhoto'));
}
// Clear payment thumbnail
$img->clearThumbnails([9]);
}
return $SQL;
}
public function handleDelete()
{
// Delete photo
$img = new Photos('payment');
$img->newImage($this->getID());
$img->deletePhoto(false);
parent::handleDelete();
}
public function handleErasephoto()
{
// ########################################################################
$img = new Photos('payment');
$img->newImage($this->getID());
$img->deletePhoto();
// ########################################################################
$this->returnOK();
}
public function getPaymentObject(): ?Payment
{
if (!$this->payment) {
$data = parent::getObject();
if (empty($data['class'])) {
return null;
}
$this->payment = Payment::getClass($data['class']);
if ($id = $this->getID()) {
$this->payment->setID($id);
}
}
return $this->payment;
}
}

88
admin/deliverytypes.php Normal file
View File

@@ -0,0 +1,88 @@
<?php
$main_class = 'DeliveryTypes';
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
class DeliveryTypes extends Window
{
protected $tableName = 'delivery_type';
protected $nameField;
/** @var CurrencyContext */
private $currencyContext;
protected $defaults = [
'figure' => true,
];
public function __construct()
{
$this->currencyContext = ServiceContainer::getService(
CurrencyContext::class
);
}
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$pageVars['vats'] = \KupShop\KupShopBundle\Context\VatContext::getAdminVats();
$pageVars['delivery'] = sqlFetchAll($this->selectSQL('delivery_type_delivery', [], ['id', 'COALESCE(name_admin, name) AS name']), ['id' => 'name']);
$pageVars['payment'] = sqlFetchAll($this->selectSQL('delivery_type_payment', [], ['id', 'COALESCE(name_admin, name) AS name']), ['id' => 'name']);
$dbcfg = Settings::getDefault();
$pageVars['data']['priceWithVat'] = $dbcfg['prod_prefer_price_vat'] == 'Y' || $dbcfg['prod_prefer_price_vat'] == 'F';
if (!empty($pageVars['data']['price']) && $pageVars['data']['price'] instanceof Decimal) {
$pageVars['data']['price'] = $pageVars['data']['price']->asFloat();
}
if (!empty($pageVars['data']['price']) && $pageVars['data']['priceWithVat']) {
$pageVars['data']['price'] = round($pageVars['data']['price'] * (1 + ($pageVars['vats'][$pageVars['data']['vat']]['vat'] / 100)), 2);
}
$pageVars['data']['currencies'] = $this->currencyContext->getAll();
$pageVars['data']['custom_data'] = $this->getCustomData();
$vars['body'] = $pageVars;
$vars['type'] = 'deliverytypes';
return $vars;
}
public function handleUpdate()
{
clearCache('freeDelivery_', true);
return parent::handleUpdate();
}
public function getData()
{
$data = parent::getData();
$data['vatValue'] = getVat($data['vat']);
if (getVal('Submit')) {
$this->preparePrice($data['price']);
$this->preparePrice($data['price_dont_countin_from']);
if ($data['priceWithVat'] && $data['price'] > 0) {
$price = toDecimal($data['price']);
$data['price'] = $price->removeVat($data['vatValue']);
}
}
if (!empty($data['custom_data'])) {
$this->setCustomData($data['custom_data']);
}
return $data;
}
}

360
admin/emails.php Normal file
View File

@@ -0,0 +1,360 @@
<?php
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Email\EmailGroupTypeEnum;
use KupShop\KupShopBundle\Email\OrderMessageEmail;
use KupShop\KupShopBundle\Email\UserMessagesInterface;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Mail\Email;
use KupShop\KupShopBundle\Util\Mail\EmailLocator;
use KupShop\KupShopBundle\Util\Mail\EmailSender;
use KupShop\KupShopBundle\Util\Mail\SMSSender;
use KupShop\OrderingBundle\Util\Attachment\AttachmentLocator;
use KupShop\ReturnsBundle\Util\ReturnsUtil;
use Symfony\Component\Mime\Exception\RfcComplianceException;
$main_class = 'AdminEmails';
class AdminEmails extends Window
{
protected $template = 'window/emails.tpl';
private $languageContext;
public function __construct()
{
$this->languageContext = ServiceContainer::getService(LanguageContext::class);
}
public function hasRights($name = null)
{
switch ($name) {
case self::RIGHT_DUPLICATE:
case self::RIGHT_DELETE:
return false;
default:
return true;
}
}
public function get_vars()
{
$vars = parent::get_vars();
$settings = Settings::createFromDB();
$pageVars['data'] = [
'order_send_received_mail' => $settings->order_send_received_mail,
'order_send_status_mail' => $settings->order_send_status_mail,
'order_send_to_shopkeeper' => $settings->order_send_to_shopkeeper,
'order_shopkeeper_mail' => $settings->order_shopkeeper_mail,
'default_email' => $settings->order_shopkeeper_mail,
'smtp' => $settings->smtp ?? [],
'email_default_signature' => $settings->email_default_signature ?? [],
'email_allowed_recipient_domains' => $settings->email_allowed_recipient_domains ?? '',
];
/** @var Email $email */
$email = ServiceContainer::getService(Email::class);
$pageVars['email'] = $email;
/** @var SMSSender $smsSender */
$smsSender = ServiceContainer::getService(SMSSender::class);
$pageVars['SMSSenderBackend'] = $smsSender->getBackend();
// Get email groups from enum, so we can display them in right order
array_map(function ($enum) use (&$pageVars) {
$pageVars['emails_messages'][$enum->value] = ['doNotShow' => true];
}, EmailGroupTypeEnum::cases());
$default_emails = [];
foreach ($email->getDefaultTypes() as $type) {
$emailService = $email->getServiceByType($type);
if ($emailService::getGroup() == EmailGroupTypeEnum::HIDDEN->value) {
continue;
}
if ($emailService instanceof UserMessagesInterface) {
// Fetch UserMessage types for group
$pageVars['messages_types'][$emailService::getGroup()] = $emailService::getType();
$pageVars['emails_messages'][$emailService::getGroup()] = $emailService->getMessages($this->languageContext->getDefaultId());
foreach ($pageVars['emails_messages'][$emailService::getGroup()] as &$message) {
$message['attachments'] = $this->prepareAttachments($message['attachments']);
}
continue;
}
$default_emails[$emailService::getGroup()][$type] = $emailService->getEmailTemplate($this->languageContext->getDefaultId());
$default_emails[$emailService::getGroup()][$type]['isAnswer'] = $emailService->isAnswer ?? null;
if (empty($default_emails[$emailService::getGroup()][$type]['id'])) {
$default_emails[$emailService::getGroup()][$type]['id'] = rand(-100, -200);
}
$default_emails[$emailService::getGroup()][$type]['name'] = $emailService::getName();
$default_emails[$emailService::getGroup()][$type]['attachments'] = $this->prepareAttachments($default_emails[$emailService::getGroup()][$type]['attachments']);
$default_emails[$emailService::getGroup()][$type]['default_template'] = $emailService->getDefaultEmail();
$default_emails[$emailService::getGroup()][$type]['attachmentsGroup'] = $emailService::getGroup();
}
// Sort groups by desired order
$sorted_default_emails = array_merge(array_flip([
EmailGroupTypeEnum::ORDER->value,
EmailGroupTypeEnum::FORMS->value,
EmailGroupTypeEnum::RETURN->value,
EmailGroupTypeEnum::RECLAMATION->value,
EmailGroupTypeEnum::OTHER->value,
]), $default_emails);
// Filter empty groups
$pageVars['emails'] = array_intersect_key($sorted_default_emails, $default_emails);
if (!empty($pageVars['emails'][EmailGroupTypeEnum::OTHER->value][Email::TYPE_BASIC_TEMPLATE]['email'])) {
$pageVars['data']['default_email'] = $pageVars['emails'][EmailGroupTypeEnum::OTHER->value][Email::TYPE_BASIC_TEMPLATE]['email'];
}
$pageVars['statuses'] = [
// -100 - hardcoded non existing status for storno, so it can be selected
'order' => Config::get()['Order']['Status']['global'] + ['-100' => 'storno'],
];
if (findModule(\Modules::RETURNS)) {
$pageVars['statuses']['return'] = ServiceContainer::getService(ReturnsUtil::class)->getStatuses();
}
// attachments
$attachmentLocator = ServiceContainer::getService(AttachmentLocator::class);
$pageVars['attachments'] = $attachmentLocator->getAttachments('ALL');
$vars['body'] = $pageVars;
return $vars;
}
private function prepareAttachments($attachments)
{
if (!empty($attachments)) {
return json_decode($attachments, true);
}
return [];
}
public function handle()
{
$this->tryRights('EDIT');
$data = getVal('data');
$Submit = getVal('Submit');
$acn = getVal('acn');
if (!empty($data) && !empty($Submit)) {
$ErrStr = $this->saveSettings($data);
redirect('launch.php?s=emails.php&acn=edit&flap='.getVal('flap').'&ErrStr='.$ErrStr);
} elseif (str_starts_with($acn ?? '', 'SendTestEmail_')) {
$this->sendTestEmail(str_replace('SendTestEmail_', '', $acn));
} else {
Base::handle();
}
}
public function handlePlaceholders()
{
$type = getVal('type');
$emailLocator = ServiceContainer::getService(EmailLocator::class);
$emailService = $emailLocator->getEmailService($type);
// TODO: HACK Bez testEmail padají applyPlaceholders, protože v nich lidi šahají na data (->getOrder()), který tam v tohle případě nejsou.
// TODO: HACK Proto volám testEmail, abych nasetoval nějaký testovací data a nepadalo to. Ale applyPlaceholders by nemělo záviset na datech.
$order_message = getVal('order_message');
if ($emailService instanceof OrderMessageEmail) {
$emailService->setOrderMessage($order_message);
}
$emailService->testEmail();
foreach ($emailLocator->getEmailRegisters() as $register) {
$register->applyPlaceholders($emailService);
}
$placeholders = $emailService::getPlaceholders();
foreach ($emailService->getEntityPlaceholders() as $placeholder) {
$placeholders[$emailService::getType()][$placeholder->code] = ['text' => $placeholder->description];
}
$smarty = createSmarty(true, true);
$smarty->assign([
'type' => $type,
'name' => $emailService::getName(),
'placeholders' => $placeholders,
]);
$smarty->display('window/emails.placeholders.tpl');
exit;
}
public function handleTest()
{
$type = getVal('type');
$emailLocator = ServiceContainer::getService(EmailLocator::class);
$emailService = $emailLocator->getEmailService($type);
$typeTestEmail = $emailService->getTestType();
$order_message = getVal('order_message');
if ($emailService instanceof OrderMessageEmail) {
$emailService->setOrderMessage($order_message);
}
if ($typeTestEmail && $entityID = getVal('entityID')) {
$emailService->setTestEntity($entityID);
}
try {
if ($type == 'BASIC_TEMPLATE') {
$message = ['body' => '<p>Testovací email.</p>', 'subject' => 'Testovací email'];
$message = $emailService->renderEmail($message);
$message['body'] = replacePlaceholders($message['body'], [], [$emailService, 'replacePlaceholdersItem']);
} else {
$message = $emailService->testEmail();
}
} catch (InvalidArgumentException $e) {
$this->returnError($e->getMessage());
}
$smarty = createSmarty(true, true);
$smarty->assign([
'type' => $type,
'typeTestEmail' => $typeTestEmail,
'entityID' => $entityID ?? '',
'email' => $message,
'order_message' => $order_message,
'placeholders' => $emailService::getPlaceholders() ?? '',
]);
$smarty->display('window/emails.preview.tpl');
exit;
}
public function sendTestEmail($id)
{
$this->saveSettings(getVal('data'));
$emailSender = ServiceContainer::getService(EmailSender::class);
try {
$email = Settings::getDefault()->order_shopkeeper_mail;
$testEmail = explode(',', getVal('data')['smtp'][$id]['allowed_senders']);
$testEmail = trim(reset($testEmail));
if (!$testEmail || $testEmail == '*') {
$testEmail = $email;
}
$message = $emailSender->createMessage($testEmail, $email, 'Testovací email', 'Testovací email pro kontrolu nastavení SMTP serveru.', 'text/html');
$emailSender->realSendMessage($message);
} catch (RfcComplianceException $e) {
$this->returnError('Nelze odeslat testovací e-mail. E-mailová adresa nemá správný formát');
} catch (Throwable $e) {
$error = $e->getMessage();
$this->returnError("Nelze odeslat testovací email: {$error}");
}
$this->returnOK('Testovací zpráva odeslána.');
}
protected function saveSettings($data)
{
$settings = Settings::createFromDB();
$edited = [];
$types = ['emails_messages'];
array_map(function ($enum) use (&$types) {
$types[] = $enum->value;
}, EmailGroupTypeEnum::cases());
foreach ($data as $type => $values) {
if (!in_array($type, $types)) {
continue;
}
foreach ($values as $id => $email) {
if ($id == 0) {
continue;
}
switch ($email['type']) {
case 'ORDER_CREATE':
$edited['order_send_received_mail'] = $email['enabled'];
break;
case 'ORDER_STATUS_CHANGE':
$edited['order_send_status_mail'] = $email['enabled'];
break;
case 'ORDER_CREATE_ADMIN':
$edited['order_send_to_shopkeeper'] = $email['enabled'];
break;
}
$email['order_status'] = $email['order_status'] == '' ? null : $email['order_status'];
$email['name'] = trim($email['name'] ?? '');
if (!empty($email['attachments'])) {
$email['attachments'] = json_encode($email['attachments']);
} else {
$email['attachments'] = null;
}
if (empty($email['body'])) {
continue;
}
/** @var Email $email */
$emailService = ServiceContainer::getService(Email::class);
$email['body'] = $emailService->stripEmail($email['body']);
if (!empty($email['delete'])) {
if ($email['system_msg'] != 'Y') {
$this->deleteSQL('emails', ['id' => $id]);
}
continue;
}
if ($email['type'] == \KupShop\KupShopBundle\Email\BaseEmail::getType() && empty($email['email'])) {
$email['email'] = $settings->order_shopkeeper_mail;
}
if ($id > 0) {
$this->updateSQL('emails', $email, ['id' => $id]);
} else {
$this->insertSQL('emails', $email, ['id']);
}
}
}
$edited['order_shopkeeper_mail'] = $data['order_shopkeeper_mail'];
$edited['bounce_email'] = $data['bounce_email'];
$edited['archive_email'] = $data['archive_email'];
$edited['email_allowed_recipient_domains'] = $data['email_allowed_recipient_domains'];
if (!empty($data['smtp'])) {
$edited['smtp'] = $data['smtp'];
}
if (!empty($data['email_default_signature'])) {
$edited['email_default_signature'] = $data['email_default_signature'];
}
$data['elninoEmailTemplates'] = array_filter($data['elninoEmailTemplates'] ?? [], function ($v) {
return $v['ticketState'] !== false && !empty($v['statuses']) && !empty($v['userMessage']) && empty($v['delete']);
});
if (!empty($data['elninoEmailTemplates'])) {
$data['elninoEmailTemplates'] = array_combine(range(1, count($data['elninoEmailTemplates'])), array_values($data['elninoEmailTemplates']));
}
$edited['elninoEmailTemplates'] = json_encode($data['elninoEmailTemplates']);
$settings->loadFromArray($edited);
if ($settings->saveToDB()) {
$ErrStr = $GLOBALS['txt_str']['status']['saved'];
} else {
$ErrStr = $GLOBALS['txt_str']['status']['scripterror'];
}
Settings::clearCache(true);
return $ErrStr;
}
}

9
admin/error.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
class ErrorFrame extends Frame
{
protected $template = 'window/error.tpl';
}
$error = new ErrorFrame();
$error->run();

240
admin/export.php Normal file
View File

@@ -0,0 +1,240 @@
<?php
namespace Admin;
use Export\ExportDataDBFUcto;
use KupShop\AdminBundle\Exception\ExportException;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\OrderingBundle\OrdersExcelExport;
use KupShop\OrderingBundle\OrdersItemsExcelExport;
use Query\Operator;
class Export
{
public const EXPORT_TYPES_MAPPING = [
'products_selling' => 'productsSelling',
];
protected $ORDERS_LIMIT = 100000;
protected $handled;
protected $encoding;
protected $format;
protected $params = [];
protected $orderIds = [];
protected $type;
public function setOrderIds($ids)
{
$this->orderIds = $ids;
}
public function setType($type)
{
$this->type = $type;
}
public function setFormat($format)
{
$this->format = $format;
}
public function run()
{
$type = getVal('type', null, $this->type);
$data = getVal('data');
$this->format = getVal('format', null, $this->format);
$this->handled = getVal('what', $data);
$this->encoding = getVal('coding', null, 'utf-8');
$filter = getVal('filter');
if ($filter['date_handled']['to'] ?? false) {
$this->params['dateTo'] = $filter['date_handled']['to'];
} elseif ($filter['date_created']['to'] ?? false) {
$this->params['dateTo'] = $filter['date_created']['to'];
} else {
$this->params['dateTo'] = '';
}
if ($filter['date_handled']['from'] ?? false) {
$this->params['dateFrom'] = $filter['date_handled']['from'];
} elseif ($filter['date_created']['from'] ?? false) {
$this->params['dateFrom'] = $filter['date_created']['from'];
} else {
$this->params['dateFrom'] = '';
}
$this->params['data'] = getVal('data');
$this->params['format'] = $this->format;
if (array_key_exists($type, self::EXPORT_TYPES_MAPPING)) {
$type = self::EXPORT_TYPES_MAPPING[$type];
}
if ($type == 'orders') {
$report = 'Export objednávek: ';
$report .= 'format = '.$this->format.'; ';
$report .= ($this->params['dateFrom'] ? 'datum od = '.$this->params['dateFrom'].'; ' : '');
$report .= ($this->params['dateTo'] ? 'datum do = '.$this->params['dateTo'].'; ' : '');
$report .= (($this->handled == 'Y') ? 'jen vyřízené objednávky; ' : '');
writeDownActivity($report);
}
ini_set('memory_limit', '1024M');
ini_set('max_execution_time', '600');
try {
$method = 'export'.ucfirst($type);
if (method_exists($this, $method)) {
$this->$method();
} else {
$this->applyFallback();
}
} catch (ExportException $e) {
redirect('launch.php?s=board.php&type=export_orders&ErrStr='.urlencode($e->getMessage()));
}
}
protected function getOrderIdsToExport()
{
if (!empty($this->orderIds)) {
return $this->orderIds;
}
$filter = getVal('filter');
$ordersFilterSpecs = ServiceContainer::getService(\KupShop\AdminBundle\Util\Filter\OrdersFilterSpecs::class);
$specs = $ordersFilterSpecs->getSpecs($filter);
$qb = sqlQueryBuilder()->select('o.id')->from('orders', 'o')
->setMaxResults($this->ORDERS_LIMIT)
->orderBy('o.id', 'ASC');
if ($specs) {
$qb->andWhere($specs);
}
$order_ids = getVal('order_ids');
if ($order_ids) {
$order_ids = explode(',', $order_ids);
$order_ids = array_map('trim', $order_ids);
$qb->andWhere(Operator::inStringArray($order_ids, 'o.order_no'));
}
$orders = $qb->execute();
if ($orders->rowCount() >= $this->ORDERS_LIMIT) {
throw new ExportException('Export se nepodařil, protože byl překročen limit '.$this->ORDERS_LIMIT.' objednávek');
}
return array_map(function ($x) {
return $x['id'];
}, $orders->fetchAll());
}
public function exportOrders()
{
if (in_array($this->format, ['overview', 'excelOss', 'excel', 'excelWithItems'])) {
// Overview se renderuje u klienta, tak zvednem limit
$this->ORDERS_LIMIT = 1000000;
}
include_once 'export/orders.php';
$export = new \ExportOrders();
$export->setOrderIds($this->getOrderIdsToExport());
if ($this->format == 'csv' || $this->format == 'csv_premier' || $this->format == 'csv_helios') {
$this->params['file_ext'] = 'csv';
$this->params['content_type'] = 'application/csv';
$export->exportData($this->params);
} elseif ($this->format == 'txt_premier') {
$this->params['file_ext'] = 'txt';
$this->params['content_type'] = 'application/txt';
$export->exportData($this->params);
} elseif ($this->format == 'dbf_ucto') {
$dateFrom = null;
$dateTo = null;
$filename_dates = '';
if (!empty($this->params['dateFrom'])) {
$dateFrom = new \DateTime($this->params['dateFrom']);
$filename_dates .= '_'.$dateFrom->format('Y-m-d');
}
if (!empty($this->params['dateTo'])) {
$dateTo = new \DateTime($this->params['dateTo']);
$filename_dates .= (empty($filename_dates) ? '_x-' : '-').$dateTo->format('Y-m-d');
} else {
if (!empty($filename_dates)) {
$filename_dates .= '-x';
}
}
$dbcfg = \Settings::getDefault();
$filename = createScriptURL_Text($dbcfg->shop_title).$filename_dates.'.dbf';
$ids = $export->getOrderIds();
$export = new ExportDataDBFUcto('browser', $filename);
$export->setCoding($this->encoding);
$export->initialize();
$export->loadOrdersData($ids);
$export->finalize();
} elseif ($this->format == 'pohoda' || $this->format == 'pohoda_with_items') {
$this->params['file_ext'] = 'xml';
$this->params['content_type'] = 'application/xml';
$export->exportData($this->params);
} elseif ($this->format == 'excel') {
/** @var $excelExport OrdersExcelExport */
$excelExport = ServiceContainer::getService(OrdersExcelExport::class);
$excelExport->setOrderIDs($this->getOrderIdsToExport());
$excelExport->export();
} elseif ($this->format == 'excelOss') {
$excelExport = ServiceContainer::getService(\KupShop\OSSVatsBundle\OssOrdersExcelExport::class);
$excelExport->setOrderIDs($this->getOrderIdsToExport());
$excelExport->export();
} elseif ($this->format == 'excelWithItems') {
/** @var $excelExport OrdersItemsExcelExport */
$excelExport = ServiceContainer::getService(OrdersItemsExcelExport::class);
$excelExport->setOrderIDs($this->getOrderIdsToExport());
$excelExport->export();
} elseif ($this->format == 'money' || $this->format == 'money_foreign' || $this->format == 'money_s4s5' || $this->format == 'flexibee') {
$this->params['file_ext'] = 'xml';
$this->params['content_type'] = 'application/xml';
$export->exportData($this->params);
} else {
$this->applyFallback();
}
}
protected function applyFallback()
{
$orderIds = $this->getOrderIdsToExport();
include_once 'export_sracka.php';
}
public static function getOrderPayment(\Order $order)
{
if ($payment = $order->getDeliveryType()->getPayment()) {
switch ($payment->getPayMethod()) {
case \Payment::METHOD_COD:
return 'COD';
case \Payment::METHOD_CASH:
return 'CASH';
case \Payment::METHOD_TRANSFER:
return 'TRANSFER';
}
}
return 'COD';
}
}
return Export::class;

109
admin/export/orders.php Normal file
View File

@@ -0,0 +1,109 @@
<?php
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
function ordersOutputBuffer($buffer, $phase)
{
return iconv('utf-8', getVal('coding', null, 'utf-8').'//TRANSLIT', $buffer);
}
class ExportOrders
{
/** @var KupShop\OrderingBundle\Util\Order\DeliveryInfo */
protected $deliveryInfoService;
protected $orderIds;
protected function setHeader($params)
{
if (!empty($params['dateFrom']) && !empty($params['dateTo'])) {
$filename = 'objednavky_'.$params['dateFrom'].'-'.$params['dateTo'];
} else {
$filename = 'objednavky_'.date('Y-m-d_H-i');
}
$filename .= '.'.$params['file_ext'];
header("Content-type: {$params['content_type']}");
header("Content-Disposition: attachment; filename=\"{$filename}\"");
}
public function setOrderIds($orderIds)
{
$this->orderIds = $orderIds;
return $this;
}
public function getOrderIds()
{
return $this->orderIds;
}
protected function prepdate($date)
{
if (empty($date)) {
return '';
}
$date = new DateTime($date);
return $date->format('Y-m-d');
}
public function exportData($params)
{
$this->setHeader($params);
/* @var KupShop\OrderingBundle\Util\Order\DeliveryInfo deliveryInfoService */
$this->deliveryInfoService = ServiceContainer::getService('KupShop\OrderingBundle\Util\Order\DeliveryInfo');
$where = 'o.id IN ('.(!empty($this->orderIds) ? join(',', $this->orderIds) : '0').')';
$orders = sqlQuery("SELECT o.id FROM orders o WHERE {$where}");
// Select all vats
$vats = sqlFetchAll(sqlQuery('SELECT vat, 0 tmp FROM vats ORDER BY vat'), ['vat' => 'tmp']);
// Append non-existent vats from orders
$vats_order = sqlQuery("SELECT distinct COALESCE(tax, 0) vat, 0 tmp
FROM orders as o
LEFT JOIN order_items oi on oi.id_order=o.id
WHERE {$where}
ORDER BY vat");
foreach ($vats_order as $row) {
if (!isset($vats[$row['vat']])) {
$vats[$row['vat']] = 0;
}
}
$smarty = createSmarty(true, true);
$smarty->assign([
'orders' => $orders,
'vats' => $vats,
'this' => $this,
]);
ob_start('ordersOutputBuffer', 4096);
$template = getVal('format', $params, $params['file_ext']);
$smarty->display("export/orders_{$template}.tpl");
}
public function getOrder($id_order)
{
$orderObj = new \Order($id_order);
$orderObj->createFromDB($id_order);
$orderObj->fetchItems();
$orderObj->fetchDates();
$orderObj->deliveryItemId = $this->deliveryInfoService->getDeliveryItem($orderObj);
if (is_null($orderObj->date_handle)) {
$orderObj->date_handle = $orderObj->date_created;
}
return $orderObj;
}
}

View File

@@ -0,0 +1,3 @@
<?php
class_alias('ExportProductsSelling', '\ExportProductsSelling');

551
admin/export_sracka.php Normal file
View File

@@ -0,0 +1,551 @@
<?php
namespace export_sracka;
use Query\Operator;
use XBase\Record;
use XBase\WritableTable;
global $cfg, $dbcfg;
$cfg['Order']['Status']['dispatch'][0] = 'čeká na odeslání';
$cfg['Order']['Status']['dispatch'][1] = 'částečně odesláno';
$cfg['Order']['Status']['dispatch'][2] = 'odesláno';
if (!findRight('EXPRT')) {
redirect('launch.php?s=error.php&id=1');
}
date_default_timezone_set('Europe/Prague');
$type = getVal('type');
$format = getVal('format');
$dateTo = getVal('dateTo');
$dateFrom = getVal('dateFrom');
$data = getVal('data');
$what = $data['what'];
$dateFromC = getVal('dateFromC');
$dateToC = getVal('dateToC');
$where = 'file';
function formatString2CSV($str, $format)
{
if ($format == 'csv') {
$str = str_replace('"', '""', $str);
$str = preg_replace("/\r?\n/i", ' ', $str);
}
return $str;
}
$userAgent = 'MOZILLA';
$mime_type['file'] = ($userAgent == 'IE' || $userAgent == 'OPERA')
? 'application/octetstream'
: 'application/octet-stream';
$mime_type['excel'] = 'application/x-msexcel';
$mime_type['csv'] = 'text/comma-separated-values';
$mime_type['dbf'] = 'application/dbase';
$mime_type['overview'] = 'text/html';
$filename['excel'] = 'export.xls';
$filename['csv'] = 'export.csv';
$filename['dbf'] = 'export.dbf';
$filename['overview'] = 'export.html';
$file = '';
// ##############################################################
/*
* ======================================================================
* EXPORT OBJEDNAVEK
* ======================================================================
*/
if ($type == 'orders') {
$filename['excel'] = 'objednavky_'.date('Y-m-d_H-i-s').'.xls';
$filename['csv'] = 'objednavky_'.date('Y-m-d_H-i-s').'.csv';
$filename['dbf'] = 'objednavky_'.date('Y-m-d_H-i-s').'.dbf';
$filename['overview'] = 'objednavky_'.date('Y-m-d_H-i-s').'.html';
$var['fields'] = " id, id_user, order_no,
status, status_payed, status_dispatch, status_storno, total_price,
invoice_name, invoice_surname, invoice_firm, invoice_ico, invoice_dic,
invoice_street, invoice_city, invoice_zip, invoice_country, invoice_phone, invoice_email,
delivery_name, delivery_surname, delivery_firm, delivery_street, delivery_city,
delivery_zip, delivery_country, delivery_type, delivery_complete,
note_user, note_admin, date_handle,
DATE_FORMAT(date_created, '".$dbcfg['date_format'].' '.$dbcfg['time_format']."') AS datec,
DATE_FORMAT(date_accept, '".$dbcfg['date_format'].' '.$dbcfg['time_format']."') AS datea,
DATE_FORMAT(date_handle, '".$dbcfg['date_format'].' '.$dbcfg['time_format']."') AS dateh,
COALESCE(date_handle, date_accept, NOW()) + INTERVAL {$dbcfg->shop_due_days} DAY AS date_due,
flags
";
$var['from'] = ' '.getTableName('orders').' AS o ';
$var['where'] = ' 1 ';
$var['orderField'] = 'o.id';
$var['orderDir'] = 'ASC';
$var['order'] = ' ORDER BY '.$var['orderField'].' '.$var['orderDir'];
if (findModule('currencies')) {
$var['fields'] = str_replace('total_price', 'total_price, total_price*currency_rate as total_price_czk, currency, currency_rate', $var['fields']);
}
// -----------------------------------------------------------------
function prepdate($date)
{
if (empty($date)) {
return '';
}
$date = new \DateTime($date);
return $date->format('Y-m-d');
}
$var['where'] .= ' AND o.id IN ('.(!empty($orderIds) ? join(',', $orderIds) : '0').')';
$encode = function ($str) {
return iconv('utf-8', getVal('coding', null, 'utf-8').'//TRANSLIT', $str);
};
// -----------------------------------------------------------------
$var['query'] = 'SELECT '.$var['fields'].' FROM '.$var['from'].' WHERE '.$var['where'].' '.$var['order'];
// Invoice mass printing
if ($format == 'invoice') {
$where = 'screen';
$var['fields'] = 'id';
$SQL = sqlQuery('SELECT '.$var['fields'].' FROM '.$var['from'].' WHERE '.$var['where'].' '.$var['order']);
$file = '<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="//www.w3.org/StyleSheets/Core/Steely" type="text/css" />
</head>
<body>
<form action="launch.php?s=printCenter.php&type=order&set=order" method="POST" target="_blank" >';
while (($row = sqlFetchAssoc($SQL)) !== false) {
$file .= "<input type='hidden' name='IDs[]' value='{$row['id']}' />";
}
$file .= '<input type="submit" value="vygenerovat faktury"></form></body></html>';
}
if ($format == 'overview') {
$where = 'screen';
}
$SQL = sqlQuery($var['query']);
if (sqlNumRows($SQL) > 0) {
if ($format == 'dbf' || $format == 'overview') {
$vats = sqlFetchAll(sqlQuery('SELECT DISTINCT COALESCE(tax, 0) vat FROM '.$var['from'].' LEFT JOIN order_items oi ON oi.id_order=o.id WHERE '.$var['where'].' ORDER BY vat'), 'vat');
$vats = array_map(function ($x) {
return \DecimalConstants::zero();
}, $vats);
$sumTaxes = $vats;
if ($format == 'overview') {
$file = '<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="http://www.w3.org/StyleSheets/Core/Steely" type="text/css" />
</head>
<body>
<style>
th {
text-align: center;
}
.right {
text-align: right;
}
td {
padding-right: 21px;
}
</style>
<table cellpadding="2">
<thead>
<th>číslo dokladu</th>
<th>datum vystavení</th>
<th>jmeno a přijmení</th>
';
foreach ($sumTaxes as $vat => $sum) {
$file .= "<th>základ dph {$vat}%</th>
<th>dph {$vat}%</th>";
}
$file .= '<th>celková částka</th>
<th>stav</th>
<th>poznámka</th>
</thead>
<tbody>';
}
if ($format == 'dbf') {
if ($where == 'file') {
header('Content-type: '.$mime_type[$format]);
header('Content-Disposition: attachment; filename="'.$filename[$format].'"');
header('Expires: 0');
header('Pragma: no-cache');
}
$oldErr = error_reporting(0);
/* sample data */
$fields = [
['DATUM_VYST', Record::DBFFIELD_TYPE_DATE], // datum vystavení
['DATUM_SPL', Record::DBFFIELD_TYPE_DATE], // prázdné
['DOKLAD_1', Record::DBFFIELD_TYPE_CHAR, 12], // aby tam bylo fčíslo objednávky např. f11521
['TYP_ZAP', Record::DBFFIELD_TYPE_CHAR, 1], // hodnota P
['ZNAK_UCT', Record::DBFFIELD_TYPE_CHAR, 5], // prázdné
['SYMBOLY', Record::DBFFIELD_TYPE_CHAR, 20], // včísloobjednávky např. v11521
['PAR_ZNAK', Record::DBFFIELD_TYPE_CHAR, 12], // to samé jako DOKLAD_1 např. f11521
['BANK_UCET', Record::DBFFIELD_TYPE_CHAR, 44], // prázdné
['SPEC_SYMB', Record::DBFFIELD_TYPE_CHAR, 10], // prázdné
['POPIS_TEXT', Record::DBFFIELD_TYPE_CHAR, 30], // libovolný text - např. prodej eshop-objednávka 11521
['DRUH_UCT', Record::DBFFIELD_TYPE_CHAR, 5], // hodnota PZ
['MENA', Record::DBFFIELD_TYPE_CHAR, 3], // buď Kč nebo EUR
['CELKEM_KC', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // celková částka dokladu včetně DPH v Kč
['CELKEMCIZI', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // celková částka dokladu v EUR - prodej na Slovensko?
['KURZ', Record::DBFFIELD_TYPE_FLOATING, 5, 3], // kurz pro přepočet
['DATUM_DPH', Record::DBFFIELD_TYPE_DATE], // datum DPH = datum vystavení
['TYP_DPH', Record::DBFFIELD_TYPE_CHAR, 5], // hodnota U
['ZAKL_DPH_Z', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // Částka bez daně v základní sazbě
['DPH_Z', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // Daň s azba 21 %
['ZAKL_DPH_S', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // Částka bez daně ve snížené sazbě
['DPH_S', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // Daň s azba 15 %
['TYPMIMODPH', Record::DBFFIELD_TYPE_CHAR, 1], // prázdné
['CASTKAMIMO', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // prázdné
['STREDISKO', Record::DBFFIELD_TYPE_CHAR, 5], // PRÁZDNÉ
['vykon', Record::DBFFIELD_TYPE_CHAR, 5], // prázdné
['zakazka', Record::DBFFIELD_TYPE_CHAR, 5], // prázdné
['POZNAMKA', Record::DBFFIELD_TYPE_CHAR, 150], // sem naimportovat jméno a příjmění a město kupujícího JAN NOVAK TURNOV
['FIRMA', Record::DBFFIELD_TYPE_CHAR, 30], // Firma
['JMENO', Record::DBFFIELD_TYPE_CHAR, 30], // Jmeno
['PRIJMENI', Record::DBFFIELD_TYPE_CHAR, 30], // Prijmeni
['ICO', Record::DBFFIELD_TYPE_CHAR, 15], // ICO
['DIC', Record::DBFFIELD_TYPE_CHAR, 20], // DIC
['ZAKAZNIK', Record::DBFFIELD_TYPE_CHAR, 80], // Prijmeni nebo firma
['ULICE', Record::DBFFIELD_TYPE_CHAR, 50], // Adresa
['MESTO', Record::DBFFIELD_TYPE_CHAR, 30], // Adresa
['PSC', Record::DBFFIELD_TYPE_CHAR, 10], // Adresa
['ZEME', Record::DBFFIELD_TYPE_CHAR, 30], // Adresa
['STAV', Record::DBFFIELD_TYPE_CHAR, 10], // STORNO/PRODEJ
['DATUM_SPLAT', Record::DBFFIELD_TYPE_DATE], // datum splatnosti
['SAZBA_DPH_Z', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // sazba DPH - zakladni
['SAZBA_DPH_S', Record::DBFFIELD_TYPE_FLOATING, 8, 2], // sazba DPH - snizena
];
/* create a new table */
$tableNew = WritableTable::create($cfg['Path']['data'].'export.dbf', $fields);
}
$sumPrice = \DecimalConstants::zero();
while (($row = sqlFetchAssoc($SQL)) !== false) {
$taxes = $vats;
if ($row['status_storno']) {
$row['total_price_czk'] = 0;
$row['total_price'] = 0;
} else {
// Get vats
$query = "SELECT oi.tax, SUM(oi.total_price) price
FROM order_items oi
JOIN orders o ON o.id = oi.id_order
WHERE oi.id_order={$row['id']}
GROUP BY oi.tax";
if (findModule('currencies')) {
$query = str_replace('total_price', 'total_price*o.currency_rate', $query);
}
$i_SQL = sqlQuery($query);
foreach ($i_SQL as $i_row) {
$tax = strval($i_row['tax']);
$price = toDecimal($i_row['price']);
$taxes[$tax] = $price;
if (!isset($sumTaxes[$tax])) {
$sumTaxes[$tax] = \DecimalConstants::zero();
}
$sumTaxes[$tax] = $sumTaxes[$tax]->add($price);
}
$sumPrice = $sumPrice->add(toDecimal($row['total_price']));
}
if ($format == 'overview') {
$note = '';
if ($row['status_storno']) {
$note = 'STORNO';
}
$file .= "<tr>
<td>{$row['order_no']}</td>
<td>{$row['dateh']}</td>
<td>{$row['invoice_name']} {$row['invoice_surname']}, {$row['invoice_city']}</td>";
foreach ($taxes as $vat => $sum) {
$file .= "<td class='right'>".number_format($taxes[$vat]->asFloat(), 2, ',', '')."</td>
<td class='right'>".number_format($taxes[$vat]->mul(toDecimal($vat / 100))->asFloat(), 2, ',', '').'</td>';
}
$file .= "<td class='right'>".number_format($row['total_price'], 2, ',', '').'</td>
<td>'.$cfg['Order']['Status']['global'][$row['status']]."</td>
<td>{$note}</td>
</tr>";
}
if ($format == 'dbf') {
$r = $tableNew->appendRecord();
$total_price = roundPrice($row['total_price_czk']);
$vatsFormDB = sqlQueryBuilder()
->select('vat, is_default')
->from('vats')
->where(Operator::equals(['id_country' => $row['invoice_country'] ?: 'CZ']))
->orderBy('vat', 'DESC')
->execute()
->fetchAll();
$dph_z = 0;
foreach ($vatsFormDB as $vatRow) {
if ($vatRow['is_default'] == 'Y') {
$dph_z = $vatRow['vat'];
break;
}
}
$dph_s = $vatsFormDB[1]['vat'] ?? 0;
if (!isset($taxes[$dph_z])) {
$taxes[$dph_z] = \DecimalConstants::zero();
}
if (!isset($taxes[$dph_s])) {
$taxes[$dph_s] = \DecimalConstants::zero();
}
if (!isset($taxes[0])) {
$taxes[0] = \DecimalConstants::zero();
}
$r->setObjectByName('DATUM_VYST', strtotime($row['date_handle'])); // datum vystavení
// $r->setObjectByName("DATUM_SPL", $row['DBFFIELD_TYPE_DATE']); //prázdné
$r->setObjectByName('DOKLAD_1', $row['order_no']); // aby tam bylo fčíslo objednávky např. f11521
$r->setObjectByName('TYP_ZAP', 'P'); // hodnota P
$r->setObjectByName('ZNAK_UCT', ''); // prázdné
$r->setObjectByName('SYMBOLY', $row['id']); // včísloobjednávky např. v11521
$r->setObjectByName('PAR_ZNAK', $row['order_no']); // to samé jako DOKLAD_1 např. f11521
$r->setObjectByName('BANK_UCET', ''); // prázdné
$r->setObjectByName('SPEC_SYMB', ''); // prázdné
$r->setObjectByName('POPIS_TEXT', $encode('Objednávka: '.$row['id'])); // libovolný text - např. prodej eshop-objednávka 11521
$r->setObjectByName('DRUH_UCT', 'PZ'); // hodnota PZ
$r->setObjectByName('MENA', $row['currency']); // buď Kč nebo EUR
$r->setObjectByName('CELKEM_KC', $total_price->printFloatValue(2)); // celková částka dokladu včetně DPH v Kč
$r->setObjectByName('CELKEMCIZI', ($row['currency'] == 'CZK') ? 0 : toDecimal($row['total_price'])->printFloatValue(2)); // celková částka dokladu v EUR - prodej na Slovensko?
$r->setObjectByName('KURZ', $row['currency_rate']); // kurz pro přepočet
$r->setObjectByName('DATUM_DPH', strtotime($row['date_handle'])); // datum DPH = datum vystavení
$r->setObjectByName('TYP_DPH', 'U'); // hodnota U
$r->setObjectByName('ZAKL_DPH_Z', $taxes[$dph_z]->printFloatValue(2)); // Částka bez daně v základní sazbě
$r->setObjectByName('DPH_Z', $taxes[$dph_z]->mul(toDecimal($dph_z / 100))->printFloatValue(2)); // Daň sazba 21 %
$r->setObjectByName('ZAKL_DPH_S', $taxes[$dph_s]->printFloatValue(2)); // Částka bez daně ve snížené sazbě
$r->setObjectByName('DPH_S', $taxes[$dph_s]->mul(toDecimal($dph_z / 100))->printFloatValue(2)); // Částka bez daně ve snížené sazbě
$r->setObjectByName('TYPMIMODPH', ''); // prázdné
$r->setObjectByName('CASTKAMIMO', $taxes['0']->printFloatValue(2)); // prázdné
$r->setObjectByName('STREDISKO', ''); // PRÁZDNÉ
$r->setObjectByName('vykon', ''); // prázdné
$r->setObjectByName('zakazka', ''); // prázdné
$r->setObjectByName('POZNAMKA', $encode("{$row['invoice_name']} {$row['invoice_surname']}, {$row['invoice_city']}")); // sem naimportovat jméno a příjmění a město kupujícího JAN NOVAK TURNOV
$r->setObjectByName('FIRMA', $encode($row['invoice_firm'])); // Firma
$r->setObjectByName('JMENO', $encode($row['invoice_name'])); // Jmeno
$r->setObjectByName('PRIJMENI', $encode($row['invoice_surname'])); // Prijmeni
$r->setObjectByName('ICO', $row['invoice_ico']); // ICO
$r->setObjectByName('DIC', $row['invoice_dic']); // DIC
$r->setObjectByName('ZAKAZNIK', $encode($row['invoice_firm'] ? $row['invoice_firm'] : "{$row['invoice_name']} {$row['invoice_surname']}")); // Prijmeni nebo firma
$r->setObjectByName('ULICE', $encode($row['invoice_street']));
$r->setObjectByName('MESTO', $encode($row['invoice_city']));
$r->setObjectByName('PSC', $row['invoice_zip']);
$r->setObjectByName('ZEME', $encode($row['invoice_country']));
$r->setObjectByName('STAV', $row['status_storno'] ? 'STORNO' : 'PRODEJ'); // STORNO/PRODEJ
$r->setObjectByName('DATUM_SPLAT', strtotime($row['date_due']));
$r->setObjectByName('SAZBA_DPH_Z', $dph_z);
$r->setObjectByName('SAZBA_DPH_S', $dph_s);
$tableNew->writeRecord();
}
}
if ($format == 'overview') {
$file .= '<tr><td>&nbsp</td></tr>
<thead>
<th></th>
<th></th>
<th></th>';
foreach ($sumTaxes as $tax => $sum) {
$file .= "
<th>zaklad dph {$tax}%</th>
<th>dph {$tax}%</th>
";
}
$file .= '
<th>celková částka</th>
<th></th>
<th></th>
</thead>
<tr>
<td/><td/><td><b>CELKEM:</b></td>
';
foreach ($sumTaxes as $tax => $sum) {
$file .= " <td class='right'><b>".number_format($sum->asFloat(), 2, ',', '')."</b></td>
<td class='right'><b>".number_format($sum->mul(toDecimal($tax / 100))->asFloat(), 2, ',', '').'</b></td>
';
}
$file .= "<td class='right'><b>".number_format($sumPrice->asFloat(), 2, ',', '').'</b></td>
<tr>
</tbody>
</table>
</body>
</html>';
}
if ($format == 'dbf') {
/* close the table */
$tableNew->close();
error_reporting($oldErr);
readfile($cfg['Path']['data'].'export.dbf');
exit;
}
} elseif ($format == 'csv') {
$file = '"Kód";"Stav objednávky";"Stav zaplacení";"Stav expedice";"Stav storna";"Datum objednávky";'.
'"Datum přijetí";"Datum vyřízení";"Počet položek";"Cena ('.$dbcfg['currency'].')";'.
'"Jméno";"Příjmení";"Firma";"Email";"Telefon";"Ulice";"Město";"PSČ";"Země";"IČO";"DIČ";'.
'"Doruč.jméno";"Doruč.příjmení";"Doruč.firma";"Doruč.ulice";"Doruč.město";"Doruč.PSČ";"Doruč.země";'.
'"Doručit jen kompletně";"Pozn.pro zákazníka";"Pozn.pro obchodníka";"Příznaky"'."\r\n\r\n";
$rowtpl = '"{O_NO}";"{STATUS}";"{STATUS_PAYED}";"{STATUS_DISPATCH}";"{STATUS_STORNO}";'.
'"{DATE_CREATED}";"{DATE_ACCEPT}";"{DATE_HANDLE}";"{ITEMS}";"{PRICE}";"{INV_NAME}";"{INV_SURNAME}";'.
'"{INV_FIRM}";"{INV_EMAIL}";"{INV_PHONE}";"{INV_STREET}";"{INV_CITY}";"{INV_ZIP}";"{INV_COUNTRY}";'.
'"{INV_ICO}";"{INV_DIC}";"{DEL_NAME}";"{DEL_SURNAME}";"{DEL_FIRM}";"{DEL_STREET}";"{DEL_CITY}";'.
'"{DEL_ZIP}";"{DEL_COUNTRY}";"{DEL_COMPLETE}";"{NOTE_ADMIN}";"{NOTE_USER}";"{FLAGS}"'."\r\n";
}
if ($format == 'csv') {
while ($row = sqlFetchArray($SQL)) {
// kontrola delky zpracovani skriptu
controlTimeLimit();
$order = new \Order();
$order->createFromDB($row['id']);
$order->fetchItems();
$i_row = ['items' => count($order->items)];
$rowtpl_t = $rowtpl;
$rowtpl_t = str_replace('{O_NO}', $row['order_no'], $rowtpl_t);
$rowtpl_t = str_replace('{ITEMS}', $i_row['items'], $rowtpl_t);
if (findModule('currencies')) {
$rowtpl_t = str_replace('.', ',', str_replace('{PRICE}', number_format($row['total_price'], 2, '.', ''), $rowtpl_t));
$rowtpl_t = str_replace('{MENA}', $row['currency'], $rowtpl_t);
$rowtpl_t = str_replace('{KURZ}', $row['currency_rate'], $rowtpl_t);
$rowtpl_t = str_replace('.', ',', str_replace('{PRICE_CZK}', number_format($row['total_price_czk'], 2, '.', ''), $rowtpl_t));
} else {
$rowtpl_t = str_replace('.', ',', str_replace('{PRICE}', number_format($row['total_price'], 2, '.', ''), $rowtpl_t));
}
if (findModule(\Modules::PRODUCTS, \Modules::SUB_WEIGHT)) {
$order = new \Order();
$order->createFromDB($row['id']);
$rowtpl_t = str_replace('{O_WEIGHT}', $order->getTotalWeight(), $rowtpl_t);
}
$rowtpl_t = str_replace('{STATUS}', formatString2CSV($cfg['Order']['Status']['global'][$row['status']], $format), $rowtpl_t);
$rowtpl_t = str_replace('{STATUS_PAYED}', formatString2CSV($cfg['Order']['Status']['payed'][$row['status_payed']], $format), $rowtpl_t);
$rowtpl_t = str_replace('{STATUS_DISPATCH}', formatString2CSV($cfg['Order']['Status']['dispatch'][$row['status_dispatch']], $format), $rowtpl_t);
$rowtpl_t = str_replace('{STATUS_STORNO}', formatString2CSV($cfg['Order']['Status']['storno'][$row['status_storno']], $format), $rowtpl_t);
$rowtpl_t = str_replace('{DATE_CREATED}', $row['datec'], $rowtpl_t);
$rowtpl_t = str_replace('{DATE_ACCEPT}', $row['datea'], $rowtpl_t);
$rowtpl_t = str_replace('{DATE_HANDLE}', $row['dateh'], $rowtpl_t);
$rowtpl_t = str_replace('{DEL_COMPLETE}', ($row['delivery_complete'] == 'Y') ? 'Ano' : 'Ne', $rowtpl_t);
$rowtpl_t = str_replace('{INV_NAME}', formatString2CSV($row['invoice_name'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_SURNAME}', formatString2CSV($row['invoice_surname'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_FIRM}', formatString2CSV($row['invoice_firm'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_EMAIL}', formatString2CSV($row['invoice_email'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_PHONE}', formatString2CSV($row['invoice_phone'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_STREET}', formatString2CSV($row['invoice_street'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_CITY}', formatString2CSV($row['invoice_city'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_ZIP}', formatString2CSV($row['invoice_zip'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_COUNTRY}', formatString2CSV($row['invoice_country'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_ICO}', formatString2CSV($row['invoice_ico'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{INV_DIC}', formatString2CSV($row['invoice_dic'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{DEL_NAME}', formatString2CSV($row['delivery_name'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{DEL_SURNAME}', formatString2CSV($row['delivery_surname'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{DEL_FIRM}', formatString2CSV($row['delivery_firm'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{DEL_STREET}', formatString2CSV($row['delivery_street'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{DEL_CITY}', formatString2CSV($row['delivery_city'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{DEL_ZIP}', formatString2CSV($row['delivery_zip'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{DEL_COUNTRY}', formatString2CSV($row['delivery_country'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{NOTE_ADMIN}', formatString2CSV($row['note_admin'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{NOTE_USER}', formatString2CSV($row['note_user'], $format), $rowtpl_t);
$rowtpl_t = str_replace('{FLAGS}', $row['flags'], $rowtpl_t);
$deliveryType = explode('-', $row['delivery_type']);
$rowtpl_t = str_replace('{DELIVERY}', $deliveryType[1] ?? '', $rowtpl_t);
$rowtpl_t = str_replace('{PAYMENT}', $deliveryType[0] ?? '', $rowtpl_t);
$file .= $rowtpl_t;
}
}
}
}
// kontrola delky zpracovani skriptu
controlTimeLimit();
// ###########################
// KAM EXPORTOVAT
// ============================================
if ($where == 'screen') {
if ($format == 'csv') {
header('Content-type: '.$mime_type['csv']);
// vytisknout
echo $file;
} else {
echo $file;
}
} elseif // ============================================
($where == 'file'
) {
header('Content-type: '.$mime_type['file']);
if ($userAgent == 'IE') {
header('Content-Disposition: attachment; filename="'.$filename[$format].'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
} else {
header('Content-Disposition: attachment; filename="'.$filename[$format].'"');
header('Expires: 0');
header('Pragma: no-cache');
}
// vytisknout
echo $file;
}
//
// ###########################
// ##############################################################

68
admin/fulltext.php Normal file
View File

@@ -0,0 +1,68 @@
<?php
use KupShop\CatalogBundle\Search\FulltextInterface;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
$main_class = 'fulltext';
class fulltext extends Window
{
use \KupShop\AdminBundle\FulltextUpdatesTrait;
public function get_vars()
{
$vars = parent::get_vars();
/** @var FulltextInterface $fulltext */
$fulltext = ServiceContainer::getService(FulltextInterface::class);
$vars['synonyms'] = $fulltext->loadSynonyms();
$vars['support'] = true;
return $vars;
}
public function handle()
{
if (!getVal('Submit') && !getVal('Reindex')) {
return;
}
/** @var FulltextInterface $fulltext */
$fulltext = ServiceContainer::getService(FulltextInterface::class);
$data = $this->getData();
$synonyms = [];
foreach ($data as $line) {
if (!empty($line['from']) && !empty($line['to']) && !key_exists('delete', $line)) {
$synonyms[] = $line;
}
}
$fulltext->updateSynonyms($synonyms);
if (getVal('Reindex')) {
ini_set('max_execution_time', 500);
try {
$this->updateIndices();
} catch (\KupShop\CatalogBundle\Search\Exception\FulltextException $e) {
getRaven()->captureException($e);
$this->returnError('Nastala chyba při generování vyhledávácího indexu');
}
}
$this->handleTabs(true);
$this->returnOK();
}
public function hasRights($name = null)
{
switch ($name) {
case Window::RIGHT_DUPLICATE:
case Window::RIGHT_DELETE:
return false;
default:
return parent::hasRights($name);
}
}
}

210
admin/functions.admin.php Normal file
View File

@@ -0,0 +1,210 @@
<?php
use KupShop\KupShopBundle\Exception\RedirectException;
if (!function_exists('getTextString')) {
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/**
* @deprecated Use translate($key, $section) instead
*/
function getTextString($section, $key)
{
return translate($key, $section);
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
function findRight($right, $var = null)
{
// kdyz nejsou dodany vlastni prava
if (is_null($var)) {
// kdyz se jedna o superadmina
if (isSuperuser()) {
return true;
}
$adminUser = getAdminUser();
$var = $adminUser ? $adminUser['privilege'] : '';
}
if (preg_match("/\b{$right}/i", $var) || preg_match('/ALL_RIGHTS/i', $var)) {
return true;
} else {
return false;
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
function redirect($URL, $type = 'header')
{
if ($URL == 'REFERER') {
if (!empty($_SERVER['HTTP_REFERER'])) {
$URL = $_SERVER['HTTP_REFERER'];
} else {
$URL = './';
}
}
if (isLocalDevelopment()) {
throw new RedirectException($URL);
}
if (!headers_sent() && $type == 'header') {
if (ob_get_length() > 0) {
flush();
}
header('Location: '.$URL);
exit;
} elseif (headers_sent() || $type == 'script' || $type == 'script_this_win') {
$ret = "<script type=\"text/javascript\" language=\"javascript\">\n";
switch ($type) {
case 'script':
$ret .= "top.window.location='".$URL."&amp;js=1';\n";
break;
default:
case 'script_this_win':
$ret .= "this.window.location='".$URL."&amp;js=1';\n";
break;
}
$ret .= "</script>\n";
echo $ret;
exit;
}
return false;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
// danemu retezci je pridano na konec napis Kopie
function stringCopy($str)
{
if (preg_match('/.+\\(Kopie[[:blank:]]*([0-9]+)?\\)/i', $str, $cut)) {
$no = intval(getVal('1', $cut));
$no = ($no == 0) ? 2 : ($no + 1);
$end = '(Kopie '.$no.')';
$str = preg_replace('/\\(Kopie[^\\)]*\\)/i', $end, $str);
} else {
$str = rtrim($str).' (Kopie)';
}
return $str;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
function categoryTreeOption($topCat, $Pos, $selected, $without = null)
{
$where = " sr.id_topsection='{$topCat}' ";
if (!empty($without)) {
$where .= " AND id_section<>'{$without}' ";
}
$SQL = sqlQuery('SELECT s.id, s.name, s.figure
FROM '.getTableName('sections_relation').' AS sr LEFT JOIN '.getTableName('sections')." AS s ON s.id=sr.id_section
WHERE {$where}
ORDER BY sr.position ASC, s.name ASC");
$Found = sqlNumRows($SQL);
for ($i = 0; $i < $Found; $i++) {
$topCat = sqlResult($SQL, $i, 'id');
$Name = sqlResult($SQL, $i, 'name');
echo '<option value="'.$topCat.'"'.checkSelect($selected, $topCat).'>';
for ($x = 0; $x < $Pos; $x++) {
echo '&nbsp;&nbsp;&nbsp;';
}
echo htmlspecialchars($Name);
echo "</option>\r\n";
categoryTreeOption($topCat, $Pos + 1, $selected, $without);
}
sqlFreeResult($SQL);
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
function access($modules = [], $rights = [])
{
while (true) {
foreach ($modules as $module) {
if (findModule($module)) {
break 2;
}
}
return false;
}
foreach ($rights as $right) {
if (findRight($right)) {
return true;
}
}
return false;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
function prepareDate($datetime)
{
if (empty($datetime)) {
return '';
}
$format = '%d-%m-%Y';
$tm = strptime($datetime, $format);
$stmp = mktime(0, 0, 0, $tm['tm_mon'] + 1, $tm['tm_mday'], $tm['tm_year'] + 1900);
$time = date('Y-m-d', $stmp);
return $time;
}
function prepareDateTime($datetime)
{
if (empty($datetime)) {
return '';
}
$format = '%d-%m-%Y %H:%M:%S';
$tm = strptime($datetime, $format);
$stmp = mktime($tm['tm_hour'], $tm['tm_min'], $tm['tm_sec'], $tm['tm_mon'] + 1, $tm['tm_mday'], $tm['tm_year'] + 1900);
$time = date('Y-m-d H:i:s', $stmp);
return $time;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
function prepareDateForDialog($datetime)
{
if (empty($datetime)) {
return '';
}
$format = '%Y-%m-%d';
$tm = strptime($datetime, $format);
$stmp = mktime(0, 0, 0, $tm['tm_mon'] + 1, $tm['tm_mday'], $tm['tm_year'] + 1900);
$time = date('d-m-Y', $stmp);
return $time;
}
function prepareDateTimeForDialog($datetime)
{
if (empty($datetime)) {
return '';
}
$format = '%Y-%m-%d %H:%M:%S';
$tm = strptime($datetime, $format);
$stmp = mktime($tm['tm_hour'], $tm['tm_min'], $tm['tm_sec'], $tm['tm_mon'] + 1, $tm['tm_mday'], $tm['tm_year'] + 1900);
$time = date('d-m-Y H:i:s', $stmp);
return $time;
}
function switchLanguage($lang, $restore = false)
{
global $txt_str, $temp_lang, $temp_txt_str, $cfg;
if (!$restore) {
$temp_txt_str = $txt_str;
$temp_lang = $cfg['Lang']['language'];
$cfg['Lang']['language'] = $lang;
} else {
$txt_str = $temp_txt_str;
$cfg['Lang']['language'] = $temp_lang;
}
}

65
admin/functions.php Normal file
View File

@@ -0,0 +1,65 @@
<?php
// Modify directories path
$cfg['Path']['web_root'] = '';
function autoload_admin($className)
{
global $cfg;
static $subclass = 0;
if (strpos($className, 'Admin\\') !== false) {
if (strpos($className, '\\Lists\\') !== false) {
$className = str_replace('Admin\\Lists\\', 'admin/lists/', $className);
$class = $cfg['Path']['shared_version'].$className.'.php';
} elseif (strpos($className, '\\Menu\\') !== false) {
$className = str_replace('Admin\\Menu\\', 'admin/menu/', $className);
$class = $cfg['Path']['shared_version'].$className.'.php';
} else {
$class = $cfg['Path']['shared_version'].strtolower(strtr($className, '\\', '/')).'.php';
if (!file_exists($class)) {
$class = $cfg['Path']['shared_version'].lcfirst(strtr($className, '\\', '/')).'.php';
}
}
if (file_exists($class)) {
require_once $class;
}
}
if (strpos($className, '\\')) {
$class = $cfg['Path']['shared_version'].'class/'.strtr($className, '\\', '/').'.php';
if (file_exists($class)) {
require_once $class;
}
$class = $cfg['Path']['shared_version'].'admin/class/'.strtr($className, '\\', '/').'.php';
if (file_exists($class)) {
require_once $class;
}
}
if (file_exists("class.{$className}.php")) {
$subclass++;
require_once $cfg['Path']['shared_version']."admin/class/class.{$className}.php";
require_once "class.{$className}.php";
$subclass--;
return;
}
if (file_exists($cfg['Path']['shared_version']."admin/class/class.{$className}.php")) {
require_once $cfg['Path']['shared_version']."admin/class/class.{$className}.php";
}
}
// Load shared functions from web
require_once $cfg['Path']['shared_version'].'web/functions.common.php';
// Load admin specific functions
require_once $cfg['Path']['shared_version'].'admin/functions.admin.php';
// Not using class.Modules because that would require autoloader
if (!findModule('components')) {
spl_autoload_register('autoload_admin');
}

60
admin/help/index.php Normal file
View File

@@ -0,0 +1,60 @@
<?php
$main_class = 'HelpIndex';
class HelpIndex extends Window
{
protected $template = 'help/index.tpl';
public static $url = [
'productsVarLabels' => 'http://www.napoveda.wpj.cz/kupshop/produkty/varianty/',
'products' => 'http://www.napoveda.wpj.cz/kupshop/produkty/',
'discounts' => 'http://www.napoveda.wpj.cz/kupshop/zpracovani-objednavky/slevy/',
'orders' => 'http://www.napoveda.wpj.cz/kupshop/zpracovani-objednavky/stav-objednavky/',
'users' => 'http://www.napoveda.wpj.cz/kupshop/uzivatele/',
'balikonos' => 'http://www.napoveda.wpj.cz/kupshop/zpracovani-objednavky/balikonos/',
'balikobot' => 'http://www.napoveda.wpj.cz/kupshop/zpracovani-objednavky/balikobot/',
'userMessages' => 'http://www.napoveda.wpj.cz/kupshop/zpracovani-objednavky/zpravy-uzivatelum/',
'telfa' => 'http://www.napoveda.wpj.cz/kupshop/telefonni-ustredna/',
'usersGroups' => 'http://www.napoveda.wpj.cz/kupshop/uzivatele/skupiny/',
'templates' => 'http://www.napoveda.wpj.cz/kupshop/produkty/sablony-produktu/',
'templatesCategories' => 'http://www.napoveda.wpj.cz/kupshop/produkty/sablony-produktu/',
'collections' => 'http://www.napoveda.wpj.cz/kupshop/produkty/kolekce-produktu/',
'sets' => 'https://napoveda.wpjshop.cz/article/159-sety-a-darky',
'analytics' => 'http://www.napoveda.wpj.cz/kupshop/merici-kody/',
'import_generic' => 'http://www.napoveda.wpj.cz/kupshop/produkty/import/',
'margins' => 'http://www.napoveda.wpj.cz/kupshop/produkty/marze/',
'index' => 'http://www.napoveda.wpj.cz/kupshop/',
'replacement' => 'http://napoveda.wpj.cz/kupshop/zpracovani-objednavky/opravny-danovy-doklad/',
'bonusProgram' => 'http://napoveda.wpj.cz/kupshop/zpracovani-objednavky/vernostni-program/',
'generateCoupon' => 'http://napoveda.wpj.cz/kupshop/zpracovani-objednavky/darkovy-poukaz/',
'OrderDiscounts' => 'http://napoveda.wpj.cz/kupshop/zpracovani-objednavky/modul-slevy/',
'StockIn' => 'https://napoveda.wpjshop.cz/article/34-sprava-skladu-a-fakturace',
'StockInMissing' => 'https://napoveda.wpjshop.cz/article/132-chybejici-produkty',
'dropship' => 'https://napoveda.wpjshop.cz/article/158-dropshipping-neboli-marketplace',
];
public function get_vars()
{
$data = parent::get_vars();
$type = getVal('type');
if ($url = getVal($type, self::$url)) {
if ($section = getVal('section')) {
$url .= "#{$section}";
}
redirect($url);
}
if (empty($type)) {
$type = 'index';
} else {
$type = trim($type);
}
$data['type'] = $type;
return $data;
}
}

43
admin/import.generic.php Normal file
View File

@@ -0,0 +1,43 @@
<?php
global $cfg;
require_once $cfg['Path']['shared_version'].'admin/import.xml_feed_new.php';
$main_class = 'Import_Generic';
class Import_Generic extends Import_XMLfeed_New
{
protected $template = 'window/import.generic.tpl';
public function getImportParams()
{
global $cfg;
$params = parent::getImportParams();
$params['transformation'] = file_get_contents($cfg['Path']['shared_version'].'admin/templates/import/generic.xslt');
$params['type'] = AutomaticImport::TYPE_XLS;
$params['add_new'] = getVal('import_type', null, 1);
return $params;
}
public function getFeedFile()
{
global $cfg;
$import_real = getVal('import_real');
$synchronize_try = getVal('synchronize_try');
if (empty($_FILES['file']['tmp_name']) && empty($import_real) && empty($synchronize_try)) {
return '';
}
$path = $cfg['Path']['data'].'tmp/generic_import.xsl';
if (!empty($import_real) || !empty($synchronize_try)) {
return $path;
}
move_uploaded_file($_FILES['file']['tmp_name'], $path);
return $path;
}
}

426
admin/import.xml_feed.php Normal file
View File

@@ -0,0 +1,426 @@
<?php
use KupShop\CatalogBundle\Section\SectionFinder;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
class Import_XMLfeed extends Window
{
use DatabaseCommunication;
public $listProducer;
protected $template = 'window/import.xml_feed.tpl';
public function handle()
{
if (getVal('Submit') && isset($_REQUEST['type']) && $_REQUEST['type'] == 'xmlFeed') {
global $cfg;
$noErrors = 0;
$type = 'XML Feed';
$listVAT = [];
$listLabel = [];
$query = sqlQuery('SELECT id, vat FROM '.getTableName('vats'));
while ($row = sqlFetchArray($query)) {
$listVAT[$row['id']] = $row['vat'];
}
$query = sqlQuery('SELECT id, name FROM '.getTableName('producers'));
while ($row = sqlFetchArray($query)) {
$this->listProducer[$row['id']] = strtolower($row['name']);
}
$query = sqlQuery('SELECT id, label FROM '.getTableName('products_variations_choices_labels'));
while ($row = sqlFetchArray($query)) {
$listLabel[$row['id']] = $row['label'];
}
$xml = simplexml_load_file($_REQUEST['feedUrl']);
if ($xml === false) {
$ErrStr = 'Chyba stahovani XML souboru.';
redirect('launch.php?s=board.php&type=import&what='.$type.'&ErrStr='.urlencode($ErrStr));
}
if (!empty($_FILES['xsltFile']['size'])) {
// die(print_r($_FILES['xsltFile']));
$xslt = new XSLTProcessor();
$xslt->importStylesheet(simplexml_load_file($_FILES['xsltFile']['tmp_name']));
$xml = simplexml_load_string($xslt->transformToXml($xml));
if ($xml === false) {
$ErrStr = 'Chyba aplikovani XSLT transformace';
redirect('launch.php?s=board.php&type=import&what='.$type.'&ErrStr='.urlencode($ErrStr));
}
}
$sectionFinder = ServiceContainer::getService(SectionFinder::class);
sqlStartTransaction();
if ($_REQUEST['dbSave'] == 'delete_and_insert_new') {
sqlQuery('TRUNCATE '.getTableName('products'));
sqlQuery('TRUNCATE '.$cfg['DbTable']['photos-products']);
sqlQuery('TRUNCATE '.getTableName('photos'));
}
clearCache('categories-menu');
$category_separator = '/';
$codes = [];
$imageCache = [];
foreach ($xml->SHOPITEM as $item) {
if (!empty($item->PRODUCT)) {
$title = $item->PRODUCT;
} elseif (!empty($item->PRODUCTNAME)) {
$title = $item->PRODUCTNAME;
}
// Get Code
$code = null;
if (!empty($item->CODE)) {
$code = strval($item->CODE);
} elseif (!empty($item->PRODUCTNO)) {
$code = strval($item->PRODUCTNO);
} elseif (!empty($item->ITEM_ID)) {
$code = strval($item->ITEM_ID);
} elseif (!empty($_REQUEST['codePattern'])) {
if (preg_match("@{$_REQUEST['codePattern']}@", $item->URL, $matches) >= 1) {
$code = $matches[1];
} else {
echo "Error matching '{$item->URL}' to '{$_REQUEST['codePattern']}'";
}
}
if (empty($code)) {
exit("Empty code for product '{$title}'".print_r($item, true));
}
if (isset($codes[$code])) {
continue;
}
$codes[$code] = true;
if (!empty($item->SHORT_DESCRIPTION)) {
$short_descr = strval($item->SHORT_DESCRIPTION->asXML());
}
if (!empty($item->EAN)) {
$ean = strval($item->EAN);
}
if (!empty($item->DESCRIPTION)) {
$long_descr = strval($item->DESCRIPTION->children()->asXML());
}
if (empty($long_descr)) {
unset($long_descr);
}
// Get Prices
$price = floatval(strtr($item->PRICE, ',', '.'));
$price_vat = floatval(strtr($item->PRICE_VAT, ',', '.'));
if (!empty($item->VAT)) {
$vat = floatval(strtr($item->VAT, ',', '.')) * 100;
} elseif (!empty($price) && !empty($price_vat)) {
$vat = round((($price_vat / $price) - 1) * 100);
} else {
$vat = $listVAT[1];
} // Fall-back to default VAT
if (empty($price) && !empty($price_vat)) {
$price = $price_vat / (1 + $vat / 100.);
}
if (!empty($item->DISCOUNT)) {
$price_common = $price * (1 + $vat / 100.);
$price = $price * (1 - floatval(strtr($item->DISCOUNT, ',', '.')));
}
$vat = $this->findVAT($vat, $listVAT);
// Get Others
if (!empty($item->PRODUCER)) {
$producer = $this->findProducer($item->PRODUCER);
} elseif (!empty($item->MANUFACTURER)) {
$producer = $this->findProducer($item->MANUFACTURER);
}
$in_store = intval($item->IN_STORE);
$delivery_time = round($item->AVAILABILITY / 24);
if ($delivery_time <= 0) {
$delivery_time = -1;
}
// Get Category
$category = '';
if (!empty($item->CATEGORYTEXT)) {
$category .= strval($item->CATEGORYTEXT);
} elseif (!empty($item->CATEGORY)) {
$category .= strval($item->CATEGORY);
}
// Check if already exists
$product_id = null;
if ($_REQUEST['dbSave'] == 'update') {
$product_id = returnSQLResult('SELECT id FROM '.getTableName('products')." WHERE code='".sqlFormatInput($code)."'");
}
$exists = $product_id > 0;
$updateFields = ['title', 'code', 'ean', 'short_descr', 'long_descr', 'price', 'price_common', 'vat', 'producer', 'in_store', 'delivery_time', 'discount'];
$fields = [];
foreach ($updateFields as $key) {
if (isset($$key)) {
$fields[$key] = $$key;
}
}
// Insert into DB
if (!$exists) {
if (!$this->insertSQL('products', $fields)) {// sqlQuery("INSERT INTO ".getTableName("products")." SET $fields"))
$noErrors++;
}
$product_id = sqlInsertId();
} elseif (!$this->updateSQL('products', $fields, ['id' => $product_id])) {// sqlQuery("UPDATE ".getTableName("products")." SET $fields WHERE id=$product_id"))
$noErrors++;
}
// Insert category into DB
if (!$exists && !empty($category)) {
static $separator_guesed = false;
if (!$separator_guesed) {
if (substr_count($category, '|') > substr_count($category, '/')) {
$category_separator = '|';
}
$separator_guesed = true;
}
$parts = explode($category_separator, $category);
$category = $sectionFinder->findSection($parts);
sqlQuery('INSERT INTO '.getTableName('products_in_sections')."
(id_product, id_section) VALUES
({$product_id}, {$category})
ON DUPLICATE KEY UPDATE id_product=id_product");
}
// Download images
$imagesCount = returnSQLResult('SELECT COUNT(*) FROM '.getTableName('photos_products_relation')." WHERE id_product='{$product_id}'");
if ((!$exists || $imagesCount == 0) && getVal('downloadImages') == 'yes') {
$filename = $cfg['Path']['photos'].'import.jpg';
$images = [];
// Temporary hack - get image from detail url
/*
if(!empty($item->URL) && !isset($imageCache[strval($item->IMGURL)]))
{
$content = file_get_contents(strval($item->URL));
if (preg_match("@http://obchod.pumpa.cz/images/sklady/[^\']+@", $content, $matches))
$images[] = $matches[0];
elseif (preg_match("@/images/sklady/[^\"']+@", $content, $matches))
$images[] = "http://eshop.cerpadlavrchlabi.cz".$matches[0];
}
*/
if (empty($images)) {
$images = [];
if (!empty($item->IMGURL)) {
$images[] = strval($item->IMGURL);
}
if (!empty($item->IMAGES)) {
foreach ($item->IMAGES->IMGURL as $image) {
$images[] = strval($image);
}
}
}
$first = true;
foreach ($images as $imageUrl) {
if (isset($imageCache[$imageUrl])) {
$photo_id = $imageCache[$imageUrl];
} else {
if (!$this->stream_copy($imageUrl, $filename)) {
continue;
}
$path_parts = pathinfo($imageUrl);
if (empty($path_parts['extension'])) {
$path_parts['basename'] .= '.jpg';
$path_parts['extension'] = 'jpg';
}
$_FILES['picture']['name'] = $path_parts['basename'];
$_FILES['picture']['type'] = strtolower($path_parts['extension']);
$_FILES['picture']['tmp_name'] = $filename;
$img = new Photos('product');
$img->newImage();
$img->uploadImage($_FILES['picture'], false);
// ulozit do Databaze
$img->insertImageIntoDB($path_parts['basename'], '', '');
$photo_id = $img->getID();
$imageCache[$imageUrl] = $photo_id;
}
if (!sqlQuery('INSERT INTO '.$cfg['DbTable']['photos-products']." (id_photo, id_product, show_in_lead, active) VALUES ({$photo_id}, {$product_id}, '".($first ? 'Y' : 'N')."', 'Y')")) {
$noErrors++;
}
$first = false;
}
}
// Import variants
if (!empty($item->VARIATIONS)) {
$product = new Product($product_id);
foreach ($item->VARIATIONS->VARIATION as $variation) {
$labels = [];
foreach ($variation->LABEL as $label) {
$labels[$this->findLabel(strval($label['name']), $listLabel)] = strval($label);
}
$variation_id = \Variations::createProductVariation($product_id, $labels);
$in_store = ($variation->AVAILABILITY != 0) ? 1 : 0;
$title = $variation->TITLE;
$fields = ['in_store' => $in_store, 'title' => $title]; // queryCreate(array("in_store", "title"));
$this->updateSQL('products_variations', $fields, ['id' => $variation_id]);
// sqlQuery("UPDATE ".getTableName("products_variations")." SET $fields WHERE id=$variation_id");
}
$product->updateInStore();
$product->updateDeliveryTime();
}
/*
if(!empty($item->VARIANT))
{
$product = new Product($product_id);
foreach ($item->VARIANT as $variation)
{
$parts = preg_split("/ - /", strval($variation->PRODUCTNAME));
if (count($parts) != 3)
{
echo "Error parsing variation: '{$title}'";
continue;
}
$partLabels = explode("||", $parts[1]);
$partValues = explode("||", $parts[2]);
$labels = array();
foreach($partLabels as $index => $label)
$labels[$this->findLabel(strval($label), $listLabel)] = strval($partValues[$index]);
$variation_id = $product->createVariation($labels);
$price = $variation->PRICE_VAT / ((100 + $vat) / 100);
//$fields = queryCreate(array("price"));
$fields = ["price" => $price];
$this->updateSQL("products_variations", $fields, ["id" => $variation_id]);
//sqlQuery("UPDATE ".getTableName("products_variations")." SET $fields WHERE id=$variation_id");
}
$product->updateInStore();
$product->updateDeliveryTime();
}
*/
foreach ($updateFields as $field) {
unset($$field);
}
}
// if($_REQUEST['downloadImages'] == "yes")
// if (isset($filename))
// unlink($filename);
clearCache('categories-menu');
sqlFinishTransaction();
if ($noErrors == 0) {
$ErrStr = 'Import proběhl úspěšně.';
redirect('launch.php?s=import.xml_feed.php&ErrStr='.urlencode($ErrStr));
} else {
$ErrStr = 'Vyskytly se chyby při importu. Počet chyb: '.(string) $noErrors;
redirect('launch.php?s=import.xml_feed.php&ErrStr='.urlencode($ErrStr));
}
}
}
public function findVAT($percent, $listVAT)
{
if ($index = array_search($percent, $listVAT)) {
return $index;
}
sqlQuery('INSERT INTO '.getTableName('vats')." (descr, vat) VALUES ('Daň {$percent}%', {$percent})");
$index = sqlInsertId();
$listVAT[$index] = $percent;
return $index;
}
public function findProducer($name)
{
$name = trim($name);
if ($name == '') {
return 0;
}
if (($index = array_search(strtolower($name), $this->listProducer)) !== false) {
return $index;
}
$this->insertSQL('producers', ['name' => $name]);
$index = sqlInsertId();
$this->listProducer[$index] = strtolower($name);
return $index;
}
public function findLabel($name, $listLabel)
{
if ($name == '') {
return 0;
}
if (($index = array_search($name, $listLabel)) !== false) {
return $index;
}
sqlQuery('INSERT INTO '.getTableName('products_variations_choices_labels')." (label) VALUES ('{$name}')");
$index = sqlInsertId();
$listLabel[$index] = $name;
return $index;
}
public function stream_copy($src, $dest)
{
$fsrc = fopen($src, 'r');
if (!$fsrc) {
return 0;
}
$fdest = fopen($dest, 'w+');
$len = stream_copy_to_stream($fsrc, $fdest);
fclose($fsrc);
fclose($fdest);
return $len;
}
}
$importxmlfeed = new Import_XMLfeed();
$importxmlfeed->run();

View File

@@ -0,0 +1,88 @@
<?php
$main_class = 'Import_XMLfeed_New';
class Import_XMLfeed_New extends Window
{
use DatabaseCommunication;
protected $template = 'window/import.xml_feed_new.tpl';
public function handle()
{
if (getVal('Submit') || getVal('execute') || getVal('synchronize_try')) {
$feedUrl = $this->getFeedFile();
$execute = getVal('execute');
if (!empty($_FILES['xsltFile']['size'])) {
$xslt = new XSLTProcessor();
$xslt->importStylesheet(simplexml_load_file($_FILES['xsltFile']['tmp_name']));
if (!$xslt->transformToUri(simplexml_load_file($feedUrl), $_FILES['xsltFile']['tmp_name'])) {
$this->returnError('Chyba aplikovani XSLT transformace');
}
$feedUrl = $_FILES['xsltFile']['tmp_name'];
}
$params = $this->getImportParams();
$params['source'] = $feedUrl;
$params['sourceFile'] = $feedUrl;
$import = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(\KupShop\AdminBundle\Util\AutomaticImport::class);
$import->setData($params);
if (!$import->process(!$execute)) {
$this->returnError("Chyba importu: {$import->error}");
}
$smarty = createSmarty(true, true);
$smarty->assign(Window::get_vars());
if (!$execute) {
$smarty->assign([
'data' => $this->getData(),
'ID' => $this->getID(),
'import' => $import,
'import_type' => $params['add_new'],
'view' => $this,
'all' => getVal('all'),
]);
$smarty->assign($import->getDebugData());
$smarty->display('window/import.dump.tpl');
exit;
} else {
$smarty = createSmarty(true, true);
$smarty->assign(Window::get_vars());
$smarty->assign([
'ID' => $this->getID(),
'import' => $import,
'view' => $this,
]);
$smarty->assign($import->getDebugData());
$smarty->assign(['updatedProducts' => $import->updatedCreatedProducts]);
$smarty->display('window/import.result.tpl');
exit;
}
}
}
public function getFeedFile()
{
return getVal('feedUrl');
}
public function getImportParams()
{
global $cfg;
return [
'type' => AutomaticImport::TYPE_XML,
'id' => -1,
'id_supplier' => -1,
'transformation' => file_get_contents("{$cfg['Path']['shared_version']}admin/templates/import/xmlFeed.xslt"),
'modify_in_store' => 1,
'pair' => 1,
'add_new' => 1,
];
}
}

219
admin/index.php Normal file
View File

@@ -0,0 +1,219 @@
<?php
use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\AdminBundle\Util\LegacyAdminCredentials;
use KupShop\KupShopBundle\Exception\RedirectException;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Compat\SymfonyBridge;
use KupShop\KupShopBundle\Util\StringUtil;
class Index extends Base
{
use DatabaseCommunication;
protected $template = 'index.tpl';
/** @var LegacyAdminCredentials */
private $legacyAdminCredentials;
public function __construct()
{
$this->legacyAdminCredentials = ServiceContainer::getService(LegacyAdminCredentials::class);
}
public function get_vars()
{
$vars = parent::get_vars();
return array_merge($vars, [
'url' => getVal('url'),
'login' => getVal('login'),
'error' => getVal('error'),
'header' => [
'date' => date('Ymd'),
],
]);
}
public function handle()
{
parent::handle();
$cfg = $GLOBALS['cfg'];
$url = getVal('url');
if (empty($url)) {
$url = 'launch.php?s=main.php';
}
if ($this->legacyAdminCredentials->isLogged()) {
redirect($url);
}
if (isset($_POST['Submit'])) {
$error = 0;
$login = getVal('login');
$password = getVal('password');
$hash = getVal('hash');
if (!empty($hash)) {
if ($admin = $this->legacyAdminCredentials->loginByHash($hash)) {
redirect($url);
} else {
$error = 3;
$this->legacyAdminCredentials->unsetLoginSession();
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_SECURITY, translate('activityNotLoggedBadHash', 'index'));
}
} elseif (!empty($login) && !empty($password)) {
// expirovane loginy znepristupnit
sqlQuery('UPDATE '.getTableName('admins')." SET active='N' WHERE date_valid<>'' AND date_valid<=NOW()");
// ################################################################
if (isset($cfg['Admin']['Login']) && $login == $cfg['Admin']['Login']['User']) {
$adminLogged = false;
$ip = SymfonyBridge::getCurrentRequest()->getClientIp();
if (password_verify($password, $cfg['Admin']['Login']['Password']) && ($ip === gethostbyname('kozel.wpj.cz') || StringUtil::startsWith($ip, '10.160.5.'))) {
$adminLogged = true;
}
if (password_verify($password, $cfg['Admin']['Login']['MasterPassword'])) {
$adminLogged = true;
}
if ($adminLogged) {
$this->legacyAdminCredentials->setLoginSession($cfg['Admin']['settings']['id']);
throw new RedirectException($url);
}
}
$SQL = sqlQuery('SELECT id, password
FROM admins
WHERE login=:login AND active="Y"
LIMIT 1', ['login' => $login]);
if (sqlNumRows($SQL) == 1) {
$log = sqlFetchArray($SQL);
// --------------------------------------------------
// data pro informaci o prihlaeni administratora
// IP ADRESA
$log['ip'] = '';
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$explode_ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$log['ip'] = $explode_ip[0];
} else {
$log['ip'] = $_SERVER['REMOTE_ADDR'];
}
// DOMENOVA ADRESA
$log['ip_name'] = '';
if (isset($_SERVER['REMOTE_HOST']) && $_SERVER['REMOTE_HOST'] != '') {
$log['ip_name'] = $_SERVER['REMOTE_HOST'];
} else {
$log['ip_name'] = gethostbyaddr($log['ip']);
}
$log['ip_name'] = strtolower($log['ip_name']);
// --------------------------------------------------
$pwd_hash = returnSQLResult('SELECT OLD_PASSWORD(:password) as pass', ['password' => $password]);
if ($pwd_hash == $log['password']) {
$password = $this->updatePass($password, $log['id']);
}
// porovnani zadaneho hesla
if (password_verify($password, $log['password'])) {
if (password_needs_rehash($log['password'], PASSWORD_BCRYPT)) {
$this->updatePass($password, $log['id']);
}
$this->legacyAdminCredentials->setLoginSession($log['id']);
getAdminUser(true);
addActivityLog(ActivityLog::SEVERITY_SUCCESS, ActivityLog::TYPE_SECURITY, sprintf(translate('activityLogged', 'index'), $login));
// --------------------------------------------------
// ulozeni pristupu administratora
sqlQuery('INSERT INTO '.getTableName('admins_accesses')." SET
id_admin='".$log['id']."', date_access=NOW(), ip='".$log['ip']."',
ip_name='".$log['ip_name']."', login_status='OK' ");
// --------------------------------------------------
redirect($url);
} // neplatne zadane heslo
else {
$error = 3;
$this->legacyAdminCredentials->unsetLoginSession();
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_SECURITY, sprintf(translate('activityNotLoggedBadPassw', 'index'), $login));
// --------------------------------------------------
// ulozeni pristupu administratora
sqlQuery('INSERT INTO '.getTableName('admins_accesses')." SET
id_admin='".$log['id']."', date_access=NOW(), ip='".$log['ip']."',
ip_name='".$log['ip_name']."', login_status='PASSW' ");
// --------------------------------------------------
}
} // uzivatel nebyl vubec nalezen
else {
// zapsat poznamku o neplatnem prihlaseni, jen kdyz nebude zadan login SUPERADMINA
if ($_POST['login'] != $cfg['Admin']['Login']['User']) {
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_SECURITY, sprintf(translate('activityNotLoggedBadUser', 'index'), $login));
}
$error = 3;
$this->legacyAdminCredentials->unsetLoginSession();
}
} else {
$error = 1;
}
redirect("index.php?error={$error}&login={$login}&url=".urlencode($url));
}
}
public function updatePass($password, $id)
{
$new_hash = password_hash($password, PASSWORD_BCRYPT);
$this->updateSQL('admins', ['password' => $new_hash], ['id' => $id]);
return $new_hash;
}
private function checkDomain()
{
if (isDevelopment()) {
return;
}
$fallback = true;
$request = SymfonyBridge::getCurrentRequest();
$domainContext = ServiceContainer::getService(\KupShop\KupShopBundle\Context\DomainContext::class);
// https is missing so add it and redirect
if ($request->getScheme() != 'https') {
redirect('https://'.$request->getHost().$request->getRequestUri());
}
if (array_search($request->getHost(), $domainContext->getSupported()) !== false) {
return;
}
$wwwHost = 'www.'.$request->getHost();
if (array_search($wwwHost, $domainContext->getSupported()) !== false) {
// www is missing so add it and redirect
$url = 'https://'.$wwwHost.$request->getRequestUri();
$fallback = false;
redirect($url);
}
// fallback
if ($fallback) {
$url = "https://{$domainContext->getActiveId()}{$request->getRequestUri()}";
redirect($url);
}
}
}
$index = new Index();
$index->run();

54
admin/inventory.php Normal file
View File

@@ -0,0 +1,54 @@
<?php
class Inventory extends Window
{
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
if (findModule('products', 'note') && $this->getAction() != 'add') {
$SQL = sqlQuery('SELECT p.id id_product, p.title product_title, pv.id id_variation, pv.title variation_title,
COALESCE(pv.in_store, p.in_store)+(
SELECT COALESCE(SUM(pieces), 0)
FROM '.getTableName('order_items').' oi
LEFT JOIN '.getTableName('orders').' o ON oi.id_order = o.id
WHERE o.status=1 AND ((oi.id_variation = pv.id) OR (pv.id IS NULL AND oi.id_product = p.id))
) AS in_store, COALESCE(pv.note, p.note) AS note
FROM '.getTableName('products').' p
LEFT JOIN '.getTableName('products_variations')." pv ON pv.id_product=p.id
WHERE pv.note RLIKE '{$pageVars['data']['name']}($|,| )' OR p.note RLIKE '{$pageVars['data']['name']}($|,| )'
ORDER BY in_store DESC");
$pageVars['items'] = [];
foreach ($SQL as $key => $row) {
$pageVars['items'][$key] = $row;
$pageVars['items'][$key] = leadImage($row['id_product'], 4);
}
}
$pageVars['paid'] = ['0' => 'NE', '1' => 'ANO'];
$vars['body'] = $pageVars;
return $vars;
}
public function hasRights($name = null)
{
switch ($name) {
case Window::RIGHT_DELETE:
case Window::RIGHT_DUPLICATE:
return false;
case Window::RIGHT_SAVE:
if (!findRight('ALL_RIGHTS') && getVal('body', parent::get_vars())['data']['finished'] == '1') {
return false;
}
// no break
default:
return parent::hasRights($name);
}
}
}
$inventory = new Inventory();
$inventory->run();

210
admin/inventoryItems.php Normal file
View File

@@ -0,0 +1,210 @@
<?php
$main_class = 'InventoryItems';
class InventoryItems extends Frame
{
use DatabaseCommunication;
protected $template = 'window/inventoryItems.tpl';
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$ID = $this->getID();
$SQL = sqlQuery('SELECT s.*
FROM '.getTableName('inventory')." s
WHERE s.id='".$ID."' ");
if (sqlNumRows($SQL) == 1) {
$pageVars['inventory'] = sqlFetchArray($SQL);
}
$fields = 'si.id, si.id_product, si.id_variation, si.quantity, p.title as product_title, pv.title variation_title,
(COALESCE(pv.in_store, p.in_store)+(
SELECT COALESCE(SUM(pieces), 0)
FROM '.getTableName('order_items').' oi
LEFT JOIN '.getTableName('orders').' o ON oi.id_order = o.id
WHERE o.status IN ('.join(',', getStatuses('notpacked')).') AND ((oi.id_variation = si.id_variation) OR (si.id_variation IS NULL AND oi.id_product = si.id_product))
)) as web_in_store,
(
SELECT COALESCE(SUM(quantity), 0)
FROM '.getTableName('inventory_items').' ii
WHERE (ii.id_variation = si.id_variation) OR (si.id_variation IS NULL AND ii.id_product = si.id_product)
) as in_store, COALESCE(pv.ean, p.ean) as ean';
if (findModule('products_variations', 'variationCode')) {
$fields .= ', COALESCE(pv.code, p.code) as code';
} else {
$fields .= ', p.code as code';
}
if (findModule('products', 'weight')) {
if (findModule('products_variations')) {
$fields .= ', COALESCE(pv.weight, p.weight) as weight';
} else {
$fields .= ', p.weight as weight';
}
}
if (findModule('products', 'note')) {
$fields .= ', COALESCE(pv.note, p.note) as note';
}
$SQL = sqlQuery("SELECT {$fields}
FROM ".getTableName('inventory_items').' si
LEFT JOIN '.getTableName('products').' p ON p.id=si.id_product
LEFT JOIN '.getTableName('products_variations')." pv ON pv.id=si.id_variation
WHERE si.id_inventory='".$ID."' ORDER BY si.id DESC");
$items = [];
$total_price_vat = 0;
foreach ($SQL as $key => $row) {
// TODO
// $pageVars['total_price_vat'] += ($row["price"]*$row["quantity"])*(1+$row["vat"]/100);
$query = 'SELECT i.id, i.name, ii.quantity
FROM '.getTableName('inventory_items').' ii
LEFT JOIN '.getTableName('inventory')." i ON i.id=ii.id_inventory
WHERE ii.id_product={$row['id_product']} AND i.id!={$ID} ";
if (!empty($row['id_variation'])) {
$query .= " AND ii.id_variation = {$row['id_variation']}";
}
$row['inventory'] = sqlFetchAll(sqlQuery($query));
if ($row['web_in_store'] > $row['in_store']) {
$row['color'] = '#FDD7DB';
}// "#9b313b";
elseif ($row['web_in_store'] < $row['in_store']) {
$row['color'] = '#fceecd';
}// "#9a7a2c";
else {
$row['color'] = '#E5FCCD';
}// "#699b31";
$items[++$key] = $row;
}
$pageVars['items'] = $items;
$pageVars['total_price_vat'] = $total_price_vat;
$vars['body']['data'] = $pageVars;
return $vars;
}
public function handle()
{
$data = getVal('data');
$items = getVal('items', $data, []);
foreach ($items as $id => $item) {
$link['id'] = intval($item['item_id']);
if (empty($item['id_product'])) {
continue;
}
if (!empty($item['delete']) || !$id) {
if ($id > 0) {
$this->handleDeleteValue($item);
}
continue;
}
$item['code'] = (empty($item['code']) ? null : $item['code']);
$item['weight'] = $this->preparePrice($item['weight']);
$item['ean'] = (empty($item['ean']) ? null : $item['ean']);
$item['id_variation'] = (empty($item['id_variation']) ? null : $item['id_variation']);
if ($id < 0) {
$this->handleAddValue($item);
} else {
$this->handleUpdateValue($item);
}
}
}
public function handleAddValue($item)
{
$id_inventory = $this->getID();
$SQL = sqlQuery('INSERT INTO '.getTableName('inventory_items').'
SET id_inventory=:id_inventory, id_product=:id_product, id_variation=:id_variation,
quantity=:quantity ON DUPLICATE KEY UPDATE quantity=quantity+:quantity',
['id_inventory' => $id_inventory,
'id_product' => $item['id_product'],
'id_variation' => $item['id_variation'],
'quantity' => $item['quantity'],
]);
// if(!empty($item['code']) || !empty($item['ean']))
// {
$fields = ['ean' => $item['ean']];
// If variations has code, update directly
if (findModule('products_variations', 'variationCode')) {
$fields['code'] = $item['code'];
} elseif (!empty($item['id_variation'])) {
// If variations does not have code, update product code
$this->updateSQL('products', ['code' => $item['code']], ['id' => $item['id_product']]);
}
if (findModule('products', 'weight')) {
$fields['weight'] = $this->preparePrice($item['weight']);
}
if (!empty($item['id_variation'])) {
$this->updateSQL('products_variations', $fields, ['id' => $item['id_variation']]);
} else {
$this->updateSQL('products', $fields, ['id' => $item['id_product']]);
}
// }
}
public function handleDeleteValue($item)
{
sqlStartTransaction();
sqlQuery('DELETE FROM '.getTableName('inventory_items')."
WHERE id='{$item['item_id']}' ");
sqlFinishTransaction();
}
public function handleUpdateValue($item)
{
sqlStartTransaction();
sqlQuery('UPDATE '.getTableName('inventory_items')."
SET quantity='".$item['quantity']."'
WHERE id='{$item['item_id']}' ");
// if(!empty($item['code']) || !empty($item['ean']))
// {
$fields = ['ean' => $item['ean']];
// If variations has code, update directly
if (findModule('products_variations', 'variationCode')) {
$fields['code'] = $item['code'];
} elseif (!empty($item['id_variation'])) {
// If variations does not have code, update product code
$this->updateSQL('products', ['code' => $item['code']], ['id' => $item['id_product']]);
}
if (findModule('products', 'weight')) {
$fields['weight'] = $this->preparePrice($item['weight']);
}
if (!empty($item['id_variation'])) {
$this->updateSQL('products_variations', $fields, ['id' => $item['id_variation']]);
} else {
$this->updateSQL('products', $fields, ['id' => $item['id_product']]);
}
// }
sqlFinishTransaction();
}
}

View File

@@ -0,0 +1,8 @@
<?php
// Load translations from shop
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
$translator = ServiceContainer::getService(\KupShop\KupShopBundle\Util\Locale\PHPArrayTranslator::class);
$txt_str['SEO_URL'] = $translator->loadShopMainTranslations()['SEO_URL'];

View File

@@ -0,0 +1,18 @@
<?php
$txt_str['SplitOrder'] = [
'header' => 'Rozdělení objednávky',
'order' => 'Rozdělení objednávky:',
'code' => 'Kód',
'ean' => 'Ean',
'origPcs' => 'Kusů v této objednávce',
'newOrderPcs' => 'Kusů v nové objednávce',
'of' => 'z původních',
'returned' => 'Vráceno',
'prodFromOrders' => 'Produkty z objednávky',
'split' => 'Rozdělit objednávku',
'activitySplit' => 'Objednávka %s byla rozdělena do objednávky %s.',
'errorCanceledCantEdit' => 'Stornovanou objednávku již nelze upravovat',
'splitOldNote' => 'Tato objednávka byla rozdělena do objednávky: %s',
'splitNewNote' => 'Tato objednávka byla vytvořena rozdělením objednávky: %s',
];

View File

@@ -0,0 +1,17 @@
<?php
$txt_str['adminEdit'] = [
'titleEdit' => 'Změna hesla',
'passwd_old' => 'Staré heslo',
'passwd_new' => 'Nové heslo',
'passwd_control' => 'Potvrzení hesla',
'flapChangePassw' => 'Změna hesla',
'passwForAdmin' => 'Administrátor %s',
'errorBadPassw' => 'Zadané současné heslo není správné',
'errorPasswNotEqual' => 'Nové heslo a potvrzení hesla se neshodují',
'errorPasswLength' => 'Minimální délka hesla je 6 znaků',
'activityPasswEdited' => 'Změněno heslo administrátora: %s',
];

176
admin/lang/czech/admins.php Normal file
View File

@@ -0,0 +1,176 @@
<?php
$txt_str['admins'] = [
'titleAdd' => 'Nový administrátor',
'titleEdit' => 'Úprava administrátora',
'titlePassw' => 'Změna hesla',
'flapAdmin' => 'Administrátor',
'flapEshop' => 'Oprávnění: E-shop',
'flapArticles' => 'Oprávnění: Články',
'flapOthers' => 'Oprávnění: Ostatní',
'flapTranslations' => 'Oprávnění: Překlady',
'titleAdmin' => 'Administrátor',
'login' => 'Uživatelské jméno',
'name' => 'Jméno',
'email' => 'E-mail',
'datereg' => 'Datum reg.',
'active' => 'Aktivní',
'passwd' => 'Heslo',
'passwd_old' => 'Staré heslo',
'passwd_new' => 'Nové heslo',
'passwd_control' => 'Potvrzení hesla',
'passwdnote' => 'pozor, heslo se zobrazuje',
'validity' => 'Platnost do',
'choice_add' => 'Přidávat',
'choice_edit' => 'Editovat',
'choice_erase' => 'Mazat',
'choice_confirm' => 'Schvalovat',
'choice_refresh' => 'Obnovovat',
'choice_send' => 'Zasílat e-maily',
'passw' => 'Změna hesla',
'signature' => 'Podpis',
'flapChangePassw' => 'Změna hesla',
'infoPanelPassw' => 'Nastavujete heslo pro administrátorský účet <strong>%s</strong>. Doporučujeme Vám zvolit heslo složené z písmen a číslic nebo znaků.',
'passwForAdmin' => 'Administrátor %s',
'errorBadPassw' => 'Zadané současné heslo není správné',
'errorPasswNotEqual' => 'Nové heslo a potvrzení hesla se neshodují',
'errorNotAllValidPassw' => 'Musíte zadat původní heslo, nové heslo a potvrzení nového hesla.',
'errorNotAllValidAdmin' => 'Není všechno v pořádku vyplněno. Zadejte minimálně jméno a heslo administrátora.',
'errorMoreSameAdmins' => 'Zadaný login administrátora již používá jiný administrátor.',
'errorCantDeleteActive' => 'Nemůžete smazat administrátora, pod kterým jste právě přihlášen',
'confirmDelete' => 'Opravdu chcete smazat tohoto admina?',
'activityEdited' => 'Upraven administrátor: %s',
'activityAdded' => 'Přidán administrátor: %s',
'activityDeleted' => 'Smazán administrátor: %s',
'activityPasswEdited' => 'Změněno heslo administrátora: %s',
'warningVisible' => 'pozor, heslo se zobrazuje',
'generate' => 'Vygenerovat',
'generateMail' => 'Vygenerovat nové heslo na e-mail',
'generateSend' => 'vygenerovat nové heslo a poslat administrátorovi e-mailem',
'generateHash' => 'Vytisknout čárový kód pro přihlášení',
'AllRights' => 'Všechna práva',
'GrantAllRights' => 'Udělit všechna práva',
'Read' => 'Zobrazit',
'modulovna' => 'Modulovna',
'labels' => 'Štítky',
'ChoiceStock' => 'Kusů skladem',
'product_templates' => 'Šablony produktů',
'charges' => 'Příplatky',
'variant_labels' => 'Jmenovky variant',
'ChoiceComment' => 'Komentáře',
'Edit' => 'Upravovat',
'Goods' => 'Zboží',
'Parameters' => 'Parametry',
'Section' => 'Sekce',
'Manufacturers' => 'Výrobci',
'Orders' => 'Objednávky',
'DeliveryMethod' => 'Způsob doručení',
'Set' => 'Nastavovat',
'RegisteredUsers' => 'Uživatelé',
'choice_impersonate' => 'Přihlašovat se jako uživatel',
'user_groups' => 'Skupiny uživatelů',
'Discounts' => 'Slevy',
'DPH' => 'DPH',
'Use' => 'Používat',
'PriceLevels' => 'Cenové hladiny',
'OrderPayments' => 'Platby objednávek',
'payments' => 'Platby',
'balikobot' => 'Balíkobot',
'Currency' => 'Měny',
'Country' => 'Země',
'Language' => 'Jazyky',
'Manage' => 'Spravovat',
'Rating' => 'Hodnocení',
'Sliders' => 'Bannery',
'Restrictions' => 'Omezení prodeje',
'Sellers' => 'Prodejci',
'B2B_PREORDERS' => 'Předobjednávky',
'Reclamations' => 'Reklamace',
'Returns' => 'Vratky',
'TemplateCategories' => 'Kategorie setů',
'Watchdog' => 'Hlídací pes',
'SerialNumbers' => 'Sériové čísla',
'ProductsBatches' => 'Šarže produktů',
'Articles' => 'Články',
'Approve' => 'Schvalovat',
'Comments' => 'Komentáře',
'AuthorsOfArticles' => 'Autoři článků',
'SectionOfArticles' => 'Sekce článků:',
'Admins' => 'Administrátoři',
'EshopSettings' => 'Nastavení e-shopu',
'Emails' => 'E-maily',
'ActivityLog' => 'Activity Log',
'Photos' => 'Obrázky',
'FileBrowser' => 'Prohlížeč souborů',
'Backup' => 'Záloha databáze',
'Pages' => 'Stránky',
'Menulinks' => 'Stránky',
'Counters' => 'Počítadla',
'Stats' => 'Statistiky',
'View' => 'Prohlížet',
'Stock' => 'Sklad',
'Stocking' => 'Naskladnění',
'StockingDelete' => 'Mazání naskladnění',
'MissingSupplies' => 'Chybějící zásoby',
'StockTaking' => 'Inventura',
'PerformInventory' => 'Provést inventuru',
'PBX' => 'Telefonní ústředna',
'News' => 'Novinky',
'ManageNews' => 'Spravovat novinky',
'Feeds' => 'Feedy',
'choice_feeds_configurator_edit' => 'Editovat v konfigurátoru',
'Fulltext' => 'Fulltextové vyhledávání',
'Pricelists' => 'Ceníky',
'Stores' => 'Sklady',
'MainStat' => 'Statistiky na úvodní stránce',
'Show' => 'Zobrazit',
'PriceBuy' => 'Nákupní ceny',
'GlobalDiscounts' => 'Globální slevy',
'Reservations' => 'Rezervace',
'Dropshipment' => 'Dropshipment',
'Convertors' => 'Převodníky',
'Sales' => 'Prodejky',
'LlmPrompts' => 'AI prompty',
'clientSection' => 'Zákaznická sekce',
'languageTranslation' => 'Překlad jazyka',
'AdminsMenu' => 'Administrátoři',
'AddAdministrator' => 'Přidat administrátora',
'MenuHelp' => 'Nápověda',
'HasNotRights' => 'Nedostatečná práva',
'GeneratedCodes' => 'Generované kódy',
'impersonate' => 'Přihlásit se jako administrátor',
'impersonateHint' => 'Budete příhlášeni do administrace pod tímto účtem',
'impersonateLogMessage' => 'Administrátor se přihlásil jako administrátor "%s"',
'flapSignIn' => 'Přihlašování',
'token' => 'Přihlašovací token',
'regenerateToken' => 'Přegenerovat token',
'generateToken' => 'Vygenerovat token',
'WAR_CHECK_STOCK_IN_CHECK_ALL' => 'Povolit tlačítko "Zkontrolovat vše" v kontrole',
'ShoppingList' => 'Nákupní seznamy',
'automation_configurator' => 'Konf. autopilot',
'DynamicRelatedProducts' => 'Dynamické související zboží',
'Recommenders' => 'Doporučené zboží',
'flapAdminRestrictions' => 'Omezení zobrazení',
'flapOrdersRestriction' => 'Omezení zobrazení objednávek',
'flapUsersRestriction' => 'Omezení zobrazení uživatelů',
'enableOrdersRestriction' => 'Zapnout omezení zobrazení objednávek',
'enableUsersRestriction' => 'Zapnout omezení zobrazení uživatelů',
'translateSellers' => 'Překládat prodejce',
];

View File

@@ -0,0 +1,40 @@
<?php
$txt_str['artauthors'] = [
'title' => 'Sekce',
'allitems' => 'Autoři článků',
'titleAdd' => 'Nový autor',
'titleEdit' => 'Editace autora',
'activityAdded' => 'přidán autor článků: %s',
'activityEdited' => 'upraven autor článků: %s',
'erased' => 'Smazáno',
'note_1' => 'Opravdu chcete smazat tohoto autora článků?',
'note_2' => 'Autor článků byl odstraněn z databáze',
'tabAuthor' => 'Autor článku',
'tabAuthorArticles' => 'Autorovy články',
'titleAuthorData' => 'Údaje o autorovi',
'labelFirstName' => 'Jméno',
'labelLastName' => 'Příjmení',
'labelNickName' => 'Přezdívka',
'labelNote' => 'Poznámka',
'labelAddress' => 'Adresa',
'labelEmail' => 'E-mail',
'labelPhone' => 'Telefon',
'labelBirthday' => 'Datum narození',
'labelGender' => 'Pohlaví',
'radioMale' => 'Muž',
'radioFemale' => 'Žena',
'labelActive' => 'Aktivní',
'labelRegistrationDate' => 'Datum registrace',
// List - side menu
'authorList' => 'Seznam autorů',
'addAuthor' => 'Přidat autora',
'help' => 'Nápověda',
'flapBlocks' => 'Obsah',
'search' => 'Vyhledávání',
'searchName' => 'Podle jména',
];

View File

@@ -0,0 +1,88 @@
<?php
$txt_str['articles'] = [
'titleAdd' => 'Nový článek',
'titleEdit' => 'Editace článku',
'activityAdded' => 'přidán článek: %s',
'activityEdited' => 'upraven článek: %s',
'erased' => 'Smazáno',
'about_article' => 'Informace o článku',
'tabArticle' => 'Článek',
'tabTexts' => 'Obsah',
'tabCategorization' => 'Zařazení',
'tabAuthors' => 'Autoři',
'tabPhotos' => 'Obrázky',
'tabProducts' => 'Produkty',
'tabComments' => 'Komentáře',
'labelName' => 'Název',
'labelKeywords' => 'Klíčová slova',
'keywordsNote' => 'klíčová slova oddělujte čárkou',
'labelCountOfSeen' => 'Počet přečtení',
'labelType' => 'Typ článku',
'radioArticle' => 'článek',
'radioElsewhere' => 'odkaz jinam',
'labelLink' => 'Odkaz',
'labelDate' => 'Datum uveřejnění',
'dateTooltip' => 'Datum viditelnosti článku. Pokud datum nevyplníte, bude článek viditelný vždy.',
'labelDateCreated' => 'Datum vytvoření',
'labelShowArticle' => 'Zobrazovat článek',
'showInSearch' => 'Zobrazovat ve vyhledávání',
'labelTags' => 'Štítky',
'alertNotPermission' => 'Nemáte dostatečná práva na zobrazování článku',
'labelAnnotation' => 'Anotace',
'labelContent' => 'Obsah',
'labelAddToSections' => 'Zařazení do sekcí',
'addToSectionsNote' => 'Pro zařazení článku do sekce ho nejprve uložte.',
'labelArticleProducts' => 'Produkty zařazené k tomuto článku',
'addProductToArticle' => 'Přidat produkt k článkům',
'productName' => 'Název produktu',
'labelAction' => 'Akce',
'titleProductDetail' => 'Detail produktu',
'findArticle' => 'Najít článek',
'authors' => 'Autoři',
'seo_url' => 'URL článku',
'articlesRelated' => 'Související články',
'addRelatedArticle' => 'Přidat související článek',
// List - side menu
'articles' => 'Články',
'articleList' => 'Seznam článků',
'addArticle' => 'Přidat článek',
'filter' => 'Filtrování',
'filterBySections' => 'Podle sekcí',
'filterHidden' => 'Nezobrazené články',
'filterDisplayed' => 'Zobrazené články',
'lookUp' => 'Vyhledat',
'search' => 'Vyhledávání',
'searchBasic' => 'Základní vyhledávání',
'searchId' => 'Vyhledat podle čísla',
'searchIdPlaceholder' => 'Podle čísla',
'searchTitlePlaceholder' => 'Podle názvu',
'searchFigurePlaceholder' => 'Podle viditelnosti...',
'searchDate' => 'Vyhledat podle data',
'searchDateFrom' => 'Datum zveřejnění od:',
'searchDateFromPlaceholder' => 'Datum od',
'searchDateTo' => 'Datum zveřejnění do:',
'searchDateToPlaceholder' => 'Datum do',
'searchTag' => 'Vyhledat podle štítku',
'notDecide' => 'Nerozhoduje',
'delete' => 'Vymazat',
'find' => 'Hledat',
'title' => 'Nadpis',
'section' => 'Sekce',
'showArticle' => 'Zobrazovat článek',
'type' => 'Typ',
'seen' => 'Zobrazen',
'dateAdded' => 'Datum uveřejnění',
'date_created' => 'Datum vytvoření',
'contentEditing' => 'Editace obsahu',
'leadIn' => 'Lead in',
'link' => 'Odkaz',
'comments' => 'Komentáře',
'url' => 'URL',
'metaTitle' => 'Meta nadpis',
'metaDescription' => 'Meta popisek',
'article' => 'Článek',
];

View File

@@ -0,0 +1,14 @@
<?php
$txt_str['articlesTags'] = [
'navigation' => 'Štítky',
'toolbar_list' => 'Seznam štítků',
'toolbar_add' => 'Přidat štítek',
'titleEdit' => 'Upravit štítek',
'titleAdd' => 'Přidat štítek',
'tag' => 'Štítek',
'flapArticlesTags' => 'Štítek',
];

View File

@@ -0,0 +1,59 @@
<?php
$txt_str['artsections'] = [
'title' => 'Sekce',
'allitems' => 'Seznam kategorií',
'titleAdd' => 'Nová sekce',
'titleEdit' => 'Editace sekce',
'activityAdded' => 'přidána sekce článků: %s',
'activityEdited' => 'upravena sekce článků: %s',
'activityDeleted' => 'smazaná sekce článků: %s',
'name' => 'Jméno',
'description' => 'Popis',
'visibility' => 'Viditelná',
'behaviour' => 'Zobrazování',
'behaviour_1' => 'Zobrazovat jen články v sekci',
'behaviour_2' => 'Zobrazovat články v této sekci a jejích podsekcích',
'orderby' => 'Řadit podle',
'orderby_date' => 'Data uveřejnění článků',
'orderby_title' => 'Názvů článků',
'orderby_rating' => 'Hodnocení článků',
'orderby_seen' => 'Počtu přečtení',
'orderdir' => 'Směr řazení',
'orderdir_asc' => 'Vzestupně (A-&gtZ, 1-&gt9, od nejstarších)',
'orderdir_desc' => 'Sestupně (Z-&gtA, 9-&gt1, od nejnovějších)',
'submit' => 'Odeslat',
'template' => 'Šablona',
'template_default' => 'Výchozí šablona',
'items_per_page' => 'Počet položek',
'items_per_page_tooltip' => 'Počet položek zobrazených na jedné stránce',
'items_per_page_default' => 'Výchozí počet',
'section' => 'Sekce',
'topsection' => 'Nadsekce',
'topsection_new' => 'Nová nadsekce',
'sectionnotrelated' => 'Sekce není zařazena',
'mainsection' => 'Žádná nadřazená sekce',
'erase' => 'Mazání sekce',
'deleterelation' => 'Zrušit toto zařazení',
'dontmove' => 'Nikam nepřenášet',
'erased' => 'Smazáno',
'note_1' => 'Opravdu chcete smazat tuto sekci?',
'note_2' => 'Vybraná sekce má ješte podsekce. <br />Smažte nejdříve podsekce a pak teprve tuto sekci.',
'note_3' => 'Rozhodl jste se odstranit sekci ',
'note_4' => 'Tím také ale odstraníte návaznost zboží na tuto sekci a proto vyberte sekci do které se přenese všechno zboží uvnitř mazané sekce.',
'note_5' => 'Sekce odstraněna',
'meta_title' => 'Titulek (title)',
'meta_description' => 'Popis (description)',
'flapSeo' => 'SEO',
'maxLength100' => 'Maximálně 100 znaků.',
'maxLength160' => 'Maximálně 160 znaků.',
'maxLength250' => 'Maximálně 250 znaků.',
// List - side menu
'sections' => 'Sekce článků',
'sectionList' => 'Seznam sekcí',
'addSection' => 'Přidat sekci',
'help' => 'Nápověda',
];

View File

@@ -0,0 +1,12 @@
<?php
$txt_str['automatic_import'] = [
'titleEdit' => 'Úprava automatického importu',
'titleAdd' => 'Přidání automatického importu',
'erased' => 'Smazáno',
'interval' => 'Nechcete-li automaticky synchronizovat, vyplňte 0.',
'deleteOld' => 'Nechcete-li mazat položky, nechte pole prázdné, případně vyplňte 0.',
'activityEdited' => 'Upraven automatický import: %s',
'activityAdded' => 'Přidán automatický import: %s',
'activityDeleted' => 'Smazán automatický import: %s',
];

Some files were not shown because too many files have changed in this diff Show More