pics/templates/PhotoPage.php

260 lines
6.9 KiB
PHP

<?php
/*****************************************************************************
* PhotoPage.php
* Contains the photo page template.
*
* Kabuki CMS (C) 2013-2016, Aaron van Geffen
*****************************************************************************/
class PhotoPage extends Template
{
private $activeFilter;
private $photo;
private $metaData;
private $tag;
public function __construct(Image $photo)
{
$this->photo = $photo;
}
public function html_main()
{
$this->photoNav();
$this->photo();
echo '
<div class="row mt-5">
<div class="col-lg-9">
<div id="sub_photo" class="content-box">';
$this->userActions();
echo '
<h2 class="entry-title">', $this->photo->getTitle(), '</h2>';
$this->printTags('Album', 'Album', false);
$this->printTags('Tagged People', 'Person', true);
echo '
</div>
</div>
<div class="col-lg-3">';
$this->photoMeta();
echo '
</div>
</div>
<script type="text/javascript" src="', BASEURL, '/js/photonav.js"></script>';
}
protected function photo()
{
echo '
<a href="', $this->photo->getUrl(), '">
<div id="photo_frame">';
if ($this->photo->isPortrait())
{
echo '
<figure id="photo-figure" class="portrait-figure">',
$this->photo->getInlineImage(null, 960, 'normal-photo'),
$this->photo->getInlineImage(null, 960, 'blur-photo'), '
</figure>';
}
else
{
$className = $this->photo->isPanorama() ? 'panorama-figure' : 'landscape-figure';
echo '
<figure id="photo-figure" class="', $className, '">',
$this->photo->getInlineImage(1280, null, 'normal-photo'),
$this->photo->getInlineImage(1280, null, 'blur-photo'), '
</figure>';
}
echo '
</figure>
</div>
</a>';
}
public function setActiveFilter($filter)
{
$this->activeFilter = $filter;
}
public function setTag(Tag $tag)
{
$this->tag = $tag;
}
private function photoNav()
{
if ($previousUrl = $this->photo->getUrlForPreviousInSet($this->tag, $this->activeFilter))
echo '
<a href="', $previousUrl, '#photo_frame" id="previous_photo"><i class="bi bi-arrow-left"></i></a>';
else
echo '
<span id="previous_photo"><i class="bi bi-arrow-left"></i></span>';
if ($nextUrl = $this->photo->getUrlForNextInSet($this->tag, $this->activeFilter))
echo '
<a href="', $nextUrl, '#photo_frame" id="next_photo"><i class="bi bi-arrow-right"></i></a>';
else
echo '
<span id="next_photo"><i class="bi bi-arrow-right"></i></span>';
}
private function photoMeta()
{
echo '
<ul class="list-group photo_meta">';
foreach ($this->metaData as $header => $body)
{
echo '
<li class="list-group-item">
<h4>', $header, '</h4>
', $body, '
</li>';
}
echo '
</ul>';
}
private function printTags($header, $tagKind, $allowLinkingNewTags)
{
static $nextTagListId = 1;
$tagListId = 'tagList' . ($nextTagListId++);
echo '
<h3>', $header, '</h3>
<ul id="', $tagListId, '" class="tag-list">';
foreach ($this->photo->getTags() as $tag)
{
if ($tag->kind !== $tagKind)
continue;
echo '
<li id="tag-', $tag->id_tag, '">
<div class="input-group">
<a class="input-group-text" href="', $tag->getUrl(), '" title="View all posts tagged ', $tag->tag, '">
', $tag->tag, '
</a>';
if ($tag->kind === 'Person')
{
echo '
<a class="delete-tag btn btn-danger px-1" title="Unlink this tag from this photo" href="#" data-id="', $tag->id_tag, '">
<i class="bi bi-x"></i>
</a>';
}
echo '
</div>
</li>';
}
static $nextNewTagId = 1;
$newTagId = 'newTag' . ($nextNewTagId++);
if ($allowLinkingNewTags)
{
echo '
<li style="position: relative">
<input class="form-control w-auto" type="text" id="', $newTagId, '" placeholder="Type to link a new tag">
</li>';
}
echo '
</ul>';
$this->printNewTagScript($tagKind, $tagListId, $newTagId);
}
private function printNewTagScript($tagKind, $tagListId, $newTagId)
{
echo '
<script type="text/javascript" src="', BASEURL, '/js/ajax.js"></script>
<script type="text/javascript" src="', BASEURL, '/js/autosuggest.js"></script>
<script type="text/javascript">
setTimeout(function() {
const removeTag = function(event) {
event.preventDefault();
const request = new HttpRequest("post", "', $this->photo->getPageUrl(), '",
"id_tag=" + this.dataset["id"] + "&delete", (response) => {
if (!response.success) {
return;
}
const tagNode = document.getElementById("tag-" + this.dataset["id"]);
tagNode.parentNode.removeChild(tagNode);
});
};
let tagRemovalTargets = document.querySelectorAll(".delete-tag");
tagRemovalTargets.forEach(el => el.addEventListener("click", removeTag));
let tag_autosuggest = new TagAutoSuggest({
inputElement: "', $newTagId, '",
listElement: "', $tagListId, '",
baseUrl: "', BASEURL, '",
appendCallback: (item) => {
const request = new HttpRequest("post", "', $this->photo->getPageUrl(), '",
"id_tag=" + item.id_tag, (response) => {
const newListItem = document.createElement("li");
newListItem.id = "tag-" + item.id_tag;
const newInputGroup = document.createElement("div");
newInputGroup.className = "input-group";
newListItem.appendChild(newInputGroup);
const newLink = document.createElement("a");
newLink.className = "input-group-text";
newLink.href = item.url;
newLink.title = "View all posts tagged " + item.label;
newLink.textContent = item.label;
newInputGroup.appendChild(newLink);
const removeLink = document.createElement("a");
removeLink.className = "delete-tag btn btn-danger px-1";
removeLink.dataset["id"] = item.id_tag;
removeLink.href = "#";
removeLink.innerHTML = \'<i class="bi bi-x"></i>\';
removeLink.addEventListener("click", removeTag);
newInputGroup.appendChild(removeLink);
const list = document.getElementById("', $tagListId, '");
list.insertBefore(newListItem, list.querySelector("li:last-child"));
}, this);
}
});
}, 100);
</script>';
}
public function setMetaData(array $metaData)
{
$this->metaData = $metaData;
}
public function userActions()
{
if (!$this->photo->isOwnedBy(Registry::get('user')))
return;
echo '
<div class="float-end">
<a class="btn btn-primary" href="', $this->photo->getEditUrl(), '">
<i class="bi bi-pencil"></i> Edit</a>
<a class="btn btn-danger" href="', $this->photo->getDeleteUrl(), '&',
Session::getSessionTokenKey(), '=', Session::getSessionToken(),
'" onclick="return confirm(\'Are you sure you want to delete this photo?\');"',
'"><i class="bi bi-pencil"></i> Delete</a></a>
</div>';
}
}