Files
rm2.pagedev.pl/.paul/phases/01-media-folders-plugin/01-01-PLAN.md
Jacek Pyziak 5014b9108f feat(media-folder-pro): add virtual folder system for WordPress media library
Custom WordPress plugin that replaces the default flat media library with
a structured folder view. Features: hierarchical folders via custom taxonomy,
sidebar folder tree, drag & drop, modal integration with Elementor/builders,
bulk assign, upload auto-assign, toast notifications.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:08:49 +01:00

9.3 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
01-media-folders-plugin 01 execute 1
wp-content/plugins/media-folder-pro/media-folder-pro.php
wp-content/plugins/media-folder-pro/includes/class-taxonomy.php
wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
wp-content/plugins/media-folder-pro/assets/css/admin.css
wp-content/plugins/media-folder-pro/assets/js/folder-tree.js
true
## Goal Stworzyc fundament pluginu WordPress "RM2 Media Folders" — rejestracja custom taxonomy `media_folder` dla attachment post type, CRUD folderow przez AJAX, oraz bazowy UI drzewka folderow w panelu admina.

Purpose

Bez tego fundamentu nie mozna budowac integracji z biblioteka mediow. Taxonomy to core mechanizm organizacji.

Output

Dzialajacy plugin z:

  • Custom taxonomy media_folder (hierarchiczna, niewidoczna publicznie)
  • AJAX endpoints: tworzenie, zmiana nazwy, usuwanie, przenoszenie folderow
  • Bazowe drzewko folderow renderowane w JS
## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md

Source Files

Nowy plugin — brak istniejacych plikow. Tworzymy od zera.

<acceptance_criteria>

AC-1: Plugin aktywuje sie bez bledow

Given WordPress 6.x z PHP 8.0+
When uzytkownik aktywuje plugin "RM2 Media Folders"
Then plugin aktywuje sie bez bledow i warnings
And w bazie danych pojawia sie taxonomy "media_folder"

AC-2: CRUD folderow dziala przez AJAX

Given plugin jest aktywny
When uzytkownik tworzy folder "Zdjecia produktow" przez UI
Then folder zostaje zapisany jako term w taxonomy media_folder
And odpowiedz AJAX zawiera id i nazwe nowego folderu

Given istniejacy folder "Zdjecia produktow"
When uzytkownik zmienia nazwe na "Produkty 2026"
Then term name i slug zostaja zaktualizowane

Given istniejacy pusty folder
When uzytkownik usuwa folder
Then term zostaje usuniety z bazy

Given istniejacy folder
When uzytkownik przenosi go jako subfolder innego folderu
Then term parent zostaje zaktualizowany

AC-3: Drzewko folderow renderuje sie poprawnie

Given plugin jest aktywny i istnieja foldery z podfolderami
When uzytkownik otwiera strone Media w panelu admina
Then widoczne jest drzewko folderow z hierarchia
And foldery mozna rozwijac/zwijac
And klikniecie folderu filtruje liste mediow

</acceptance_criteria>

Task 1: Core plugin file + taxonomy registration wp-content/plugins/rm2-media-folders/rm2-media-folders.php, wp-content/plugins/rm2-media-folders/includes/class-taxonomy.php 1. Utworzyc glowny plik pluginu rm2-media-folders.php: - Plugin header (Name: RM2 Media Folders, Version: 0.1.0) - Autoload includes/ - Hook init: rejestracja taxonomy - Hook admin_enqueue_scripts: ladowanie CSS/JS na stronach media - Hook wp_ajax_*: rejestracja AJAX handlers
2. Utworzyc includes/class-taxonomy.php:
   - Klasa RM2_Media_Folders_Taxonomy
   - Metoda register(): register_taxonomy('media_folder', 'attachment', args)
     - hierarchical: true
     - public: false
     - show_ui: false (wlasny UI)
     - show_in_rest: true (dla block editora)
   - Metoda get_folder_tree(): zwraca hierarchiczne drzewo folderow
     - Uzywa get_terms() z 'hide_empty' => false
     - Buduje drzewo parent-child

Avoid: Nie uzywac show_ui: true — bedziemy miec wlasny interfejs.
Avoid: Nie rejestrowac taxonomy dla innych post types niz attachment.
- Plugin pojawia sie na liscie pluginow WP - Po aktywacji: wp term list media_folder --format=json (WP-CLI) nie zwraca bledu - Taxonomy istnieje: taxonomy_exists('media_folder') === true AC-1 satisfied: Plugin aktywuje sie, taxonomy zarejestrowana Task 2: AJAX handler for folder CRUD wp-content/plugins/rm2-media-folders/includes/class-ajax-handler.php Utworzyc includes/class-ajax-handler.php: - Klasa RM2_Media_Folders_Ajax
Endpointy AJAX (kazdy z nonce verification + capability check 'upload_files'):

1. rm2_mf_create_folder:
   - Parametry: name (string), parent_id (int, 0 = root)
   - wp_insert_term($name, 'media_folder', ['parent' => $parent_id])
   - Zwraca: {success: true, folder: {id, name, slug, parent}}

2. rm2_mf_rename_folder:
   - Parametry: folder_id (int), name (string)
   - wp_update_term($folder_id, 'media_folder', ['name' => $name])
   - Zwraca: {success: true, folder: {id, name, slug}}

