<?php /* Copyright (C) 2021 Alexander Rosenberg * This file is AGPL v3. See LICENSE file for more information */ class Album { private const PATH_PREFIX = 'albums'; private const THUMB_PREFIX = 'thumbnails'; private const NUMBER_REGEX = '/^[0-9]+(\\.[0-9]+)?$/'; private $name; private $title; private $thumbnail; private $images; private $metadata; function __construct($name) { $this->name = $name; if (!file_exists($this->get_path())) { $this->invalidate(); } else { $this->read(); } } private function read() { $content = file_get_contents($this->get_path() . '/data.json'); if ($content == null) { $this->invalidate(); return; } $root = json_decode($content); if ($root == null) { $this->invalidate(); return; } $this->title = $root->{'title'}; $this->thumbnail = $root->{'thumbnail'}; $this->images = $root->{'images'}; $this->metadata = $root->{'metadata'}; } private function invalidate() { $this->title = null; $this->thumbnail = null; $this->images = null; } function is_valid() { if ($this->title == null || $this->thumbnail == null || $this->images == null) { return false; } if (!is_string($this->title) || !is_string($this->thumbnail) || !is_array($this->images)) { return false; } foreach ($this->images as $image) { if (!is_string($image)) { return false; } } unset($image); return true; } function get_name() { return $this->name; } function get_path() { return $this::PATH_PREFIX . '/' . $this->name; } function get_title() { return $this->title; } function get_thumbnail() { return $this->get_path() . '/' . $this->thumbnail; } function get_small_thumbnail() { return $this::THUMB_PREFIX . '/small/' . $this->get_name() . '/' . $this->thumbnail; } function get_images() { return $this->images; } function get_html() { $out = '<a href="view.php?album=' . urlencode($this->get_name()) . '" class="album-wrapper">'; if (file_exists($this->get_thumbnail())) { $type = mime_content_type($this->get_thumbnail()); } $category = explode('/', $type)[0]; if (!file_exists($this->get_thumbnail())) { $out .= '<img class="album-thumbnail" src="missing-image-icon.svg"/>'; } else if ($category == 'audio') { $out .= '<img class="album-thumbnail" src="music-icon.svg"/>'; } else { $out .= '<img class="album-thumbnail" src="' . htmlspecialchars($this->get_small_thumbnail(), ENT_QUOTES | ENT_HTML5) . '"/>'; } $album_len = count($this->get_images()); if ($album_len == 1) { $out .= '<div class="album-length">' . $album_len . ' Image</div>'; } else { $out .= '<div class="album-length">' . $album_len . ' Images</div>'; } $out .= '<div class="album-title">' . htmlspecialchars($this->get_title(), ENT_QUOTES | ENT_HTML5) . '</div>'; $out .= '</a>'; return $out; } function get_metadata($image) { if ($image == null || !in_array($image, $this->images)) { return null; } if ($this->metadata == null || !property_exists($this->metadata, $image)) { return [ 'description' => '', 'date' => '', 'time' => '', 'latitude' => '', 'longitude' => '' ]; } $description = $this->metadata->{$image}->{'description'}; $date = $this->metadata->{$image}->{'date'}; $time = $this->metadata->{$image}->{'time'}; $lat= $this->metadata->{$image}->{'latitude'}; $lon = $this->metadata->{$image}->{'longitude'}; if (preg_match($this::NUMBER_REGEX, $lat) === false || preg_match($this::NUMBER_REGEX, $lon) === false) { $lat = null; $lon = null; } return [ 'description' => $description == null ? '' : htmlspecialchars($description, ENT_QUOTES | ENT_HTML5), 'date' => $date == null ? '' : htmlspecialchars($date, ENT_QUOTES | ENT_HTML5), 'time' => $time == null ? '' : htmlspecialchars($time, ENT_QUOTES | ENT_HTML5), 'latitude' => $lat == null ? '' : htmlspecialchars($lat, ENT_QUOTES | ENT_HTML5), 'longitude' => $lon == null ? '' : htmlspecialchars($lon, ENT_QUOTES | ENT_HTML5) ]; } function get_image_index($image) { for ($i = 0; $i < count($this->images); ++$i) { if ($image == $this->images[$i]) { return $i; } } return -1; } function get_image_entry($image) { if ($image == null || !in_array($image, $this->images)) { return null; } $index = $this->get_image_index($image); $rpath = $this->get_path() . '/' . $image; $path = htmlspecialchars($rpath); if (file_exists($rpath)) { $file_size = number_format(filesize($path)); $rtype = mime_content_type($path); } else { $file_size = 0; $rtype = "Unknown"; } $type = htmlspecialchars($rtype); $category = explode('/', $type)[0]; $name = htmlspecialchars(basename($path)); $metadata = $this->get_metadata($image); $entry = '<div class="sidebar-image-wrapper" onclick="set_main_image(' . strval($index) . ')" ' . "data-size='$file_size' data-type='$type' data-name='$name' data-desc='" . $metadata['description'] . "' data-date='" . $metadata['date'] . "' data-time='" . $metadata['time'] . "' " . "data-lat='" . $metadata['latitude'] . "' data-lon='" . $metadata['longitude'] . "'>"; if (!file_exists($rpath)) { $entry .= '<img style="display: none" class="sidebar-image" data-src="missing-image-icon.svg"/>'; } else if ($category == 'video') { $thumb_name = htmlspecialchars($this->get_name() . '/' . $image); $entry .= '<img style="display: none" class="sidebar-image" '; $entry .= 'data-src="' . $thumb_name . '" '; $entry .= 'data-type="' . $type . '" '; $entry .= 'data-videopath="' . $path . '"/>'; } else if ($category == 'audio') { $entry .= '<img class="sidebar-image" src="music-icon.svg" '; $entry .= 'data-audiotype="' . $type . '" '; $entry .= 'data-audiopath="' . $path . '"/>'; } else { list($width, $height) = getimagesize($rpath); $path = htmlspecialchars($this->get_name() . '/' . $image); $entry .= '<img style="display: none" class="sidebar-image" data-src="' . $path . '" ' . 'data-size="' . $width . 'x' . $height . '" />'; } $entry .= '</div>'; return $entry; } } ?>