Drupal 6 – duże obrazy, lokalizacja tematów i bezpieczna optymalizacja
Rozbudowana wersja compare_filesize_drupal6. Działa poza Drupalem, w Pythonie 3.9+; potrzebuje dostępu do MySQL/MariaDB i katalogu plików.
Co robi
- Wyszukuje największe pliki i największe rozdzielczości (JPG, PNG, GIF – GIF wyłącznie do analizy).
- Wskazuje, w jakim temacie, poście lub komentarzu pojawia się obraz. Raport pokazuje
nid,cid, tytuł, typ zawartości, URL do wpisu, URL do edycji i źródło powiązania. - Szuka połączeń przez
upload.fidi pola*_fidw tabelach CCK/ImageField/FileField; obsługuje aktualne rewizje (vid) i opcjonalne tabele załączników komentarzy (cid+fid). - Szuka obrazów w
node_revisions.bodyinode_revisions.teaser,comments.comment, opcjonalnie też w tekstowych polach CCK. Rozróżnia pewne dopasowania identyfikatorafidlub pełnej ścieżki od możliwych trafień po samej nazwie pliku. - Generuje link do oryginalnego pliku (jeżeli publiczny) i pomocniczy link do Drupal Search (jeżeli moduł Search jest aktywny).
- Generuje CSV (polskie kolumny, Excel, UTF-8 BOM) i JSON.
- Symuluje dokładną optymalizację w dry-run, bez zapisu źródłowego pliku i bazy.
- Przy
--applyzachowuje oryginał w oddzielnym katalogu, przygotowuje nowy obraz do atomowej podmiany, zapisujefiles.filesize, a przy błędzie próbuje odtworzyć oryginał i wartości bazy. - Wykrywa duplikaty SHA-256 i pliki na dysku, których nie ma w analizowanym zestawieniu z bazy.
Instalacja
unzip compare_filesize_drupal6-extended.zip
cd compare_filesize_drupal6
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp config.example.py config.py
W config.py ustaw:
DB_CONFIG = {
'host': 'localhost',
'port': 3306,
'database': 'drupal6_db',
'user': 'drupal_user',
'password': 'twoje_haslo',
'charset': 'utf8',
}
FILES_BASE_PATH = '/var/www/drupal/sites/default/files'
PUBLIC_FILES_PATH = 'sites/default/files'
DRUPAL_ROOT = '/var/www/drupal'
DRUPAL_BASE_URL = 'https://forum.example.org'
DB_TABLE_PREFIX = ''
Ważne: FILES_BASE_PATH to lokalizacja rzeczywistych plików, a PUBLIC_FILES_PATH to fragment zapisany zwykle w files.filepath. Jeśli pliki są np. w /var/www/drupal/files, zmień obie wartości. Można też podać je w CLI: --public-files-path, --drupal-root. Gdy Drupal pracuje bez clean URLs, dodaj --no-clean-urls.
1. Znajdź tematy i komentarze z największymi obrazami
python main.py --find-usage --top 50 --report-csv najwieksze-z-linkami.csv
Przykładowe wiersze (fikcyjne):
1. 18.42 MB 4200x5900 fid=1234 scans/mapa.jpg
-> Archiwalne skany (forum, nid=812, pewne)
LINK: https://forum.example.org/node/812
EDYCJA: https://forum.example.org/node/812/edit
SKAD: upload.fid, tresc wpisu (sciezka)
-> Zdjęcie w komentarzu (forum, nid=920, cid=42, pewne)
LINK: https://forum.example.org/node/920#comment-42
CSV zawiera jedną linię dla każdego znalezionego miejsca. Gdy powiązania brak, w CSV zostaje plik, jego fid, rozmiar i propozycja wyszukiwania nazwą w Drupal Search.
Tylko skany lub wybrane pliki
python main.py --find-usage --top 100 --path-contains skan --report-csv skany.csv
python main.py --find-usage --fid 1234 --report-csv jeden-obraz.csv
python main.py --find-usage --min-size-mb 5 --usage-scope all --report-csv wieksze-niz-5mb.csv
--usage-scope top szuka tylko w --top N największych obrazach; optimizable – w obrazach przekraczających limity; all – w całym filtrowanym zestawieniu. Przy bardzo dużych bazach all może oznaczać długi skan treści. --no-text-scan wyłącza szukanie w treściach i zostawia szybsze powiązania fid. --scan-cck-text rozszerza skan na tekstowe pola CCK.
2. Dokładny dry-run optymalizacji
python main.py \
--find-usage --usage-scope optimizable \
--optimize --dry-run --optimize-top 20 \
--max-width 2400 --max-height 3200 --max-file-mb 2 \
--report-csv plan.csv --report-json plan.json
Dostaniesz rzeczywisty przewidywany rozmiar po rekompresji (test wykonany na pliku tymczasowym). Nie zmieni to oryginałów ani SQL. --top dotyczy wyświetlania; --optimize-top ogranicza liczbę obrazów poddawanych testowi/zmniejszaniu.
3. Zmniejsz np. pierwsze 10 obrazów i aktualizuj bazę
Najpierw zrób pełen backup bazy danych i katalogu plików oraz przetestuj na kopii. Następnie:
python main.py \
--optimize --apply \
--optimize-top 10 --max-changes 10 \
--backup-dir /srv/backups/drupal6-images \
--max-width 2400 --max-height 3200 --max-file-mb 2 \
--report-csv wykonane.csv --report-json wykonane.json
Każda udana zmiana:
- Zapisuje oryginał w osobnym katalogu (automatycznie tworzony podfolder uruchomienia).
- Zastępuje obraz tylko jeżeli nowy plik jest mniejszy o co najmniej
--min-gain-percent(domyślnie 5%). - Aktualizuje
files.filesizedla wszystkichfidwskazujących na tę samą ścieżkę. - W przypadku błędu SQL próbuje odtworzyć oryginalny plik i rozmiar w DB (także przy MyISAM – kompensacja aktualizacji).
--apply jest wymagane do każdego zapisu. Samo --optimize lub --update-db nie wykonuje zmian. Realna optymalizacja zawsze aktualizuje rozmiar w DB, także bez --update-db.
Jeżeli chcesz wyłącznie zsynchronizować rozmiary plików w istniejącym files:
python main.py --update-db --dry-run
python main.py --update-db --apply
--update-db w połączeniu z --optimize --apply dodatkowo koryguje rozmiary tych plików, które nie zostały zoptymalizowane.
Zasady jakości i bezpieczeństwa
- JPEG: zachowuje rozszerzenie i ścieżkę, skaluje proporcjonalnie filtrem LANCZOS, zapisuje z wysoką jakością 92/89/86/85 (
--jpeg-quality,--min-jpeg-quality). Nie schodzi poniżej skonfigurowanej jakości, nawet gdy cel 2 MB nie zostanie osiągnięty. JPEG jest formatem stratnym – każda ponowna kompresja może zmienić piksele. - PNG: zachowuje format oraz kanał przezroczystości, używa kompresji bezstratnej. Nie konwertuje PNG do JPEG i nie zmienia rozszerzeń, bo mogłoby to popsuć stare linki w Drupalu. Duży PNG ze skanem może pozostać duży, jeśli kompresja bezstratna nic nie da. Konwersja do JPEG wymagałaby osobnej, kontrolowanej migracji i aktualizacji odnośników.
- Skan tekstowy: domyślny limit 2400 × 3200 px zamiast starego 1920 × 1080. Przed decyzją sprawdź czytelność drobnego druku w próbce i w razie potrzeby zwiększ limity lub pomiń plik.
- GIF/animacje, nieobsługiwane formaty, niezgodności formatu i rozszerzenia: pomijane przy zapisie. Symlinki i hardlinki też są pomijane.
- Kopia oryginału wymagana jest przy
--optimize --apply, a lokalizacja kopii musi być pozaFILES_BASE_PATHi poza katalogiem WWW Drupala (jeśli ustawionoDRUPAL_ROOT). - Weryfikacja czasu modyfikacji i inode chroni przed zmianą pliku w trakcie skanowania; zalecane jest wykonywanie pracy w oknie serwisowym.
- Zachowuje ICC, DPI, EXIF (z prawidłową obsługą orientacji) i tekstowe metadane PNG w obsługiwanych formatach, ale nie gwarantuje zachowania każdego niestandardowego segmentu metadanych.
- Aktualizowany jest tylko
files.filesize– nie są zmieniane ścieżki,fid, treści postów ani załączniki. Zmiana dużego obrazka może wymagać ręcznego odświeżenia wygenerowanych miniatur przez ImageCache. - Kopia wykonana przez samo narzędzie obejmuje obraz, nie całą bazę. MyISAM nie zapewnia transakcji; procedura przywracania jest best-effort. Pełny backup DB i plików przed zmianami jest obowiązkowy.
Pozostałe opcje
python main.py --find-duplicates
python main.py --show-deleted --exclude-folders imagecache styles
python main.py --find-usage --no-clean-urls --site-url https://example.org/drupal
python main.py --help
Uwaga do --show-deleted: pokazuje pliki na dysku bez pasującego wpisu files w analizowanym zestawieniu, nie zaś potwierdzenie, że plik naprawdę nie występuje w treści. Przy filtrach (--path-contains, --min-size-mb, --fid) plik odfiltrowany może zostać pokazany jako „spoza zestawienia”. Nic nie jest usuwane.
Ograniczenia wyszukiwania
- Powiązania po
fidsą najbardziej jednoznaczne; wyszukiwanie po samej nazwie pliku bywa niejednoznaczne – w raporciepewnosc=mozliwe. - Tekst przeszukiwany jest w aktualnych rewizjach węzłów i komentarzach. Nie szuka w archiwalnych rewizjach ani w niestandardowych zewnętrznych modułach przechowywania treści bez włączonego skanu CCK.
- Link do nieopublikowanego wpisu lub komentarza może wymagać konta z prawami administracyjnymi. Raport to zaznacza.
- Drupal 6 stronicuje komentarze:
node/NID#comment-CIDmoże nie przewinąć do komentarza z dalszej strony. Jeżeli masz zainstalowany moduł Permalink dla Drupal 6, dodaj--comment-permalinks, aby generowaćcomment/CID#comment-CID, które kieruje na właściwą stronę komentarzy. Bez tego modułu nie używaj tej flagi. Niezależnie od typu linku raport pokazujenidicid. - Nie ma gwarancji odnalezienia obrazów w niestandardowych relacjach tworzonych przez własne moduły, w CSS i w HTML poza bazą.
- W przypadku prywatnego systemu plików adres bezpośredni do pliku może nie działać; odnośnik do tematu nadal powinien wskazać miejsce.
Testy
python -m unittest discover -s tests -v
Testy z lokalną, symulowaną bazą weryfikują powiązania Upload/CCK, obecne rewizje, komentarze, brak zmian w dry-run, aktualizację files.filesize, backup, przywracanie po błędzie SQL, format PNG i ścieżki katalogów. Nie zastępują próby na kopii konkretnej instalacji Drupal 6.
Źródła struktury bazy Drupal 6
- Oficjalny migrator Drupal 6 Upload –
upload.fid,upload.nid,upload.vid. - Oficjalny migrator komentarzy D6 – tabela
comments,cid,nid, status komentarza. - CCK 6 –
content_type_*,content_field_*.