fix: Bildauswahl nach Dolibarr-Galerie-Reihenfolge (Position/Cover) statt alphabetisch [deploy]
All checks were successful
Deploy ProductImageTags / deploy (push) Successful in 9s
All checks were successful
Deploy ProductImageTags / deploy (push) Successful in 9s
Bilder wurden bisher rein alphabetisch nach Dateiname sortiert — dadurch landete ein willkürliches Bild im Angebot, nicht das, was in der Produktgalerie als erstes/Hauptbild festgelegt ist. listSourceImages liest jetzt position + cover aus llx_ecm_files und sortiert exakt wie Product::show_photos(): Cover zuerst, dann Galerie-Position (Dokumente-Tab → Reihenfolge per Pfeile/Drag&Drop), dann alphabetisch als Fallback. Nicht indexierte Dateien ans Ende. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8cd8ec58ab
commit
6b74300233
2 changed files with 57 additions and 4 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
|
@ -1,5 +1,17 @@
|
|||
# Changelog — ProductImageTags
|
||||
|
||||
## 0.1.1 (2026-06-18)
|
||||
|
||||
### Behoben
|
||||
- **Falsches Produktbild im Angebot.** Bilder wurden rein alphabetisch nach Dateiname
|
||||
sortiert, dadurch landete „das erste Bild" willkürlich im PDF — nicht das, was im
|
||||
Produktkärtchen als Hauptbild/erstes Bild angezeigt wird. `listSourceImages` liest
|
||||
jetzt `position` und `cover` aus `llx_ecm_files` und sortiert exakt wie Dolibarrs
|
||||
`Product::show_photos()`: Cover (Hauptbild) zuerst, dann Galerie-Position, dann
|
||||
alphabetisch als Fallback. Nicht indexierte Dateien landen am Ende (Position 999999).
|
||||
→ Hauptbild per Drag&Drop an Position 1 ziehen oder als Cover markieren steuert jetzt,
|
||||
welches Bild im Angebot erscheint.
|
||||
|
||||
## 0.1.0 (2026-04-24)
|
||||
|
||||
Erste lauffähige Version — Bilder erscheinen live in Angebots-/Auftrags-PDFs.
|
||||
|
|
|
|||
|
|
@ -167,18 +167,59 @@ class ProductImage
|
|||
return array();
|
||||
}
|
||||
|
||||
// dol_dir_list sortiert stabil alphabetisch. Thumbnails (thumbs-Unterordner + _small/_mini-Suffixe) ausschließen.
|
||||
// Thumbnails (thumbs-Unterordner + _small/_mini-Suffixe) ausschließen.
|
||||
$files = dol_dir_list($photoDir, 'files', 0, '', array('\.meta$', '_small\.', '_mini\.', '_preview'), 'name', SORT_ASC);
|
||||
if (empty($files)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$result = array();
|
||||
// WICHTIG: Reihenfolge GENAU wie Dolibarr im Produktkärtchen (Product::show_photos
|
||||
// sortiert nach position_name + cover aus der Tabelle ecm_files). Sortieren wir nur
|
||||
// alphabetisch nach Dateiname, ist „das erste Bild" willkürlich und passt nicht zu
|
||||
// dem, was der User als Hauptbild/erste Reihenfolge in der Bildergalerie sieht.
|
||||
// Deshalb Position + Cover aus ecm_files lesen und danach sortieren:
|
||||
// 1. Cover (manuell als Hauptbild markiert) zuerst
|
||||
// 2. dann Position (per Drag&Drop in der Galerie festgelegt)
|
||||
// 3. dann alphabetisch als Fallback (nicht indexierte Dateien ans Ende)
|
||||
$relativedir = trim(preg_replace('#^'.preg_quote(DOL_DATA_ROOT, '#').'#', '', $photoDir), '/\\');
|
||||
$meta = array();
|
||||
$dbfiles = dol_dir_list_in_database($relativedir, '', null, 'name', SORT_ASC, 0, '', $product);
|
||||
foreach ($dbfiles as $dbf) {
|
||||
$meta[$dbf['name']] = array(
|
||||
'position' => (int) $dbf['position'],
|
||||
'cover' => (int) $dbf['cover'],
|
||||
);
|
||||
}
|
||||
|
||||
$indexed = array();
|
||||
foreach ($files as $file) {
|
||||
$fullPath = $file['fullname'];
|
||||
if (image_format_supported($fullPath) > 0) {
|
||||
$result[] = $fullPath;
|
||||
if (image_format_supported($fullPath) <= 0) {
|
||||
continue;
|
||||
}
|
||||
$name = $file['name'];
|
||||
$indexed[] = array(
|
||||
'path' => $fullPath,
|
||||
'name' => $name,
|
||||
'cover' => isset($meta[$name]) ? $meta[$name]['cover'] : 0,
|
||||
// Nicht indexierte Dateien ans Ende (Dolibarr-Konvention: position 999999)
|
||||
'position' => isset($meta[$name]) ? $meta[$name]['position'] : 999999,
|
||||
);
|
||||
}
|
||||
|
||||
usort($indexed, function ($a, $b) {
|
||||
if ($a['cover'] !== $b['cover']) {
|
||||
return $b['cover'] - $a['cover']; // cover=1 zuerst
|
||||
}
|
||||
if ($a['position'] !== $b['position']) {
|
||||
return $a['position'] - $b['position'];
|
||||
}
|
||||
return strcasecmp($a['name'], $b['name']);
|
||||
});
|
||||
|
||||
$result = array();
|
||||
foreach ($indexed as $row) {
|
||||
$result[] = $row['path'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue