776 lines
18 KiB
PHP
776 lines
18 KiB
PHP
<?php
|
|
/*****************************************************************************
|
|
* Asset.php
|
|
* Contains key class Asset.
|
|
*
|
|
* Kabuki CMS (C) 2013-2015, Aaron van Geffen
|
|
*****************************************************************************/
|
|
|
|
class Asset
|
|
{
|
|
public $id_asset;
|
|
public $id_user_uploaded;
|
|
public $subdir;
|
|
public $filename;
|
|
public $title;
|
|
public $slug;
|
|
public $mimetype;
|
|
public $image_width;
|
|
public $image_height;
|
|
public $date_captured;
|
|
public $priority;
|
|
|
|
protected $meta;
|
|
protected $tags;
|
|
protected $thumbnails;
|
|
|
|
protected function __construct(array $data)
|
|
{
|
|
foreach ($data as $attribute => $value)
|
|
{
|
|
if (property_exists($this, $attribute))
|
|
$this->$attribute = $value;
|
|
}
|
|
|
|
if (!empty($data['date_captured']) && $data['date_captured'] !== 'NULL')
|
|
$this->date_captured = new DateTime($data['date_captured']);
|
|
}
|
|
|
|
public static function cleanSlug($slug)
|
|
{
|
|
// Only alphanumerical chars, underscores and forward slashes are allowed
|
|
if (!preg_match_all('~([A-z0-9\/_]+)~', $slug, $allowedTokens, PREG_PATTERN_ORDER))
|
|
throw new UnexpectedValueException('Slug does not make sense.');
|
|
|
|
// Join valid substrings together with hyphens
|
|
return implode('-', $allowedTokens[1]);
|
|
}
|
|
|
|
public static function fromId($id_asset, $return_format = 'object')
|
|
{
|
|
$row = Registry::get('db')->queryAssoc('
|
|
SELECT *
|
|
FROM assets
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $id_asset,
|
|
]);
|
|
|
|
return empty($row) ? false : self::byRow($row, $return_format);
|
|
}
|
|
|
|
public static function fromSlug($slug, $return_format = 'object')
|
|
{
|
|
$row = Registry::get('db')->queryAssoc('
|
|
SELECT *
|
|
FROM assets
|
|
WHERE slug = {string:slug}',
|
|
[
|
|
'slug' => $slug,
|
|
]);
|
|
|
|
return empty($row) ? false : self::byRow($row, $return_format);
|
|
}
|
|
|
|
public static function byRow(array $row, $return_format = 'object')
|
|
{
|
|
$db = Registry::get('db');
|
|
|
|
// Supplement with metadata.
|
|
$row['meta'] = $db->queryPair('
|
|
SELECT variable, value
|
|
FROM assets_meta
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $row['id_asset'],
|
|
]);
|
|
|
|
// And thumbnails.
|
|
$row['thumbnails'] = $db->queryPair('
|
|
SELECT
|
|
CONCAT(
|
|
width,
|
|
{string:x},
|
|
height,
|
|
IF(mode != {string:empty}, CONCAT({string:_}, mode), {string:empty})
|
|
) AS selector, filename
|
|
FROM assets_thumbs
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $row['id_asset'],
|
|
'empty' => '',
|
|
'x' => 'x',
|
|
'_' => '_',
|
|
]);
|
|
|
|
return $return_format == 'object' ? new Asset($row) : $row;
|
|
}
|
|
|
|
public static function fromIds(array $id_assets, $return_format = 'array')
|
|
{
|
|
if (empty($id_assets))
|
|
return [];
|
|
|
|
$db = Registry::get('db');
|
|
|
|
$res = $db->query('
|
|
SELECT *
|
|
FROM assets
|
|
WHERE id_asset IN ({array_int:id_assets})
|
|
ORDER BY id_asset',
|
|
[
|
|
'id_assets' => $id_assets,
|
|
]);
|
|
|
|
$assets = [];
|
|
while ($asset = $db->fetch_assoc($res))
|
|
{
|
|
$assets[$asset['id_asset']] = $asset;
|
|
$assets[$asset['id_asset']]['meta'] = [];
|
|
$assets[$asset['id_asset']]['thumbnails'] = [];
|
|
}
|
|
|
|
$metas = $db->queryRows('
|
|
SELECT id_asset, variable, value
|
|
FROM assets_meta
|
|
WHERE id_asset IN ({array_int:id_assets})
|
|
ORDER BY id_asset',
|
|
[
|
|
'id_assets' => $id_assets,
|
|
]);
|
|
|
|
foreach ($metas as $meta)
|
|
$assets[$meta[0]]['meta'][$meta[1]] = $meta[2];
|
|
|
|
$thumbnails = $db->queryRows('
|
|
SELECT id_asset,
|
|
CONCAT(
|
|
width,
|
|
{string:x},
|
|
height,
|
|
IF(mode != {string:empty}, CONCAT({string:_}, mode), {string:empty})
|
|
) AS selector, filename
|
|
FROM assets_thumbs
|
|
WHERE id_asset IN ({array_int:id_assets})
|
|
ORDER BY id_asset',
|
|
[
|
|
'id_assets' => $id_assets,
|
|
'empty' => '',
|
|
'x' => 'x',
|
|
'_' => '_',
|
|
]);
|
|
|
|
foreach ($thumbnails as $thumb)
|
|
$assets[$thumb[0]]['thumbnails'][$thumb[1]] = $thumb[2];
|
|
|
|
if ($return_format == 'array')
|
|
return $assets;
|
|
else
|
|
{
|
|
$objects = [];
|
|
foreach ($assets as $id => $asset)
|
|
$objects[$id] = new Asset($asset);
|
|
return $objects;
|
|
}
|
|
}
|
|
|
|
public static function createNew(array $data, $return_format = 'object')
|
|
{
|
|
// Extract the data array.
|
|
extract($data);
|
|
|
|
// No filename? Abort!
|
|
if (!isset($filename_to_copy) || !is_file($filename_to_copy))
|
|
return false;
|
|
|
|
// No subdir? Use YYYY/MM
|
|
if (!isset($preferred_subdir))
|
|
$preferred_subdir = date('Y') . '/' . date('m');
|
|
|
|
// Does this dir exist yet? If not, create it.
|
|
if (!is_dir(ASSETSDIR . '/' . $preferred_subdir))
|
|
mkdir(ASSETSDIR . '/' . $preferred_subdir, 0755, true);
|
|
|
|
// Construct the destination filename. Make sure we don't accidentally overwrite anything.
|
|
if (!isset($preferred_filename))
|
|
$preferred_filename = basename($filename_to_copy);
|
|
|
|
$new_filename = $preferred_filename;
|
|
$destination = ASSETSDIR . '/' . $preferred_subdir . '/' . $preferred_filename;
|
|
for ($i = 1; file_exists($destination); $i++)
|
|
{
|
|
$suffix = $i;
|
|
$filename = pathinfo($preferred_filename, PATHINFO_FILENAME) . ' (' . $suffix . ')';
|
|
$extension = pathinfo($preferred_filename, PATHINFO_EXTENSION);
|
|
$new_filename = $filename . '.' . $extension;
|
|
$destination = dirname($destination) . '/' . $new_filename;
|
|
}
|
|
|
|
// Can we write to the target directory? Then copy the file.
|
|
if (is_writable(ASSETSDIR . '/' . $preferred_subdir))
|
|
copy($filename_to_copy, $destination);
|
|
else
|
|
return false;
|
|
|
|
// Figure out the mime type for the file.
|
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
|
$mimetype = finfo_file($finfo, $destination);
|
|
finfo_close($finfo);
|
|
|
|
// We're going to need the base name a few times...
|
|
$basename = pathinfo($new_filename, PATHINFO_FILENAME);
|
|
|
|
// Do we have a title yet? Otherwise, use the filename.
|
|
$title = $data['title'] ?? $basename;
|
|
|
|
// Same with the slug.
|
|
$slug = $data['slug'] ?? self::cleanSlug(sprintf('%s/%s', $preferred_subdir, $basename));
|
|
|
|
// Detected an image?
|
|
if (substr($mimetype, 0, 5) == 'image')
|
|
{
|
|
$image = new Imagick($destination);
|
|
$d = $image->getImageGeometry();
|
|
|
|
// Get image dimensions, bearing orientation in mind.
|
|
switch ($image->getImageOrientation())
|
|
{
|
|
case Imagick::ORIENTATION_LEFTBOTTOM:
|
|
case Imagick::ORIENTATION_RIGHTTOP:
|
|
$image_width = $d['height'];
|
|
$image_height = $d['width'];
|
|
break;
|
|
|
|
default:
|
|
$image_width = $d['width'];
|
|
$image_height = $d['height'];
|
|
}
|
|
|
|
unset($image);
|
|
|
|
$exif = EXIF::fromFile($destination);
|
|
$date_captured = $exif->created_timestamp > 0 ? $exif->created_timestamp : time();
|
|
}
|
|
|
|
$db = Registry::get('db');
|
|
$res = $db->query('
|
|
INSERT INTO assets
|
|
(id_user_uploaded, subdir, filename, title, slug, mimetype, image_width, image_height, date_captured, priority)
|
|
VALUES
|
|
({int:id_user_uploaded}, {string:subdir}, {string:filename}, {string:title}, {string:slug}, {string:mimetype},
|
|
{int:image_width}, {int:image_height},
|
|
IF({int:date_captured} > 0, FROM_UNIXTIME({int:date_captured}), NULL),
|
|
{int:priority})',
|
|
[
|
|
'id_user_uploaded' => isset($id_user) ? $id_user : Registry::get('user')->getUserId(),
|
|
'subdir' => $preferred_subdir,
|
|
'filename' => $new_filename,
|
|
'title' => $title,
|
|
'slug' => $slug,
|
|
'mimetype' => $mimetype,
|
|
'image_width' => isset($image_width) ? $image_width : 'NULL',
|
|
'image_height' => isset($image_height) ? $image_height : 'NULL',
|
|
'date_captured' => isset($date_captured) ? $date_captured : 'NULL',
|
|
'priority' => isset($priority) ? (int) $priority : 0,
|
|
]);
|
|
|
|
if (!$res)
|
|
{
|
|
unlink($destination);
|
|
return false;
|
|
}
|
|
|
|
$data['id_asset'] = $db->insert_id();
|
|
return $return_format === 'object' ? new self($data) : $data;
|
|
}
|
|
|
|
public function getId()
|
|
{
|
|
return $this->id_asset;
|
|
}
|
|
|
|
public function getAuthor()
|
|
{
|
|
return Member::fromId($this->id_user_uploaded);
|
|
}
|
|
|
|
public function getDateCaptured()
|
|
{
|
|
return $this->date_captured;
|
|
}
|
|
|
|
public function getDeleteUrl()
|
|
{
|
|
return BASEURL . '/editasset/?id=' . $this->id_asset . '&delete';
|
|
}
|
|
|
|
public function getEditUrl()
|
|
{
|
|
return BASEURL . '/editasset/?id=' . $this->id_asset;
|
|
}
|
|
|
|
public function getFilename()
|
|
{
|
|
return $this->filename;
|
|
}
|
|
|
|
public function getLinkedPosts()
|
|
{
|
|
$posts = Registry::get('db')->queryValues('
|
|
SELECT id_post
|
|
FROM posts_assets
|
|
WHERE id_asset = {int:id_asset}',
|
|
['id_asset' => $this->id_asset]);
|
|
|
|
// TODO: fix empty post iterator.
|
|
if (empty($posts))
|
|
return [];
|
|
|
|
return PostIterator::getByOptions([
|
|
'ids' => $posts,
|
|
'type' => '',
|
|
]);
|
|
}
|
|
|
|
public function getMeta()
|
|
{
|
|
return $this->meta;
|
|
}
|
|
|
|
public function getFullPath()
|
|
{
|
|
return ASSETSDIR . '/' . $this->subdir . '/' . $this->filename;
|
|
}
|
|
|
|
public function getSlug()
|
|
{
|
|
return $this->slug;
|
|
}
|
|
|
|
public function getSubdir()
|
|
{
|
|
return $this->subdir;
|
|
}
|
|
|
|
public function getPriority()
|
|
{
|
|
return $this->priority;
|
|
}
|
|
|
|
public function getTags()
|
|
{
|
|
if (!isset($this->tags))
|
|
$this->tags = Tag::byAssetId($this->id_asset);
|
|
|
|
return $this->tags;
|
|
}
|
|
|
|
public function getTitle()
|
|
{
|
|
return $this->title;
|
|
}
|
|
|
|
public function getUrl()
|
|
{
|
|
return BASEURL . '/assets/' . $this->subdir . '/' . $this->filename;
|
|
}
|
|
|
|
public function getPageUrl()
|
|
{
|
|
return BASEURL . '/' . $this->slug . '/';
|
|
}
|
|
|
|
public function getType()
|
|
{
|
|
return substr($this->mimetype, 0, strpos($this->mimetype, '/'));
|
|
}
|
|
|
|
public function getDimensions($as_type = 'string')
|
|
{
|
|
return $as_type === 'string' ? $this->image_width . 'x' . $this->image_height : [$this->image_width, $this->image_height];
|
|
}
|
|
|
|
public function isImage()
|
|
{
|
|
return isset($this->mimetype) && substr($this->mimetype, 0, 5) === 'image';
|
|
}
|
|
|
|
public function getImage()
|
|
{
|
|
if (!$this->isImage())
|
|
throw new Exception('Trying to upgrade an Asset to an Image while the Asset is not an image!');
|
|
|
|
return new Image(get_object_vars($this));
|
|
}
|
|
|
|
public function isOwnedBy(User $user)
|
|
{
|
|
return $this->id_user_uploaded == $user->getUserId();
|
|
}
|
|
|
|
public function moveToSubDir($destSubDir)
|
|
{
|
|
// Verify the original exists
|
|
$source = ASSETSDIR . '/' . $this->subdir . '/' . $this->filename;
|
|
if (!file_exists($source))
|
|
return -1;
|
|
|
|
// Ensure the intended target file doesn't exist yet
|
|
$destDir = ASSETSDIR . '/' . $destSubDir;
|
|
$destFile = $destDir . '/' . $this->filename;
|
|
|
|
if (file_exists($destFile))
|
|
return -2;
|
|
|
|
// Can we write to the target directory?
|
|
if (!is_writable($destDir))
|
|
return -3;
|
|
|
|
// Perform move
|
|
if (rename($source, $destFile))
|
|
{
|
|
$this->subdir = $destSubDir;
|
|
$this->slug = $this->subdir . '/' . $this->title;
|
|
Registry::get('db')->query('
|
|
UPDATE assets
|
|
SET subdir = {string:subdir},
|
|
slug = {string:slug}
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
'subdir' => $this->subdir,
|
|
'slug' => $this->slug,
|
|
]);
|
|
return true;
|
|
}
|
|
|
|
return -4;
|
|
}
|
|
|
|
public function replaceFile($filename)
|
|
{
|
|
// No filename? Abort!
|
|
if (!isset($filename) || !is_readable($filename))
|
|
return false;
|
|
|
|
// Can we write to the target file?
|
|
$destination = ASSETSDIR . '/' . $this->subdir . '/' . $this->filename;
|
|
if (!is_writable($destination))
|
|
return false;
|
|
|
|
copy($filename, $destination);
|
|
|
|
// Figure out the mime type for the file.
|
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
|
$this->mimetype = finfo_file($finfo, $destination);
|
|
finfo_close($finfo);
|
|
|
|
// Detected an image?
|
|
if (substr($this->mimetype, 0, 5) === 'image')
|
|
{
|
|
$image = new Imagick($destination);
|
|
$d = $image->getImageGeometry();
|
|
$this->image_width = $d['width'];
|
|
$this->image_height = $d['height'];
|
|
unset($image);
|
|
|
|
$exif = EXIF::fromFile($destination);
|
|
if (!empty($exif->created_timestamp))
|
|
$this->date_captured = new DateTime(date('r', $exif->created_timestamp));
|
|
else
|
|
$this->date_captured = null;
|
|
}
|
|
else
|
|
{
|
|
$this->image_width = null;
|
|
$this->image_height = null;
|
|
$this->date_captured = null;
|
|
}
|
|
|
|
return Registry::get('db')->query('
|
|
UPDATE assets
|
|
SET
|
|
mimetype = {string:mimetype},
|
|
image_width = {int:image_width},
|
|
image_height = {int:image_height},
|
|
date_captured = {datetime:date_captured},
|
|
priority = {int:priority}
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
'mimetype' => $this->mimetype,
|
|
'image_width' => isset($this->image_width) ? $this->image_width : 'NULL',
|
|
'image_height' => isset($this->image_height) ? $this->image_height : 'NULL',
|
|
'date_captured' => isset($this->date_captured) ? $this->date_captured : 'NULL',
|
|
'priority' => $this->priority,
|
|
]);
|
|
}
|
|
|
|
protected function saveMetaData()
|
|
{
|
|
$this->setMetaData($this->meta);
|
|
}
|
|
|
|
public function setMetaData(array $new_meta, $mode = 'replace')
|
|
{
|
|
$db = Registry::get('db');
|
|
|
|
// If we're replacing, delete current data first.
|
|
if ($mode === 'replace')
|
|
{
|
|
$to_remove = array_diff_key($this->meta, $new_meta);
|
|
if (!empty($to_remove))
|
|
$db->query('
|
|
DELETE FROM assets_meta
|
|
WHERE id_asset = {int:id_asset} AND
|
|
variable IN({array_string:variables})',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
'variables' => array_keys($to_remove),
|
|
]);
|
|
}
|
|
|
|
// Build rows
|
|
$to_insert = [];
|
|
foreach ($new_meta as $key => $value)
|
|
$to_insert[] = [
|
|
'id_asset' => $this->id_asset,
|
|
'variable' => $key,
|
|
'value' => $value,
|
|
];
|
|
|
|
// Do the insertion
|
|
$res = Registry::get('db')->insert('replace', 'assets_meta', [
|
|
'id_asset' => 'int',
|
|
'variable' => 'string',
|
|
'value' => 'string',
|
|
], $to_insert, ['id_asset', 'variable']);
|
|
|
|
if ($res)
|
|
$this->meta = $new_meta;
|
|
}
|
|
|
|
public function delete()
|
|
{
|
|
$db = Registry::get('db');
|
|
|
|
// First: delete associated metadata
|
|
$db->query('
|
|
DELETE FROM assets_meta
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
]);
|
|
|
|
// Second: figure out what tags to recount cardinality for
|
|
$recount_tags = $db->queryValues('
|
|
SELECT id_tag
|
|
FROM assets_tags
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
]);
|
|
|
|
$db->query('
|
|
DELETE FROM assets_tags
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
]);
|
|
|
|
Tag::recount($recount_tags);
|
|
|
|
// Third: figure out what associated thumbs to delete
|
|
$thumbs_to_delete = $db->queryValues('
|
|
SELECT filename
|
|
FROM assets_thumbs
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
]);
|
|
|
|
foreach ($thumbs_to_delete as $filename)
|
|
{
|
|
$thumb_path = THUMBSDIR . '/' . $this->subdir . '/' . $filename;
|
|
if (is_file($thumb_path))
|
|
unlink($thumb_path);
|
|
}
|
|
|
|
$db->query('
|
|
DELETE FROM assets_thumbs
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
]);
|
|
|
|
// Reset asset ID for tags that use this asset for their thumbnail
|
|
$rows = $db->query('
|
|
SELECT id_tag
|
|
FROM tags
|
|
WHERE id_asset_thumb = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
]);
|
|
|
|
if (!empty($rows))
|
|
{
|
|
foreach ($rows as $row)
|
|
{
|
|
$tag = Tag::fromId($row['id_tag']);
|
|
$tag->resetIdAsset();
|
|
}
|
|
}
|
|
|
|
// Finally, delete the actual asset
|
|
if (!unlink(ASSETSDIR . '/' . $this->subdir . '/' . $this->filename))
|
|
return false;
|
|
|
|
$return = $db->query('
|
|
DELETE FROM assets
|
|
WHERE id_asset = {int:id_asset}',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
]);
|
|
|
|
return $return;
|
|
}
|
|
|
|
public function linkTags(array $id_tags)
|
|
{
|
|
if (empty($id_tags))
|
|
return true;
|
|
|
|
$pairs = [];
|
|
foreach ($id_tags as $id_tag)
|
|
$pairs[] = ['id_asset' => $this->id_asset, 'id_tag' => $id_tag];
|
|
|
|
Registry::get('db')->insert('ignore', 'assets_tags', [
|
|
'id_asset' => 'int',
|
|
'id_tag' => 'int',
|
|
], $pairs, ['id_asset', 'id_tag']);
|
|
|
|
Tag::recount($id_tags);
|
|
}
|
|
|
|
public function unlinkTags(array $id_tags)
|
|
{
|
|
if (empty($id_tags))
|
|
return true;
|
|
|
|
Registry::get('db')->query('
|
|
DELETE FROM assets_tags
|
|
WHERE id_asset = {int:id_asset} AND id_tag IN ({array_int:id_tags})',
|
|
[
|
|
'id_asset' => $this->id_asset,
|
|
'id_tags' => $id_tags,
|
|
]);
|
|
|
|
Tag::recount($id_tags);
|
|
}
|
|
|
|
public static function getCount()
|
|
{
|
|
return Registry::get('db')->queryValue('
|
|
SELECT COUNT(*)
|
|
FROM assets');
|
|
}
|
|
|
|
public function save()
|
|
{
|
|
if (empty($this->id_asset))
|
|
throw new UnexpectedValueException();
|
|
|
|
return Registry::get('db')->query('
|
|
UPDATE assets
|
|
SET id_asset = {int:id_asset},
|
|
id_user_uploaded = {int:id_user_uploaded},
|
|
subdir = {string:subdir},
|
|
filename = {string:filename},
|
|
title = {string:title},
|
|
slug = {string:slug},
|
|
mimetype = {string:mimetype},
|
|
image_width = {int:image_width},
|
|
image_height = {int:image_height},
|
|
date_captured = {datetime:date_captured},
|
|
priority = {int:priority}
|
|
WHERE id_asset = {int:id_asset}',
|
|
get_object_vars($this));
|
|
}
|
|
|
|
protected function getUrlForAdjacentInSet($prevNext, ?Tag $tag, $activeFilter)
|
|
{
|
|
$next = $prevNext === 'next';
|
|
$previous = !$next;
|
|
|
|
$where = [];
|
|
$params = [
|
|
'id_asset' => $this->id_asset,
|
|
'date_captured' => $this->date_captured,
|
|
];
|
|
|
|
// Direction depends on whether we're browsing a tag or timeline
|
|
if (isset($tag))
|
|
{
|
|
$where[] = 't.id_tag = {int:id_tag}';
|
|
$params['id_tag'] = $tag->id_tag;
|
|
$params['where_op'] = $previous ? '<' : '>';
|
|
$params['order_dir'] = $previous ? 'DESC' : 'ASC';
|
|
}
|
|
else
|
|
{
|
|
$params['where_op'] = $previous ? '>' : '<';
|
|
$params['order_dir'] = $previous ? 'ASC' : 'DESC';
|
|
}
|
|
|
|
// Take active filter into account as well
|
|
if (!empty($activeFilter) && ($user = Member::fromSlug($activeFilter)) !== false)
|
|
{
|
|
$where[] = 'id_user_uploaded = {int:id_user_uploaded}';
|
|
$params['id_user_uploaded'] = $user->getUserId();
|
|
}
|
|
|
|
// Use complete ordering when sorting the set
|
|
$where[] = '(a.date_captured, a.id_asset) {raw:where_op} ' .
|
|
'({datetime:date_captured}, {int:id_asset})';
|
|
|
|
// Stringify conditions together
|
|
$where = '(' . implode(') AND (', $where) . ')';
|
|
|
|
// Run query, leaving out tags table if not required
|
|
$row = Registry::get('db')->queryAssoc('
|
|
SELECT a.*
|
|
FROM assets AS a
|
|
' . (isset($tag) ? '
|
|
INNER JOIN assets_tags AS t ON a.id_asset = t.id_asset' : '') . '
|
|
WHERE ' . $where . '
|
|
ORDER BY a.date_captured {raw:order_dir}, a.id_asset {raw:order_dir}
|
|
LIMIT 1',
|
|
$params);
|
|
|
|
if (!$row)
|
|
return false;
|
|
|
|
$obj = self::byRow($row, 'object');
|
|
|
|
$urlParams = [];
|
|
if (isset($tag))
|
|
$urlParams['in'] = $tag->id_tag;
|
|
if (!empty($activeFilter))
|
|
$urlParams['by'] = $activeFilter;
|
|
|
|
$queryString = !empty($urlParams) ? '?' . http_build_query($urlParams) : '';
|
|
|
|
return $obj->getPageUrl() . $queryString;
|
|
}
|
|
|
|
public function getUrlForPreviousInSet(?Tag $tag, $activeFilter)
|
|
{
|
|
return $this->getUrlForAdjacentInSet('previous', $tag, $activeFilter);
|
|
}
|
|
|
|
public function getUrlForNextInSet(?Tag $tag, $activeFilter)
|
|
{
|
|
return $this->getUrlForAdjacentInSet('next', $tag, $activeFilter);
|
|
}
|
|
}
|