---
phase: 01-media-folders-plugin
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - 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
autonomous: true
---

<objective>
## 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
</objective>

<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md

## Source Files
Nowy plugin — brak istniejacych plikow. Tworzymy od zera.
</context>

<acceptance_criteria>

## AC-1: Plugin aktywuje sie bez bledow
```gherkin
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
```gherkin
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
```gherkin
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>

<tasks>

<task type="auto">
  <name>Task 1: Core plugin file + taxonomy registration</name>
  <files>wp-content/plugins/rm2-media-folders/rm2-media-folders.php, wp-content/plugins/rm2-media-folders/includes/class-taxonomy.php</files>
  <action>
    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.
  </action>
  <verify>
    - 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
  </verify>
  <done>AC-1 satisfied: Plugin aktywuje sie, taxonomy zarejestrowana</done>
</task>

<task type="auto">
  <name>Task 2: AJAX handler for folder CRUD</name>
  <files>wp-content/plugins/rm2-media-folders/includes/class-ajax-handler.php</files>
  <action>
    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.
  </action>
  <verify>
    - 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
  </verify>
  <done>AC-2 satisfied: CRUD folderow dziala przez AJAX z walidacja</done>
</task>

<task type="auto">
  <name>Task 3: Admin assets + folder tree UI</name>
  <files>wp-content/plugins/rm2-media-folders/assets/css/admin.css, wp-content/plugins/rm2-media-folders/assets/js/folder-tree.js</files>
  <action>
    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.
  </action>
  <verify>
    - 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
  </verify>
  <done>AC-3 satisfied: Drzewko folderow renderuje sie z CRUD operacjami</done>
</task>

</tasks>

<boundaries>

## 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)

</boundaries>

<verification>
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)
</verification>

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

<output>
After completion, create `.paul/phases/01-media-folders-plugin/01-01-SUMMARY.md`
</output>
