From f4521d4cced5261293dc8448146ecc9a95c191a9 Mon Sep 17 00:00:00 2001 From: hbrain Date: Tue, 26 May 2026 10:38:11 +0200 Subject: [PATCH] Use media date for new input directories --- new.php | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/new.php b/new.php index 722203e..45db00d 100644 --- a/new.php +++ b/new.php @@ -64,6 +64,62 @@ function write_data($dir, $post){ } function editable_file($f){ $ext = strtolower(pathinfo((string)$f, PATHINFO_EXTENSION)); return $f !== '' && $f[0] !== '.' && $f !== 'data.txt' && in_array($ext, ['jpg','jpeg','png','webp','gif','mp4','mov','m4v','avi','mkv','webm','mp3','wav','m4a','aac','ogg','flac'], true); } function list_files($dir){ $files = array_values(array_filter(scandir($dir), fn($f)=>editable_file($f) && is_file($dir.'/'.$f))); natcasesort($files); return $files; } +function media_file_date($path){ + $ext = strtolower(pathinfo((string)$path, PATHINFO_EXTENSION)); + if (in_array($ext, ['jpg','jpeg','tif','tiff'], true) && function_exists('exif_read_data')) { + $exif = @exif_read_data($path); + foreach (['DateTimeOriginal','DateTimeDigitized','DateTime'] as $k) { + if (!empty($exif[$k]) && preg_match('/^(\d{4}):(\d{2}):(\d{2})/', (string)$exif[$k], $m)) return "$m[1]$m[2]$m[3]"; + } + } + if (in_array($ext, ['mp4','mov','m4v','avi','mkv','webm'], true)) { + $ffprobe = trim((string)shell_exec('command -v ffprobe 2>/dev/null')); + if ($ffprobe !== '') { + $json = shell_exec(escapeshellarg($ffprobe).' -v quiet -print_format json -show_entries format_tags=creation_time:stream_tags=creation_time '.escapeshellarg($path).' 2>/dev/null'); + $data = json_decode((string)$json, true); + $candidates = []; + if (is_array($data['format']['tags'] ?? null)) $candidates[] = $data['format']['tags']['creation_time'] ?? ''; + foreach (($data['streams'] ?? []) as $stream) if (is_array($stream['tags'] ?? null)) $candidates[] = $stream['tags']['creation_time'] ?? ''; + foreach ($candidates as $value) { + if (preg_match('/^(\d{4})-(\d{2})-(\d{2})/', (string)$value, $m)) return "$m[1]$m[2]$m[3]"; + } + } + } + return null; +} +function input_dir_date_from_media($dir){ + $dates = []; + foreach (list_files($dir) as $file) { + $date = media_file_date($dir . '/' . $file); + if ($date !== null) $dates[] = $date; + } + if ($dates) { + sort($dates, SORT_STRING); + return $dates[0]; + } + return date('Ymd'); +} +function input_dir_date_from_text($text){ + $text = trim((string)$text); + if ($text === '') return null; + if (preg_match('/^(\d{4})[.-]?(\d{2})[.-]?(\d{2})$/', $text, $m) && checkdate((int)$m[2], (int)$m[3], (int)$m[1])) return "$m[1]$m[2]$m[3]"; + if (preg_match('/^(\d{1,2})[\/. -](\d{1,2})[\/. -](\d{4})$/', $text, $m) && checkdate((int)$m[2], (int)$m[1], (int)$m[3])) return sprintf('%04d%02d%02d', $m[3], $m[2], $m[1]); + $ts = strtotime($text); + if ($ts !== false) return date('Ymd', $ts); + if (preg_match('/^(jan|january|feb|february|mar|march|apr|april|may|jun|june|jul|july|aug|august|sep|sept|september|oct|october|nov|november|dec|december)\s+(\d{4})$/i', $text, $m)) { + $months = ['jan'=>1,'january'=>1,'feb'=>2,'february'=>2,'mar'=>3,'march'=>3,'apr'=>4,'april'=>4,'may'=>5,'jun'=>6,'june'=>6,'jul'=>7,'july'=>7,'aug'=>8,'august'=>8,'sep'=>9,'sept'=>9,'september'=>9,'oct'=>10,'october'=>10,'nov'=>11,'november'=>11,'dec'=>12,'december'=>12]; + return sprintf('%04d%02d01', (int)$m[2], $months[strtolower($m[1])]); + } + return null; +} +function unique_input_dir($base, $slug){ + $dir = $base . '/' . $slug; + if (!file_exists($dir)) return $dir; + for ($i = 2; ; $i++) { + $candidate = $base . '/' . $slug . '-' . $i; + if (!file_exists($candidate)) return $candidate; + } +} function orphan_videos($config){ $referenced = []; foreach (input_dirs($config['uploads_dir']) as $dir) { @@ -123,13 +179,19 @@ try { if ($action === 'create') { $title = trim($_POST['title'] ?? ''); if ($title === '') throw new RuntimeException('Title is required.'); - $slug = date('Ymd') . '_' . slugify($title); - $dir = $config['uploads_dir'] . '/' . $slug; - if (!mkdir($dir, 0775, true)) throw new RuntimeException('Cannot create input directory.'); + $tmpSlug = '.upload-' . date('YmdHis') . '-' . bin2hex(random_bytes(4)); + $tmpDir = $config['uploads_dir'] . '/' . $tmpSlug; + if (!mkdir($tmpDir, 0775, true)) throw new RuntimeException('Cannot create temporary input directory.'); + chmod($tmpDir, 02775); + $media = save_uploads('media', $tmpDir, $allowedMedia); + if (!$media) { rrmdir($tmpDir); throw new RuntimeException('Upload at least one image or video.'); } + save_uploads('audio', $tmpDir, $allowedAudio); + $mediaDate = input_dir_date_from_text($_POST['date'] ?? '') ?? input_dir_date_from_media($tmpDir); + $slug = $mediaDate . '_' . slugify($title); + $dir = unique_input_dir($config['uploads_dir'], $slug); + $slug = basename($dir); + if (!rename($tmpDir, $dir)) { rrmdir($tmpDir); throw new RuntimeException('Cannot create input directory.'); } chmod($dir, 02775); - $media = save_uploads('media', $dir, $allowedMedia); - if (!$media) { rrmdir($dir); throw new RuntimeException('Upload at least one image or video.'); } - save_uploads('audio', $dir, $allowedAudio); write_data($dir, $_POST); $msg = "Created movmaker input directory: in-dir/$slug"; $_GET['edit'] = $slug;