mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Improved xlist endpoint
This commit is contained in:
@@ -8,12 +8,15 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Query as QueryException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Queries;
|
||||
use Utopia\Database\Validator\Query\Filter;
|
||||
use Utopia\Database\Validator\Query\Limit;
|
||||
use Utopia\Database\Validator\Query\Offset;
|
||||
use Utopia\Database\Validator\Query\Order;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
@@ -22,6 +25,17 @@ class XList extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
private const ALLOWED_ATTRIBUTES = [
|
||||
'type' => Database::VAR_STRING,
|
||||
'locale' => Database::VAR_STRING,
|
||||
'subject' => Database::VAR_STRING,
|
||||
'message' => Database::VAR_STRING,
|
||||
'senderName' => Database::VAR_STRING,
|
||||
'senderEmail' => Database::VAR_STRING,
|
||||
'replyTo' => Database::VAR_STRING,
|
||||
'custom' => Database::VAR_BOOLEAN,
|
||||
];
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'listProjectEmailTemplates';
|
||||
@@ -29,10 +43,25 @@ class XList extends Action
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$attributes = [];
|
||||
foreach (self::ALLOWED_ATTRIBUTES as $key => $type) {
|
||||
$attributes[] = new Document([
|
||||
'key' => $key,
|
||||
'type' => $type,
|
||||
'array' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
$queriesValidator = new Queries([
|
||||
new Limit(),
|
||||
new Offset(),
|
||||
new Filter($attributes, Database::VAR_STRING, APP_DATABASE_QUERY_MAX_VALUES),
|
||||
new Order($attributes),
|
||||
]);
|
||||
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET)
|
||||
->setHttpPath('/v1/project/templates/email')
|
||||
->httpAlias('/v1/projects/:projectId/templates/email')
|
||||
->desc('List project email templates')
|
||||
->groups(['api', 'project'])
|
||||
->label('scope', 'templates.read')
|
||||
@@ -51,7 +80,7 @@ class XList extends Action
|
||||
)
|
||||
]
|
||||
))
|
||||
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset.', true)
|
||||
->param('queries', [], $queriesValidator, 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter and order on the following attributes: ' . implode(', ', array_keys(self::ALLOWED_ATTRIBUTES)), true)
|
||||
->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true)
|
||||
->inject('project')
|
||||
->inject('response')
|
||||
@@ -80,6 +109,13 @@ class XList extends Action
|
||||
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
|
||||
$offset = $grouped['offset'] ?? 0;
|
||||
|
||||
/** @var array<Query> $filters */
|
||||
$filters = $grouped['filters'] ?? [];
|
||||
/** @var array<string> $orderAttributes */
|
||||
$orderAttributes = $grouped['orderAttributes'] ?? [];
|
||||
/** @var array<string> $orderTypes */
|
||||
$orderTypes = $grouped['orderTypes'] ?? [];
|
||||
|
||||
$types = Config::getParam('locale-templates')['email'] ?? [];
|
||||
$projectTemplates = $project->getAttribute('templates', []);
|
||||
|
||||
@@ -102,6 +138,9 @@ class XList extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$templates = $this->applyFilters($templates, $filters);
|
||||
$templates = $this->applyOrder($templates, $orderAttributes, $orderTypes);
|
||||
|
||||
$total = $includeTotal ? \count($templates) : 0;
|
||||
$templates = \array_slice($templates, $offset, $limit);
|
||||
|
||||
@@ -110,4 +149,80 @@ class XList extends Action
|
||||
'total' => $total,
|
||||
]), Response::MODEL_EMAIL_TEMPLATE_LIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<Document> $templates
|
||||
* @param array<Query> $filters
|
||||
* @return array<Document>
|
||||
*/
|
||||
private function applyFilters(array $templates, array $filters): array
|
||||
{
|
||||
if (empty($filters)) {
|
||||
return $templates;
|
||||
}
|
||||
|
||||
return \array_values(\array_filter($templates, function (Document $template) use ($filters) {
|
||||
foreach ($filters as $filter) {
|
||||
if (!$this->matches($template, $filter)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
private function matches(Document $template, Query $filter): bool
|
||||
{
|
||||
$attribute = $filter->getAttribute();
|
||||
$values = $filter->getValues();
|
||||
$actual = $template->getAttribute($attribute);
|
||||
$needle = (string) ($values[0] ?? '');
|
||||
|
||||
return match ($filter->getMethod()) {
|
||||
Query::TYPE_EQUAL => \in_array($actual, $values, false),
|
||||
Query::TYPE_NOT_EQUAL => !\in_array($actual, $values, false),
|
||||
Query::TYPE_STARTS_WITH => \is_string($actual) && \str_starts_with($actual, $needle),
|
||||
Query::TYPE_NOT_STARTS_WITH => \is_string($actual) && !\str_starts_with($actual, $needle),
|
||||
Query::TYPE_ENDS_WITH => \is_string($actual) && \str_ends_with($actual, $needle),
|
||||
Query::TYPE_NOT_ENDS_WITH => \is_string($actual) && !\str_ends_with($actual, $needle),
|
||||
Query::TYPE_CONTAINS => \is_string($actual) && \str_contains($actual, $needle),
|
||||
Query::TYPE_NOT_CONTAINS => \is_string($actual) && !\str_contains($actual, $needle),
|
||||
Query::TYPE_SEARCH => \is_string($actual) && \stripos($actual, $needle) !== false,
|
||||
Query::TYPE_NOT_SEARCH => \is_string($actual) && \stripos($actual, $needle) === false,
|
||||
Query::TYPE_IS_NULL => $actual === null || $actual === '',
|
||||
Query::TYPE_IS_NOT_NULL => $actual !== null && $actual !== '',
|
||||
default => throw new Exception(Exception::GENERAL_QUERY_INVALID, 'Query method not supported for email templates: ' . $filter->getMethod()),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<Document> $templates
|
||||
* @param array<string> $orderAttributes
|
||||
* @param array<string> $orderTypes
|
||||
* @return array<Document>
|
||||
*/
|
||||
private function applyOrder(array $templates, array $orderAttributes, array $orderTypes): array
|
||||
{
|
||||
if (empty($orderAttributes)) {
|
||||
return $templates;
|
||||
}
|
||||
|
||||
\usort($templates, function (Document $a, Document $b) use ($orderAttributes, $orderTypes) {
|
||||
foreach ($orderAttributes as $index => $attribute) {
|
||||
$direction = \strtoupper($orderTypes[$index] ?? Database::ORDER_ASC);
|
||||
$valueA = $a->getAttribute($attribute);
|
||||
$valueB = $b->getAttribute($attribute);
|
||||
|
||||
$cmp = $valueA <=> $valueB;
|
||||
if ($cmp === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $direction === Database::ORDER_DESC ? -$cmp : $cmp;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return $templates;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user