Add view classes for articles, banners, languages, menu, newsletter, containers, shop categories, clients, payment methods, products, and search

- Created Articles.php for rendering article views including full articles, miniature lists, and news sections.
- Added Banners.php for handling banner displays.
- Introduced Languages.php for rendering language options.
- Implemented Menu.php for dynamic menu rendering.
- Developed Newsletter.php for newsletter view rendering.
- Created Scontainers.php for rendering specific containers.
- Added ShopCategory.php for category descriptions and product listings.
- Introduced ShopClient.php for managing client-related views such as address editing and order history.
- Implemented ShopPaymentMethod.php for displaying payment methods in the basket.
- Created ShopProduct.php for generating product URLs.
- Added ShopSearch.php for rendering a simple search form.
- Added .htaccess file to enhance security by restricting access to sensitive files and directories.
This commit is contained in:
2026-02-21 23:00:15 +01:00
parent b51244c1d6
commit 3ecbe628dc
435 changed files with 44107 additions and 31270 deletions

449
autoload/admin/App.php Normal file
View File

@@ -0,0 +1,449 @@
<?php
namespace admin;
class App
{
const APP_SECRET_KEY = 'c3cb2537d25c0efc9e573d059d79c3b8';
/**
* Mapa nowych kontrolerów: module => fabryka kontrolera (DI)
*/
private static $newControllers = [];
public static function finalize_admin_login( array $user, string $domain, string $cookie_name, bool $remember = false )
{
\Shared\Helpers\Helpers::set_session( 'user', $user );
\Shared\Helpers\Helpers::delete_session( 'twofa_pending' );
if ( $remember ) {
$payloadArr = [
'login' => $user['login'],
'ts' => time()
];
$json = json_encode( $payloadArr, JSON_UNESCAPED_SLASHES );
$sig = hash_hmac( 'sha256', $json, self::APP_SECRET_KEY );
$payload = base64_encode( $json . '.' . $sig );
setcookie( $cookie_name, $payload, [
'expires' => time() + ( 86400 * 14 ),
'path' => '/',
'domain' => $domain,
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
] );
}
}
public static function special_actions()
{
global $mdb;
$sa = \Shared\Helpers\Helpers::get( 's-action' );
if ( !$sa ) return;
$domain = preg_replace( '/^www\./', '', $_SERVER['SERVER_NAME'] );
$cookie_name = 'admin_remember_' . str_replace( '.', '-', $domain );
$users = new \Domain\User\UserRepository( $mdb );
switch ( $sa )
{
case 'user-logon':
$login = \Shared\Helpers\Helpers::get( 'login' );
$pass = \Shared\Helpers\Helpers::get( 'password' );
$result = $users->logon( $login, $pass );
if ( $result == 1 )
{
$user = $users->details( $login );
if ( !$user ) {
\Shared\Helpers\Helpers::alert( 'Błąd logowania.' );
header( 'Location: /admin/' );
exit;
}
if ( $user['twofa_enabled'] == 1 )
{
\Shared\Helpers\Helpers::set_session( 'twofa_pending', [
'uid' => (int) $user['id'],
'login' => $login,
'remember' => (bool) \Shared\Helpers\Helpers::get( 'remember' ),
'started' => time(),
] );
if ( !$users->sendTwofaCode( (int) $user['id'] ) )
{
\Shared\Helpers\Helpers::alert( 'Nie udało się wysłać kodu 2FA. Spróbuj ponownie.' );
\Shared\Helpers\Helpers::delete_session( 'twofa_pending' );
header( 'Location: /admin/' );
exit;
}
header( 'Location: /admin/user/twofa/' );
exit;
}
self::finalize_admin_login( $user, $domain, $cookie_name, (bool) \Shared\Helpers\Helpers::get( 'remember' ) );
header( 'Location: /admin/articles/list/' );
exit;
}
if ( $result == -1 )
\Shared\Helpers\Helpers::alert( 'Z powodu 5 nieudanych prób Twoje konto zostało zablokowane.' );
else
\Shared\Helpers\Helpers::alert( 'Podane hasło jest nieprawidłowe lub użytkownik nie istnieje.' );
header( 'Location: /admin/' );
exit;
case 'user-2fa-verify':
$pending = \Shared\Helpers\Helpers::get_session( 'twofa_pending' );
if ( !$pending || empty( $pending['uid'] ) ) {
\Shared\Helpers\Helpers::alert( 'Sesja 2FA wygasła. Zaloguj się ponownie.' );
header( 'Location: /admin/' );
exit;
}
$code = trim( (string) \Shared\Helpers\Helpers::get( 'twofa' ) );
if ( !preg_match( '/^\d{6}$/', $code ) )
{
\Shared\Helpers\Helpers::alert( 'Nieprawidłowy format kodu.' );
header( 'Location: /admin/user/twofa/' );
exit;
}
if ( !$users->verifyTwofaCode( (int) $pending['uid'], $code ) )
{
\Shared\Helpers\Helpers::alert( 'Błędny lub wygasły kod.' );
header( 'Location: /admin/user/twofa/' );
exit;
}
$user = $users->details( $pending['login'] );
if ( !$user ) {
\Shared\Helpers\Helpers::delete_session( 'twofa_pending' );
\Shared\Helpers\Helpers::alert( 'Sesja wygasła. Zaloguj się ponownie.' );
header( 'Location: /admin/' );
exit;
}
self::finalize_admin_login( $user, $domain, $cookie_name, !empty( $pending['remember'] ) );
header( 'Location: /admin/articles/list/' );
exit;
case 'user-2fa-resend':
$pending = \Shared\Helpers\Helpers::get_session( 'twofa_pending' );
if ( !$pending || empty( $pending['uid'] ) )
{
\Shared\Helpers\Helpers::alert( 'Sesja 2FA wygasła. Zaloguj się ponownie.' );
header( 'Location: /admin/' );
exit;
}
if ( !$users->sendTwofaCode( (int) $pending['uid'], true ) )
\Shared\Helpers\Helpers::alert( 'Kod można wysłać ponownie po krótkiej przerwie.' );
else
\Shared\Helpers\Helpers::alert( 'Nowy kod został wysłany.' );
header( 'Location: /admin/user/twofa/' );
exit;
case 'user-logout':
setcookie( $cookie_name, '', [
'expires' => time() - 86400,
'path' => '/',
'domain' => $domain,
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
] );
\Shared\Helpers\Helpers::delete_session( 'twofa_pending' );
session_destroy();
header( 'Location: /admin/' );
exit;
}
}
/**
* Entry point — auth check + layout rendering.
*/
public static function render(): string
{
global $user;
if ( \Shared\Helpers\Helpers::get( 'module' ) === 'user' && \Shared\Helpers\Helpers::get( 'action' ) === 'twofa' ) {
$controller = self::createController( 'Users' );
return $controller->twofa();
}
if ( !$user || !$user['admin'] )
{
$controller = self::createController( 'Users' );
return $controller->login_form();
}
$tpl = new \Shared\Tpl\Tpl;
$tpl->content = self::route();
return $tpl->render( 'site/main-layout' );
}
/**
* Routing — buduje nazwę modułu z URL i wywołuje akcję kontrolera.
*/
public static function route()
{
$_SESSION['admin'] = true;
if ( \Shared\Helpers\Helpers::get( 'p' ) )
\Shared\Helpers\Helpers::set_session( 'p', \Shared\Helpers\Helpers::get( 'p' ) );
// Budowanie nazwy modułu: shop_product → ShopProduct
$moduleName = '';
$parts = explode( '_', (string) \Shared\Helpers\Helpers::get( 'module' ) );
foreach ( $parts as $part )
$moduleName .= ucfirst( $part );
$action = \Shared\Helpers\Helpers::get( 'action' );
$controller = self::createController( $moduleName );
if ( $controller && method_exists( $controller, $action ) )
return $controller->$action();
\Shared\Helpers\Helpers::alert( 'Nieprawidłowy adres url.' );
return false;
}
/**
* Tworzy instancję kontrolera z Dependency Injection.
*/
private static function createController( string $moduleName )
{
$factories = self::getControllerFactories();
if ( !isset( $factories[$moduleName] ) )
return null;
$factory = $factories[$moduleName];
return is_callable( $factory ) ? $factory() : null;
}
/**
* Zwraca mapę fabryk kontrolerów (lazy init).
*/
private static function getControllerFactories(): array
{
if ( !empty( self::$newControllers ) )
return self::$newControllers;
self::$newControllers = [
'Dashboard' => function() {
global $mdb;
return new \admin\Controllers\DashboardController(
new \Domain\Dashboard\DashboardRepository( $mdb ),
new \Domain\ShopStatus\ShopStatusRepository( $mdb )
);
},
'Articles' => function() {
global $mdb;
return new \admin\Controllers\ArticlesController(
new \Domain\Article\ArticleRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb ),
new \Domain\Layouts\LayoutsRepository( $mdb ),
new \Domain\Pages\PagesRepository( $mdb )
);
},
'ArticlesArchive' => function() {
global $mdb;
return new \admin\Controllers\ArticlesArchiveController(
new \Domain\Article\ArticleRepository( $mdb )
);
},
'Banners' => function() {
global $mdb;
return new \admin\Controllers\BannerController(
new \Domain\Banner\BannerRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'Settings' => function() {
global $mdb;
return new \admin\Controllers\SettingsController(
new \Domain\Settings\SettingsRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'ProductArchive' => function() {
global $mdb;
return new \admin\Controllers\ProductArchiveController(
new \Domain\Product\ProductRepository( $mdb )
);
},
'Archive' => function() {
global $mdb;
return new \admin\Controllers\ProductArchiveController(
new \Domain\Product\ProductRepository( $mdb )
);
},
'Dictionaries' => function() {
global $mdb;
return new \admin\Controllers\DictionariesController(
new \Domain\Dictionaries\DictionariesRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'Filemanager' => function() {
return new \admin\Controllers\FilemanagerController();
},
'Users' => function() {
global $mdb;
return new \admin\Controllers\UsersController(
new \Domain\User\UserRepository( $mdb )
);
},
'Languages' => function() {
global $mdb;
return new \admin\Controllers\LanguagesController(
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'Layouts' => function() {
global $mdb;
return new \admin\Controllers\LayoutsController(
new \Domain\Layouts\LayoutsRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'Newsletter' => function() {
global $mdb;
return new \admin\Controllers\NewsletterController(
new \Domain\Newsletter\NewsletterRepository(
$mdb,
new \Domain\Settings\SettingsRepository( $mdb )
),
new \Domain\Newsletter\NewsletterPreviewRenderer()
);
},
'Scontainers' => function() {
global $mdb;
return new \admin\Controllers\ScontainersController(
new \Domain\Scontainers\ScontainersRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'ShopPromotion' => function() {
global $mdb;
return new \admin\Controllers\ShopPromotionController(
new \Domain\Promotion\PromotionRepository( $mdb )
);
},
'ShopCoupon' => function() {
global $mdb;
return new \admin\Controllers\ShopCouponController(
new \Domain\Coupon\CouponRepository( $mdb )
);
},
'ShopAttribute' => function() {
global $mdb;
return new \admin\Controllers\ShopAttributeController(
new \Domain\Attribute\AttributeRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'ShopPaymentMethod' => function() {
global $mdb;
return new \admin\Controllers\ShopPaymentMethodController(
new \Domain\PaymentMethod\PaymentMethodRepository( $mdb )
);
},
'ShopTransport' => function() {
global $mdb;
return new \admin\Controllers\ShopTransportController(
new \Domain\Transport\TransportRepository( $mdb ),
new \Domain\PaymentMethod\PaymentMethodRepository( $mdb )
);
},
'Pages' => function() {
global $mdb;
return new \admin\Controllers\PagesController(
new \Domain\Pages\PagesRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb ),
new \Domain\Layouts\LayoutsRepository( $mdb )
);
},
'Integrations' => function() {
global $mdb;
return new \admin\Controllers\IntegrationsController(
new \Domain\Integrations\IntegrationsRepository( $mdb )
);
},
'ShopStatuses' => function() {
global $mdb;
return new \admin\Controllers\ShopStatusesController(
new \Domain\ShopStatus\ShopStatusRepository( $mdb )
);
},
'ShopProductSets' => function() {
global $mdb;
return new \admin\Controllers\ShopProductSetsController(
new \Domain\ProductSet\ProductSetRepository( $mdb )
);
},
'ShopProducer' => function() {
global $mdb;
return new \admin\Controllers\ShopProducerController(
new \Domain\Producer\ProducerRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'ShopCategory' => function() {
global $mdb;
return new \admin\Controllers\ShopCategoryController(
new \Domain\Category\CategoryRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'ShopProduct' => function() {
global $mdb;
return new \admin\Controllers\ShopProductController(
new \Domain\Product\ProductRepository( $mdb ),
new \Domain\Integrations\IntegrationsRepository( $mdb ),
new \Domain\Languages\LanguagesRepository( $mdb )
);
},
'ShopClients' => function() {
global $mdb;
return new \admin\Controllers\ShopClientsController(
new \Domain\Client\ClientRepository( $mdb )
);
},
'ShopOrder' => function() {
global $mdb;
$productRepo = new \Domain\Product\ProductRepository( $mdb );
return new \admin\Controllers\ShopOrderController(
new \Domain\Order\OrderAdminService(
new \Domain\Order\OrderRepository( $mdb ),
$productRepo,
new \Domain\Settings\SettingsRepository( $mdb ),
new \Domain\Transport\TransportRepository( $mdb )
),
$productRepo
);
},
'Update' => function() {
global $mdb;
return new \admin\Controllers\UpdateController(
new \Domain\Update\UpdateRepository( $mdb )
);
},
];
return self::$newControllers;
}
public static function update()
{
global $mdb;
$repository = new \Domain\Update\UpdateRepository( $mdb );
$repository->runPendingMigrations();
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace admin\Controllers;
use Domain\Article\ArticleRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
class ArticlesArchiveController
{
private ArticleRepository $repository;
public function __construct(ArticleRepository $repository)
{
$this->repository = $repository;
}
public function list(): string
{
$sortableColumns = ['title', 'date_add', 'date_modify'];
$filterDefinitions = [
[
'key' => 'title',
'label' => 'Tytul',
'type' => 'text',
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'date_add'
);
$result = $this->repository->listArchivedForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$listRequest['sortDir'],
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$title = trim((string)($item['title'] ?? ''));
$rows[] = [
'lp' => $lp++ . '.',
'title' => '<a href="/admin/articles/edit/id=' . $id . '">' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '</a>',
'date_add' => !empty($item['date_add']) ? date('Y-m-d H:i', strtotime((string)$item['date_add'])) : '-',
'date_modify' => !empty($item['date_modify']) ? date('Y-m-d H:i', strtotime((string)$item['date_modify'])) : '-',
'_actions' => [
[
'label' => 'Przywroc',
'url' => '/admin/articles_archive/restore/id=' . $id,
'class' => 'btn btn-xs btn-success',
'confirm' => 'Na pewno chcesz przywrocic wybrany artykul?',
'confirm_ok' => 'Przywroc',
'confirm_cancel' => 'Anuluj',
],
[
'label' => 'Usun',
'url' => '/admin/articles_archive/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz trwale usunac wybrany artykul?',
'confirm_ok' => 'Usun',
'confirm_cancel' => 'Anuluj',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'title', 'sort_key' => 'title', 'label' => 'Tytul', 'sortable' => true, 'raw' => true],
['key' => 'date_add', 'sort_key' => 'date_add', 'label' => 'Data dodania', 'class' => 'text-center', 'sortable' => true],
['key' => 'date_modify', 'sort_key' => 'date_modify', 'label' => 'Data modyfikacji', 'class' => 'text-center', 'sortable' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $listRequest['sortDir'],
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $listRequest['sortDir'],
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/articles_archive/list/',
'Brak danych w tabeli.'
);
return \Shared\Tpl\Tpl::view('articles/articles-archive-list', [
'viewModel' => $viewModel,
]);
}
public function view_list(): string
{
return $this->list();
}
public function restore(): void
{
if ($this->repository->restore((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Artykul zostal przywrocony.');
}
header('Location: /admin/articles_archive/list/');
exit;
}
public function article_restore(): void
{
$this->restore();
}
public function delete(): void
{
if ($this->repository->deletePermanently((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Artykul zostal trwale usuniety.');
}
header('Location: /admin/articles_archive/list/');
exit;
}
public function article_delete(): void
{
$this->delete();
}
}

View File

@@ -0,0 +1,509 @@
<?php
namespace admin\Controllers;
use Domain\Article\ArticleRepository;
use Domain\Languages\LanguagesRepository;
use Domain\Layouts\LayoutsRepository;
use Domain\Pages\PagesRepository;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class ArticlesController
{
private ArticleRepository $repository;
private LanguagesRepository $languagesRepository;
private LayoutsRepository $layoutsRepository;
private PagesRepository $pagesRepository;
public function __construct(
ArticleRepository $repository,
LanguagesRepository $languagesRepository,
LayoutsRepository $layoutsRepository,
PagesRepository $pagesRepository
)
{
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
$this->layoutsRepository = $layoutsRepository;
$this->pagesRepository = $pagesRepository;
}
/**
* Lista artykulow
*/
public function list(): string
{
$sortableColumns = ['title', 'status', 'date_add', 'date_modify'];
$filterDefinitions = [
[
'key' => 'title',
'label' => 'Tytul',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'date_add'
);
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$listRequest['sortDir'],
$listRequest['page'],
$listRequest['perPage']
);
$articleIds = [];
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
if ($id > 0) {
$articleIds[] = $id;
}
}
$pagesSummary = $this->repository->pagesSummaryForArticles($articleIds);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)$item['id'];
$title = (string)($item['title'] ?? '');
$pages = (string)($pagesSummary[$id] ?? '');
$rows[] = [
'lp' => $lp++ . '.',
'title' => '<a href="/admin/articles/edit/id=' . $id . '">' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '</a>'
. '<small class="text-muted">' . htmlspecialchars($pages, ENT_QUOTES, 'UTF-8') . '</small>',
'status' => ((int)$item['status'] === 1) ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'date_add' => !empty($item['date_add']) ? date('Y-m-d H:i', strtotime((string)$item['date_add'])) : '-',
'date_modify' => !empty($item['date_modify']) ? date('Y-m-d H:i', strtotime((string)$item['date_modify'])) : '-',
'user' => htmlspecialchars((string)($item['user'] ?? ''), ENT_QUOTES, 'UTF-8'),
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/articles/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/articles/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrany element?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'title', 'sort_key' => 'title', 'label' => 'Tytul', 'sortable' => true, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'date_add', 'sort_key' => 'date_add', 'label' => 'Data dodania', 'class' => 'text-center', 'sortable' => true],
['key' => 'date_modify', 'sort_key' => 'date_modify', 'label' => 'Data modyfikacji', 'class' => 'text-center', 'sortable' => true],
['key' => 'user', 'sort_key' => 'user', 'label' => 'Modyfikowany przez', 'class' => 'text-center', 'sortable' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $listRequest['sortDir'],
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $listRequest['sortDir'],
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/articles/list/',
'Brak danych w tabeli.',
'/admin/articles/edit/',
'Dodaj artykul'
);
return \Shared\Tpl\Tpl::view('articles/articles-list', [
'viewModel' => $viewModel,
]);
}
/**
* Zapis kolejnosci galerii (AJAX)
*/
public function galleryOrderSave(): void
{
if ($this->repository->saveGalleryOrder((int)\Shared\Helpers\Helpers::get('article_id'), (string)\Shared\Helpers\Helpers::get('order'))) {
echo json_encode(['status' => 'ok', 'msg' => 'Artykul zostal zapisany.']);
}
exit;
}
/**
* Zapis kolejnosci zalacznikow (AJAX)
*/
public function filesOrderSave(): void
{
if ($this->repository->saveFilesOrder((int)\Shared\Helpers\Helpers::get('article_id'), (string)\Shared\Helpers\Helpers::get('order'))) {
echo json_encode(['status' => 'ok', 'msg' => 'Artykul zostal zapisany.']);
}
exit;
}
/**
* Zapis artykulu (AJAX)
*/
public function save(): void
{
global $user;
$values = $this->resolveSavePayload();
$articleId = (int)($values['id'] ?? \Shared\Helpers\Helpers::get('id') ?? 0);
$id = $this->repository->save($articleId, $values, (int)$user['id']);
if ($id) {
echo json_encode([
'success' => true,
'status' => 'ok',
'message' => 'Artykul zostal zapisany.',
'msg' => 'Artykul zostal zapisany.',
'id' => (int)$id,
]);
exit;
}
echo json_encode([
'success' => false,
'status' => 'error',
'message' => 'Podczas zapisywania artykulu wystapil blad. Prosze sprobowac ponownie.',
'msg' => 'Podczas zapisywania artykulu wystapil blad. Prosze sprobowac ponownie.',
]);
exit;
}
public function imageAltChange(): void
{
$response = ['status' => 'error', 'msg' => 'Podczas zmiany atrybutu alt zdjecia wystapil blad. Prosze sprobowac ponownie.'];
if ($this->repository->updateImageAlt((int)\Shared\Helpers\Helpers::get('image_id'), (string)\Shared\Helpers\Helpers::get('image_alt'))) {
$response = ['status' => 'ok'];
}
echo json_encode($response);
exit;
}
public function fileNameChange(): void
{
$response = ['status' => 'error', 'msg' => 'Podczas zmiany nazwy zalacznika wystapil blad. Prosze sprobowac ponownie.'];
if ($this->repository->updateFileName((int)\Shared\Helpers\Helpers::get('file_id'), (string)\Shared\Helpers\Helpers::get('file_name'))) {
$response = ['status' => 'ok'];
}
echo json_encode($response);
exit;
}
public function imageDelete(): void
{
$response = ['status' => 'error', 'msg' => 'Podczas usuwania zdjecia wystapil blad. Prosze sprobowac ponownie.'];
if ($this->repository->markImageToDelete((int)\Shared\Helpers\Helpers::get('image_id'))) {
$response = ['status' => 'ok'];
}
echo json_encode($response);
exit;
}
public function fileDelete(): void
{
$response = ['status' => 'error', 'msg' => 'Podczas usuwania zalacznika wystapil blad. Prosze sprobowac ponownie.'];
if ($this->repository->markFileToDelete((int)\Shared\Helpers\Helpers::get('file_id'))) {
$response = ['status' => 'ok'];
}
echo json_encode($response);
exit;
}
/**
* Archiwizacja artykulu (ustawia status = -1)
*/
public function delete(): void
{
if ($this->repository->archive((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Artykul zostal przeniesiony do archiwum.');
}
header('Location: /admin/articles/list/');
exit;
}
/**
* Edycja artykulu
*/
public function edit(): string
{
global $user;
if (!$user) {
header('Location: /admin/');
exit;
}
$this->repository->deleteNonassignedImages();
$this->repository->deleteNonassignedFiles();
$article = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: ['id' => 0, 'languages' => [], 'images' => [], 'files' => [], 'pages' => []];
$languages = $this->languagesRepository->languagesList();
$menus = $this->pagesRepository->menusList();
$layouts = $this->layoutsRepository->listAll();
$viewModel = $this->buildFormViewModel($article, $languages, $menus, $layouts);
return \Shared\Tpl\Tpl::view('articles/article-edit', [
'form' => $viewModel,
'article' => $article,
'user' => $user,
]);
}
private function resolveSavePayload(): array
{
$legacyValuesRaw = \Shared\Helpers\Helpers::get('values');
if ($legacyValuesRaw !== null && $legacyValuesRaw !== '') {
$legacyValues = json_decode((string)$legacyValuesRaw, true);
if (is_array($legacyValues)) {
return $legacyValues;
}
}
$payload = $_POST;
unset($payload['_form_id']);
return is_array($payload) ? $payload : [];
}
private function buildFormViewModel(array $article, array $languages, array $menus, array $layouts): FormEditViewModel
{
$articleId = (int)($article['id'] ?? 0);
$defaultLanguageId = (string)($this->languagesRepository->defaultLanguageId() ?? 'pl');
$title = $articleId > 0
? 'Edycja artykulu: <u>' . $this->escapeHtml((string)($article['languages'][$defaultLanguageId]['title'] ?? '')) . '</u>'
: 'Edycja artykulu';
$layoutOptions = ['' => '---- szablon domyslny ----'];
foreach ($layouts as $layout) {
$layoutOptions[(string)$layout['id']] = (string)$layout['name'];
}
$copyFromOptions = ['' => '---- wersja jezykowa ----'];
foreach ($languages as $language) {
if (!empty($language['id'])) {
$copyFromOptions[(string)$language['id']] = (string)$language['name'];
}
}
$tabs = [
new FormTab('content', 'Tresc', 'fa-file'),
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
new FormTab('seo', 'SEO', 'fa-globe'),
new FormTab('display', 'Wyswietlanie', 'fa-share-alt'),
new FormTab('gallery', 'Galeria', 'fa-file-image-o'),
new FormTab('files', 'Zalaczniki', 'fa-file-archive-o'),
];
$fields = [
FormField::hidden('id', $articleId),
FormField::langSection('article_content', 'content', [
FormField::select('copy_from', [
'label' => 'Wyswietlaj tresc z wersji',
'options' => $copyFromOptions,
]),
FormField::text('title', [
'label' => 'Tytul',
'required' => true,
'attributes' => ['id' => 'title'],
]),
FormField::image('main_image', [
'label' => 'Zdjecie tytulowe',
'filemanager' => true,
'attributes' => ['id' => 'main_image'],
]),
FormField::editor('entry', [
'label' => 'Wstep',
'toolbar' => 'MyToolbar',
'height' => 250,
'attributes' => ['id' => 'entry'],
]),
FormField::editor('text', [
'label' => 'Tresc',
'toolbar' => 'MyToolbar',
'height' => 250,
'attributes' => ['id' => 'text'],
]),
FormField::editor('table_of_contents', [
'label' => 'Spis tresci',
'toolbar' => 'MyToolbar',
'height' => 250,
'attributes' => ['id' => 'table_of_contents'],
]),
]),
FormField::switch('status', ['label' => 'Opublikowany', 'tab' => 'settings', 'value' => ((int)($article['status'] ?? 0) === 1) || $articleId === 0]),
FormField::switch('show_title', ['label' => 'Pokaz tytul', 'tab' => 'settings', 'value' => (int)($article['show_title'] ?? 0) === 1]),
FormField::switch('show_table_of_contents', ['label' => 'Pokaz spis tresci', 'tab' => 'settings', 'value' => (int)($article['show_table_of_contents'] ?? 0) === 1]),
FormField::switch('show_date_add', ['label' => 'Pokaz date dodania', 'tab' => 'settings', 'value' => (int)($article['show_date_add'] ?? 0) === 1]),
FormField::switch('show_date_modify', ['label' => 'Pokaz date modyfikacji', 'tab' => 'settings', 'value' => (int)($article['show_date_modify'] ?? 0) === 1]),
FormField::switch('repeat_entry', ['label' => 'Powtorz wprowadzenie', 'tab' => 'settings', 'value' => (int)($article['repeat_entry'] ?? 0) === 1]),
FormField::switch('social_icons', ['label' => 'Linki do portali spolecznosciowych', 'tab' => 'settings', 'value' => (int)($article['social_icons'] ?? 0) === 1]),
FormField::langSection('article_seo', 'seo', [
FormField::text('seo_link', ['label' => 'Link SEO', 'attributes' => ['id' => 'seo_link']]),
FormField::text('meta_title', ['label' => 'Meta title']),
FormField::textarea('meta_description', ['label' => 'Meta description', 'rows' => 4]),
FormField::textarea('meta_keywords', ['label' => 'Meta keywords', 'rows' => 4]),
FormField::switch('noindex', ['label' => 'Blokuj indeksacje']),
FormField::switch('block_direct_access', ['label' => 'Blokuj bezposredni dostep']),
]),
FormField::select('layout_id', [
'label' => 'Szablon',
'tab' => 'display',
'options' => $layoutOptions,
'value' => $article['layout_id'] ?? '',
]),
FormField::custom('pages_tree', $this->renderPagesTree($menus, $article), ['tab' => 'display']),
FormField::custom('images_box', $this->renderImagesBox($article), ['tab' => 'gallery']),
FormField::custom('files_box', $this->renderFilesBox($article), ['tab' => 'files']),
];
$actions = [
FormAction::save('/admin/articles/save/' . ($articleId > 0 ? 'id=' . $articleId : ''), '/admin/articles/list/'),
FormAction::cancel('/admin/articles/list/'),
];
return new FormEditViewModel(
'article-edit',
$title,
$article,
$fields,
$tabs,
$actions,
'POST',
'/admin/articles/save/' . ($articleId > 0 ? 'id=' . $articleId : ''),
'/admin/articles/list/',
true,
['id' => $articleId],
$languages
);
}
private function renderPagesTree(array $menus, array $article): string
{
$html = '<div class="form-group row">';
$html .= '<label class="col-lg-4 control-label">Wyswietlaj na:</label>';
$html .= '<div class="col-lg-8">';
foreach ($menus as $menu) {
$menuId = (int)($menu['id'] ?? 0);
$menuName = $this->escapeHtml((string)($menu['name'] ?? ''));
$menuStatus = (int)($menu['status'] ?? 0);
$menuPages = $this->pagesRepository->menuPages($menuId);
$html .= '<div class="menu_sortable">';
$html .= '<ol class="sortable" id="sortable_' . $menuId . '">';
$html .= '<li id="list_' . $menuId . '" class="menu_' . $menuId . '" menu="' . $menuId . '">';
$html .= '<div class="context_0 content content_menu"' . ($menuStatus ? '' : ' style="color: #cc0000;"') . '>';
$html .= '<button type="button" class="disclose layout-tree-toggle" aria-expanded="false" title="Rozwin / zwin">'
. '<i class="fa fa-caret-right"></i>'
. '</button>Menu: <b>' . $menuName . '</b>';
$html .= '</div>';
$html .= \Shared\Tpl\Tpl::view('articles/subpages-list', [
'pages' => $menuPages,
'article_pages' => $article['pages'] ?? [],
'parent_id' => $menuId,
'step' => 1,
]);
$html .= '</li></ol></div>';
}
$html .= '</div><div class="clear"></div></div>';
return $html;
}
private function renderImagesBox(array $article): string
{
$html = '<ul id="images-list">';
$images = is_array($article['images'] ?? null) ? $article['images'] : [];
foreach ($images as $img) {
$id = (int)($img['id'] ?? 0);
$src = $this->escapeHtml((string)($img['src'] ?? ''));
$alt = $this->escapeHtml((string)($img['alt'] ?? ''));
$html .= '<li id="image-' . $id . '">';
$html .= '<img class="article-image lozad" data-src="/libraries/thumb.php?img=' . $src . '&w=300&h=300">';
$html .= '<a href="#" class="input-group-addon btn btn-danger article_image_delete" image-id="' . $id . '"><i class="fa fa-trash"></i></a>';
$html .= '<input type="text" class="form-control image-alt" value="' . $alt . '" image-id="' . $id . '" placeholder="atrybut alt...">';
$html .= '</li>';
}
$html .= '</ul><div id="images-uploader">You browser doesn\'t have Flash installed.</div>';
return $html;
}
private function renderFilesBox(array $article): string
{
$html = '<ul id="files-list">';
$files = is_array($article['files'] ?? null) ? $article['files'] : [];
foreach ($files as $file) {
$id = (int)($file['id'] ?? 0);
$src = (string)($file['src'] ?? '');
$name = trim((string)($file['name'] ?? ''));
if ($name === '') {
$parts = explode('/', $src);
$name = (string)end($parts);
}
$name = $this->escapeHtml($name);
$html .= '<li id="file-' . $id . '"><div class="input-group">';
$html .= '<input type="text" class="article_file_edit form-control" file_id="' . $id . '" value="' . $name . '" />';
$html .= '<a href="#" class="input-group-addon btn btn-info article_file_delete" file_id="' . $id . '"><i class="fa fa-trash"></i></a>';
$html .= '</div></li>';
}
$html .= '</ul><div id="files-uploader">You browser doesn\'t have Flash installed.</div>';
return $html;
}
private function escapeHtml(string $value): string
{
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
}

View File

@@ -0,0 +1,339 @@
<?php
namespace admin\Controllers;
use Domain\Banner\BannerRepository;
use Domain\Languages\LanguagesRepository;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
use admin\ViewModels\Forms\FormAction;
use admin\Support\Forms\FormRequestHandler;
class BannerController
{
private BannerRepository $repository;
private LanguagesRepository $languagesRepository;
private FormRequestHandler $formHandler;
public function __construct(BannerRepository $repository, LanguagesRepository $languagesRepository)
{
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
$this->formHandler = new FormRequestHandler();
}
/**
* Lista banerow
*/
public function list(): string
{
$sortableColumns = ['name', 'status', 'home_page', 'date_start', 'date_end'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'name'
);
// Historycznie lista banerow domyslnie byla sortowana rosnaco po nazwie.
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)$item['id'];
$name = (string)($item['name'] ?? '');
$homePage = (int)($item['home_page'] ?? 0);
$isActive = (int)($item['status'] ?? 0) === 1;
$thumbnailSrc = trim((string)($item['thumbnail_src'] ?? ''));
if ($thumbnailSrc !== '' && !preg_match('#^(https?:)?//#i', $thumbnailSrc) && strpos($thumbnailSrc, '/') !== 0) {
$thumbnailSrc = '/' . ltrim($thumbnailSrc, '/');
}
$thumbnail = '<span class="text-muted">-</span>';
if ($thumbnailSrc !== '') {
$thumbnail = '<div class="banner-thumb-wrap">'
. '<img src="' . htmlspecialchars($thumbnailSrc, ENT_QUOTES, 'UTF-8') . '" alt="" '
. 'data-preview-src="' . htmlspecialchars($thumbnailSrc, ENT_QUOTES, 'UTF-8') . '" '
. 'class="banner-thumb-image js-banner-thumb-preview" '
. 'loading="lazy">'
. '</div>';
}
$rows[] = [
'lp' => $lp++ . '.',
'thumbnail' => $thumbnail,
'name' => '<a href="/admin/banners/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'status' => $isActive ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'home_page' => $homePage === 1 ? '<span class="text-system">tak</span>' : 'nie',
'slider' => $homePage === 1 ? 'nie' : '<span class="text-system">tak</span>',
'date_start' => !empty($item['date_start']) ? date('Y-m-d', strtotime((string)$item['date_start'])) : '-',
'date_end' => !empty($item['date_end']) ? date('Y-m-d', strtotime((string)$item['date_end'])) : '-',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/banners/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/banners/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrany element?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'thumbnail', 'label' => 'Miniatura', 'class' => 'text-center', 'sortable' => false, 'raw' => true],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'home_page', 'sort_key' => 'home_page', 'label' => 'Strona glowna', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'slider', 'label' => 'Slajder', 'class' => 'text-center', 'sortable' => false, 'raw' => true],
['key' => 'date_start', 'sort_key' => 'date_start', 'label' => 'Data rozpoczecia', 'class' => 'text-center', 'sortable' => true],
['key' => 'date_end', 'sort_key' => 'date_end', 'label' => 'Data zakonczenia', 'class' => 'text-center', 'sortable' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/banners/list/',
'Brak danych w tabeli.',
'/admin/banners/edit/',
'Dodaj baner',
'banners/banners-list-custom-script'
);
return \Shared\Tpl\Tpl::view('banners/banners-list', [
'viewModel' => $viewModel,
]);
}
/**
* Edycja banera
*/
public function edit(): string
{
$bannerId = (int)\Shared\Helpers\Helpers::get('id');
$banner = $this->repository->find($bannerId) ?: [];
$languages = $this->languagesRepository->languagesList();
// Sprawdź czy są błędy walidacji z poprzedniego requestu
$validationErrors = $_SESSION['form_errors'][$this->getFormId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->getFormId()]);
}
$viewModel = $this->buildFormViewModel($banner, $languages, $validationErrors);
return \Shared\Tpl\Tpl::view('components/form-edit', ['form' => $viewModel]);
}
/**
* Zapisanie banera (AJAX)
*/
public function save(): void
{
$response = ['success' => false, 'errors' => []];
$bannerId = (int)\Shared\Helpers\Helpers::get('id');
$banner = $this->repository->find($bannerId) ?: [];
$languages = $this->languagesRepository->languagesList();
$viewModel = $this->buildFormViewModel($banner, $languages);
// Przetwórz dane z POST
$result = $this->formHandler->handleSubmit($viewModel, $_POST);
if (!$result['success']) {
// Zapisz błędy w sesji i zwróć jako JSON
$_SESSION['form_errors'][$this->getFormId()] = $result['errors'];
$response['errors'] = $result['errors'];
echo json_encode($response);
exit;
}
// Zapisz dane
$data = $result['data'];
$data['id'] = $bannerId ?: null;
$savedId = $this->repository->save($data);
if ($savedId) {
$response = [
'success' => true,
'id' => $savedId,
'message' => 'Baner został zapisany.'
];
} else {
$response['errors'] = ['general' => 'Błąd podczas zapisywania do bazy.'];
}
echo json_encode($response);
exit;
}
/**
* Usuniecie banera
*/
public function delete(): void
{
$bannerId = (int)\Shared\Helpers\Helpers::get('id');
if ($this->repository->delete($bannerId)) {
\Shared\Helpers\Helpers::delete_dir('../temp/');
\Shared\Helpers\Helpers::alert('Baner zostal usuniety.');
}
header('Location: /admin/banners/list/');
exit;
}
/**
* Buduje model widoku formularza
*/
private function buildFormViewModel(array $banner, array $languages, ?array $errors = null): FormEditViewModel
{
$bannerId = $banner['id'] ?? 0;
$isNew = empty($bannerId);
// Domyślne wartości dla nowego banera
if ($isNew) {
$banner['status'] = 1;
$banner['home_page'] = 0;
}
$tabs = [
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
new FormTab('content', 'Zawartość', 'fa-file'),
];
$fields = [
// Zakładka Ustawienia
FormField::text('name', [
'label' => 'Nazwa',
'tab' => 'settings',
'required' => true,
]),
FormField::switch('status', [
'label' => 'Aktywny',
'tab' => 'settings',
'value' => ($banner['status'] ?? 1) == 1,
]),
FormField::date('date_start', [
'label' => 'Data rozpoczęcia',
'tab' => 'settings',
]),
FormField::date('date_end', [
'label' => 'Data zakończenia',
'tab' => 'settings',
]),
FormField::switch('home_page', [
'label' => 'Slajder / Strona główna',
'tab' => 'settings',
'value' => ($banner['home_page'] ?? 0) == 1,
]),
// Sekcja językowa w zakładce Zawartość
FormField::langSection('translations', 'content', [
FormField::image('src', [
'label' => 'Obraz',
'filemanager' => true,
]),
FormField::text('url', [
'label' => 'Url',
]),
FormField::textarea('html', [
'label' => 'Kod HTML',
'rows' => 6,
]),
FormField::editor('text', [
'label' => 'Treść',
'toolbar' => 'MyTool',
'height' => 300,
]),
]),
];
$actions = [
FormAction::save(
'/admin/banners/save/' . ($isNew ? '' : 'id=' . $bannerId),
'/admin/banners/list/'
),
FormAction::cancel('/admin/banners/list/'),
];
return new FormEditViewModel(
$this->getFormId(),
$isNew ? 'Nowy baner' : 'Edycja banera',
$banner,
$fields,
$tabs,
$actions,
'POST',
'/admin/banners/save/' . ($isNew ? '' : 'id=' . $bannerId),
'/admin/banners/list/',
true,
['id' => $bannerId],
$languages,
$errors
);
}
/**
* Zwraca identyfikator formularza
*/
private function getFormId(): string
{
return 'banner-edit';
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace admin\Controllers;
use Domain\Dashboard\DashboardRepository;
use Domain\ShopStatus\ShopStatusRepository;
class DashboardController
{
private DashboardRepository $repository;
private ShopStatusRepository $statusesRepository;
public function __construct( DashboardRepository $repository, ShopStatusRepository $statusesRepository )
{
$this->repository = $repository;
$this->statusesRepository = $statusesRepository;
}
public function main_view(): string
{
return \Shared\Tpl\Tpl::view( 'dashboard/main-view', [
'last_orders' => $this->repository->lastOrders(),
'order_statuses' => $this->statusesRepository->allStatuses(),
'sales' => $this->repository->last24MonthsSales(),
'best_sales_products' => $this->repository->bestSalesProducts(),
'most_view_products' => $this->repository->mostViewedProducts(),
'sales_grid' => $this->repository->salesGrid(),
'summary_sales' => $this->repository->summarySales(),
'summary_orders' => $this->repository->summaryOrders(),
] );
}
}

View File

@@ -0,0 +1,256 @@
<?php
namespace admin\Controllers;
use Domain\Dictionaries\DictionariesRepository;
use Domain\Languages\LanguagesRepository;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
use admin\Support\Forms\FormRequestHandler;
class DictionariesController
{
private DictionariesRepository $repository;
private LanguagesRepository $languagesRepository;
private FormRequestHandler $formHandler;
public function __construct(DictionariesRepository $repository, LanguagesRepository $languagesRepository)
{
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
$this->formHandler = new FormRequestHandler();
}
public function list(): string
{
$sortableColumns = ['id', 'text'];
$filterDefinitions = [
[
'key' => 'text',
'label' => 'Tekst',
'type' => 'text',
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'id'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)$item['id'];
$text = trim((string)($item['text'] ?? ''));
$rows[] = [
'lp' => $lp++ . '.',
'text' => '<a href="/admin/dictionaries/edit/id=' . $id . '">' . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . '</a>',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/dictionaries/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/dictionaries/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrana jednostke miary?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'text', 'sort_key' => 'text', 'label' => 'Tekst', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/dictionaries/list/',
'Brak danych w tabeli.',
'/admin/dictionaries/edit/',
'Dodaj jednostke miary'
);
return \Shared\Tpl\Tpl::view('dictionaries/units-list', [
'viewModel' => $viewModel,
]);
}
public function edit(): string
{
$unitId = (int)\Shared\Helpers\Helpers::get('id');
$unit = $this->repository->find($unitId) ?? ['id' => 0, 'languages' => []];
$languages = $this->languagesRepository->languagesList();
$validationErrors = $_SESSION['form_errors'][$this->getFormId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->getFormId()]);
}
$viewModel = $this->buildFormViewModel($unit, $languages, $validationErrors);
return \Shared\Tpl\Tpl::view('dictionaries/unit-edit', ['form' => $viewModel]);
}
public function save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode($legacyValues, true);
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania jednostki miary wystapil blad.'];
if (is_array($values)) {
$savedId = $this->repository->save([
'id' => (int)($values['id'] ?? 0),
'text' => (array)($values['text'] ?? []),
]);
if ($savedId) {
$response = ['status' => 'ok', 'msg' => 'Jednostka miary zostala zapisana.', 'id' => $savedId];
}
}
echo json_encode($response);
exit;
}
$unitId = (int)\Shared\Helpers\Helpers::get('id');
$unit = $this->repository->find($unitId) ?? ['id' => 0, 'languages' => []];
$languages = $this->languagesRepository->languagesList();
$viewModel = $this->buildFormViewModel($unit, $languages);
$result = $this->formHandler->handleSubmit($viewModel, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->getFormId()] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$data = $result['data'];
$data['id'] = $unitId ?: null;
$savedId = $this->repository->save($data);
if ($savedId) {
echo json_encode([
'success' => true,
'id' => $savedId,
'message' => 'Jednostka miary zostala zapisana.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Blad podczas zapisywania do bazy.'],
]);
exit;
}
public function delete(): void
{
$unitId = (int)\Shared\Helpers\Helpers::get('id');
if ($this->repository->delete($unitId)) {
\Shared\Helpers\Helpers::alert('Jednostka miary zostala usunieta.');
}
header('Location: /admin/dictionaries/list/');
exit;
}
private function buildFormViewModel(array $unit, array $languages, ?array $errors = null): FormEditViewModel
{
$unitId = (int)($unit['id'] ?? 0);
$isNew = $unitId <= 0;
$data = [
'id' => $unitId,
'languages' => [],
];
if (isset($unit['languages']) && is_array($unit['languages'])) {
foreach ($unit['languages'] as $langId => $translation) {
$data['languages'][(string)$langId] = [
'text' => (string)($translation['text'] ?? ''),
];
}
}
$tabs = [
new FormTab('content', 'Tresc', 'fa-file'),
];
$fields = [
FormField::langSection('translations', 'content', [
FormField::text('text', [
'label' => 'Tekst',
]),
]),
];
$actionUrl = '/admin/dictionaries/save/' . ($isNew ? '' : ('id=' . $unitId));
$actions = [
FormAction::save($actionUrl, '/admin/dictionaries/list/'),
FormAction::cancel('/admin/dictionaries/list/'),
];
return new FormEditViewModel(
$this->getFormId(),
$isNew ? 'Nowa jednostka miary' : 'Edycja jednostki miary',
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/dictionaries/list/',
true,
['id' => $unitId],
$languages,
$errors
);
}
private function getFormId(): string
{
return 'dictionaries-unit-edit';
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace admin\Controllers;
class FilemanagerController
{
private const RFM_KEY_TTL = 1200; // 20 min
private const FILEMANAGER_DIALOG_PATH = '/libraries/filemanager-9.14.2/dialog.php';
public function draw(): string
{
$akey = $this->ensureFilemanagerAccessKey();
$filemanagerUrl = $this->buildFilemanagerUrl($akey);
return \Shared\Tpl\Tpl::view('filemanager/filemanager', [
'filemanager_url' => $filemanagerUrl,
]);
}
private function ensureFilemanagerAccessKey(): string
{
$expiresAt = (int)($_SESSION['rfm_akey_expires'] ?? 0);
$existingKey = trim((string)($_SESSION['rfm_akey'] ?? ''));
if ($existingKey !== '' && $expiresAt >= time()) {
$_SESSION['rfm_akey_expires'] = time() + self::RFM_KEY_TTL;
return $existingKey;
}
try {
$newKey = bin2hex(random_bytes(16));
} catch (\Throwable $e) {
$newKey = sha1(uniqid('rfm', true));
}
$_SESSION['rfm_akey'] = $newKey;
$_SESSION['rfm_akey_expires'] = time() + self::RFM_KEY_TTL;
return $newKey;
}
private function buildFilemanagerUrl(string $akey): string
{
return self::FILEMANAGER_DIALOG_PATH . '?akey=' . rawurlencode($akey);
}
}

View File

@@ -0,0 +1,178 @@
<?php
namespace admin\Controllers;
use Domain\Integrations\IntegrationsRepository;
class IntegrationsController
{
private IntegrationsRepository $repository;
public function __construct( IntegrationsRepository $repository )
{
$this->repository = $repository;
}
public function apilo_settings(): string
{
return \Shared\Tpl\Tpl::view( 'integrations/apilo-settings', [
'settings' => $this->repository->getSettings( 'apilo' ),
'apilo_status' => $this->repository->apiloIntegrationStatus(),
] );
}
public function apilo_settings_save(): void
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania ustawien wystapil blad. Prosze sprobowac ponownie.' ];
$fieldId = \Shared\Helpers\Helpers::get( 'field_id' );
$value = \Shared\Helpers\Helpers::get( 'value' );
if ( $this->repository->saveSetting( 'apilo', $fieldId, $value ) ) {
$response = [ 'status' => 'ok', 'msg' => 'Ustawienia zostaly zapisane.', 'value' => $value ];
}
echo json_encode( $response );
exit;
}
public function apilo_authorization(): void
{
$settings = $this->repository->getSettings( 'apilo' );
if ( $this->repository->apiloAuthorize(
(string)($settings['client-id'] ?? ''),
(string)($settings['client-secret'] ?? ''),
(string)($settings['authorization-code'] ?? '')
) ) {
echo json_encode( [ 'status' => 'ok', 'msg' => 'Autoryzacja przebiegla pomyslnie.' ] );
exit;
}
$status = $this->repository->apiloIntegrationStatus();
$message = trim( (string)($status['message'] ?? '') );
if ( $message === '' ) {
$message = 'Podczas autoryzacji wystapil blad. Prosze sprawdzic dane i sprobowac ponownie.';
} else {
$message = 'Autoryzacja nieudana. ' . $message;
}
echo json_encode( [ 'status' => 'error', 'msg' => $message ] );
exit;
}
public function get_platform_list(): void
{
$this->fetchApiloListWithFeedback( 'platform', 'Liste platform' );
}
public function get_status_types_list(): void
{
$this->fetchApiloListWithFeedback( 'status', 'Liste statusow' );
}
public function get_carrier_account_list(): void
{
$this->fetchApiloListWithFeedback( 'carrier', 'Liste kont przewoznikow' );
}
public function get_payment_types_list(): void
{
$this->fetchApiloListWithFeedback( 'payment', 'Liste metod platnosci' );
}
public function apilo_create_product(): void
{
$productId = (int) \Shared\Helpers\Helpers::get( 'product_id' );
$result = $this->repository->apiloCreateProduct( $productId );
\Shared\Helpers\Helpers::alert( (string)($result['message'] ?? 'Wystapil blad podczas tworzenia produktu w Apilo.') );
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
public function apilo_product_search(): void
{
$productId = (int) \Shared\Helpers\Helpers::get( 'product_id' );
$sku = $this->repository->getProductSku( $productId );
if ( !$sku ) {
echo json_encode( [ 'status' => 'error', 'msg' => 'Podany produkt nie posiada kodu SKU.' ] );
exit;
}
echo json_encode( $this->repository->apiloProductSearch( $sku ) );
exit;
}
public function apilo_product_select_save(): void
{
if ( $this->repository->linkProduct( (int) \Shared\Helpers\Helpers::get( 'product_id' ), \Shared\Helpers\Helpers::get( 'apilo_product_id' ), \Shared\Helpers\Helpers::get( 'apilo_product_name' ) ) ) {
echo json_encode( [ 'status' => 'ok' ] );
} else {
echo json_encode( [ 'status' => 'error', 'msg' => 'Podczas zapisywania produktu wystapil blad. Prosze sprobowac ponownie.' ] );
}
exit;
}
public function apilo_product_select_delete(): void
{
if ( $this->repository->unlinkProduct( (int) \Shared\Helpers\Helpers::get( 'product_id' ) ) ) {
echo json_encode( [ 'status' => 'ok' ] );
} else {
echo json_encode( [ 'status' => 'error', 'msg' => 'Podczas usuwania produktu wystapil blad. Prosze sprobowac ponownie.' ] );
}
exit;
}
public function shoppro_settings(): string
{
return \Shared\Tpl\Tpl::view( 'integrations/shoppro-settings', [
'settings' => $this->repository->getSettings( 'shoppro' ),
] );
}
public function shoppro_settings_save(): void
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania ustawien wystapil blad. Prosze sprobowac ponownie.' ];
$fieldId = \Shared\Helpers\Helpers::get( 'field_id' );
$value = \Shared\Helpers\Helpers::get( 'value' );
if ( $this->repository->saveSetting( 'shoppro', $fieldId, $value ) ) {
$response = [ 'status' => 'ok', 'msg' => 'Ustawienia zostaly zapisane.', 'value' => $value ];
}
echo json_encode( $response );
exit;
}
public function shoppro_product_import(): void
{
$productId = (int) \Shared\Helpers\Helpers::get( 'product_id' );
$result = $this->repository->shopproImportProduct( $productId );
\Shared\Helpers\Helpers::alert( (string)($result['message'] ?? 'Wystapil blad podczas importu produktu.') );
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
private function fetchApiloListWithFeedback( string $type, string $label ): void
{
$result = $this->repository->apiloFetchListResult( $type );
if ( !empty( $result['success'] ) ) {
$count = (int)($result['count'] ?? 0);
\Shared\Helpers\Helpers::alert( $label . ' zostala pobrana. Liczba rekordow: ' . $count . '.' );
} else {
$details = trim( (string)($result['message'] ?? 'Nieznany blad.') );
\Shared\Helpers\Helpers::alert(
'Nie udalo sie pobrac ' . strtolower( $label ) . '. '
. $details
. ' Co zrobic: sprawdz konfiguracje Apilo, wykonaj autoryzacje i ponow pobranie listy.'
);
}
header( 'Location: /admin/integrations/apilo_settings/' );
exit;
}
}

View File

@@ -0,0 +1,560 @@
<?php
namespace admin\Controllers;
use Domain\Languages\LanguagesRepository;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\Support\Forms\FormRequestHandler;
class LanguagesController
{
private LanguagesRepository $repository;
private FormRequestHandler $formHandler;
public function __construct(LanguagesRepository $repository)
{
$this->repository = $repository;
$this->formHandler = new FormRequestHandler();
}
public function list(): string
{
$sortableColumns = ['o', 'name', 'status', 'start'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Jezyk',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
[
'key' => 'start',
'label' => 'Domyslny',
'type' => 'select',
'options' => [
'' => '- domyslny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'o'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (string)($item['id'] ?? '');
$name = trim((string)($item['name'] ?? ''));
$rows[] = [
'lp' => $lp++ . '.',
'start' => ((int)($item['start'] ?? 0) === 1) ? '<span class="text-system">tak</span>' : 'nie',
'status' => ((int)($item['status'] ?? 0) === 1) ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'name' => '<a href="/admin/languages/language_edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/languages/language_edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/languages/language_delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrany jezyk?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'start', 'sort_key' => 'start', 'label' => 'Domyslny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Jezyk', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/languages/view_list/',
'Brak danych w tabeli.',
'/admin/languages/language_edit/',
'Dodaj jezyk'
);
return \Shared\Tpl\Tpl::view('languages/languages-list', [
'viewModel' => $viewModel,
]);
}
public function view_list(): string
{
return $this->list();
}
public function language_edit(): string
{
$languageId = trim((string)\Shared\Helpers\Helpers::get('id'));
$language = $this->repository->languageDetails($languageId) ?? [];
$validationErrors = $_SESSION['form_errors'][$this->getLanguageFormId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->getLanguageFormId()]);
}
return \Shared\Tpl\Tpl::view('languages/language-edit', [
'form' => $this->buildLanguageFormViewModel($language, $this->repository->maxOrder(), $validationErrors),
]);
}
public function language_save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania jezyka wystapil blad.'];
if (is_array($values)) {
$savedId = $this->repository->saveLanguage(
(string)($values['id'] ?? ''),
(string)($values['name'] ?? ''),
$values['status'] ?? 0,
$values['start'] ?? 0,
(int)($values['o'] ?? 0)
);
if ($savedId) {
$response = ['status' => 'ok', 'msg' => 'Jezyk zostal zapisany.', 'id' => $savedId];
}
}
echo json_encode($response);
exit;
}
$languageId = trim((string)\Shared\Helpers\Helpers::get('id'));
$language = $this->repository->languageDetails($languageId) ?? [];
$viewModel = $this->buildLanguageFormViewModel($language, $this->repository->maxOrder());
$result = $this->formHandler->handleSubmit($viewModel, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->getLanguageFormId()] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$data = $result['data'];
$requestId = strtolower(trim((string)\Shared\Helpers\Helpers::get('id')));
$idFromData = strtolower(trim((string)($data['id'] ?? '')));
$id = $idFromData !== '' ? $idFromData : $requestId;
if (!preg_match('/^[a-z]{2}$/', $id)) {
echo json_encode([
'success' => false,
'errors' => ['id' => 'ID jezyka musi miec 2 litery (np. pl, en).'],
]);
exit;
}
$savedId = $this->repository->saveLanguage(
$id,
trim((string)($data['name'] ?? '')),
$data['status'] ?? 0,
$data['start'] ?? 0,
(int)($data['o'] ?? 0)
);
if ($savedId) {
echo json_encode([
'success' => true,
'id' => $savedId,
'message' => 'Jezyk zostal zapisany.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania jezyka wystapil blad.'],
]);
exit;
}
public function language_delete(): void
{
if ($this->repository->deleteLanguage((string)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Jezyk zostal usuniety.');
}
header('Location: /admin/languages/view_list/');
exit;
}
public function translation_list(): string
{
$sortableColumns = ['text', 'id'];
$filterDefinitions = [
[
'key' => 'text',
'label' => 'Tekst',
'type' => 'text',
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'text'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listTranslationsForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$text = trim((string)($item['text'] ?? ''));
$rows[] = [
'lp' => $lp++ . '.',
'text' => '<a href="/admin/languages/translation_edit/id=' . $id . '">' . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . '</a>',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/languages/translation_edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/languages/translation_delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrane tlumaczenie?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'text', 'sort_key' => 'text', 'label' => 'Tekst', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/languages/translation_list/',
'Brak danych w tabeli.',
'/admin/languages/translation_edit/',
'Dodaj tlumaczenie'
);
return \Shared\Tpl\Tpl::view('languages/translations-list', [
'viewModel' => $viewModel,
]);
}
public function translation_edit(): string
{
$translationId = (int)\Shared\Helpers\Helpers::get('id');
$translation = $this->repository->translationDetails($translationId) ?? [];
$languages = $this->repository->languagesList();
$validationErrors = $_SESSION['form_errors'][$this->getTranslationFormId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->getTranslationFormId()]);
}
return \Shared\Tpl\Tpl::view('languages/translation-edit', [
'form' => $this->buildTranslationFormViewModel($translation, $languages, $validationErrors),
]);
}
public function translation_save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania tlumaczenia wystapil blad.'];
if (is_array($values)) {
$languagesMap = $this->extractLegacyTranslations($values, $this->repository->languagesList());
$savedId = $this->repository->saveTranslation(
(int)($values['id'] ?? 0),
(string)($values['text'] ?? ''),
$languagesMap
);
if ($savedId) {
$this->clearLanguageSessions($this->repository->languagesList());
$response = ['status' => 'ok', 'msg' => 'Tlumaczenie zostalo zapisane.', 'id' => $savedId];
}
}
echo json_encode($response);
exit;
}
$translationId = (int)\Shared\Helpers\Helpers::get('id');
$translation = $this->repository->translationDetails($translationId) ?? [];
$languages = $this->repository->languagesList();
$viewModel = $this->buildTranslationFormViewModel($translation, $languages);
$result = $this->formHandler->handleSubmit($viewModel, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->getTranslationFormId()] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$data = $result['data'];
$languagesMap = [];
foreach ($languages as $language) {
$langId = (string)($language['id'] ?? '');
$key = 'lang_' . $langId;
$languagesMap[$langId] = (string)($data[$key] ?? '');
}
$savedId = $this->repository->saveTranslation(
$translationId,
(string)($data['text'] ?? ''),
$languagesMap
);
if ($savedId) {
$this->clearLanguageSessions($languages);
echo json_encode([
'success' => true,
'id' => $savedId,
'message' => 'Tlumaczenie zostalo zapisane.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania tlumaczenia wystapil blad.'],
]);
exit;
}
public function translation_delete(): void
{
if ($this->repository->deleteTranslation((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Tlumaczenie zostalo usuniete.');
}
header('Location: /admin/languages/translation_list/');
exit;
}
private function buildLanguageFormViewModel(array $language, int $maxOrder, ?array $errors = null): FormEditViewModel
{
$languageId = strtolower(trim((string)($language['id'] ?? '')));
$isNew = $languageId === '';
$data = [
'id' => $languageId,
'name' => (string)($language['name'] ?? ''),
'status' => (int)($language['status'] ?? 0),
'start' => (int)($language['start'] ?? 0),
'o' => (int)($language['o'] ?? ($maxOrder + 1)),
];
$fields = [];
if ($isNew) {
$fields[] = FormField::text('id', [
'label' => 'ID (2 znaki)',
'required' => true,
'attributes' => ['maxlength' => 2],
]);
}
$fields[] = FormField::text('name', [
'label' => 'Jezyk',
'required' => true,
]);
$fields[] = FormField::switch('status', [
'label' => 'Aktywny',
]);
$fields[] = FormField::switch('start', [
'label' => 'Domyslny',
]);
$fields[] = FormField::hidden('o', $data['o']);
$actionUrl = '/admin/languages/language_save/' . ($isNew ? '' : ('id=' . $languageId));
$actions = [
FormAction::save($actionUrl, '/admin/languages/view_list/'),
FormAction::cancel('/admin/languages/view_list/'),
];
return new FormEditViewModel(
$this->getLanguageFormId(),
$isNew ? 'Nowy jezyk' : 'Edycja jezyka',
$data,
$fields,
[],
$actions,
'POST',
$actionUrl,
'/admin/languages/view_list/',
true,
$isNew ? [] : ['id' => $languageId],
null,
$errors
);
}
private function buildTranslationFormViewModel(array $translation, array $languages, ?array $errors = null): FormEditViewModel
{
$translationId = (int)($translation['id'] ?? 0);
$isNew = $translationId <= 0;
$data = [
'id' => $translationId,
'text' => (string)($translation['text'] ?? ''),
];
$fields = [
FormField::text('text', [
'label' => 'Tekst',
'required' => true,
]),
];
foreach ($languages as $language) {
$langId = (string)($language['id'] ?? '');
$fieldName = 'lang_' . $langId;
$data[$fieldName] = (string)($translation[$langId] ?? '');
$fields[] = FormField::text($fieldName, [
'label' => (string)($language['name'] ?? $langId),
]);
}
$actionUrl = '/admin/languages/translation_save/' . ($isNew ? '' : ('id=' . $translationId));
$actions = [
FormAction::save($actionUrl, '/admin/languages/translation_list/'),
FormAction::cancel('/admin/languages/translation_list/'),
];
return new FormEditViewModel(
$this->getTranslationFormId(),
$isNew ? 'Nowe tlumaczenie' : 'Edycja tlumaczenia',
$data,
$fields,
[],
$actions,
'POST',
$actionUrl,
'/admin/languages/translation_list/',
true,
$isNew ? [] : ['id' => $translationId],
null,
$errors
);
}
private function extractLegacyTranslations(array $values, array $languages): array
{
$result = [];
foreach ($languages as $language) {
$langId = (string)($language['id'] ?? '');
$result[$langId] = (string)($values[$langId] ?? '');
}
return $result;
}
private function clearLanguageSessions(array $languages): void
{
foreach ($languages as $language) {
if (!isset($language['id'])) {
continue;
}
\Shared\Helpers\Helpers::delete_session('lang-' . (string)$language['id']);
}
}
private function getLanguageFormId(): string
{
return 'languages-language-edit';
}
private function getTranslationFormId(): string
{
return 'languages-translation-edit';
}
}

View File

@@ -0,0 +1,172 @@
<?php
namespace admin\Controllers;
use Domain\Layouts\LayoutsRepository;
use Domain\Languages\LanguagesRepository;
class LayoutsController
{
private LayoutsRepository $repository;
private LanguagesRepository $languagesRepository;
public function __construct(LayoutsRepository $repository, LanguagesRepository $languagesRepository)
{
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
}
public function list(): string
{
$sortableColumns = ['name', 'status', 'categories_default'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Szablon domyslny',
'type' => 'select',
'options' => [
'' => '- domyslny -',
'1' => 'tak',
'0' => 'nie',
],
],
[
'key' => 'categories_default',
'label' => 'Domyslny (kategorie)',
'type' => 'select',
'options' => [
'' => '- kategorie -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'name'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$rows[] = [
'lp' => $lp++ . '.',
'name' => '<a href="/admin/layouts/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'status' => ((int)($item['status'] ?? 0) === 1) ? '<span class="text-system">tak</span>' : 'nie',
'categories_default' => ((int)($item['categories_default'] ?? 0) === 1) ? '<span class="text-system">tak</span>' : 'nie',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/layouts/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/layouts/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrany szablon?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Szablon domyslny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'categories_default', 'sort_key' => 'categories_default', 'label' => 'Domyslny (kategorie)', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/layouts/list/',
'Brak danych w tabeli.',
'/admin/layouts/edit/',
'Dodaj szablon'
);
return \Shared\Tpl\Tpl::view('layouts/layouts-list', [
'viewModel' => $viewModel,
]);
}
public function edit(): string
{
return \Shared\Tpl\Tpl::view('layouts/layout-edit', [
'layout' => $this->repository->find((int)\Shared\Helpers\Helpers::get('id')),
'menus' => $this->repository->menusWithPages(),
'categories' => $this->repository->categoriesTree(),
'dlang' => $this->languagesRepository->defaultLanguageId(),
]);
}
public function save(): void
{
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania szablonu wystapil blad. Prosze sprobowac ponownie.'];
$values = json_decode((string)\Shared\Helpers\Helpers::get('values'), true);
if (is_array($values)) {
$id = $this->repository->save($values);
if (!empty($id)) {
$response = ['status' => 'ok', 'msg' => 'Szablon zostal zapisany.', 'id' => $id];
}
}
echo json_encode($response);
exit;
}
public function delete(): void
{
if ($this->repository->delete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Szablon zostal usuniety.');
}
header('Location: /admin/layouts/list/');
exit;
}
}

View File

@@ -0,0 +1,514 @@
<?php
namespace admin\Controllers;
use Domain\Newsletter\NewsletterRepository;
use Domain\Newsletter\NewsletterPreviewRenderer;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\Support\Forms\FormRequestHandler;
class NewsletterController
{
private NewsletterRepository $repository;
private NewsletterPreviewRenderer $previewRenderer;
private FormRequestHandler $formHandler;
public function __construct(NewsletterRepository $repository, NewsletterPreviewRenderer $previewRenderer)
{
$this->repository = $repository;
$this->previewRenderer = $previewRenderer;
$this->formHandler = new FormRequestHandler();
}
public function list(): string
{
return $this->emails_list();
}
public function view_list(): string
{
return $this->list();
}
public function emails_list(): string
{
$sortableColumns = ['email', 'status'];
$filterDefinitions = [
[
'key' => 'email',
'label' => 'Email',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Potwierdzony',
'type' => 'select',
'options' => [
'' => '- potwierdzony -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'email'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listSubscribersForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$email = trim((string)($item['email'] ?? ''));
$status = (int)($item['status'] ?? 0);
$rows[] = [
'lp' => $lp++ . '.',
'email' => htmlspecialchars($email, ENT_QUOTES, 'UTF-8'),
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'_actions' => [
[
'label' => 'Usun',
'url' => '/admin/newsletter/email_delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrany adres email?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'email', 'sort_key' => 'email', 'label' => 'Email', 'sortable' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Potwierdzony', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/newsletter/emails_list/',
'Brak danych w tabeli.'
);
return \Shared\Tpl\Tpl::view('newsletter/emails-list', [
'viewModel' => $viewModel,
]);
}
public function email_delete(): void
{
if ($this->repository->deleteSubscriber((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Adres email zostal usuniety.');
}
header('Location: /admin/newsletter/emails_list/');
exit;
}
public function delete(): void
{
$this->email_delete();
}
public function prepare(): string
{
\Shared\Helpers\Helpers::alert('Funkcjonalnosc "Wysylka - przygotowanie" jest tymczasowo wylaczona.');
header('Location: /admin/newsletter/emails_list/');
exit;
}
public function preview(): string
{
return '';
}
public function send(): void
{
\Shared\Helpers\Helpers::alert('Funkcjonalnosc "Wysylka - przygotowanie" jest tymczasowo wylaczona.');
header('Location: /admin/newsletter/emails_list/');
exit;
}
public function settings(): string
{
$settings = $this->repository->getSettings();
$validationErrors = $_SESSION['form_errors'][$this->settingsFormId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->settingsFormId()]);
}
return \Shared\Tpl\Tpl::view('newsletter/settings', [
'form' => $this->buildSettingsFormViewModel($settings, $validationErrors),
]);
}
public function settings_save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
if (!is_array($values)) {
echo json_encode(['status' => 'error', 'msg' => 'Nieprawidlowe dane formularza.']);
exit;
}
$this->repository->saveSettings($values);
\Shared\Helpers\Helpers::alert('Ustawienia zostaly zapisane.');
echo json_encode(['status' => 'ok', 'msg' => 'Ustawienia zostaly zapisane.']);
exit;
}
$viewModel = $this->buildSettingsFormViewModel($this->repository->getSettings());
$result = $this->formHandler->handleSubmit($viewModel, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->settingsFormId()] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$this->repository->saveSettings($result['data']);
\Shared\Helpers\Helpers::alert('Ustawienia zostaly zapisane.');
echo json_encode([
'success' => true,
'message' => 'Ustawienia zostaly zapisane.',
]);
exit;
}
public function email_templates_user(): string
{
\Shared\Helpers\Helpers::alert('Funkcjonalnosc "Szablony uzytkownika" jest tymczasowo wylaczona.');
header('Location: /admin/newsletter/email_templates_admin/');
exit;
}
public function email_templates_admin(): string
{
$viewModel = $this->templatesListViewModel();
return \Shared\Tpl\Tpl::view('newsletter/email-templates-admin', [
'viewModel' => $viewModel,
]);
}
public function email_template_edit(): string
{
$template = $this->repository->templateDetails((int)\Shared\Helpers\Helpers::get('id'));
if (!is_array($template) || (int)($template['is_admin'] ?? 0) !== 1) {
\Shared\Helpers\Helpers::alert('Dostepne sa tylko szablony administracyjne.');
header('Location: /admin/newsletter/email_templates_admin/');
exit;
}
$formId = $this->templateFormId((int)$template['id']);
$validationErrors = $_SESSION['form_errors'][$formId] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$formId]);
}
return \Shared\Tpl\Tpl::view('newsletter/email-template-edit', [
'form' => $this->buildTemplateFormViewModel($template, $validationErrors),
]);
}
public function template_save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania wystapil blad.'];
if (is_array($values)) {
$templateId = (int)($values['id'] ?? 0);
$template = $this->repository->templateDetails($templateId);
if (is_array($template) && (int)($template['is_admin'] ?? 0) === 1) {
$id = $this->repository->saveTemplate(
$templateId,
(string)($values['name'] ?? ''),
(string)($values['text'] ?? '')
);
if ($id) {
$response = ['status' => 'ok', 'msg' => 'Zmiany zostaly zapisane.', 'id' => $id];
}
}
}
echo json_encode($response);
exit;
}
$template = $this->repository->templateDetails((int)\Shared\Helpers\Helpers::get('id'));
if (!is_array($template) || (int)($template['is_admin'] ?? 0) !== 1) {
echo json_encode([
'success' => false,
'errors' => ['general' => 'Dostepne sa tylko szablony administracyjne.'],
]);
exit;
}
$form = $this->buildTemplateFormViewModel($template);
$result = $this->formHandler->handleSubmit($form, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->templateFormId((int)$template['id'])] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$data = $result['data'];
$id = $this->repository->saveTemplate(
(int)($template['id'] ?? 0),
(string)($data['name'] ?? ''),
(string)($data['text'] ?? '')
);
if ($id) {
echo json_encode([
'success' => true,
'id' => $id,
'message' => 'Zmiany zostaly zapisane.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania wystapil blad.'],
]);
exit;
}
public function email_template_delete(): void
{
\Shared\Helpers\Helpers::alert('Usuwanie szablonow uzytkownika jest tymczasowo wylaczone.');
header('Location: /admin/newsletter/email_templates_admin/');
exit;
}
private function buildSettingsFormViewModel(array $settings, ?array $errors = null): FormEditViewModel
{
$data = [
'newsletter_header' => (string)($settings['newsletter_header'] ?? ''),
'newsletter_footer' => (string)($settings['newsletter_footer'] ?? ''),
];
$fields = [
FormField::editor('newsletter_header', [
'label' => 'Naglowek',
'height' => 150,
]),
FormField::editor('newsletter_footer', [
'label' => 'Stopka',
'height' => 150,
]),
];
$actionUrl = '/admin/newsletter/settings_save/';
$actions = [
FormAction::save($actionUrl, '/admin/newsletter/settings/'),
];
return new FormEditViewModel(
$this->settingsFormId(),
'Edycja ustawien newslettera',
$data,
$fields,
[],
$actions,
'POST',
$actionUrl,
'/admin/newsletter/settings/',
true,
[],
null,
$errors
);
}
private function buildTemplateFormViewModel(array $template, ?array $errors = null): FormEditViewModel
{
$templateId = (int)($template['id'] ?? 0);
$isAdminTemplate = (int)($template['is_admin'] ?? 0) === 1;
$isNew = $templateId <= 0;
$data = [
'id' => $templateId,
'name' => (string)($template['name'] ?? ''),
'text' => (string)($template['text'] ?? ''),
];
$nameAttrs = [];
if ($isAdminTemplate) {
$nameAttrs['readonly'] = 'readonly';
}
$fields = [
FormField::text('name', [
'label' => 'Nazwa',
'required' => true,
'attributes' => $nameAttrs,
]),
FormField::editor('text', [
'label' => 'Tresc',
'required' => true,
'height' => 350,
]),
];
$backUrl = '/admin/newsletter/email_templates_admin/';
$actionUrl = '/admin/newsletter/template_save/' . ($isNew ? '' : ('id=' . $templateId));
$actions = [
FormAction::save($actionUrl, $backUrl),
FormAction::cancel($backUrl),
];
return new FormEditViewModel(
$this->templateFormId($templateId),
'Edycja szablonu newslettera',
$data,
$fields,
[],
$actions,
'POST',
$actionUrl,
$backUrl,
true,
['id' => $templateId],
null,
$errors
);
}
private function templatesListViewModel(): PaginatedTableViewModel
{
$sortableColumns = ['name'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
];
$basePath = '/admin/newsletter/email_templates_admin/';
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'name'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listTemplatesForAdmin(
true,
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$actions = [
[
'label' => 'Edytuj',
'url' => '/admin/newsletter/email_template_edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
];
$rows[] = [
'lp' => $lp++ . '.',
'name' => '<a href="/admin/newsletter/email_template_edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'_actions' => $actions,
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
return new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
$basePath,
'Brak danych w tabeli.'
);
}
private function settingsFormId(): string
{
return 'newsletter-settings-edit';
}
private function templateFormId(int $templateId): string
{
return 'newsletter-template-edit-' . $templateId;
}
}

View File

@@ -0,0 +1,660 @@
<?php
namespace admin\Controllers;
use Domain\Pages\PagesRepository;
use Domain\Languages\LanguagesRepository;
use Domain\Layouts\LayoutsRepository;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class PagesController
{
private PagesRepository $repository;
private LanguagesRepository $languagesRepository;
private LayoutsRepository $layoutsRepository;
public function __construct(
PagesRepository $repository,
LanguagesRepository $languagesRepository,
LayoutsRepository $layoutsRepository
) {
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
$this->layoutsRepository = $layoutsRepository;
}
public function list(): string
{
return \Shared\Tpl\Tpl::view('pages/pages-list', [
'menus' => $this->repository->menusWithPages(),
'cookie_pages' => $this->cookieState('cookie_pages'),
'cookie_menus' => $this->cookieState('cookie_menus'),
]);
}
public function browseList(): string
{
$menus = $this->repository->menusWithPages();
$defaultLanguage = $this->languagesRepository->defaultLanguageId();
foreach ($menus as $index => $menu) {
$menus[$index]['pages'] = $this->withPreviewUrls($menu['pages'] ?? [], $defaultLanguage);
}
return \Shared\Tpl\Tpl::view('pages/pages-browse-list', [
'menus' => $menus,
'modal' => \Shared\Helpers\Helpers::get('modal'),
'cookie_pages' => $this->cookieState('cookie_pages'),
'cookie_menus' => $this->cookieState('cookie_menus'),
]);
}
public function pagesUrlBrowser(): string
{
return $this->browseList();
}
public function menuEdit(): string
{
$menu = $this->repository->menuDetails((int)\Shared\Helpers\Helpers::get('id')) ?: [];
return \Shared\Tpl\Tpl::view('pages/menu-edit', [
'form' => $this->buildMenuFormViewModel($menu),
]);
}
public function menuSave(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania menu wystapil blad. Prosze sprobowac ponownie.'];
$values = json_decode((string)$legacyValues, true);
if (is_array($values) && $this->repository->menuSave(
(int)($values['id'] ?? 0),
(string)($values['name'] ?? ''),
$values['status'] ?? 0
)) {
$response = ['status' => 'ok', 'msg' => 'Menu zostalo zapisane.'];
}
echo json_encode($response);
exit;
}
$menuId = (int)\Shared\Helpers\Helpers::get('id');
$name = trim((string)\Shared\Helpers\Helpers::get('name'));
$status = \Shared\Helpers\Helpers::get('status');
if ($name === '') {
echo json_encode([
'success' => false,
'errors' => ['name' => 'Pole "Nazwa" jest wymagane.'],
]);
exit;
}
if ($this->repository->menuSave($menuId, $name, $status)) {
echo json_encode([
'success' => true,
'message' => 'Menu zostalo zapisane.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania menu wystapil blad. Prosze sprobowac ponownie.'],
]);
exit;
}
/**
* @param array<string, mixed> $menu
*/
private function buildMenuFormViewModel(array $menu): FormEditViewModel
{
$menuId = (int)($menu['id'] ?? 0);
$actionUrl = '/admin/pages/menuSave/' . ($menuId > 0 ? ('id=' . $menuId) : '');
$fields = [
FormField::hidden('id', $menuId),
FormField::text('name', [
'label' => 'Nazwa',
'required' => true,
'attributes' => ['class' => 'require'],
'value' => (string)($menu['name'] ?? ''),
]),
FormField::switch('status', [
'label' => 'Aktywne',
'value' => (int)($menu['status'] ?? 0) === 1,
]),
];
$actions = [
FormAction::save($actionUrl, '/admin/pages/list/'),
FormAction::cancel('/admin/pages/list/'),
];
return new FormEditViewModel(
'pages-menu-edit',
'Zapisz menu',
$menu,
$fields,
[],
$actions,
'POST',
$actionUrl,
'/admin/pages/list/',
true,
['id' => $menuId]
);
}
public function menuDelete(): void
{
if ($this->repository->menuDelete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::set_message('Menu zostało usunięte.');
} else {
\Shared\Helpers\Helpers::alert('Podczas usuwania menu wystąpił błąd. Aby usunąć menu, nie może ono posiadać przypiętych stron.');
}
header('Location: /admin/pages/list/');
exit;
}
public function edit(): string
{
$page = $this->repository->pageDetails((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$parentId = (int)\Shared\Helpers\Helpers::get('pid');
$menuId = (int)\Shared\Helpers\Helpers::get('menu_id');
$menus = $this->repository->menusList();
$layouts = $this->layoutsRepository->listAll();
$languages = $this->languagesRepository->languagesList();
return \Shared\Tpl\Tpl::view('pages/page-edit', [
'form' => $this->buildPageFormViewModel(
$page,
$parentId,
$menuId,
$menus,
$layouts,
$languages
),
]);
}
public function save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania strony wystapil blad. Prosze sprobowac ponownie.'];
$values = json_decode((string)$legacyValues, true);
if (is_array($values)) {
$id = $this->repository->pageSave($values);
if (!empty($id)) {
$response = [
'status' => 'ok',
'msg' => 'Strona zostala zapisana.',
'id' => (int)$id,
];
}
}
echo json_encode($response);
exit;
}
$data = $_POST;
if (!isset($data['id']) || $data['id'] === '') {
$data['id'] = (int)\Shared\Helpers\Helpers::get('id');
}
if (!isset($data['parent_id']) || $data['parent_id'] === '') {
$data['parent_id'] = (int)\Shared\Helpers\Helpers::get('pid');
}
if ((!isset($data['menu_id']) || $data['menu_id'] === '') && (int)\Shared\Helpers\Helpers::get('menu_id') > 0) {
$data['menu_id'] = (int)\Shared\Helpers\Helpers::get('menu_id');
}
$savedId = $this->repository->pageSave($data);
if (!empty($savedId)) {
echo json_encode([
'success' => true,
'message' => 'Strona zostala zapisana.',
'id' => (int)$savedId,
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania strony wystapil blad. Prosze sprobowac ponownie.'],
]);
exit;
}
/**
* @param array<string, mixed> $page
* @param array<int, array<string, mixed>> $menus
* @param array<int, array<string, mixed>> $layouts
* @param array<int, array<string, mixed>> $languages
*/
private function buildPageFormViewModel(
array $page,
int $parentId,
int $menuId,
array $menus,
array $layouts,
array $languages
): FormEditViewModel {
$pageId = (int)($page['id'] ?? 0);
$isNew = $pageId <= 0;
$resolvedParentId = $pageId > 0 ? (int)($page['parent_id'] ?? 0) : $parentId;
$resolvedMenuId = $pageId > 0 ? (int)($page['menu_id'] ?? 0) : $menuId;
$menuOptions = [];
foreach ($menus as $menu) {
$id = (int)($menu['id'] ?? 0);
if ($id <= 0) {
continue;
}
$menuOptions[$id] = (string)($menu['name'] ?? '');
}
$layoutOptions = ['' => '---- szablon ----'];
foreach ($layouts as $layout) {
$id = (int)($layout['id'] ?? 0);
if ($id <= 0) {
continue;
}
$layoutOptions[$id] = (string)($layout['name'] ?? '');
}
$data = [
'id' => $pageId,
'parent_id' => $resolvedParentId > 0 ? $resolvedParentId : '',
'menu_id' => $resolvedMenuId > 0 ? $resolvedMenuId : '',
'page_type' => (int)($page['page_type'] ?? 0),
'sort_type' => (int)($page['sort_type'] ?? 0),
'layout_id' => (int)($page['layout_id'] ?? 0),
'articles_limit' => (int)($page['articles_limit'] ?? 2),
'show_title' => (int)($page['show_title'] ?? 1),
'status' => (int)($page['status'] ?? 1),
'start' => (int)($page['start'] ?? 0),
'category_id' => (int)($page['category_id'] ?? 0),
'languages' => [],
];
foreach ($languages as $language) {
$langId = (string)($language['id'] ?? '');
if ($langId === '') {
continue;
}
$translation = is_array($page['languages'][$langId] ?? null) ? $page['languages'][$langId] : [];
$data['languages'][$langId] = [
'title' => (string)($translation['title'] ?? ''),
'link' => (string)($translation['link'] ?? ''),
'seo_link' => (string)($translation['seo_link'] ?? ''),
'page_title' => (string)($translation['page_title'] ?? ''),
'meta_title' => (string)($translation['meta_title'] ?? ''),
'meta_description' => (string)($translation['meta_description'] ?? ''),
'meta_keywords' => (string)($translation['meta_keywords'] ?? ''),
'noindex' => (int)($translation['noindex'] ?? 0),
'canonical' => (string)($translation['canonical'] ?? ''),
];
}
$tabs = [
new FormTab('content', 'Tresc', 'fa-file'),
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
new FormTab('seo', 'SEO', 'fa-globe'),
];
$fields = [
FormField::hidden('id', $pageId),
FormField::hidden('parent_id', $resolvedParentId > 0 ? $resolvedParentId : ''),
FormField::langSection('page_content', 'content', [
FormField::text('title', [
'label' => 'Nazwa strony',
'required' => true,
]),
]),
FormField::select('menu_id', [
'label' => 'Menu',
'tab' => 'settings',
'options' => $menuOptions,
'value' => $resolvedMenuId > 0 ? $resolvedMenuId : '',
]),
FormField::select('page_type', [
'label' => 'Typ strony',
'tab' => 'settings',
'options' => $this->repository->pageTypes(),
'attributes' => ['id' => 'page_type'],
'value' => (int)($page['page_type'] ?? 0),
]),
FormField::langSection('page_links', 'settings', [
FormField::text('link', [
'label' => 'Link',
]),
]),
FormField::text('category_id', [
'label' => 'ID kategorii',
'tab' => 'settings',
'attributes' => ['id' => 'category_id'],
'value' => (int)($page['category_id'] ?? 0),
]),
FormField::select('sort_type', [
'label' => 'Sortowanie artykulow',
'tab' => 'settings',
'attributes' => ['id' => 'sort_type'],
'options' => $this->repository->sortTypes(),
'value' => (int)($page['sort_type'] ?? 0),
]),
FormField::select('layout_id', [
'label' => 'Szablon',
'tab' => 'settings',
'attributes' => ['id' => 'layout_id'],
'options' => $layoutOptions,
'value' => (int)($page['layout_id'] ?? 0),
]),
FormField::text('articles_limit', [
'label' => 'Liczba artykulow na stronie',
'tab' => 'settings',
'attributes' => ['id' => 'articles_limit'],
'value' => (int)($page['articles_limit'] ?? 2),
]),
FormField::switch('show_title', [
'label' => 'Pokaz tytul',
'tab' => 'settings',
'value' => (int)($page['show_title'] ?? 0) === 1 || $isNew,
]),
FormField::switch('status', [
'label' => 'Aktywna',
'tab' => 'settings',
'value' => (int)($page['status'] ?? 0) === 1 || $isNew,
]),
FormField::switch('start', [
'label' => 'Strona startowa',
'tab' => 'settings',
'value' => (int)($page['start'] ?? 0) === 1,
]),
FormField::langSection('page_seo', 'seo', [
FormField::text('seo_link', [
'label' => 'Link SEO',
'attributes' => [
'icon_content' => 'generuj',
'icon_js' => 'generateSeoLinkForButton(\'{lang}\')',
],
]),
FormField::text('page_title', [
'label' => 'Tytul strony (h1)',
]),
FormField::text('meta_title', [
'label' => 'Meta title',
]),
FormField::textarea('meta_description', [
'label' => 'Meta description',
]),
FormField::textarea('meta_keywords', [
'label' => 'Meta keywords',
]),
FormField::select('noindex', [
'label' => 'Blokuj indeksacje',
'options' => [0 => 'nie', 1 => 'tak'],
]),
FormField::text('canonical', [
'label' => 'Rel canonical',
]),
]),
FormField::custom('page_edit_script', '
<script type="text/javascript">
(function () {
function toggleByType() {
var pageType = String($(\'#page_type\').val() || \'\');
var $links = $(\'#languages-page_links\');
var $category = $(\'#category_id\').closest(\'.form-group\');
var $articlesLimit = $(\'#articles_limit\').closest(\'.form-group\');
var $sortType = $(\'#sort_type\').closest(\'.form-group\');
if (pageType === \'0\' || pageType === \'1\' || pageType === \'2\') {
$articlesLimit.show();
$sortType.show();
$links.addClass(\'hide\');
$category.hide();
} else if (pageType === \'3\') {
$links.removeClass(\'hide\');
$articlesLimit.hide();
$sortType.hide();
$category.hide();
} else if (pageType === \'5\') {
$category.show();
$links.addClass(\'hide\');
$articlesLimit.hide();
$sortType.hide();
} else {
$links.addClass(\'hide\');
$category.hide();
$articlesLimit.hide();
$sortType.hide();
}
}
function generateSeoLink(langId, title) {
if (!title) {
return;
}
$.ajax({
type: \'POST\',
cache: false,
url: \'/admin/pages/generateSeoLink/\',
data: {
title: title,
page_id: ' . $pageId . '
},
success: function (data) {
var response = data;
if (typeof data === \'string\') {
try { response = JSON.parse(data); } catch (e) { response = null; }
}
if (response && response.status === \'ok\') {
$(\'#seo_link_\' + langId).val(response.seo_link || \'\');
}
}
});
}
window.generateSeoLinkForButton = function (langId) {
var title = $(\'#title_\' + langId).val() || \'\';
generateSeoLink(langId, title);
};
$(function () {
$(\'#page_type\').on(\'change\', toggleByType);
toggleByType();
$(\'[id^=title_]\').on(\'blur\', function () {
var fieldId = $(this).attr(\'id\') || \'\';
var langId = fieldId.replace(/^title_/, \'\');
if (!langId) {
return;
}
var $seo = $(\'#seo_link_\' + langId);
if ($seo.length && !$seo.val()) {
generateSeoLink(langId, $(this).val());
}
});
});
})();
</script>', [
'tab' => 'settings',
]),
];
$actionUrl = '/admin/pages/save/' . ($pageId > 0 ? ('id=' . $pageId) : '');
$actions = [
FormAction::save($actionUrl, '/admin/pages/list/'),
FormAction::cancel('/admin/pages/list/'),
];
return new FormEditViewModel(
'pages-page-edit',
'Edycja strony',
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/pages/list/',
true,
[
'id' => $pageId,
'parent_id' => $resolvedParentId > 0 ? $resolvedParentId : '',
],
$languages
);
}
public function delete(): void
{
if ($this->repository->pageDelete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::set_message('Strona zostala usunieta.');
} else {
\Shared\Helpers\Helpers::alert('Podczas usuwania strony wystapil blad. Aby usunac strone nie moze ona posiadac przypietych podstron.');
}
header('Location: /admin/pages/list/');
exit;
}
public function pageArticles(): string
{
$pageId = (int)\Shared\Helpers\Helpers::get('id');
return \Shared\Tpl\Tpl::view('pages/page-articles', [
'page_id' => $pageId,
'articles' => $this->repository->pageArticles($pageId),
]);
}
public function savePagesOrder(): void
{
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania kolejnosci stron wystapil blad. Prosze sprobowac ponownie.'];
if ($this->repository->savePagesOrder((int)\Shared\Helpers\Helpers::get('menu_id'), \Shared\Helpers\Helpers::get('pages'))) {
$response = ['status' => 'ok'];
}
echo json_encode($response);
exit;
}
public function saveArticlesOrder(): void
{
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania kolejnosci wyswietlania artykulow wystapil blad. Prosze sprobowac ponownie.'];
if ($this->repository->saveArticlesOrder((int)\Shared\Helpers\Helpers::get('page_id'), \Shared\Helpers\Helpers::get('articles'))) {
$response = ['status' => 'ok'];
}
echo json_encode($response);
exit;
}
public function generateSeoLink(): void
{
$response = ['status' => 'error', 'msg' => 'Podczas generowania pola "seo link" wystapil blad. Prosze sprobowac ponownie.'];
$seoLink = $this->repository->generateSeoLink(
(string)\Shared\Helpers\Helpers::get('title'),
(int)\Shared\Helpers\Helpers::get('page_id'),
(int)\Shared\Helpers\Helpers::get('article_id'),
(int)\Shared\Helpers\Helpers::get('category_id')
);
if ($seoLink !== '') {
$response = [
'status' => 'ok',
'seo_link' => $seoLink,
];
}
echo json_encode($response);
exit;
}
public function cookieMenus(): void
{
$this->repository->toggleCookieValue('cookie_menus', (int)\Shared\Helpers\Helpers::get('menu_id'));
exit;
}
public function cookiePages(): void
{
$this->repository->toggleCookieValue('cookie_pages', (int)\Shared\Helpers\Helpers::get('page_id'));
exit;
}
/**
* @param array<int, array<string, mixed>> $pages
* @return array<int, array<string, mixed>>
*/
private function withPreviewUrls(array $pages, string $defaultLanguage): array
{
foreach ($pages as $index => $page) {
$pageId = (int)($page['id'] ?? 0);
$languages = is_array($page['languages'] ?? null) ? $page['languages'] : [];
$previewUrls = [];
foreach ($languages as $languageRow) {
$langId = (string)($languageRow['lang_id'] ?? '');
if ($langId === '') {
continue;
}
$previewUrls[$langId] = $this->repository->pageUrlPreview(
$pageId,
$langId,
(string)($languageRow['title'] ?? ''),
(string)($languageRow['seo_link'] ?? ''),
$defaultLanguage
);
}
$page['preview_urls'] = $previewUrls;
$page['subpages'] = $this->withPreviewUrls($page['subpages'] ?? [], $defaultLanguage);
$pages[$index] = $page;
}
return $pages;
}
/**
* @return array<int, int>
*/
private function cookieState(string $cookieName): array
{
if (empty($_COOKIE[$cookieName])) {
return [];
}
$decoded = @unserialize((string)$_COOKIE[$cookieName], ['allowed_classes' => false]);
if (!is_array($decoded)) {
return [];
}
$state = [];
foreach ($decoded as $key => $value) {
$state[(int)$key] = (int)$value;
}
return $state;
}
}

View File

@@ -0,0 +1,165 @@
<?php
namespace admin\Controllers;
use Domain\Product\ProductRepository;
class ProductArchiveController
{
private ProductRepository $productRepository;
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
public function list(): string
{
$sortableColumns = ['id', 'name', 'price_brutto', 'price_brutto_promo', 'quantity'];
$filterDefinitions = [
[
'key' => 'phrase',
'label' => 'Nazwa / EAN / SKU',
'type' => 'text',
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'id',
[10, 15, 25, 50, 100],
10
);
$result = $this->productRepository->listArchivedForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$listRequest['sortDir'],
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$sku = trim((string)($item['sku'] ?? ''));
$ean = trim((string)($item['ean'] ?? ''));
$imageSrc = trim((string)($item['image_src'] ?? ''));
$imageAlt = trim((string)($item['image_alt'] ?? ''));
$priceBrutto = (string)($item['price_brutto'] ?? '');
$priceBruttoPromo = (string)($item['price_brutto_promo'] ?? '');
$quantity = (int)($item['quantity'] ?? 0);
$combinations = (int)($item['combinations'] ?? 0);
if ($imageSrc === '') {
$imageSrc = '/admin/layout/images/no-image.png';
} elseif (!preg_match('#^(https?:)?//#i', $imageSrc) && strpos($imageSrc, '/') !== 0) {
$imageSrc = '/' . ltrim($imageSrc, '/');
}
$categories = trim((string)$this->productRepository->productCategoriesText($id));
$categoriesHtml = '';
if ($categories !== '') {
$categoriesHtml = '<small class="text-muted product-categories">'
. htmlspecialchars($categories, ENT_QUOTES, 'UTF-8')
. '</small>';
}
$skuEanParts = [];
if ($sku !== '') {
$skuEanParts[] = 'SKU: ' . htmlspecialchars($sku, ENT_QUOTES, 'UTF-8');
}
if ($ean !== '') {
$skuEanParts[] = 'EAN: ' . htmlspecialchars($ean, ENT_QUOTES, 'UTF-8');
}
$skuEanHtml = '';
if (!empty($skuEanParts)) {
$skuEanHtml = '<small class="text-muted product-categories">' . implode(', ', $skuEanParts) . '</small>';
}
$productCell = '<div class="product-image product-archive-thumb-wrap">'
. '<img src="' . htmlspecialchars($imageSrc, ENT_QUOTES, 'UTF-8') . '" alt="' . htmlspecialchars($imageAlt, ENT_QUOTES, 'UTF-8') . '" '
. 'data-preview-src="' . htmlspecialchars($imageSrc, ENT_QUOTES, 'UTF-8') . '" '
. 'class="img-responsive product-archive-thumb-image js-product-archive-thumb-preview" loading="lazy">'
. '</div>'
. '<div class="product-name">'
. '<a href="/admin/shop_product/product_edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>'
. '</div>'
. $categoriesHtml
. $skuEanHtml;
$rows[] = [
'lp' => $lp++ . '.',
'product' => $productCell,
'price_brutto' => $priceBrutto !== '' ? $priceBrutto : '-',
'price_brutto_promo' => $priceBruttoPromo !== '' ? $priceBruttoPromo : '-',
'quantity' => (string)$quantity,
'_actions' => [
[
'label' => 'Przywroc',
'url' => '/admin/product_archive/unarchive/product_id=' . $id,
'class' => 'btn btn-xs btn-success',
'confirm' => 'Na pewno chcesz przywrocic wybrany produkt z archiwum?',
'confirm_ok' => 'Przywroc',
'confirm_cancel' => 'Anuluj',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'product', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'price_brutto', 'sort_key' => 'price_brutto', 'label' => 'Cena', 'class' => 'text-center', 'sortable' => true],
['key' => 'price_brutto_promo', 'sort_key' => 'price_brutto_promo', 'label' => 'Cena promocyjna', 'class' => 'text-center', 'sortable' => true],
['key' => 'quantity', 'sort_key' => 'quantity', 'label' => 'Stan MG', 'class' => 'text-center', 'sortable' => true]
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $listRequest['sortDir'],
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $listRequest['sortDir'],
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/product_archive/list/',
'Brak danych w tabeli.',
null,
null,
'product-archive/products-list-custom-script'
);
return \Shared\Tpl\Tpl::view('product-archive/products-list', [
'viewModel' => $viewModel,
]);
}
public function unarchive(): void
{
if ( $this->productRepository->unarchive( (int) \Shared\Helpers\Helpers::get( 'product_id' ) ) )
\Shared\Helpers\Helpers::alert( 'Produkt został przywrócony z archiwum.' );
else
\Shared\Helpers\Helpers::alert( 'Podczas przywracania produktu z archiwum wystąpił błąd. Proszę spróbować ponownie' );
header( 'Location: /admin/product_archive/list/' );
exit;
}
}

View File

@@ -0,0 +1,297 @@
<?php
namespace admin\Controllers;
use Domain\Languages\LanguagesRepository;
use Domain\Scontainers\ScontainersRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
use admin\Support\Forms\FormRequestHandler;
class ScontainersController
{
private ScontainersRepository $repository;
private LanguagesRepository $languagesRepository;
private FormRequestHandler $formHandler;
public function __construct(ScontainersRepository $repository, LanguagesRepository $languagesRepository)
{
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
$this->formHandler = new FormRequestHandler();
}
public function list(): string
{
$sortableColumns = ['id', 'title', 'status'];
$filterDefinitions = [
[
'key' => 'title',
'label' => 'Tytul',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'id'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'DESC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$title = trim((string)($item['title'] ?? ''));
$rows[] = [
'lp' => $lp++ . '.',
'title' => '<a href="/admin/scontainers/edit/id=' . $id . '">' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '</a>',
'code' => '[KONTENER:' . $id . ']',
'status' => ((int)($item['status'] ?? 0) === 1) ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/scontainers/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/scontainers/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrany kontener?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'title', 'sort_key' => 'title', 'label' => 'Tytul', 'sortable' => true, 'raw' => true],
['key' => 'code', 'label' => 'Kod', 'sortable' => false],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/scontainers/list/',
'Brak danych w tabeli.',
'/admin/scontainers/edit/',
'Dodaj kontener'
);
return \Shared\Tpl\Tpl::view('scontainers/containers-list', [
'viewModel' => $viewModel,
]);
}
public function view_list(): string
{
return $this->list();
}
public function edit(): string
{
$container = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$languages = $this->languagesRepository->languagesList();
$validationErrors = $_SESSION['form_errors'][$this->formId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->formId()]);
}
return \Shared\Tpl\Tpl::view('scontainers/container-edit', [
'form' => $this->buildFormViewModel($container, $languages, $validationErrors),
]);
}
public function container_edit(): string
{
return $this->edit();
}
public function save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania kontenera wystapil blad.'];
if (is_array($values)) {
$savedId = $this->repository->save($values);
if (!empty($savedId)) {
$response = ['status' => 'ok', 'msg' => 'Kontener zostal zapisany.', 'id' => $savedId];
}
}
echo json_encode($response);
exit;
}
$container = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$languages = $this->languagesRepository->languagesList();
$form = $this->buildFormViewModel($container, $languages);
$result = $this->formHandler->handleSubmit($form, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->formId()] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$data = $result['data'];
$savedId = $this->repository->save([
'id' => (int)($data['id'] ?? 0),
'status' => $data['status'] ?? 0,
'show_title' => $data['show_title'] ?? 0,
'translations' => $data['translations'] ?? [],
]);
if ($savedId) {
echo json_encode([
'success' => true,
'id' => $savedId,
'message' => 'Kontener zostal zapisany.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania kontenera wystapil blad.'],
]);
exit;
}
public function container_save(): void
{
$this->save();
}
public function delete(): void
{
if ($this->repository->delete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Kontener zostal usuniety.');
}
header('Location: /admin/scontainers/list/');
exit;
}
public function container_delete(): void
{
$this->delete();
}
private function buildFormViewModel(array $container, array $languages, ?array $errors = null): FormEditViewModel
{
$id = (int)($container['id'] ?? 0);
$isNew = $id <= 0;
$data = [
'id' => $id,
'status' => (int)($container['status'] ?? 1),
'show_title' => (int)($container['show_title'] ?? 0),
'languages' => is_array($container['languages'] ?? null) ? $container['languages'] : [],
];
$fields = [
FormField::hidden('id', $id),
FormField::langSection('translations', 'content', [
FormField::text('title', [
'label' => 'Tytul',
]),
FormField::editor('text', [
'label' => 'Tresc',
'height' => 300,
]),
]),
FormField::switch('status', [
'label' => 'Aktywny',
'tab' => 'settings',
'value' => true,
]),
FormField::switch('show_title', [
'label' => 'Pokaz tytul',
'tab' => 'settings',
]),
];
$tabs = [
new FormTab('content', 'Tresc', 'fa-file'),
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
];
$actionUrl = '/admin/scontainers/save/' . ($isNew ? '' : ('id=' . $id));
$actions = [
FormAction::save($actionUrl, '/admin/scontainers/list/'),
FormAction::cancel('/admin/scontainers/list/'),
];
return new FormEditViewModel(
$this->formId(),
'Edycja kontenera statycznego',
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/scontainers/list/',
true,
[],
$languages,
$errors
);
}
private function formId(): string
{
return 'scontainers-container-edit';
}
}

View File

@@ -0,0 +1,536 @@
<?php
namespace admin\Controllers;
use Domain\Languages\LanguagesRepository;
use Domain\Settings\SettingsRepository;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
use admin\ViewModels\Forms\FormAction;
use admin\Support\Forms\FormRequestHandler;
/**
* Kontroler ustawien w panelu administratora.
*/
class SettingsController
{
private SettingsRepository $settingsRepository;
private LanguagesRepository $languagesRepository;
private FormRequestHandler $formHandler;
public function __construct(SettingsRepository $settingsRepository, LanguagesRepository $languagesRepository)
{
$this->settingsRepository = $settingsRepository;
$this->languagesRepository = $languagesRepository;
$this->formHandler = new FormRequestHandler();
}
/**
* Czyszczenie cache.
*/
public function clearCache(): void
{
\Shared\Helpers\Helpers::delete_dir('../temp/');
\Shared\Helpers\Helpers::delete_dir('../thumbs/');
$redis = \Shared\Cache\RedisConnection::getInstance()->getConnection();
if ($redis) {
$redis->flushAll();
}
\Shared\Helpers\Helpers::alert('Cache został wyczyszczony.');
\Shared\Helpers\Helpers::htacces();
header('Location: /admin/dashboard/main_view/');
exit;
}
/**
* Czyszczenie cache (AJAX).
*/
public function clearCacheAjax(): void
{
try {
\Shared\Helpers\Helpers::delete_dir('../temp/');
\Shared\Helpers\Helpers::delete_dir('../thumbs/');
$redis = \Shared\Cache\RedisConnection::getInstance()->getConnection();
if ($redis) {
$redis->flushAll();
}
\Shared\Helpers\Helpers::htacces();
echo json_encode(['status' => 'success', 'message' => 'Cache został wyczyszczony.']);
} catch (\Exception $e) {
echo json_encode(['status' => 'error', 'message' => 'Błąd podczas czyszczenia cache: ' . $e->getMessage()]);
}
exit;
}
/**
* Globalna wyszukiwarka admin (produkty + zamowienia) - AJAX.
*/
public function globalSearchAjax(): void
{
global $mdb;
$phrase = trim((string)\Shared\Helpers\Helpers::get('q'));
if ($phrase === '' || mb_strlen($phrase) < 2) {
echo json_encode([
'status' => 'ok',
'items' => [],
]);
exit;
}
$phrase = mb_substr($phrase, 0, 120);
$phraseNormalized = preg_replace('/\s+/', ' ', $phrase);
$phraseNormalized = trim((string)$phraseNormalized);
$like = '%' . $phrase . '%';
$likeNormalized = '%' . $phraseNormalized . '%';
$items = [];
$defaultLang = (string)$this->languagesRepository->defaultLanguage();
try {
$productStmt = $mdb->query(
'SELECT '
. 'p.id, p.ean, p.sku, p.parent_id, psl.name '
. 'FROM pp_shop_products AS p '
. 'LEFT JOIN pp_shop_products_langs AS psl ON psl.product_id = p.id AND psl.lang_id = :lang_id '
. 'WHERE '
. '(p.ean LIKE :q1 OR p.sku LIKE :q2 OR psl.name LIKE :q3) '
. 'AND p.archive != 1 '
. 'ORDER BY p.id DESC '
. 'LIMIT 15',
[
':lang_id' => $defaultLang,
':q1' => $like,
':q2' => $like,
':q3' => $like,
]
);
} catch (\Throwable $e) {
$productStmt = false;
}
$productRows = $productStmt ? $productStmt->fetchAll() : [];
if (is_array($productRows)) {
foreach ($productRows as $row) {
$productId = (int)($row['id'] ?? 0);
if ($productId <= 0) {
continue;
}
$name = trim((string)($row['name'] ?? ''));
if ($name === '') {
$name = 'Produkt #' . $productId;
}
$meta = [];
$sku = trim((string)($row['sku'] ?? ''));
$ean = trim((string)($row['ean'] ?? ''));
if ($sku !== '') {
$meta[] = 'SKU: ' . $sku;
}
if ($ean !== '') {
$meta[] = 'EAN: ' . $ean;
}
$items[] = [
'type' => 'product',
'title' => $name,
'subtitle' => implode(' | ', $meta),
'url' => '/admin/shop_product/product_edit/id=' . $productId,
];
}
}
try {
$orderStmt = $mdb->query(
'SELECT '
. 'id, number, client_name, client_surname, client_email, client_phone '
. 'FROM pp_shop_orders '
. 'WHERE '
. '('
. 'number LIKE :q1 '
. 'OR client_email LIKE :q2 '
. 'OR client_name LIKE :q3 '
. 'OR client_surname LIKE :q4 '
. 'OR client_phone LIKE :q5 '
. "OR CONCAT_WS(' ', TRIM(client_name), TRIM(client_surname)) LIKE :q6 "
. "OR CONCAT_WS(' ', TRIM(client_surname), TRIM(client_name)) LIKE :q7 "
. ') '
. 'ORDER BY id DESC '
. 'LIMIT 15',
[
':q1' => $like,
':q2' => $like,
':q3' => $like,
':q4' => $like,
':q5' => $like,
':q6' => $likeNormalized,
':q7' => $likeNormalized,
]
);
} catch (\Throwable $e) {
$orderStmt = false;
}
$orderRows = $orderStmt ? $orderStmt->fetchAll() : [];
if (is_array($orderRows)) {
foreach ($orderRows as $row) {
$orderId = (int)($row['id'] ?? 0);
if ($orderId <= 0) {
continue;
}
$orderNumber = trim((string)($row['number'] ?? ''));
$clientName = trim((string)($row['client_name'] ?? ''));
$clientSurname = trim((string)($row['client_surname'] ?? ''));
$clientEmail = trim((string)($row['client_email'] ?? ''));
$clientPhone = trim((string)($row['client_phone'] ?? ''));
$title = $orderNumber !== '' ? 'Zamówienie ' . $orderNumber : 'Zamówienie #' . $orderId;
$subtitleParts = [];
$fullName = trim($clientName . ' ' . $clientSurname);
if ($fullName !== '') {
$subtitleParts[] = $fullName;
}
if ($clientEmail !== '') {
$subtitleParts[] = $clientEmail;
}
if ($clientPhone !== '') {
$subtitleParts[] = $clientPhone;
}
$items[] = [
'type' => 'order',
'title' => $title,
'subtitle' => implode(' | ', $subtitleParts),
'url' => '/admin/shop_order/order_details/order_id=' . $orderId,
];
}
}
echo json_encode([
'status' => 'ok',
'items' => array_slice($items, 0, 20),
]);
exit;
}
/**
* Zapis ustawien (AJAX).
*/
public function save(): void
{
// Kompatybilnosc wsteczna dla legacy gridEdit (values jako JSON).
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode($legacyValues, true);
$result = $this->settingsRepository->saveSettings(is_array($values) ? $values : []);
\Shared\Helpers\Helpers::delete_dir('../temp/');
\Shared\Helpers\Helpers::htacces();
echo json_encode($result);
exit;
}
$languages = $this->languagesRepository->languagesList();
$settings = $this->settingsRepository->getSettings();
$viewModel = $this->buildFormViewModel($settings, $languages);
$result = $this->formHandler->handleSubmit($viewModel, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->getFormId()] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$values = $this->transformFormDataToSettings($result['data']);
$saveResult = $this->settingsRepository->saveSettings($values);
\Shared\Helpers\Helpers::delete_dir('../temp/');
\Shared\Helpers\Helpers::htacces();
echo json_encode([
'success' => ($saveResult['status'] ?? '') === 'ok',
'message' => $saveResult['msg'] ?? 'Ustawienia zostały zapisane.',
'errors' => (($saveResult['status'] ?? '') === 'ok') ? [] : ['general' => ($saveResult['msg'] ?? 'Błąd zapisu.')],
]);
exit;
}
/**
* Widok ustawien.
*/
public function view(): string
{
$languages = $this->languagesRepository->languagesList();
$settings = $this->settingsRepository->getSettings();
$validationErrors = $_SESSION['form_errors'][$this->getFormId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->getFormId()]);
}
$viewModel = $this->buildFormViewModel($settings, $languages, $validationErrors);
return \Shared\Tpl\Tpl::view('components/form-edit', ['form' => $viewModel]);
}
private function buildFormViewModel(array $settings, array $languages, ?array $errors = null): FormEditViewModel
{
$data = $this->transformSettingsToFormData($settings, $languages);
$tabs = [
new FormTab('contact', 'Dane kontaktowe', 'fa-paper-plane'),
new FormTab('shop', 'Sklep', 'fa-dollar'),
new FormTab('products', 'Produkty', 'fa-shopping-cart'),
new FormTab('mail', 'Poczta', 'fa-envelope'),
new FormTab('other', 'Pozostałe', 'fa-bars'),
new FormTab('system', 'System', 'fa-cog'),
new FormTab('conversions', 'Konwersje', 'fa-line-chart'),
];
$fields = [
FormField::text('firm_name', [
'label' => 'Nazwa firmy',
'tab' => 'contact',
]),
FormField::editor('additional_info', [
'label' => 'Dodatkowe informacje',
'tab' => 'contact',
'height' => 150,
]),
FormField::switch('google_maps', [
'label' => 'Mapa',
'tab' => 'contact',
]),
FormField::textarea('firm_adress', [
'label' => 'Mapa - adres',
'tab' => 'contact',
]),
FormField::editor('shop_bank_account_info', [
'label' => 'Dane do przelewu',
'tab' => 'shop',
'height' => 200,
]),
FormField::text('hotpay_api', [
'label' => 'Klucz API HotPay',
'tab' => 'shop',
]),
FormField::switch('tpay_sandbox', [
'label' => 'Tpay.com - tryb sandbox',
'tab' => 'shop',
]),
FormField::text('tpay_id', [
'label' => 'Tpay.com ID',
'tab' => 'shop',
]),
FormField::text('tpay_security_code', [
'label' => 'Tpay.com - kod bezpieczeństwa',
'tab' => 'shop',
]),
FormField::switch('przelewy24_sandbox', [
'label' => 'Przelewy24.pl - tryb sandbox',
'tab' => 'shop',
]),
FormField::text('przelewy24_merchant_id', [
'label' => 'Przelewy24.pl - merchant ID',
'tab' => 'shop',
]),
FormField::text('przelewy24_crc_key', [
'label' => 'Przelewy24.pl - klucz CRC',
'tab' => 'shop',
]),
FormField::text('free_delivery', [
'label' => 'Darmowa dostawa od',
'tab' => 'shop',
'attributes' => ['class' => 'number-format'],
]),
FormField::text('orlen_paczka_map_token', [
'label' => 'Orlen Paczka map token',
'tab' => 'shop',
]),
FormField::langSection('warehouse_messages', 'products', [
FormField::text('warehouse_message_zero', [
'label' => 'Komunikat gdy stan magazynowy równy 0',
]),
FormField::text('warehouse_message_nonzero', [
'label' => 'Komunikat gdy stan magazynowy większy niż 0',
]),
]),
FormField::switch('contact_form', [
'label' => 'Formularz kontaktowy',
'tab' => 'mail',
]),
FormField::text('contact_email', [
'label' => 'Email kontaktowy',
'tab' => 'mail',
]),
FormField::text('email_host', [
'label' => 'Email - host',
'tab' => 'mail',
]),
FormField::text('email_port', [
'label' => 'Email - port',
'tab' => 'mail',
]),
FormField::text('email_login', [
'label' => 'Email - login',
'tab' => 'mail',
]),
FormField::text('email_password', [
'label' => 'Email - hasło',
'tab' => 'mail',
]),
FormField::text('facebook_link', [
'label' => 'Facebook link',
'tab' => 'other',
]),
FormField::text('piksel', [
'label' => 'Piksel Facebook',
'tab' => 'other',
]),
FormField::textarea('statistic_code', [
'label' => 'Kod statystyk',
'tab' => 'other',
'rows' => 10,
]),
FormField::textarea('htaccess', [
'label' => 'Własne reguły htacess',
'tab' => 'other',
'rows' => 10,
]),
FormField::textarea('robots', [
'label' => 'Własne reguły robots.txt',
'tab' => 'other',
'rows' => 10,
]),
FormField::switch('update', [
'label' => 'Aktualizacja',
'tab' => 'system',
]),
FormField::text('update_key', [
'label' => 'Numer licencji',
'tab' => 'system',
]),
FormField::switch('devel', [
'label' => 'Strona konstrukcyjna',
'tab' => 'system',
]),
FormField::switch('lazy_loading', [
'label' => 'Lazy loading obrazów',
'tab' => 'system',
]),
FormField::switch('generate_webp', [
'label' => 'Generowanie obrazków WEBP',
'tab' => 'system',
]),
FormField::switch('infinitescroll', [
'label' => 'Infinitescroll',
'tab' => 'system',
]),
FormField::switch('htaccess_cache', [
'label' => 'Htaccess cache',
'tab' => 'system',
]),
FormField::text('api_key', [
'label' => 'Klucz API (ordersPRO)',
'tab' => 'system',
]),
FormField::text('google_tag_manager_id', [
'label' => 'Google Tag Manager - ID',
'tab' => 'conversions',
]),
FormField::textarea('own_gtm_js', [
'label' => 'Własny kod GTM JS (bez tagu script)',
'tab' => 'conversions',
'rows' => 10,
]),
FormField::textarea('own_gtm_html', [
'label' => 'Własny kod GTM HTML',
'tab' => 'conversions',
'rows' => 10,
]),
];
$actions = [
FormAction::save('/admin/settings/save/', ''),
];
return new FormEditViewModel(
$this->getFormId(),
'Edycja ustawień',
$data,
$fields,
$tabs,
$actions,
'POST',
'/admin/settings/save/',
null,
false,
[],
$languages,
$errors
);
}
private function getFormId(): string
{
return 'settings-edit';
}
private function transformSettingsToFormData(array $settings, array $languages): array
{
$data = $settings;
$data['languages'] = [];
foreach ($languages as $lang) {
if (!($lang['status'] ?? false)) {
continue;
}
$langId = (string)$lang['id'];
$data['languages'][$langId] = [
'warehouse_message_zero' => $settings['warehouse_message_zero_' . $langId] ?? '',
'warehouse_message_nonzero' => $settings['warehouse_message_nonzero_' . $langId] ?? '',
];
}
return $data;
}
private function transformFormDataToSettings(array $data): array
{
if (!isset($data['warehouse_messages']) || !is_array($data['warehouse_messages'])) {
return $data;
}
$data['warehouse_message_zero'] = [];
$data['warehouse_message_nonzero'] = [];
foreach ($data['warehouse_messages'] as $langId => $langValues) {
if (!is_array($langValues)) {
continue;
}
$data['warehouse_message_zero'][$langId] = $langValues['warehouse_message_zero'] ?? '';
$data['warehouse_message_nonzero'][$langId] = $langValues['warehouse_message_nonzero'] ?? '';
}
unset($data['warehouse_messages']);
return $data;
}
}

View File

@@ -0,0 +1,451 @@
<?php
namespace admin\Controllers;
use Domain\Attribute\AttributeRepository;
use Domain\Languages\LanguagesRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class ShopAttributeController
{
private AttributeRepository $repository;
private LanguagesRepository $languagesRepository;
public function __construct(
AttributeRepository $repository,
LanguagesRepository $languagesRepository
) {
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
}
public function list(): string
{
$sortableColumns = ['id', 'o', 'name', 'type', 'status', 'values_count'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'o'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$status = (int)($item['status'] ?? 0);
$type = (int)($item['type'] ?? 0);
$order = (int)($item['o'] ?? 0);
$valuesCount = (int)($item['values_count'] ?? 0);
$typeLabel = '-';
if ($type === 0) {
$typeLabel = 'tekst';
} elseif ($type === 1) {
$typeLabel = 'kolor';
} elseif ($type === 2) {
$typeLabel = 'wzor';
}
$rows[] = [
'lp' => $lp++ . '.',
'o' => $order,
'name' => '<a href="/admin/shop_attribute/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'type' => htmlspecialchars($typeLabel, ENT_QUOTES, 'UTF-8'),
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'values' => '<a href="/admin/shop_attribute/values/id=' . $id . '">edytuj wartosci</a>',
'values_count' => $valuesCount,
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/shop_attribute/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/shop_attribute/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrana ceche?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'o', 'sort_key' => 'o', 'label' => 'Kolejnosc', 'class' => 'text-center', 'sortable' => true],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'type', 'sort_key' => 'type', 'label' => 'Typ', 'class' => 'text-center', 'sortable' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'values_count', 'sort_key' => 'values_count', 'label' => 'Ilosc wartosci', 'class' => 'text-center', 'sortable' => true],
['key' => 'values', 'label' => 'Wartosci', 'class' => 'text-center', 'sortable' => false, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_attribute/list/',
'Brak danych w tabeli.',
'/admin/shop_attribute/edit/',
'Dodaj ceche'
);
return \Shared\Tpl\Tpl::view('shop-attribute/attributes-list', [
'viewModel' => $viewModel,
]);
}
public function edit(): string
{
$attribute = $this->repository->findAttribute((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$languages = $this->languagesRepository->languagesList();
return \Shared\Tpl\Tpl::view('shop-attribute/attribute-edit', [
'form' => $this->buildFormViewModel($attribute, $languages),
]);
}
public function save(): void
{
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania atrybutu wystapil blad. Prosze sprobowac ponownie.',
];
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
if (is_array($values)) {
$id = $this->repository->saveAttribute($values);
if (!empty($id)) {
$response = [
'status' => 'ok',
'msg' => 'Atrybut zostal zapisany.',
'id' => (int)$id,
];
}
}
echo json_encode($response);
exit;
}
$payload = $_POST;
if (empty($payload['id'])) {
$routeId = (int)\Shared\Helpers\Helpers::get('id');
if ($routeId > 0) {
$payload['id'] = $routeId;
}
}
$id = $this->repository->saveAttribute($payload);
if (!empty($id)) {
echo json_encode([
'success' => true,
'id' => (int)$id,
'message' => 'Atrybut zostal zapisany.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania atrybutu wystapil blad.'],
]);
exit;
}
public function delete(): void
{
if ($this->repository->deleteAttribute((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Atrybut zostal usuniety.');
}
header('Location: /admin/shop_attribute/list/');
exit;
}
public function values(): string
{
$attributeId = (int)\Shared\Helpers\Helpers::get('id');
if ($attributeId <= 0) {
\Shared\Helpers\Helpers::alert('Nieprawidlowy identyfikator cechy.');
header('Location: /admin/shop_attribute/list/');
exit;
}
$attribute = $this->repository->findAttribute($attributeId);
if ((int)($attribute['id'] ?? 0) <= 0) {
\Shared\Helpers\Helpers::alert('Wybrana cecha nie zostala znaleziona.');
header('Location: /admin/shop_attribute/list/');
exit;
}
$languages = $this->languagesRepository->languagesList();
return \Shared\Tpl\Tpl::view('shop-attribute/values-edit', [
'attribute' => $attribute,
'values' => $this->repository->findValues($attributeId),
'languages' => $languages,
'defaultLanguageId' => $this->languagesRepository->defaultLanguageId(),
]);
}
public function values_save(): void
{
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania wartosci atrybutu wystapil blad. Prosze sprobowac ponownie.',
];
$attributeId = (int)\Shared\Helpers\Helpers::get('attribute_id');
if ($attributeId <= 0) {
$attributeId = (int)\Shared\Helpers\Helpers::get('id');
}
$payloadRaw = \Shared\Helpers\Helpers::get('payload');
$payload = json_decode((string)$payloadRaw, true);
if (is_array($payload) && is_array($payload['rows'] ?? null) && $attributeId > 0) {
$validationErrors = $this->validateValuesRows(
$payload['rows'],
$this->languagesRepository->defaultLanguageId()
);
if (!empty($validationErrors)) {
echo json_encode([
'status' => 'error',
'msg' => $validationErrors[0],
'errors' => $validationErrors,
]);
exit;
}
$saved = $this->repository->saveValues($attributeId, ['rows' => $payload['rows']]);
if ($saved) {
$response = [
'status' => 'ok',
'msg' => 'Wartosci atrybutu zostaly zapisane.',
'id' => (int)$attributeId,
];
}
echo json_encode($response);
exit;
}
$valuesRaw = \Shared\Helpers\Helpers::get('values');
$values = json_decode((string)$valuesRaw, true);
if (is_array($values) && $attributeId > 0) {
$savedId = $this->repository->saveLegacyValues(
$attributeId,
is_array($values['name'] ?? null) ? $values['name'] : [],
is_array($values['value'] ?? null) ? $values['value'] : [],
is_array($values['ids'] ?? null) ? $values['ids'] : [],
$values['default_value'] ?? '',
is_array($values['impact_on_the_price'] ?? null) ? $values['impact_on_the_price'] : []
);
if (!empty($savedId)) {
$response = [
'status' => 'ok',
'msg' => 'Wartosci atrybutu zostaly zapisane.',
'id' => (int)$savedId,
];
}
}
echo json_encode($response);
exit;
}
public function value_row_tpl(): void
{
$rowKey = trim((string)\Shared\Helpers\Helpers::get('row_key'));
if ($rowKey === '') {
$rowKey = 'new-' . time();
}
$html = \Shared\Tpl\Tpl::view('shop-attribute/_partials/value-row', [
'rowKey' => $rowKey,
'value' => ['id' => 0, 'is_default' => 0, 'impact_on_the_price' => null, 'languages' => []],
'languages' => $this->languagesRepository->languagesList(),
'defaultLanguageId' => $this->languagesRepository->defaultLanguageId(),
]);
echo $html;
exit;
}
/**
* @param array<int, array<string, mixed>> $rows
* @return array<int, string>
*/
private function validateValuesRows(array $rows, string $defaultLanguageId): array
{
$errors = [];
if (empty($rows)) {
return ['Dodaj co najmniej jedna wartosc cechy.'];
}
$defaultCount = 0;
foreach ($rows as $index => $row) {
$rowNumber = $index + 1;
if (!is_array($row)) {
$errors[] = 'Nieprawidlowe dane wiersza nr ' . $rowNumber . '.';
continue;
}
if (!empty($row['is_default'])) {
++$defaultCount;
}
$translations = is_array($row['translations'] ?? null) ? $row['translations'] : [];
$defaultLangData = is_array($translations[$defaultLanguageId] ?? null)
? $translations[$defaultLanguageId]
: [];
$defaultName = trim((string)($defaultLangData['name'] ?? ''));
if ($defaultName === '') {
$errors[] = 'Wiersz nr ' . $rowNumber . ': nazwa w jezyku domyslnym jest wymagana.';
}
$impact = trim((string)($row['impact_on_the_price'] ?? ''));
if ($impact !== '' && !preg_match('/^-?[0-9]+([.,][0-9]{1,4})?$/', $impact)) {
$errors[] = 'Wiersz nr ' . $rowNumber . ': nieprawidlowy format "wplyw na cene".';
}
}
if ($defaultCount !== 1) {
$errors[] = 'Wybierz dokladnie jedna wartosc domyslna.';
}
return $errors;
}
private function buildFormViewModel(array $attribute, array $languages): FormEditViewModel
{
$id = (int)($attribute['id'] ?? 0);
$isNew = $id <= 0;
$data = [
'id' => $id,
'status' => (int)($attribute['status'] ?? 1),
'type' => (int)($attribute['type'] ?? 0),
'o' => (int)($attribute['o'] ?? 0),
'languages' => [],
];
if (is_array($attribute['languages'] ?? null)) {
foreach ($attribute['languages'] as $langId => $translation) {
$data['languages'][(string)$langId] = [
'name' => (string)($translation['name'] ?? ''),
];
}
}
$fields = [
FormField::hidden('id', $id),
FormField::langSection('attribute_content', 'content', [
FormField::text('name', [
'label' => 'Tytul',
]),
]),
FormField::switch('status', [
'label' => 'Aktywny',
'tab' => 'settings',
'value' => true,
]),
FormField::select('type', [
'label' => 'Typ',
'tab' => 'settings',
'options' => [
0 => 'tekst',
1 => 'kolor',
2 => 'wzor',
],
]),
FormField::number('o', [
'label' => 'Kolejnosc',
'tab' => 'settings',
]),
];
$tabs = [
new FormTab('content', 'Tresc', 'fa-file'),
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
];
$actionUrl = '/admin/shop_attribute/save/' . ($isNew ? '' : ('id=' . $id));
$actions = [
FormAction::save($actionUrl, '/admin/shop_attribute/list/'),
FormAction::cancel('/admin/shop_attribute/list/'),
];
return new FormEditViewModel(
'shop-attribute-edit',
$isNew ? 'Nowa cecha' : 'Edycja cechy',
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/shop_attribute/list/',
true,
['id' => $id],
$languages
);
}
}

View File

@@ -0,0 +1,164 @@
<?php
namespace admin\Controllers;
use Domain\Category\CategoryRepository;
use Domain\Languages\LanguagesRepository;
class ShopCategoryController
{
private CategoryRepository $repository;
private LanguagesRepository $languagesRepository;
public function __construct(CategoryRepository $repository, LanguagesRepository $languagesRepository)
{
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
}
public function view_list(): string
{
return \Shared\Tpl\Tpl::view('shop-category/categories-list', [
'categories' => $this->repository->subcategories(null),
'level' => 0,
'dlang' => $this->languagesRepository->defaultLanguage(),
]);
}
public function list(): string
{
return $this->view_list();
}
public function category_edit(): string
{
return \Shared\Tpl\Tpl::view('shop-category/category-edit', [
'category' => $this->repository->categoryDetails(\Shared\Helpers\Helpers::get('id')),
'pid' => \Shared\Helpers\Helpers::get('pid'),
'languages' => $this->languagesRepository->languagesList(),
'sort_types' => $this->repository->sortTypes(),
'dlang' => $this->languagesRepository->defaultLanguage(),
]);
}
public function edit(): string
{
return $this->category_edit();
}
public function save(): void
{
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania kategorii wystąpił błąd. Proszę spróbować ponownie.',
];
$values = json_decode((string)\Shared\Helpers\Helpers::get('values'), true);
if (is_array($values)) {
$savedId = $this->repository->save($values);
if (!empty($savedId)) {
$response = [
'status' => 'ok',
'msg' => 'Kategoria została zapisana.',
'id' => (int)$savedId,
];
}
}
echo json_encode($response);
exit;
}
public function category_delete(): void
{
if ($this->repository->categoryDelete(\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::set_message('Kategoria została usunięta.');
} else {
\Shared\Helpers\Helpers::alert('Podczas usuwania kategorii wystąpił błąd. Aby usunąć kategorię nie może ona posiadać przypiętych podkategorii.');
}
header('Location: /admin/shop_category/view_list/');
exit;
}
public function delete(): void
{
$this->category_delete();
}
public function category_products(): string
{
return \Shared\Tpl\Tpl::view('shop-category/category-products', [
'category_id' => \Shared\Helpers\Helpers::get('id'),
'products' => $this->repository->categoryProducts((int)\Shared\Helpers\Helpers::get('id')),
]);
}
public function products(): string
{
return $this->category_products();
}
public function category_url_browser(): void
{
echo \Shared\Tpl\Tpl::view('shop-category/category-browse-list', [
'categories' => $this->repository->subcategories(null),
'level' => 0,
'dlang' => $this->languagesRepository->defaultLanguage(),
]);
exit;
}
public function save_categories_order(): void
{
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania kolejności kategorii wystąpił błąd. Proszę spróbować ponownie.',
];
if ( $this->repository->saveCategoriesOrder( \Shared\Helpers\Helpers::get( 'categories' ) ) ) {
$response = [ 'status' => 'ok' ];
}
echo json_encode( $response );
exit;
}
public function save_products_order(): void
{
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania kolejności wyświetlania produktów wystąpił błąd. Proszę spróbować ponownie.',
];
if ( $this->repository->saveProductOrder( \Shared\Helpers\Helpers::get( 'category_id' ), \Shared\Helpers\Helpers::get( 'products' ) ) ) {
$response = [ 'status' => 'ok' ];
}
echo json_encode( $response );
exit;
}
public function cookie_categories(): void
{
$categoryId = (string) \Shared\Helpers\Helpers::get( 'category_id' );
if ( $categoryId === '' ) {
echo json_encode( [ 'status' => 'error' ] );
exit;
}
$array = [];
if ( isset( $_COOKIE['cookie_categories'] ) ) {
$tmp = @unserialize( (string) $_COOKIE['cookie_categories'] );
if ( is_array( $tmp ) ) {
$array = $tmp;
}
}
$array[$categoryId] = isset( $array[$categoryId] ) && (int) $array[$categoryId] === 1 ? 0 : 1;
setcookie( 'cookie_categories', serialize( $array ), time() + 3600 * 24 * 365, '/' );
echo json_encode( [ 'status' => 'ok' ] );
exit;
}
}

View File

@@ -0,0 +1,222 @@
<?php
namespace admin\Controllers;
use Domain\Client\ClientRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
class ShopClientsController
{
private ClientRepository $repository;
public function __construct(ClientRepository $repository)
{
$this->repository = $repository;
}
public function list(): string
{
$sortableColumns = [
'client_name',
'client_surname',
'client_email',
'client_phone',
'client_city',
'total_orders',
'total_spent',
'client_type',
];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Imie',
'type' => 'text',
],
[
'key' => 'surname',
'label' => 'Nazwisko',
'type' => 'text',
],
[
'key' => 'email',
'label' => 'E-mail',
'type' => 'text',
],
[
'key' => 'client_type',
'label' => 'Typ klienta',
'type' => 'select',
'options' => [
'' => '- typ klienta -',
'registered' => 'Zarejestrowany',
'guest' => 'Gosc',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'client_surname'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$name = trim((string)($item['client_name'] ?? ''));
$surname = trim((string)($item['client_surname'] ?? ''));
$email = trim((string)($item['client_email'] ?? ''));
$params = [
'name' => $name,
'surname' => $surname,
'email' => $email,
];
$detailsUrl = '/admin/shop_clients/details/?' . http_build_query($params);
$rows[] = [
'lp' => $lp++ . '.',
'client_type' => ((int)($item['is_registered'] ?? 0) === 1) ? 'Zarejestrowany' : 'Gosc',
'full_name' => htmlspecialchars($surname, ENT_QUOTES, 'UTF-8') . ' ' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8'),
'client_email' => $email,
'client_phone' => (string)($item['client_phone'] ?? ''),
'client_city' => (string)($item['client_city'] ?? ''),
'total_spent' => number_format((float)($item['total_spent'] ?? 0), 2, '.', ' ') . ' zl',
'total_orders' => '<a href="' . htmlspecialchars($detailsUrl, ENT_QUOTES, 'UTF-8') . '">' . (int)($item['total_orders'] ?? 0) . '</a>',
'_actions' => [
[
'label' => 'Zobacz zamowienia',
'url' => $detailsUrl,
'class' => 'btn btn-xs btn-primary',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'client_type', 'sort_key' => 'client_type', 'label' => 'Typ klienta', 'class' => 'text-center', 'sortable' => true],
['key' => 'full_name', 'label' => 'Nazwisko, imie', 'sortable' => false, 'raw' => true],
['key' => 'client_email', 'sort_key' => 'client_email', 'label' => 'Email', 'sortable' => true],
['key' => 'client_phone', 'sort_key' => 'client_phone', 'label' => 'Telefon', 'sortable' => true],
['key' => 'client_city', 'sort_key' => 'client_city', 'label' => 'Miasto', 'sortable' => true],
['key' => 'total_spent', 'sort_key' => 'total_spent', 'label' => 'Wartosc zamowien', 'class' => 'text-right', 'sortable' => true],
['key' => 'total_orders', 'sort_key' => 'total_orders', 'label' => 'Ilosc zamowien', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_clients/list/',
'Brak danych w tabeli.'
);
return \Shared\Tpl\Tpl::view('shop-clients/view-list', [
'viewModel' => $viewModel,
]);
}
public function view_list(): string
{
return $this->list();
}
public function details(): string
{
$name = (string)\Shared\Helpers\Helpers::get('name');
$surname = (string)\Shared\Helpers\Helpers::get('surname');
$email = (string)\Shared\Helpers\Helpers::get('email');
$ordersInfo = $this->repository->ordersForClient($name, $surname, $email);
$totals = $this->repository->totalsForClient($name, $surname, $email);
$rows = [];
$lp = 1;
foreach ($ordersInfo as $order) {
$rows[] = [
'lp' => $lp++ . '.',
'date_order' => (string)($order['date_order'] ?? ''),
'summary' => number_format((float)($order['summary'] ?? 0), 2, '.', ' ') . ' zl',
'payment_method' => (string)($order['payment_method'] ?? ''),
'transport' => (string)($order['transport'] ?? ''),
'message' => (string)($order['message'] ?? ''),
'_actions' => [],
];
}
$ordersTable = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'date_order', 'label' => 'Data zamowienia', 'class' => 'text-center', 'sortable' => false],
['key' => 'summary', 'label' => 'Wartosc', 'class' => 'text-right', 'sortable' => false],
['key' => 'payment_method', 'label' => 'Typ platnosci', 'sortable' => false],
['key' => 'transport', 'label' => 'Rodzaj transportu', 'sortable' => false],
['key' => 'message', 'label' => 'Wiadomosc', 'sortable' => false],
],
$rows,
[],
[],
[
'page' => 1,
'per_page' => max(1, count($rows)),
'total' => count($rows),
'total_pages' => 1,
],
[],
[count($rows) > 0 ? count($rows) : 1],
[],
'/admin/shop_clients/details/?' . http_build_query([
'name' => $name,
'surname' => $surname,
'email' => $email,
]),
'Brak zamowien klienta.'
);
return \Shared\Tpl\Tpl::view('shop-clients/clients-details', [
'name' => $name,
'surname' => $surname,
'email' => $email,
'total_spent' => $totals['total_spent'],
'ordersTable' => $ordersTable,
'total_orders' => $totals['total_orders'],
]);
}
public function clients_details(): string
{
return $this->details();
}
}

View File

@@ -0,0 +1,353 @@
<?php
namespace admin\Controllers;
use Domain\Coupon\CouponRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class ShopCouponController
{
private CouponRepository $repository;
public function __construct(CouponRepository $repository)
{
$this->repository = $repository;
}
public function list(): string
{
$sortableColumns = ['id', 'status', 'used_count', 'name', 'type', 'amount', 'one_time', 'send', 'used', 'date_used'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
[
'key' => 'used',
'label' => 'Uzyty',
'type' => 'select',
'options' => [
'' => '- uzyty -',
'1' => 'tak',
'0' => 'nie',
],
],
[
'key' => 'send',
'label' => 'Wyslany',
'type' => 'select',
'options' => [
'' => '- wyslany -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'name'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$status = (int)($item['status'] ?? 0);
$used = (int)($item['used'] ?? 0);
$send = (int)($item['send'] ?? 0);
$oneTime = (int)($item['one_time'] ?? 0);
$type = (int)($item['type'] ?? 0);
$amount = (string)($item['amount'] ?? '');
$dateUsed = trim((string)($item['date_used'] ?? ''));
$rows[] = [
'lp' => $lp++ . '.',
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'used_count' => (int)($item['used_count'] ?? 0),
'name' => '<a href="/admin/shop_coupon/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'type' => htmlspecialchars((string)($type === 1 ? 'Rabat procentowy na koszyk' : '-'), ENT_QUOTES, 'UTF-8'),
'amount' => $type === 1 && $amount !== '' ? htmlspecialchars($amount, ENT_QUOTES, 'UTF-8') . '%' : '-',
'one_time' => $oneTime === 1 ? 'tak' : 'nie',
'send' => $send === 1 ? 'tak' : 'nie',
'used' => $used === 1 ? 'tak' : 'nie',
'date_used' => $dateUsed !== '' ? htmlspecialchars($dateUsed, ENT_QUOTES, 'UTF-8') : '-',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/shop_coupon/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/shop_coupon/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrany kupon?',
'confirm_ok' => 'Usun',
'confirm_cancel' => 'Anuluj',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'used_count', 'sort_key' => 'used_count', 'label' => 'Uzyto X razy', 'class' => 'text-center', 'sortable' => true],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'type', 'sort_key' => 'type', 'label' => 'Typ kuponu', 'sortable' => true],
['key' => 'amount', 'sort_key' => 'amount', 'label' => 'Wartosc', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'one_time', 'sort_key' => 'one_time', 'label' => 'Kupon jednorazowy', 'class' => 'text-center', 'sortable' => true],
['key' => 'send', 'sort_key' => 'send', 'label' => 'Wyslany', 'class' => 'text-center', 'sortable' => true],
['key' => 'used', 'sort_key' => 'used', 'label' => 'Uzyty', 'class' => 'text-center', 'sortable' => true],
['key' => 'date_used', 'sort_key' => 'date_used', 'label' => 'Data uzycia', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_coupon/list/',
'Brak danych w tabeli.',
'/admin/shop_coupon/edit/',
'Dodaj kupon'
);
return \Shared\Tpl\Tpl::view('shop-coupon/coupons-list', [
'viewModel' => $viewModel,
]);
}
public function view_list(): string
{
return $this->list();
}
public function edit(): string
{
$coupon = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$categories = $this->repository->categoriesTree(null);
return \Shared\Tpl\Tpl::view('shop-coupon/coupon-edit-new', [
'form' => $this->buildFormViewModel($coupon, $categories),
]);
}
public function coupon_edit(): string
{
return $this->edit();
}
public function save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania kuponu wystapil blad. Prosze sprobowac ponownie.',
];
if (is_array($values)) {
$id = $this->repository->save($values);
if (!empty($id)) {
$response = [
'status' => 'ok',
'msg' => 'Kupon zostal zapisany.',
'id' => (int)$id,
];
}
}
echo json_encode($response);
exit;
}
$payload = $_POST;
if (empty($payload['id'])) {
$routeId = (int)\Shared\Helpers\Helpers::get('id');
if ($routeId > 0) {
$payload['id'] = $routeId;
}
}
$id = $this->repository->save($payload);
if (!empty($id)) {
echo json_encode([
'success' => true,
'id' => (int)$id,
'message' => 'Kupon zostal zapisany.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania kuponu wystapil blad.'],
]);
exit;
}
public function coupon_save(): void
{
$this->save();
}
public function delete(): void
{
if ($this->repository->delete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Kupon zostal usuniety.');
}
header('Location: /admin/shop_coupon/list/');
exit;
}
public function coupon_delete(): void
{
$this->delete();
}
private function buildFormViewModel(array $coupon, array $categories): FormEditViewModel
{
$id = (int)($coupon['id'] ?? 0);
$isNew = $id <= 0;
$data = [
'id' => $id,
'name' => (string)($coupon['name'] ?? ''),
'send' => (int)($coupon['send'] ?? 0),
'status' => (int)($coupon['status'] ?? 1),
'used' => (int)($coupon['used'] ?? 0),
'type' => (int)($coupon['type'] ?? 1),
'amount' => (string)($coupon['amount'] ?? ''),
'one_time' => (int)($coupon['one_time'] ?? 1),
'include_discounted_product' => (int)($coupon['include_discounted_product'] ?? 0),
];
$fields = [
FormField::hidden('id', $id),
FormField::text('name', [
'label' => 'Nazwa',
'tab' => 'settings',
'required' => true,
]),
FormField::switch('send', [
'label' => 'Wyslany',
'tab' => 'settings',
]),
FormField::switch('status', [
'label' => 'Aktywny',
'tab' => 'settings',
'value' => true,
]),
FormField::switch('used', [
'label' => 'Uzyty',
'tab' => 'settings',
]),
FormField::select('type', [
'label' => 'Typ kuponu',
'tab' => 'settings',
'options' => [
1 => 'Rabat procentowy na koszyk',
],
'required' => true,
]),
FormField::text('amount', [
'label' => 'Wartosc',
'tab' => 'settings',
'attributes' => ['class' => 'number-format'],
]),
FormField::switch('one_time', [
'label' => 'Kupon jednorazowy',
'tab' => 'settings',
'value' => true,
]),
FormField::switch('include_discounted_product', [
'label' => 'Dotyczy rowniez produktow przecenionych',
'tab' => 'settings',
]),
FormField::custom('coupon_categories', \Shared\Tpl\Tpl::view('shop-coupon/coupon-categories-selector', [
'label' => 'Ogranicz promocje do wybranych kategorii',
'inputName' => 'categories[]',
'categories' => $categories,
'selectedIds' => is_array($coupon['categories'] ?? null) ? $coupon['categories'] : [],
]), [
'tab' => 'categories',
]),
];
$tabs = [
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
new FormTab('categories', 'Kategorie', 'fa-folder-open'),
];
$actionUrl = '/admin/shop_coupon/save/' . ($isNew ? '' : ('id=' . $id));
$actions = [
FormAction::save($actionUrl, '/admin/shop_coupon/list/'),
FormAction::cancel('/admin/shop_coupon/list/'),
];
return new FormEditViewModel(
'shop-coupon-edit',
$isNew ? 'Nowy kupon' : ('Edycja kuponu: ' . (string)($coupon['name'] ?? '')),
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/shop_coupon/list/',
true,
['id' => $id]
);
}
}

View File

@@ -0,0 +1,364 @@
<?php
namespace admin\Controllers;
use Domain\Order\OrderAdminService;
use Domain\Product\ProductRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
class ShopOrderController
{
private OrderAdminService $service;
private $productRepo;
public function __construct(OrderAdminService $service, ProductRepository $productRepo = null)
{
$this->service = $service;
$this->productRepo = $productRepo;
}
public function list(): string
{
return $this->view_list();
}
public function view_list(): string
{
$sortableColumns = [
'number',
'date_order',
'status',
'summary',
'client',
'order_email',
'client_phone',
'transport',
'payment_method',
'total_orders',
'paid',
];
$statusOptions = ['' => '- status -'];
foreach ($this->service->statuses() as $statusId => $statusName) {
$statusOptions[(string)$statusId] = (string)$statusName;
}
$filterDefinitions = [
['key' => 'number', 'label' => 'Nr zamówienia', 'type' => 'text'],
['key' => 'date_from', 'label' => 'Data od', 'type' => 'date'],
['key' => 'date_to', 'label' => 'Data do', 'type' => 'date'],
['key' => 'status', 'label' => 'Status', 'type' => 'select', 'options' => $statusOptions],
['key' => 'client', 'label' => 'Klient', 'type' => 'text'],
['key' => 'address', 'label' => 'Adres', 'type' => 'text'],
['key' => 'order_email', 'label' => 'Email', 'type' => 'text'],
['key' => 'client_phone', 'label' => 'Telefon', 'type' => 'text'],
['key' => 'transport', 'label' => 'Dostawa', 'type' => 'text'],
['key' => 'payment_method', 'label' => 'Płatność', 'type' => 'text'],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'date_order'
);
$result = $this->service->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$listRequest['sortDir'],
$listRequest['page'],
$listRequest['perPage']
);
$statusesMap = $this->service->statuses();
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$orderId = (int)($item['id'] ?? 0);
$orderNumber = (string)($item['number'] ?? '');
$statusId = (int)($item['status'] ?? 0);
$statusLabel = (string)($statusesMap[$statusId] ?? ('Status #' . $statusId));
$rows[] = [
'lp' => $lp++ . '.',
'date_order' => $this->formatDateTime((string)($item['date_order'] ?? '')),
'number' => '<a href="/admin/shop_order/order_details/order_id=' . $orderId . '">' . htmlspecialchars($orderNumber, ENT_QUOTES, 'UTF-8') . '</a>',
'paid' => ((int)($item['paid'] ?? 0) === 1)
? '<i class="fa fa-check text-success"></i>'
: '<i class="fa fa-times text-dark"></i>',
'status' => htmlspecialchars($statusLabel, ENT_QUOTES, 'UTF-8'),
'summary' => number_format((float)($item['summary'] ?? 0), 2, '.', ' ') . ' zł',
'client' => htmlspecialchars((string)($item['client'] ?? ''), ENT_QUOTES, 'UTF-8') . ' | zamówienia: <strong>' . (int)($item['total_orders'] ?? 0) . '</strong>',
'address' => (string)($item['address'] ?? ''),
'order_email' => (string)($item['order_email'] ?? ''),
'client_phone' => (string)($item['client_phone'] ?? ''),
'transport' => (string)($item['transport'] ?? ''),
'payment_method' => (string)($item['payment_method'] ?? ''),
'_actions' => [
[
'label' => 'Szczegóły',
'url' => '/admin/shop_order/order_details/order_id=' . $orderId,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usuń',
'url' => '/admin/shop_order/order_delete/id=' . $orderId,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunąć wybrane zamówienie?',
'confirm_ok' => 'Usuń',
'confirm_cancel' => 'Anuluj',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'date_order', 'sort_key' => 'date_order', 'label' => 'Data dodania', 'class' => 'text-center', 'sortable' => true],
['key' => 'number', 'sort_key' => 'number', 'label' => 'Nr zamówienia', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'paid', 'sort_key' => 'paid', 'label' => '', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Status', 'sortable' => true, 'raw' => true],
['key' => 'summary', 'sort_key' => 'summary', 'label' => 'Wartość', 'class' => 'text-right align-middle', 'sortable' => true],
['key' => 'client', 'sort_key' => 'client', 'label' => 'Klient', 'sortable' => true, 'raw' => true],
['key' => 'address', 'label' => 'Adres', 'sortable' => false],
['key' => 'order_email', 'sort_key' => 'order_email', 'label' => 'Email', 'sortable' => true],
['key' => 'client_phone', 'sort_key' => 'client_phone', 'label' => 'Telefon', 'sortable' => true],
['key' => 'transport', 'sort_key' => 'transport', 'label' => 'Dostawa', 'sortable' => true],
['key' => 'payment_method', 'sort_key' => 'payment_method', 'label' => 'Płatność', 'sortable' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $listRequest['sortDir'],
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $listRequest['sortDir'],
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_order/list/',
'Brak danych w tabeli.'
);
return \Shared\Tpl\Tpl::view('shop-order/orders-list', [
'viewModel' => $viewModel,
]);
}
public function details(): string
{
return $this->order_details();
}
public function order_details(): string
{
$orderId = (int)\Shared\Helpers\Helpers::get('order_id');
$order = $this->service->details($orderId);
$coupon = null;
if (!empty($order) && !empty($order['coupon_id'])) {
$coupon = ( new \Domain\Coupon\CouponRepository( $GLOBALS['mdb'] ) )->find((int)$order['coupon_id']);
}
return \Shared\Tpl\Tpl::view('shop-order/order-details', [
'order' => $order,
'coupon' => $coupon,
'order_statuses' => $this->service->statuses(),
'next_order_id' => $this->service->nextOrderId($orderId),
'prev_order_id' => $this->service->prevOrderId($orderId),
]);
}
public function edit(): string
{
return $this->order_edit();
}
public function order_edit(): string
{
$orderId = (int)\Shared\Helpers\Helpers::get('order_id');
$transports = ( new \Domain\Transport\TransportRepository( $GLOBALS['mdb'] ) )->allActive();
// Dane transportów do JS (id, cost, delivery_free)
$transportsJson = [];
if (is_array($transports)) {
foreach ($transports as $t) {
$transportsJson[] = [
'id' => (int)$t['id'],
'cost' => (float)$t['cost'],
'delivery_free' => (int)($t['delivery_free'] ?? 0),
];
}
}
return \Shared\Tpl\Tpl::view('shop-order/order-edit', [
'order' => $this->service->details($orderId),
'order_statuses' => $this->service->statuses(),
'transport' => $transports,
'payment_methods' => ( new \Domain\PaymentMethod\PaymentMethodRepository( $GLOBALS['mdb'] ) )->allActive(),
'free_delivery' => $this->service->getFreeDeliveryThreshold(),
'transports_json' => json_encode($transportsJson),
]);
}
public function save(): void
{
$this->order_save();
}
public function order_save(): void
{
$orderId = (int)\Shared\Helpers\Helpers::get('order_id');
// Zapisz produkty PRZED zapisem zamówienia (bo saveOrderByAdmin przelicza summary)
$productsData = \Shared\Helpers\Helpers::get('products');
if (is_array($productsData)) {
$this->service->saveOrderProducts($orderId, $productsData);
}
$saved = $this->service->saveOrderByAdmin([
'order_id' => $orderId,
'client_name' => (string)\Shared\Helpers\Helpers::get('client_name'),
'client_surname' => (string)\Shared\Helpers\Helpers::get('client_surname'),
'client_street' => (string)\Shared\Helpers\Helpers::get('client_street'),
'client_postal_code' => (string)\Shared\Helpers\Helpers::get('client_postal_code'),
'client_city' => (string)\Shared\Helpers\Helpers::get('client_city'),
'client_email' => (string)\Shared\Helpers\Helpers::get('client_email'),
'firm_name' => (string)\Shared\Helpers\Helpers::get('firm_name'),
'firm_street' => (string)\Shared\Helpers\Helpers::get('firm_street'),
'firm_postal_code' => (string)\Shared\Helpers\Helpers::get('firm_postal_code'),
'firm_city' => (string)\Shared\Helpers\Helpers::get('firm_city'),
'firm_nip' => (string)\Shared\Helpers\Helpers::get('firm_nip'),
'transport_id' => (int)\Shared\Helpers\Helpers::get('transport_id'),
'inpost_paczkomat' => (string)\Shared\Helpers\Helpers::get('inpost_paczkomat'),
'payment_method_id' => (int)\Shared\Helpers\Helpers::get('payment_method_id'),
]);
if ($saved) {
\Shared\Helpers\Helpers::alert('Zamówienie zostało zapisane.');
}
header('Location: /admin/shop_order/order_details/order_id=' . $orderId);
exit;
}
public function search_products_ajax(): void
{
$query = trim((string)\Shared\Helpers\Helpers::get('query'));
$langId = trim((string)\Shared\Helpers\Helpers::get('lang_id'));
if ($langId === '') {
$langId = isset($_SESSION['lang_id']) ? (string)$_SESSION['lang_id'] : 'pl';
}
$results = $this->service->searchProducts($query, $langId);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['status' => 'ok', 'products' => $results]);
exit;
}
public function notes_save(): void
{
$this->service->saveNotes((int)\Shared\Helpers\Helpers::get('order_id'), (string)\Shared\Helpers\Helpers::get('notes'));
}
public function order_status_change(): void
{
$response = $this->service->changeStatus(
(int)\Shared\Helpers\Helpers::get('order_id'),
(int)\Shared\Helpers\Helpers::get('status'),
(string)\Shared\Helpers\Helpers::get('email') === 'true'
);
echo json_encode($response);
exit;
}
public function order_resend_confirmation_email(): void
{
$response = $this->service->resendConfirmationEmail((int)\Shared\Helpers\Helpers::get('order_id'));
echo json_encode(['result' => $response]);
exit;
}
public function set_order_as_unpaid(): void
{
$orderId = (int)\Shared\Helpers\Helpers::get('order_id');
$this->service->setOrderAsUnpaid($orderId);
header('Location: /admin/shop_order/order_details/order_id=' . $orderId);
exit;
}
public function set_order_as_paid(): void
{
$orderId = (int)\Shared\Helpers\Helpers::get('order_id');
$this->service->setOrderAsPaid($orderId, (int)\Shared\Helpers\Helpers::get('send_mail') === 1);
header('Location: /admin/shop_order/order_details/order_id=' . $orderId);
exit;
}
public function send_order_to_apilo(): void
{
$orderId = (int)\Shared\Helpers\Helpers::get('order_id');
if ($this->service->sendOrderToApilo($orderId)) {
\Shared\Helpers\Helpers::alert('Zamówienie zostanie wysłane ponownie do apilo.com');
} else {
\Shared\Helpers\Helpers::alert('Wystąpił błąd podczas wysyłania zamówienia do apilo.com');
}
header('Location: /admin/shop_order/order_details/order_id=' . $orderId);
exit;
}
public function toggle_trustmate_send(): void
{
echo json_encode($this->service->toggleTrustmateSend((int)\Shared\Helpers\Helpers::get('order_id')));
exit;
}
public function delete(): void
{
$this->order_delete();
}
public function order_delete(): void
{
if ($this->service->deleteOrder((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Zamówienie zostało usunięte');
}
header('Location: /admin/shop_order/list/');
exit;
}
private function formatDateTime(string $value): string
{
if ($value === '') {
return '';
}
$ts = strtotime($value);
if ($ts === false) {
return $value;
}
return date('Y-m-d H:i', $ts);
}
}

View File

@@ -0,0 +1,294 @@
<?php
namespace admin\Controllers;
use Domain\PaymentMethod\PaymentMethodRepository;
use Domain\Integrations\IntegrationsRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class ShopPaymentMethodController
{
private PaymentMethodRepository $repository;
public function __construct(PaymentMethodRepository $repository)
{
$this->repository = $repository;
}
public function list(): string
{
$sortableColumns = ['id', 'name', 'status', 'apilo_payment_type_id'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'id'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$apiloPaymentTypes = $this->getApiloPaymentTypes();
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$status = (int)($item['status'] ?? 0);
$apiloPaymentTypeId = $item['apilo_payment_type_id'] ?? null;
$apiloLabel = '-';
if ($apiloPaymentTypeId !== null) {
$apiloKey = (string)$apiloPaymentTypeId;
if (isset($apiloPaymentTypes[$apiloKey])) {
$apiloLabel = $apiloPaymentTypes[$apiloKey];
}
}
$rows[] = [
'lp' => $lp++ . '.',
'name' => '<a href="/admin/shop_payment_method/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'apilo_payment_type' => htmlspecialchars((string)$apiloLabel, ENT_QUOTES, 'UTF-8'),
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/shop_payment_method/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'apilo_payment_type', 'sort_key' => 'apilo_payment_type_id', 'label' => 'Typ platnosci Apilo', 'class' => 'text-center', 'sortable' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_payment_method/list/',
'Brak danych w tabeli.'
);
return \Shared\Tpl\Tpl::view('shop-payment-method/payment-methods-list', [
'viewModel' => $viewModel,
]);
}
public function edit(): string
{
$paymentMethod = $this->repository->find((int)\Shared\Helpers\Helpers::get('id'));
if ($paymentMethod === null) {
\Shared\Helpers\Helpers::alert('Metoda platnosci nie zostala znaleziona.');
header('Location: /admin/shop_payment_method/list/');
exit;
}
return \Shared\Tpl\Tpl::view('shop-payment-method/payment-method-edit', [
'form' => $this->buildFormViewModel($paymentMethod, $this->getApiloPaymentTypes()),
]);
}
public function save(): void
{
$payload = $_POST;
$paymentMethodId = isset($payload['id']) && $payload['id'] !== ''
? (int)$payload['id']
: (int)\Shared\Helpers\Helpers::get('id');
$id = $this->repository->save($paymentMethodId, $payload);
if ($id !== null) {
echo json_encode([
'success' => true,
'id' => (int)$id,
'message' => 'Metoda platnosci zostala zapisana.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania metody platnosci wystapil blad.'],
]);
exit;
}
private function buildFormViewModel(array $paymentMethod, array $apiloPaymentTypes): FormEditViewModel
{
$id = (int)($paymentMethod['id'] ?? 0);
$name = (string)($paymentMethod['name'] ?? '');
$apiloOptions = ['' => '--- wybierz typ platnosci apilo.com ---'];
foreach ($apiloPaymentTypes as $apiloId => $apiloName) {
$apiloOptions[(string)$apiloId] = $apiloName;
}
$data = [
'id' => $id,
'description' => (string)($paymentMethod['description'] ?? ''),
'status' => (int)($paymentMethod['status'] ?? 0),
'apilo_payment_type_id' => $paymentMethod['apilo_payment_type_id'] ?? '',
];
$fields = [
FormField::hidden('id', $id),
FormField::custom(
'name_preview',
\Shared\Html\Html::input([
'label' => 'Nazwa',
'name' => 'name_preview',
'id' => 'name_preview',
'value' => $name,
'type' => 'text',
'readonly' => true,
]),
['tab' => 'settings']
),
FormField::textarea('description', [
'label' => 'Opis',
'tab' => 'settings',
'rows' => 5,
]),
FormField::select('apilo_payment_type_id', [
'label' => 'Typ platnosci Apilo',
'tab' => 'settings',
'options' => $apiloOptions,
]),
FormField::switch('status', [
'label' => 'Aktywny',
'tab' => 'settings',
]),
];
$tabs = [
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
];
$actionUrl = '/admin/shop_payment_method/save/id=' . $id;
$actions = [
FormAction::save($actionUrl, '/admin/shop_payment_method/list/'),
FormAction::cancel('/admin/shop_payment_method/list/'),
];
return new FormEditViewModel(
'shop-payment-method-edit',
'Edycja metody platnosci: ' . $name,
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/shop_payment_method/list/',
true,
['id' => $id]
);
}
private function getApiloPaymentTypes(): array
{
global $mdb;
$integrationsRepository = new IntegrationsRepository( $mdb );
$rawSetting = $integrationsRepository -> getSetting( 'apilo', 'payment-types-list' );
$raw = null;
if (is_array($rawSetting)) {
$raw = $rawSetting;
} elseif (is_string($rawSetting)) {
$decoded = @unserialize($rawSetting);
if (is_array($decoded)) {
$raw = $decoded;
} else {
$decodedJson = json_decode($rawSetting, true);
if (is_array($decodedJson)) {
$raw = $decodedJson;
}
}
}
if (!is_array($raw)) {
return [];
}
if (isset($raw['message']) && isset($raw['code'])) {
return [];
}
if (isset($raw['items']) && is_array($raw['items'])) {
$raw = $raw['items'];
} elseif (isset($raw['data']) && is_array($raw['data'])) {
$raw = $raw['data'];
}
$list = [];
foreach ($raw as $key => $paymentType) {
if (is_array($paymentType)) {
if (isset($paymentType['id'], $paymentType['name'])) {
$list[(string)$paymentType['id']] = (string)$paymentType['name'];
continue;
}
} elseif (is_scalar($paymentType)) {
if (is_int($key) || (is_string($key) && preg_match('/^-?\d+$/', $key) === 1)) {
$list[(string)$key] = (string)$paymentType;
}
}
}
return $list;
}
}

View File

@@ -0,0 +1,379 @@
<?php
namespace admin\Controllers;
use Domain\Producer\ProducerRepository;
use Domain\Languages\LanguagesRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
use admin\Support\Forms\FormRequestHandler;
class ShopProducerController
{
private ProducerRepository $repository;
private LanguagesRepository $languagesRepository;
private FormRequestHandler $formHandler;
public function __construct(ProducerRepository $repository, LanguagesRepository $languagesRepository)
{
$this->repository = $repository;
$this->languagesRepository = $languagesRepository;
$this->formHandler = new FormRequestHandler();
}
public function list(): string
{
$sortableColumns = ['id', 'name', 'status'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'name'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$status = (int)($item['status'] ?? 0);
$img = trim((string)($item['img'] ?? ''));
$imgHtml = '';
if ($img !== '') {
$imgHtml = '<img src="' . htmlspecialchars($img, ENT_QUOTES, 'UTF-8') . '" style="max-height:30px;" />';
}
$rows[] = [
'lp' => $lp++ . '.',
'name' => '<a href="/admin/shop_producer/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'img' => $imgHtml,
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/shop_producer/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/shop_producer/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybranego producenta?',
'confirm_ok' => 'Usun',
'confirm_cancel' => 'Anuluj',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'img', 'label' => 'Logo', 'sortable' => false, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_producer/list/',
'Brak danych w tabeli.',
'/admin/shop_producer/edit/',
'Dodaj producenta'
);
return \Shared\Tpl\Tpl::view('shop-producer/producers-list', [
'viewModel' => $viewModel,
]);
}
public function view_list(): string
{
return $this->list();
}
public function edit(): string
{
$producer = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$languages = $this->languagesRepository->languagesList();
$validationErrors = $_SESSION['form_errors'][$this->formId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->formId()]);
}
return \Shared\Tpl\Tpl::view('shop-producer/producer-edit', [
'form' => $this->buildFormViewModel($producer, $languages, $validationErrors),
]);
}
public function producer_edit(): string
{
return $this->edit();
}
public function save(): void
{
// Legacy JSON (gridEdit)
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania producenta wystapil blad. Prosze sprobowac ponownie.',
];
if (is_array($values)) {
$langs = $this->languagesRepository->languagesList(true);
$id = $this->repository->save(
(int)($values['id'] ?? 0),
(string)($values['name'] ?? ''),
$this->toSwitchValue($values['status'] ?? 0),
$values['img'] ?? null,
$values['description'] ?? [],
$values['data'] ?? [],
$values['meta_title'] ?? [],
$langs
);
if (!empty($id)) {
\Shared\Helpers\Helpers::htacces();
\Shared\Helpers\Helpers::delete_dir('../temp/');
$response = [
'status' => 'ok',
'msg' => 'Producent zostal zapisany.',
'id' => (int)$id,
];
}
}
echo json_encode($response);
exit;
}
// Nowy flow (form-edit)
$producer = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$languages = $this->languagesRepository->languagesList();
$form = $this->buildFormViewModel($producer, $languages);
$result = $this->formHandler->handleSubmit($form, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->formId()] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$data = $result['data'];
$langs = $this->languagesRepository->languagesList(true);
$translations = $data['translations'] ?? [];
$description = [];
$metaData = [];
$metaTitle = [];
foreach ($translations as $langId => $fields) {
$description[$langId] = $fields['description'] ?? null;
$metaData[$langId] = $fields['data'] ?? null;
$metaTitle[$langId] = $fields['meta_title'] ?? null;
}
$savedId = $this->repository->save(
(int)($data['id'] ?? 0),
(string)($data['name'] ?? ''),
$this->toSwitchValue($data['status'] ?? 0),
$data['img'] ?? null,
$description,
$metaData,
$metaTitle,
$langs
);
if ($savedId) {
\Shared\Helpers\Helpers::htacces();
\Shared\Helpers\Helpers::delete_dir('../temp/');
echo json_encode([
'success' => true,
'id' => $savedId,
'message' => 'Producent zostal zapisany.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania producenta wystapil blad.'],
]);
exit;
}
public function producer_save(): void
{
$this->save();
}
public function delete(): void
{
if ($this->repository->delete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::htacces();
\Shared\Helpers\Helpers::delete_dir('../temp/');
\Shared\Helpers\Helpers::alert('Producent zostal usuniety.');
}
header('Location: /admin/shop_producer/list/');
exit;
}
public function producer_delete(): void
{
$this->delete();
}
private function buildFormViewModel(array $producer, array $languages, ?array $errors = null): FormEditViewModel
{
$id = (int)($producer['id'] ?? 0);
$isNew = $id <= 0;
$data = [
'id' => $id,
'name' => (string)($producer['name'] ?? ''),
'status' => (int)($producer['status'] ?? 1),
'img' => $producer['img'] ?? null,
'languages' => is_array($producer['languages'] ?? null) ? $producer['languages'] : [],
];
$fields = [
FormField::hidden('id', $id),
FormField::text('name', [
'label' => 'Nazwa',
'required' => true,
'tab' => 'general',
]),
FormField::switch('status', [
'label' => 'Aktywny',
'tab' => 'general',
'value' => true,
]),
FormField::image('img', [
'label' => 'Logo',
'tab' => 'general',
]),
FormField::langSection('translations', 'description', [
FormField::editor('description', [
'label' => 'Opis',
'height' => 250,
]),
FormField::editor('data', [
'label' => 'Dane producenta',
'height' => 250,
]),
]),
FormField::langSection('translations', 'seo', [
FormField::text('meta_title', [
'label' => 'Meta title',
]),
]),
];
$tabs = [
new FormTab('general', 'Ogolne', 'fa-file'),
new FormTab('description', 'Opis', 'fa-file'),
new FormTab('seo', 'SEO', 'fa-globe'),
];
$actionUrl = '/admin/shop_producer/save/' . ($isNew ? '' : ('id=' . $id));
$actions = [
FormAction::save($actionUrl, '/admin/shop_producer/list/'),
FormAction::cancel('/admin/shop_producer/list/'),
];
return new FormEditViewModel(
$this->formId(),
'Edycja producenta',
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/shop_producer/list/',
true,
[],
$languages,
$errors
);
}
private function formId(): string
{
return 'shop-producer-edit';
}
private function toSwitchValue($value): int
{
if (is_bool($value)) {
return $value ? 1 : 0;
}
if (is_numeric($value)) {
return ((int)$value) === 1 ? 1 : 0;
}
if (is_string($value)) {
$normalized = strtolower(trim($value));
return in_array($normalized, ['1', 'on', 'true', 'yes'], true) ? 1 : 0;
}
return 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,328 @@
<?php
namespace admin\Controllers;
use Domain\ProductSet\ProductSetRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class ShopProductSetsController
{
private ProductSetRepository $repository;
public function __construct(ProductSetRepository $repository)
{
$this->repository = $repository;
}
public function list(): string
{
$sortableColumns = ['id', 'name', 'status'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'name'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$status = (int)($item['status'] ?? 0);
$rows[] = [
'lp' => $lp++ . '.',
'name' => '<a href="/admin/shop_product_sets/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/shop_product_sets/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/shop_product_sets/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrany komplet produktow?',
'confirm_ok' => 'Usun',
'confirm_cancel' => 'Anuluj',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_product_sets/list/',
'Brak danych w tabeli.',
'/admin/shop_product_sets/edit/',
'Dodaj komplet produktow'
);
return \Shared\Tpl\Tpl::view('shop-product-sets/product-sets-list', [
'viewModel' => $viewModel,
]);
}
public function view_list(): string
{
return $this->list();
}
public function edit(): string
{
$set = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$products = $this->repository->allProductsMap();
return \Shared\Tpl\Tpl::view('shop-product-sets/product-set-edit', [
'form' => $this->buildFormViewModel($set, $products),
]);
}
public function set_edit(): string
{
return $this->edit();
}
public function save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania kompletu produktow wystapil blad. Prosze sprobowac ponownie.',
];
if (is_array($values)) {
$productIds = $values['set_products_id'] ?? [];
if (!is_array($productIds)) {
$productIds = $productIds ? [$productIds] : [];
}
$id = $this->repository->save(
(int)($values['id'] ?? 0),
(string)($values['name'] ?? ''),
$this->toSwitchValue($values['status'] ?? 0),
$productIds
);
if (!empty($id)) {
$response = [
'status' => 'ok',
'msg' => 'Komplet produktow zostal zapisany.',
'id' => (int)$id,
];
}
}
echo json_encode($response);
exit;
}
$payload = $_POST;
if (empty($payload['id'])) {
$routeId = (int)\Shared\Helpers\Helpers::get('id');
if ($routeId > 0) {
$payload['id'] = $routeId;
}
}
$productIds = $payload['set_products_id'] ?? [];
if (!is_array($productIds)) {
$productIds = $productIds ? [$productIds] : [];
}
$id = $this->repository->save(
(int)($payload['id'] ?? 0),
(string)($payload['name'] ?? ''),
$this->toSwitchValue($payload['status'] ?? 0),
$productIds
);
if (!empty($id)) {
echo json_encode([
'success' => true,
'id' => (int)$id,
'message' => 'Komplet produktow zostal zapisany.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania kompletu produktow wystapil blad.'],
]);
exit;
}
public function delete(): void
{
if ($this->repository->delete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Komplet produktow zostal usuniety.');
}
header('Location: /admin/shop_product_sets/list/');
exit;
}
public function set_delete(): void
{
$this->delete();
}
private function buildFormViewModel(array $set, array $products = []): FormEditViewModel
{
$id = (int)($set['id'] ?? 0);
$isNew = $id <= 0;
$selectedProducts = $set['products'] ?? [];
$data = [
'id' => $id,
'name' => (string)($set['name'] ?? ''),
'status' => (int)($set['status'] ?? 1),
];
$productsSelectHtml = $this->renderProductsSelect($products, $selectedProducts);
$fields = [
FormField::hidden('id', $id),
FormField::text('name', [
'label' => 'Nazwa',
'tab' => 'settings',
'required' => true,
]),
FormField::switch('status', [
'label' => 'Aktywny',
'tab' => 'settings',
'value' => true,
]),
FormField::custom('set_products', $productsSelectHtml, [
'tab' => 'settings',
]),
];
$tabs = [
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
];
$actionUrl = '/admin/shop_product_sets/save/' . ($isNew ? '' : ('id=' . $id));
$actions = [
FormAction::save($actionUrl, '/admin/shop_product_sets/list/'),
FormAction::cancel('/admin/shop_product_sets/list/'),
];
return new FormEditViewModel(
'shop-product-set-edit',
$isNew ? 'Nowy komplet produktow' : ('Edycja kompletu produktow: ' . (string)($set['name'] ?? '')),
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/shop_product_sets/list/',
true,
['id' => $id]
);
}
private function toSwitchValue($value): int
{
if (is_numeric($value)) {
return ((int)$value) === 1 ? 1 : 0;
}
if (is_string($value)) {
$normalized = strtolower(trim($value));
return in_array($normalized, ['1', 'on', 'true', 'yes'], true) ? 1 : 0;
}
return 0;
}
private function renderProductsSelect(array $products, array $selectedProducts): string
{
$html = '<div class="form-group row">';
$html .= '<label class="col-lg-4 control-label">Produkty do kompletu:</label>';
$html .= '<div class="col-lg-8">';
$html .= '<select id="set_products_id" multiple name="set_products_id[]" placeholder="produkty do kompletu">';
$html .= '<option value="">wybierz produkt...</option>';
foreach ($products as $productId => $productName) {
$pid = (int)$productId;
$selected = in_array($pid, $selectedProducts, true) ? ' selected' : '';
$html .= '<option value="' . $pid . '"' . $selected . '>'
. htmlspecialchars((string)$productName, ENT_QUOTES, 'UTF-8')
. '</option>';
}
$html .= '</select>';
$html .= '</div>';
$html .= '</div>';
return $html;
}
}

View File

@@ -0,0 +1,327 @@
<?php
namespace admin\Controllers;
use Domain\Promotion\PromotionRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class ShopPromotionController
{
private PromotionRepository $repository;
public function __construct(PromotionRepository $repository)
{
$this->repository = $repository;
}
public function list(): string
{
$sortableColumns = ['id', 'name', 'status', 'condition_type', 'date_from', 'date_to'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'id'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'DESC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$status = (int)($item['status'] ?? 0);
$conditionType = (int)($item['condition_type'] ?? 0);
$dateFrom = trim((string)($item['date_from'] ?? ''));
$dateTo = trim((string)($item['date_to'] ?? ''));
$rows[] = [
'lp' => $lp++ . '.',
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'name' => '<a href="/admin/shop_promotion/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'condition_type' => htmlspecialchars((string)(\Domain\Promotion\PromotionRepository::$condition_type[$conditionType] ?? '-'), ENT_QUOTES, 'UTF-8'),
'date_from' => $dateFrom !== '' ? htmlspecialchars($dateFrom, ENT_QUOTES, 'UTF-8') : '-',
'date_to' => $dateTo !== '' ? htmlspecialchars($dateTo, ENT_QUOTES, 'UTF-8') : '-',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/shop_promotion/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/shop_promotion/delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybrana promocje?',
'confirm_ok' => 'Usun',
'confirm_cancel' => 'Anuluj',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'condition_type', 'sort_key' => 'condition_type', 'label' => 'Typ kuponu', 'sortable' => true],
['key' => 'date_from', 'sort_key' => 'date_from', 'label' => 'Data od', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'date_to', 'sort_key' => 'date_to', 'label' => 'Data do', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_promotion/list/',
'Brak danych w tabeli.',
'/admin/shop_promotion/edit/',
'Dodaj promocje'
);
return \Shared\Tpl\Tpl::view('shop-promotion/promotions-list', [
'viewModel' => $viewModel,
]);
}
public function edit(): string
{
$promotion = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: [];
$categories = $this->repository->categoriesTree(null);
return \Shared\Tpl\Tpl::view('shop-promotion/promotion-edit', [
'form' => $this->buildFormViewModel($promotion, $categories),
]);
}
public function save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania promocji wystapil blad. Prosze sprobowac ponownie.',
];
if (is_array($values)) {
$id = $this->repository->save($values);
if (!empty($id)) {
$response = [
'status' => 'ok',
'msg' => 'Promocja zostala zapisana.',
'id' => (int)$id,
];
}
}
echo json_encode($response);
exit;
}
$payload = $_POST;
if (empty($payload['id'])) {
$routeId = (int)\Shared\Helpers\Helpers::get('id');
if ($routeId > 0) {
$payload['id'] = $routeId;
}
}
$id = $this->repository->save($payload);
if (!empty($id)) {
echo json_encode([
'success' => true,
'id' => (int)$id,
'message' => 'Promocja zostala zapisana.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania promocji wystapil blad.'],
]);
exit;
}
public function delete(): void
{
if ($this->repository->delete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Promocja zostala usunieta.');
}
header('Location: /admin/shop_promotion/list/');
exit;
}
private function buildFormViewModel(array $promotion, array $categories): FormEditViewModel
{
$id = (int)($promotion['id'] ?? 0);
$isNew = $id <= 0;
$data = [
'id' => $id,
'name' => (string)($promotion['name'] ?? ''),
'status' => (int)($promotion['status'] ?? 1),
'include_coupon' => (int)($promotion['include_coupon'] ?? 0),
'include_product_promo' => (int)($promotion['include_product_promo'] ?? 0),
'condition_type' => (int)($promotion['condition_type'] ?? 1),
'discount_type' => (int)($promotion['discount_type'] ?? 1),
'min_product_count' => $promotion['min_product_count'] ?? '',
'price_cheapest_product' => $promotion['price_cheapest_product'] ?? '',
'amount' => $promotion['amount'] ?? '',
'date_from' => (string)($promotion['date_from'] ?? ''),
'date_to' => (string)($promotion['date_to'] ?? ''),
];
$fields = [
FormField::hidden('id', $id),
FormField::text('name', [
'label' => 'Nazwa',
'tab' => 'settings',
'required' => true,
]),
FormField::switch('status', [
'label' => 'Aktywna',
'tab' => 'settings',
'value' => true,
]),
FormField::switch('include_coupon', [
'label' => 'Lacz z kuponami rabatowymi',
'tab' => 'settings',
]),
FormField::switch('include_product_promo', [
'label' => 'Uwzglednij produkty przecenione',
'tab' => 'settings',
]),
FormField::select('condition_type', [
'label' => 'Warunki promocji',
'tab' => 'settings',
'options' => \Domain\Promotion\PromotionRepository::$condition_type,
'required' => true,
]),
FormField::select('discount_type', [
'label' => 'Typ rabatu',
'tab' => 'settings',
'options' => \Domain\Promotion\PromotionRepository::$discount_type,
'required' => true,
]),
FormField::text('min_product_count', [
'label' => 'Min. ilosc produktow z danej kategorii',
'tab' => 'settings',
'attributes' => ['class' => 'int-format'],
]),
FormField::text('price_cheapest_product', [
'label' => 'Cena najtanszego produktu',
'tab' => 'settings',
'attributes' => ['class' => 'number-format'],
]),
FormField::text('amount', [
'label' => 'Wartosc',
'tab' => 'settings',
'attributes' => ['class' => 'number-format'],
]),
FormField::date('date_from', [
'label' => 'Data od',
'tab' => 'settings',
]),
FormField::date('date_to', [
'label' => 'Data do',
'tab' => 'settings',
]),
FormField::custom('categories_group_1', \Shared\Tpl\Tpl::view('shop-promotion/promotion-categories-selector', [
'label' => 'Kategorie grupa I',
'inputName' => 'categories[]',
'categories' => $categories,
'selectedIds' => is_array($promotion['categories'] ?? null) ? $promotion['categories'] : [],
]), [
'tab' => 'categories',
]),
FormField::custom('categories_group_2', \Shared\Tpl\Tpl::view('shop-promotion/promotion-categories-selector', [
'label' => 'Kategorie grupa II',
'inputName' => 'condition_categories[]',
'categories' => $categories,
'selectedIds' => is_array($promotion['condition_categories'] ?? null) ? $promotion['condition_categories'] : [],
]), [
'tab' => 'categories',
]),
];
$tabs = [
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
new FormTab('categories', 'Kategorie', 'fa-folder-open'),
];
$actionUrl = '/admin/shop_promotion/save/' . ($isNew ? '' : ('id=' . $id));
$actions = [
FormAction::save($actionUrl, '/admin/shop_promotion/list/'),
FormAction::cancel('/admin/shop_promotion/list/'),
];
return new FormEditViewModel(
'shop-promotion-edit',
$isNew ? 'Nowa promocja' : ('Edycja promocji: ' . (string)($promotion['name'] ?? '')),
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/shop_promotion/list/',
true,
['id' => $id]
);
}
}

View File

@@ -0,0 +1,265 @@
<?php
namespace admin\Controllers;
use Domain\ShopStatus\ShopStatusRepository;
use Domain\Integrations\IntegrationsRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class ShopStatusesController
{
private ShopStatusRepository $repository;
public function __construct(ShopStatusRepository $repository)
{
$this->repository = $repository;
}
public function list(): string
{
$sortableColumns = ['id', 'status', 'color', 'o', 'apilo_status_id'];
$filterDefinitions = [
[
'key' => 'status',
'label' => 'Status',
'type' => 'text',
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'o'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$apiloStatusList = $this->getApiloStatusList();
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$statusName = trim((string)($item['status'] ?? ''));
$color = trim((string)($item['color'] ?? ''));
$apiloStatusId = $item['apilo_status_id'] ?? null;
$apiloStatusLabel = '';
if ($apiloStatusId !== null && isset($apiloStatusList[$apiloStatusId])) {
$apiloStatusLabel = $apiloStatusList[$apiloStatusId];
}
$colorHtml = $color !== ''
? '<span style="display:inline-block;width:20px;height:20px;background:' . htmlspecialchars($color, ENT_QUOTES, 'UTF-8') . ';border:1px solid #ccc;vertical-align:middle;margin-right:5px;"></span> ' . htmlspecialchars($color, ENT_QUOTES, 'UTF-8')
: '-';
$rows[] = [
'lp' => $lp++ . '.',
'status' => '<a href="/admin/shop_statuses/edit/id=' . $id . '">' . htmlspecialchars($statusName, ENT_QUOTES, 'UTF-8') . '</a>',
'color' => $colorHtml,
'apilo_status' => htmlspecialchars($apiloStatusLabel, ENT_QUOTES, 'UTF-8'),
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/shop_statuses/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Status', 'sortable' => true, 'raw' => true],
['key' => 'color', 'sort_key' => 'color', 'label' => 'Kolor', 'sortable' => true, 'raw' => true],
['key' => 'apilo_status', 'sort_key' => 'apilo_status_id', 'label' => 'Status Apilo', 'sortable' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_statuses/list/',
'Brak danych w tabeli.'
);
return \Shared\Tpl\Tpl::view('shop-statuses/view-list', [
'viewModel' => $viewModel,
]);
}
public function edit(): string
{
$status = $this->repository->find((int)\Shared\Helpers\Helpers::get('id'));
if ($status === null) {
\Shared\Helpers\Helpers::alert('Status nie zostal znaleziony.');
header('Location: /admin/shop_statuses/list/');
exit;
}
$apiloStatusList = $this->getApiloStatusList();
return \Shared\Tpl\Tpl::view('shop-statuses/status-edit', [
'form' => $this->buildFormViewModel($status, $apiloStatusList),
]);
}
public function save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
$response = [
'status' => 'error',
'msg' => 'Podczas zapisywania statusu wystapil blad. Prosze sprobowac ponownie.',
];
if (is_array($values)) {
$statusId = (int)($values['id'] ?? 0);
$id = $this->repository->save($statusId, $values);
if ($id !== null && $id >= 0) {
$response = [
'status' => 'ok',
'msg' => 'Status zostal zapisany.',
'id' => (int)$id,
];
}
}
echo json_encode($response);
exit;
}
$payload = $_POST;
$statusId = isset($payload['id']) && $payload['id'] !== '' ? (int)$payload['id'] : null;
if ($statusId === null) {
$statusId = (int)\Shared\Helpers\Helpers::get('id');
}
$id = $this->repository->save($statusId, $payload);
if ($id !== null && $id >= 0) {
echo json_encode([
'success' => true,
'id' => (int)$id,
'message' => 'Status zostal zapisany.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania statusu wystapil blad.'],
]);
exit;
}
private function buildFormViewModel(array $status, array $apiloStatusList): FormEditViewModel
{
$id = (int)($status['id'] ?? 0);
$apiloOptions = ['' => '--- wybierz status apilo.com ---'];
foreach ($apiloStatusList as $apiloId => $apiloName) {
$apiloOptions[$apiloId] = $apiloName;
}
$data = [
'id' => $id,
'status' => (string)($status['status'] ?? ''),
'color' => (string)($status['color'] ?? ''),
'apilo_status_id' => $status['apilo_status_id'] ?? '',
];
$fields = [
FormField::hidden('id', $id),
FormField::text('status', [
'label' => 'Status',
'tab' => 'settings',
'readonly' => true,
]),
FormField::color('color', [
'label' => 'Kolor',
'tab' => 'settings',
]),
FormField::select('apilo_status_id', [
'label' => 'Status z Apilo',
'tab' => 'settings',
'options' => $apiloOptions,
]),
];
$tabs = [
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
];
$actionUrl = '/admin/shop_statuses/save/id=' . $id;
$actions = [
FormAction::save($actionUrl, '/admin/shop_statuses/list/'),
FormAction::cancel('/admin/shop_statuses/list/'),
];
return new FormEditViewModel(
'status-edit',
'Edycja statusu zamowienia',
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/shop_statuses/list/',
true,
['id' => $id]
);
}
private function getApiloStatusList(): array
{
global $mdb;
$integrationsRepository = new IntegrationsRepository( $mdb );
$list = [];
$raw = @unserialize( $integrationsRepository -> getSetting( 'apilo', 'status-types-list' ) );
if (is_array($raw)) {
foreach ($raw as $apiloStatus) {
if (isset($apiloStatus['id'], $apiloStatus['name'])) {
$list[(int)$apiloStatus['id']] = (string)$apiloStatus['name'];
}
}
}
return $list;
}
}

View File

@@ -0,0 +1,346 @@
<?php
namespace admin\Controllers;
use Domain\Transport\TransportRepository;
use Domain\PaymentMethod\PaymentMethodRepository;
use Domain\Integrations\IntegrationsRepository;
use admin\ViewModels\Common\PaginatedTableViewModel;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;
class ShopTransportController
{
private TransportRepository $transportRepository;
private PaymentMethodRepository $paymentMethodRepository;
public function __construct(
TransportRepository $transportRepository,
PaymentMethodRepository $paymentMethodRepository
) {
$this->transportRepository = $transportRepository;
$this->paymentMethodRepository = $paymentMethodRepository;
}
public function list(): string
{
$sortableColumns = ['id', 'name', 'status', 'cost', 'max_wp', 'default', 'o'];
$filterDefinitions = [
[
'key' => 'name',
'label' => 'Nazwa',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'name'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->transportRepository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$apiloCarrierAccounts = $this->getApiloCarrierAccounts();
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)($item['id'] ?? 0);
$name = trim((string)($item['name'] ?? ''));
$status = (int)($item['status'] ?? 0);
$cost = (float)($item['cost'] ?? 0.0);
$maxWp = $item['max_wp'] ?? null;
$default = (int)($item['default'] ?? 0);
$apiloCarrierAccountId = $item['apilo_carrier_account_id'] ?? null;
$apiloLabel = '-';
if ($apiloCarrierAccountId !== null) {
$apiloKey = (string)$apiloCarrierAccountId;
if (isset($apiloCarrierAccounts[$apiloKey])) {
$apiloLabel = $apiloCarrierAccounts[$apiloKey];
}
}
$rows[] = [
'lp' => $lp++ . '.',
'default' => $default === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'cost' => \Shared\Helpers\Helpers::decimal($cost) . ' zł',
'max_wp' => $maxWp !== null ? (int)$maxWp : '-',
'name' => '<a href="/admin/shop_transport/edit/id=' . $id . '">' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</a>',
'apilo_carrier' => htmlspecialchars((string)$apiloLabel, ENT_QUOTES, 'UTF-8'),
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/shop_transport/edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'default', 'sort_key' => 'default', 'label' => 'Domyślna FT', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'cost', 'sort_key' => 'cost', 'label' => 'Koszt', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'max_wp', 'sort_key' => 'max_wp', 'label' => 'Maks. WP', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'name', 'sort_key' => 'name', 'label' => 'Nazwa', 'sortable' => true, 'raw' => true],
['key' => 'apilo_carrier', 'label' => 'Typ kuriera Apilo', 'class' => 'text-center', 'sortable' => false],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/shop_transport/list/',
'Brak danych w tabeli.'
);
return \Shared\Tpl\Tpl::view('shop-transport/transports-list', [
'viewModel' => $viewModel,
]);
}
public function edit(): string
{
$transport = $this->transportRepository->find((int)\Shared\Helpers\Helpers::get('id'));
if ($transport === null) {
\Shared\Helpers\Helpers::alert('Rodzaj transportu nie został znaleziony.');
header('Location: /admin/shop_transport/list/');
exit;
}
$paymentMethods = $this->paymentMethodRepository->allForAdmin();
$apiloCarrierAccounts = $this->getApiloCarrierAccounts();
return \Shared\Tpl\Tpl::view('shop-transport/transport-edit', [
'form' => $this->buildFormViewModel($transport, $paymentMethods, $apiloCarrierAccounts),
]);
}
public function save(): void
{
$payload = $_POST;
$transportId = isset($payload['id']) && $payload['id'] !== ''
? (int)$payload['id']
: (int)\Shared\Helpers\Helpers::get('id');
$payload['id'] = $transportId;
$id = $this->transportRepository->save($payload);
if ($id !== null) {
\Shared\Helpers\Helpers::delete_dir('../temp/');
echo json_encode([
'success' => true,
'id' => (int)$id,
'message' => 'Rodzaj transportu został zapisany.',
]);
exit;
}
echo json_encode([
'success' => false,
'errors' => ['general' => 'Podczas zapisywania rodzaju transportu wystąpił błąd.'],
]);
exit;
}
private function buildFormViewModel(
array $transport,
array $paymentMethods,
array $apiloCarrierAccounts
): FormEditViewModel {
$id = (int)($transport['id'] ?? 0);
$name = (string)($transport['name'] ?? '');
$apiloOptions = ['' => '--- wybierz konto przewoźnika ---'];
foreach ($apiloCarrierAccounts as $carrierId => $carrierName) {
$apiloOptions[(string)$carrierId] = $carrierName;
}
$data = [
'id' => $id,
'name' => $name,
'name_visible' => (string)($transport['name_visible'] ?? ''),
'description' => (string)($transport['description'] ?? ''),
'cost' => (float)($transport['cost'] ?? 0.0),
'max_wp' => $transport['max_wp'] ?? '',
'default' => (int)($transport['default'] ?? 0),
'status' => (int)($transport['status'] ?? 0),
'delivery_free' => (int)($transport['delivery_free'] ?? 0),
'apilo_carrier_account_id' => $transport['apilo_carrier_account_id'] ?? '',
];
$fields = [
FormField::hidden('id', $id),
FormField::text('name', [
'label' => 'Nazwa',
'tab' => 'general',
'readonly' => true,
'required' => true,
]),
FormField::text('name_visible', [
'label' => 'Nazwa widoczna',
'tab' => 'general',
]),
FormField::text('description', [
'label' => 'Opis',
'tab' => 'general',
]),
FormField::number('cost', [
'label' => 'Koszt (PLN)',
'tab' => 'general',
'step' => 0.01,
'required' => true,
]),
FormField::number('max_wp', [
'label' => 'Maks. WP',
'tab' => 'general',
'required' => true,
]),
FormField::switch('default', [
'label' => 'Domyślna forma dostawy',
'tab' => 'general',
]),
FormField::switch('status', [
'label' => 'Aktywny',
'tab' => 'general',
]),
FormField::switch('delivery_free', [
'label' => 'Darmowa dostawa',
'tab' => 'general',
]),
FormField::select('apilo_carrier_account_id', [
'label' => 'Kurier z Apilo',
'tab' => 'general',
'options' => $apiloOptions,
]),
];
$transportPaymentMethods = $transport['payment_methods'] ?? [];
$paymentMethodsHtml = '';
if (is_array($paymentMethods) && !empty($paymentMethods)) {
foreach ($paymentMethods as $paymentMethod) {
$pmId = (int)($paymentMethod['id'] ?? 0);
$pmName = htmlspecialchars((string)($paymentMethod['name'] ?? ''), ENT_QUOTES, 'UTF-8');
$pmStatus = (int)($paymentMethod['status'] ?? 0);
$checked = in_array($pmId, $transportPaymentMethods) ? 'checked="checked"' : '';
$statusClass = $pmStatus === 0 ? 'text-muted' : '';
$paymentMethodsHtml .= '<div class="form-group">';
$paymentMethodsHtml .= '<div class="col-lg-12">';
$paymentMethodsHtml .= '<div class="list">';
$paymentMethodsHtml .= '<input type="checkbox" class="g-checkbox" name="payment_methods[]" value="' . $pmId . '" ' . $checked . ' />';
$paymentMethodsHtml .= '<span class="bold ' . $statusClass . '">' . $pmName . '</span>';
$paymentMethodsHtml .= '</div>';
$paymentMethodsHtml .= '</div>';
$paymentMethodsHtml .= '</div>';
}
}
$fields[] = FormField::custom(
'payment_methods_section',
$paymentMethodsHtml,
['tab' => 'payment_methods']
);
$tabs = [
new FormTab('general', 'Ogólne', 'fa-file'),
new FormTab('payment_methods', 'Powiązane metody płatności', 'fa-wrench'),
];
$actionUrl = '/admin/shop_transport/save/id=' . $id;
$actions = [
FormAction::save($actionUrl, '/admin/shop_transport/list/'),
FormAction::cancel('/admin/shop_transport/list/'),
];
return new FormEditViewModel(
'shop-transport-edit',
'Edycja rodzaju transportu: ' . $name,
$data,
$fields,
$tabs,
$actions,
'POST',
$actionUrl,
'/admin/shop_transport/list/',
true,
['id' => $id]
);
}
private function getApiloCarrierAccounts(): array
{
global $mdb;
$integrationsRepository = new IntegrationsRepository( $mdb );
$rawSetting = $integrationsRepository -> getSetting( 'apilo', 'carrier-account-list' );
$raw = null;
if (is_array($rawSetting)) {
$raw = $rawSetting;
} elseif (is_string($rawSetting)) {
$decoded = @unserialize($rawSetting);
if (is_array($decoded)) {
$raw = $decoded;
}
}
if (!is_array($raw)) {
return [];
}
$list = [];
foreach ($raw as $carrier) {
if (is_array($carrier) && isset($carrier['id'], $carrier['name'])) {
$list[(string)$carrier['id']] = (string)$carrier['name'];
}
}
return $list;
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace admin\Controllers;
use Domain\Update\UpdateRepository;
class UpdateController
{
private UpdateRepository $repository;
public function __construct( UpdateRepository $repository )
{
$this->repository = $repository;
}
public function main_view(): string
{
return \Shared\Tpl\Tpl::view( 'update/main-view', [
'ver' => \Shared\Helpers\Helpers::get_version(),
'new_ver' => \Shared\Helpers\Helpers::get_new_version(),
] );
}
public function update(): void
{
$result = $this->repository->update();
if ( !$result['success'] ) {
\Shared\Helpers\Helpers::alert( 'W trakcie aktualizacji systemu wystąpił błąd. Proszę spróbować ponownie.' );
} else {
\Shared\Helpers\Helpers::set_message( 'Aktualizacja przebiegła pomyślnie.' );
}
header( 'Location: /admin/update/main_view/' );
exit;
}
public function updateAll(): void
{
$result = $this->repository->update();
$response = [
'status' => !empty( $result['success'] ) && empty( $result['no_updates'] ),
'version' => number_format( (float) \Shared\Helpers\Helpers::get( 'version_current' ) + 0.001, 3, '.', '' ),
];
echo json_encode( $response );
exit;
}
}

View File

@@ -0,0 +1,346 @@
<?php
namespace admin\Controllers;
use Domain\User\UserRepository;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\Support\Forms\FormRequestHandler;
class UsersController
{
private UserRepository $repository;
private FormRequestHandler $formHandler;
public function __construct(UserRepository $repository)
{
$this->repository = $repository;
$this->formHandler = new FormRequestHandler();
}
public function user_delete(): void
{
if ($this->repository->delete((int)\Shared\Helpers\Helpers::get('id'))) {
\Shared\Helpers\Helpers::alert('Uzytkownik zostal usuniety.');
}
header('Location: /admin/users/view_list/');
exit;
}
public function user_save(): void
{
$legacyValues = \Shared\Helpers\Helpers::get('values');
if ($legacyValues) {
$values = json_decode((string)$legacyValues, true);
if (!is_array($values)) {
echo json_encode(['status' => 'error', 'msg' => 'Nieprawidlowe dane formularza.']);
exit;
}
if (!$this->isTwofaEmailValidForEnabled($values['twofa_enabled'] ?? 0, (string)($values['twofa_email'] ?? ''))) {
echo json_encode([
'status' => 'error',
'msg' => 'Jesli wlaczono dwustopniowe uwierzytelnianie (2FA), pole "E-mail do 2FA" jest wymagane.',
]);
exit;
}
$response = $this->repository->save(
(int)($values['id'] ?? 0),
(string)($values['login'] ?? ''),
$values['status'] ?? 0,
(string)($values['password'] ?? ''),
(string)($values['password_re'] ?? ''),
$values['admin'] ?? 1,
$values['twofa_enabled'] ?? 0,
(string)($values['twofa_email'] ?? '')
);
echo json_encode($response);
exit;
}
$userId = (int)\Shared\Helpers\Helpers::get('id');
$user = $this->normalizeUser($this->repository->find($userId));
$viewModel = $this->buildFormViewModel($user);
$result = $this->formHandler->handleSubmit($viewModel, $_POST);
if (!$result['success']) {
$_SESSION['form_errors'][$this->getFormId()] = $result['errors'];
echo json_encode(['success' => false, 'errors' => $result['errors']]);
exit;
}
$data = $result['data'];
$data['id'] = $userId;
$data['admin'] = 1;
if (!$this->isTwofaEmailValidForEnabled($data['twofa_enabled'] ?? 0, (string)($data['twofa_email'] ?? ''))) {
echo json_encode([
'success' => false,
'errors' => [
'twofa_email' => 'Pole "E-mail do 2FA" jest wymagane, gdy wlaczono 2FA.',
],
]);
exit;
}
$duplicateLoginCheck = $this->repository->checkLogin((string)($data['login'] ?? ''), $userId);
if (($duplicateLoginCheck['status'] ?? '') !== 'ok') {
echo json_encode([
'success' => false,
'errors' => ['login' => (string)($duplicateLoginCheck['msg'] ?? 'Podany login jest juz zajety.')],
]);
exit;
}
$response = $this->repository->save(
(int)$data['id'],
(string)($data['login'] ?? ''),
(int)($data['status'] ?? 0),
(string)($data['password'] ?? ''),
(string)($data['password_re'] ?? ''),
1,
(int)($data['twofa_enabled'] ?? 0),
(string)($data['twofa_email'] ?? '')
);
echo json_encode([
'success' => ($response['status'] ?? '') === 'ok',
'message' => (string)($response['msg'] ?? 'Zmiany zostaly zapisane.'),
'errors' => (($response['status'] ?? '') === 'ok') ? [] : ['general' => (string)($response['msg'] ?? 'Wystapil blad.')],
]);
exit;
}
public function user_edit(): string
{
$user = $this->normalizeUser($this->repository->find((int)\Shared\Helpers\Helpers::get('id')));
$validationErrors = $_SESSION['form_errors'][$this->getFormId()] ?? null;
if ($validationErrors) {
unset($_SESSION['form_errors'][$this->getFormId()]);
}
return \Shared\Tpl\Tpl::view('users/user-edit', [
'form' => $this->buildFormViewModel($user, $validationErrors),
]);
}
public function view_list(): string
{
$sortableColumns = ['login', 'status'];
$filterDefinitions = [
[
'key' => 'login',
'label' => 'Login',
'type' => 'text',
],
[
'key' => 'status',
'label' => 'Aktywny',
'type' => 'select',
'options' => [
'' => '- aktywny -',
'1' => 'tak',
'0' => 'nie',
],
],
];
$listRequest = \admin\Support\TableListRequestFactory::fromRequest(
$filterDefinitions,
$sortableColumns,
'login'
);
$sortDir = $listRequest['sortDir'];
if (trim((string)\Shared\Helpers\Helpers::get('sort')) === '') {
$sortDir = 'ASC';
}
$result = $this->repository->listForAdmin(
$listRequest['filters'],
$listRequest['sortColumn'],
$sortDir,
$listRequest['page'],
$listRequest['perPage']
);
$rows = [];
$lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
foreach ($result['items'] as $item) {
$id = (int)$item['id'];
$login = trim((string)($item['login'] ?? ''));
$status = (int)($item['status'] ?? 0);
$rows[] = [
'lp' => $lp++ . '.',
'status' => $status === 1 ? 'tak' : '<span style="color: #FF0000;">nie</span>',
'login' => '<a href="/admin/users/user_edit/id=' . $id . '">' . htmlspecialchars($login, ENT_QUOTES, 'UTF-8') . '</a>',
'_actions' => [
[
'label' => 'Edytuj',
'url' => '/admin/users/user_edit/id=' . $id,
'class' => 'btn btn-xs btn-primary',
],
[
'label' => 'Usun',
'url' => '/admin/users/user_delete/id=' . $id,
'class' => 'btn btn-xs btn-danger',
'confirm' => 'Na pewno chcesz usunac wybranego uzytkownika?',
],
],
];
}
$total = (int)$result['total'];
$totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
$viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
[
['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
['key' => 'login', 'sort_key' => 'login', 'label' => 'Login', 'sortable' => true, 'raw' => true],
],
$rows,
$listRequest['viewFilters'],
[
'column' => $listRequest['sortColumn'],
'dir' => $sortDir,
],
[
'page' => $listRequest['page'],
'per_page' => $listRequest['perPage'],
'total' => $total,
'total_pages' => $totalPages,
],
array_merge($listRequest['queryFilters'], [
'sort' => $listRequest['sortColumn'],
'dir' => $sortDir,
'per_page' => $listRequest['perPage'],
]),
$listRequest['perPageOptions'],
$sortableColumns,
'/admin/users/view_list/',
'Brak danych w tabeli.',
'/admin/users/user_edit/',
'Dodaj uzytkownika'
);
return \Shared\Tpl\Tpl::view('users/users-list', [
'viewModel' => $viewModel,
]);
}
public function list(): string
{
return $this->view_list();
}
public function login_form(): string
{
return \Shared\Tpl\Tpl::view('site/unlogged-layout');
}
public function twofa(): string
{
return \Shared\Tpl\Tpl::view('site/unlogged', [
'content' => \Shared\Tpl\Tpl::view('users/user-2fa'),
]);
}
private function normalizeUser(?array $user): array
{
return [
'id' => (int)($user['id'] ?? 0),
'login' => (string)($user['login'] ?? ''),
'status' => (int)($user['status'] ?? 1),
'admin' => (int)($user['admin'] ?? 1),
'twofa_enabled' => (int)($user['twofa_enabled'] ?? 0),
'twofa_email' => (string)($user['twofa_email'] ?? ''),
];
}
private function buildFormViewModel(array $user, ?array $errors = null): FormEditViewModel
{
$userId = (int)($user['id'] ?? 0);
$isNew = $userId <= 0;
$data = [
'id' => $userId,
'login' => (string)($user['login'] ?? ''),
'status' => (int)($user['status'] ?? 1),
'twofa_enabled' => (int)($user['twofa_enabled'] ?? 0),
'twofa_email' => (string)($user['twofa_email'] ?? ''),
'password' => '',
'password_re' => '',
];
$fields = [
FormField::text('login', [
'label' => 'Login',
'required' => true,
]),
FormField::switch('status', [
'label' => 'Aktywny',
]),
FormField::switch('twofa_enabled', [
'label' => 'Dwustopniowe uwierzytelnianie (2FA)',
]),
FormField::email('twofa_email', [
'label' => 'E-mail do 2FA',
]),
FormField::password('password', [
'label' => 'Haslo',
'required' => $isNew,
'attributes' => ['minlength' => 5],
]),
FormField::password('password_re', [
'label' => 'Haslo - powtorz',
'required' => $isNew,
'attributes' => ['minlength' => 5],
]),
];
$actionUrl = '/admin/users/user_save/' . ($isNew ? '' : ('id=' . $userId));
$actions = [
FormAction::save($actionUrl, '/admin/users/view_list/'),
FormAction::cancel('/admin/users/view_list/'),
];
return new FormEditViewModel(
$this->getFormId(),
$isNew ? 'Nowy uzytkownik' : 'Edycja uzytkownika',
$data,
$fields,
[],
$actions,
'POST',
$actionUrl,
'/admin/users/view_list/',
true,
[
'id' => $userId,
'admin' => 1,
],
null,
$errors
);
}
private function getFormId(): string
{
return 'users-edit';
}
private function isTwofaEmailValidForEnabled($twofaEnabled, string $twofaEmail): bool
{
$enabled = ($twofaEnabled === 'on' || $twofaEnabled === 1 || $twofaEnabled === '1' || $twofaEnabled === true);
if (!$enabled) {
return true;
}
return trim($twofaEmail) !== '';
}
}

View File

@@ -0,0 +1,494 @@
<?php
namespace admin\Support\Forms;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormFieldType;
/**
* Renderer pól formularza
*/
class FormFieldRenderer
{
private FormEditViewModel $form;
public function __construct(FormEditViewModel $form)
{
$this->form = $form;
}
/**
* Renderuje pojedyncze pole
*/
public function renderField(FormField $field): string
{
$method = 'render' . ucfirst($field->type);
if (method_exists($this, $method)) {
return $this->$method($field);
}
// Fallback dla nieznanych typów - renderuj jako text
return $this->renderText($field);
}
/**
* Renderuje pole tekstowe
*/
public function renderText(FormField $field): string
{
$value = $this->form->getFieldValue($field);
$error = $this->form->getError($field->name);
$params = [
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'type' => 'text',
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
];
if ($field->placeholder) {
$params['placeholder'] = $field->placeholder;
}
if ($error) {
$params['class'] .= ' error';
}
return $this->wrapWithError(\Shared\Html\Html::input($params), $error);
}
/**
* Renderuje pole number
*/
public function renderNumber(FormField $field): string
{
$value = $this->form->getFieldValue($field);
$error = $this->form->getError($field->name);
$params = [
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'type' => 'number',
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
];
if ($error) {
$params['class'] .= ' error';
}
return $this->wrapWithError(\Shared\Html\Html::input($params), $error);
}
/**
* Renderuje pole email
*/
public function renderEmail(FormField $field): string
{
$value = $this->form->getFieldValue($field);
$error = $this->form->getError($field->name);
$params = [
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'type' => 'email',
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
];
if ($error) {
$params['class'] .= ' error';
}
return $this->wrapWithError(\Shared\Html\Html::input($params), $error);
}
/**
* Renderuje pole password
*/
public function renderPassword(FormField $field): string
{
$value = $this->form->getFieldValue($field);
return \Shared\Html\Html::input([
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'type' => 'password',
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
]);
}
/**
* Renderuje pole daty
*/
public function renderDate(FormField $field): string
{
$value = $this->form->getFieldValue($field);
$error = $this->form->getError($field->name);
$params = [
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'type' => 'text',
'class' => 'date ' . ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
];
if ($error) {
$params['class'] .= ' error';
}
return $this->wrapWithError(\Shared\Html\Html::input($params), $error);
}
/**
* Renderuje pole daty i czasu
*/
public function renderDatetime(FormField $field): string
{
$value = $this->form->getFieldValue($field);
return \Shared\Html\Html::input([
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'type' => 'text',
'class' => 'datetime ' . ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
]);
}
/**
* Renderuje przełącznik (switch)
*/
public function renderSwitch(FormField $field): string
{
$value = $this->form->getFieldValue($field);
// Domyślna wartość dla nowego rekordu
if ($value === null && $field->value === true) {
$checked = true;
} else {
$checked = (bool) $value;
}
return \Shared\Html\Html::input_switch([
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'checked' => $checked,
]);
}
/**
* Renderuje select
*/
public function renderSelect(FormField $field): string
{
$value = $this->form->getFieldValue($field);
$error = $this->form->getError($field->name);
$params = [
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'values' => $field->options,
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
];
if ($error) {
$params['class'] .= ' error';
}
return $this->wrapWithError(\Shared\Html\Html::select($params), $error);
}
/**
* Renderuje textarea
*/
public function renderTextarea(FormField $field): string
{
$value = $this->form->getFieldValue($field);
return \Shared\Html\Html::textarea([
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'rows' => $field->attributes['rows'] ?? 4,
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
]);
}
/**
* Renderuje edytor (CKEditor)
*/
public function renderEditor(FormField $field): string
{
$value = $this->form->getFieldValue($field);
return \Shared\Html\Html::textarea([
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'rows' => max(10, ($field->attributes['rows'] ?? 10)),
'class' => 'editor ' . ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
]);
}
/**
* Renderuje pole obrazu z filemanagerem
*/
public function renderImage(FormField $field): string
{
$value = $this->form->getFieldValue($field);
$filemanagerUrl = $field->filemanagerUrl ?? $this->generateFilemanagerUrl($field->id);
return \Shared\Html\Html::input_icon([
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'type' => 'text',
'icon_content' => 'przeglądaj',
'icon_js' => "window.open('{$filemanagerUrl}', 'filemanager', 'location=1,status=1,scrollbars=1,width=1100,height=700')",
]);
}
/**
* Renderuje pole pliku
*/
public function renderFile(FormField $field): string
{
$value = $this->form->getFieldValue($field);
if ($field->useFilemanager) {
$filemanagerUrl = $field->filemanagerUrl ?? $this->generateFilemanagerUrl($field->id);
return \Shared\Html\Html::input_icon([
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'value' => $value ?? '',
'type' => 'text',
'icon_content' => 'przeglądaj',
'icon_js' => "window.open('{$filemanagerUrl}', 'filemanager', 'location=1,status=1,scrollbars=1,width=1100,height=700')",
]);
}
return \Shared\Html\Html::input([
'label' => $field->label,
'name' => $field->name,
'id' => $field->id,
'type' => 'file',
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
]);
}
/**
* Renderuje ukryte pole
*/
public function renderHidden(FormField $field): string
{
$value = $this->form->getFieldValue($field);
return '<input type="hidden" name="' . htmlspecialchars($field->name) . '" ' .
'id="' . htmlspecialchars($field->id) . '" ' .
'value="' . htmlspecialchars($value ?? '') . '">';
}
/**
* Renderuje pole koloru (color picker + text input)
*/
public function renderColor(FormField $field): string
{
$value = $this->form->getFieldValue($field);
$error = $this->form->getError($field->name);
$colorValue = htmlspecialchars($value ?? '#000000', ENT_QUOTES, 'UTF-8');
$fieldName = htmlspecialchars($field->name, ENT_QUOTES, 'UTF-8');
$fieldId = htmlspecialchars($field->id, ENT_QUOTES, 'UTF-8');
$label = htmlspecialchars($field->label, ENT_QUOTES, 'UTF-8');
$html = '<div class="form-group row">';
$html .= '<label class="col-lg-4 control-label">' . $label . ':</label>';
$html .= '<div class="col-lg-8">';
$html .= '<div style="display:flex;align-items:center;gap:8px;">';
$html .= '<input type="color" id="' . $fieldId . '_picker" value="' . $colorValue . '" style="width:40px;height:34px;padding:2px;border:1px solid #ccc;cursor:pointer;" />';
$html .= '<input type="text" name="' . $fieldName . '" id="' . $fieldId . '" value="' . $colorValue . '" class="form-control" style="max-width:150px;" />';
$html .= '</div>';
$html .= '</div>';
$html .= '</div>';
$html .= '<script>$(function(){'
. 'var $p=$("#' . $fieldId . '_picker"),$t=$("#' . $fieldId . '");'
. '$p.on("input",function(){$t.val(this.value);});'
. '$t.on("input",function(){var v=this.value;if(/^#[0-9a-fA-F]{6}$/.test(v))$p.val(v);});'
. '});</script>';
return $this->wrapWithError($html, $error);
}
public function renderCustom(FormField $field): string
{
return (string)($field->customHtml ?? '');
}
/**
* Renderuje sekcję językową
*/
public function renderLangSection(FormField $section): string
{
if ($section->langFields === null || $this->form->languages === null) {
return '';
}
$out = '<div id="languages-' . $section->name . '" class="languages-tabs">';
// Zakładki języków
$out .= '<ul class="resp-tabs-list languages-tabs htabs">';
foreach ($this->form->languages as $lang) {
if ($lang['status']) {
$out .= '<li>' . htmlspecialchars($lang['name']) . '</li>';
}
}
$out .= '</ul>';
// Kontenery języków
$out .= '<div class="resp-tabs-container languages-tabs">';
foreach ($this->form->languages as $lang) {
if ($lang['status']) {
$out .= '<div>';
foreach ($section->langFields as $field) {
$out .= $this->renderLangField($field, $lang['id'], $section->name);
}
$out .= '</div>';
}
}
$out .= '</div>';
$out .= '</div>';
return $out;
}
/**
* Renderuje pole w sekcji językowej
*/
private function renderLangField(FormField $field, $languageId, string $sectionName): string
{
$value = $this->form->getFieldValue($field, $languageId, $field->name);
$error = $this->form->getError($sectionName . '_' . $field->name, $languageId);
$name = $field->getLocalizedName($languageId);
$id = $field->getLocalizedId($languageId);
switch ($field->type) {
case FormFieldType::IMAGE:
$filemanagerUrl = $field->filemanagerUrl ?? $this->generateFilemanagerUrl($id);
return $this->wrapWithError(\Shared\Html\Html::input_icon([
'label' => $field->label,
'name' => $name,
'id' => $id,
'value' => $value ?? '',
'type' => 'text',
'icon_content' => 'przeglądaj',
'icon_js' => "window.open('{$filemanagerUrl}', 'filemanager', 'location=1,status=1,scrollbars=1,width=1100,height=700')",
]), $error);
case FormFieldType::TEXTAREA:
case FormFieldType::EDITOR:
return $this->wrapWithError(\Shared\Html\Html::textarea([
'label' => $field->label,
'name' => $name,
'id' => $id,
'value' => $value ?? '',
'rows' => $field->type === FormFieldType::EDITOR ? 10 : ($field->attributes['rows'] ?? 4),
'class' => $field->type === FormFieldType::EDITOR ? 'editor' : '',
]), $error);
case FormFieldType::SWITCH:
return \Shared\Html\Html::input_switch([
'label' => $field->label,
'name' => $name,
'id' => $id,
'checked' => (bool) $value,
]);
case FormFieldType::SELECT:
return $this->wrapWithError(\Shared\Html\Html::select([
'label' => $field->label,
'name' => $name,
'id' => $id,
'value' => $value ?? '',
'values' => $field->options,
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
]), $error);
default: // TEXT, URL, etc.
if (!empty($field->attributes['icon_content'])) {
$iconJs = (string)($field->attributes['icon_js'] ?? '');
if ($iconJs !== '') {
$iconJs = str_replace('{lang}', (string)$languageId, $iconJs);
}
return $this->wrapWithError(\Shared\Html\Html::input_icon([
'label' => $field->label,
'name' => $name,
'id' => $id,
'value' => $value ?? '',
'type' => $field->type === FormFieldType::EMAIL ? 'email' : 'text',
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
'icon_content' => (string)$field->attributes['icon_content'],
'icon_class' => (string)($field->attributes['icon_class'] ?? ''),
'icon_js' => $iconJs,
]), $error);
}
return $this->wrapWithError(\Shared\Html\Html::input([
'label' => $field->label,
'name' => $name,
'id' => $id,
'value' => $value ?? '',
'type' => $field->type === FormFieldType::EMAIL ? 'email' : 'text',
'class' => ($field->required ? 'require ' : '') . ($field->attributes['class'] ?? ''),
]), $error);
}
}
/**
* Generuje URL do filemanagera
*/
private function generateFilemanagerUrl(string $fieldId): string
{
$rfmAkey = $_SESSION['rfm_akey'] ?? bin2hex(random_bytes(16));
$_SESSION['rfm_akey'] = $rfmAkey;
$_SESSION['rfm_akey_expires'] = time() + 20 * 60;
$_SESSION['can_use_rfm'] = true;
$fieldIdParam = rawurlencode($fieldId);
$akeyParam = rawurlencode($rfmAkey);
return "/libraries/filemanager-9.14.2/dialog.php?type=1&popup=1&field_id={$fieldIdParam}&akey={$akeyParam}";
}
/**
* Opakowuje pole w kontener błędu
*/
private function wrapWithError(string $html, ?string $error): string
{
if ($error) {
return '<div class="field-with-error">' . $html .
'<span class="error-message">' . htmlspecialchars($error) . '</span></div>';
}
return $html;
}
}

View File

@@ -0,0 +1,152 @@
<?php
namespace admin\Support\Forms;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormFieldType;
use admin\Validation\FormValidator;
/**
* Obsługa żądań formularza (POST, persist, walidacja)
*/
class FormRequestHandler
{
private FormValidator $validator;
public function __construct()
{
$this->validator = new FormValidator();
}
/**
* Przetwarza żądanie POST formularza
*
* @param FormEditViewModel $formViewModel
* @param array $postData Dane z $_POST
* @return array Wynik przetwarzania ['success' => bool, 'errors' => array, 'data' => array]
*/
public function handleSubmit(FormEditViewModel $formViewModel, array $postData): array
{
$result = [
'success' => false,
'errors' => [],
'data' => []
];
// Walidacja
$errors = $this->validator->validate($postData, $formViewModel->fields, $formViewModel->languages);
if (!empty($errors)) {
$result['errors'] = $errors;
// Zapisz dane do persist przy błędzie walidacji
if ($formViewModel->persist) {
$formViewModel->saveToPersist($postData);
}
return $result;
}
// Przetwórz dane (np. konwersja typów)
$processedData = $this->processData($postData, $formViewModel->fields);
$result['success'] = true;
$result['data'] = $processedData;
// Wyczyść persist po sukcesie
if ($formViewModel->persist) {
$formViewModel->clearPersist();
}
return $result;
}
/**
* Przetwarza dane z formularza (konwersja typów)
*/
private function processData(array $postData, array $fields): array
{
$processed = [];
foreach ($fields as $field) {
$value = $postData[$field->name] ?? null;
// Konwersja typów
switch ($field->type) {
case FormFieldType::SWITCH:
$processed[$field->name] = $value ? 1 : 0;
break;
case FormFieldType::NUMBER:
$processed[$field->name] = $value !== null && $value !== '' ? (float)$value : null;
break;
case FormFieldType::LANG_SECTION:
if ($field->langFields !== null) {
$processed[$field->name] = $this->processLangSection($postData, $field);
}
break;
default:
$processed[$field->name] = $value;
}
}
return $processed;
}
/**
* Przetwarza sekcję językową
*/
private function processLangSection(array $postData, $section): array
{
$result = [];
if ($section->langFields === null) {
return $result;
}
foreach ($section->langFields as $field) {
$fieldName = $field->name;
$langData = $postData[$fieldName] ?? [];
foreach ($langData as $langId => $value) {
if (!isset($result[$langId])) {
$result[$langId] = [];
}
// Konwersja typów dla pól językowych
switch ($field->type) {
case FormFieldType::SWITCH:
$result[$langId][$fieldName] = $value ? 1 : 0;
break;
case FormFieldType::NUMBER:
$result[$langId][$fieldName] = $value !== null && $value !== '' ? (float)$value : null;
break;
default:
$result[$langId][$fieldName] = $value;
}
}
}
return $result;
}
/**
* Przywraca dane z persist do POST (przy błędzie walidacji)
*/
public function restoreFromPersist(FormEditViewModel $formViewModel): ?array
{
if (!$formViewModel->persist) {
return null;
}
return $_SESSION['form_persist'][$formViewModel->formId] ?? null;
}
/**
* Sprawdza czy żądanie jest submitowaniem formularza
*/
public function isFormSubmit(string $formId): bool
{
return $_SERVER['REQUEST_METHOD'] === 'POST' &&
(isset($_POST['_form_id']) && $_POST['_form_id'] === $formId);
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace admin\Support;
class TableListRequestFactory
{
public const DEFAULT_PER_PAGE_OPTIONS = [5, 10, 15, 25, 50, 100];
public const DEFAULT_PER_PAGE = 15;
/**
* Buduje kontekst listy (filtry, sortowanie, paginacja) z requestu.
*
* @return array{
* page:int,
* perPage:int,
* perPageOptions:array<int,int>,
* filters:array<string,string>,
* viewFilters:array<int,array<string,mixed>>,
* queryFilters:array<string,string>,
* sortColumn:string,
* sortDir:string
* }
*/
public static function fromRequest(
array $filterDefinitions,
array $sortableColumns,
string $defaultSortColumn = 'date_add',
?array $perPageOptions = null,
?int $defaultPerPage = null
): array {
if ($perPageOptions === null) {
$perPageOptions = self::DEFAULT_PER_PAGE_OPTIONS;
}
if ($defaultPerPage === null) {
$defaultPerPage = self::DEFAULT_PER_PAGE;
}
if (!in_array($defaultPerPage, $perPageOptions, true)) {
$defaultPerPage = (int)$perPageOptions[0];
}
$page = max(1, (int)\Shared\Helpers\Helpers::get('page'));
$perPage = (int)\Shared\Helpers\Helpers::get('per_page');
if (!in_array($perPage, $perPageOptions, true)) {
$perPage = $defaultPerPage;
}
$filters = [];
$viewFilters = [];
$queryFilters = [];
foreach ($filterDefinitions as $definition) {
$key = (string)($definition['key'] ?? '');
if ($key === '') {
continue;
}
$type = (string)($definition['type'] ?? 'text');
$value = (string)\Shared\Helpers\Helpers::get($key);
$filters[$key] = $value;
$queryFilters[$key] = $value;
$filterConfig = [
'key' => $key,
'label' => (string)($definition['label'] ?? $key),
'type' => $type,
'value' => $value,
];
if ($type === 'select' && isset($definition['options']) && is_array($definition['options'])) {
$filterConfig['options'] = $definition['options'];
}
$viewFilters[] = $filterConfig;
}
$sortColumn = trim((string)\Shared\Helpers\Helpers::get('sort'));
if (!in_array($sortColumn, $sortableColumns, true)) {
$sortColumn = $defaultSortColumn;
}
$sortDir = strtoupper(trim((string)\Shared\Helpers\Helpers::get('dir')));
if (!in_array($sortDir, ['ASC', 'DESC'], true)) {
$sortDir = 'DESC';
}
return [
'page' => $page,
'perPage' => $perPage,
'perPageOptions' => $perPageOptions,
'filters' => $filters,
'viewFilters' => $viewFilters,
'queryFilters' => $queryFilters,
'sortColumn' => $sortColumn,
'sortDir' => $sortDir,
];
}
}
?>

View File

@@ -0,0 +1,196 @@
<?php
namespace admin\Validation;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormFieldType;
/**
* Walidator formularzy
*/
class FormValidator
{
private array $errors = [];
/**
* Waliduje dane na podstawie definicji pól
*
* @param array $data Dane z POST
* @param array $fields Definicje pól (FormField[])
* @param array|null $languages Języki (dla walidacji pól językowych)
* @return array Tablica błędów (pusta jeśli OK)
*/
public function validate(array $data, array $fields, ?array $languages = null): array
{
$this->errors = [];
foreach ($fields as $field) {
if ($field->type === FormFieldType::LANG_SECTION) {
$this->validateLangSection($data, $field, $languages ?? []);
} else {
$this->validateField($data, $field);
}
}
return $this->errors;
}
/**
* Waliduje pojedyncze pole
*/
private function validateField(array $data, FormField $field): void
{
$value = $data[$field->name] ?? null;
// Walidacja wymagalności
if ($field->required && $this->isEmpty($value)) {
$this->errors[$field->name] = "Pole \"{$field->label}\" jest wymagane.";
return;
}
// Jeśli pole puste i nie jest wymagane - pomijamy dalszą walidację
if ($this->isEmpty($value)) {
return;
}
// Walidacja typu
switch ($field->type) {
case FormFieldType::EMAIL:
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
$this->errors[$field->name] = "Pole \"{$field->label}\" musi być poprawnym adresem e-mail.";
}
break;
case FormFieldType::NUMBER:
if (!is_numeric($value)) {
$this->errors[$field->name] = "Pole \"{$field->label}\" musi być liczbą.";
}
break;
case FormFieldType::DATE:
if (!$this->isValidDate($value)) {
$this->errors[$field->name] = "Pole \"{$field->label}\" musi być poprawną datą (YYYY-MM-DD).";
}
break;
case FormFieldType::DATETIME:
if (!$this->isValidDateTime($value)) {
$this->errors[$field->name] = "Pole \"{$field->label}\" musi być poprawną datą i czasem.";
}
break;
}
// Walidacja customowa (callback)
if (isset($field->attributes['validate_callback']) && is_callable($field->attributes['validate_callback'])) {
$result = call_user_func($field->attributes['validate_callback'], $value, $data);
if ($result !== true) {
$this->errors[$field->name] = is_string($result) ? $result : "Pole \"{$field->label}\" zawiera nieprawidłową wartość.";
}
}
}
/**
* Waliduje sekcję językową
*/
private function validateLangSection(array $data, FormField $section, array $languages): void
{
if ($section->langFields === null) {
return;
}
foreach ($languages as $language) {
if (!($language['status'] ?? false)) {
continue;
}
$langId = $language['id'];
foreach ($section->langFields as $field) {
$fieldName = $field->name;
$value = $data[$fieldName][$langId] ?? null;
// Walidacja wymagalności
if ($field->required && $this->isEmpty($value)) {
$errorKey = "{$section->name}_{$fieldName}";
$this->errors[$errorKey][$langId] = "Pole \"{$field->label}\" ({$language['name']}) jest wymagane.";
continue;
}
// Walidacja typu dla pól językowych
if (!$this->isEmpty($value)) {
switch ($field->type) {
case FormFieldType::EMAIL:
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
$errorKey = "{$section->name}_{$fieldName}";
$this->errors[$errorKey][$langId] = "Pole \"{$field->label}\" ({$language['name']}) musi być poprawnym e-mailem.";
}
break;
}
}
}
}
}
/**
* Sprawdza czy wartość jest pusta
*/
private function isEmpty($value): bool
{
return $value === null || $value === '' || (is_array($value) && empty($value));
}
/**
* Sprawdza czy data jest poprawna (YYYY-MM-DD)
*/
private function isValidDate(string $date): bool
{
$d = \DateTime::createFromFormat('Y-m-d', $date);
return $d && $d->format('Y-m-d') === $date;
}
/**
* Sprawdza czy data i czas są poprawne
*/
private function isValidDateTime(string $datetime): bool
{
$d = \DateTime::createFromFormat('Y-m-d H:i:s', $datetime);
if ($d && $d->format('Y-m-d H:i:s') === $datetime) {
return true;
}
// Spróbuj bez sekund
$d = \DateTime::createFromFormat('Y-m-d H:i', $datetime);
return $d && $d->format('Y-m-d H:i') === $datetime;
}
/**
* Sprawdza czy walidacja zakończyła się sukcesem
*/
public function isValid(): bool
{
return empty($this->errors);
}
/**
* Zwraca wszystkie błędy
*/
public function getErrors(): array
{
return $this->errors;
}
/**
* Zwraca pierwszy błąd
*/
public function getFirstError(): ?string
{
if (empty($this->errors)) {
return null;
}
$first = reset($this->errors);
if (is_array($first)) {
return reset($first);
}
return $first;
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace admin\ViewModels\Common;
class PaginatedTableViewModel
{
public array $columns;
public array $rows;
public array $filters;
public array $sort;
public array $pagination;
public array $query;
public array $perPageOptions;
public array $sortableColumns;
public string $basePath;
public string $emptyMessage;
public ?string $createUrl;
public ?string $createLabel;
public ?string $customScriptView;
public function __construct(
array $columns = [],
array $rows = [],
array $filters = [],
array $sort = [],
array $pagination = [],
array $query = [],
array $perPageOptions = [5, 10, 15, 25, 50, 100],
array $sortableColumns = [],
string $basePath = '',
string $emptyMessage = 'Brak danych.',
?string $createUrl = null,
?string $createLabel = null,
?string $customScriptView = null
) {
$this->columns = $columns;
$this->rows = $rows;
$this->filters = $filters;
$this->sort = $sort;
$this->pagination = $pagination;
$this->query = $query;
$this->perPageOptions = $perPageOptions;
$this->sortableColumns = $sortableColumns;
$this->basePath = $basePath;
$this->emptyMessage = $emptyMessage;
$this->createUrl = $createUrl;
$this->createLabel = $createLabel;
$this->customScriptView = $customScriptView;
}
}
?>

View File

@@ -0,0 +1,73 @@
<?php
namespace admin\ViewModels\Forms;
/**
* Definicja akcji formularza (przycisku)
*/
class FormAction
{
public string $name;
public string $label;
public string $type;
public string $url;
public ?string $backUrl;
public string $cssClass;
public array $attributes;
/**
* @param string $name Nazwa akcji (save, cancel, delete)
* @param string $label Etykieta przycisku
* @param string $url URL akcji (dla save)
* @param string|null $backUrl URL powrotu po zapisie
* @param string $cssClass Klasy CSS przycisku
* @param string $type Typ przycisku (submit, button, link)
* @param array $attributes Dodatkowe atrybuty HTML
*/
public function __construct(
string $name,
string $label,
string $url = '',
?string $backUrl = null,
string $cssClass = 'btn btn-primary',
string $type = 'submit',
array $attributes = []
) {
$this->name = $name;
$this->label = $label;
$this->url = $url;
$this->backUrl = $backUrl;
$this->cssClass = $cssClass;
$this->type = $type;
$this->attributes = $attributes;
}
/**
* Predefiniowana akcja Zapisz
*/
public static function save(string $url, string $backUrl = '', string $label = 'Zapisz'): self
{
return new self(
'save',
$label,
$url,
$backUrl,
'btn btn-primary',
'submit'
);
}
/**
* Predefiniowana akcja Anuluj
*/
public static function cancel(string $backUrl, string $label = 'Anuluj'): self
{
return new self(
'cancel',
$label,
$backUrl,
null,
'btn btn-default',
'link'
);
}
}

View File

@@ -0,0 +1,178 @@
<?php
namespace admin\ViewModels\Forms;
/**
* Główny model widoku formularza edycji
*/
class FormEditViewModel
{
public string $formId;
public string $title;
public string $method;
public string $action;
public ?string $backUrl;
public array $tabs;
public array $fields;
public array $hiddenFields;
public array $actions;
public bool $persist;
public array $data;
public ?array $validationErrors;
public ?array $languages;
/**
* @param string $formId Unikalny identyfikator formularza
* @param string $title Tytuł formularza
* @param array $data Dane obiektu (np. banner)
* @param array $fields Pola formularza
* @param array $tabs Zakładki formularza
* @param array $actions Akcje (przyciski)
* @param string $method Metoda HTTP (POST, GET)
* @param string $action URL akcji formularza
* @param string|null $backUrl URL powrotu
* @param bool $persist Czy zapamiętywać dane w sesji
* @param array $hiddenFields Dodatkowe ukryte pola
* @param array|null $languages Dostępne języki (dla sekcji językowych)
* @param array|null $validationErrors Błędy walidacji
*/
public function __construct(
string $formId,
string $title,
array $data = [],
array $fields = [],
array $tabs = [],
array $actions = [],
string $method = 'POST',
string $action = '',
?string $backUrl = null,
bool $persist = true,
array $hiddenFields = [],
?array $languages = null,
?array $validationErrors = null
) {
$this->formId = $formId;
$this->title = $title;
$this->data = $data;
$this->fields = $fields;
$this->tabs = $tabs;
$this->actions = $actions;
$this->method = $method;
$this->action = $action;
$this->backUrl = $backUrl;
$this->persist = $persist;
$this->hiddenFields = $hiddenFields;
$this->languages = $languages;
$this->validationErrors = $validationErrors;
}
/**
* Sprawdza czy formularz ma zakładki
*/
public function hasTabs(): bool
{
return count($this->tabs) > 0;
}
/**
* Sprawdza czy formularz ma sekcje językowe
*/
public function hasLangSections(): bool
{
foreach ($this->fields as $field) {
if ($field->type === FormFieldType::LANG_SECTION) {
return true;
}
}
return false;
}
/**
* Zwraca pola dla konkretnej zakładki
*/
public function getFieldsForTab(string $tabId): array
{
return array_filter($this->fields, function (FormField $field) use ($tabId) {
return $field->tabId === $tabId && $field->type !== FormFieldType::LANG_SECTION;
});
}
/**
* Zwraca sekcje językowe dla konkretnej zakładki
*/
public function getLangSectionsForTab(string $tabId): array
{
return array_filter($this->fields, function (FormField $field) use ($tabId) {
return $field->type === FormFieldType::LANG_SECTION &&
$field->langSectionParentTab === $tabId;
});
}
/**
* Pobiera wartość pola z danych lub sesji (persist)
*/
public function getFieldValue(FormField $field, $languageId = null, ?string $langFieldName = null)
{
$fieldName = $field->name;
// Dla sekcji językowych - pobierz wartość z data[lang_id][field_name]
if ($languageId !== null && $langFieldName !== null) {
$fieldName = $langFieldName;
return $this->data['languages'][$languageId][$fieldName] ?? null;
}
// Zwykłe pole - najpierw sprawdź sesję (persist), potem dane
if ($this->persist && isset($_SESSION['form_persist'][$this->formId][$fieldName])) {
return $_SESSION['form_persist'][$this->formId][$fieldName];
}
return $this->data[$fieldName] ?? $field->value;
}
/**
* Sprawdza czy pole ma błąd walidacji
*/
public function hasError(string $fieldName, $languageId = null): bool
{
if ($this->validationErrors === null) {
return false;
}
if ($languageId !== null) {
return isset($this->validationErrors[$fieldName][$languageId]);
}
return isset($this->validationErrors[$fieldName]);
}
/**
* Pobiera komunikat błędu dla pola
*/
public function getError(string $fieldName, $languageId = null): ?string
{
if ($languageId !== null) {
return $this->validationErrors[$fieldName][$languageId] ?? null;
}
return $this->validationErrors[$fieldName] ?? null;
}
/**
* Czyści dane persist z sesji
*/
public function clearPersist(): void
{
if (isset($_SESSION['form_persist'][$this->formId])) {
unset($_SESSION['form_persist'][$this->formId]);
}
}
/**
* Zapisuje dane do sesji (persist)
*/
public function saveToPersist(array $data): void
{
if (!isset($_SESSION['form_persist'])) {
$_SESSION['form_persist'] = [];
}
$_SESSION['form_persist'][$this->formId] = $data;
}
}

View File

@@ -0,0 +1,364 @@
<?php
namespace admin\ViewModels\Forms;
/**
* Definicja pojedynczego pola formularza
*/
class FormField
{
public string $name;
public string $type;
public string $label;
public $value;
public string $tabId;
public bool $required;
public array $attributes;
public array $options;
public ?string $helpText;
public ?string $placeholder;
public ?string $id;
// Specyficzne dla obrazów/plików
public bool $useFilemanager;
public ?string $filemanagerUrl;
// Specyficzne dla edytora
public string $editorToolbar;
public int $editorHeight;
// Specyficzne dla lang_section
public ?array $langFields;
public ?string $langSectionParentTab;
public ?string $customHtml;
/**
* @param string $name Nazwa pola (name)
* @param string $type Typ pola (z FormFieldType)
* @param string $label Etykieta pola
* @param mixed $value Wartość domyślna
* @param string $tabId Identyfikator zakładki
* @param bool $required Czy pole wymagane
* @param array $attributes Atrybuty HTML
* @param array $options Opcje dla select
* @param string|null $helpText Tekst pomocniczy
* @param string|null $placeholder Placeholder
* @param bool $useFilemanager Czy używać filemanagera
* @param string|null $filemanagerUrl URL filemanagera
* @param string $editorToolbar Konfiguracja toolbar CKEditor
* @param int $editorHeight Wysokość edytora
* @param array|null $langFields Pola w sekcji językowej
* @param string|null $langSectionParentTab Zakładka nadrzędna dla sekcji językowej
*/
public function __construct(
string $name,
string $type = FormFieldType::TEXT,
string $label = '',
$value = null,
string $tabId = 'default',
bool $required = false,
array $attributes = [],
array $options = [],
?string $helpText = null,
?string $placeholder = null,
bool $useFilemanager = false,
?string $filemanagerUrl = null,
string $editorToolbar = 'MyTool',
int $editorHeight = 300,
?array $langFields = null,
?string $langSectionParentTab = null,
?string $customHtml = null
) {
$this->name = $name;
$this->type = $type;
$this->label = $label;
$this->value = $value;
$this->tabId = $tabId;
$this->required = $required;
$this->attributes = $attributes;
$this->options = $options;
$this->helpText = $helpText;
$this->placeholder = $placeholder;
$this->useFilemanager = $useFilemanager;
$this->filemanagerUrl = $filemanagerUrl;
$this->editorToolbar = $editorToolbar;
$this->editorHeight = $editorHeight;
$this->langFields = $langFields;
$this->langSectionParentTab = $langSectionParentTab;
$this->customHtml = $customHtml;
$this->id = $attributes['id'] ?? $name;
}
// Factory methods dla różnych typów pól
public static function text(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::TEXT,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? [],
[],
$config['help'] ?? null,
$config['placeholder'] ?? null
);
}
public static function number(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::NUMBER,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? [],
[],
$config['help'] ?? null
);
}
public static function email(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::EMAIL,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? []
);
}
public static function password(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::PASSWORD,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? []
);
}
public static function date(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::DATE,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
array_merge(['class' => 'date'], $config['attributes'] ?? [])
);
}
public static function datetime(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::DATETIME,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
array_merge(['class' => 'datetime'], $config['attributes'] ?? [])
);
}
public static function switch(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::SWITCH,
$config['label'] ?? '',
$config['value'] ?? false,
$config['tab'] ?? 'default',
false,
$config['attributes'] ?? []
);
}
public static function select(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::SELECT,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? [],
$config['options'] ?? []
);
}
public static function textarea(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::TEXTAREA,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
array_merge(['rows' => $config['rows'] ?? 4], $config['attributes'] ?? [])
);
}
public static function editor(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::EDITOR,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? [],
[],
null,
null,
false,
null,
$config['toolbar'] ?? 'MyTool',
$config['height'] ?? 300
);
}
public static function image(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::IMAGE,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? [],
[],
null,
null,
$config['filemanager'] ?? true,
$config['filemanager_url'] ?? null
);
}
public static function file(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::FILE,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? [],
[],
null,
null,
$config['filemanager'] ?? true
);
}
public static function color(string $name, array $config = []): self
{
return new self(
$name,
FormFieldType::COLOR,
$config['label'] ?? '',
$config['value'] ?? null,
$config['tab'] ?? 'default',
$config['required'] ?? false,
$config['attributes'] ?? [],
[],
$config['help'] ?? null
);
}
public static function hidden(string $name, $value = null): self
{
return new self(
$name,
FormFieldType::HIDDEN,
'',
$value,
'default'
);
}
public static function custom(string $name, string $html, array $config = []): self
{
return new self(
$name,
FormFieldType::CUSTOM,
$config['label'] ?? '',
null,
$config['tab'] ?? 'default',
false,
$config['attributes'] ?? [],
[],
null,
null,
false,
null,
'MyTool',
300,
null,
null,
$html
);
}
/**
* Sekcja językowa - grupa pól powtarzana dla każdego języka
*
* @param string $name Nazwa sekcji (prefiks dla pól)
* @param string $parentTab Identyfikator zakładki nadrzędnej
* @param array $fields Pola w sekcji językowej (tablica FormField)
*/
public static function langSection(string $name, string $parentTab, array $fields): self
{
return new self(
$name,
FormFieldType::LANG_SECTION,
'',
null,
$parentTab,
false,
[],
[],
null,
null,
false,
null,
'MyTool',
300,
$fields,
$parentTab
);
}
/**
* Zwraca nazwę pola z sufiksem dla konkretnego języka
*/
public function getLocalizedName($languageId): string
{
return "{$this->name}[{$languageId}]";
}
/**
* Zwraca ID pola z sufiksem dla konkretnego języka
*/
public function getLocalizedId($languageId): string
{
return "{$this->id}_{$languageId}";
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace admin\ViewModels\Forms;
/**
* Dostępne typy pól formularza
*/
class FormFieldType
{
public const TEXT = 'text';
public const NUMBER = 'number';
public const EMAIL = 'email';
public const PASSWORD = 'password';
public const DATE = 'date';
public const DATETIME = 'datetime';
public const SWITCH = 'switch';
public const SELECT = 'select';
public const TEXTAREA = 'textarea';
public const EDITOR = 'editor';
public const IMAGE = 'image';
public const FILE = 'file';
public const HIDDEN = 'hidden';
public const LANG_SECTION = 'lang_section';
public const CUSTOM = 'custom';
public const COLOR = 'color';
}

View File

@@ -0,0 +1,31 @@
<?php
namespace admin\ViewModels\Forms;
/**
* Definicja zakładki formularza
*/
class FormTab
{
public string $id;
public string $label;
public string $icon;
public ?string $parentTabId;
/**
* @param string $id Unikalny identyfikator zakładki
* @param string $label Etykieta wyświetlana
* @param string $icon Klasa FontAwesome (np. 'fa-wrench')
* @param string|null $parentTabId Identyfikator zakładki nadrzędnej (dla zagnieżdżenia)
*/
public function __construct(
string $id,
string $label,
string $icon = '',
?string $parentTabId = null
) {
$this->id = $id;
$this->label = $label;
$this->icon = $icon;
$this->parentTabId = $parentTabId;
}
}

View File

@@ -1,229 +0,0 @@
<?php
namespace admin;
class Site
{
// define APP_SECRET_KEY
const APP_SECRET_KEY = 'c3cb2537d25c0efc9e573d059d79c3b8';
static public function finalize_admin_login( array $user, string $domain, string $cookie_name, bool $remember = false ) {
\S::set_session( 'user', $user );
\S::delete_session( 'twofa_pending' );
if ( $remember ) {
$payloadArr = [
'login' => $user['login'],
'ts' => time()
];
$json = json_encode($payloadArr, JSON_UNESCAPED_SLASHES);
$sig = hash_hmac('sha256', $json, self::APP_SECRET_KEY);
$payload = base64_encode($json . '.' . $sig);
setcookie( $cookie_name, $payload, [
'expires' => time() + (86400 * 14),
'path' => '/',
'domain' => $domain,
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
}
}
public static function special_actions()
{
$sa = \S::get('s-action');
$domain = preg_replace('/^www\./', '', $_SERVER['SERVER_NAME']);
$cookie_name = 'admin_remember_' . str_replace( '.', '-', $domain );
switch ($sa)
{
case 'user-logon':
{
$login = \S::get('login');
$pass = \S::get('password');
$result = \admin\factory\Users::logon($login, $pass);
if ( $result == 1 )
{
$user = \admin\factory\Users::details($login);
if ( $user['twofa_enabled'] == 1 )
{
\S::set_session( 'twofa_pending', [
'uid' => (int)$user['id'],
'login' => $login,
'remember' => (bool)\S::get('remember'),
'started' => time(),
] );
if ( !\admin\factory\Users::send_twofa_code( (int)$user['id'] ) )
{
\S::alert('Nie udało się wysłać kodu 2FA. Spróbuj ponownie.');
\S::delete_session('twofa_pending');
header('Location: /admin/');
exit;
}
header('Location: /admin/user/twofa/');
exit;
}
else
{
$user = \admin\factory\Users::details($login);
self::finalize_admin_login(
$user,
$domain,
$cookie_name,
(bool)\S::get('remember')
);
header('Location: /admin/articles/view_list/');
exit;
}
}
else
{
if ($result == -1)
{
\S::alert('Z powodu 5 nieudanych prób Twoje konto zostało zablokowane.');
}
else
{
\S::alert('Podane hasło jest nieprawidłowe lub użytkownik nie istnieje.');
}
header('Location: /admin/');
exit;
}
}
break;
case 'user-2fa-verify':
{
$pending = \S::get_session('twofa_pending');
if ( !$pending || empty( $pending['uid'] ) ) {
\S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.');
header('Location: /admin/');
exit;
}
$code = trim((string)\S::get('twofa'));
if (!preg_match('/^\d{6}$/', $code))
{
\S::alert('Nieprawidłowy format kodu.');
header('Location: /admin/user/twofa/');
exit;
}
$ok = \admin\factory\Users::verify_twofa_code((int)$pending['uid'], $code);
if (!$ok)
{
\S::alert('Błędny lub wygasły kod.');
header('Location: /admin/user/twofa/');
exit;
}
// 2FA OK — finalna sesja
$user = \admin\factory\Users::details($pending['login']);
self::finalize_admin_login(
$user,
$domain,
$cookie_name,
$pending['remember'] ? true : false
);
header('Location: /admin/articles/view_list/');
exit;
}
break;
case 'user-2fa-resend':
{
$pending = \S::get_session('twofa_pending');
if (!$pending || empty($pending['uid']))
{
\S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.');
header('Location: /admin/');
exit;
}
if (!\admin\factory\Users::send_twofa_code((int)$pending['uid'], true))
{
\S::alert('Kod można wysłać ponownie po krótkiej przerwie.');
}
else
{
\S::alert('Nowy kod został wysłany.');
}
header('Location: /admin/user/twofa/');
exit;
}
break;
case 'user-logout':
{
setcookie($cookie_name, "", [
'expires' => time() - 86400,
'path' => '/',
'domain' => $domain,
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
\S::delete_session('twofa_pending');
session_destroy();
header('Location: /admin/');
exit;
}
break;
}
}
public static function route()
{
$_SESSION['admin'] = true;
if ( \S::get( 'p' ) )
\S::set_session( 'p' , \S::get( 'p' ) );
$page = \S::get_session( 'p' );
$class = '\admin\controls\\';
$results = explode( '_', \S::get( 'module' ) );
if ( is_array( $results ) ) foreach ( $results as $row )
$class .= ucfirst( $row );
$action = \S::get( 'action' );
if ( class_exists( $class ) and method_exists( new $class, $action ) )
return call_user_func_array( array( $class, $action ), array() );
else
{
\S::alert( 'Nieprawidłowy adres url.' );
return false;
}
}
static public function update()
{
global $mdb;
if ( $results = $mdb -> select( 'pp_updates', [ 'name' ], [ 'done' => 0 ] ) )
{
foreach ( $results as $row )
{
$class = '\admin\factory\Update';
$method = $row['name'];
if ( class_exists( $class ) and method_exists( new $class, $method ) )
call_user_func_array( array( $class, $method ), array() );
}
}
}
}

View File

@@ -1,25 +0,0 @@
<?
namespace admin\controls;
class Archive {
static public function products_list() {
$current_page = \S::get_session( 'archive_products_list_current_page' );
if ( !$current_page ) {
$current_page = 1;
\S::set_session( 'archive_products_list_current_page', $current_page );
}
$query = \S::get_session( 'archive_products_list_query' );
if ( $query ) {
$query_array = [];
parse_str( $query, $query_array );
}
return \Tpl::view( 'archive/products-list', [
'current_page' => $current_page,
'query_array' => $query_array,
'pagination_max' => ceil( \admin\factory\ShopProduct::count_product() / 10 )
] );
}
}

View File

@@ -1,67 +0,0 @@
<?php
namespace admin\controls;
class Articles
{
public static function gallery_order_save()
{
if ( \admin\factory\Articles::gallery_order_save( \S::get( 'article_id' ), \S::get( 'order' ) ) )
echo json_encode( [ 'status' => 'ok', 'msg' => 'Artykuł został zapisany.' ] );
exit;
}
public static function browse_list()
{
return \admin\view\Articles::browse_list();
}
public static function article_delete()
{
if ( \admin\factory\Articles::articles_set_archive( \S::get( 'id' ) ) )
\S::alert( 'Artykuł został przeniesiony do archiwum.' );
header( 'Location: /admin/articles/view_list/' );
exit;
}
public static function article_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania artykułu wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\Articles::article_save(
$values['id'], $values['title'], $values['main_image'], $values['entry'], $values['text'], $values['table_of_contents'], $values['status'], $values['show_title'], $values['show_table_of_contents'], $values['show_date_add'], $values['date_add'], $values['show_date_modify'], $values['date_modify'], $values['seo_link'], $values['meta_title'],
$values['meta_description'], $values['meta_keywords'], $values['layout_id'], $values['pages'], $values['noindex'], $values['repeat_entry'], $values['copy_from'], $values['social_icons'], $values['block_direct_access']
) )
$response = [ 'status' => 'ok', 'msg' => 'Artykuł został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function article_edit() {
global $user;
if ( !$user ) {
header( 'Location: /admin/' );
exit;
}
\admin\factory\Articles::delete_nonassigned_images();
\admin\factory\Articles::delete_nonassigned_files();
return \Tpl::view( 'articles/article-edit', [
'article' => \admin\factory\Articles::article_details( (int)\S::get( 'id' ) ),
'menus' => \admin\factory\Pages::menus_list(),
'languages' => \admin\factory\Languages::languages_list(),
'layouts' => \admin\factory\Layouts::layouts_list(),
'user' => $user
] );
}
public static function view_list()
{
return \admin\view\Articles::articles_list();
}
}
?>

View File

@@ -1,26 +0,0 @@
<?php
namespace admin\controls;
class ArticlesArchive
{
public static function article_restore()
{
if ( \admin\factory\ArticlesArchive::article_restore( \S::get( 'id' ) ) )
\S::alert( 'Artykuł został przywrócony.' );
header( 'Location: /admin/articles_archive/view_list/' );
exit;
}
public static function article_delete()
{
if ( \admin\factory\ArticlesArchive::article_delete( \S::get( 'id' ) ) )
\S::alert( 'Artykuł został usunięty.' );
header( 'Location: /admin/articles_archive/view_list/' );
exit;
}
public static function view_list()
{
return \admin\view\ArticlesArchive::articles_list();
}
}

View File

@@ -1,43 +0,0 @@
<?php
namespace admin\controls;
class Banners
{
public static function banner_delete()
{
if ( \admin\factory\Banners::banner_delete( \S::get( 'id' ) ) )
\S::alert( 'Baner został usunięty.' );
header( 'Location: /admin/banners/view_list/' );
exit;
}
public static function banner_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania baneru wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $banner_id = \admin\factory\Banners::banner_save( $values['id'], $values['name'], $values['status'], $values['date_start'], $values['date_end'],
$values['home_page'], $values['src'], $values['url'], $values['html'], $values['text'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Baner został zapisany.', 'id' => $banner_id ];
echo json_encode( $response );
exit;
}
public static function banner_edit()
{
return \admin\view\Banners::banner_edit(
\admin\factory\Banners::banner_details(
\S::get( 'id' )
),
\admin\factory\Languages::languages_list()
);
}
public static function view_list()
{
return \admin\view\Banners::banners_list();
}
}
?>

View File

@@ -1,20 +0,0 @@
<?php
namespace admin\controls;
class Baselinker {
// widok wiązania produktów
static public function bundling_products() {
return \Tpl::view( 'baselinker/bundling-products', [
'products' => \admin\factory\ShopProduct::products_list_for_baselinker(),
'baselinker_products' => \admin\factory\Baselinker::products_list()
] );
}
// zapis wiązania produktów
static public function bundling_products_save() {
\admin\factory\Baselinker::bundling_products_save( $_POST );
header( 'Location: /admin/baselinker/bundling_products/' );
exit;
}
}

View File

@@ -1,18 +0,0 @@
<?
namespace admin\controls;
class Dashboard
{
static public function main_view()
{
return \Tpl::view( 'dashboard/main-view', [
'last_orders' => \shop\Dashboard::last_orders(),
'order_statuses' => \shop\Order::order_statuses(),
'sales' => \shop\Dashboard::last_24_months_sales(),
'best_sales_products' => \shop\Dashboard::best_sales_products(),
'most_view_products' => \shop\Dashboard::most_view_products(),
'sales_grid' => \shop\Dashboard::sales_grid(),
'summary_sales' => \shop\Dashboard::summary_sales(),
'summary_orders' => \shop\Dashboard::summary_orders(),
] );
}
}

View File

@@ -1,39 +0,0 @@
<?php
namespace admin\controls;
class Dictionaries {
public static function view_list()
{
return \Tpl::view( 'dictionaries/units-list' );
}
public static function unit_edit()
{
return \Tpl::view( 'dictionaries/unit-edit', [
'unit' => \admin\factory\Dictionaries::unit_details( \S::get( 'id' )),
'languages' => \admin\factory\Languages::languages_list(),
] );
}
static public function unit_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania jednostki miary wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\Dictionaries::unit_save( $values['id'], $values['text']) )
$response = [ 'status' => 'ok', 'msg' => 'Jednostka miary została zapisana.', 'id' => $id ];
echo json_encode( $response );
exit;
}
static public function unit_delete()
{
if ( \admin\factory\Dictionaries::unit_delete( \S::get( 'id' ) ) )
\S::alert( 'Jesdnostka miary została usunięta.' );
header( 'Location: /admin/dictionaries/view_list/' );
exit;
}
}

View File

@@ -1,11 +0,0 @@
<?php
namespace admin\controls;
class Filemanager
{
static public function draw()
{
return \Tpl::view( 'filemanager/filemanager' );
}
}
?>

View File

@@ -1,846 +0,0 @@
<?
namespace admin\controls;
class Integrations {
// apilo_create_product
static public function apilo_create_product()
{
global $mdb, $settings;
$access_token = \admin\factory\Integrations::apilo_get_access_token();
$product_id = \S::get( 'product_id' );
$product = new \shop\Product( $product_id );
$methodParams = [
"sku" => $product -> sku,
"ean" => $product -> ean,
"name" => $product -> language['name'],
"tax" => (int) $product -> vat,
'status' => 1,
"quantity" => (int) $product -> quantity,
"priceWithTax" => $product -> price_brutto,
'description' => $product -> language['description'] . '<br>' . $product -> language['short_description'],
'shortDescription' => '',
'images' => []
];
foreach ($product->images as $image) {
$methodParams["images"][] = "https://" . $_SERVER['HTTP_HOST'] . $image['src'];
}
$ch = curl_init( "https://projectpro.apilo.com/rest/api/warehouse/product/" );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( [ $methodParams ] ) );
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $access_token,
"Content-Type: application/json",
"Accept: application/json"
] );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
{
\S::alert( 'Błąd cURL: ' . curl_error( $ch ) );
}
else
{
if ( $responseData['products'] )
{
$mdb -> update( 'pp_shop_products', [ 'apilo_product_id' => reset( $responseData['products'] ), 'apilo_product_name' => $product->language['name'] ], [ 'id' => $product -> id ] );
}
\S::alert( 'Produkt został dodany do magazynu APILO.' );
}
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
// baselinker_create_product
static public function baselinker_create_product()
{
global $mdb, $settings;
$api_code = \admin\factory\Integrations::baselinker_settings( 'api_code' );
$product_id = \S::get( 'product_id' );
$product = \shop\Product::getFromCache( $product_id, 'pl' );
$methodParams = [
"storage_id" => \admin\factory\Integrations::baselinker_settings('storage_id'),
"ean" => $product->ean,
"sku" => $product->sku,
"name" => $product->language['name'],
"quantity" => "0",
"price_brutto" => $product->price_brutto,
"tax_rate" => $product->vat,
"description" => $product->language['short_description'],
"description_extra1" => $product->language['description'],
"images" => []
];
foreach ($product->images as $image) {
$methodParams["images"][] = "url:https://" . $_SERVER['HTTP_HOST'] . $image['src'];
}
$methodParams = json_encode( $methodParams, JSON_UNESCAPED_SLASHES );
$apiParams = [
"token" => $api_code,
"method" => "addProduct",
"parameters" => $methodParams
];
$curl = curl_init( "https://api.baselinker.com/connector.php" );
curl_setopt( $curl, CURLOPT_POST, 1 );
curl_setopt( $curl, CURLOPT_POSTFIELDS, http_build_query( $apiParams ) );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
$response = json_decode( curl_exec( $curl ), true );
if ( $response['status'] == 'SUCCESS' )
{
if ( $response['product_id'] )
{
$mdb -> update( 'pp_shop_products', [ 'baselinker_product_id' => $response['product_id'], 'baselinker_product_name' => $product->language['name'] ], [ 'id' => $product -> id ] );
}
\S::alert( 'Produkt został dodany do magazynu Baselinker.' );
}
else
{
\S::alert( 'Podczas dodawania produktu wystąpił błąd.' );
}
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
// baselinker pobierz listę magazynów
static public function baselinker_get_storages_list()
{
global $mdb, $settings;
$api_code = \admin\factory\Integrations::baselinker_settings( 'api_code' );
$methodParams = '{
"storage_id": "bl_1"
}';
$apiParams = [
"token" => $api_code,
"method" => "getStoragesList",
"parameters" => $methodParams
];
$curl = curl_init( "https://api.baselinker.com/connector.php" );
curl_setopt( $curl, CURLOPT_POST, 1 );
curl_setopt( $curl, CURLOPT_POSTFIELDS, http_build_query( $apiParams ) );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
$response = json_decode( curl_exec( $curl ), true );
if ( $response['status'] == 'SUCCESS' )
{
\admin\factory\Integrations::baselinker_settings_save( 'storages_list', $response['storages'] );
\S::alert( 'Lista magazynów została pobrana.' );
}
else
{
\S::alert( 'Brak wyników.' );
}
header( 'Location: /admin/integrations/baselinker_settings/' );
exit;
}
// baselinker_get_order_status_list
static public function baselinker_get_order_status_list()
{
global $mdb, $settings;
$api_code = \admin\factory\Integrations::baselinker_settings( 'api_code' );
$apiParams = [
"token" => $api_code,
"method" => "getOrderStatusList",
"parameters" => []
];
$curl = curl_init( "https://api.baselinker.com/connector.php" );
curl_setopt( $curl, CURLOPT_POST, 1 );
curl_setopt( $curl, CURLOPT_POSTFIELDS, http_build_query( $apiParams ) );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
$response = json_decode( curl_exec( $curl ), true );
if ( $response['status'] == 'SUCCESS' )
{
\admin\factory\Integrations::baselinker_settings_save( 'order_status_list', $response['statuses'] );
\S::alert( 'Lista statusów została pobrana.' );
}
else
{
\S::alert( 'Brak wyników.' );
}
header( 'Location: /admin/integrations/baselinker_settings/' );
exit;
}
// get_sellasist_carriers_list
static public function get_sellasist_shipments_list()
{
$api_code = \admin\factory\Integrations::sellasist_settings( 'api_code' );
$ch = curl_init( "https://projectpro.sellasist.pl/api/v1/shipments" );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"apiKey: " . $api_code,
"accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
\S::alert( 'Błąd cURL: ' . curl_error( $ch ) );
else {
if ( $responseData ) {
\admin\factory\Integrations::sellasist_settings_save( 'shipments_methods', $responseData );
\S::alert( 'Lista przewoźników została pobrana.' );
} else
\S::alert( 'Brak wyników.' );
}
header( 'Location: /admin/integrations/sellasist_settings/' );
exit;
}
// get_sellasist_payment_types_list
static public function get_sellasist_payment_types_list()
{
$api_code = \admin\factory\Integrations::sellasist_settings( 'api_code' );
$ch = curl_init( "https://projectpro.sellasist.pl/api/v1/payments" );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"apiKey: " . $api_code,
"accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
\S::alert( 'Błąd cURL: ' . curl_error( $ch ) );
else {
if ( $responseData ) {
\admin\factory\Integrations::sellasist_settings_save( 'payment_types_list', $responseData );
\S::alert( 'Lista metod płatności została pobrana.' );
} else
\S::alert( 'Brak wyników.' );
}
header( 'Location: /admin/integrations/sellasist_settings/' );
exit;
}
static public function get_sellasist_status_types_list()
{
$api_code = \admin\factory\Integrations::sellasist_settings( 'api_code' );
$ch = curl_init( "https://projectpro.sellasist.pl/api/v1/statuses" );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"apiKey: " . $api_code,
"accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
\S::alert( 'Błąd cURL: ' . curl_error( $ch ) );
else {
if ( $responseData ) {
\admin\factory\Integrations::sellasist_settings_save( 'status_types_list', $responseData );
\S::alert( 'Lista statusów została pobrana.' );
} else
\S::alert( 'Brak wyników.' );
}
header( 'Location: /admin/integrations/sellasist_settings/' );
exit;
}
// get_platform_list
static public function get_platform_list()
{
global $mdb, $settings;
$access_token = \admin\factory\Integrations::apilo_get_access_token();
$url = "https://projectpro.apilo.com/rest/api/orders/platform/map/";
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $access_token,
"Accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
{
\S::alert( 'Błąd cURL: ' . curl_error( $ch ) );
}
else
{
if ( $responseData )
{
\admin\factory\Integrations::apilo_settings_save( 'platform-list', $responseData );
\S::alert( 'Lista platform została pobrana.' );
}
else
{
\S::alert( 'Brak wyników.' );
}
}
header( 'Location: /admin/integrations/apilo_settings/' );
exit;
}
// get_status_types_list
static public function get_status_types_list()
{
global $mdb, $settings;
$access_token = \admin\factory\Integrations::apilo_get_access_token();
$url = "https://projectpro.apilo.com/rest/api/orders/status/map/";
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $access_token,
"Accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
{
\S::alert( 'Błąd cURL: ' . curl_error( $ch ) );
}
else
{
if ( $responseData )
{
\admin\factory\Integrations::apilo_settings_save( 'status-types-list', $responseData );
\S::alert( 'Lista statusów została pobrana.' );
}
else
{
\S::alert( 'Brak wyników.' );
}
}
header( 'Location: /admin/integrations/apilo_settings/' );
exit;
}
// get_carrier_account_list
static public function get_carrier_account_list()
{
global $mdb, $settings;
$access_token = \admin\factory\Integrations::apilo_get_access_token();
$url = "https://projectpro.apilo.com/rest/api/orders/carrier-account/map/";
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $access_token,
"Accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
{
\S::alert( 'Błąd cURL: ' . curl_error( $ch ) );
}
else
{
if ( $responseData )
{
\admin\factory\Integrations::apilo_settings_save( 'carrier-account-list', $responseData );
\S::alert( 'Lista kont przewoźników została pobrana.' );
}
else
{
\S::alert( 'Brak wyników.' );
}
}
header( 'Location: /admin/integrations/apilo_settings/' );
exit;
}
// get_payment_types_list
static public function get_payment_types_list()
{
global $mdb, $settings;
$access_token = \admin\factory\Integrations::apilo_get_access_token();
$url = "https://projectpro.apilo.com/rest/api/orders/payment/map/";
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $access_token,
"Accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
{
\S::alert( 'Błąd cURL: ' . curl_error( $ch ) );
}
else
{
if ( $responseData )
{
\admin\factory\Integrations::apilo_settings_save( 'payment-types-list', $responseData );
\S::alert( 'Lista metod płatności została pobrana.' );
}
else
{
\S::alert( 'Brak wyników.' );
}
}
header( 'Location: /admin/integrations/apilo_settings/' );
exit;
}
// settings for the sellasist integration
static public function sellasist_settings()
{
return \Tpl::view( 'integrations/sellasist-settings', [
'settings' => \admin\factory\Integrations::sellasist_settings(),
] );
}
// settings for the Baselinker integration
static public function baselinker_settings()
{
return \Tpl::view( 'integrations/baselinker-settings', [
'settings' => \admin\factory\Integrations::baselinker_settings(),
] );
}
// settings for shoppro
static public function shoppro_settings()
{
return \Tpl::view( 'integrations/shoppro-settings', [
'settings' => \admin\factory\Integrations::shoppro_settings(),
] );
}
// Settings for the APILO plugin
static public function apilo_settings()
{
return \Tpl::view( 'integrations/apilo-settings', [
'settings' => \admin\factory\Integrations::apilo_settings(),
] );
}
// save settings for the shoppro integration
static public function shoppro_settings_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania ustawień wystąpił błąd. Proszę spróbować ponownie.' ];
$field_id = \S::get( 'field_id' );
$value = \S::get( 'value' );
if ( \admin\factory\Integrations::shoppro_settings_save( $field_id, $value ) )
$response = [ 'status' => 'ok', 'msg' => 'Ustawienia zostały zapisane.', 'value' => $value ];
echo json_encode( $response );
exit;
}
// save settings for the sellasist integration
static public function sellasist_settings_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania ustawień wystąpił błąd. Proszę spróbować ponownie.' ];
$field_id = \S::get( 'field_id' );
$value = \S::get( 'value' );
if ( \admin\factory\Integrations::sellasist_settings_save( $field_id, $value ) )
$response = [ 'status' => 'ok', 'msg' => 'Ustawienia zostały zapisane.', 'value' => $value ];
echo json_encode( $response );
exit;
}
// save settings for the Baselinker integration
static public function baselinker_settings_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania ustawień wystąpił błąd. Proszę spróbować ponownie.' ];
$field_id = \S::get( 'field_id' );
$value = \S::get( 'value' );
if ( \admin\factory\Integrations::baselinker_settings_save( $field_id, $value ) )
$response = [ 'status' => 'ok', 'msg' => 'Ustawienia zostały zapisane.', 'value' => $value ];
echo json_encode( $response );
exit;
}
// Save settings for the APILO plugin
static public function apilo_settings_save() {
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania ustawień wystąpił błąd. Proszę spróbować ponownie.' ];
$field_id = \S::get( 'field_id' );
$value = \S::get( 'value' );
if ( \admin\factory\Integrations::apilo_settings_save( $field_id, $value ) )
$response = [ 'status' => 'ok', 'msg' => 'Ustawienia zostały zapisane.', 'value' => $value ];
echo json_encode( $response );
exit;
}
// Authorization in apilo.com
static public function apilo_authorization() {
$response = [ 'status' => 'error', 'msg' => 'Podczas autoryzacji wystąpił błąd. Proszę spróbować ponownie.' ];
$settings = \admin\factory\Integrations::apilo_settings();
if ( \admin\factory\Integrations::apilo_authorization( $settings['client-id'], $settings['client-secret'], $settings['authorization-code'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Autoryzacja przebiegła pomyślnie.' ];
echo json_encode( $response );
exit;
}
// sellasist product search by sku
static public function sellasist_product_search() {
global $mdb, $settings;
$sku = $mdb -> get( 'pp_shop_products', 'sku', [ 'id' => \S::get( 'product_id' ) ] );
if ( !$sku ) {
echo json_encode( [ 'status' => 'error', 'msg' => 'Podany produkt nie posiada kodu SKU.' ] );
exit;
}
$url = "https://projectpro.sellasist.pl/api/v1/products";
$params['symbol '] = $sku;
$url .= '?' . http_build_query( $params );
$api_code = \admin\factory\Integrations::sellasist_settings( 'api_code' );
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"apiKey: " . $api_code,
"accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) )
{
echo 'Błąd cURL: ' . curl_error( $ch );
}
else
{
if ( $responseData['error'] )
{
echo json_encode( [ 'status' => 'error', 'msg' => 'Brak wyników dla podanego SKU.' ] );
exit;
}
else
{
$return_data = array();
$return_data['status'] = 'SUCCESS';
$return_data['products'] = $responseData;
echo json_encode( $return_data );
exit;
}
}
echo json_encode( [ 'status' => 'error', 'msg' => 'Brak wyników dla podanego SKU.' ] );
exit;
}
// apilo product search by sku
static public function apilo_product_search() {
global $mdb, $settings;
$sku = $mdb -> get( 'pp_shop_products', 'sku', [ 'id' => \S::get( 'product_id' ) ] );
if ( !$sku ) {
echo json_encode( [ 'status' => 'error', 'msg' => 'Podany produkt nie posiada kodu SKU.' ] );
exit;
}
$access_token = \admin\factory\Integrations::apilo_get_access_token();
$url = "https://projectpro.apilo.com/rest/api/warehouse/product/";
$params['sku'] = $sku;
$url .= '?' . http_build_query( $params );
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $access_token,
"Accept: application/json"
] );
$response = curl_exec( $ch );
$responseData = json_decode( $response, true );
if ( curl_errno( $ch ) ) {
echo 'Błąd cURL: ' . curl_error( $ch );
} else {
if ( $responseData && isset( $responseData['products'] ) ) {
$responseData['status'] = 'SUCCESS';
echo json_encode( $responseData );
exit;
} else {
echo json_encode( [ 'status' => 'SUCCESS', 'msg' => 'Brak wyników dla podanego SKU.', 'products' => '' ] );
exit;
}
}
echo json_encode( [ 'status' => 'SUCCESS', 'msg' => 'Brak wyników dla podanego SKU.', 'products' => '' ] );
exit;
}
// wyszukiwanie produktu w bazie baselinkera
static public function baselinker_product_search()
{
global $mdb, $settings;
$api_code = \admin\factory\Integrations::baselinker_settings( 'api_code' );
$sku = $mdb -> get( 'pp_shop_products', 'sku', [ 'id' => \S::get( 'product_id' ) ] );
if ( !$sku ) {
echo json_encode( [ 'status' => 'error', 'msg' => 'Podany produkt nie posiada kodu SKU.' ] );
exit;
}
$methodParams = '{
"storage_id": "bl_1",
"filter_sku": "' . $sku . '"
}';
$apiParams = [
"token" => $api_code,
"method" => "getProductsList",
"parameters" => $methodParams
];
$curl = curl_init( "https://api.baselinker.com/connector.php" );
curl_setopt( $curl, CURLOPT_POST, 1 );
curl_setopt( $curl, CURLOPT_POSTFIELDS, http_build_query( $apiParams ) );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
$response = json_decode( curl_exec( $curl ), true );
echo json_encode( $response );
exit;
}
// sellasist_product_select_delete
static public function sellasist_product_select_delete()
{
global $mdb;
if ( \admin\factory\Integrations::sellasist_product_select_delete( \S::get( 'product_id' ) ) )
echo json_encode( [ 'status' => 'ok' ] );
else
echo json_encode( [ 'status' => 'error', 'msg' => 'Podczas usuwania produktu wystąpił błąd. Proszę spróbować ponownie.' ] );
exit;
}
// apilo product select delete
static public function apilo_product_select_delete()
{
global $mdb;
if ( \admin\factory\Integrations::apilo_product_select_delete( \S::get( 'product_id' ) ) )
echo json_encode( [ 'status' => 'ok' ] );
else
echo json_encode( [ 'status' => 'error', 'msg' => 'Podczas usuwania produktu wystąpił błąd. Proszę spróbować ponownie.' ] );
exit;
}
// baselinker delete product linking
static public function baselinker_product_select_delete()
{
global $mdb;
if ( \admin\factory\Integrations::baselinker_product_select_delete( \S::get( 'product_id' ) ) )
echo json_encode( [ 'status' => 'ok' ] );
else
echo json_encode( [ 'status' => 'error', 'msg' => 'Podczas usuwania produktu wystąpił błąd. Proszę spróbować ponownie.' ] );
exit;
}
// sellasist_product_select_save
static public function sellasist_product_select_save()
{
global $mdb;
if ( \admin\factory\Integrations::sellasist_product_select_save( \S::get( 'product_id' ), \S::get( 'sellasist_product_id' ), \S::get( 'sellasist_product_name' ) ) )
echo json_encode( [ 'status' => 'ok' ] );
else
echo json_encode( [ 'status' => 'error', 'msg' => 'Podczas zapisywania produktu wystąpił błąd. Proszę spróbować ponownie.' ] );
exit;
}
// apilo product select save
static public function apilo_product_select_save()
{
global $mdb;
if ( \admin\factory\Integrations::apilo_product_select_save( \S::get( 'product_id' ), \S::get( 'apilo_product_id' ), \S::get( 'apilo_product_name' ) ) )
echo json_encode( [ 'status' => 'ok' ] );
else
echo json_encode( [ 'status' => 'error', 'msg' => 'Podczas zapisywania produktu wystąpił błąd. Proszę spróbować ponownie.' ] );
exit;
}
static public function baselinker_product_select_save() {
global $mdb;
if ( \admin\factory\Integrations::baselinker_product_select_save( \S::get( 'product_id' ), \S::get( 'baselinker_product_id' ), \S::get( 'baselinker_product_name' ) ) )
echo json_encode( [ 'status' => 'ok' ] );
else
echo json_encode( [ 'status' => 'error', 'msg' => 'Podczas zapisywania produktu wystąpił błąd. Proszę spróbować ponownie.' ] );
exit;
}
// shoppro_product_import
static public function shoppro_product_import()
{
global $mdb;
$shoppro_settings = \admin\factory\Integrations::shoppro_settings();
$mdb2 = new \medoo( [
'database_type' => 'mysql',
'database_name' => $shoppro_settings[ 'db_name' ],
'server' => $shoppro_settings[ 'db_host' ],
'username' => $shoppro_settings[ 'db_user' ],
'password' => $shoppro_settings[ 'db_password' ],
'charset' => 'utf8'
] );
$product_id = \S::get( 'product_id' );
$product = $mdb2 -> get( 'pp_shop_products', '*', [ 'id' => $product_id ] );
if ( $product )
{
$mdb -> insert( 'pp_shop_products', [
'price_netto' => $product[ 'price_netto' ],
'price_brutto' => $product[ 'price_brutto' ],
'vat' => $product[ 'vat' ],
'stock_0_buy' => $product[ 'stock_0_buy' ],
'quantity' => $product[ 'quantity' ],
'wp' => $product[ 'wp' ],
'sku' => $product[ 'sku' ],
'ean' => $product[ 'ean' ],
'custom_label_0' => $product[ 'custom_label_0' ],
'custom_label_1' => $product[ 'custom_label_1' ],
'custom_label_2' => $product[ 'custom_label_2' ],
'custom_label_3' => $product[ 'custom_label_3' ],
'custom_label_4' => $product[ 'custom_label_4' ],
'additional_message' => $product[ 'additional_message' ],
'additional_message_text' => $product[ 'additional_message_text' ],
'additional_message_required' => $product[ 'additional_message_required' ],
'weight' => $product[ 'weight' ]
] );
$new_product_id = $mdb -> id();
if ( $new_product_id )
{
$languages = $mdb2 -> select( 'pp_shop_products_langs', '*', [ 'product_id' => $product_id ] );
if ( is_array( $languages ) )
{
foreach ( $languages as $language )
{
$mdb -> insert( 'pp_shop_products_langs', [
'product_id' => $new_product_id,
'lang_id' => $language['lang_id'],
'name' => $language['name'],
'short_description' => $language['short_description'],
'description' => $language['description'],
'tab_name_1' => $language['tab_name_1'],
'tab_description_1' => $language['tab_description_1'],
'tab_name_2' => $language['tab_name_2'],
'tab_description_2' => $language['tab_description_2'],
'meta_title' => $language['meta_title'],
'meta_description' => $language['meta_description'],
'meta_keywords' => $language['meta_keywords'],
'seo_link' => $language['seo_link'],
'copy_from' => $language['copy_from'],
'warehouse_message_zero' => $language['warehouse_message_zero'],
'warehouse_message_nonzero' => $language['warehouse_message_nonzero'],
'canonical' => $language['canonical'],
'xml_name' => $language['xml_name']
] );
}
}
$images = $mdb2 -> select( 'pp_shop_products_images', '*', [ 'product_id' => $product_id ] );
if ( is_array( $images ) )
{
foreach ( $images as $image )
{
$image_url = 'https://' . $shoppro_settings['domain'] . $image['src'];
// pobierz zdjęcie za pomocą curl
$ch = curl_init( $image_url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
$image_data = curl_exec( $ch );
$image_data;
curl_close( $ch );
// ścieżdka do nowego zdjęcia to "/upload/product_images/product_[product_id]/[nazwa_zdjęcia]
$image_name = basename( $image_url );
$image_path = '../upload/product_images/product_' . $new_product_id . '/' . $image_name;
// utwórz katalog dla zdjęć produktu jeśli nie istnieje
if ( !file_exists( '../upload/product_images/product_' . $new_product_id ) )
mkdir( '../upload/product_images/product_' . $new_product_id, 0777, true );
// zapisz zdjęcie
file_put_contents( $image_path, $image_data );
// zapisz zdjęcie w bazie danych
$mdb -> insert( 'pp_shop_products_images', [
'product_id' => $new_product_id,
'src' => '/upload/product_images/product_' . $new_product_id . '/' . $image_name,
'o' => $image['o']
] );
}
}
\S::alert( 'Produkt został zaimportowany.' );
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
}
\S::alert( 'Podczas importowania produktu wystąpił błąd.' );
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
}

View File

@@ -1,82 +0,0 @@
<?
namespace admin\controls;
class Languages
{
public static function language_delete()
{
if ( \admin\factory\Languages::language_delete( \S::get( 'id' ) ) )
\S::alert( 'Język został usunięty.' );
header( 'Location: /admin/languages/view_list/' );
exit;
}
public static function language_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania języka wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( \admin\factory\Languages::language_save(
$values['id'], $values['name'], $values['status'],
$values['start'], $values['o'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Język został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function language_edit()
{
return \admin\view\Languages::language_edit(
\admin\factory\Languages::language_details(
\S::get( 'id' )
), \admin\factory\Languages::max_order()
);
}
public static function view_list()
{
return \admin\view\Languages::languages_list();
}
public static function translation_delete()
{
if ( \admin\factory\Languages::translation_delete( \S::get( 'id' ) ) )
\S::alert( 'Tłumaczenie zostało usunięte.' );
header( 'Location: /admin/languages/translation_list/' );
exit;
}
public static function translation_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania tłumaczenia wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
$languages_list = \admin\factory\Languages::languages_list();
if ( is_array( $languages_list ) and !empty( $languages_list ) ) foreach ( $languages_list as $language )
{
\S::delete_session( 'lang-' . $language['id'] );
$languages[ $language['id'] ] = $values[ $language['id'] ];
}
if ( $id = \admin\factory\Languages::translation_save( $values['id'], $values['text'], $languages ) )
$response = [ 'status' => 'ok', 'msg' => 'Tłumaczenie zostało zapisane.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function translation_edit()
{
return \admin\view\Languages::translation_edit(
\admin\factory\Languages::translation_details( \S::get( 'id' ) ),
\admin\factory\Languages::languages_list()
);
}
public static function translation_list()
{
return \admin\view\Languages::translations_list();
}
}
?>

View File

@@ -1,43 +0,0 @@
<?php
namespace admin\controls;
class Layouts
{
public static function layout_delete()
{
if ( \admin\factory\Layouts::layout_delete( \S::get( 'id' ) ) )
\S::alert( 'Szablon został usunięty.' );
header( 'Location: /admin/layouts/view_list/' );
exit;
}
public static function layout_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania szablonu wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\Layouts::layout_save( $values['id'], $values['name'], $values['status'], $values['pages'], $values['html'], $values['css'], $values['js'], $values['m_html'],
$values['m_css'], $values['m_js'], $values['categories'], $values['categories_default'] )
)
$response = [ 'status' => 'ok', 'msg' => 'Szablon został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function layout_edit()
{
return \Tpl::view( 'layouts/layout-edit', [
'layout' => \admin\factory\Layouts::layout_details( \S::get( 'id' ) ),
'menus' => \admin\factory\Layouts::menus_list(),
'categories' => \admin\factory\ShopCategory::subcategories( null ),
'dlang' => \front\factory\Languages::default_language()
] );
}
public static function view_list()
{
return \admin\view\Layouts::layouts_list();
}
}
?>

View File

@@ -1,92 +0,0 @@
<?php
namespace admin\controls;
class Newsletter
{
public static function emails_list()
{
return \admin\view\Newsletter::emails_list();
}
public static function send()
{
if ( \admin\factory\Newsletter::send( \S::get( 'dates' ), \S::get('template')) )
\S::alert( 'Newsletter został dodany do kolejki wysyłania.' );
header( 'Location: /admin/newsletter/prepare/' );
exit;
}
public static function prepare()
{
return \admin\view\Newsletter::prepare(
\admin\factory\Newsletter::templates_list()
);
}
public static function settings_save()
{
$settings = \admin\factory\Settings::settings_details();
$values = json_decode( \S::get( 'values' ), true );
\admin\factory\Settings::settings_update( 'newsletter_footer', $values['newsletter_footer'] );
\admin\factory\Settings::settings_update( 'newsletter_header', $values['newsletter_header'] );
\S::alert( 'Ustawienia zostały zapisane.' );
echo json_encode( [ 'status' => 'ok', 'msg' => 'Ustawienia zostały zapisane.' ] );
exit;
}
public static function settings()
{
return \admin\view\Newsletter::settings(
\admin\factory\Settings::settings_details()
);
}
public static function email_templates_user()
{
return \admin\view\Newsletter::email_templates_user();
}
public static function email_templates_admin()
{
return \admin\view\Newsletter::email_templates_admin();
}
public static function email_template_delete()
{
$is_admin = \admin\factory\Newsletter::is_admin_template( \S::get( 'id' ) );
if ( !$is_admin and \admin\factory\Newsletter::newsletter_template_delete( \S::get( 'id' ) ) )
\S::alert( 'Szablon newslettera został usunięty.' );
if ( $is_admin )
header( 'Location: /admin/newsletter/email_templates_admin/' );
else
header( 'Location: /admin/newsletter/email_templates_user/' );
exit;
}
public static function email_template_edit()
{
return \admin\view\Newsletter::email_template_edit(
\admin\factory\Newsletter::email_template_detalis(
\S::get( 'id' )
)
);
}
public static function template_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\Newsletter::template_save( $values['id'], $values['name'], $values['text'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Zmiany zostały zapisane.', 'id' => $id ];
echo json_encode( $response );
exit;
}
}

View File

@@ -1,100 +0,0 @@
<?php
namespace admin\controls;
class Pages
{
public static function pages_url_browser()
{
echo \Tpl::view( 'pages/pages-browse-list', [
'menus' => \admin\factory\Pages::menus_list(),
'modal' => \S::get( 'modal' )
] );
exit;
}
public static function browse_list()
{
return \admin\view\Pages::browse_list(
\admin\factory\Pages::menus_list()
);
}
public static function menu_delete()
{
if ( \admin\factory\Pages::menu_delete( \S::get( 'id' ) ) )
\S::set_message( 'Menu zostało usunięte.' );
else
\S::alert( 'Podczas usuwania menu wystąpił błąd. Aby usunąć menu nie może ono posiadać przypiętych stron.' );
header( 'Location: /admin/pages/view_list/' );
exit;
}
public static function page_delete()
{
if ( \admin\factory\Pages::page_delete( \S::get( 'id' ) ) )
\S::set_message( 'Strona została usunięta.' );
else
\S::alert( 'Podczas usuwania strony wystąpił błąd. Aby usunąć stronę nie może ona posiadać przypiętych podstron.' );
header( 'Location: /admin/pages/view_list/' );
exit;
}
public static function page_articles()
{
return \admin\view\Pages::page_articles( \S::get( 'id' ), \admin\factory\Pages::page_articles( \S::get( 'id' ) ) );
}
public static function page_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania strony wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\Pages::page_save(
$values['id'], $values['title'], $values['seo_link'], $values['meta_title'], $values['meta_description'], $values['meta_keywords'], $values['menu_id'], $values['parent_id'], $values['page_type'],
$values['sort_type'], $values['layout_id'], $values['articles_limit'], $values['show_title'], $values['status'], $values['link'], $values['noindex'], $values['start'], $values['page_title'],
$values['canonical'], $values['category_id']
) )
$response = [ 'status' => 'ok', 'msg' => 'Strona została zapisana.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function page_edit()
{
return \Tpl::view( 'pages/page-edit', [
'page' => \admin\factory\Pages::page_details( \S::get( 'id' ) ),
'parent_id' => \S::get( 'pid' ),
'menu_id' => \S::get( 'menu_id' ),
'menus' => \admin\factory\Pages::menu_lists(),
'layouts' => \admin\factory\Layouts::layouts_list(),
'languages' => \admin\factory\Languages::languages_list()
] );
}
public static function menu_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania menu wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( \admin\factory\Pages::menu_save( $values['id'], $values['name'], $values['status'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Menu zostało zapisane.' ];
echo json_encode( $response );
exit;
}
public static function menu_edit()
{
return \admin\view\Pages::menu_edit(
\admin\factory\Pages::menu_details( \S::get( 'id' ) )
);
}
public static function view_list()
{
return \Tpl::view( 'pages/pages-list', [
'menus' => \admin\factory\Pages::menus_list()
] );
}
}
?>

View File

@@ -1,40 +0,0 @@
<?php
namespace admin\controls;
class Scontainers
{
public static function container_delete()
{
if ( \admin\factory\Scontainers::container_delete( \S::get( 'id' ) ) )
\S::alert( 'Kontener został usunięty.' );
header( 'Location: /admin/scontainers/view_list/' );
exit;
}
public static function container_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania kontenera wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\Scontainers::container_save( $values['id'], $values['title'], $values['text'], $values['status'], $values['show_title'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Kontener został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function container_edit()
{
return \admin\view\Scontainers::container_edit(
\admin\factory\Scontainers::container_details(
\S::get( 'id' )
),
\admin\factory\Languages::languages_list()
);
}
public static function view_list()
{
return \admin\view\Scontainers::containers_list();
}
}

View File

@@ -1,75 +0,0 @@
<?
namespace admin\controls;
class Settings
{
static public function clear_cache()
{
\S::delete_dir( '../temp/' );
\S::delete_dir( '../thumbs/' );
$redis = \RedisConnection::getInstance() -> getConnection();
if ( $redis )
$redis -> flushAll();
\S::alert( 'Cache został wyczyszczony.' );
header( 'Location: /admin/dashboard/main_view/' );
exit;
}
public static function settings_save()
{
$values = json_decode( \S::get( 'values' ), true );
$settings = \admin\factory\Settings::settings_details( true );
$response = \admin\factory\Settings::settings_save(
$values['firm_name'], $values['firm_adress'], $values['additional_info'], $values['contact_form'], $values['contact_email'], $values['email_host'],
$values['email_port'], $values['email_login'], $values['email_password'], $values['google_maps'], $values['facebook_link'], $values['statistic_code'], $values['htaccess'],
$values['robots'], $values['shop_bank_account_info'], $values['update'], $values['boot_animation'], $settings['newsletter_header'], $settings['newsletter_footer'], $values['hotpay_api']
);
\admin\factory\Settings::settings_update( 'devel', $values['devel'] == 'on' ? 1 : 0 );
\admin\factory\Settings::settings_update( 'ssl', $values['ssl'] == 'on' ? 1 : 0 );
\admin\factory\Settings::settings_update( 'htaccess_cache', $values['htaccess_cache'] == 'on' ? 1 : 0 );
\admin\factory\Settings::settings_update( 'free_delivery', $values['free_delivery'] );
\admin\factory\Settings::settings_update( 'przelewy24_sandbox', $values['przelewy24_sandbox'] == 'on' ? 1 : 0 );
\admin\factory\Settings::settings_update( 'przelewy24_merchant_id', $values['przelewy24_merchant_id'] );
\admin\factory\Settings::settings_update( 'przelewy24_crc_key', $values['przelewy24_crc_key'] );
\admin\factory\Settings::settings_update( 'update_key', $values['update_key'] );
\admin\factory\Settings::settings_update( 'tpay_id', $values['tpay_id'] );
\admin\factory\Settings::settings_update( 'tpay_sandbox', $values['tpay_sandbox'] == 'on' ? 1 : 0 );
\admin\factory\Settings::settings_update( 'tpay_security_code', $values['tpay_security_code'] );
\admin\factory\Settings::settings_update( 'piksel', $values['piksel'] );
\admin\factory\Settings::settings_update( 'generate_webp', $values['generate_webp'] == 'on' ? 1 : 0 );
\admin\factory\Settings::settings_update( 'lazy_loading', $values['lazy_loading'] == 'on' ? 1 : 0 );
\admin\factory\Settings::settings_update( 'orlen_paczka_map_token', $values['orlen_paczka_map_token'] );
\admin\factory\Settings::settings_update( 'google_tag_manager_id', $values['google_tag_manager_id'] );
\admin\factory\Settings::settings_update( 'infinitescroll', $values['infinitescroll'] == 'on' ? 1 : 0 );
// own_gtm_js
\admin\factory\Settings::settings_update( 'own_gtm_js', $values['own_gtm_js'] );
// own_gtm_html
\admin\factory\Settings::settings_update( 'own_gtm_html', $values['own_gtm_html'] );
foreach ( $values[ 'warehouse_message_zero'] as $key => $val )
\admin\factory\Settings::settings_update( 'warehouse_message_zero_' . $key, $val );
foreach ( $values[ 'warehouse_message_nonzero'] as $key => $val )
\admin\factory\Settings::settings_update( 'warehouse_message_nonzero_' . $key, $val );
\S::delete_dir( '../temp/' );
\S::htacces();
echo json_encode( $response );
exit;
}
public static function view()
{
return \Tpl::view( 'settings/settings', [
'languages' => \admin\factory\Languages::languages_list(),
'settings' => \admin\factory\Settings::settings_details()
] );
}
}
?>

View File

@@ -1,71 +0,0 @@
<?php
namespace admin\controls;
class ShopAttribute
{
static public function attribute_value_tpl()
{
$html = \Tpl::view( 'shop-attribute/_partials/value', [
'i' => \S::get( 'i' ),
'value' => \S::get( 'value' ),
'languages' => \S::get( 'languages' ),
'attribute' => \S::get( 'attribute' ),
] );
echo $html;
exit;
}
static public function values_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania wartości atrybutu wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\ShopAttribute::values_save( (int) \S::get( 'attribute_id' ), $values['name'], $values['value'], $values['ids'], $values['default_value'], $values['impact_on_the_price'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Wartości atrybutu zostały zapisane.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function values_edit()
{
return \Tpl::view( 'shop-attribute/values-edit', [
'attribute' => \admin\factory\ShopAttribute::attribute_details( (int) \S::get( 'attribute-id' ) ),
'values' => \admin\factory\ShopAttribute::get_attribute_values( (int) \S::get( 'attribute-id' ) ),
'languages' => \admin\factory\Languages::languages_list()
] );
}
public static function delete_attribute()
{
if ( \admin\factory\ShopAttribute::delete_attribute( (int) \S::get( 'id' ) ) )
\S::alert( 'Atrybut został usunięty.' );
header( 'Location: /admin/shop_attribute/view_list/' );
exit;
}
public static function attribute_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania atrybutu wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\ShopAttribute::attribute_save( (int) $values['id'], $values['name'], $values['status'] == 'on' ? 1 : 0, (int) $values['type'], (int) $values['o'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Atrybut został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
static public function attribute_edit()
{
return \Tpl::view( 'shop-attribute/attribute-edit', [
'attribute' => \admin\factory\ShopAttribute::attribute_details( (int) \S::get( 'id' ) ),
'languages' => \admin\factory\Languages::languages_list()
] );
}
public static function view_list()
{
return \Tpl::view( 'shop-attribute/attributes-list' );
}
}

View File

@@ -1,66 +0,0 @@
<?php
namespace admin\controls;
class ShopCategory
{
public static function category_products()
{
return \Tpl::view( 'shop-category/category-products', [
'category_id' => \S::get( 'id' ),
'products' => \admin\factory\ShopCategory::category_products( (int)\S::get( 'id' ) )
] );
}
public static function category_url_browser() {
echo \Tpl::view( 'shop-category/category-browse-list', [
'categories' => \admin\factory\ShopCategory::subcategories( null ),
'level' => 0,
'dlang' => \front\factory\Languages::default_language()
] );
exit;
}
public static function category_delete()
{
if ( \admin\factory\ShopCategory::category_delete( \S::get( 'id' ) ) )
\S::set_message( 'Kategoria została usunięta.' );
else
\S::alert( 'Podczas usuwania kategorii wystąpił błąd. Aby usunąć kategorię nie może ona posiadać przypiętych podkategorii.' );
header( 'Location: /admin/shop_category/view_list/' );
exit;
}
static public function save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania kategorii wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\ShopCategory::save(
$values['id'], $values['title'], $values['text'], $values['text_hidden'], $values['seo_link'], $values['meta_title'], $values['meta_description'], $values['meta_keywords'], $values['parent_id'], $values['status'],
$values['noindex'], $values['category_title'], $values['sort_type'], $values['additional_text'], $values['view_subcategories']
) )
$response = [ 'status' => 'ok', 'msg' => 'Kategoria została zapisana.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function category_edit()
{
return \admin\view\ShopCategory::category_edit(
\admin\factory\ShopCategory::category_details(
\S::get( 'id' )
),
\S::get( 'pid' ),
\admin\factory\Languages::languages_list()
);
}
public static function view_list()
{
return \Tpl::view( 'shop-category/categories-list', [
'categories' => \admin\factory\ShopCategory::subcategories( null ),
'level' => 0,
'dlang' => \front\factory\Languages::default_language()
] );
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace admin\controls;
class ShopClients
{
public static function view_list()
{
return \Tpl::view(
'shop-clients/view-list'
);
}
public static function clients_details()
{
$query_string = $_SERVER['REDIRECT_QUERY_STRING'];
parse_str($query_string, $query_array);
$orders_info = \admin\factory\ShopClients::get_order_all_info( $query_array['name'], $query_array['surname'], $query_array['email'] );
return \Tpl::view('shop-clients/clients-details', [
'name' => $query_array['name'],
'surname' => $query_array['surname'],
'email' => $query_array['email'],
'total_spent' => $query_array['total_spent'],
'orders_info' => $orders_info
]);
}
}
?>

View File

@@ -1,58 +0,0 @@
<?php
namespace admin\controls;
class ShopCoupon
{
public static function coupon_delete()
{
$coupon = new \shop\Coupon( (int)\S::get( 'id' ) );
if ( $coupon -> delete() )
\S::alert( 'Kupon został usunięty.' );
header( 'Location: /admin/shop_coupon/view_list/' );
exit;
}
public static function coupon_save()
{
$response = ['status' => 'error', 'msg' => 'Podczas zapisywania kuponu wystąpił błąd. Proszę spróbować ponownie.'];
$values = json_decode( \S::get( 'values' ), true );
if ( $values['categories'] != null )
$categories = is_array( $values['categories'] ) ? json_encode( $values['categories'] ) : json_encode( [ $values['categories'] ] );
else
$categories = null;
if ( \admin\factory\ShopCoupon::save(
$values['id'],
$values['name'],
$values['status'] == 'on' ? 1 : 0,
$values['send'] == 'on' ? 1 : 0,
$values['used'] == 'on' ? 1 : 0,
$values['type'],
$values['amount'],
$values['one_time'] == 'on' ? 1 : 0,
$values['include_discounted_product'] == 'on' ? 1 : 0,
$categories
)
)
$response = [ 'status' => 'ok', 'msg' => 'Kupon został zapisany.', 'id' => $values['id'] ];
echo json_encode( $response );
exit;
}
public static function coupon_edit()
{
return \Tpl::view( 'shop-coupon/coupon-edit', [
'coupon' => \admin\factory\ShopCoupon::details( (int)\S::get( 'id' ) ),
'categories' => \admin\factory\ShopCategory::subcategories( null ),
'dlang' => \front\factory\Languages::default_language()
] );
}
public static function view_list()
{
return \Tpl::view( 'shop-coupon/view-list' );
}
}

View File

@@ -1,133 +0,0 @@
<?php
namespace admin\controls;
class ShopOrder
{
static public function send_order_to_apilo()
{
$order_id = \S::get( 'order_id' );
if ( \admin\factory\ShopOrder::send_order_to_apilo( $order_id ) ) {
\S::alert( 'Zamówienie zostanie wysłane ponownie do apilo.com' );
} else {
\S::alert( 'Wystąpił błąd podczas wysyłania zamówienia do apilo.com' );
}
header( 'Location: /admin/shop_order/order_details/order_id=' . $order_id );
exit;
}
static public function order_resend_confirmation_email()
{
$order = new \shop\Order( (int)\S::get( 'order_id' ) );
$response = $order -> order_resend_confirmation_email();
echo json_encode( [ 'result' => $response ] );
exit;
}
static public function notes_save()
{
\shop\Order::notes_save( \S::get( 'order_id' ), \S::get( 'notes' ) );
}
static public function order_save()
{
if ( \shop\Order::order_save_by_admin(
\S::get( 'order_id' ), \S::get( 'client_name' ), \S::get( 'client_surname' ), \S::get( 'client_street' ), \S::get( 'client_postal_code' ), \S::get( 'client_city' ), \S::get( 'client_email' ), \S::get( 'firm_name' ), \S::get( 'firm_street' ), \S::get( 'firm_postal_code' ), \S::get( 'firm_city' ), \S::get( 'firm_nip' ), \S::get( 'transport_id' ), \S::get( 'inpost_paczkomat' ), \S::get( 'payment_method_id' )
) )
\S::alert( 'Zamówienie zostało zapisane.' );
header( 'Location: /admin/shop_order/order_details/order_id=' . \S::get( 'order_id' ) );
exit;
}
static public function order_edit()
{
return \Tpl::view( 'shop-order/order-edit', [
'order' => new \shop\Order( (int)\S::get( 'order_id' ) ),
'order_statuses' => \shop\Order::order_statuses(),
'transport' => \shop\Transport::transport_list(),
'payment_methods' => \shop\PaymentMethod::method_list()
] );
}
public static function order_details()
{
$order = new \shop\Order( (int)\S::get( 'order_id' ) );
$coupon = $order -> coupon_id ? new \shop\Coupon( $order -> coupon_id ) : null;
return \Tpl::view( 'shop-order/order-details', [
'order' => $order,
'coupon' => $coupon,
'order_statuses' => \shop\Order::order_statuses(),
'next_order_id' => \admin\factory\ShopOrder::next_order_id( (int)\S::get( 'order_id' ) ),
'prev_order_id' => \admin\factory\ShopOrder::prev_order_id( (int)\S::get( 'order_id' ) ),
] );
}
public static function view_list()
{
return \Tpl::view(
'shop-order/view-list'
);
}
public static function order_status_change()
{
global $mdb;
$order = new \shop\Order( (int)\S::get( 'order_id' ) );
$response = $order -> update_status( (int)\S::get( 'status' ), \S::get( 'email' ) == 'true' ? 1 : 0 );
echo json_encode( $response );
exit;
}
public static function order_delete()
{
global $user;
if ( \shop\Order::order_delete( (int)\S::get( 'id' ) ) )
{
\S::alert( 'Zamówienie zostało usunięte' );
\Log::save_log( 'Usunięcie zamówienia | ID: ' . (int)\S::get( 'id' ), $user['id'] );
}
header( 'Location: /admin/shop_order/view_list/' );
exit;
}
// set_order_as_unpaid
public static function set_order_as_unpaid()
{
$order = new \shop\Order( (int)\S::get( 'order_id' ) );
$order -> set_as_unpaid();
header( 'Location: /admin/shop_order/order_details/order_id=' . (int)\S::get( 'order_id' ) );
exit;
}
// set_order_as_paid
public static function set_order_as_paid()
{
$order = new \shop\Order( (int)\S::get( 'order_id' ) );
if ( $order -> set_as_paid() )
{
$order -> update_status( 4, (int)\S::get( 'send_mail' ) );
}
header( 'Location: /admin/shop_order/order_details/order_id=' . (int)\S::get( 'order_id' ) );
exit;
}
// toggle_trustmate_send
public static function toggle_trustmate_send()
{
global $mdb;
$order_id = (int)\S::get( 'order_id' );
$order = $mdb -> get( 'pp_shop_orders', [ 'trustmate_send' ], [ 'id' => $order_id ] );
$new_value = $order['trustmate_send'] ? 0 : 1;
$mdb -> update( 'pp_shop_orders', [ 'trustmate_send' => $new_value ], [ 'id' => $order_id ] );
echo json_encode( [ 'result' => true, 'trustmate_send' => $new_value ] );
exit;
}
}

View File

@@ -1,12 +0,0 @@
<?php
namespace admin\controls;
class ShopPaymentMethod
{
public static function view_list()
{
return \Tpl::view( 'shop-payment-method/view-list', [
'apilo_payment_types_list' => unserialize( \admin\factory\Integrations::apilo_settings( 'payment-types-list' ) ),
'sellasist_payment_types_list' => unserialize( \admin\factory\Integrations::sellasist_settings( 'payment_types_list' ) ),
] );
}
}

View File

@@ -1,37 +0,0 @@
<?
namespace admin\controls;
class ShopProducer
{
static public function delete()
{
if ( \admin\factory\ShopProducer::delete( \S::get( 'id' ) ) )
\S::alert( 'Producent został usunięty' );
header( 'Location: /admin/shop_producer/list/' );
exit;
}
static public function save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania producenta wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $producer_id = \admin\factory\ShopProducer::save( $values['id'], $values['name'], $values['status'] == 'on' ? 1 : 0, $values['img'], $values['description'], $values['data'], $values['meta_title'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Producent został zapisany.', 'id' => $producer_id ];
echo json_encode( $response );
exit;
}
static public function edit()
{
return \Tpl::view( 'shop-producer/edit', [
'producer' => \S::get( 'id' ) ? new \shop\Producer( \S::get( 'id' ) ) : null,
'languages' => \admin\factory\Languages::languages_list()
] );
}
static public function list()
{
return \Tpl::view( 'shop-producer/list' );
}
}

View File

@@ -1,426 +0,0 @@
<?php
namespace admin\controls;
class ShopProduct
{
static public function mass_edit_save()
{
global $mdb;
if ( \S::get( 'discount_percent' ) != '' and \S::get( 'products' ) )
{
$product_details = \admin\factory\ShopProduct::product_details( \S::get( 'products' )[0] );
$vat = $product_details['vat'];
$price_brutto = $product_details['price_brutto'];
$price_brutto_promo = $price_brutto - ( $price_brutto * ( \S::get( 'discount_percent' ) / 100 ) );
$price_netto = $product_details['price_netto'];
$price_netto_promo = $price_netto - ( $price_netto * ( \S::get( 'discount_percent' ) / 100 ) );
if ( $price_brutto == $price_brutto_promo)
$price_brutto_promo = null;
if ( $price_netto == $price_netto_promo )
$price_netto_promo = null;
$mdb -> update( 'pp_shop_products', [ 'price_brutto_promo' => $price_brutto_promo, 'price_netto_promo' => $price_netto_promo ], [ 'id' => \S::get( 'products' )[0] ] );
\admin\factory\ShopProduct::update_product_combinations_prices( \S::get( 'products' )[0], $price_netto, $vat, $price_netto_promo );
echo json_encode( [ 'status' => 'ok', 'price_brutto_promo' => $price_brutto_promo, 'price_brutto' => $price_brutto ] );
exit;
}
echo json_encode( [ 'status' => 'error' ] );
exit;
}
// get_products_by_category
static public function get_products_by_category() {
global $mdb;
$products = $mdb -> select( 'pp_shop_products_categories', 'product_id', [ 'category_id' => \S::get( 'category_id' ) ] );
echo json_encode( [ 'status' => 'ok', 'products' => $products ] );
exit;
}
static public function mass_edit()
{
return \Tpl::view( 'shop-product/mass-edit', [
'products' => \admin\factory\ShopProduct::products_list(),
'categories' => \admin\factory\ShopCategory::subcategories( null ),
'dlang' => \front\factory\Languages::default_language()
] );
}
static public function generate_combination()
{
foreach ( $_POST as $key => $val )
{
if ( strpos( $key, 'attribute_' ) !== false )
{
$attribute = explode( 'attribute_', $key );
$attributes[ $attribute[1] ] = $val;
}
}
if ( \admin\factory\ShopProduct::generate_permutation( (int) \S::get( 'product_id' ), $attributes ) )
\S::alert( 'Kombinacje produktu zostały wygenerowane.' );
header( 'Location: /admin/shop_product/product_combination/product_id=' . (int) \S::get( 'product_id' ) );
exit;
}
//usunięcie kombinacji produktu
static public function delete_combination()
{
if ( \admin\factory\ShopProduct::delete_combination( (int)\S::get( 'combination_id' ) ) )
\S::alert( 'Kombinacja produktu została usunięta' );
else
\S::alert( 'Podczas usuwania kombinacji produktu wystąpił błąd. Proszę spróbować ponownie' );
header( 'Location: /admin/shop_product/product_combination/product_id=' . \S::get( 'product_id' ) );
exit;
}
static public function duplicate_product()
{
if ( \admin\factory\ShopProduct::duplicate_product( (int)\S::get( 'product-id' ), (int)\S::get( 'combination' ) ) )
\S::set_message( 'Produkt został zduplikowany.' );
else
\S::alert( 'Podczas duplikowania produktu wystąpił błąd. Proszę spróbować ponownie' );
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
public static function image_delete()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas usuwania zdjecia wystąpił błąd. Proszę spróbować ponownie.' ];
if ( \admin\factory\ShopProduct::delete_img( \S::get( 'image_id' ) ) )
$response = [ 'status' => 'ok' ];
echo json_encode( $response );
exit;
}
public static function images_order_save()
{
if ( \admin\factory\ShopProduct::images_order_save( \S::get( 'product_id' ), \S::get( 'order' ) ) )
echo json_encode( [ 'status' => 'ok', 'msg' => 'Produkt został zapisany.' ] );
exit;
}
public static function image_alt_change()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zmiany atrybutu alt zdjęcia wystąpił błąd. Proszę spróbować ponownie.' ];
if ( \admin\factory\ShopProduct::image_alt_change( \S::get( 'image_id' ), \S::get( 'image_alt' ) ) )
$response = [ 'status' => 'ok' ];
echo json_encode( $response );
exit;
}
// szybka zmiana statusu produktu
static public function change_product_status() {
if ( \admin\factory\ShopProduct::change_product_status( (int)\S::get( 'product-id' ) ) )
\S::set_message( 'Status produktu został zmieniony' );
header( 'Location: ' . $_SERVER['HTTP_REFERER'] );
exit;
}
// szybka zmiana google xml label
static public function product_change_custom_label()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zmiany google xml label wystąpił błąd. Proszę spróbować ponownie.' ];
if ( \admin\factory\ShopProduct::product_change_custom_label( (int) \S::get( 'product_id' ), \S::get( 'custom_label' ), \S::get( 'value' ) ) )
$response = [ 'status' => 'ok' ];
echo json_encode( $response );
exit;
}
// szybka zmiana ceny promocyjnej
static public function product_change_price_brutto_promo()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zmiany ceny wystąpił błąd. Proszę spróbować ponownie.' ];
if ( \admin\factory\ShopProduct::product_change_price_brutto_promo( (int) \S::get( 'product_id' ), \S::get( 'price' ) ) )
$response = [ 'status' => 'ok' ];
echo json_encode( $response );
exit;
}
// szybka zmiana ceny
static public function product_change_price_brutto()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zmiany ceny wystąpił błąd. Proszę spróbować ponownie.' ];
if ( \admin\factory\ShopProduct::product_change_price_brutto( (int) \S::get( 'product_id' ), \S::get( 'price' ) ) )
$response = [ 'status' => 'ok' ];
echo json_encode( $response );
exit;
}
// pobierz bezpośredni url produktu
static public function ajax_product_url()
{
echo json_encode( [ 'url' => \shop\Product::getProductUrl( \S::get( 'product_id' ) ) ] );
exit;
}
// zapisanie produktu
public static function save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania produktu wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\ShopProduct::save(
$values['id'], $values['name'], $values['short_description'], $values['description'], $values['status'], $values['meta_description'], $values['meta_keywords'], $values['seo_link'],
$values['copy_from'], $values['categories'], $values['price_netto'], $values['price_brutto'], $values['vat'], $values['promoted'], $values['warehouse_message_zero'], $values['warehouse_message_nonzero'], $values['tab_name_1'],
$values['tab_description_1'], $values['tab_name_2'], $values['tab_description_2'], $values['layout_id'], $values['products_related'], (int) $values['set'], $values['price_netto_promo'], $values['price_brutto_promo'],
$values['new_to_date'], $values['stock_0_buy'], $values['wp'], $values['custom_label_0'], $values['custom_label_1'], $values['custom_label_2'], $values['custom_label_3'], $values['custom_label_4'], $values['additional_message'], (int)$values['quantity'], $values['additional_message_text'], $values['additional_message_required'] == 'on' ? 1 : 0, $values['canonical'], $values['meta_title'], $values['producer_id'], $values['sku'], $values['ean'], $values['product_unit'], $values['weight'], $values['xml_name'], $values['custom_field_name'], $values['custom_field_required'], $values['security_information']
) ) {
$response = [ 'status' => 'ok', 'msg' => 'Produkt został zapisany.', 'id' => $id ];
}
echo json_encode( $response );
exit;
}
// product_unarchive
static public function product_unarchive()
{
if ( \admin\factory\ShopProduct::product_unarchive( (int) \S::get( 'product_id' ) ) )
\S::alert( 'Produkt został przywrócony z archiwum.' );
else
\S::alert( 'Podczas przywracania produktu z archiwum wystąpił błąd. Proszę spróbować ponownie' );
header( 'Location: /admin/archive/products_list/' );
exit;
}
static public function product_archive()
{
if ( \admin\factory\ShopProduct::product_archive( (int) \S::get( 'product_id' ) ) )
\S::alert( 'Produkt został przeniesiony do archiwum.' );
else
\S::alert( 'Podczas przenoszenia produktu do archiwum wystąpił błąd. Proszę spróbować ponownie' );
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
public static function product_delete()
{
if ( \admin\factory\ShopProduct::product_delete( (int) \S::get( 'id' ) ) )
\S::set_message( 'Produkt został usunięty.' );
else
\S::alert( 'Podczas usuwania produktu wystąpił błąd. Proszę spróbować ponownie' );
header( 'Location: /admin/shop_product/view_list/' );
exit;
}
// edycja produktu
public static function product_edit() {
global $user;
if ( !$user ) {
header( 'Location: /admin/' );
exit;
}
\admin\factory\ShopProduct::delete_nonassigned_images();
\admin\factory\ShopProduct::delete_nonassigned_files();
return \Tpl::view( 'shop-product/product-edit', [
'product' => \admin\factory\ShopProduct::product_details( (int) \S::get( 'id' ) ),
'languages' => \admin\factory\Languages::languages_list(),
'categories' => \admin\factory\ShopCategory::subcategories( null ),
'layouts' => \admin\factory\Layouts::layouts_list(),
'products' => \admin\factory\ShopProduct::products_list(),
'dlang' => \front\factory\Languages::default_language(),
'sets' => \shop\ProductSet::sets_list(),
'producers' => \admin\factory\ShopProducer::all(),
'units' => \admin\factory\Dictionaries::all_units(),
'user' => $user
] );
}
// ajax_load_products ARCHIVE
static public function ajax_load_products_archive()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas ładowania produktów wystąpił błąd. Proszę spróbować ponownie.' ];
\S::set_session( 'products_list_current_page', \S::get( 'current_page' ) );
\S::set_session( 'products_list_query', \S::get( 'query' ) );
if ( $products = \admin\factory\ShopProduct::ajax_products_list_archive( \S::get_session( 'products_list_current_page' ), \S::get_session( 'products_list_query' ) ) ) {
$response = [
'status' => 'ok',
'pagination_max' => ceil( $products['products_count'] / 10 ),
'html' => \Tpl::view( 'archive/products-list-table', [
'products' => $products['products'],
'current_page' => \S::get( 'current_page' ),
] )
];
}
echo json_encode( $response );
exit;
}
// ajax_load_products
static public function ajax_load_products() {
$response = [ 'status' => 'error', 'msg' => 'Podczas ładowania produktów wystąpił błąd. Proszę spróbować ponownie.' ];
\S::set_session( 'products_list_current_page', \S::get( 'current_page' ) );
\S::set_session( 'products_list_query', \S::get( 'query' ) );
if ( $products = \admin\factory\ShopProduct::ajax_products_list( \S::get_session( 'products_list_current_page' ), \S::get_session( 'products_list_query' ) ) ) {
$response = [
'status' => 'ok',
'pagination_max' => ceil( $products['products_count'] / 10 ),
'html' => \Tpl::view( 'shop-product/products-list-table', [
'products' => $products['products'],
'current_page' => \S::get( 'current_page' ),
'baselinker_enabled' => \admin\factory\Integrations::baselinker_settings( 'enabled' ),
'apilo_enabled' => \admin\factory\Integrations::apilo_settings( 'enabled' ),
'sellasist_enabled' => \admin\factory\Integrations::sellasist_settings( 'enabled' ),
'show_xml_data' => \S::get_session( 'show_xml_data' )
] )
];
}
echo json_encode( $response );
exit;
}
static public function view_list()
{
$current_page = \S::get_session( 'products_list_current_page' );
if ( !$current_page ) {
$current_page = 1;
\S::set_session( 'products_list_current_page', $current_page );
}
$query = \S::get_session( 'products_list_query' );
if ( $query ) {
$query_array = [];
parse_str( $query, $query_array );
}
if ( \S::get( 'show_xml_data' ) === 'true' ) {
\S::set_session( 'show_xml_data', true );
} else if ( \S::get( 'show_xml_data' ) === 'false' ) {
\S::set_session( 'show_xml_data', false );
}
return \Tpl::view( 'shop-product/products-list', [
'current_page' => $current_page,
'query_array' => $query_array,
'pagination_max' => ceil( \admin\factory\ShopProduct::count_product() / 10 ),
'baselinker_enabled' => \admin\factory\Integrations::baselinker_settings( 'enabled' ),
'apilo_enabled' => \admin\factory\Integrations::apilo_settings( 'enabled' ),
'sellasist_enabled' => \admin\factory\Integrations::sellasist_settings( 'enabled' ),
'show_xml_data' => \S::get_session( 'show_xml_data' ),
'shoppro_enabled' => \admin\factory\Integrations::shoppro_settings( 'enabled' )
] );
}
//
// KOMBINACJE PRODUKTU
//
// zapisanie możliwości zakupu przy stanie 0 w kombinacji produktu
static public function product_combination_stock_0_buy_save()
{
\admin\factory\ShopProduct::product_combination_stock_0_buy_save( (int)\S::get( 'product_id' ), \S::get( 'stock_0_buy' ) );
exit;
}
// zapisanie sku w kombinacji produktu
static public function product_combination_sku_save()
{
\admin\factory\ShopProduct::product_combination_sku_save( (int)\S::get( 'product_id' ), \S::get( 'sku' ) );
exit;
}
// zapisanie ilości w kombinacji produktu
static public function product_combination_quantity_save()
{
\admin\factory\ShopProduct::product_combination_quantity_save( (int)\S::get( 'product_id' ), \S::get( 'quantity' ) );
exit;
}
// zapisanie ceny w kombinacji produktu
static public function product_combination_price_save()
{
\admin\factory\ShopProduct::product_combination_price_save( (int)\S::get( 'product_id' ), \S::get( 'price' ) );
exit;
}
//wyświetlenie kombinacji produktu
static public function product_combination()
{
return \Tpl::view( 'shop-product/product-combination', [
'product' => \admin\factory\ShopProduct::product_details( (int) \S::get( 'product_id' ) ),
'attributes' => \admin\factory\ShopAttribute::get_attributes_list(),
'default_language' => \front\factory\Languages::default_language(),
'product_permutations' => \admin\factory\ShopProduct::get_product_permutations( (int) \S::get( 'product_id' ) )
] );
}
// generate_sku_code
static public function generate_sku_code() {
$response = [ 'status' => 'error', 'msg' => 'Podczas generowania kodu sku wystąpił błąd. Proszę spróbować ponownie.' ];
if ( $sku = \shop\Product::generate_sku_code( \S::get( 'product_id' ) ) )
$response = [ 'status' => 'ok', 'sku' => $sku ];
echo json_encode( $response );
exit;
}
// product_xml_name_save
static public function product_xml_name_save() {
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania nazwy produktu wystąpił błąd. Proszę spróbować ponownie.' ];
if ( \shop\Product::product_xml_name_save( \S::get( 'product_id' ), \S::get( 'product_xml_name' ), \S::get( 'lang_id' ) ) )
$response = [ 'status' => 'ok' ];
echo json_encode( $response );
exit;
}
// product_custom_label_suggestions
static public function product_custom_label_suggestions() {
$response = [ 'status' => 'error', 'msg' => 'Podczas pobierania sugestii dla custom label wystąpił błąd. Proszę spróbować ponownie.' ];
if ( $suggestions = \shop\Product::product_custom_label_suggestions( \S::get( 'custom_label' ), \S::get( 'label_type' ) ) )
$response = [ 'status' => 'ok', 'suggestions' => $suggestions ];
echo json_encode( $response );
exit;
}
// product_custom_label_save
static public function product_custom_label_save() {
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania custom label wystąpił błąd. Proszę spróbować ponownie.' ];
if ( \shop\Product::product_custom_label_save( \S::get( 'product_id' ), \S::get( 'custom_label' ), \S::get( 'label_type' ) ) )
$response = [ 'status' => 'ok' ];
echo json_encode( $response );
exit;
}
}

View File

@@ -1,43 +0,0 @@
<?php
namespace admin\controls;
class ShopProductSets
{
static public function set_delete()
{
if ( \shop\ProductSet::set_delete( \S::get( 'id' ) ) )
\S::set_message( 'Komplet produktów usunięty.' );
else
\S::alert( 'Podczas usuwania kompletu produktów wystąpił błąd. Proszę spróbować ponownie' );
header( 'Location: /admin/shop_product_sets/view_list/' );
exit;
}
static public function save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania kompletu produktów wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\ShopProductSet::save(
(int)$values['id'], $values['name'], (string) $values['status'], $values['set_products_id']
) ) {
$response = [ 'status' => 'ok', 'msg' => 'Komplet produktów został zapisany.', 'id' => $id ];
}
echo json_encode( $response );
exit;
}
static public function set_edit()
{
return \Tpl::view( 'shop-product-sets/set-edit', [
'set' => new \shop\ProductSet( (int) \S::get( 'id' ) ),
'products' => \admin\factory\ShopProduct::products_list()
] );
}
static public function view_list()
{
return \Tpl::view( 'shop-product-sets/view-list' );
}
}

View File

@@ -1,59 +0,0 @@
<?php
namespace admin\controls;
class ShopPromotion
{
// usunięcie promocji
static public function promotion_delete()
{
$promotion = \R::load( 'pp_shop_promotion', (int)\S::get( 'id' ) );
if ( \R::trash( $promotion ) )
\S::alert( 'Promocja została usunięta' );
header( 'Location: /admin/shop_promotion/view_list/' );
exit;
}
// zapisanie promocji
static public function save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania promocji wystąpił błąd. Proszę spróbować ponownie' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\ShopPromotion::save(
$values['id'],
$values['name'],
$values['status'] == 'on' ? 1 : 0,
$values['condition_type'],
$values['discount_type'],
$values['amount'],
$values['date_to'],
$values['categories'],
$values['condition_categories'],
$values['include_coupon'] == 'on' ? 1 : 0,
$values['include_product_promo'] == 'on' ? 1 : 0,
$values['min_product_count'],
$values['price_cheapest_product']
) )
$response = [ 'status' => 'ok', 'msg' => 'Promocja została zapisana', 'id' => $id ];
echo json_encode( $response );
exit;
}
// edycja promocji
static public function edit()
{
return \Tpl::view( 'shop-promotion/promotion-edit', [
'promotion' => \admin\factory\ShopPromotion::promotion_details( (int)\S::get( 'id' ) ),
'categories' => \admin\factory\ShopCategory::subcategories( null ),
'dlang' => \front\factory\Languages::default_language()
] );
}
// lista promocji
public static function view_list()
{
return \Tpl::view( 'shop-promotion/view-list' );
}
}

View File

@@ -1,38 +0,0 @@
<?
namespace admin\controls;
class ShopStatuses {
// status_save
public static function status_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania statusu wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\ShopStatuses::status_save( $values['id'], $values['color'], $values['apilo_status_id'], $values['sellasist_status_id'], $values['baselinker_status_id'] ) )
$response = [ 'status' => 'ok', 'msg' => 'Status został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
// status_edit
public static function status_edit()
{
return \Tpl::view( 'shop-statuses/status-edit', [
'status' => \admin\factory\ShopStatuses::get_status( \S::get( 'id' ) ),
'apilo_order_status_list' => unserialize( \admin\factory\Integrations::apilo_settings( 'status-types-list' ) ),
'sellasist_order_status_list' => unserialize( \admin\factory\Integrations::sellasist_settings( 'status_types_list' ) ),
'baselinker_order_status_list' => unserialize( \admin\factory\Integrations::baselinker_settings( 'order_status_list' ) ),
] );
}
static public function view_list()
{
return \Tpl::view( 'shop-statuses/view-list', [
'apilo_order_status_list' => unserialize( \admin\factory\Integrations::apilo_settings( 'status-types-list' ) ),
'sellasist_order_status_list' => unserialize( \admin\factory\Integrations::sellasist_settings( 'status_types_list' ) ),
'baselinker_order_status_list' => unserialize( \admin\factory\Integrations::baselinker_settings( 'order_status_list' ) ),
] );
}
}

View File

@@ -1,36 +0,0 @@
<?php
namespace admin\controls;
class ShopTransport
{
public static function transport_save()
{
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania rodzaju transportu wystąpił błąd. Proszę spróbować ponownie.' ];
$values = json_decode( \S::get( 'values' ), true );
if ( $id = \admin\factory\ShopTransport::transport_save(
$values['id'], $values['name'], $values['name_visible'], $values['description'], $values['status'], $values['cost'], $values['payment_methods'], $values['max_wp'], $values['default'], $values['apilo_carrier_account_id'], $values['sellasist_shipment_method_id'], $values['delivery_free']
) )
$response = [ 'status' => 'ok', 'msg' => 'Rodzaj transportu został zapisany.', 'id' => $id ];
echo json_encode( $response );
exit;
}
public static function transport_edit()
{
return \Tpl::view( 'shop-transport/transport-edit', [
'transport_details' => \admin\factory\ShopTransport::transport_details( \S::get( 'id' ) ),
'payments_list' => \admin\factory\ShopPaymentMethod::payments_list(),
'apilo_carrier_account_list' => unserialize( \admin\factory\Integrations::apilo_settings( 'carrier-account-list' ) ),
'sellasist_shipments_methods' => unserialize( \admin\factory\Integrations::sellasist_settings( 'shipments_methods' ) ),
] );
}
public static function view_list()
{
return \Tpl::view( 'shop-transport/view-list', [
'apilo_carrier_account_list' => unserialize( \admin\factory\Integrations::apilo_settings( 'carrier-account-list' ) ),
'sellasist_shipments_methods' => unserialize( \admin\factory\Integrations::sellasist_settings( 'shipments_methods' ) ),
] );
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace admin\controls;
class Update
{
public static function update()
{
if ( !\admin\factory\Update::update() )
\S::alert( 'W trakcie aktualizacji systemu wystąpił błąd. Proszę spróbować ponownie.' );
else
\S::set_message( 'Aktualizacja przebiegła pomyślnie.' );
header( 'Location: /admin/update/main_view/' );
exit;
}
public static function updateAll()
{
$response['status'] = \admin\factory\Update::update();
$response['version'] = number_format( \S::get('version_current') + 0.001, 3, '.', '' );
echo json_encode( $response );
exit;
}
public static function main_view()
{
return \admin\view\Update::main_view();
}
}

View File

@@ -1,43 +0,0 @@
<?php
namespace admin\controls;
class Users
{
public static function user_delete()
{
if ( \admin\factory\Users::user_delete( \S::get( 'id' ) ) )
\S::alert( 'Użytkownik został usunięty.' );
header( 'Location: /admin/users/view_list/' );
exit;
}
public static function user_save()
{
$values = json_decode( \S::get( 'values' ), true );
$response = \admin\factory\Users::user_save( $values['id'], $values['login'], $values['status'], $values['password'], $values['password_re'], $values['admin'], $values['twofa_enabled'], $values['twofa_email'] );
echo json_encode( $response );
exit;
}
public static function user_edit()
{
return \admin\view\Users::user_edit(
\admin\factory\Users::user_details(
\S::get( 'id' )
)
);
}
public static function view_list()
{
return \admin\view\Users::users_list();
}
static public function twofa() {
return \Tpl::view( 'site/unlogged', [
'content' => \Tpl::view( 'users/user-2fa' )
] );
}
}
?>

View File

@@ -1,472 +0,0 @@
<?php
namespace admin\factory;
class Articles
{
public static function gallery_order_save( $article_id, $order )
{
global $mdb;
$order = explode( ';', $order );
if ( is_array( $order ) and !empty( $order ) ) foreach ( $order as $image_id )
{
$mdb -> update( 'pp_articles_images', [
'o' => $i++
], [
'AND' => [
'article_id' => $article_id,
'id' => $image_id
]
] );
}
return true;
}
public static function image_alt_change( $image_id, $image_alt )
{
global $mdb;
$result = $mdb -> update( 'pp_articles_images', [
'alt' => $image_alt
], [
'id' => $image_id
] );
\S::delete_cache();
return $result;
}
public static function article_url( $article_id )
{
global $mdb;
$results = $mdb -> query( "SELECT seo_link FROM pp_articles_langs AS pal, pp_langs AS pl WHERE lang_id = pl.id AND article_id = " . (int)$article_id . " AND seo_link != '' ORDER BY o ASC LIMIT 1" ) -> fetchAll();
if ( !$results[0]['seo_link'] )
{
$title = self::article_title( $article_id );
return 'a-' . $article_id . '-' . \S::seo( $title );
}
else
return $results[0]['seo_link'];
}
public static function articles_by_date_add( $date_start, $date_end )
{
global $mdb;
$results = $mdb -> query( 'SELECT '
. 'id '
. 'FROM '
. 'pp_articles '
. 'WHERE '
. 'status = 1 '
. 'AND '
. 'date_add BETWEEN \'' . $date_start . '\' AND \'' . $date_end . '\' '
. 'ORDER BY '
. 'date_add DESC' ) -> fetchAll();
if ( is_array( $results ) and !empty( $results ) ) foreach ( $results as $row )
$articles[] = \front\factory\Articles::article_details( $row['id'], 'pl' );
return $articles;
}
public static function article_pages( $article_id )
{
global $mdb;
$results = $mdb -> query( "SELECT page_id FROM pp_articles_pages WHERE article_id = " . (int)$article_id ) -> fetchAll();
if ( is_array( $results ) and !empty( $results ) ) foreach ( $results as $row )
{
if ( $out == '' )
$out .= ' - ';
$out .= \admin\factory\Pages::page_title( $row['page_id'] );
if ( end( $results ) != $row )
$out .= ' / ';
}
return $out;
}
public static function article_title( $article_id )
{
global $mdb;
$results = $mdb -> query( "SELECT title FROM pp_articles_langs AS pal, pp_langs AS pl WHERE lang_id = pl.id AND article_id = " . (int)$article_id . " AND title != '' ORDER BY o ASC LIMIT 1" ) -> fetchAll();
return $results[0]['title'];
}
public static function articles_set_archive( $article_id )
{
global $mdb;
return $mdb -> update( 'pp_articles', [ 'status' => -1 ], [ 'id' => (int)$article_id ] );
}
public static function file_name_change( $file_id, $file_name )
{
global $mdb;
$mdb -> update( 'pp_articles_files', [ 'name' => $file_name ], [ 'id' => (int)$file_id ] );
return true;
}
public static function delete_file( $file_id )
{
global $mdb;
$mdb -> update( 'pp_articles_files', [ 'to_delete' => 1 ], [ 'id' => (int)$file_id ] );
return true;
}
public static function delete_img( $image_id )
{
global $mdb;
$mdb -> update( 'pp_articles_images', [ 'to_delete' => 1 ], [ 'id' => (int)$image_id ] );
return true;
}
public static function article_details( $article_id )
{
global $mdb;
if ( $article = $mdb -> get( 'pp_articles', '*', [ 'id' => (int)$article_id ] ) )
{
$results = $mdb -> select( 'pp_articles_langs', '*', [ 'article_id' => (int)$article_id ] );
if ( is_array( $results ) ) foreach ( $results as $row )
$article['languages'][ $row['lang_id'] ] = $row;
$article['images'] = $mdb -> select( 'pp_articles_images', '*', [ 'article_id' => (int)$article_id, 'ORDER' => [ 'o' => 'ASC', 'id' => 'DESC' ] ] );
$article['files'] = $mdb -> select( 'pp_articles_files', '*', [ 'article_id' => (int)$article_id ] );
$article['pages'] = $mdb -> select( 'pp_articles_pages', 'page_id', [ 'article_id' => (int)$article_id ] );
}
return $article;
}
public static function max_order()
{
global $mdb;
return $mdb -> max( 'pp_articles_pages', 'o' );
}
public static function article_save(
$article_id, $title, $main_image, $entry, $text, $table_of_contents, $status, $show_title, $show_table_of_contents, $show_date_add, $date_add, $show_date_modify, $date_modify, $seo_link, $meta_title, $meta_description, $meta_keywords, $layout_id, $pages,
$noindex, $repeat_entry, $copy_from, $social_icons, $block_direct_access )
{
global $mdb, $user;
if ( !$article_id )
{
$mdb -> insert( 'pp_articles', [
'show_title' => $show_title == 'on' ? 1 : 0,
'show_date_add' => $show_date_add == 'on' ? 1 : 0,
'show_date_modify' => $show_date_modify == 'on' ? 1 : 0,
'date_add' => date( 'Y-m-d H:i:s' ),
'date_modify' => date( 'Y-m-d H:i:s' ),
'modify_by' => $user['id'],
'layout_id' => $layout_id ? (int)$layout_id : null,
'status' => $status == 'on' ? 1 : 0,
'repeat_entry' => $repeat_entry == 'on' ? 1 : 0,
'social_icons' => $social_icons == 'on' ? 1 : 0,
'show_table_of_contents' => $show_table_of_contents == 'on' ? 1 : 0,
] );
$id = $mdb -> id();
if ( $id )
{
foreach ( $title as $key => $val )
{
$mdb -> insert( 'pp_articles_langs', [
'article_id' => (int)$id,
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'main_image' => $main_image[$key] != '' ? $main_image[$key] : null,
'entry' => $entry[$key] != '' ? $entry[$key] : null,
'text' => $text[$key] != '' ? $text[$key] : null,
'table_of_contents' => $table_of_contents[$key] != '' ? $table_of_contents[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key] == 'on' ? 1 : 0,
'copy_from' => $copy_from[$key] != '' ? $copy_from[$key] : null,
'block_direct_access' => $block_direct_access[$key] == 'on' ? 1 : 0
] );
}
if ( is_array( $pages ) ) foreach ( $pages as $page )
{
$order = self::max_order() + 1;
$mdb -> insert( 'pp_articles_pages', [
'article_id' => (int)$id,
'page_id' => (int)$page,
'o' => (int)$order
] );
}
else if ( $pages )
{
$order = self::max_order() + 1;
$mdb -> insert( 'pp_articles_pages', [
'article_id' => (int)$id,
'page_id' => (int)$pages,
'o' => (int)$order
] );
}
$results = $mdb -> select( 'pp_articles_files', '*', [ 'article_id' => null ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$dir = '/upload/article_files/article_' . $id;
$new_file_name = str_replace( '/upload/article_files/tmp', $dir, $row['src'] );
if ( file_exists( '..' . $row['src'] ) )
{
if ( !is_dir( '../' . $dir ) and $created !== true )
{
if ( mkdir( '../' . $dir, 0755, true ) )
$created = true;
}
rename( '..' . $row['src'], '..' . $new_file_name );
}
$mdb -> update( 'pp_articles_files', [ 'src' => $new_file_name, 'article_id' => $id ], [ 'id' => $row['id'] ] );
}
$created = false;
/* zdjęcia */
$results = $mdb -> select( 'pp_articles_images', '*', [ 'article_id' => null ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$dir = '/upload/article_images/article_' . $id;
$new_file_name = str_replace( '/upload/article_images/tmp', $dir, $row['src'] );
if ( file_exists( '../' . $new_file_name ) )
{
$ext = strrpos( $new_file_name, '.' );
$fileName_a = substr( $new_file_name, 0, $ext );
$fileName_b = substr( $new_file_name, $ext );
$count = 1;
while ( file_exists( '../' . $fileName_a . '_' . $count . $fileName_b ) )
$count++;
$new_file_name = $fileName_a . '_' . $count . $fileName_b;
}
if ( file_exists( '..' . $row['src'] ) )
{
if ( !is_dir( '../' . $dir ) and $created !== true )
{
if ( mkdir( '../' . $dir, 0755, true ) )
$created = true;
}
rename( '..' . $row['src'], '..' . $new_file_name );
}
$mdb -> update( 'pp_articles_images', [ 'src' => $new_file_name, 'article_id' => (int)$id ], [ 'id' => $row['id'] ] );
}
\S::htacces();
\S::delete_dir( '../temp/' );
return $id;
}
}
else
{
$mdb -> update( 'pp_articles', [
'show_title' => $show_title == 'on' ? 1 : 0,
'show_date_add' => $show_date_add == 'on' ? 1 : 0,
'show_date_modify' => $show_date_modify == 'on' ? 1 : 0,
'date_modify' => date( 'Y-m-d H:i:s' ),
'modify_by' => $user['id'],
'layout_id' => $layout_id ? (int)$layout_id : null,
'status' => $status == 'on' ? 1 : 0,
'repeat_entry' => $repeat_entry == 'on' ? 1 : 0,
'social_icons' => $social_icons == 'on' ? 1 : 0,
'show_table_of_contents' => $show_table_of_contents == 'on' ? 1 : 0,
], [
'id' => (int)$article_id
] );
foreach ( $title as $key => $val )
{
if ( $translation_id = $mdb -> get( 'pp_articles_langs', 'id', [ 'AND' => [ 'article_id' => $article_id, 'lang_id' => $key ] ] ) )
$mdb -> update( 'pp_articles_langs', [
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'main_image' => $main_image[$key] != '' ? $main_image[$key] : null,
'entry' => $entry[$key] != '' ? $entry[$key] : null,
'text' => $text[$key] != '' ? $text[$key] : null,
'table_of_contents' => $table_of_contents[$key] != '' ? $table_of_contents[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key] == 'on' ? 1 : 0,
'copy_from' => $copy_from[$key] != '' ? $copy_from[$key] : null,
'block_direct_access' => $block_direct_access[$key] == 'on' ? 1 : 0
], [
'id' => $translation_id
] );
else
$mdb -> insert( 'pp_articles_langs', [
'article_id' => (int)$article_id,
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'main_image' => $main_image[$key] != '' ? $main_image[$key] : null,
'entry' => $entry[$key] != '' ? $entry[$key] : null,
'text' => $text[$key] != '' ? $text[$key] : null,
'table_of_contents' => $table_of_contents[$key] != '' ? $table_of_contents[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key] == 'on' ? 1 : 0,
'copy_from' => $copy_from[$key] != '' ? $copy_from[$key] : null,
'block_direct_access' => $block_direct_access[$key] == 'on' ? 1 : 0
] );
}
$not_in = [ 0 ];
if ( is_array( $pages ) ) foreach ( $pages as $page )
$not_in[] = $page;
else if ( $pages )
$not_in[] = $pages;
$mdb -> delete( 'pp_articles_pages', [ 'AND' => [ 'article_id' => (int)$article_id, 'page_id[!]' => $not_in ] ] );
$pages_tmp = $mdb -> select( 'pp_articles_pages', 'page_id', [ 'article_id' => (int)$article_id ] );
if ( !is_array( $pages ) )
$pages = [ $pages ];
$pages = array_diff( $pages, $pages_tmp );
if ( is_array( $pages ) ) foreach ( $pages as $page )
{
$order = self::max_order() + 1;
$mdb -> insert( 'pp_articles_pages', [
'article_id' => (int)$article_id,
'page_id' => (int)$page,
'o' => (int)$order
] );
}
$results = $mdb -> select( 'pp_articles_files', '*', [ 'article_id' => null ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$dir = '/upload/article_files/article_' . $article_id;
$new_file_name = str_replace( '/upload/article_files/tmp', $dir, $row['src'] );
if ( file_exists( '..' . $row['src'] ) )
{
if ( !is_dir( '../' . $dir ) and $created !== true )
{
if ( mkdir( '../' . $dir, 0755, true ) )
$created = true;
}
rename( '..' . $row['src'], '..' . $new_file_name );
}
$mdb -> update( 'pp_articles_files', [ 'src' => $new_file_name, 'article_id' => (int)$article_id ], [ 'id' => $row['id'] ] );
}
$created = false;
/* zdjęcia */
$results = $mdb -> select( 'pp_articles_images', '*', [ 'article_id' => null ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$dir = '/upload/article_images/article_' . $article_id;
$new_file_name = str_replace( '/upload/article_images/tmp', $dir, $row['src'] );
if ( file_exists( '../' . $new_file_name ) )
{
$ext = strrpos( $new_file_name, '.' );
$fileName_a = substr( $new_file_name, 0, $ext );
$fileName_b = substr( $new_file_name, $ext );
$count = 1;
while ( file_exists( '../' . $fileName_a . '_' . $count . $fileName_b ) )
$count++;
$new_file_name = $fileName_a . '_' . $count . $fileName_b;
}
if ( file_exists( '..' . $row['src'] ) )
{
if ( !is_dir( '../' . $dir ) and $created !== true )
{
if ( mkdir( '../' . $dir, 0755, true ) )
$created = true;
}
rename( '..' . $row['src'], '..' . $new_file_name );
}
$mdb -> update( 'pp_articles_images', [ 'src' => $new_file_name, 'article_id' => (int)$article_id ], [ 'id' => $row['id'] ] );
}
$results = $mdb -> select( 'pp_articles_images', '*', [ 'AND' => [ 'article_id' => (int)$article_id, 'to_delete' => 1 ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
if ( file_exists( '../' . $row['src'] ) )
unlink( '../' . $row['src'] );
}
$mdb -> delete( 'pp_articles_images', [ 'AND' => [ 'article_id' => (int)$article_id, 'to_delete' => 1 ] ] );
$results = $mdb -> select( 'pp_articles_files', '*', [ 'AND' => [ 'article_id' => (int)$article_id, 'to_delete' => 1 ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
if ( file_exists( '../' . $row['src'] ) )
unlink( '../' . $row['src'] );
}
$mdb -> delete( 'pp_articles_files', [ 'AND' => [ 'article_id' => (int)$article_id, 'to_delete' => 1 ] ] );
\S::htacces();
\S::delete_dir( '../temp/' );
return $article_id;
}
}
public static function delete_nonassigned_files()
{
global $mdb;
$results = $mdb -> select( 'pp_articles_files', '*', [ 'article_id' => null ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
if ( file_exists( '../' . $row['src'] ) )
unlink( '../' . $row['src'] );
}
$mdb -> delete( 'pp_articles_files', [ 'article_id' => null ] );
}
public static function delete_nonassigned_images()
{
global $mdb;
$results = $mdb -> select( 'pp_articles_images', '*', [ 'article_id' => null ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
if ( file_exists( '../' . $row['src'] ) )
unlink( '../' . $row['src'] );
}
$mdb -> delete( 'pp_articles_images', [ 'article_id' => null ] );
}
}
?>

View File

@@ -1,27 +0,0 @@
<?php
namespace admin\factory;
class ArticlesArchive
{
public static function article_restore( $article_id )
{
global $mdb;
return $mdb -> update( 'pp_articles', [ 'status' => 0 ], [ 'id' => (int)$article_id ] );
}
public static function article_delete( $article_id )
{
global $mdb;
$mdb -> delete( 'pp_articles_pages', [ 'article_id' => (int)$article_id ] );
$mdb -> delete( 'pp_articles_langs', [ 'article_id' => (int)$article_id ] );
$mdb -> delete( 'pp_articles_images', [ 'article_id' => (int)$article_id ] );
$mdb -> delete( 'pp_articles_files', [ 'article_id' => (int)$article_id ] );
$mdb -> delete( 'pp_articles', [ 'id' => (int)$article_id ] );
\S::delete_dir( '../upload/article_images/article_' . (int)$article_id . '/' );
\S::delete_dir( '../upload/article_files/article_' . (int)$article_id . '/' );
return true;
}
}

View File

@@ -1,108 +0,0 @@
<?php
namespace admin\factory;
class Banners
{
public static function banner_delete( $banner_id )
{
global $mdb;
$result = $mdb -> delete( 'pp_banners', [ 'id' => (int) $banner_id ] );
\S::delete_dir( '../temp/' );
return $result;
}
public static function banner_save( $banner_id, $name, $status, $date_start, $date_end, $home_page, $src, $url, $html, $text )
{
global $mdb;
if ( !$banner_id )
{
$mdb -> insert( 'pp_banners', [
'name' => $name,
'status' => $status == 'on' ? 1 : 0,
'date_start' => $date_start != '' ? $date_start : null,
'date_end' => $date_end != '' ? $date_end : null,
'home_page' => $home_page == 'on' ? 1 : 0
] );
$id = $mdb -> id();
if ( $id )
{
foreach ( $src as $key => $val )
{
$mdb -> insert( 'pp_banners_langs', [
'id_banner' => (int)$id,
'id_lang' => $key,
'src' => $src[$key],
'url' => $url[$key],
'html' => $html[$key],
'text' => $text[$key]
] );
}
\S::delete_dir( '../temp/' );
return $id;
}
}
else
{
$mdb -> update( 'pp_banners', [
'name' => $name,
'status' => $status == 'on' ? 1 : 0,
'date_start' => $date_start != '' ? $date_start : null,
'date_end' => $date_end != '' ? $date_end : null,
'home_page' => $home_page == 'on' ? 1 : 0
], [
'id' => (int)$banner_id
] );
foreach ( $src as $key => $val )
{
if ( $translation_id = $mdb -> get( 'pp_banners_langs', 'id', [ 'AND' => [ 'banner_id' => $banner_id, 'lang_id' => $key ] ] ) )
$mdb -> update( 'pp_banners_langs', [
'id_lang' => $key,
'src' => $src[$key],
'url' => $url[$key],
'html' => $html[$key],
'text' => $text[$key]
], [
'id' => $translation_id
] );
else
$mdb -> insert( 'pp_banners_langs', [
'id_banner' => (int)$banner_id,
'id_lang' => $key,
'src' => $src[$key],
'url' => $url[$key],
'html' => $html[$key],
'text' => $text[$key]
] );
}
\S::delete_dir( '../temp/' );
return $banner_id;
}
return false;
}
public static function banner_details( $id_banner )
{
global $mdb;
$banner = $mdb -> get( 'pp_banners', '*', [ 'id' => (int)$id_banner ] );
$results = $mdb -> select( 'pp_banners_langs', '*', [ 'id_banner' => (int)$id_banner ] );
if ( is_array( $results ) ) foreach ( $results as $row )
$banner['languages'][$row['id_lang']] = $row;
return $banner;
}
}
?>

View File

@@ -1,39 +0,0 @@
<?
namespace admin\factory;
class Baselinker {
// zapis wiązania produktów
static public function bundling_products_save( $values ) {
global $mdb;
foreach ( $values as $key => $val ) {
$key = explode( '_', $key );
$mdb -> update( 'pp_shop_products', [ 'baselinker_product_id' => $val ], [ 'id' => $key[1] ] );
}
}
// pobranie produktów z Baselinkera
static public function products_list() {
global $settings;
$methodParams = '{
"storage_id": "bl_1"
}';
$apiParams = [
"token" => $settings['baselinker_api'],
"method" => "getProductsList",
"parameters" => $methodParams
];
$curl = curl_init( "https://api.baselinker.com/connector.php" );
curl_setopt( $curl, CURLOPT_POST, 1 );
curl_setopt( $curl, CURLOPT_POSTFIELDS, http_build_query( $apiParams ) );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
$response = json_decode( curl_exec( $curl ), true );
if ( $response['status'] == 'SUCCESS' )
return $response['products'];
}
}

View File

@@ -1,89 +0,0 @@
<?
namespace admin\factory;
class Dictionaries
{
static public function all_units()
{
global $mdb;
$results = $mdb -> select( 'pp_units', '*' );
foreach ( $results as $row )
{
$resutls2 = $mdb -> query( 'SELECT text FROM pp_units_langs AS psl, pp_langs AS pl WHERE unit_id = ' . $row['id'] . ' AND lang_id = pl.id AND text != \'\' ORDER BY o ASC LIMIT 1' ) -> fetchAll( \PDO::FETCH_ASSOC );
$row['text'] = $resutls2[0]['text'];
$units[ $row['id'] ] = $row;
}
return $units;
}
static public function unit_details( $unit_id )
{
global $mdb;
$unit = $mdb -> get( 'pp_units', '*', [ 'id' => (int)$unit_id ] );
$results = $mdb -> select( 'pp_units_langs', '*', [ 'unit_id' => (int)$unit_id ] );
if ( is_array( $results ) ) foreach ( $results as $row )
$unit['languages'][ $row['lang_id'] ] = $row;
return $unit;
}
static public function unit_save( $unit_id, $text )
{
global $mdb;
if ( !$unit_id )
{
$mdb -> insert( 'pp_units', array());
$id = $mdb -> id();
if ( $id )
{
foreach ( $text as $key => $val )
{
$mdb -> insert( 'pp_units_langs', [
'unit_id' => (int)$id,
'lang_id' => $key,
'text' => $text[$key]
] );
}
\S::delete_dir( '../temp/' );
return $id;
}
}
else
{
foreach ( $text as $key => $val )
{
if ( $translation_id = $mdb -> get( 'pp_units_langs', 'id', [ 'AND' => [ 'unit_id' => $unit_id, 'lang_id' => $key ] ] ) )
$mdb -> update( 'pp_units_langs', [
'lang_id' => $key,
'text' => $text[$key]
], [
'id' => $translation_id
] );
else
$mdb -> insert( 'pp_units_langs', [
'unit_id' => (int)$unit_id,
'lang_id' => $key,
'text' => $text[$key]
] );
}
\S::delete_dir( '../temp/dictionaries' );
return $unit_id;
}
}
static public function unit_delete( $unit_id )
{
global $mdb;
return $mdb -> delete( 'pp_units', [ 'id' => (int)$unit_id ] );
}
}

View File

@@ -1,264 +0,0 @@
<?
namespace admin\factory;
class Integrations {
// sellasist_product_select_delete
static public function sellasist_product_select_delete( int $product_id ) {
global $mdb;
return $mdb -> update( 'pp_shop_products', [ 'sellasist_product_id' => null, 'sellasist_product_name' => null ], [ 'id' => $product_id ] );
}
// sellasist_product_select_save
static public function sellasist_product_select_save( int $product_id, $sellasist_product_id, $sellasist_product_name ) {
global $mdb;
return $mdb -> update( 'pp_shop_products', [ 'sellasist_product_id' => $sellasist_product_id, 'sellasist_product_name' => \S::remove_special_chars( $sellasist_product_name ) ], [ 'id' => $product_id ] );
}
// apilo delete product linking
static public function apilo_product_select_delete( int $product_id ) {
global $mdb;
return $mdb -> update( 'pp_shop_products', [ 'apilo_product_id' => null, 'apilo_product_name' => null ], [ 'id' => $product_id ] );
}
// baselinker delete product linking
static public function baselinker_product_select_delete( int $product_id ) {
global $mdb;
return $mdb -> update( 'pp_shop_products', [ 'baselinker_product_id' => null, 'baselinker_product_name' => null ], [ 'id' => $product_id ] );
}
// apilo product select save
static public function apilo_product_select_save( int $product_id, $apilo_product_id, $apilo_product_name ) {
global $mdb;
return $mdb -> update( 'pp_shop_products', [ 'apilo_product_id' => $apilo_product_id, 'apilo_product_name' => \S::remove_special_chars( $apilo_product_name ) ], [ 'id' => $product_id ] );
}
static public function baselinker_product_select_save( int $product_id, $baselinker_product_id, $baselinker_product_name ) {
global $mdb;
return $mdb -> update( 'pp_shop_products', [ 'baselinker_product_id' => $baselinker_product_id, 'baselinker_product_name' => $baselinker_product_name ], [ 'id' => $product_id ] );
}
// get settings for shoppro integration
static public function shoppro_settings( $name = '' )
{
global $mdb;
if ( $name )
{
return $mdb -> get( 'pp_shop_shoppro_settings', 'value', [ 'name' => $name ] );
}
$results = $mdb -> query( 'SELECT * FROM pp_shop_shoppro_settings' ) -> fetchAll( \PDO::FETCH_ASSOC );
$settings = [];
foreach ( $results as $result )
{
$settings[$result['name']] = $result['value'];
}
return $settings;
}
// get settings for the sellasist integration
static public function sellasist_settings( $name = '' )
{
global $mdb;
if ( $name )
{
return $mdb -> get( 'pp_shop_sellasist_settings', 'value', [ 'name' => $name ] );
}
$results = $mdb -> query( 'SELECT * FROM pp_shop_sellasist_settings' ) -> fetchAll( \PDO::FETCH_ASSOC );
$settings = [];
foreach ( $results as $result )
{
$settings[$result['name']] = $result['value'];
}
return $settings;
}
// get settings for the Baselinker integration
static public function baselinker_settings( $name = '' )
{
global $mdb;
if ( $name )
{
return $mdb -> get( 'pp_shop_baselinker_settings', 'value', [ 'name' => $name ] );
}
$results = $mdb -> query( 'SELECT * FROM pp_shop_baselinker_settings' ) -> fetchAll( \PDO::FETCH_ASSOC );
$settings = [];
foreach ( $results as $result )
{
$settings[$result['name']] = $result['value'];
}
return $settings;
}
// get settings for the APILO plugin
static public function apilo_settings( $name = '' )
{
global $mdb;
if ( $name )
{
return $mdb -> get( 'pp_shop_apilo_settings', 'value', [ 'name' => $name ] );
}
$results = $mdb -> query( 'SELECT * FROM pp_shop_apilo_settings' ) -> fetchAll( \PDO::FETCH_ASSOC );
$settings = [];
foreach ( $results as $result )
{
$settings[$result['name']] = $result['value'];
}
return $settings;
}
// save settings for shoppro integration
static public function shoppro_settings_save( $field_id, $value )
{
global $mdb;
if ( $mdb -> count( 'pp_shop_shoppro_settings', [ 'name' => $field_id ] ) ) {
$mdb -> update( 'pp_shop_shoppro_settings', [ 'value' => $value ], [ 'name' => $field_id ] );
} else {
$mdb -> insert( 'pp_shop_shoppro_settings', [ 'name' => $field_id, 'value' => $value ] );
}
return true;
}
// save settings for the sellasist integration
static public function sellasist_settings_save( $field_id, $value )
{
global $mdb;
if ( $mdb -> count( 'pp_shop_sellasist_settings', [ 'name' => $field_id ] ) ) {
$mdb -> update( 'pp_shop_sellasist_settings', [ 'value' => $value ], [ 'name' => $field_id ] );
} else {
$mdb -> insert( 'pp_shop_sellasist_settings', [ 'name' => $field_id, 'value' => $value ] );
}
return true;
}
// save settings for the Baselinker integration
static public function baselinker_settings_save( $field_id, $value )
{
global $mdb;
if ( $mdb -> count( 'pp_shop_baselinker_settings', [ 'name' => $field_id ] ) ) {
$mdb -> update( 'pp_shop_baselinker_settings', [ 'value' => $value ], [ 'name' => $field_id ] );
} else {
$mdb -> insert( 'pp_shop_baselinker_settings', [ 'name' => $field_id, 'value' => $value ] );
}
return true;
}
// save settings for the APILO plugin
static public function apilo_settings_save( $field_id, $value )
{
global $mdb;
if ( $mdb -> count( 'pp_shop_apilo_settings', [ 'name' => $field_id ] ) ) {
$mdb -> update( 'pp_shop_apilo_settings', [ 'value' => $value ], [ 'name' => $field_id ] );
} else {
$mdb -> insert( 'pp_shop_apilo_settings', [ 'name' => $field_id, 'value' => $value ] );
}
return true;
}
// authorization in apilo.com
static public function apilo_authorization( $client_id, $client_secret, $authorization_code )
{
global $mdb;
$url = "https://projectpro.apilo.com/rest/auth/token/";
$postData['grantType'] = 'authorization_code';
$postData['token'] = $authorization_code;
$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $postData ) );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Basic " . base64_encode( $client_id . ":" . $client_secret ),
"Accept: application/json"
] );
$response = curl_exec( $ch );
if ( curl_errno( $ch ) ) {
return false;
}
curl_close( $ch );
$response = json_decode( $response, true );
$access_token = $response['accessToken'];
$refresh_token = $response['refreshToken'];
$access_token_expire_at = $response['accessTokenExpireAt'];
$refresh_token_expire_at = $response['refreshTokenExpireAt'];
self::apilo_settings_save( 'access-token', $access_token );
self::apilo_settings_save( 'refresh-token', $refresh_token );
self::apilo_settings_save( 'access-token-expire-at', $access_token_expire_at );
self::apilo_settings_save( 'refresh-token-expire-at', $refresh_token_expire_at );
return true;
}
// get access token or refresh it apilo.com
static public function apilo_get_access_token()
{
global $mdb;
$apilo_settings = self::apilo_settings();
$date1 = new \DateTime( $apilo_settings['access-token-expire-at'] );
$date2 = new \DateTime( date( 'Y-m-d H:i:s' ) );
if ( $date1 < $date2 )
{
$post_data = [
'grantType' => 'refresh_token',
'token' => $apilo_settings['refresh-token']
];
$ch = curl_init( "https://projectpro.apilo.com/rest/auth/token/" );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Basic " . base64_encode( $apilo_settings['client-id'] . ":" . $apilo_settings['client-secret'] ),
"Accept: application/json"
] );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $post_data ) );
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$response = curl_exec( $ch );
if ( curl_errno( $ch ) ) {
return false;
}
curl_close( $ch );
$response = json_decode( $response, true );
$access_token = $response['accessToken'];
$refresh_token = $response['refreshToken'];
$access_token_expire_at = $response['accessTokenExpireAt'];
$refresh_token_expire_at = $response['refreshTokenExpireAt'];
if ( $access_token == '' ) {
return false;
}
self::apilo_settings_save( 'access-token', $access_token );
self::apilo_settings_save( 'refresh-token', $refresh_token );
self::apilo_settings_save( 'access-token-expire-at', $access_token_expire_at );
self::apilo_settings_save( 'refresh-token-expire-at', $refresh_token_expire_at );
return $access_token;
}
return $apilo_settings['access-token'];
}
}

View File

@@ -1,141 +0,0 @@
<?
namespace admin\factory;
class Languages
{
public static function translation_delete( $translation_id )
{
global $mdb;
return $mdb -> delete( 'pp_langs_translations', [ 'id' => $translation_id ] );
}
public static function translation_save( $translation_id, $text, $languages )
{
global $mdb;
if ( $translation_id )
{
$mdb -> update( 'pp_langs_translations', [ 'text' => $text ], [ 'id' => $translation_id ] );
if ( is_array( $languages ) and !empty( $languages ) ): foreach ( $languages as $key => $val ):
$mdb -> update( 'pp_langs_translations', [ $key => $val ], [ 'id' => $translation_id ] );
endforeach; endif;
\S::htacces();
\S::delete_dir( '../temp/' );
return $translation_id;
}
else
{
$mdb -> insert( 'pp_langs_translations', [ 'text' => $text ] );
if ( $translation_id = $mdb -> id() )
{
if ( is_array( $languages ) and !empty( $languages ) ): foreach ( $languages as $key => $val ):
$mdb -> update( 'pp_langs_translations', [ $key => $val ], [ 'id' => $translation_id ] );
endforeach; endif;
}
\S::htacces();
\S::delete_dir( '../temp/' );
return $translation_id;
}
}
public static function translation_details( $translation_id )
{
global $mdb;
return $mdb -> get( 'pp_langs_translations', '*', [ 'id' => $translation_id ] );
}
public static function language_delete( $language_id )
{
global $mdb;
if ( $mdb -> count( 'pp_langs' ) > 1 )
{
if ( $mdb -> query( 'ALTER TABLE pp_langs_translations DROP ' . $language_id )
and
$mdb -> delete( 'pp_langs', [ 'id' => $language_id ] )
)
return true;
}
return false;
}
public static function max_order()
{
global $mdb;
return $mdb -> max( 'pp_langs', 'o' );
}
public static function language_save( $language_id, $name, $status, $start, $o )
{
global $mdb;
if ( $start == 'on' )
$mdb -> update( 'pp_langs', [
'start' => 0
], [
'id[!]' => $language_id
] );
if ( $mdb -> count( 'pp_langs', [ 'id' => $language_id ] ) )
{
$mdb -> update( 'pp_langs',
[
'status' => $status == 'on' ? 1 : 0,
'start' => $start == 'on' ? 1 : 0,
'name' => $name,
'o' => $o
], [
'id' => $language_id
] );
if ( !$mdb -> count( 'pp_langs', [ 'start' => 1 ] ) )
{
$id_tmp = $mdb -> get( 'pp_langs', 'id', [ 'ORDER' => [ 'o' => 'ASC' ] ] );
$mdb -> update( 'pp_langs', [ 'start' => 1 ], [ 'id' => $id_tmp ] );
}
\S::htacces();
\S::delete_dir( '../temp/' );
return $language_id;
}
else
{
if ( $mdb -> query( 'ALTER TABLE pp_langs_translations ADD ' . $language_id . ' TEXT NULL DEFAULT NULL' ) )
{
$mdb -> insert( 'pp_langs',
[
'id' => $language_id,
'name' => $name,
'status' => $status == 'on' ? 1 : 0,
'start' => $start == 'on' ? 1 : 0,
'o' => $o
] );
\S::htacces();
\S::delete_dir( '../temp/' );
return $language_id;
}
}
return faslse;
}
public static function language_details( $language_id )
{
global $mdb;
return $mdb -> get( 'pp_langs', '*', [ 'id' => $language_id ] );
}
public static function languages_list( $only_active = false )
{
global $mdb;
$where = [];
if ( $only_active )
$where['status'] = 1;
return $mdb -> select( 'pp_langs', '*', array_merge( [ 'ORDER' => [ 'o' => 'ASC' ] ], $where ) );
}
}
?>

View File

@@ -1,190 +0,0 @@
<?php
namespace admin\factory;
class Layouts
{
public static function layout_delete( $layout_id )
{
global $mdb;
if ( $mdb -> count( 'pp_layouts' ) > 1 )
return $mdb -> delete( 'pp_layouts', [ 'id' => (int)$layout_id ] );
return false;
}
public static function layout_details( $layout_id )
{
global $mdb;
$layout = $mdb -> get( 'pp_layouts', '*', [ 'id' => (int)$layout_id ] );
$layout['pages'] = $mdb -> select( 'pp_layouts_pages', 'page_id', [ 'layout_id' => (int)$layout_id ] );
$layout['categories'] = $mdb -> select( 'pp_layouts_categories', 'category_id', [ 'layout_id' => (int)$layout_id ] );
return $layout;
}
public static function layout_save( $layout_id, $name, $status, $pages, $html, $css, $js, $m_html, $m_css, $m_js, $categories, $categories_default )
{
global $mdb;
if ( !$layout_id )
{
if ( $status == 'on' )
$mdb -> update( 'pp_layouts', [ 'status' => 0 ] );
if ( $categories_default == 'on' )
$mdb -> update( 'pp_layouts', [ 'categories_default' => 0 ] );
$mdb -> insert( 'pp_layouts', [
'name' => $name,
'html' => $html,
'css' => $css,
'js' => $js,
'm_html' => $m_html,
'm_css' => $m_css,
'm_js' => $m_js,
'status' => $status == 'on' ? 1 : 0,
'categories_default' => $categories_default == 'on' ? 1 : 0
] );
$id = $mdb -> id();
if ( $id )
{
if ( is_array( $pages ) ) foreach ( $pages as $page )
{
$mdb -> delete( 'pp_layouts_pages', [ 'page_id' => (int)$page ] );
$mdb -> insert( 'pp_layouts_pages', [
'layout_id' => (int)$id,
'page_id' => (int)$page
] );
}
else if ( $pages )
{
$mdb -> delete( 'pp_layouts_pages', [ 'page_id' => (int)$pages ] );
$mdb -> insert( 'pp_layouts_pages', [
'layout_id' => (int)$id,
'page_id' => (int)$pages
] );
}
if ( is_array( $categories ) ) foreach ( $categories as $category )
{
$mdb -> delete( 'pp_layouts_categories', [ 'category_id' => (int)$category ] );
$mdb -> insert( 'pp_layouts_categories', [
'layout_id' => (int)$id,
'category_id' => (int)$category
] );
}
else if ( $categories )
{
$mdb -> delete( 'pp_layouts_categories', [ 'category_id' => (int)$categories ] );
$mdb -> insert( 'pp_layouts_categories', [
'layout_id' => (int)$id,
'category_id' => (int)$categories
] );
}
\S::delete_dir( '../temp/' );
return $id;
}
}
else
{
if ( $status == 'on' )
$mdb -> update( 'pp_layouts', [ 'status' => 0 ] );
if ( $categories_default == 'on' )
$mdb -> update( 'pp_layouts', [ 'categories_default' => 0 ] );
$mdb -> update( 'pp_layouts', [
'name' => $name,
'html' => $html,
'css' => $css,
'js' => $js,
'm_html' => $m_html,
'm_css' => $m_css,
'm_js' => $m_js,
'status' => $status == 'on' ? 1 : 0,
'categories_default' => $categories_default == 'on' ? 1 : 0
], [
'id' => $layout_id
] );
$mdb -> delete( 'pp_layouts_pages', [ 'layout_id' => (int)$layout_id ] );
if ( is_array( $pages ) ) foreach ( $pages as $page )
{
$mdb -> delete( 'pp_layouts_pages', [ 'page_id' => (int)$page ] );
$mdb -> insert( 'pp_layouts_pages', [
'layout_id' => (int)$layout_id,
'page_id' => (int)$page
] );
}
else if ( $pages )
{
$mdb -> delete( 'pp_layouts_pages', [ 'page_id' => (int)$pages ] );
$mdb -> insert( 'pp_layouts_pages', [
'layout_id' => (int)$layout_id,
'page_id' => (int)$pages
] );
}
$mdb -> delete( 'pp_layouts_categories', [ 'layout_id' => (int)$layout_id ] );
if ( is_array( $categories ) ) foreach ( $categories as $category )
{
$mdb -> delete( 'pp_layouts_categories', [ 'category_id' => (int)$category ] );
$mdb -> insert( 'pp_layouts_categories', [
'layout_id' => (int)$layout_id,
'category_id' => (int)$category
] );
}
else if ( $categories )
{
$mdb -> delete( 'pp_layouts_categories', [ 'category_id' => (int)$categories ] );
$mdb -> insert( 'pp_layouts_categories', [
'layout_id' => (int)$layout_id,
'category_id' => (int)$categories
] );
}
\S::delete_dir( '../temp/' );
return $layout_id;
}
return false;
}
public static function menus_list()
{
global $mdb;
$results = $mdb -> select( 'pp_menus', 'id', [ 'ORDER' => [ 'id' => 'ASC' ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$menu = \admin\factory\Pages::menu_details( $row );
$menu['pages'] = \admin\factory\Pages::menu_pages( $row );
$menus[] = $menu;
}
return $menus;
}
public static function layouts_list()
{
global $mdb;
return $mdb -> select( 'pp_layouts', '*', [ 'ORDER' => [ 'name' => 'ASC' ] ] );
}
}
?>

View File

@@ -1,76 +0,0 @@
<?php
namespace admin\factory;
class Newsletter
{
public static function is_admin_template( $template_id )
{
global $mdb;
return $mdb -> get( 'pp_newsletter_templates', 'is_admin', [ 'id' => (int)$template_id ] );
}
public static function newsletter_template_delete( $template_id )
{
global $mdb;
return $mdb -> delete( 'pp_newsletter_templates', [ 'id' => (int)$template_id ] );
}
public static function send( $dates, $template )
{
global $mdb;
$results = $mdb -> select( 'pp_newsletter', 'email', [ 'status' => 1 ] );
if ( is_array( $results ) and !empty( $results ) ) foreach ( $results as $row )
{
$mdb -> insert( 'pp_newsletter_send', [
'email' => $row,
'dates' => $dates,
'id_template' => $template ? $template : null
] );
}
return true;
}
public static function email_template_detalis ($id_template)
{
global $mdb;
$result = $mdb -> get ('pp_newsletter_templates', '*', [ 'id' => (int)$id_template ] );
return $result;
}
public static function template_save( $id, $name, $text )
{
global $mdb;
if ( !$id )
{
if ( $mdb -> insert( 'pp_newsletter_templates', [
'name' => $name,
'text' => $text
] ) )
{
\S::delete_dir( '../temp/' );
return $mdb -> id();
}
}
else
{
$mdb -> update( 'pp_newsletter_templates', [
'name' => $name,
'text' => $text
], [
'id' => (int)$id
] );
\S::delete_dir( '../temp/' );
return $id;
}
}
public static function templates_list()
{
global $mdb;
return $mdb -> select( 'pp_newsletter_templates', '*', [ 'is_admin' => 0, 'ORDER' => [ 'name' => 'ASC' ] ] );
}
}

View File

@@ -1,407 +0,0 @@
<?
namespace admin\factory;
class Pages
{
public static $_page_types = [ 0 => 'pełne artykuły', 1 => 'wprowadzenia', 2 => 'miniaturki', 3 => 'link', 4 => 'kontakt', 5 => 'kategoria sklepu' ];
public static $_sort_types = [
0 => 'data dodania - najstarsze na początku',
1 => 'data dodania - najnowsze na początku',
2 => 'data modyfikacji - rosnąco',
3 => 'data mofyfikacji - malejąco',
4 => 'ręczne',
5 => 'alfabetycznie - A - Z',
6 => 'alfabetycznie - Z - A'
];
public static function save_articles_order( $page_id, $articles )
{
global $mdb;
if ( is_array( $articles ) )
{
$mdb -> update( 'pp_articles_pages', [ 'o' => 0 ], [ 'page_id' => (int)$page_id ] );
for ( $i = 0; $i < count( $articles ); $i++ )
{
if ( $articles[$i]['item_id'] )
{
$x++;
$mdb -> update( 'pp_articles_pages', [ 'o' => $x ], [ 'AND' => [ 'page_id' => (int)$page_id, 'article_id' => $articles[ $i ]['item_id'] ] ] );
}
}
}
return true;
}
public static function page_articles( $page_id )
{
global $mdb;
$results = $mdb -> query( 'SELECT '
. 'article_id, o, status '
. 'FROM '
. 'pp_articles_pages AS ap '
. 'INNER JOIN pp_articles AS a ON a.id = ap.article_id '
. 'WHERE '
. 'page_id = ' . (int)$page_id . ' AND status != -1 '
. 'ORDER BY '
. 'o ASC' ) -> fetchAll();
if ( is_array( $results ) ) foreach ( $results as $row )
{
$row['title'] = \admin\factory\Articles::article_title( $row['article_id'] );
$articles[] = $row;
}
return $articles;
}
public static function menus_list()
{
global $mdb;
return $mdb -> select( 'pp_menus', '*', [ 'ORDER' => [ 'id' => 'ASC' ] ] );
}
public static function save_pages_order( $menu_id, $pages )
{
global $mdb;
if ( is_array( $pages ) )
{
$mdb -> update( 'pp_pages', [ 'o' => 0 ], [ 'menu_id' => (int)$menu_id ] );
for ( $i = 0; $i < count( $pages ); $i++ )
{
if ( $pages[$i]['item_id'] )
{
$pages[$i]['parent_id'] ? $parent_id = $pages[$i]['parent_id'] : $parent_id = 0;
if ( $pages[$i]['item_id'] && $pages[$i]['depth'] > 1 )
{
if ( $pages[$i]['depth'] == 2 )
$parent_id = null;
$x++;
$mdb -> update( 'pp_pages', [ 'o' => $x, 'parent_id' => $parent_id ], [ 'id' => (int)$pages[ $i ]['item_id'] ] );
}
}
}
}
\S::delete_dir( '../temp/' );
return true;
}
public static function page_delete( $page_id )
{
global $mdb;
if ( $mdb -> count( 'pp_pages', [ 'parent_id' => (int)$page_id ] ) )
return false;
return $mdb -> delete( 'pp_pages', [ 'id' => (int)$page_id ] );
}
public static function max_order()
{
global $mdb;
return $mdb -> max( 'pp_pages', 'o' );
}
public static function page_save(
$page_id, $title, $seo_link, $meta_title, $meta_description, $meta_keywords, $menu_id, $parent_id, $page_type, $sort_type, $layout_id, $articles_limit, $show_title, $status,
$link, $noindex, $start, $page_title, $canonical, $category_id
)
{
global $mdb;
if ( !$parent_id )
$parent_id = null;
if ( !$page_id )
{
$order = self::max_order() + 1;
$mdb -> insert( 'pp_pages', [
'menu_id' => (int)$menu_id,
'page_type' => $page_type,
'sort_type' => $sort_type,
'articles_limit' => $articles_limit,
'show_title' => $show_title == 'on' ? 1 : 0,
'status' => $status == 'on' ? 1 : 0,
'o' => (int)$order,
'parent_id' => $parent_id,
'start' => $start == 'on' ? 1 : 0,
'category_id' => ( $category_id and $page_type == 5 ) ? $category_id : null
] );
$id = $mdb -> id();
if ( $id )
{
if ( $start )
$mdb -> update( 'pp_pages', [ 'start' => 0 ], [ 'id[!]' => (int)$id ] );
if ( $layout_id )
$mdb -> insert( 'pp_layouts_pages', [ 'page_id' => (int)$id, 'layout_id' => (int)$layout_id ] );
foreach ( $title as $key => $val )
{
$mdb -> insert( 'pp_pages_langs', [
'page_id' => (int)$id,
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key],
'page_title' => $page_title[$key] != '' ? $page_title[$key] : null,
'link' => ( $link[$key] and $page_type == 3 ) ? $link[$key] : null,
'canonical' => $canonical[$key] != '' ? $canonical[$key] : null
] );
}
\S::htacces();
\S::delete_dir( '../temp/' );
return $id;
}
}
else
{
$mdb -> update( 'pp_pages', [
'menu_id' => (int)$menu_id,
'page_type' => $page_type,
'sort_type' => $sort_type,
'articles_limit' => $articles_limit,
'show_title' => $show_title == 'on' ? 1 : 0,
'status' => $status == 'on' ? 1 : 0,
'parent_id' => $parent_id,
'start' => $start == 'on' ? 1 : 0,
'category_id' => ( $category_id and $page_type == 5 ) ? $category_id : null
], [
'id' => (int)$page_id
] );
if ( $layout_id )
{
$mdb -> delete( 'pp_layouts_pages', [ 'page_id' => (int)$page_id ] );
$mdb -> insert( 'pp_layouts_pages', [ 'layout_id' => (int)$layout_id, 'page_id' => (int)$page_id ] );
}
if ( $start )
$mdb -> update( 'pp_pages', [ 'start' => 0 ], [ 'id[!]' => (int)$page_id ] );
foreach ( $title as $key => $val )
{
if ( $translation_id = $mdb -> get( 'pp_pages_langs', 'id', [ 'AND' => [ 'page_id' => $page_id, 'lang_id' => $key ] ] ) )
$mdb -> update( 'pp_pages_langs', [
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key],
'page_title' => $page_title[$key] != '' ? $page_title[$key] : null,
'link' => ( $link[$key] and $page_type == 3 ) ? $link[$key] : null,
'canonical' => $canonical[$key] != '' ? $canonical[$key] : null
], [
'id' => $translation_id
] );
else
$mdb -> insert( 'pp_pages_langs', [
'page_id' => (int)$page_id,
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key],
'page_title' => $page_title[$key] != '' ? $page_title[$key] : null,
'link' => ( $link[$key] and $page_type == 3 ) ? $link[$key] : null,
'canonical' => $canonical[$key] != '' ? $canonical[$key] : null
] );
}
self::update_supages_menu_id( $page_id, $menu_id );
\S::htacces();
\S::delete_dir( '../temp/' );
return $page_id;
}
return false;
}
public static function update_supages_menu_id( $parent_id, $menu_id )
{
global $mdb;
$mdb -> update( 'pp_pages', [ 'menu_id' => (int)$menu_id ], [ 'parent_id' => $parent_id ] );
$results = $mdb -> select( 'pp_pages', [ 'id' ], [ 'parent_id' => $parent_id ] );
if ( is_array( $results ) ) foreach ( $results as $row )
self::update_supages_menu_id( $row['id'], $menu_id );
}
public static function generate_seo_link( $title, $page_id, $article_id, $category_id )
{
global $mdb;
$seo_link = \S::seo( $title );
while ( !$seo_link_check )
{
if ( $mdb -> count( 'pp_pages_langs', [ 'AND' => [ 'seo_link' => $seo_link, 'page_id[!]' => (int)$page_id ] ] ) )
$seo_link = \S::seo( $title ) . '-' . ( ++$i );
else
$seo_link_check = true;
}
$seo_link_check = false;
while ( !$seo_link_check )
{
if ( $mdb -> count( 'pp_articles_langs', [ 'AND' => [ 'seo_link' => $seo_link, 'article_id[!]' => (int)$article_id ] ] ) )
$seo_link = \S::seo( $title ) . '-' . ( ++$i );
else
$seo_link_check = true;
}
$seo_link_check = false;
while ( !$seo_link_check )
{
if ( $mdb -> count( 'pp_shop_categories_langs', [ 'AND' => [ 'seo_link' => $seo_link, 'category_id[!]' => (int)$category_id ] ] ) )
$seo_link = \S::seo( $title ) . '-' . ( ++$i );
else
$seo_link_check = true;
}
return $seo_link;
}
public static function menu_delete( $menu_id )
{
global $mdb;
if ( $mdb -> count( 'pp_pages', [ 'menu_id' => (int)$menu_id ] ) )
return false;
return $mdb -> delete( 'pp_menus', [ 'id' => (int)$menu_id ] );
}
public static function menu_details( $menu_id )
{
global $mdb;
return $mdb -> get( 'pp_menus', '*', [ 'id' => (int)$menu_id ] );
}
public static function menu_save( $menu_id, $name, $status )
{
global $mdb;
$status == 'on' ? $status = 1 : $status = 0;
if ( !$menu_id )
{
return $mdb -> insert( 'pp_menus', [
'name' => $name,
'status' => $status
] );
}
else
{
$mdb -> update( 'pp_menus', [
'name' => $name,
'status' => $status
], [
'id' => (int)$menu_id
] );
return true;
}
return false;
}
public static function menu_lists()
{
global $mdb;
return $mdb -> select( 'pp_menus', '*', [ 'ORDER' => [ 'id' => 'ASC' ] ] );
}
public static function page_details( $page_id )
{
global $mdb;
$page = $mdb -> get( 'pp_pages', '*', [ 'id' => (int)$page_id ] );
$results = $mdb -> select( 'pp_pages_langs', '*', [ 'page_id' => (int)$page_id ] );
if ( is_array( $results ) ) foreach ( $results as $row )
$page['languages'][ $row['lang_id'] ] = $row;
$page['layout_id'] = $mdb -> get( 'pp_layouts_pages', 'layout_id', [ 'page_id' => (int)$page_id ] );
return $page;
}
public static function page_url( $page_id )
{
global $mdb;
$results = $mdb -> query( "SELECT seo_link FROM pp_pages_langs AS ppl, pp_langs AS pl WHERE lang_id = pl.id AND page_id = " . (int)$page_id . " AND seo_link != '' ORDER BY o ASC LIMIT 1" ) -> fetchAll();
if ( !$results[0]['seo_link'] )
{
$title = self::page_title( $article_id );
return 's-' . $page_id . '-' . \S::seo( $title );
}
else
return $results[0]['seo_link'];
}
public static function page_title( $page_id )
{
global $mdb;
$result = $mdb -> select( 'pp_pages_langs', [
'[><]pp_langs' => [ 'lang_id' => 'id' ]
], 'title', [
'AND' => [
'page_id' => (int)$page_id, 'title[!]' => ''
],
'ORDER' => [ 'o' => 'ASC' ],
'LIMIT' => 1
] );
return $result[0];
}
public static function page_languages( $page_id )
{
global $mdb;
return $mdb -> select( 'pp_pages_langs', '*',
[ 'AND' => [ 'page_id' => (int) $page_id, 'title[!]' => null ] ] );
}
public static function menu_pages( $menu_id, $parent_id = null )
{
global $mdb;
$results = $mdb -> select( 'pp_pages',
[ 'id', 'menu_id', 'status', 'parent_id', 'start' ],
[ 'AND' => [ 'menu_id' => $menu_id, 'parent_id' => $parent_id ], 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$row['title'] = self::page_title( $row['id'] );
$row['languages'] = self::page_languages( $row['id'] );
$row['subpages'] = self::menu_pages( $menu_id, $row['id'] );
$pages[] = $row;
}
return $pages;
}
}
?>

View File

@@ -1,88 +0,0 @@
<?php
namespace admin\factory;
class Scontainers
{
public static function container_delete( $container_id )
{
global $mdb;
return $mdb -> delete( 'pp_scontainers', [ 'id' => (int)$container_id ] );
}
public static function container_save( $container_id, $title, $text, $status, $show_title )
{
global $mdb;
if ( !$container_id )
{
$mdb -> insert( 'pp_scontainers', [
'status' => $status == 'on' ? 1 : 0,
'show_title' => $show_title == 'on' ? 1 : 0
] );
$id = $mdb -> id();
if ( $id )
{
foreach ( $title as $key => $val )
{
$mdb -> insert( 'pp_scontainers_langs', [
'container_id' => (int)$id,
'lang_id' => $key,
'title' => $title[$key],
'text' => $text[$key]
] );
}
\S::delete_dir( '../temp/' );
return $id;
}
}
else
{
$mdb -> update( 'pp_scontainers', [
'status' => $status == 'on' ? 1 : 0,
'show_title' => $show_title == 'on' ? 1 : 0
], [
'id' => (int)$container_id
] );
foreach ( $title as $key => $val )
{
if ( $translation_id = $mdb -> get( 'pp_scontainers_langs', 'id', [ 'AND' => [ 'container_id' => $container_id, 'lang_id' => $key ] ] ) )
$mdb -> update( 'pp_scontainers_langs', [
'lang_id' => $key,
'title' => $title[$key],
'text' => $text[$key]
], [
'id' => $translation_id
] );
else
$mdb -> insert( 'pp_scontainers_langs', [
'container_id' => (int)$container_id,
'lang_id' => $key,
'title' => $title[$key],
'text' => $text[$key]
] );
}
\S::delete_dir( '../temp/' );
return $container_id;
}
}
public static function container_details( $container_id )
{
global $mdb;
$container = $mdb -> get( 'pp_scontainers', '*', [ 'id' => (int)$container_id ] );
$results = $mdb -> select( 'pp_scontainers_langs', '*', [ 'container_id' => (int)$container_id ] );
if ( is_array( $results ) ) foreach ( $results as $row )
$container['languages'][ $row['lang_id'] ] = $row;
return $container;
}
}

View File

@@ -1,104 +0,0 @@
<?
namespace admin\factory;
class Settings
{
public static function settings_update( $param, $value )
{
global $mdb;
$mdb -> delete( 'pp_settings', [ 'param' => $param ] );
$mdb -> insert( 'pp_settings', [ 'param' => $param, 'value' => $value ] );
return true;
}
public static function settings_save(
$firm_name, $firm_adress, $additional_info, $contact_form, $contact_email, $email_host, $email_port, $email_login, $email_password, $google_maps, $facebook_link, $statistic_code, $htaccess,
$robots, $shop_bank_account_info, $update, $boot_animation, $newsletter_header, $newsletter_footer, $hotpay_api
)
{
global $mdb;
$mdb -> query( 'TRUNCATE pp_settings' );
$mdb -> insert( 'pp_settings', [
[
'param' => 'firm_name',
'value' => $firm_name,
], [
'param' => 'firm_adress',
'value' => $firm_adress
], [
'param' => 'additional_info',
'value' => $additional_info
], [
'param' => 'contact_form',
'value' => $contact_form == 'on' ? 1 : 0
], [
'param' => 'contact_email',
'value' => $contact_email
], [
'param' => 'email_host',
'value' => $email_host
], [
'param' => 'email_port',
'value' => $email_port
], [
'param' => 'email_login',
'value' => $email_login
], [
'param' => 'email_password',
'value' => $email_password
], [
'param' => 'google_maps',
'value' => $google_maps
], [
"param" => 'facebook_link',
'value' => $facebook_link
], [
'param' => 'statistic_code',
'value' => $statistic_code
], [
'param' => 'htaccess',
'value' => $htaccess
], [
'param' => 'robots',
'value' => $robots
], [
'param' => 'shop_bank_account_info',
'value' => $shop_bank_account_info
], [
'param' => 'update',
'value' => $update == 'on' ? 1 : 0
], [
'param' => 'boot_animation',
'value' => $boot_animation
], [
'param' => 'newsletter_header',
'value' => $newsletter_header
], [
'param' => 'newsletter_footer',
'value' => $newsletter_footer
], [
'param' => 'hotpay_api',
'value' => $hotpay_api
]
]
);
\S::set_message( 'Ustawienia zostały zapisane' );
return $response = [ 'status' => 'ok', 'msg' => 'Ustawienia zostały zapisane.' ];
}
public static function settings_details()
{
global $mdb;
$results = $mdb -> select( 'pp_settings', '*', [ 'ORDER' => [ 'id' => 'ASC' ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
$settings[ $row['param'] ] = $row['value'];
return $settings;
}
}
?>

View File

@@ -1,263 +0,0 @@
<?php
namespace admin\factory;
class ShopAttribute
{
static public function get_attributes_list()
{
global $mdb;
$rows = $mdb -> select( 'pp_shop_attributes', '*', [ 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( \S::is_array_fix( $rows ) ) foreach ( $rows as $row )
{
$attribute = \admin\factory\ShopAttribute::attribute_details( $row['id'] );
$attribute['values'] = \admin\factory\ShopAttribute::get_attribute_values( $row['id'] );
$attributes[] = $attribute;
}
return $attributes;
}
// pobierz nazwę wartości atrybutu
static public function get_attribute_value_by_id( int $value_id )
{
global $mdb;
return $mdb -> get( 'pp_shop_attributes_values_langs', 'name', [ 'AND' => [ 'value_id' => $value_id, 'lang_id' => \front\factory\Languages::default_language() ] ] );
}
//pobierz nazwę atrybutu
static public function get_attribute_name_by_id( int $attribute_id )
{
global $mdb;
return $mdb -> get( 'pp_shop_attributes_langs', 'name', [ 'AND' => [ 'attribute_id' => $attribute_id, 'lang_id' => \front\factory\Languages::default_language() ] ] );
}
static public function values_save( int $attribute_id, $names, $values, $ids, $default_value = '', $impact_on_the_price )
{
global $mdb;
$main_language = \front\factory\Languages::default_language();
if ( \S::is_array_fix( $ids[$main_language] ) )
$ids_delete = implode( ',', $ids[$main_language] );
else
{
if ( $ids[$main_language] )
$ids_delete = $ids[$main_language];
}
if ( $ids_delete )
$mdb -> query( 'DELETE FROM pp_shop_attributes_values WHERE id NOT IN (' . $ids_delete . ') AND attribute_id = ' . $attribute_id );
for ( $i = 0; $i < count( $names[$main_language] ); ++$i )
{
if ( $ids[$main_language][$i] )
{
$mdb -> update( 'pp_shop_attributes_values', [
'impact_on_the_price' => $impact_on_the_price[$i] ? \S::normalize_decimal( $impact_on_the_price[$i] ) : null,
], [
'id' => $ids[$main_language][$i],
] );
\admin\factory\ShopProduct::update_product_price_by_attribute_value_impact( $ids[$main_language][$i], $impact_on_the_price[$i] );
$langs = \admin\factory\Languages::languages_list();
foreach ( $langs as $lang )
{
if ( $names[$lang['id']][$i] and $mdb -> count( 'pp_shop_attributes_values_langs', [ 'AND' => [ 'value_id' => $ids[$main_language][$i], 'lang_id' => $lang['id'] ] ] ) )
{
$mdb -> update( 'pp_shop_attributes_values_langs', [
'name' => $names[$lang['id']][$i],
'value' => $values[$lang['id']][$i] ? $values[$lang['id']][$i] : null,
], [
'AND' => [
'value_id' => $ids[$main_language][$i],
'lang_id' => $lang['id'],
],
] );
}
elseif ( $names[$lang['id']][$i] and !$mdb -> count( 'pp_shop_attributes_values_langs', [ 'AND' => [ 'value_id' => $ids[$main_language][$i], 'lang_id' => $lang['id'] ] ] ) )
{
$mdb -> insert('pp_shop_attributes_values_langs', [
'value_id' => $ids[$main_language][$i],
'lang_id' => $lang['id'],
'name' => $names[$lang['id']][$i],
'value' => $values[$lang['id']][$i] ? $values[$lang['id']][$i] : null,
] );
}
}
if ( $default_value == $i )
$default_value_id = $ids[$main_language][$i];
}
else
{
$mdb -> insert( 'pp_shop_attributes_values', [ 'attribute_id' => $attribute_id ] );
$value_id = $mdb -> id();
if ( $value_id )
{
$mdb -> update( 'pp_shop_attributes_values', [
'impact_on_the_price' => $impact_on_the_price[$i] ? \S::normalize_decimal( $impact_on_the_price[$i] ) : null,
], [
'id' => $value_id,
] );
if ( $impact_on_the_price[$i] )
\admin\factory\ShopProduct::update_product_price_by_attribute_value_impact( $value_id, \S::normalize_decimal( $impact_on_the_price[$i] ) );
$langs = \admin\factory\Languages::languages_list();
if ( \S::is_array_fix( $langs ) ) foreach ( $langs as $lang )
{
if ( $names[$lang['id']][$i] )
{
$mdb -> insert('pp_shop_attributes_values_langs', [
'value_id' => $value_id,
'lang_id' => $lang['id'],
'name' => $names[$lang['id']][$i],
'value' => $values[$lang['id']][$i] ? $values[$lang['id']][$i] : null,
] );
}
}
if ( $default_value == $i )
$default_value_id = $value_id;
}
}
}
if ( $default_value_id )
{
$mdb -> update( 'pp_shop_attributes_values', [ 'is_default' => 0 ], [ 'attribute_id' => $attribute_id ] );
$mdb -> update( 'pp_shop_attributes_values', [ 'is_default' => 1 ], [ 'id' => $default_value_id ] );
}
\S::delete_cache();
return $attribute_id;
}
static public function get_attribute_values( int $attribute_id )
{
global $mdb;
$results = $mdb -> select( 'pp_shop_attributes_values', [ 'id', 'is_default', 'impact_on_the_price' ], [ 'attribute_id' => $attribute_id ] );
if ( \S::is_array_fix( $results ) ) foreach ( $results as $row )
{
$results2 = $mdb -> select( 'pp_shop_attributes_values_langs', [ 'lang_id', 'name', 'value' ], [ 'value_id' => $row['id'] ] );
if ( \S::is_array_fix( $results2 ) ) foreach ( $results2 as $row2 )
$row['languages'][$row2['lang_id']] = $row2;
$values[] = $row;
}
return $values;
}
static public function delete_attribute( int $attribute_id )
{
global $mdb, $user;
if ( $mdb -> delete( 'pp_shop_attributes', [ 'id' => $attribute_id ] ) )
{
\Log::save_log( 'Atrybut został usunięty | ID: ' . $attribute_id, $user['id'] );
return true;
}
return false;
}
static public function attribute_save( int $attribute_id, $name, int $status, int $type, int $o )
{
global $mdb, $user;
if ( !$attribute_id )
{
$mdb -> insert( 'pp_shop_attributes', [
'status' => $status,
'type' => $type,
'o' => $o
] );
$id = $mdb -> id();
if ( !$id )
return false;
\Log::save_log( 'Dodano nowy atrybut | ID: ' . $id, $user['id'] );
foreach ( $name as $key => $val )
{
$mdb -> insert( 'pp_shop_attributes_langs', [
'attribute_id' => (int)$id,
'lang_id' => $key,
'name' => $name[$key],
] );
}
\S::delete_dir( '../temp/' );
return $id;
}
else
{
$mdb -> update( 'pp_shop_attributes', [
'status' => $status,
'type' => $type,
'o' => $o
], [
'id' => $attribute_id,
] );
\Log::save_log( 'Zaktualizowano atrybut | ID: ' . $attribute_id, $user['id'] );
foreach ( $name as $key => $val )
{
if ( $translation_id = $mdb -> get( 'pp_shop_attributes_langs', 'id', [ 'AND' => [ 'attribute_id' => $attribute_id, 'lang_id' => $key ] ] ) )
$mdb -> update( 'pp_shop_attributes_langs', [
'lang_id' => $key,
'name' => $name[$key],
], [
'id' => $translation_id
] );
else
$mdb -> insert( 'pp_shop_attributes_langs', [
'attribute_id' => (int)$attribute_id,
'lang_id' => $key,
'name' => $name[$key],
] );
}
\S::delete_dir( '../temp/' );
return $attribute_id;
}
}
static public function value_details( int $value_id )
{
global $mdb;
$value = $mdb -> get( 'pp_shop_attributes_values', '*', [ 'id' => (int) $value_id ] );
$results = $mdb -> select( 'pp_shop_attributes_values_langs', [ 'lang_id', 'name', 'value' ], [ 'value_id' => (int) $value_id ] );
if ( \S::is_array_fix( $results ) ) foreach ( $results as $row)
$value['languages'][$row['lang_id']] = $row;
return $value;
}
static public function attribute_details( int $attribute_id )
{
global $mdb;
$attribute = $mdb -> get( 'pp_shop_attributes', '*', [ 'id' => (int) $attribute_id ] );
$results = $mdb -> select( 'pp_shop_attributes_langs', [ 'lang_id', 'name' ], [ 'attribute_id' => (int) $attribute_id ] );
if ( \S::is_array_fix( $results ) ) foreach ( $results as $row)
$attribute['languages'][$row['lang_id']] = $row;
return $attribute;
}
}

View File

@@ -1,245 +0,0 @@
<?php
namespace admin\factory;
class ShopCategory
{
public static $_sort_types = [
0 => 'data dodania - najstarsze na początku',
1 => 'data dodania - najnowsze na początku',
2 => 'data modyfikacji - rosnąco',
3 => 'data mofyfikacji - malejąco',
4 => 'ręczne',
5 => 'alfabetycznie - A - Z',
6 => 'alfabetycznie - Z - A'
];
public static function save_product_order( $category_id, $products )
{
global $mdb;
if ( is_array( $products ) )
{
$mdb -> update( 'pp_shop_products_categories', [ 'o' => 0 ], [ 'category_id' => (int)$category_id ] );
for ( $i = 0; $i < count( $products ); $i++ )
{
if ( $products[$i]['item_id'] )
{
$x++;
$mdb -> update( 'pp_shop_products_categories', [ 'o' => $x ], [ 'AND' => [ 'category_id' => (int)$category_id, 'product_id' => $products[ $i ]['item_id'] ] ] );
}
}
}
return true;
}
public static function category_products( $category_id )
{
global $mdb;
$results = $mdb -> query( 'SELECT '
. 'product_id, o, status '
. 'FROM '
. 'pp_shop_products_categories AS pspc '
. 'INNER JOIN pp_shop_products AS psp ON psp.id = pspc.product_id '
. 'WHERE '
. 'category_id = :category_id '
. 'ORDER BY '
. 'o ASC', [
':category_id' => $category_id
] ) -> fetchAll();
if ( is_array( $results ) ) foreach ( $results as $row )
{
$row['name'] = \admin\factory\ShopProduct::product_name( $row['product_id'] );
$products[] = $row;
}
return $products;
}
public static function save_categories_order( $categories )
{
global $mdb;
if ( is_array( $categories ) )
{
$mdb -> update( 'pp_shop_categories', [ 'o' => 0 ] );
for ( $i = 0; $i < count( $categories ); $i++ )
{
if ( $categories[$i]['item_id'] )
{
$categories[$i]['parent_id'] ? $parent_id = $categories[$i]['parent_id'] : $parent_id = null;
$x++;
$mdb -> update( 'pp_shop_categories', [ 'o' => $x, 'parent_id' => $parent_id ], [ 'id' => (int)$categories[ $i ]['item_id'] ] );
}
}
}
\S::delete_dir( '../temp/' );
return true;
}
public static function category_delete( $category_id )
{
global $mdb;
if ( $mdb -> count( 'pp_shop_categories', [ 'parent_id' => (int)$category_id ] ) )
return false;
return $mdb -> delete( 'pp_shop_categories', [ 'id' => (int)$category_id ] );
}
public static function category_languages( $category_id )
{
global $mdb;
return $mdb -> select( 'pp_shop_categories_langs', '*', [ 'AND' => [ 'category_id' => (int)$category_id, 'title[!]' => null ] ] );
}
public static function category_title( $category_id )
{
global $mdb;
$result = $mdb -> select( 'pp_shop_categories_langs', [
'[><]pp_langs' => [ 'lang_id' => 'id' ]
], 'title', [
'AND' => [
'category_id' => (int)$category_id, 'title[!]' => ''
],
'ORDER' => [ 'o' => 'ASC' ],
'LIMIT' => 1
] );
return $result[0];
}
public static function subcategories( $parent_id = null )
{
global $mdb;
$results = $mdb -> select( 'pp_shop_categories', [ 'id' ], [ 'parent_id' => $parent_id, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
$categories[] = self::category_details( $row['id'] );
return $categories;
}
public static function max_order()
{
global $mdb;
return $mdb -> max( 'pp_shop_categories', 'o' );
}
public static function save( $category_id, $title, $text, $text_hidden, $seo_link, $meta_title, $meta_description, $meta_keywords, $parent_id, $status, $noindex, $category_title, $sort_type, $additional_text, $view_subcategories )
{
global $mdb;
if ( !$parent_id )
$parent_id = null;
if ( !$category_id )
{
$order = self::max_order() + 1;
$mdb -> insert( 'pp_shop_categories', [
'status' => $status == 'on' ? 1 : 0,
'o' => (int)$order,
'parent_id' => $parent_id,
'sort_type' => $sort_type,
'view_subcategories' => $view_subcategories == 'on' ? 1 : 0,
] );
$id = $mdb -> id();
if ( $id )
{
foreach ( $title as $key => $val )
{
$mdb -> insert( 'pp_shop_categories_langs', [
'category_id' => (int)$id,
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'text' => $text[$key] != '' ? $text[$key] : null,
'text_hidden' => $text_hidden[$key] != '' ? $text_hidden[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key],
'category_title' => $category_title[$key] != '' ? $category_title[$key] : null,
'additional_text' => $additional_text[$key] != '' ? $additional_text[$key] : null
] );
}
\S::htacces();
\S::delete_dir( '../temp/' );
return $id;
}
}
else
{
$mdb -> update( 'pp_shop_categories', [
'status' => $status == 'on' ? 1 : 0,
'parent_id' => $parent_id,
'sort_type' => $sort_type,
'view_subcategories' => $view_subcategories == 'on' ? 1 : 0,
], [
'id' => (int)$category_id
] );
foreach ( $title as $key => $val )
{
if ( $translation_id = $mdb -> get( 'pp_shop_categories_langs', 'id', [ 'AND' => [ 'category_id' => $category_id, 'lang_id' => $key ] ] ) )
$mdb -> update( 'pp_shop_categories_langs', [
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'text' => $text[$key] != '' ? $text[$key] : null,
'text_hidden' => $text_hidden[$key] != '' ? $text_hidden[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key],
'category_title' => $category_title[$key] != '' ? $category_title[$key] : null,
'additional_text' => $additional_text[$key] != '' ? $additional_text[$key] : null
], [
'id' => $translation_id
] );
else
$mdb -> insert( 'pp_shop_categories_langs', [
'category_id' => (int)$category_id,
'lang_id' => $key,
'title' => $title[$key] != '' ? $title[$key] : null,
'text' => $text[$key] != '' ? $text[$key] : null,
'text_hidden' => $text_hidden[$key] != '' ? $text_hidden[$key] : null,
'meta_description' => $meta_description[$key] != '' ? $meta_description[$key] : null,
'meta_keywords' => $meta_keywords[$key] != '' ? $meta_keywords[$key] : null,
'meta_title' => $meta_title[$key] != '' ? $meta_title[$key] : null,
'seo_link' => \S::seo( $seo_link[$key] ) != '' ? \S::seo( $seo_link[$key] ) : null,
'noindex' => $noindex[$key],
'category_title' => $category_title[$key] != '' ? $category_title[$key] : null,
'additional_text' => $additional_text[$key] != '' ? $additional_text[$key] : null
] );
}
\S::htacces();
\S::delete_dir( '../temp/' );
return $category_id;
}
return false;
}
public static function category_details( $category_id = '' )
{
global $mdb;
$category = $mdb -> get( 'pp_shop_categories', '*', [ 'id' => (int)$category_id ] );
$results = $mdb -> select( 'pp_shop_categories_langs', '*', [ 'category_id' => (int)$category_id ] );
if ( is_array( $results ) ) foreach ( $results as $row )
$category['languages'][ $row['lang_id'] ] = $row;
return $category;
}
}

View File

@@ -1,17 +0,0 @@
<?php
namespace admin\factory;
class ShopClients
{
public static function get_order_all_info($name, $surname, $email)
{
global $mdb;
$results = $mdb->select('pp_shop_orders', '*', [
'client_name' => $name,
'client_surname' => $surname,
'client_email' => $email
]);
return $results;}
}
?>

View File

@@ -1,54 +0,0 @@
<?php
namespace admin\factory;
class ShopCoupon
{
static public function details( int $coupon_id )
{
global $mdb;
return $mdb -> get( 'pp_shop_coupon', '*', [ 'id' => $coupon_id ] );
}
public static function coupon_delete( $coupon_id )
{
global $mdb;
return $mdb -> delete( 'pp_shop_coupon', [ 'id' => $coupon_id ] );
}
public static function save( $coupon_id, $name, $status, $send, $used, $type, $amount, $one_time, $include_discounted_product, $categories )
{
global $mdb;
if ( !$coupon_id )
{
if ( $mdb -> insert( 'pp_shop_coupon', [
'name' => $name,
'status' => $status,
'used' => $used,
'type' => $type,
'amount' => $amount,
'one_time' => $one_time,
'send' => $send,
'include_discounted_product' => $include_discounted_product,
'categories' => $categories
] ) )
return $mdb -> id();
}
else
{
$mdb -> update( 'pp_shop_coupon', [
'name' => $name,
'status' => $status,
'used' => $used,
'type' => $type,
'amount' => $amount,
'one_time' => $one_time,
'send' => $send,
'include_discounted_product' => $include_discounted_product,
'categories' => $categories
], [
'id' => $coupon_id
] );
return true;
}
}
}

View File

@@ -1,114 +0,0 @@
<?php
namespace admin\factory;
class ShopOrder
{
static public function send_order_to_apilo( int $order_id ) {
global $mdb;
// początek - anulowanie zamówienia w apilo
$apilo_settings = \admin\factory\Integrations::apilo_settings();
$new_status = 8; // zamówienie anulowwane
$order = \admin\factory\ShopOrder::order_details( $order_id );
if ( $order['apilo_order_id'] ) {
$access_token = \admin\factory\Integrations::apilo_get_access_token();
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, "https://projectpro.apilo.com/rest/api/orders/" . $order['apilo_order_id'] . '/status/' );
curl_setopt( $ch, CURLOPT_POST, 1 );
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( [
'id' => $order['apilo_order_id'],
'status' => (int)\front\factory\ShopStatuses::get_apilo_status_id( $new_status )
] ) );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . $access_token,
"Accept: application/json",
"Content-Type: application/json"
] );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
$apilo_result = curl_exec( $ch );
$apilo_result = json_decode( $apilo_result, true );
if ( $apilo_result['updates'] == 1 ) {
// zmień ID zamówienia na największe ID zamówienia + 1, oraz usuń ID zamówienia z apilo
$new_order_id = $mdb -> max( 'pp_shop_orders', 'id' ) + 1;
// pobierz listę kolumn zamówienia
$query = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'pp_shop_orders' AND COLUMN_NAME != 'id'";
$columns = $mdb -> query( $query ) -> fetchAll( \PDO::FETCH_COLUMN );
$columns_list = implode( ', ', $columns );
// kopiuj stare zamówienie do nowego ID
$mdb -> query( 'INSERT INTO pp_shop_orders (' . $columns_list . ') SELECT ' . $columns_list . ' FROM pp_shop_orders pso WHERE pso.id = ' . $order_id );
$new_order_id = $mdb -> id();
// pobierz listę kolumn produktów zamówienia
$query = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'pp_shop_order_products' AND COLUMN_NAME != 'id' AND COLUMN_NAME != 'order_id'";
$columns = $mdb -> query( $query ) -> fetchAll( \PDO::FETCH_COLUMN );
$columns_list = implode( ', ', $columns );
// kopiuj produkty zamówienia do nowego zamówienia
$mdb -> query( 'INSERT INTO pp_shop_order_products (order_id, ' . $columns_list . ') SELECT ' . $new_order_id . ',' . $columns_list . ' FROM pp_shop_order_products psop WHERE psop.order_id = ' . $order_id );
// pobierz listę kolumn z tabeli pp_shop_order_statuses
$query = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'pp_shop_order_statuses' AND COLUMN_NAME != 'id' AND COLUMN_NAME != 'order_id'";
$columns = $mdb -> query( $query ) -> fetchAll( \PDO::FETCH_COLUMN );
$columns_list = implode( ', ', $columns );
// kopiuj statusy zamówienia do nowego zamówienia
$mdb -> query( 'INSERT INTO pp_shop_order_statuses (order_id, ' . $columns_list . ') SELECT ' . $new_order_id . ',' . $columns_list . ' FROM pp_shop_order_statuses psos WHERE psos.order_id = ' . $order_id );
// usuń stare zamówienie
$mdb -> delete( 'pp_shop_orders', [ 'id' => $order_id ] );
$mdb -> delete( 'pp_shop_order_products', [ 'order_id' => $order_id ] );
$mdb -> delete( 'pp_shop_order_statuses', [ 'order_id' => $order_id ] );
// zmień wartość kolumny apilo_order_id na NULL
$mdb -> update( 'pp_shop_orders', [ 'apilo_order_id' => NULL ], [ 'id' => $new_order_id ] );
return true;
}
curl_close( $ch );
}
return false;
}
static public function next_order_id( int $order_id )
{
global $mdb;
if ( !$order_id )
return false;
return $mdb -> get( 'pp_shop_orders', 'id', [ 'id[>]' => $order_id, 'ORDER' => [ 'id' => 'ASC' ], 'LIMIT' => 1 ] );
}
static public function prev_order_id( int $order_id )
{
global $mdb;
if ( !$order_id )
return false;
return $mdb -> get( 'pp_shop_orders', 'id', [ 'id[<]' => $order_id, 'ORDER' => [ 'id' => 'DESC' ], 'LIMIT' => 1 ] );
}
static public function order_details( int $order_id )
{
global $mdb;
$order = $mdb -> get( 'pp_shop_orders', '*', [ 'id' => $order_id ] );
$order['products'] = $mdb -> select( 'pp_shop_order_products', '*', [ 'order_id' => $order_id ] );
return $order;
}
}

View File

@@ -1,10 +0,0 @@
<?php
namespace admin\factory;
class ShopPaymentMethod
{
public static function payments_list()
{
global $mdb;
return $mdb -> select( 'pp_shop_payment_methods', '*', [ 'ORDER' => [ 'name' => 'ASC'] ] );
}
}

View File

@@ -1,89 +0,0 @@
<?
namespace admin\factory;
class ShopProducer
{
static public function all()
{
global $mdb;
return $mdb -> select( 'pp_shop_producer', '*', [ 'ORDER' => [ 'name' => 'ASC' ] ] );
}
static public function delete( int $producer_id )
{
global $mdb;
return $mdb -> delete( 'pp_shop_producer', [ 'id' => $producer_id ] );
}
static public function save( $producer_id, $name, int $status, $img, $description, $data, $meta_title )
{
global $mdb;
if ( !$producer_id )
{
$mdb -> insert( 'pp_shop_producer', [
'name' => $name,
'status' => $status,
'img' => $img
] );
$id = $mdb -> id();
$langs = \admin\factory\Languages::languages_list( true );
foreach ( $langs as $lg )
{
$mdb -> insert( 'pp_shop_producer_lang', [
'producer_id' => $id,
'lang_id' => $lg['id'],
'description' => $description[ $lg['id'] ] ?? null,
'data' => $data[ $lg['id'] ] ?? null,
'meta_title' => $meta_title[ $lg['id'] ] ?? null
] );
}
\S::htacces();
\S::delete_dir( '../temp/' );
return $id;
}
else
{
$mdb -> update( 'pp_shop_producer', [
'name' => $name,
'status' => $status,
'img' => $img
], [
'id' => (int) $producer_id
] );
$langs = \admin\factory\Languages::languages_list( true );
foreach ( $langs as $lg )
{
if ( $translation_id = $mdb -> get( 'pp_shop_producer_lang', 'id', [ 'AND' => [ 'producer_id' => $producer_id, 'lang_id' => $lg['id'] ] ] ) )
{
$mdb -> update( 'pp_shop_producer_lang', [
'description' => $description[ $lg['id'] ] ?? null,
'meta_title' => $meta_title[ $lg['id'] ] ?? null,
'data' => $data[ $lg['id'] ] ?? null
], [
'id' => $translation_id
] );
}
else
{
$mdb -> insert( 'pp_shop_producer_lang', [
'producer_id' => $producer_id,
'lang_id' => $lg['id'],
'description' => $description[ $lg['id'] ] ?? null,
'data' => $data[ $lg['id'] ] ?? null,
'meta_title' => $meta_title[ $lg['id'] ] ?? null
] );
}
}
\S::htacces();
\S::delete_dir( '../temp/' );
return $producer_id;
}
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,68 +0,0 @@
<?
namespace admin\factory;
class ShopProductSet
{
// zapisywanie kompletu produktów
static public function save( int $set_id, string $name, string $status, $set_products_id )
{
global $mdb;
if ( !$set_id )
{
$mdb -> insert('pp_shop_product_sets', [
'name' => $name,
'status' => 'on' === $status ? 1 : 0
] );
$id = $mdb -> id();
if ( $set_products_id == null )
$not_in = [ 0 ];
elseif ( !is_array( $set_products_id ) )
$not_in = [ 0, $set_products_id ];
elseif ( is_array( $set_products_id ) )
$not_in = $set_products_id;
foreach ( $not_in as $product_id )
{
if ( $product_id != 0 )
$mdb -> insert( 'pp_shop_product_sets_products', [ 'set_id' => $id, 'product_id' => $product_id ] );
}
\S::delete_dir('../temp/');
\S::delete_dir('../thumbs/');
return $id;
}
else
{
$mdb -> update('pp_shop_product_sets', [
'name' => $name,
'status' => 'on' === $status ? 1 : 0
], [
'id' => (int)$set_id,
] );
$mdb -> delete( 'pp_shop_product_sets_products', [ 'set_id' => $set_id ] );
if ( $set_products_id == null )
$not_in = [ 0 ];
elseif ( !is_array( $set_products_id ) )
$not_in = [ 0, $set_products_id ];
elseif ( is_array( $set_products_id ) )
$not_in = $set_products_id;
foreach ( $not_in as $product_id )
{
if ( $product_id != 0 )
$mdb -> insert( 'pp_shop_product_sets_products', [ 'set_id' => $set_id, 'product_id' => $product_id ] );
}
\S::delete_dir('../temp/');
\S::delete_dir('../thumbs/');
return $set_id;
}
}
}

View File

@@ -1,55 +0,0 @@
<?php
namespace admin\factory;
class ShopPromotion
{
static public function promotion_details( int $promotion_id )
{
global $mdb;
return $mdb -> get( 'pp_shop_promotion', '*', [ 'id' => $promotion_id ] );
}
static public function save( $promotion_id, $name, $status, $condition_type, $discount_type, $amount, $date_to, $categories, $condition_categories, $include_coupon, $include_product_promo, $min_product_count, $price_cheapest_product )
{
global $mdb, $user;
if ( !$promotion_id )
{
$mdb -> insert( 'pp_shop_promotion', [
'name' => $name,
'status' => $status,
'condition_type' => $condition_type,
'discount_type' => $discount_type,
'amount' => $amount,
'date_to' => $date_to != '' ? $date_to : null,
'categories' => $categories != null ? ( is_array( $categories ) ? json_encode( $categories ) : json_encode( [ $categories ] ) ) : null,
'condition_categories' => $condition_categories != null ? ( is_array( $condition_categories ) ? json_encode( $condition_categories ) : json_encode( [ $condition_categories ] ) ) : null,
'include_coupon' => $include_coupon,
'include_product_promo' => $include_product_promo,
'min_product_count' => $min_product_count ? $min_product_count : null,
'price_cheapest_product' => $price_cheapest_product ? $price_cheapest_product : null
] );
return $mdb -> id();
}
else
{
$mdb -> update( 'pp_shop_promotion', [
'name' => $name,
'status' => $status,
'condition_type' => $condition_type,
'discount_type' => $discount_type,
'amount' => $amount,
'date_to' => $date_to != '' ? $date_to : null,
'categories' => $categories != null ? ( is_array( $categories ) ? json_encode( $categories ) : json_encode( [ $categories ] ) ) : null,
'condition_categories' => $condition_categories != null ? ( is_array( $condition_categories ) ? json_encode( $condition_categories ) : json_encode( [ $condition_categories ] ) ) : null,
'include_coupon' => $include_coupon,
'include_product_promo' => $include_product_promo,
'min_product_count' => $min_product_count ? $min_product_count : null,
'price_cheapest_product' => $price_cheapest_product ? $price_cheapest_product : null
], [
'id' => $promotion_id
] );
return $promotion_id;
}
}
}

View File

@@ -1,26 +0,0 @@
<?
namespace admin\factory;
class ShopStatuses {
// get_status
public static function get_status( $id )
{
global $mdb;
return $mdb -> get( 'pp_shop_statuses', '*', [ 'id' => $id ] );
}
// status_save
public static function status_save( $status_id, $color, $apilo_status_id, $sellasi_status_id, $baselinker_status_id )
{
global $mdb;
$mdb -> update( 'pp_shop_statuses', [
'color' => $color,
'apilo_status_id' => $apilo_status_id ? $apilo_status_id : null,
'sellasist_status_id' => $sellasi_status_id ? $sellasi_status_id : null,
'baselinker_status_id' => $baselinker_status_id ? $baselinker_status_id : null
], [ 'id' => $status_id ] );
return $status_id;
}
}

View File

@@ -1,108 +0,0 @@
<?php
namespace admin\factory;
class ShopTransport
{
public static function lowest_transport_price( $wp ) {
global $mdb;
return $mdb -> get( 'pp_shop_transports', 'cost', [ 'AND' => [ 'status' => 1, 'id' => [ 2, 4, 6, 8, 9 ], 'max_wp[>=]' => $wp ], 'ORDER' => [ 'cost' => 'ASC' ] ] );
}
public static function transport_save( $transport_id, $name, $name_visible, $description, $status, $cost, $payment_methods, $max_wp, $default, $apilo_carrier_account_id, $sellasist_shipment_method_id, $delivery_free )
{
global $mdb;
if ( !$transport_id )
{
if ( $default == 'on' )
$mdb -> update( 'pp_shop_transports', [ 'default' => '0' ] );
$mdb -> insert( 'pp_shop_transports', [
'name' => $name,
'name_visible' => $name_visible,
'description' => $description,
'status' => $status == 'on' ? 1 : 0,
'default' => $default == 'on' ? 1 : 0,
'cost' => $cost,
'max_wp' => $max_wp ? $max_wp : null,
'apilo_carrier_account_id' => $apilo_carrier_account_id ? $apilo_carrier_account_id : null,
'sellasist_shipment_method_id' => $sellasist_shipment_method_id ? $sellasist_shipment_method_id : null,
'delivery_free' => $delivery_free == 'on' ? 1 : 0
] );
$id = $mdb -> id();
if ( $id )
{
if ( is_array( $payment_methods ) ) foreach ( $payment_methods as $payment_method )
{
$mdb -> insert( 'pp_shop_transport_payment_methods', [
'id_payment_method' => (int)$payment_method,
'id_transport' => (int)$id
] );
}
else if ( $payment_methods )
{
$mdb -> insert( 'pp_shop_transport_payment_methods', [
'id_payment_method' => (int)$payment_methods,
'id_transport' => (int)$id
] );
}
\S::delete_dir( '../temp/' );
return $id;
}
}
else
{
if ( $default == 'on' )
$mdb -> update( 'pp_shop_transports', [ 'default' => '0' ] );
$mdb -> update( 'pp_shop_transports', [
'name' => $name,
'name_visible' => $name_visible,
'description' => $description,
'status' => $status == 'on' ? 1 : 0,
'default' => $default == 'on' ? 1 : 0,
'cost' => $cost,
'max_wp' => $max_wp ? $max_wp : null,
'apilo_carrier_account_id' => $apilo_carrier_account_id ? $apilo_carrier_account_id : null,
'sellasist_shipment_method_id' => $sellasist_shipment_method_id ? $sellasist_shipment_method_id : null,
'delivery_free' => $delivery_free == 'on' ? 1 : 0
], [
'id' => $transport_id
] );
$mdb -> delete( 'pp_shop_transport_payment_methods', [ 'id_transport' => (int)$transport_id ] );
if ( is_array( $payment_methods ) ) foreach ( $payment_methods as $payment_method )
{
$mdb -> insert( 'pp_shop_transport_payment_methods', [
'id_payment_method' => (int)$payment_method,
'id_transport' => (int)$transport_id
] );
}
else if ( $payment_methods )
{
$mdb -> insert( 'pp_shop_transport_payment_methods', [
'id_payment_method' => (int)$payment_methods,
'id_transport' => (int)$transport_id
] );
}
\S::delete_dir( '../temp/' );
return true;
}
}
public static function transport_details( $transport_id )
{
global $mdb;
$transport = $mdb -> get( 'pp_shop_transports', '*', [ 'id' => $transport_id ] );
$transport['payment_methods'] = $mdb -> select( 'pp_shop_transport_payment_methods', 'id_payment_method', [ 'id_transport' => $transport_id ] );
return $transport;
}
}

View File

@@ -1,365 +0,0 @@
<?php
namespace admin\factory;
class Update
{
public static function update()
{
global $mdb, $settings;
@file_put_contents( '../libraries/update_log.txt', '' );
$log = [];
$log[] = '[START] Rozpoczęcie aktualizacji - ' . date('Y-m-d H:i:s');
$log[] = '[INFO] Aktualna wersja: ' . \S::get_version();
\S::delete_session( 'new-version' );
$versions_url = 'https://shoppro.project-dc.pl/updates/versions.php?key=' . $settings['update_key'];
$versions = @file_get_contents( $versions_url );
if ( $versions === false )
{
$log[] = '[ERROR] Nie udało się pobrać listy wersji z: ' . $versions_url;
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
$log[] = '[OK] Pobrano listę wersji';
$versions = explode( PHP_EOL, $versions );
$log[] = '[INFO] Znaleziono ' . count($versions) . ' wersji do sprawdzenia';
foreach ( $versions as $ver )
{
$ver = trim( $ver );
if ( floatval( $ver ) > (float)\S::get_version() )
{
$log[] = '[INFO] Aktualizacja do wersji: ' . $ver;
if ( strlen( $ver ) == 5 )
$dir = substr( $ver, 0, strlen( $ver ) - 2 ) . 0;
else
$dir = substr( $ver, 0, strlen( $ver ) - 1 ) . 0;
$zip_url = 'https://shoppro.project-dc.pl/updates/' . $dir . '/ver_' . $ver . '.zip';
$log[] = '[INFO] Pobieranie pliku ZIP: ' . $zip_url;
$file = @file_get_contents( $zip_url );
if ( $file === false )
{
$log[] = '[ERROR] Nie udało się pobrać pliku ZIP';
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
$file_size = strlen( $file );
$log[] = '[OK] Pobrano plik ZIP, rozmiar: ' . $file_size . ' bajtów';
if ( $file_size < 100 )
{
$log[] = '[ERROR] Plik ZIP jest za mały (prawdopodobnie błąd pobierania)';
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
$dlHandler = @fopen( 'update.zip' , 'w' );
if ( !$dlHandler )
{
$log[] = '[ERROR] Nie udało się otworzyć pliku update.zip do zapisu';
$log[] = '[INFO] Katalog roboczy: ' . getcwd();
$log[] = '[INFO] Uprawnienia katalogu: ' . substr(sprintf('%o', fileperms('.')), -4);
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
$written = fwrite( $dlHandler, $file );
fclose( $dlHandler );
if ( $written === false || $written === 0 )
{
$log[] = '[ERROR] Nie udało się zapisać pliku ZIP (zapisano: ' . ($written === false ? 'false' : $written) . ' bajtów)';
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
$log[] = '[OK] Zapisano plik ZIP (' . $written . ' bajtów)';
if ( !file_exists( 'update.zip' ) )
{
$log[] = '[ERROR] Plik update.zip nie istnieje po zapisie';
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
$actual_size = filesize( 'update.zip' );
$log[] = '[OK] Plik update.zip istnieje, rozmiar na dysku: ' . $actual_size . ' bajtów';
/* aktualizacja bazy danych */
$sql_url = 'https://shoppro.project-dc.pl/updates/' . $dir . '/ver_' . $ver . '_sql.txt';
$log[] = '[INFO] Sprawdzanie aktualizacji SQL: ' . $sql_url;
$ch = curl_init( $sql_url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HEADER, false );
$response = curl_exec( $ch );
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
$content_type = curl_getinfo( $ch, CURLINFO_CONTENT_TYPE );
curl_close( $ch );
$sql = [];
if ( $response && strpos( $content_type, 'text/plain' ) !== false )
{
$sql = explode( PHP_EOL, $response );
$log[] = '[OK] Pobrano ' . count($sql) . ' zapytań SQL';
}
else
{
$log[] = '[INFO] Brak aktualizacji SQL (HTTP: ' . $http_code . ')';
}
if ( is_array( $sql ) && !empty( $sql ) )
{
$sql_success = 0;
$sql_errors = 0;
foreach ( $sql as $query )
{
$query = trim( $query );
if ( !empty( $query ) )
{
$result = $mdb->query( $query );
if ( $result ) $sql_success++;
else $sql_errors++;
}
}
$log[] = '[INFO] Wykonano zapytania SQL - sukces: ' . $sql_success . ', błędy: ' . $sql_errors;
}
/* usuwanie zbędnych plików */
$files_url = 'https://shoppro.project-dc.pl/updates/' . $dir . '/ver_' . $ver . '_files.txt';
$log[] = '[INFO] Sprawdzanie plików do usunięcia: ' . $files_url;
$ch = curl_init( $files_url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_HEADER, false );
$response = curl_exec( $ch );
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
$content_type = curl_getinfo( $ch, CURLINFO_CONTENT_TYPE );
curl_close( $ch );
$files = [];
if ( $response && strpos( $content_type, 'text/plain' ) !== false )
$files = explode( PHP_EOL, $response );
$deleted_files = 0;
$deleted_dirs = 0;
if ( is_array( $files ) && !empty( $files ) )
{
foreach ( $files as $file )
{
if ( strpos( $file, 'F: ' ) !== false )
{
$file = substr( $file, 3, strlen( $file ) );
if ( file_exists( $file ) )
{
if ( @unlink( $file ) ) $deleted_files++;
else $log[] = '[WARNING] Nie udało się usunąć pliku: ' . $file;
}
}
if ( strpos( $file, 'D: ' ) !== false )
{
$dir_to_delete = substr( $file, 3, strlen( $file ) );
if ( is_dir( $dir_to_delete ) )
{
\S::delete_dir( $dir_to_delete );
$deleted_dirs++;
}
}
}
}
$log[] = '[INFO] Usunięto plików: ' . $deleted_files . ', katalogów: ' . $deleted_dirs;
/* wgrywanie nowych plików */
$file_name = 'update.zip';
$log[] = '[INFO] Rozpoczęcie rozpakowywania pliku ZIP';
$path = pathinfo( realpath( $file_name ), PATHINFO_DIRNAME );
$log[] = '[INFO] Ścieżka pathinfo: ' . $path;
$path = substr( $path, 0, strlen( $path ) - 5 );
$log[] = '[INFO] Ścieżka docelowa (po obcięciu): ' . $path;
if ( !is_dir( $path ) )
{
$log[] = '[ERROR] Ścieżka docelowa nie istnieje: ' . $path;
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
if ( !is_writable( $path ) )
{
$log[] = '[ERROR] Brak uprawnień do zapisu w: ' . $path;
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
$log[] = '[OK] Ścieżka docelowa istnieje i jest zapisywalna';
$zip = new \ZipArchive;
$res = $zip->open( $file_name );
if ( $res !== true )
{
$zip_errors = [
\ZipArchive::ER_EXISTS => 'Plik już istnieje',
\ZipArchive::ER_INCONS => 'Archiwum ZIP jest niespójne',
\ZipArchive::ER_INVAL => 'Nieprawidłowy argument',
\ZipArchive::ER_MEMORY => 'Błąd alokacji pamięci',
\ZipArchive::ER_NOENT => 'Plik nie istnieje',
\ZipArchive::ER_NOZIP => 'Plik nie jest archiwum ZIP',
\ZipArchive::ER_OPEN => 'Nie można otworzyć pliku',
\ZipArchive::ER_READ => 'Błąd odczytu',
\ZipArchive::ER_SEEK => 'Błąd seek',
];
$error_msg = isset( $zip_errors[$res] ) ? $zip_errors[$res] : 'Nieznany błąd (' . $res . ')';
$log[] = '[ERROR] Nie udało się otworzyć pliku ZIP: ' . $error_msg;
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
$log[] = '[OK] Otwarto archiwum ZIP, liczba plików: ' . $zip->numFiles;
$extracted_count = 0;
$extract_errors = 0;
$skipped_dirs = 0;
for ( $i = 0; $i < $zip->numFiles; $i++ )
{
$filename = $zip->getNameIndex( $i );
$filename_clean = str_replace( '\\', '/', $filename );
if ( substr( $filename_clean, -1 ) === '/' )
{
$dir_path = $path . '/' . $filename_clean;
if ( !is_dir( $dir_path ) )
{
if ( @mkdir( $dir_path, 0755, true ) )
$log[] = '[DIR] Utworzono katalog: ' . $filename_clean;
else
$log[] = '[WARNING] Nie udało się utworzyć katalogu: ' . $filename_clean;
}
$skipped_dirs++;
continue;
}
$target_file = $path . '/' . $filename_clean;
$target_dir = dirname( $target_file );
if ( !is_dir( $target_dir ) )
{
if ( !@mkdir( $target_dir, 0755, true ) )
{
$log[] = '[ERROR] Nie udało się utworzyć katalogu dla: ' . $filename_clean;
$extract_errors++;
continue;
}
}
$file_existed = file_exists( $target_file );
$old_size = $file_existed ? filesize( $target_file ) : 0;
$old_mtime = $file_existed ? filemtime( $target_file ) : 0;
$content = $zip->getFromIndex( $i );
if ( $content === false )
{
$log[] = '[ERROR] Nie udało się odczytać z ZIP: ' . $filename_clean;
$extract_errors++;
continue;
}
$write_result = @file_put_contents( $target_file, $content );
if ( $write_result === false )
{
$log[] = '[ERROR] Nie udało się zapisać: ' . $filename_clean . ' (uprawnienia?)';
$extract_errors++;
}
else
{
$new_size = filesize( $target_file );
$new_mtime = filemtime( $target_file );
if ( $file_existed )
{
if ( $old_mtime !== $new_mtime || $old_size !== $new_size )
$log[] = '[UPDATED] ' . $filename_clean . ' (' . $old_size . ' -> ' . $new_size . ' bajtów)';
else
$log[] = '[UNCHANGED] ' . $filename_clean . ' (nie zmieniono - identyczny?)';
}
else
{
$log[] = '[NEW] ' . $filename_clean . ' (' . $new_size . ' bajtów)';
}
$extracted_count++;
}
}
$log[] = '[OK] Rozpakowano ' . $extracted_count . ' plików, błędów: ' . $extract_errors . ', katalogów: ' . $skipped_dirs;
$zip->close();
if ( @unlink( $file_name ) )
$log[] = '[OK] Usunięto plik update.zip';
else
$log[] = '[WARNING] Nie udało się usunąć pliku update.zip';
/* aktualizacja wersji */
$version_file = '../libraries/version.ini';
$updateThis = @fopen( $version_file, 'w' );
if ( !$updateThis )
{
$log[] = '[ERROR] Nie udało się otworzyć pliku version.ini do zapisu';
self::saveUpdateLog( $log );
return [ 'success' => false, 'log' => $log ];
}
fwrite( $updateThis, $ver );
fclose( $updateThis );
$log[] = '[OK] Zaktualizowano plik version.ini do wersji: ' . $ver;
$log[] = '[SUCCESS] Aktualizacja do wersji ' . $ver . ' zakończona pomyślnie';
self::saveUpdateLog( $log );
return [ 'success' => true, 'log' => $log ];
}
}
$log[] = '[INFO] Brak nowych wersji do zainstalowania';
self::saveUpdateLog( $log );
return [ 'success' => true, 'log' => $log, 'no_updates' => true ];
}
private static function saveUpdateLog( $log )
{
$log_content = implode( "\n", $log );
@file_put_contents( '../libraries/update_log.txt', $log_content );
}
public static function update0197()
{
global $mdb;
$rows = $mdb -> select( 'pp_shop_order_products', [ 'id', 'product_id' ], [ 'parent_product_id' => null ] );
foreach ( $rows as $row )
{
$parent_id = $mdb -> get( 'pp_shop_products', 'parent_id', [ 'id' => $row['product_id'] ] );
if ( $parent_id )
$mdb -> update( 'pp_shop_order_products', [ 'parent_product_id' => $parent_id ], [ 'id' => $row['id'] ] );
else
$mdb -> update( 'pp_shop_order_products', [ 'parent_product_id' => $row['product_id'] ], [ 'id' => $row['id'] ] );
}
$mdb -> update( 'pp_updates', [ 'done' => 1 ], [ 'name' => 'update0197' ] );
}
}

View File

@@ -1,214 +0,0 @@
<?php
namespace admin\factory;
class Users
{
static public function verify_twofa_code(int $userId, string $code): bool
{
$user = self::get_by_id( $userId );
if (!$user) return false;
if ((int)$user['twofa_failed_attempts'] >= 5)
{
return false; // zbyt wiele prób
}
// sprawdź ważność
if (empty($user['twofa_expires_at']) || time() > strtotime($user['twofa_expires_at']))
{
// wyczyść po wygaśnięciu
self::update_by_id($userId, [
'twofa_code_hash' => null,
'twofa_expires_at' => null,
]);
return false;
}
$ok = (!empty($user['twofa_code_hash']) && password_verify($code, $user['twofa_code_hash']));
if ($ok)
{
// sukces: czyścimy wszystko
self::update_by_id($userId, [
'twofa_code_hash' => null,
'twofa_expires_at' => null,
'twofa_sent_at' => null,
'twofa_failed_attempts' => 0,
'last_logged' => date('Y-m-d H:i:s'),
]);
return true;
}
// zła próba — inkrementacja
self::update_by_id($userId, [
'twofa_failed_attempts' => (int)$user['twofa_failed_attempts'] + 1,
'last_error_logged' => date('Y-m-d H:i:s'),
]);
return false;
}
static public function get_by_id(int $userId): ?array {
global $mdb;
return $mdb->get('pp_users', '*', ['id' => $userId]) ?: null;
}
static public function update_by_id(int $userId, array $data): bool {
global $mdb;
return (bool)$mdb->update('pp_users', $data, ['id' => $userId]);
}
static public function send_twofa_code(int $userId, bool $resend = false): bool {
$user = self::get_by_id($userId);
if ( !$user )
return false;
if ( (int)$user['twofa_enabled'] !== 1 )
return false;
$to = $user['twofa_email'] ?: $user['login'];
if (!filter_var($to, FILTER_VALIDATE_EMAIL))
return false;
if ( $resend && !empty( $user['twofa_sent_at'] ) ) {
$last = strtotime($user['twofa_sent_at']);
if ($last && (time() - $last) < 30)
return false;
}
$code = random_int(100000, 999999);
$hash = password_hash((string)$code, PASSWORD_DEFAULT);
self::update_by_id( $userId, [
'twofa_code_hash' => $hash,
'twofa_expires_at' => date('Y-m-d H:i:s', time() + 10 * 60), // 10 minut
'twofa_sent_at' => date('Y-m-d H:i:s'),
'twofa_failed_attempts' => 0,
] );
$subject = 'Twój kod logowania 2FA';
$body = "Twój kod logowania do panelu administratora: {$code}. Kod jest ważny przez 10 minut. Jeśli to nie Ty inicjowałeś logowanie zignoruj tę wiadomość i poinformuj administratora.";
$sent = \S::send_email($to, $subject, $body);
if (!$sent) {
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/plain; charset=UTF-8\r\n";
$headers .= "From: no-reply@" . ($_SERVER['HTTP_HOST'] ?? 'localhost') . "\r\n";
$encodedSubject = mb_encode_mimeheader($subject, 'UTF-8');
$sent = mail($to, $encodedSubject, $body, $headers);
}
return $sent;
}
public static function user_delete( $user_id )
{
global $mdb;
return $mdb -> delete( 'pp_users', [ 'id' => (int)$user_id ] );
}
public static function user_details( $user_id )
{
global $mdb;
return $mdb -> get( 'pp_users', '*', [ 'id' => (int)$user_id ] );
}
public static function user_save( $user_id = '', $login, $status, $password, $password_re, $admin, $twofa_enabled = 0, $twofa_email = '' )
{
global $mdb, $lang, $config;
if ( !$user_id )
{
if ( strlen( $password ) < 5 )
return $response = [ 'status' => 'error', 'msg' => 'Podane hasło jest zbyt krótkie.' ];
if ( $password != $password_re )
return $response = [ 'status' => 'error', 'msg' => 'Podane hasła są różne' ];
if ( $mdb -> insert( 'pp_users', [
'login' => $login,
'status' => $status == 'on' ? 1 : 0,
'admin' => $admin,
'password' => md5( $password ),
'twofa_enabled' => $twofa_enabled == 'on' ? 1 : 0,
'twofa_email' => $twofa_email
] ) )
{
return $response = [ 'status' => 'ok', 'msg' => 'Użytkownik został zapisany.' ];
}
}
else
{
if ( $password and strlen( $password ) < 5 )
return $response = [ 'status' => 'error', 'msg' => 'Podane hasło jest zbyt krótkie.' ];
if ( $password and $password != $password_re )
return $response = [ 'status' => 'error', 'msg' => 'Podane hasła są różne' ];
if ( $password )
$mdb -> update( 'pp_users', [
'password' => md5( $password )
], [
'id' => (int)$user_id
] );
$mdb -> update( 'pp_users', [
'login' => $login,
'admin' => $admin,
'status' => $status == 'on' ? 1 : 0,
'twofa_enabled' => $twofa_enabled == 'on' ? 1 : 0,
'twofa_email' => $twofa_email
], [
'id' => (int)$user_id
] );
return $response = [ 'status' => 'ok', 'msg' => 'Uzytkownik został zapisany.' ];
}
}
public static function check_login( $login, $user_id )
{
global $mdb;
if ( $mdb -> get( 'pp_users', 'login', [ 'AND' => [ 'login' => $login, 'id[!]' => (int)$user_id ] ] ) )
return $response = [ 'status' => 'error', 'msg' => 'Podany login jest już zajęty.' ];
return $response = [ 'status' => 'ok' ];
}
public static function logon( $login, $password )
{
global $mdb;
if ( !$mdb -> get( 'pp_users', '*', [ 'login' => $login ] ) )
return 0;
if ( !$mdb -> get( 'pp_users', '*', [ 'AND' => [ 'login' => $login, 'status' => 1, 'error_logged_count[<]' => 5 ] ] ) )
return -1;
if ( $mdb -> get( 'pp_users', '*', [ 'AND' => [ 'login' => $login, 'status' => 1, 'password' => md5( $password ) ] ] ) )
{
$mdb -> update( 'pp_users', [ 'last_logged' => date( 'Y-m-d H:i:s' ), 'error_logged_count' => 0 ], [ 'login' => $login ] );
return 1;
}
else
{
$mdb -> update( 'pp_users', [ 'last_error_logged' => date( 'Y-m-d H:i:s' ), 'error_logged_count[+]' => 1 ], [ 'login' => $login ] );
if ( $mdb -> get( 'pp_users', 'error_logged_count', [ 'login' => $login ] ) >= 5 )
{
$mdb -> update( 'pp_users', [ 'status' => 0 ], [ 'login' => $login ] );
return -1;
}
}
return 0;
}
public static function details( $login )
{
global $mdb;
return $mdb -> get( 'pp_users', '*', [ 'login' => $login ] );
}
}
?>

View File

@@ -1,28 +0,0 @@
<?php
namespace admin\view;
class Articles
{
public static function browse_list()
{
$tpl = new \Tpl;
return $tpl -> render( 'articles/articles-browse-list' );
}
public static function subpages_list( $pages, $article_pages, $parent_id = 0, $step = 1 )
{
$tpl = new \Tpl();
$tpl -> pages = $pages;
$tpl -> parent_id = $parent_id;
$tpl -> step = $step;
$tpl -> article_pages = $article_pages;
return $tpl -> render( 'articles/subpages-list' );
}
public static function articles_list()
{
$tpl = new \Tpl;
return $tpl -> render( 'articles/articles-list' );
}
}
?>

View File

@@ -1,11 +0,0 @@
<?php
namespace admin\view;
class ArticlesArchive
{
public static function articles_list()
{
$tpl = new \Tpl;
return $tpl -> render( 'articles/articles-archive-list' );
}
}

View File

@@ -1,20 +0,0 @@
<?php
namespace admin\view;
class Banners
{
public static function banners_list()
{
$tpl = new \Tpl;
return $tpl -> render( 'banners/banners-list' );
}
public static function banner_edit( $banner, $languages )
{
$tpl = new \Tpl;
$tpl -> banner = $banner;
$tpl -> languages = $languages;
return $tpl -> render( 'banners/banner-edit' );
}
}
?>

View File

@@ -1,7 +0,0 @@
<?php
namespace admin\view;
class FileManager
{
}
?>

View File

@@ -1,34 +0,0 @@
<?
namespace admin\view;
class Languages
{
public static function translation_edit( $translation, $languages )
{
$tpl = new \Tpl;
$tpl -> languages = $languages;
$tpl -> translation = $translation;
return $tpl -> render( 'languages/translation-edit' );
}
public static function language_edit( $language, $order )
{
$tpl = new \Tpl;
$tpl -> language = $language;
$tpl -> order = $order;
return $tpl -> render( 'languages/language-edit' );
}
public static function translations_list()
{
$tpl = new \Tpl;
return $tpl -> render( 'languages/translations-list' );
}
public static function languages_list()
{
$tpl = new \Tpl;
return $tpl -> render( 'languages/languages-list' );
}
}
?>

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