diff --git a/admin/templates/banners/banners-list-custom-script.php b/admin/templates/banners/banners-list-custom-script.php
new file mode 100644
index 0000000..56ab843
--- /dev/null
+++ b/admin/templates/banners/banners-list-custom-script.php
@@ -0,0 +1,100 @@
+
+
+
diff --git a/admin/templates/banners/banners-list.php b/admin/templates/banners/banners-list.php
index 45cd47a..3e70c9a 100644
--- a/admin/templates/banners/banners-list.php
+++ b/admin/templates/banners/banners-list.php
@@ -1,105 +1,5 @@
= \Tpl::view('components/table-list', ['list' => $this->viewModel]); ?>
-
-
-
-
viewModel->customScriptView)): ?>
= \Tpl::view($this->viewModel->customScriptView, ['list' => $this->viewModel]); ?>
diff --git a/admin/templates/filemanager/filemanager.php b/admin/templates/filemanager/filemanager.php
index 114d499..dc2d008 100644
--- a/admin/templates/filemanager/filemanager.php
+++ b/admin/templates/filemanager/filemanager.php
@@ -1 +1,4 @@
-
+filemanager_url ?? '/libraries/filemanager-9.14.2/dialog.php'));
+?>
+
diff --git a/admin/templates/product-archive/products-list-custom-script.php b/admin/templates/product-archive/products-list-custom-script.php
new file mode 100644
index 0000000..aacad98
--- /dev/null
+++ b/admin/templates/product-archive/products-list-custom-script.php
@@ -0,0 +1,100 @@
+
+
+
diff --git a/admin/templates/product-archive/products-list.php b/admin/templates/product-archive/products-list.php
new file mode 100644
index 0000000..3e70c9a
--- /dev/null
+++ b/admin/templates/product-archive/products-list.php
@@ -0,0 +1,5 @@
+= \Tpl::view('components/table-list', ['list' => $this->viewModel]); ?>
+
+viewModel->customScriptView)): ?>
+ = \Tpl::view($this->viewModel->customScriptView, ['list' => $this->viewModel]); ?>
+
diff --git a/admin/templates/product_archive/products-list-table.php b/admin/templates/product_archive/products-list-table.php
deleted file mode 100644
index f2ac941..0000000
--- a/admin/templates/product_archive/products-list-table.php
+++ /dev/null
@@ -1,41 +0,0 @@
- $i = ( $this -> current_page - 1 ) * 10 + 1;?>
- foreach ( $this -> products as $product ):?>
-
- |
- = $i++;?>
- |
-
-
- if ( $product['images'][0]['src'] ):?>
- ![<?= $product['images'][0]['alt'];?>](<?= $product['images'][0]['src'];?>)
- else:?>
- 
- endif;?>
-
-
- = \admin\factory\ShopProduct::product_categories( $product['id'] );?>
- |
-
- = $product['price_brutto'];?>
- |
-
- = $product['price_brutto_promo'];?>
- |
-
- = (int)\admin\factory\shopProduct::get_product_quantity_list( $product['id'] );?>
- |
-
- '>kombinacje (= \admin\factory\shopProduct::count_product_combinations( $product['id'] );?>)
- |
-
- '>edytuj
- |
-
- ' class="product-unarchive">przywróć
- |
-
- endforeach;?>
diff --git a/admin/templates/product_archive/products-list.php b/admin/templates/product_archive/products-list.php
deleted file mode 100644
index b86d2ac..0000000
--- a/admin/templates/product_archive/products-list.php
+++ /dev/null
@@ -1,152 +0,0 @@
-
-
diff --git a/autoload/Domain/Product/ProductRepository.php b/autoload/Domain/Product/ProductRepository.php
index 4d5dd67..e397697 100644
--- a/autoload/Domain/Product/ProductRepository.php
+++ b/autoload/Domain/Product/ProductRepository.php
@@ -9,6 +9,8 @@ namespace Domain\Product;
*/
class ProductRepository
{
+ private const MAX_PER_PAGE = 100;
+
/**
* @var \medoo Instancja Medoo ORM
*/
@@ -50,6 +52,118 @@ class ProductRepository
return $product ?: null;
}
+ /**
+ * Zwraca liste produktow z archiwum do panelu admin.
+ *
+ * @return array{items: array>, total: int}
+ */
+ public function listArchivedForAdmin(
+ array $filters,
+ string $sortColumn = 'id',
+ string $sortDir = 'DESC',
+ int $page = 1,
+ int $perPage = 10
+ ): array {
+ $allowedSortColumns = [
+ 'id' => 'psp.id',
+ 'name' => 'name',
+ 'price_brutto' => 'psp.price_brutto',
+ 'price_brutto_promo' => 'psp.price_brutto_promo',
+ 'quantity' => 'psp.quantity',
+ 'combinations' => 'combinations',
+ ];
+
+ $sortSql = $allowedSortColumns[$sortColumn] ?? 'psp.id';
+ $sortDir = strtoupper(trim($sortDir)) === 'ASC' ? 'ASC' : 'DESC';
+ $page = max(1, $page);
+ $perPage = min(self::MAX_PER_PAGE, max(1, $perPage));
+ $offset = ($page - 1) * $perPage;
+
+ $where = ['psp.archive = 1', 'psp.parent_id IS NULL'];
+ $params = [];
+
+ $phrase = trim((string)($filters['phrase'] ?? ''));
+ if (strlen($phrase) > 255) {
+ $phrase = substr($phrase, 0, 255);
+ }
+
+ if ($phrase !== '') {
+ $where[] = '(
+ psp.ean LIKE :phrase
+ OR psp.sku LIKE :phrase
+ OR EXISTS (
+ SELECT 1
+ FROM pp_shop_products_langs AS pspl2
+ WHERE pspl2.product_id = psp.id
+ AND pspl2.name LIKE :phrase
+ )
+ )';
+ $params[':phrase'] = '%' . $phrase . '%';
+ }
+
+ $whereSql = implode(' AND ', $where);
+
+ $sqlCount = "
+ SELECT COUNT(0)
+ FROM pp_shop_products AS psp
+ WHERE {$whereSql}
+ ";
+
+ $stmtCount = $this->db->query($sqlCount, $params);
+ $countRows = $stmtCount ? $stmtCount->fetchAll() : [];
+ $total = isset($countRows[0][0]) ? (int)$countRows[0][0] : 0;
+
+ $sql = "
+ SELECT
+ psp.id,
+ psp.price_brutto,
+ psp.price_brutto_promo,
+ psp.quantity,
+ psp.sku,
+ psp.ean,
+ (
+ SELECT pspl.name
+ FROM pp_shop_products_langs AS pspl
+ INNER JOIN pp_langs AS pl ON pl.id = pspl.lang_id
+ WHERE pspl.product_id = psp.id
+ AND pspl.name <> ''
+ ORDER BY pl.o ASC
+ LIMIT 1
+ ) AS name,
+ (
+ SELECT pspi.src
+ FROM pp_shop_products_images AS pspi
+ WHERE pspi.product_id = psp.id
+ ORDER BY pspi.o ASC, pspi.id ASC
+ LIMIT 1
+ ) AS image_src,
+ (
+ SELECT pspi.alt
+ FROM pp_shop_products_images AS pspi
+ WHERE pspi.product_id = psp.id
+ ORDER BY pspi.o ASC, pspi.id ASC
+ LIMIT 1
+ ) AS image_alt,
+ (
+ SELECT COUNT(0)
+ FROM pp_shop_products AS pspc
+ WHERE pspc.parent_id = psp.id
+ ) AS combinations
+ FROM pp_shop_products AS psp
+ WHERE {$whereSql}
+ ORDER BY {$sortSql} {$sortDir}, psp.id {$sortDir}
+ LIMIT {$perPage} OFFSET {$offset}
+ ";
+
+ $stmt = $this->db->query($sql, $params);
+ $items = $stmt ? $stmt->fetchAll() : [];
+
+ return [
+ 'items' => is_array($items) ? $items : [],
+ 'total' => $total,
+ ];
+ }
+
/**
* Pobiera cenę produktu (promocyjną jeśli jest niższa, w przeciwnym razie regularną)
*
diff --git a/autoload/admin/Controllers/BannerController.php b/autoload/admin/Controllers/BannerController.php
index d2c8a74..666a64c 100644
--- a/autoload/admin/Controllers/BannerController.php
+++ b/autoload/admin/Controllers/BannerController.php
@@ -147,7 +147,8 @@ class BannerController
'/admin/banners/view_list/',
'Brak danych w tabeli.',
'/admin/banners/banner_edit/',
- 'Dodaj baner'
+ 'Dodaj baner',
+ 'banners/banners-list-custom-script'
);
return \Tpl::view('banners/banners-list', [
diff --git a/autoload/admin/Controllers/FilemanagerController.php b/autoload/admin/Controllers/FilemanagerController.php
new file mode 100644
index 0000000..ba2535e
--- /dev/null
+++ b/autoload/admin/Controllers/FilemanagerController.php
@@ -0,0 +1,46 @@
+ensureFilemanagerAccessKey();
+ $filemanagerUrl = $this->buildFilemanagerUrl($akey);
+
+ return \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);
+ }
+}
+
diff --git a/autoload/admin/Controllers/ProductArchiveController.php b/autoload/admin/Controllers/ProductArchiveController.php
index b364335..5883b59 100644
--- a/autoload/admin/Controllers/ProductArchiveController.php
+++ b/autoload/admin/Controllers/ProductArchiveController.php
@@ -14,24 +14,142 @@ class ProductArchiveController
public function list(): string
{
- $current_page = \S::get_session( 'archive_products_list_current_page' );
+ $sortableColumns = ['id', 'name', 'price_brutto', 'price_brutto_promo', 'quantity'];
- if ( !$current_page ) {
- $current_page = 1;
- \S::set_session( 'archive_products_list_current_page', $current_page );
+ $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)\admin\factory\ShopProduct::product_categories($id));
+ $categoriesHtml = '';
+ if ($categories !== '') {
+ $categoriesHtml = ''
+ . htmlspecialchars($categories, ENT_QUOTES, 'UTF-8')
+ . '';
+ }
+
+ $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 = '' . implode(', ', $skuEanParts) . '';
+ }
+
+ $productCell = ''
+ . '
 . ')
'
+ . '
'
+ . ''
+ . $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',
+ ],
+ ],
+ ];
}
- $query = \S::get_session( 'archive_products_list_query' );
- $query_array = [];
- if ( $query ) {
- parse_str( $query, $query_array );
- }
+ $total = (int)$result['total'];
+ $totalPages = max(1, (int)ceil($total / $listRequest['perPage']));
- return \Tpl::view( 'product_archive/products-list', [
- 'current_page' => $current_page,
- 'query_array' => $query_array,
- 'pagination_max' => ceil( \admin\factory\ShopProduct::count_product( [ 'archive' => 1 ] ) / 10 )
- ] );
+ $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/products_list/',
+ 'Brak danych w tabeli.',
+ null,
+ null,
+ 'product-archive/products-list-custom-script'
+ );
+
+ return \Tpl::view('product-archive/products-list', [
+ 'viewModel' => $viewModel,
+ ]);
}
public function unarchive(): void
diff --git a/autoload/admin/class.Site.php b/autoload/admin/class.Site.php
index 4172a23..7d196bd 100644
--- a/autoload/admin/class.Site.php
+++ b/autoload/admin/class.Site.php
@@ -227,6 +227,14 @@ class Site
new \Domain\Product\ProductRepository( $mdb )
);
},
+ // Alias dla starego modułu /admin/archive/products_list/
+ 'Archive' => function() {
+ global $mdb;
+
+ return new \admin\Controllers\ProductArchiveController(
+ new \Domain\Product\ProductRepository( $mdb )
+ );
+ },
'Dictionaries' => function() {
global $mdb;
@@ -234,6 +242,9 @@ class Site
new \Domain\Dictionaries\DictionariesRepository( $mdb )
);
},
+ 'Filemanager' => function() {
+ return new \admin\Controllers\FilemanagerController();
+ },
];
return self::$newControllers;
diff --git a/autoload/admin/controls/class.Archive.php b/autoload/admin/controls/class.Archive.php
deleted file mode 100644
index 1db4624..0000000
--- a/autoload/admin/controls/class.Archive.php
+++ /dev/null
@@ -1,30 +0,0 @@
-
-namespace admin\controls;
-
-/**
- * @deprecated Użyj \admin\Controllers\ProductArchiveController
- * Klasa zachowana jako fallback dla starego URL /admin/archive/products_list/
- */
-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( 'product_archive/products-list', [
- 'current_page' => $current_page,
- 'query_array' => $query_array,
- 'pagination_max' => ceil( \admin\factory\ShopProduct::count_product() / 10 )
- ] );
- }
-}
\ No newline at end of file
diff --git a/autoload/admin/controls/class.Filemanager.php b/autoload/admin/controls/class.Filemanager.php
deleted file mode 100644
index cfa6e21..0000000
--- a/autoload/admin/controls/class.Filemanager.php
+++ /dev/null
@@ -1,11 +0,0 @@
-
diff --git a/autoload/admin/controls/class.ShopProduct.php b/autoload/admin/controls/class.ShopProduct.php
index 62541b6..e076736 100644
--- a/autoload/admin/controls/class.ShopProduct.php
+++ b/autoload/admin/controls/class.ShopProduct.php
@@ -257,23 +257,11 @@ class ShopProduct
// 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( 'product_archive/products-list-table', [
- 'products' => $products['products'],
- 'current_page' => \S::get( 'current_page' ),
- ] )
- ];
- }
-
- echo json_encode( $response );
+ echo json_encode( [
+ 'status' => 'deprecated',
+ 'msg' => 'Endpoint nie jest juz wspierany. Uzyj /admin/product_archive/products_list/.',
+ 'redirect_url' => '/admin/product_archive/products_list/'
+ ] );
exit;
}
diff --git a/autoload/admin/view/class.FileManager.php b/autoload/admin/view/class.FileManager.php
deleted file mode 100644
index f6c4b1e..0000000
--- a/autoload/admin/view/class.FileManager.php
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/updates/0.10/ver_0.200.zip b/updates/0.10/ver_0.200.zip
new file mode 100644
index 0000000..1058d88
Binary files /dev/null and b/updates/0.10/ver_0.200.zip differ
diff --git a/updates/0.10/ver_0.200_deleted_files.txt b/updates/0.10/ver_0.200_deleted_files.txt
new file mode 100644
index 0000000..31bca08
--- /dev/null
+++ b/updates/0.10/ver_0.200_deleted_files.txt
@@ -0,0 +1,8 @@
+# Deleted files for update ver_0.200
+# Generated: 2026-02-11 00:02:27
+
+admin/templates/product_archive/products-list-table.php
+admin/templates/product_archive/products-list.php
+autoload/admin/controls/class.Archive.php
+autoload/admin/controls/class.Filemanager.php
+autoload/admin/view/class.FileManager.php