2016-09-03 21:32:55 +02:00
|
|
|
<?php
|
|
|
|
/*****************************************************************************
|
|
|
|
* PhotoPage.php
|
|
|
|
* Contains the photo page template.
|
|
|
|
*
|
|
|
|
* Kabuki CMS (C) 2013-2016, Aaron van Geffen
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2023-03-11 13:37:59 +01:00
|
|
|
class PhotoPage extends Template
|
2016-09-03 21:32:55 +02:00
|
|
|
{
|
2018-07-08 10:19:37 +02:00
|
|
|
protected $photo;
|
2016-09-03 21:32:55 +02:00
|
|
|
private $exif;
|
2016-09-04 16:00:39 +02:00
|
|
|
private $previous_photo_url = '';
|
|
|
|
private $next_photo_url = '';
|
2016-09-03 21:32:55 +02:00
|
|
|
|
|
|
|
public function __construct(Image $photo)
|
|
|
|
{
|
|
|
|
$this->photo = $photo;
|
|
|
|
}
|
|
|
|
|
2016-09-04 16:00:39 +02:00
|
|
|
public function setPreviousPhotoUrl($url)
|
|
|
|
{
|
|
|
|
$this->previous_photo_url = $url;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setNextPhotoUrl($url)
|
|
|
|
{
|
|
|
|
$this->next_photo_url = $url;
|
|
|
|
}
|
|
|
|
|
2023-03-11 13:37:59 +01:00
|
|
|
public function html_main()
|
2016-09-03 21:32:55 +02:00
|
|
|
{
|
|
|
|
$this->photoNav();
|
|
|
|
$this->photo();
|
|
|
|
|
|
|
|
echo '
|
2023-03-11 13:57:57 +01:00
|
|
|
<div class="row mt-5">
|
2023-03-11 22:04:02 +01:00
|
|
|
<div class="col-lg-8">
|
2023-03-11 13:57:57 +01:00
|
|
|
<div id="sub_photo" class="content-box">
|
|
|
|
<h2 class="entry-title">', $this->photo->getTitle(), '</h2>';
|
2016-09-03 21:32:55 +02:00
|
|
|
|
2024-01-11 20:00:29 +01:00
|
|
|
$this->printTags('Album', 'Album', false);
|
|
|
|
$this->printTags('Tagged People', 'Person', true);
|
2016-09-03 21:32:55 +02:00
|
|
|
|
|
|
|
echo '
|
2023-03-11 13:57:57 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
2023-03-11 22:04:02 +01:00
|
|
|
<div class="col-lg-4">';
|
2016-09-03 21:32:55 +02:00
|
|
|
|
|
|
|
$this->photoMeta();
|
2023-11-11 15:29:32 +01:00
|
|
|
$this->userActions();
|
2018-07-02 20:32:59 +02:00
|
|
|
|
2016-09-03 21:32:55 +02:00
|
|
|
echo '
|
2023-03-11 13:57:57 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
2016-09-03 21:32:55 +02:00
|
|
|
<script type="text/javascript" src="', BASEURL, '/js/photonav.js"></script>';
|
|
|
|
}
|
|
|
|
|
2018-07-08 10:19:37 +02:00
|
|
|
protected function photo()
|
2016-09-03 21:32:55 +02:00
|
|
|
{
|
|
|
|
echo '
|
2023-11-10 22:50:51 +01:00
|
|
|
<a href="', $this->photo->getUrl(), '">
|
|
|
|
<div id="photo_frame">';
|
2016-09-03 21:32:55 +02:00
|
|
|
|
|
|
|
if ($this->photo->isPortrait())
|
2023-11-10 22:50:51 +01:00
|
|
|
{
|
|
|
|
echo '
|
2023-11-10 23:22:09 +01:00
|
|
|
<figure id="photo-figure" class="portrait-figure">',
|
2023-11-10 22:50:51 +01:00
|
|
|
$this->photo->getInlineImage(null, 960, 'normal-photo'),
|
|
|
|
$this->photo->getInlineImage(null, 960, 'blur-photo'), '
|
|
|
|
</figure>';
|
|
|
|
}
|
2016-09-03 21:32:55 +02:00
|
|
|
else
|
2023-11-10 22:50:51 +01:00
|
|
|
{
|
|
|
|
$className = $this->photo->isPanorama() ? 'panorama-figure' : 'landscape-figure';
|
|
|
|
echo '
|
2023-11-10 23:22:09 +01:00
|
|
|
<figure id="photo-figure" class="', $className, '">',
|
2023-11-10 22:50:51 +01:00
|
|
|
$this->photo->getInlineImage(1280, null, 'normal-photo'),
|
|
|
|
$this->photo->getInlineImage(1280, null, 'blur-photo'), '
|
|
|
|
</figure>';
|
|
|
|
}
|
2016-09-03 21:32:55 +02:00
|
|
|
|
|
|
|
echo '
|
2023-11-10 22:50:51 +01:00
|
|
|
</figure>
|
|
|
|
</div>
|
|
|
|
</a>';
|
2016-09-03 21:32:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private function photoNav()
|
|
|
|
{
|
2016-09-04 16:00:39 +02:00
|
|
|
if ($this->previous_photo_url)
|
2016-09-03 21:32:55 +02:00
|
|
|
echo '
|
2023-03-12 12:55:32 +01:00
|
|
|
<a href="', $this->previous_photo_url, '#photo_frame" id="previous_photo"><i class="bi bi-arrow-left"></i></a>';
|
2016-09-03 21:32:55 +02:00
|
|
|
else
|
|
|
|
echo '
|
2023-03-11 14:13:29 +01:00
|
|
|
<span id="previous_photo"><i class="bi bi-arrow-left"></i></span>';
|
2016-09-03 21:32:55 +02:00
|
|
|
|
2016-09-04 16:00:39 +02:00
|
|
|
if ($this->next_photo_url)
|
2016-09-03 21:32:55 +02:00
|
|
|
echo '
|
2023-03-12 12:55:32 +01:00
|
|
|
<a href="', $this->next_photo_url, '#photo_frame" id="next_photo"><i class="bi bi-arrow-right"></i></a>';
|
2016-09-03 21:32:55 +02:00
|
|
|
else
|
|
|
|
echo '
|
2023-03-11 14:13:29 +01:00
|
|
|
<span id="next_photo"><i class="bi bi-arrow-right"></i></span>';
|
2016-09-03 21:32:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private function photoMeta()
|
|
|
|
{
|
|
|
|
echo '
|
2023-03-11 13:57:57 +01:00
|
|
|
<div id="photo_exif_box" class="content-box clearfix">
|
2016-09-03 21:32:55 +02:00
|
|
|
<h3>EXIF</h3>
|
|
|
|
<dl class="photo_meta">';
|
|
|
|
|
|
|
|
if (!empty($this->exif->created_timestamp))
|
|
|
|
echo '
|
|
|
|
<dt>Date Taken</dt>
|
|
|
|
<dd>', date("j M Y, H:i:s", $this->exif->created_timestamp), '</dd>';
|
|
|
|
|
2016-09-04 21:34:08 +02:00
|
|
|
echo '
|
|
|
|
<dt>Uploaded by</dt>
|
|
|
|
<dd>', $this->photo->getAuthor()->getfullName(), '</dd>';
|
|
|
|
|
2016-09-03 21:32:55 +02:00
|
|
|
if (!empty($this->exif->camera))
|
|
|
|
echo '
|
2016-09-04 21:34:08 +02:00
|
|
|
<dt>Camera Model</dt>
|
2016-09-03 21:32:55 +02:00
|
|
|
<dd>', $this->exif->camera, '</dd>';
|
|
|
|
|
|
|
|
if (!empty($this->exif->shutter_speed))
|
|
|
|
echo '
|
|
|
|
<dt>Shutter Speed</dt>
|
|
|
|
<dd>', $this->exif->shutterSpeedFraction(), '</dd>';
|
|
|
|
|
|
|
|
if (!empty($this->exif->aperture))
|
|
|
|
echo '
|
|
|
|
<dt>Aperture</dt>
|
|
|
|
<dd>f/', number_format($this->exif->aperture, 1), '</dd>';
|
|
|
|
|
|
|
|
if (!empty($this->exif->focal_length))
|
|
|
|
echo '
|
|
|
|
<dt>Focal Length</dt>
|
|
|
|
<dd>', $this->exif->focal_length, ' mm</dd>';
|
|
|
|
|
|
|
|
if (!empty($this->exif->iso))
|
|
|
|
echo '
|
|
|
|
<dt>ISO Speed</dt>
|
|
|
|
<dd>', $this->exif->iso, '</dd>';
|
|
|
|
|
2022-12-25 13:44:19 +01:00
|
|
|
if (!empty($this->exif->software))
|
|
|
|
echo '
|
|
|
|
<dt>Software</dt>
|
|
|
|
<dd>', $this->exif->software, '</dd>';
|
|
|
|
|
2016-09-03 21:32:55 +02:00
|
|
|
echo '
|
|
|
|
</dl>
|
|
|
|
</div>';
|
|
|
|
}
|
|
|
|
|
2024-01-11 20:00:29 +01:00
|
|
|
private function printTags($header, $tagKind, $allowLinkingNewTags)
|
2016-09-03 21:32:55 +02:00
|
|
|
{
|
|
|
|
echo '
|
2024-01-11 20:00:29 +01:00
|
|
|
<h3>', $header, '</h3>
|
|
|
|
<ul id="tag_list" class="d-flex">';
|
2016-09-03 21:32:55 +02:00
|
|
|
|
|
|
|
foreach ($this->photo->getTags() as $tag)
|
|
|
|
{
|
2024-01-11 20:00:29 +01:00
|
|
|
if ($tag->kind !== $tagKind)
|
|
|
|
continue;
|
|
|
|
|
2016-09-03 21:32:55 +02:00
|
|
|
echo '
|
2019-03-09 13:48:18 +01:00
|
|
|
<li id="tag-', $tag->id_tag, '">
|
2024-01-11 20:00:29 +01:00
|
|
|
<a href="', $tag->getUrl(), '" title="View all posts tagged ', $tag->tag, '">
|
|
|
|
<div class="input-group">
|
|
|
|
<span class="input-group-text">', $tag->tag, '</span>';
|
2019-03-09 13:48:18 +01:00
|
|
|
|
|
|
|
if ($tag->kind === 'Person')
|
2024-01-11 20:00:29 +01:00
|
|
|
{
|
2019-03-09 13:48:18 +01:00
|
|
|
echo '
|
2024-01-11 20:00:29 +01:00
|
|
|
<a class="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>';
|
|
|
|
}
|
2019-03-09 13:48:18 +01:00
|
|
|
|
|
|
|
echo '
|
2024-01-11 20:00:29 +01:00
|
|
|
</div>
|
|
|
|
</a>
|
2016-09-03 21:32:55 +02:00
|
|
|
</li>';
|
|
|
|
}
|
|
|
|
|
2024-01-11 20:00:29 +01:00
|
|
|
if ($allowLinkingNewTags)
|
|
|
|
$this->linkNewTags();
|
|
|
|
|
2016-09-03 21:32:55 +02:00
|
|
|
echo '
|
|
|
|
</ul>';
|
|
|
|
}
|
|
|
|
|
2016-09-04 11:23:08 +02:00
|
|
|
private function linkNewTags()
|
|
|
|
{
|
|
|
|
echo '
|
2024-01-11 20:00:29 +01:00
|
|
|
<li style="position: relative">
|
|
|
|
<input class="form-control w-auto" type="text" id="new_tag" placeholder="Type to link a new tag">
|
|
|
|
</li>
|
2016-09-04 11:23:08 +02:00
|
|
|
<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() {
|
2019-03-09 13:48:18 +01:00
|
|
|
var removeTag = function(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
var that = this;
|
|
|
|
var request = new HttpRequest("post", "', $this->photo->getPageUrl(), '",
|
|
|
|
"id_tag=" + this.dataset["id"] + "&delete", function(response) {
|
|
|
|
if (!response.success) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var tagNode = document.getElementById("tag-" + that.dataset["id"]);
|
|
|
|
tagNode.parentNode.removeChild(tagNode);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
var tagRemovalTargets = document.getElementsByClassName("delete-tag");
|
2020-02-22 17:40:34 +01:00
|
|
|
for (var i = 0; i < tagRemovalTargets.length; i++) {
|
|
|
|
tagRemovalTargets[i].addEventListener("click", removeTag);
|
|
|
|
}
|
2019-03-09 13:48:18 +01:00
|
|
|
|
2016-09-04 11:23:08 +02:00
|
|
|
var tag_autosuggest = new TagAutoSuggest({
|
|
|
|
inputElement: "new_tag",
|
|
|
|
listElement: "tag_list",
|
|
|
|
baseUrl: "', BASEURL, '",
|
|
|
|
appendCallback: function(item) {
|
2016-11-13 14:42:53 +01:00
|
|
|
var request = new HttpRequest("post", "', $this->photo->getPageUrl(), '",
|
|
|
|
"id_tag=" + item.id_tag, function(response) {
|
2019-03-09 13:22:32 +01:00
|
|
|
var newLink = document.createElement("a");
|
|
|
|
newLink.href = item.url;
|
|
|
|
|
2016-11-13 14:42:53 +01:00
|
|
|
var newLabel = document.createTextNode(item.label);
|
2019-03-09 13:22:32 +01:00
|
|
|
newLink.appendChild(newLabel);
|
|
|
|
|
2019-03-09 13:48:18 +01:00
|
|
|
var removeLink = document.createElement("a");
|
|
|
|
removeLink.className = "delete-tag";
|
|
|
|
removeLink.dataset["id"] = item.id_tag;
|
|
|
|
removeLink.href = "#";
|
|
|
|
removeLink.addEventListener("click", removeTag);
|
|
|
|
|
|
|
|
var crossmark = document.createTextNode("❌");
|
|
|
|
removeLink.appendChild(crossmark);
|
|
|
|
|
2019-03-09 13:22:32 +01:00
|
|
|
var newNode = document.createElement("li");
|
2019-03-09 13:48:18 +01:00
|
|
|
newNode.id = "tag-" + item.id_tag;
|
2019-03-09 13:22:32 +01:00
|
|
|
newNode.appendChild(newLink);
|
2019-03-09 13:48:18 +01:00
|
|
|
newNode.appendChild(removeLink);
|
2016-11-13 14:42:53 +01:00
|
|
|
|
|
|
|
var list = document.getElementById("tag_list");
|
|
|
|
list.appendChild(newNode);
|
|
|
|
}, this);
|
2016-09-04 11:23:08 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}, 100);
|
|
|
|
</script>';
|
|
|
|
}
|
|
|
|
|
2016-09-03 21:32:55 +02:00
|
|
|
public function setExif(EXIF $exif)
|
|
|
|
{
|
|
|
|
$this->exif = $exif;
|
|
|
|
}
|
2018-07-02 20:32:59 +02:00
|
|
|
|
2023-11-11 15:29:32 +01:00
|
|
|
public function userActions()
|
2018-07-02 20:32:59 +02:00
|
|
|
{
|
2023-11-11 15:29:32 +01:00
|
|
|
if (!$this->photo->isOwnedBy(Registry::get('user')))
|
|
|
|
return;
|
|
|
|
|
2018-07-02 20:32:59 +02:00
|
|
|
echo '
|
2023-03-11 13:57:57 +01:00
|
|
|
<div id="user_actions_box" class="content-box">
|
2018-07-02 20:32:59 +02:00
|
|
|
<h3>Actions</h3>
|
2023-11-11 15:29:32 +01:00
|
|
|
<a class="btn btn-primary" href="', $this->photo->getEditUrl(), '">Edit photo</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?\');"',
|
|
|
|
'">Delete photo</a>
|
2018-07-02 20:32:59 +02:00
|
|
|
</div>';
|
|
|
|
}
|
2016-09-03 21:32:55 +02:00
|
|
|
}
|