diff --git a/DATABASE_STRUCTURE.md b/DATABASE_STRUCTURE.md index cd858d0..44c989e 100644 --- a/DATABASE_STRUCTURE.md +++ b/DATABASE_STRUCTURE.md @@ -134,10 +134,14 @@ Pliki artykułów. | Kolumna | Opis | |---------|------| +| id | PK | | article_id | FK do pp_articles | | src | Ścieżka do pliku | +| name | Nazwa wyświetlana załącznika (opcjonalna) | +| to_delete | Flaga miękkiego usuwania (0/1) | +| o | Kolejność załączników (używana przez sortowanie drag&drop w adminie) | -**Używane w:** `Domain\Article\ArticleRepository::find()` +**Używane w:** `Domain\Article\ArticleRepository::find()`, `Domain\Article\ArticleRepository::saveFilesOrder()` ## pp_units Jednostki/slowniki (np. jednostki produktu). diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md index 738c505..f8817ca 100644 --- a/PROJECT_STRUCTURE.md +++ b/PROJECT_STRUCTURE.md @@ -455,3 +455,19 @@ Aktualnie w suite są też testy modułów `Dictionaries`, `Articles` i `Users` - UPDATE: `/admin/articles_archive/view_list/` przepiete z legacy `grid` na `components/table-list`. - CLEANUP: usuniete legacy klasy `autoload/admin/controls/class.ArticlesArchive.php`, `autoload/admin/factory/class.ArticlesArchive.php`, `autoload/admin/view/class.ArticlesArchive.php`. - Testy: 165 tests, 424 assertions. + +### 2026-02-13: Refaktoryzacja /admin/articles (ver. 0.261) +- **UPDATE:** routing DI dla `ArticlesController` obsluguje akcje AJAX: `article_image_alt_change`, `article_file_name_change`, `article_image_delete`, `article_file_delete`. +- **UPDATE:** widok `admin/templates/articles/article-edit.php` korzysta z endpointow `/admin/articles/*` zamiast `admin/ajax.php?a=article_*`. +- **UPDATE:** lista artykulow nie korzysta juz z `admin\factory\Articles::article_pages` (etykiety stron z `Domain\Article\ArticleRepository`). +- **CLEANUP:** usuniete legacy pliki `autoload/admin/view/class.Articles.php` i `admin/ajax/articles.php`; odpiecie include w `admin/ajax.php`. +- Testy: 176 tests, 439 assertions. + +### 2026-02-13: Articles edit UX i sortowanie zalacznikow (ver. 0.262) +- **UPDATE:** `Domain\Article\ArticleRepository` - dodane `saveFilesOrder()` oraz obsluga `files_order` podczas `save()` (pierwszy zapis zachowuje kolejnosc). +- **UPDATE:** routing DI (`admin\Site::$actionMap`) rozszerzony o `files_order_save -> filesOrderSave`. +- **UPDATE:** `admin\Controllers\ArticlesController` - nowa akcja AJAX `filesOrderSave()`. +- **UPDATE:** `admin/templates/articles/article-edit-custom-script.php` - drag&drop sortowania listy zalacznikow + synchronizacja hidden input `files_order`. +- **UPDATE:** potwierdzenia usuwania zdjec i zalacznikow w edycji artykulu ujednolicone wizualnie z dialogiem usuwania z listy (jquery-confirm, `table-list-confirm-dialog`). +- **FIX:** dodane ladowanie biblioteki `jquery-impromptu` w widoku edycji artykulu (kompatybilnosc dla `$.prompt`). +- Testy: 178 tests, 443 assertions. diff --git a/REFACTORING_PLAN.md b/REFACTORING_PLAN.md index 8e48b33..a62c7f8 100644 --- a/REFACTORING_PLAN.md +++ b/REFACTORING_PLAN.md @@ -654,3 +654,31 @@ Gdy `persist = true`: - UPDATE: routing DI (`admin\Site`) rozszerzony o modul `ArticlesArchive` + mapowanie `article_restore -> restore` - CLEANUP: usuniete `autoload/admin/controls/class.ArticlesArchive.php`, `autoload/admin/factory/class.ArticlesArchive.php`, `autoload/admin/view/class.ArticlesArchive.php` - Testy po zmianie: **165 tests, 424 assertions** + +## Plan 2026-02-13 - Refaktoryzacja `/admin/articles/` +- [ ] Przeniesc zaleznosci listy artykulow z `admin\factory\Articles` do `Domain\Article\ArticleRepository` (etykiety stron, operacje pomocnicze). +- [ ] Dodac akcje routowane przez `admin\Controllers\ArticlesController` dla operacji AJAX (`article_image_alt_change`, `article_file_name_change`, `article_image_delete`, `article_file_delete`). +- [ ] Przepiac widok `admin/templates/articles/article-edit.php` z `/admin/ajax.php` na endpointy `/admin/articles/*`. +- [ ] Usunac legacy `admin\view\Articles` i zastapic rekurencje podstron przez `Tpl::view('articles/subpages-list', ...)`. +- [ ] Usunac `admin/ajax/articles.php` oraz odpiac include z `admin/ajax.php`. +- [ ] Przeszukac projekt pod pozostale zaleznosci i uruchomic testy modulu Articles. + +## Aktualizacja 2026-02-13 (ver. 0.261) +- **Articles** - dalsza refaktoryzacja `/admin/articles/` + - UPDATE: `Domain\Article\ArticleRepository` rozszerzone o metody UI/admin: `pagesSummaryForArticles()`, `updateImageAlt()`, `updateFileName()`, `markImageToDelete()`, `markFileToDelete()`. + - UPDATE: `admin\Controllers\ArticlesController` obsluguje nowe akcje routingu: `article_image_alt_change`, `article_file_name_change`, `article_image_delete`, `article_file_delete`. + - UPDATE: lista artykulow (`list`) nie korzysta juz z `admin\factory\Articles::article_pages()`. + - UPDATE: `admin/templates/articles/article-edit.php` przepiete z `/admin/ajax.php?a=article_*` na endpointy `/admin/articles/article_*/`. + - UPDATE: rekurencja podstron w widoku oparta o `Tpl::view('articles/subpages-list', ...)` (bez `admin\view\Articles`). + - CLEANUP: usuniete legacy pliki `autoload/admin/view/class.Articles.php` oraz `admin/ajax/articles.php`; `admin/ajax.php` nie includuje juz `ajax/articles.php`. +- Testy po zmianie: **176 tests, 439 assertions**. + +## Aktualizacja 2026-02-13 (ver. 0.262) +- **Articles (/admin/articles)** + - UPDATE: `Domain\Article\ArticleRepository` rozszerzone o `saveFilesOrder()` oraz zapis `files_order` przy `save()` (eliminuje koniecznosc drugiego zapisu po sortowaniu). + - UPDATE: routing DI (`admin\Site`) rozszerzony o mapowanie `files_order_save -> filesOrderSave`. + - UPDATE: `admin\Controllers\ArticlesController` - nowa akcja AJAX `filesOrderSave`. + - UPDATE: widok `admin/templates/articles/article-edit-custom-script.php` - drag&drop dla listy zalacznikow + hidden input `files_order`. + - UPDATE: potwierdzenia usuwania zdjec i zalacznikow przepiete na `jquery-confirm` ze stylem `table-list-confirm-dialog` (jak na liscie artykulow). + - FIX: dolaczona biblioteka `jquery-impromptu` w widoku edycji artykulu dla kompatybilnosci. +- Testy po zmianie: **178 tests, 443 assertions**. diff --git a/TESTING.md b/TESTING.md index a5c83dd..ad519b2 100644 --- a/TESTING.md +++ b/TESTING.md @@ -246,3 +246,24 @@ OK (165 tests, 424 assertions) Nowe testy dodane 2026-02-12: - `tests/Unit/Domain/Article/ArticleRepositoryTest.php` (rozszerzenie o testy `restore`, `deletePermanently`, `listArchivedForAdmin`) - `tests/Unit/admin/Controllers/ArticlesArchiveControllerTest.php` + +## Aktualizacja suite (release 0.261) +Ostatnio zweryfikowano: 2026-02-13 + +```text +OK (176 tests, 439 assertions) +``` + +Nowe testy/rozszerzenia 2026-02-13: +- `tests/Unit/Domain/Article/ArticleRepositoryTest.php` (nowe przypadki dla `pagesSummaryForArticles`, `updateImageAlt`, `markFileToDelete`) +- `tests/Unit/admin/Controllers/ArticlesControllerTest.php` (nowe kontrakty dla akcji `imageAltChange`, `fileNameChange`, `imageDelete`, `fileDelete`) + +## Aktualizacja suite (release 0.262) +Ostatnio zweryfikowano: 2026-02-13 + +```text +OK (178 tests, 443 assertions) +``` + +Nowe testy/rozszerzenia 2026-02-13: +- `tests/Unit/Domain/Article/ArticleRepositoryTest.php` (nowe przypadki dla `saveFilesOrder`) diff --git a/admin/ajax.php b/admin/ajax.php index e951dcd..eeef67c 100644 --- a/admin/ajax.php +++ b/admin/ajax.php @@ -38,8 +38,7 @@ $mdb = new medoo( [ ] ); require_once 'ajax/pages.php'; -require_once 'ajax/articles.php'; require_once 'ajax/shop-category.php'; require_once 'ajax/users.php'; require_once 'ajax/shop.php'; -?> \ No newline at end of file +?> diff --git a/admin/ajax/articles.php b/admin/ajax/articles.php deleted file mode 100644 index 66d52d6..0000000 --- a/admin/ajax/articles.php +++ /dev/null @@ -1,46 +0,0 @@ - 'error', 'msg' => 'Podczas usuwania zdjecia wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\Articles::delete_img( \S::get( 'image_id' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} - -if ( $a == 'article_file_delete' ) -{ - $response = [ 'status' => 'error', 'msg' => 'Podczas usuwania załącznika wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\Articles::delete_file( \S::get( 'file_id' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} - -if ( $a == 'article_image_alt_change' ) -{ - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany atrybutu alt zdjęcia wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\Articles::image_alt_change( \S::get( 'image_id' ), \S::get( 'image_alt' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} - -if ( $a == 'article_file_name_change' ) -{ - $response = [ 'status' => 'error', 'msg' => 'Podczas zmiany nazwy załącznika wystąpił błąd. Proszę spróbować ponownie.' ]; - - if ( \admin\factory\Articles::file_name_change( \S::get( 'file_id' ), \S::get( 'file_name' ) ) ) - $response = [ 'status' => 'ok' ]; - - echo json_encode( $response ); - exit; -} \ No newline at end of file diff --git a/admin/templates/articles/article-edit-custom-script.php b/admin/templates/articles/article-edit-custom-script.php new file mode 100644 index 0000000..51a0b71 --- /dev/null +++ b/admin/templates/articles/article-edit-custom-script.php @@ -0,0 +1,583 @@ +article ?? null) ? $this->article : []; +$articleId = (int)($article['id'] ?? 0); +$userId = (int)($this->user['id'] ?? 0); +$imagesCount = is_array($article['images'] ?? null) ? count($article['images']) : 0; +$filesCount = is_array($article['files'] ?? null) ? count($article['files']) : 0; + +$imageMaxPx = 1920; +if (isset($this->settings['image_px']) && (int)$this->settings['image_px'] > 0) { + $imageMaxPx = (int)$this->settings['image_px']; +} elseif (isset($GLOBALS['settings']['image_px']) && (int)$GLOBALS['settings']['image_px'] > 0) { + $imageMaxPx = (int)$GLOBALS['settings']['image_px']; +} + +$uploadToken = bin2hex(random_bytes(24)); +if (!isset($_SESSION['upload_tokens']) || !is_array($_SESSION['upload_tokens'])) { + $_SESSION['upload_tokens'] = []; +} +$_SESSION['upload_tokens'][$uploadToken] = [ + 'user_id' => $userId, + 'expires' => time() + 60 * 20, +]; + +$cookiePages = []; +$cookieMenus = []; +if (!empty($_COOKIE['cookie_pages'])) { + $decoded = @unserialize($_COOKIE['cookie_pages']); + if (is_array($decoded)) { + $cookiePages = $decoded; + } +} +if (!empty($_COOKIE['cookie_menus'])) { + $decoded = @unserialize($_COOKIE['cookie_menus']); + if (is_array($decoded)) { + $cookieMenus = $decoded; + } +} +?> + + + + + + + + + + + + + + + + + + diff --git a/admin/templates/articles/article-edit.php b/admin/templates/articles/article-edit.php index 8cd9888..7d3e596 100644 --- a/admin/templates/articles/article-edit.php +++ b/admin/templates/articles/article-edit.php @@ -1,804 +1,6 @@ - - - - -global $db; - -$upload_token = bin2hex( random_bytes(24) ); -$_SESSION['upload_tokens'][$upload_token] = [ - 'user_id' => $this -> user['id'], - 'expires' => time() + 60*20 -]; - -$_SESSION['rfm_akey'] = bin2hex(random_bytes(16)); -$_SESSION['rfm_akey_expires'] = time() + 20*60; -$_SESSION['can_use_rfm'] = true; -$rfmAkeyJS = $_SESSION['rfm_akey']; - -ob_start(); -?> -