refactor(photos): extract shared zero-padded PhotoRenumberer helper
Factor cache-on-save's renumberPhotos into a shared PhotoRenumberer class (Grav\Plugin\Shared), the single owner of the photo-NN naming invariant used by both the create/edit reconcile and the upcoming live reorder route, so their numbering can't diverge. Changes vs the old private method: - Zero-pads to photo-01..NN (pad width grows with the set) so lexicographic media order equals numeric order past 9 photos — cover = images|first stays correct for 10+ photos. Normalises pre-existing un-padded photo-N on first pass. - Image-extension guard moved into the helper: only real image files on disk are renamed, so a crafted manifest naming the entry .md, a .gpx or a .meta.yaml is skipped by every caller, not just cache-on-save. Create-mode entries now also emit photo-01..NN — an intentional, accepted side effect of sharing one helper. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,15 +6,17 @@ use Grav\Common\Plugin;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
|
||||
require_once __DIR__ . '/classes/EntryScopeGuard.php';
|
||||
require_once __DIR__ . '/classes/PhotoRenumberer.php';
|
||||
|
||||
use Grav\Plugin\Shared\EntryScopeGuard;
|
||||
use Grav\Plugin\Shared\PhotoRenumberer;
|
||||
|
||||
class CacheOnSavePlugin extends Plugin
|
||||
{
|
||||
/**
|
||||
* onFormProcessed fires once per `process:` action (add_page, upload, message,
|
||||
* reset — 4x for the post form). Photo reconciliation must run exactly once:
|
||||
* the first pass renames the kept photos to photo-1..N, so a second pass with
|
||||
* the first pass renames the kept photos to photo-01..NN, so a second pass with
|
||||
* the same manifest would see those renamed files as "unlisted" and delete
|
||||
* them. This latches after the first run (the plugin instance persists for the
|
||||
* request); the first fire is the `add_page` action, after add-page-by-form
|
||||
@@ -244,7 +246,7 @@ class CacheOnSavePlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
$this->renumberPhotos($dir, $names);
|
||||
PhotoRenumberer::renumber($dir, $names);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,38 +278,6 @@ class CacheOnSavePlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename the files named in $names to photo-1..N in that order, in $dir.
|
||||
* Two-phase via temp names so a target (photo-2.jpg) can't clobber a
|
||||
* not-yet-moved source of the same name.
|
||||
*/
|
||||
private function renumberPhotos(string $dir, array $names): void
|
||||
{
|
||||
$planned = [];
|
||||
$i = 1;
|
||||
foreach ($names as $name) {
|
||||
$src = $dir . DIRECTORY_SEPARATOR . $name;
|
||||
if (!is_file($src)) {
|
||||
continue; // skip anything not actually on disk
|
||||
}
|
||||
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION)) ?: 'jpg';
|
||||
$tmp = $dir . DIRECTORY_SEPARATOR . '.reorder-tmp-' . $i . '.' . $ext;
|
||||
$final = $dir . DIRECTORY_SEPARATOR . 'photo-' . $i . '.' . $ext;
|
||||
if ($src === $final) {
|
||||
$i++;
|
||||
continue; // already correctly named
|
||||
}
|
||||
@rename($src, $tmp);
|
||||
$planned[] = [$tmp, $final];
|
||||
$i++;
|
||||
}
|
||||
foreach ($planned as [$tmp, $final]) {
|
||||
if (is_file($tmp)) {
|
||||
@rename($tmp, $final);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate the freshly-created entry folder: the child of the active trip's
|
||||
* dailies directory that contains all of the uploaded files. Matching by the
|
||||
|
||||
Reference in New Issue
Block a user