AssetIterator: rewrite to standard Iterator interface

This commit is contained in:
Aaron van Geffen 2025-05-13 23:29:43 +02:00
parent 9989ba1fa7
commit 4b26c677bb
6 changed files with 75 additions and 87 deletions

View File

@ -289,10 +289,4 @@ class ViewPhotoAlbum extends HTMLController
$description = !empty($tag->description) ? $tag->description : ''; $description = !empty($tag->description) ? $tag->description : '';
return new AlbumHeaderBox($tag->tag, $description, $back_link, $back_link_title); return new AlbumHeaderBox($tag->tag, $description, $back_link, $back_link_title);
} }
public function __destruct()
{
if (isset($this->iterator))
$this->iterator->clean();
}
} }

View File

@ -54,10 +54,4 @@ class ViewTimeline extends HTMLController
// Set the canonical url. // Set the canonical url.
$this->page->setCanonicalUrl(BASEURL . '/timeline/'); $this->page->setCanonicalUrl(BASEURL . '/timeline/');
} }
public function __destruct()
{
if (isset($this->iterator))
$this->iterator->clean();
}
} }

View File

@ -24,7 +24,7 @@ class Asset
protected $tags; protected $tags;
protected $thumbnails; protected $thumbnails;
protected function __construct(array $data) public function __construct(array $data)
{ {
foreach ($data as $attribute => $value) foreach ($data as $attribute => $value)
{ {

View File

@ -1,42 +1,50 @@
<?php <?php
/***************************************************************************** /*****************************************************************************
* AssetIterator.php * AssetIterator.php
* Contains key class AssetIterator. * Contains model class AssetIterator.
* *
* Kabuki CMS (C) 2013-2015, Aaron van Geffen * Kabuki CMS (C) 2013-2025, Aaron van Geffen
*****************************************************************************/ *****************************************************************************/
class AssetIterator extends Asset class AssetIterator implements Iterator
{ {
private Database $db;
private $direction; private $direction;
private $return_format; private $return_format;
private $res_assets; private $rowCount;
private $res_meta;
private $res_thumbs;
protected function __construct($res_assets, $res_meta, $res_thumbs, $return_format, $direction) private $assets_iterator;
private $meta_iterator;
private $thumbs_iterator;
protected function __construct(PDOStatement $stmt_assets, PDOStatement $stmt_meta, PDOStatement $stmt_thumbs,
$return_format, $direction)
{ {
$this->db = Registry::get('db');
$this->direction = $direction; $this->direction = $direction;
$this->res_assets = $res_assets;
$this->res_meta = $res_meta;
$this->res_thumbs = $res_thumbs;
$this->return_format = $return_format; $this->return_format = $return_format;
$this->rowCount = $stmt_assets->rowCount();
$this->assets_iterator = new CachedPDOIterator($stmt_assets);
$this->assets_iterator->rewind();
$this->meta_iterator = new CachedPDOIterator($stmt_meta);
$this->thumbs_iterator = new CachedPDOIterator($stmt_thumbs);
} }
public function next() public static function all()
{ {
$row = $this->db->fetchAssoc($this->res_assets); return self::getByOptions();
}
// No more rows? public function current(): mixed
{
$row = $this->assets_iterator->current();
if (!$row) if (!$row)
return false; return $row;
// Looks up metadata. // Collect metadata
$row['meta'] = []; $row['meta'] = [];
while ($meta = $this->db->fetchAssoc($this->res_meta)) $this->meta_iterator->rewind();
foreach ($this->meta_iterator as $meta)
{ {
if ($meta['id_asset'] != $row['id_asset']) if ($meta['id_asset'] != $row['id_asset'])
continue; continue;
@ -44,54 +52,23 @@ class AssetIterator extends Asset
$row['meta'][$meta['variable']] = $meta['value']; $row['meta'][$meta['variable']] = $meta['value'];
} }
// Reset internal pointer for next asset. // Collect thumbnails
$this->db->data_seek($this->res_meta, 0);
// Looks up thumbnails.
$row['thumbnails'] = []; $row['thumbnails'] = [];
while ($thumbs = $this->db->fetchAssoc($this->res_thumbs)) $this->thumbs_iterator->rewind();
foreach ($this->thumbs_iterator as $thumb)
{ {
if ($thumbs['id_asset'] != $row['id_asset']) if ($thumb['id_asset'] != $row['id_asset'])
continue; continue;
$row['thumbnails'][$thumbs['selector']] = $thumbs['filename']; $row['thumbnails'][$thumb['selector']] = $thumb['filename'];
} }
// Reset internal pointer for next asset.
$this->db->data_seek($this->res_thumbs, 0);
if ($this->return_format === 'object') if ($this->return_format === 'object')
return new Asset($row); return new Asset($row);
else else
return $row; return $row;
} }
public function reset()
{
$this->db->data_seek($this->res_assets, 0);
$this->db->data_seek($this->res_meta, 0);
$this->db->data_seek($this->res_thumbs, 0);
}
public function clean()
{
if (!$this->res_assets)
return;
$this->db->free($this->res_assets);
$this->res_assets = null;
}
public function num()
{
return $this->db->rowCount($this->res_assets);
}
public static function all()
{
return self::getByOptions();
}
public static function getByOptions(array $options = [], $return_count = false, $return_format = 'object') public static function getByOptions(array $options = [], $return_count = false, $return_format = 'object')
{ {
$params = [ $params = [
@ -210,13 +187,38 @@ class AssetIterator extends Asset
return $iterator; return $iterator;
} }
public function isAscending() public function key(): mixed
{
return $this->assets_iterator->key();
}
public function isAscending(): bool
{ {
return $this->direction === 'asc'; return $this->direction === 'asc';
} }
public function isDescending() public function isDescending(): bool
{ {
return $this->direction === 'desc'; return $this->direction === 'desc';
} }
public function next(): void
{
$this->assets_iterator->next();
}
public function num(): int
{
return $this->rowCount;
}
public function rewind(): void
{
$this->assets_iterator->rewind();
}
public function valid(): bool
{
return $this->assets_iterator->valid();
}
} }

View File

@ -8,11 +8,11 @@
class PhotoMosaic class PhotoMosaic
{ {
private $descending; private bool $descending;
private AssetIterator $iterator; private AssetIterator $iterator;
private $layouts; private array $layouts;
private $processedImages = 0; private int $processedImages = 0;
private $queue = []; private array $queue = [];
const IMAGE_MASK_ALL = Image::TYPE_PORTRAIT | Image::TYPE_LANDSCAPE | Image::TYPE_PANORAMA; const IMAGE_MASK_ALL = Image::TYPE_PORTRAIT | Image::TYPE_LANDSCAPE | Image::TYPE_PANORAMA;
const NUM_DAYS_CUTOFF = 7; const NUM_DAYS_CUTOFF = 7;
@ -25,11 +25,6 @@ class PhotoMosaic
$this->descending = $iterator->isDescending(); $this->descending = $iterator->isDescending();
} }
public function __destruct()
{
$this->iterator->clean();
}
private function availableLayouts() private function availableLayouts()
{ {
static $layouts = [ static $layouts = [
@ -86,9 +81,14 @@ class PhotoMosaic
} }
} }
// Check whatever's next up! // Check whatever's up next!
while (($asset = $this->iterator->next()) && ($image = $asset->getImage())) // NB: not is not a `foreach` so as to not reset the iterator implicitly
while ($this->iterator->valid())
{ {
$asset = $this->iterator->current();
$image = $asset->getImage();
$this->iterator->next();
// Give up on the recordset once dates are too far apart // Give up on the recordset once dates are too far apart
if (isset($refDate) && abs(self::daysApart($image->getDateCaptured(), $refDate)) > self::NUM_DAYS_CUTOFF) if (isset($refDate) && abs(self::daysApart($image->getDateCaptured(), $refDate)) > self::NUM_DAYS_CUTOFF)
{ {

View File

@ -8,12 +8,12 @@
class FeaturedThumbnailManager extends SubTemplate class FeaturedThumbnailManager extends SubTemplate
{ {
private $assets; private $iterator;
private $currentThumbnailId; private $currentThumbnailId;
public function __construct(AssetIterator $assets, $currentThumbnailId) public function __construct(AssetIterator $iterator, $currentThumbnailId)
{ {
$this->assets = $assets; $this->iterator = $iterator;
$this->currentThumbnailId = $currentThumbnailId; $this->currentThumbnailId = $currentThumbnailId;
} }
@ -25,7 +25,7 @@ class FeaturedThumbnailManager extends SubTemplate
<h2>Select thumbnail</h2> <h2>Select thumbnail</h2>
<ul id="featuredThumbnail">'; <ul id="featuredThumbnail">';
while ($asset = $this->assets->next()) foreach ($this->iterator as $asset)
{ {
$image = $asset->getImage(); $image = $asset->getImage();
echo ' echo '
@ -36,8 +36,6 @@ class FeaturedThumbnailManager extends SubTemplate
</li>'; </li>';
} }
$this->assets->clean();
echo ' echo '
</ul> </ul>
<input type="hidden" name="', Session::getSessionTokenKey(), '" value="', Session::getSessionToken(), '"> <input type="hidden" name="', Session::getSessionTokenKey(), '" value="', Session::getSessionToken(), '">