3. rm2_mf_delete_folder:
   - Parametry: folder_id (int)
   - Sprawdz czy folder jest pusty (brak attachmentow i subfolderow)
   - Jesli nie pusty: zwroc blad
   - wp_delete_term($folder_id, 'media_folder')
   - Zwraca: {success: true}

4. rm2_mf_move_folder:
   - Parametry: folder_id (int), new_parent_id (int, 0 = root)
   - Walidacja: nie mozna przeniesc folderu do samego siebie lub swojego dziecka
   - wp_update_term($folder_id, 'media_folder', ['parent' => $new_parent_id])
   - Zwraca: {success: true, folder: {id, name, parent}}

5. rm2_mf_get_folders:
   - Brak parametrow
   - Zwraca pelne drzewo folderow z countami attachmentow

Kazdy endpoint:
- check_ajax_referer('rm2_media_folders_nonce', 'nonce')
- current_user_can('upload_files')
- wp_send_json_success() / wp_send_json_error()

Avoid: Nie uzywac $_GET — wszystko przez $_POST.
Avoid: Nie usuwac folderow z dziecmi — wymuszaj pusty folder.
- AJAX call do rm2_mf_create_folder zwraca 200 z JSON {success: true} - Utworzony term widoczny w get_terms('media_folder') - Proba bez nonce zwraca 403 - Proba bez uprawnien zwraca blad AC-2 satisfied: CRUD folderow dziala przez AJAX z walidacja Task 3: Admin assets + folder tree UI wp-content/plugins/rm2-media-folders/assets/css/admin.css, wp-content/plugins/rm2-media-folders/assets/js/folder-tree.js 1. admin.css: - Styl dla sidebar drzewka folderow (lewy panel, 250px szerokosci) - Style dla elementow drzewka: folder icon, nazwa, expand/collapse arrow - Styl aktywnego folderu (podswietlenie) - Style dla context menu (prawy klik: rename, delete, new subfolder) - Style dla inline edit (zmiana nazwy folderu) - Responsywnosc: na mniejszych ekranach sidebar chowa sie
2. folder-tree.js (vanilla JS, bez jQuery dependency):
   - Klasa RM2FolderTree
   - init(): fetch folderow z AJAX (rm2_mf_get_folders), renderuj drzewo
   - renderTree(folders, container): rekurencyjny render z <ul><li>
   - toggleFolder(folderId): expand/collapse children
   - selectFolder(folderId): podswietl + wyslij event 'rm2-folder-selected'
   - createFolder(parentId): prompt nazwa → AJAX create
   - renameFolder(folderId): inline edit → AJAX rename
   - deleteFolder(folderId): confirm → AJAX delete
   - moveFolder(folderId, newParentId): AJAX move (drag & drop w nastepnej fazie)

   Toolbar nad drzewkiem:
   - Przycisk "+" (nowy folder w root)
   - Przycisk "All Media" (reset filtra)

   Context menu (prawy klik na folder):
   - New subfolder
   - Rename
   - Delete

   Localization: uzyj wp_localize_script z rm2MediaFolders object:
   - ajaxUrl, nonce, i18n strings

3. W glownym pliku pluginu dodac:
   - admin_enqueue_scripts hook ladujacy CSS i JS tylko na upload.php i media-new.php
   - wp_localize_script z nonce i ajax URL
   - Hook na admin_footer (upload.php) wstawiajacy container div dla drzewka

Avoid: Nie ladowac assetow na stronach innych niz media.
Avoid: Nie uzywac jQuery — czysty vanilla JS.
- Na stronie Media > Library widoczny sidebar z drzewkiem - Klikniecie "+" otwiera prompt, po wpisaniu nazwy folder sie pojawia - Prawy klik na folder pokazuje context menu - Klikniecie folderu podswietla go - CSS nie koliduje z domyslnymi stylami WP admin AC-3 satisfied: Drzewko folderow renderuje sie z CRUD operacjami

DO NOT CHANGE

  • wp-content/plugins/elementor-pro/* (nie modyfikujemy Elementora)
  • Zadne pliki core WordPress

SCOPE LIMITS

  • Brak drag & drop mediow do folderow (Phase 2)
  • Brak integracji z media modal (Phase 3)
  • Brak bulk operations (Phase 4)
  • Brak filtrowania listy mediow po kliknieciu folderu (bedzie placeholder, pelna implementacja w Phase 2)
Before declaring plan complete: - [ ] Plugin aktywuje sie bez bledow PHP - [ ] Taxonomy media_folder zarejestrowana i hierarchiczna - [ ] Wszystkie 5 AJAX endpointow odpowiada poprawnie - [ ] Nonce verification dziala (odrzuca requesty bez nonce) - [ ] Drzewko folderow wyswietla sie na stronie Media - [ ] Tworzenie/usuwanie/zmiana nazwy folderu dziala z UI - [ ] Assets ladowane tylko na stronach media (nie na innych)

<success_criteria>

  • Wszystkie taski ukonczone
  • Wszystkie verification checks przeszly
  • Brak bledow PHP (error_log czysty)
  • Brak JS errors w konsoli przegladarki
  • Plugin gotowy jako baza do Phase 2 </success_criteria>
After completion, create `.paul/phases/01-media-folders-plugin/01-01-SUMMARY.md`