| Current Path : /home/u4uwebca/public_html/pano.4uweb.ca/src/Library/Queue/ |
| Current File : /home/u4uwebca/public_html/pano.4uweb.ca/src/Library/Queue/MySQLQueue.php |
<?php
/**
* @package panopticon
* @copyright Copyright (c)2023-2024 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license https://www.gnu.org/licenses/agpl-3.0.txt GNU Affero General Public License, version 3 or later
*/
namespace Akeeba\Panopticon\Library\Queue;
defined('AKEEBA') || die;
use Akeeba\Panopticon\Factory;
use Awf\Container\ContainerAwareInterface;
use Awf\Container\ContainerAwareTrait;
use Awf\Database\Driver;
use Awf\Date\Date;
use DateTime;
use Exception;
class MySQLQueue implements QueueInterface, ContainerAwareInterface
{
use ContainerAwareTrait;
public function __construct(private string $queueIdentifier, private Driver $db, private string $tableName = '#__queue')
{
$this->setContainer(Factory::getContainer());
}
public function push(QueueItem $item, DateTime|int|string|null $time = null): void
{
$db = $this->db;
$time = $this->normaliseTime($time);
$query = $db->getQuery(true)
->insert($db->quoteName($this->tableName))
->columns([
$db->quoteName('item'),
$db->quoteName('time'),
])
->values(
$db->quote(json_encode($item)) . ',' .
$db->q($time->toSql())
);
$db->transactionStart();
try
{
$db->setQuery($query)->execute();
$db->transactionCommit();
}
catch (Exception $e)
{
$db->transactionRollback();
throw $e;
}
}
public function pop(): ?QueueItem
{
$db = $this->db;
$query = $db->getQuery(true)
->select([
$db->quoteName('id'),
$db->quoteName('item'),
])
->from($db->quoteName($this->tableName))
->where([
$db->quoteName('time') . ' <= NOW()',
'JSON_EXTRACT(' . $db->quoteName('item') . ', \'$.queueType\') = ' . $db->quote(strtolower($this->queueIdentifier)),
])
->order($db->quoteName('time') . 'ASC');
// Append this because we can't do this with the query interface
$query = (string) $query . ' LIMIT 0, 1 FOR UPDATE';
// Wrap the select and delete in a transaction
$db->transactionStart();
try
{
$object = $db->setQuery($db->replacePrefix((string) $query))->loadObject();
}
catch (Exception $e)
{
$db->transactionRollback();
throw $e;
}
if (empty($object))
{
// Nothing to return. Roll back the transaction.
$db->transactionRollback();
return null;
}
$query = $db->getQuery(true)
->delete($db->quoteName($this->tableName))
->where($db->quoteName('id') . ' = ' . $object->id);
try
{
$db->setQuery($query)->execute();
}
catch (Exception $e)
{
$db->transactionRollback();
throw $e;
}
$db->transactionCommit();
return QueueItem::fromJson($object->item);
}
public function clear(array $conditions = []): void
{
$db = $this->db;
$query = $db->getQuery(true)
->delete('IGNORE ' . $db->quoteName($this->tableName))
->where('JSON_EXTRACT(' . $db->quoteName('item') . ', \'$.queueType\') = ' . $db->quote($this->queueIdentifier));
if (isset($conditions['queueType']))
{
unset($conditions['queueType']);
}
foreach ($conditions as $key => $value)
{
$query->where(
sprintf(
"JSON_EXTRACT(%s, %s) = %s",
$db->quoteName('item'),
$db->quote('$.' . $key),
$db->quote($value)
)
);
}
$db->transactionStart();
try
{
$db->setQuery($query)->execute();
}
catch (Exception $e)
{
$db->transactionRollback();
throw $e;
}
$db->transactionCommit();
}
public function count(): int
{
$db = $this->db;
$query = $db->getQuery(true)
->select('COUNT(*)')
->from($db->quoteName($this->tableName))
->where('JSON_EXTRACT(' . $db->quoteName('item') . ', \'$.queueType\') = ' . $db->quote($this->queueIdentifier));
return $db->setQuery($query)->loadResult() ?: 0;
}
public function countByCondition(array $conditions = []): int
{
if (isset($conditions['queueType']))
{
unset($conditions['queueType']);
}
if (empty($conditions))
{
return $this->count();
}
$db = $this->db;
$query = $db->getQuery(true)
->select('COUNT(*)')
->from($db->quoteName($this->tableName))
->where('JSON_EXTRACT(' . $db->quoteName('item') . ', \'$.queueType\') = ' . $db->quote($this->queueIdentifier));
foreach ($conditions as $key => $value)
{
if (is_integer($value))
{
$value = intval($value);
}
elseif (is_numeric($value))
{
$value = floatval($value);
}
else
{
$value = $db->quote($value);
}
$query->where(
sprintf(
"JSON_EXTRACT(%s, %s) = %s",
$db->quoteName('item'),
$db->quote('$.' . $key),
$value
)
);
}
return $db->setQuery($query)->loadResult() ?: 0;
}
private function normaliseTime(DateTime|int|string|null $time): Date
{
if (empty($time))
{
$time = $this->container->dateFactory();
}
if (is_integer($time))
{
$time = Date('@' . $time);
}
if ($time instanceof DateTime)
{
$time = $time->toRFC3339();
}
if (is_string($time))
{
try
{
$time = $this->container->dateFactory($time);
}
catch (Exception)
{
$time = $this->container->dateFactory();
}
}
return $time;
}
}