<?php /***************************************************************************** * PhotosIndex.php * Contains the project index template. * * Kabuki CMS (C) 2013-2015, Aaron van Geffen *****************************************************************************/ class PhotosIndex extends Template { protected $mosaic; protected $show_edit_buttons; protected $show_headers; protected $show_labels; protected $previous_header = ''; protected $edit_menu_items = []; protected $photo_url_suffix; const PANORAMA_WIDTH = 1256; const PANORAMA_HEIGHT = null; const PORTRAIT_WIDTH = 387; const PORTRAIT_HEIGHT = 628; const LANDSCAPE_WIDTH = 822; const LANDSCAPE_HEIGHT = 628; const DUO_WIDTH = 604; const DUO_HEIGHT = 403; const SINGLE_WIDTH = 618; const SINGLE_HEIGHT = 412; const TILE_WIDTH = 387; const TILE_HEIGHT = 290; public function __construct(PhotoMosaic $mosaic, $show_edit_buttons = false, $show_labels = false, $show_headers = true) { $this->mosaic = $mosaic; $this->show_edit_buttons = $show_edit_buttons; $this->show_headers = $show_headers; $this->show_labels = $show_labels; } public function html_main() { echo ' <div class="container photo-index">'; $i = 0; while ($row = $this->mosaic->getRow()) { [$photos, $what] = $row; $this->header($photos); $this->$what($photos, ($i++) % 2); } echo ' </div> <script type="text/javascript" src="', BASEURL, '/js/albumnav.js"></script>'; } protected function header($photos) { if (!$this->show_headers) return; $date = $photos[0]->getDateCaptured(); if (!$date) return; $header = $date->format('F Y'); if ($header === $this->previous_header) return; $name = str_replace(' ', '', strtolower($header)); echo ' <h4 class="tiled-header" id="', $name, '"> <a href="#', $name, '">', $header, '</a> </h4>'; $this->previous_header = $header; } protected function editMenu(Image $image) { if (empty($this->edit_menu_items)) return; echo ' <div class="edit dropdown"> <button class="btn btn-primary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> </button> <ul class="dropdown-menu">'; foreach ($this->edit_menu_items as $item) { echo ' <li><a class="dropdown-item" href="', $item['uri']($image), '"', isset($item['onclick']) ? ' onclick="' . $item['onclick'] . '"' : '', '>', $item['label'], '</a></li>'; } echo ' </ul> </div>'; } protected function photo(Image $image, $className, $width, $height, $crop = true, $fit = true) { // Prefer thumbnail aspect ratio if available, otherwise use image aspect ratio. $aspectRatio = isset($width, $height) ? $width / $height : $image->ratio(); echo ' <div class="polaroid ', $className, '" style="aspect-ratio: ', $aspectRatio, '">'; if ($this->show_edit_buttons && $image->canBeEditedBy(Registry::get('user'))) $this->editMenu($image); echo ' <a href="', $image->getPageUrl(), $this->photo_url_suffix, '#photo_frame">'; foreach (['normal-photo', 'blur-photo'] as $className) { echo ' <img src="', $image->getThumbnailUrl($width, $height, $crop, $fit), '"'; // Can we offer double-density thumbs? if ($image->width() >= $width * 2 && $image->height() >= $height * 2) echo ' srcset="', $image->getThumbnailUrl($width * 2, $height * 2, $crop, $fit), ' 2x"'; else echo ' srcset="', $image->getThumbnailUrl($image->width(), $image->height(), true), ' 2x"'; echo ' alt="" title="', $image->getTitle(), '" class="', $className, '" style="aspect-ratio: ', $aspectRatio, '">'; } if ($this->show_labels) echo ' <h4>', $image->getTitle(), '</h4>'; echo ' </a> </div>'; } protected function panorama(array $photos, $altLayout) { foreach ($photos as $image) { echo ' <div class="row mb-5 tile-panorama"> <div class="col">'; $this->photo($image, 'panorama', static::PANORAMA_WIDTH, static::PANORAMA_HEIGHT, false, false); echo ' </div> </div>'; } } protected function sixLandscapes(array $photos, $altLayout) { $chunks = array_chunk($photos, 3); $this->sideLandscape($chunks[0], $altLayout); $this->threeLandscapes($chunks[1], $altLayout); } protected function sidePortrait(array $photos, $altLayout) { $image = array_shift($photos); echo ' <div class="row g-5 mb-5 tile-feat-portrait', $altLayout ? ' flex-row-reverse' : '', '"> <div class="col-md-4">'; $this->photo($image, 'portrait', static::PORTRAIT_WIDTH, static::PORTRAIT_HEIGHT, 'centre'); echo ' </div> <div class="col-md-8"> <div class="row g-5">'; foreach ($photos as $image) { echo ' <div class="col-md-6">'; $this->photo($image, 'landscape', static::TILE_WIDTH, static::TILE_HEIGHT, 'top'); echo ' </div>'; } echo ' </div> </div> </div>'; } protected function sideLandscape(array $photos, $altLayout) { $image = array_shift($photos); echo ' <div class="row g-5 mb-5 tile-feat-landscape', $altLayout ? ' flex-row-reverse' : '', '"> <div class="col-md-8">'; $this->photo($image, 'landscape', static::LANDSCAPE_WIDTH, static::LANDSCAPE_HEIGHT, 'top'); echo ' </div> <div class="col-md-4"> <div class="row g-5">'; foreach ($photos as $image) { echo ' <div>'; $this->photo($image, 'landscape', static::TILE_WIDTH, static::TILE_HEIGHT, 'top'); echo ' </div>'; } echo ' </div> </div> </div>'; } protected function threeLandscapes(array $photos, $altLayout) { echo ' <div class="row g-5 mb-5 tile-row-landscapes">'; foreach ($photos as $image) { echo ' <div class="col-md-4">'; $this->photo($image, 'landscape', static::TILE_WIDTH, static::TILE_HEIGHT, true); echo ' </div>'; } echo ' </div>'; } protected function threePortraits(array $photos, $altLayout) { echo ' <div class="row g-5 mb-5 tile-row-portraits">'; foreach ($photos as $image) { echo ' <div class="col-md-4">'; $this->photo($image, 'portrait', static::PORTRAIT_WIDTH, static::PORTRAIT_HEIGHT, true); echo ' </div>'; } echo ' </div>'; } protected function dualLandscapes(array $photos, $altLayout) { echo ' <div class="row g-5 mb-5 tile-duo">'; foreach ($photos as $image) { echo ' <div class="col-md-6">'; $this->photo($image, 'duo', static::DUO_WIDTH, static::DUO_HEIGHT, true); echo ' </div>'; } echo ' </div>'; } protected function dualMixed(array $photos, $altLayout) { echo ' <div class="row g-5 mb-5 tile-feat-landscape', $altLayout ? ' flex-row-reverse' : '', '"> <div class="col-md-8">'; $image = array_shift($photos); $this->photo($image, 'landscape', static::LANDSCAPE_WIDTH, static::LANDSCAPE_HEIGHT, 'top'); echo ' </div> <div class="col-md-4">'; $image = array_shift($photos); $this->photo($image, 'portrait', static::PORTRAIT_WIDTH, static::PORTRAIT_HEIGHT, true); echo ' </div> </div> </div>'; } protected function dualPortraits(array $photos, $altLayout) { // Recycle the row layout so portraits don't appear too large $this->threePortraits($photos, $altLayout); } protected function singleLandscape(array $photos, $altLayout) { echo ' <div class="row g-5 mb-5 tile-single"> <div class="col-md-6">'; $image = array_shift($photos); $this->photo($image, 'single', static::SINGLE_WIDTH, static::SINGLE_HEIGHT, 'top'); echo ' </div> </div>'; } protected function singlePortrait(array $photos, $altLayout) { // Recycle the row layout so portraits don't appear too large $this->threePortraits($photos, $altLayout); } public function setEditMenuItems(array $items) { $this->edit_menu_items = $items; } public function setUrlSuffix($suffix) { $this->photo_url_suffix = $suffix; } }