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>
This commit is contained in:
211
.paul/phases/03-media-modal/03-01-PLAN.md
Normal file
211
.paul/phases/03-media-modal/03-01-PLAN.md
Normal file
@@ -0,0 +1,211 @@
|
||||
---
|
||||
phase: 03-media-modal
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: ["02-01"]
|
||||
files_modified:
|
||||
- wp-content/plugins/media-folder-pro/assets/js/modal-integration.js
|
||||
- wp-content/plugins/media-folder-pro/assets/css/admin.css
|
||||
- wp-content/plugins/media-folder-pro/media-folder-pro.php
|
||||
- wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Zintegrowac drzewko folderow z modalem WP media (wp.media modal) — tym samym, ktory otwiera sie w edytorze blokowym, klasycznym edytorze, Elementorze i innych pluginach uzywajacych wp.media. Uzytkownik moze filtrowac media po folderze wewnatrz modala oraz przypisac folder podczas uploadu.
|
||||
|
||||
## Purpose
|
||||
Modal mediow to glowny punkt interakcji z biblioteka — bez integracji uzytkownik nie moze korzystac z folderow podczas wstawiania mediow do tresci.
|
||||
|
||||
## Output
|
||||
- Dropdown/sidebar z folderami wewnatrz modala media
|
||||
- Filtrowanie mediow w modalu po wybranym folderze
|
||||
- Mozliwosc wyboru folderu docelowego przy uploadzie nowych plikow
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
|
||||
## Prior Work
|
||||
@.paul/phases/02-media-library-grid/02-01-SUMMARY.md
|
||||
- MFP_Media_Query z filtrem ajax_query_attachments_args (juz dziala dla modala tez!)
|
||||
- mfp_assign_media endpoint gotowy
|
||||
- media-filter.js z wzorcem library.props.set({media_folder: id})
|
||||
|
||||
## Source Files
|
||||
@wp-content/plugins/media-folder-pro/media-folder-pro.php
|
||||
@wp-content/plugins/media-folder-pro/assets/js/media-filter.js
|
||||
@wp-content/plugins/media-folder-pro/includes/class-media-query.php
|
||||
@wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
|
||||
@wp-content/plugins/media-folder-pro/assets/css/admin.css
|
||||
</context>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Dropdown folderow widoczny w modalu media
|
||||
```gherkin
|
||||
Given plugin aktywny, istnieja foldery
|
||||
When uzytkownik otwiera modal media (np. "Dodaj media" w edytorze)
|
||||
Then w pasku narzedzi modala widoczny jest dropdown z lista folderow
|
||||
And dropdown zawiera opcje "Wszystkie media" + lista folderow hierarchicznie
|
||||
```
|
||||
|
||||
## AC-2: Filtrowanie mediow w modalu po folderze
|
||||
```gherkin
|
||||
Given modal media otwarty, istnieja foldery z mediami
|
||||
When uzytkownik wybiera folder z dropdown
|
||||
Then grid mediow w modalu pokazuje tylko media z wybranego folderu
|
||||
And wybranie "Wszystkie media" przywraca pelna liste
|
||||
```
|
||||
|
||||
## AC-3: Przypisanie folderu przy uploadzie
|
||||
```gherkin
|
||||
Given modal media otwarty, wybrany folder "Zdjecia produktow"
|
||||
When uzytkownik uploaduje nowy plik przez zakladke "Wyslij pliki"
|
||||
Then nowo uploadowany plik zostaje automatycznie przypisany do aktywnego folderu
|
||||
And plik pojawia sie w filtrowanym widoku tego folderu
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Modal folder dropdown + filtering</name>
|
||||
<files>wp-content/plugins/media-folder-pro/assets/js/modal-integration.js, wp-content/plugins/media-folder-pro/assets/css/admin.css, wp-content/plugins/media-folder-pro/media-folder-pro.php</files>
|
||||
<action>
|
||||
1. Utworzyc assets/js/modal-integration.js:
|
||||
- Hook na wp.media.view.AttachmentsBrowser:
|
||||
- Nadpisz (extend) domyslny AttachmentsBrowser
|
||||
- W metodzie createToolbar() dodaj customowy dropdown filter
|
||||
- Dropdown budowany z danych folderow (AJAX mfp_get_folders przy otwarciu)
|
||||
- Opcje: "Wszystkie media" (value=0) + foldery z wciecia dla hierarchii
|
||||
- Np: "Zdjecia", "— Produkty", "— — Elektronika" (hierarchia przez prefiks)
|
||||
- Przy zmianie dropdown:
|
||||
- library.props.set({media_folder: selectedFolderId})
|
||||
- To uzyje istniejacego MFP_Media_Query filtra server-side
|
||||
- Przechowuj aktywny folder w zmiennej modulu (potrzebne dla upload)
|
||||
|
||||
2. Hook na wp.media.view.UploaderInline (upload tab):
|
||||
- Po uplywie uploadu (wp.Uploader 'upload-success' lub 'wp-upload-complete'):
|
||||
- Jesli aktywny folder > 0:
|
||||
- Wywolaj AJAX mfp_assign_media z nowym attachment_id i aktywnym folderem
|
||||
- Alternatywnie: hook na wp.media.model.Attachment po dodaniu do kolekcji
|
||||
|
||||
3. Podejscie do hookowania WP media views:
|
||||
- Uzyj wp.media.view.AttachmentsBrowser.extend() do nadpisania createToolbar
|
||||
- LUB: uzyj filtra 'AttachmentsBrowser:ready' jesli dostepny
|
||||
- LUB: monkey-patch wp.media.view.AttachmentsBrowser.prototype.createToolbar
|
||||
- Wybierz podejscie ktore NIE wymaga modyfikacji core WP JS
|
||||
- Najstabilniejszy pattern: nadpisz prototype.createToolbar, wywolaj original,
|
||||
potem dodaj swoj element do this.toolbar
|
||||
|
||||
4. W admin.css dodac style dla:
|
||||
- .mfp-modal-filter — select dropdown w toolbarze modala
|
||||
- Styl opcji z wciecia (hierarchia folderow)
|
||||
- Dopasowanie do domyslnego stylu WP media toolbar
|
||||
|
||||
5. W media-folder-pro.php:
|
||||
- Enqueue modal-integration.js globalnie w admin (nie tylko upload.php)
|
||||
bo modal moze byc otwarty z dowolnej strony admina
|
||||
- Dependency: ['media-views']
|
||||
- Warunek: enqueue tylko jesli wp_script_is('media-views', 'enqueued')
|
||||
lub laduj z wp_enqueue_media hook
|
||||
|
||||
Avoid: Nie modyfikowac core WP JS — tylko extend/override prototypow.
|
||||
Avoid: Nie ladowac pelnego folder-tree.js w modalu — uzyj lekkiego dropdown.
|
||||
Avoid: Nie uzywac jQuery UI — czysty select element lub custom dropdown.
|
||||
</action>
|
||||
<verify>
|
||||
- Otwarcie modala media w edytorze pokazuje dropdown folderow
|
||||
- Wybranie folderu filtruje media w modalu
|
||||
- Upload pliku z aktywnym folderem przypisuje go do folderu
|
||||
- Modal dziala normalnie bez folderow (brak regresji)
|
||||
- Dropdown laduje hierarchie poprawnie (wciety subfoldery)
|
||||
</verify>
|
||||
<done>AC-1 + AC-2 + AC-3 satisfied: modal z dropdown, filtrowanie, upload do folderu</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Auto-assign uploaded media + refresh counters</name>
|
||||
<files>wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php, wp-content/plugins/media-folder-pro/assets/js/modal-integration.js</files>
|
||||
<action>
|
||||
1. W class-ajax-handler.php dodac nowy endpoint mfp_upload_to_folder:
|
||||
- Parametry: attachment_id (int), folder_id (int)
|
||||
- Prostszy niz mfp_assign_media (pojedynczy plik, nie tablica)
|
||||
- wp_set_object_terms($attachment_id, [$folder_id], 'media_folder')
|
||||
- Zwraca: {success: true}
|
||||
- Dodac do tablicy $actions w register_hooks()
|
||||
- Ten endpoint jest dedykowany dla upload flow (szybszy, bez folder_counts)
|
||||
|
||||
2. W modal-integration.js:
|
||||
- Po AJAX uplywie uploadu nowego pliku:
|
||||
- Nasluchuj na wp.Uploader events lub Attachment collection events
|
||||
- Pattern: wp.media.model.Attachments on('add') — nowy attachment dodany
|
||||
- Jesli aktywny folder: wywolaj mfp_upload_to_folder
|
||||
- Po przypisaniu: dispatch 'mfp-folder-changed' event
|
||||
(zeby upload.php folder tree tez sie odswieszyl jesli otwarty)
|
||||
|
||||
3. Synchronizacja z upload.php:
|
||||
- Jesli modal otwarty z upload.php (media library page):
|
||||
- Po zamknieciu modala: dispatch 'mfp-folder-changed'
|
||||
- folder-tree.js nasluchuje i wywoluje refreshTree()
|
||||
- Dodac listener w folder-tree.js na 'mfp-folder-changed'
|
||||
|
||||
Avoid: Nie duplikuj logiki mfp_assign_media — mfp_upload_to_folder to uproszczona wersja.
|
||||
Avoid: Nie refreshuj counterow w modalu (zbyt ciezkie) — tylko po zamknieciu.
|
||||
</action>
|
||||
<verify>
|
||||
- Upload pliku z aktywnym folderem przypisuje automatycznie
|
||||
- Po zamknieciu modala countery folderow na upload.php sa aktualne
|
||||
- Upload bez aktywnego folderu nie przypisuje do zadnego folderu
|
||||
- Brak duplikatow przypisania (jeden upload = jedna operacja)
|
||||
</verify>
|
||||
<done>AC-3 reinforced: upload flow roboczy z auto-assign i sync counterow</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- wp-content/plugins/elementor-pro/* (nie modyfikujemy Elementora)
|
||||
- wp-content/plugins/media-folder-pro/includes/class-taxonomy.php (stabilna)
|
||||
- wp-content/plugins/media-folder-pro/includes/class-media-query.php (stabilna, juz filtruje modal)
|
||||
- Zadne pliki core WordPress
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Brak drag & drop w modalu (tylko dropdown filter)
|
||||
- Brak tworzenia folderow z modala (tylko wybor istniejacych)
|
||||
- Brak bulk operations (Phase 4)
|
||||
- Elementor-specific hooks NIE sa potrzebne — Elementor uzywa standardowego wp.media
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] Dropdown folderow widoczny w modalu media
|
||||
- [ ] Filtrowanie dziala: wybor folderu → tylko media z folderu
|
||||
- [ ] "Wszystkie media" przywraca pelna liste
|
||||
- [ ] Upload z aktywnym folderem → auto-assign do folderu
|
||||
- [ ] Upload bez folderu → brak przypisania (normalne zachowanie)
|
||||
- [ ] Po zamknieciu modala → countery na upload.php odswiezone
|
||||
- [ ] Modal otwierany z roznych stron (post edit, page edit) dziala
|
||||
- [ ] Brak regresji: modal bez folderow dziala normalnie
|
||||
- [ ] Brak JS errors w konsoli
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie taski ukonczone
|
||||
- Wszystkie verification checks przeszly
|
||||
- Modal media w pelni zintegrowany z folderami
|
||||
- Brak bledow PHP i JS
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/03-media-modal/03-01-SUMMARY.md`
|
||||
</output>
|
||||
121
.paul/phases/03-media-modal/03-01-SUMMARY.md
Normal file
121
.paul/phases/03-media-modal/03-01-SUMMARY.md
Normal file
@@ -0,0 +1,121 @@
|
||||
---
|
||||
phase: 03-media-modal
|
||||
plan: 01
|
||||
subsystem: media
|
||||
tags: [wordpress, media-modal, backbone-extend, upload-hook, wp-uploader]
|
||||
|
||||
requires:
|
||||
- phase: 02-media-library-grid
|
||||
provides: MFP_Media_Query filter, mfp_assign_media endpoint
|
||||
provides:
|
||||
- Folder dropdown in wp.media modal
|
||||
- Modal filtering via backbone props
|
||||
- Auto-assign uploads to active folder
|
||||
- mfp_upload_to_folder lightweight endpoint
|
||||
affects: [04-polish-ux]
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [wp.media.view.AttachmentsBrowser.extend, wp.Uploader.queue hook, modal close hook, foldersCache pattern]
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- wp-content/plugins/media-folder-pro/assets/js/modal-integration.js
|
||||
modified:
|
||||
- wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
|
||||
- wp-content/plugins/media-folder-pro/assets/js/folder-tree.js
|
||||
- wp-content/plugins/media-folder-pro/assets/css/admin.css
|
||||
- wp-content/plugins/media-folder-pro/media-folder-pro.php
|
||||
|
||||
key-decisions:
|
||||
- "Extend AttachmentsBrowser.prototype.createToolbar — call original then add dropdown"
|
||||
- "Flat <select> dropdown instead of full tree in modal — lightweight, less DOM"
|
||||
- "Hierarchical indent via em-space prefix in option labels"
|
||||
- "Cache folders per modal open, invalidate on close"
|
||||
- "Dual upload hook: wp.Uploader.queue + Attachment.sync override for reliability"
|
||||
- "enqueue_modal_assets on all admin pages except upload.php (handled separately)"
|
||||
|
||||
patterns-established:
|
||||
- "mfp-folder-changed CustomEvent for cross-module sync"
|
||||
- "Modal close → foldersCache invalidation + counter refresh"
|
||||
- "Inline script registration (wp_register_script false) for mfpData on non-media pages"
|
||||
|
||||
duration: ~10min
|
||||
started: 2026-03-28
|
||||
completed: 2026-03-28
|
||||
---
|
||||
|
||||
# Phase 3 Plan 01: Media Upload Modal Integration Summary
|
||||
|
||||
**Folder dropdown filter in wp.media modal with auto-assign on upload, using AttachmentsBrowser.extend and wp.Uploader hooks.**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~10min |
|
||||
| Tasks | 2 completed |
|
||||
| Files created | 1 |
|
||||
| Files modified | 4 |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Dropdown folderow widoczny w modalu | Pass | AttachmentsBrowser toolbar extended with select |
|
||||
| AC-2: Filtrowanie mediow w modalu | Pass | library.props.set via same MFP_Media_Query filter |
|
||||
| AC-3: Przypisanie folderu przy uploadzie | Pass | wp.Uploader.queue + Attachment.sync hooks |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Extended `wp.media.view.AttachmentsBrowser.createToolbar` to inject folder dropdown
|
||||
- Hierarchical folder list with em-space indent and counts in dropdown options
|
||||
- Upload auto-assign via dual hooks (wp.Uploader.queue change:status + Attachment.sync)
|
||||
- `mfp_upload_to_folder` lightweight single-file endpoint
|
||||
- Modal close triggers `mfp-folder-changed` event → folder-tree.js refreshes counters
|
||||
- `enqueue_modal_assets()` loads on all admin pages where media-views is present
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `assets/js/modal-integration.js` | Created | Modal dropdown, filtering, upload auto-assign, close sync |
|
||||
| `includes/class-ajax-handler.php` | Modified | Added mfp_upload_to_folder endpoint |
|
||||
| `assets/js/folder-tree.js` | Modified | Added mfp-folder-changed listener |
|
||||
| `assets/css/admin.css` | Modified | Modal dropdown styles |
|
||||
| `media-folder-pro.php` | Modified | enqueue_modal_assets + modal JS enqueue on upload.php |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| Extend prototype vs filter hook | More reliable, works across all modal instances | Robust integration |
|
||||
| Flat select vs tree in modal | Modal space is limited, select is native WP pattern | Consistent UX |
|
||||
| Dual upload hooks | Different WP versions trigger differently | Reliable across WP 6.0+ |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
None
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Full modal integration operational
|
||||
- All 7 AJAX endpoints in place
|
||||
- Core feature set complete for MVP
|
||||
- Phase 4 can focus purely on UX polish
|
||||
|
||||
**Concerns:**
|
||||
- List view (table mode) still unhandled
|
||||
- No keyboard navigation in modal dropdown
|
||||
|
||||
**Blockers:**
|
||||
- None
|
||||
|
||||
---
|
||||
*Phase: 03-media-modal, Plan: 01*
|
||||
*Completed: 2026-03-28*
|
||||
Reference in New Issue
Block a user