diff --git a/main-cache-build.php b/main-cache-build.php new file mode 100644 index 0000000..788d954 --- /dev/null +++ b/main-cache-build.php @@ -0,0 +1,311 @@ +$state, + 'message'=>$message, + 'total'=>(int)$total, + 'completed'=>(int)$completed, + 'generated'=>(int)$generated, + 'cached'=>(int)$cached, + 'skipped'=>(int)$skipped, + 'errors'=>(int)$errors, + 'current'=>(string)$current, + )); +} + +function bratonien_tools_cache_builder_size($value) +{ + $parts = explode('x', (string)$value, 2); + if (count($parts) === 1) + { + $size = max(1, (int)$parts[0]); + return array($size, $size); + } + return array(max(1, (int)$parts[0]), max(1, (int)$parts[1])); +} + +function bratonien_tools_cache_builder_custom_params($key) +{ + $tokens = explode('_', (string)$key); + if (!$tokens) + { + return null; + } + + $token = array_shift($tokens); + $crop = 0; + $min_size = null; + if (isset($token[0]) && $token[0] === 's') + { + $size = bratonien_tools_cache_builder_size(substr($token, 1)); + } + elseif (isset($token[0]) && $token[0] === 'e') + { + $crop = 1; + $size = $min_size = bratonien_tools_cache_builder_size(substr($token, 1)); + } + else + { + if (count($tokens) < 2) + { + return null; + } + $size = bratonien_tools_cache_builder_size($token); + $crop_token = array_shift($tokens); + $min_size = bratonien_tools_cache_builder_size(array_shift($tokens)); + $crop = char_to_fraction($crop_token); + } + + $params = new DerivativeParams(new SizingParams($size, $crop, $min_size)); + ImageStdParams::apply_global($params); + return $params; +} + +function bratonien_tools_cache_builder_effective_params_from_path($path) +{ + $filename = pathinfo($path, PATHINFO_FILENAME); + $dash = strrpos($filename, '-'); + if ($dash === false) + { + return null; + } + + $tokens = explode('_', substr($filename, $dash + 1)); + $type_token = array_shift($tokens); + foreach (ImageStdParams::get_defined_type_map() as $type => $params) + { + if (function_exists('derivative_to_url') && derivative_to_url($type) === $type_token) + { + return $params; + } + } + + if (defined('IMG_CUSTOM') && function_exists('derivative_to_url') && derivative_to_url(IMG_CUSTOM) === $type_token) + { + return bratonien_tools_cache_builder_custom_params(implode('_', $tokens)); + } + return null; +} + +function bratonien_tools_cache_builder_metadata(array $image, $source_path) +{ + $rotation = 0; + if (isset($image['rotation'])) + { + $rotation = pwg_image::get_rotation_angle_from_code($image['rotation']); + } + else + { + $rotation = pwg_image::get_rotation_angle($source_path); + } + return array('rotation'=>$rotation, 'coi'=>$image['coi'] ?? null); +} + +function bratonien_tools_cache_builder_generate($source_path, $target_path, $params, array $metadata) +{ + $directory = dirname($target_path); + if (!is_dir($directory) && !mkdir($directory, 0755, true) && !is_dir($directory)) + { + return false; + } + + $image = new pwg_image($source_path); + if (!empty($metadata['rotation'])) + { + $image->rotate($metadata['rotation']); + } + + $original_size = array($image->get_width(), $image->get_height()); + $crop_rect = null; + $scaled_size = null; + $params->sizing->compute($original_size, $metadata['coi'], $crop_rect, $scaled_size); + if ($crop_rect) + { + $image->crop($crop_rect->width(), $crop_rect->height(), $crop_rect->l, $crop_rect->t); + } + if ($scaled_size) + { + $image->resize($scaled_size[0], $scaled_size[1]); + } + if ($params->sharpen) + { + $image->sharpen($params->sharpen); + } + + $image->write($target_path); + $image->destroy(); + @chmod($target_path, 0644); + clearstatcache(true, $target_path); + return is_file($target_path) && is_readable($target_path); +} + +$lock_path = PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'bratonien-tools-main-cache.lock'; +$lock = @fopen($lock_path, 'c'); +if (!$lock || !flock($lock, LOCK_EX | LOCK_NB)) +{ + if (is_resource($lock)) + { + fclose($lock); + } + fwrite(STDERR, "Ein Cache-Aufbau laeuft bereits.\n"); + exit(0); +} + +// Solange die Bratonien-Engine aktiv ist, muss Piwigos natives Wasserzeichen +// fuer alle Derivate neutral bleiben. Der manuelle Cache-Builder erzeugt nur +// Piwigos normalen, unveraenderten Derivatcache. +bratonien_tools_watermark_engine_enabled(); + +$variants = array(); +foreach (ImageStdParams::get_defined_type_map() as $type => $params) +{ + $variants['standard:'.$type] = $params; +} +foreach (ImageStdParams::$custom as $custom_key => $last_used) +{ + $params = bratonien_tools_cache_builder_custom_params($custom_key); + if ($params) + { + $variants['custom:'.$custom_key] = $params; + } +} + +$image_count = (int)pwg_db_fetch_assoc(pwg_query('SELECT COUNT(*) AS cnt FROM '.IMAGES_TABLE))['cnt']; +$total = $image_count * count($variants); +$completed = 0; +$generated = 0; +$cached = 0; +$skipped = 0; +$errors = 0; +$last_write = 0.0; + +bratonien_tools_cache_builder_status('running', 'Piwigo-Bildcache wird aufgebaut.', $total, 0, 0, 0, 0, 0, 'Vorbereitung'); + +$result = pwg_query('SELECT * FROM '.IMAGES_TABLE.' ORDER BY id'); +while ($image_row = pwg_db_fetch_assoc($result)) +{ + $src = new SrcImage($image_row); + $source_path = $src->get_path(); + $image_id = (int)$image_row['id']; + $metadata = null; + + foreach ($variants as $variant_name => $requested_params) + { + $completed++; + $current = 'Bild #'.$image_id.' ยท '.$variant_name; + + try + { + $derivative = new DerivativeImage($requested_params, $src); + $target_path = $derivative->get_path(); + + // Kleine Originale koennen bei Piwigo direkt auf das Original oder auf + // eine bereits kleinere Standardgroesse zurueckfallen. Dann gibt es fuer + // diese Anforderung nichts zusaetzlich zu erzeugen. + if (strpos($target_path, PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR) !== 0) + { + $skipped++; + continue; + } + + $effective_params = bratonien_tools_cache_builder_effective_params_from_path($target_path); + if (!$effective_params) + { + $skipped++; + continue; + } + + if (is_file($target_path) && is_readable($target_path) && @filemtime($target_path) >= (int)$effective_params->last_mod_time) + { + $cached++; + } + else + { + if (!is_file($source_path) || !is_readable($source_path)) + { + $errors++; + } + else + { + if ($metadata === null) + { + $metadata = bratonien_tools_cache_builder_metadata($image_row, $source_path); + } + if (bratonien_tools_cache_builder_generate($source_path, $target_path, $effective_params, $metadata)) + { + $generated++; + } + else + { + $errors++; + } + } + } + } + catch (Throwable $e) + { + $errors++; + fwrite(STDERR, $current.': '.$e->getMessage()."\n"); + } + + $now = microtime(true); + if (($now - $last_write) >= 0.3 || $completed >= $total) + { + bratonien_tools_cache_builder_status('running', 'Piwigo-Bildcache wird aufgebaut.', $total, $completed, $generated, $cached, $skipped, $errors, $current); + $last_write = $now; + } + } +} + +$state = $errors > 0 ? 'error' : 'complete'; +$message = $errors > 0 + ? 'Piwigo-Bildcache wurde aufgebaut, einige Varianten konnten jedoch nicht erzeugt werden.' + : 'Piwigo-Bildcache wurde vollstaendig aufgebaut.'; +bratonien_tools_cache_builder_status($state, $message, $total, $completed, $generated, $cached, $skipped, $errors, ''); + +flock($lock, LOCK_UN); +fclose($lock); +@unlink($lock_path); + +printf("Piwigo-Bildcache: %d/%d, %d neu, %d vorhanden, %d uebersprungen, %d Fehler.\n", $completed, $total, $generated, $cached, $skipped, $errors); +exit($errors > 0 ? 1 : 0);