generated from Nodarx/template
refactor: use custom imap client
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
377
lib/Client/SearchCriteriaBuilder.php
Normal file
377
lib/Client/SearchCriteriaBuilder.php
Normal file
@@ -0,0 +1,377 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KTXM\ProviderImap\Client;
|
||||
|
||||
use DateTimeInterface;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class SearchCriteriaBuilder
|
||||
{
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private array $criteria = [];
|
||||
|
||||
public static function create(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function all(): self
|
||||
{
|
||||
return $this->pushExpression('ALL');
|
||||
}
|
||||
|
||||
public function answered(): self
|
||||
{
|
||||
return $this->pushExpression('ANSWERED');
|
||||
}
|
||||
|
||||
public function unanswered(): self
|
||||
{
|
||||
return $this->pushExpression('UNANSWERED');
|
||||
}
|
||||
|
||||
public function deleted(): self
|
||||
{
|
||||
return $this->pushExpression('DELETED');
|
||||
}
|
||||
|
||||
public function undeleted(): self
|
||||
{
|
||||
return $this->pushExpression('UNDELETED');
|
||||
}
|
||||
|
||||
public function draft(): self
|
||||
{
|
||||
return $this->pushExpression('DRAFT');
|
||||
}
|
||||
|
||||
public function undraft(): self
|
||||
{
|
||||
return $this->pushExpression('UNDRAFT');
|
||||
}
|
||||
|
||||
public function flagged(): self
|
||||
{
|
||||
return $this->pushExpression('FLAGGED');
|
||||
}
|
||||
|
||||
public function unflagged(): self
|
||||
{
|
||||
return $this->pushExpression('UNFLAGGED');
|
||||
}
|
||||
|
||||
public function seen(): self
|
||||
{
|
||||
return $this->pushExpression('SEEN');
|
||||
}
|
||||
|
||||
public function unseen(): self
|
||||
{
|
||||
return $this->pushExpression('UNSEEN');
|
||||
}
|
||||
|
||||
public function recent(): self
|
||||
{
|
||||
return $this->pushExpression('RECENT');
|
||||
}
|
||||
|
||||
public function old(): self
|
||||
{
|
||||
return $this->pushExpression('OLD');
|
||||
}
|
||||
|
||||
public function new(): self
|
||||
{
|
||||
return $this->pushExpression('NEW');
|
||||
}
|
||||
|
||||
public function from(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('FROM', $value);
|
||||
}
|
||||
|
||||
public function to(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('TO', $value);
|
||||
}
|
||||
|
||||
public function cc(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('CC', $value);
|
||||
}
|
||||
|
||||
public function bcc(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('BCC', $value);
|
||||
}
|
||||
|
||||
public function subject(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('SUBJECT', $value);
|
||||
}
|
||||
|
||||
public function body(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('BODY', $value);
|
||||
}
|
||||
|
||||
public function text(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('TEXT', $value);
|
||||
}
|
||||
|
||||
public function keyword(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('KEYWORD', $value, false);
|
||||
}
|
||||
|
||||
public function unkeyword(string $value): self
|
||||
{
|
||||
return $this->pushKeyValue('UNKEYWORD', $value, false);
|
||||
}
|
||||
|
||||
public function before(DateTimeInterface|string $value): self
|
||||
{
|
||||
return $this->pushDate('BEFORE', $value);
|
||||
}
|
||||
|
||||
public function on(DateTimeInterface|string $value): self
|
||||
{
|
||||
return $this->pushDate('ON', $value);
|
||||
}
|
||||
|
||||
public function since(DateTimeInterface|string $value): self
|
||||
{
|
||||
return $this->pushDate('SINCE', $value);
|
||||
}
|
||||
|
||||
public function sentBefore(DateTimeInterface|string $value): self
|
||||
{
|
||||
return $this->pushDate('SENTBEFORE', $value);
|
||||
}
|
||||
|
||||
public function sentOn(DateTimeInterface|string $value): self
|
||||
{
|
||||
return $this->pushDate('SENTON', $value);
|
||||
}
|
||||
|
||||
public function sentSince(DateTimeInterface|string $value): self
|
||||
{
|
||||
return $this->pushDate('SENTSINCE', $value);
|
||||
}
|
||||
|
||||
public function larger(int $value): self
|
||||
{
|
||||
return $this->pushNumber('LARGER', $value);
|
||||
}
|
||||
|
||||
public function smaller(int $value): self
|
||||
{
|
||||
return $this->pushNumber('SMALLER', $value);
|
||||
}
|
||||
|
||||
public function uid(int|string|SequenceSet $value): self
|
||||
{
|
||||
return $this->pushExpression('UID ' . $this->formatSequenceSet($value));
|
||||
}
|
||||
|
||||
public function sequence(int|string|SequenceSet $value): self
|
||||
{
|
||||
return $this->pushExpression($this->formatSequenceSet($value));
|
||||
}
|
||||
|
||||
public function header(string $name, string $value): self
|
||||
{
|
||||
return $this->pushExpression(sprintf(
|
||||
'HEADER %s %s',
|
||||
$this->formatString($name),
|
||||
$this->formatString($value),
|
||||
));
|
||||
}
|
||||
|
||||
public function group(SearchCriteriaBuilder|array|string $criteria): self
|
||||
{
|
||||
$expression = $this->normalizeOperand($criteria, true);
|
||||
if ($expression === '') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->pushExpression($expression);
|
||||
}
|
||||
|
||||
public function not(SearchCriteriaBuilder|array|string $criteria): self
|
||||
{
|
||||
$expression = $this->normalizeOperand($criteria, true);
|
||||
if ($expression === '') {
|
||||
throw new InvalidArgumentException('NOT search criteria cannot be empty.');
|
||||
}
|
||||
|
||||
return $this->pushExpression('NOT ' . $expression);
|
||||
}
|
||||
|
||||
public function or(SearchCriteriaBuilder|array|string $left, SearchCriteriaBuilder|array|string $right): self
|
||||
{
|
||||
$leftExpression = $this->normalizeOperand($left, true);
|
||||
$rightExpression = $this->normalizeOperand($right, true);
|
||||
|
||||
if ($leftExpression === '' || $rightExpression === '') {
|
||||
throw new InvalidArgumentException('OR search criteria requires two non-empty operands.');
|
||||
}
|
||||
|
||||
return $this->pushExpression(sprintf('OR %s %s', $leftExpression, $rightExpression));
|
||||
}
|
||||
|
||||
public function raw(string ...$criteria): self
|
||||
{
|
||||
$normalized = [];
|
||||
|
||||
foreach ($criteria as $criterion) {
|
||||
$criterion = trim($criterion);
|
||||
if ($criterion === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$normalized[] = $criterion;
|
||||
}
|
||||
|
||||
if ($normalized === []) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
foreach ($normalized as $expression) {
|
||||
$this->pushExpression($expression);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function build(): array
|
||||
{
|
||||
return $this->criteria === [] ? ['ALL'] : $this->criteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->build();
|
||||
}
|
||||
|
||||
private function pushExpression(string $expression): self
|
||||
{
|
||||
$expression = trim($expression);
|
||||
if ($expression !== '') {
|
||||
$this->criteria[] = $expression;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function pushKeyValue(string $key, string $value, bool $quote = true): self
|
||||
{
|
||||
$value = trim($value);
|
||||
if ($value === '') {
|
||||
throw new InvalidArgumentException(sprintf('%s search criteria cannot be empty.', $key));
|
||||
}
|
||||
|
||||
return $this->pushExpression(sprintf(
|
||||
'%s %s',
|
||||
$key,
|
||||
$quote ? $this->formatString($value) : $value,
|
||||
));
|
||||
}
|
||||
|
||||
private function pushDate(string $key, DateTimeInterface|string $value): self
|
||||
{
|
||||
return $this->pushExpression(sprintf('%s %s', $key, $this->formatDate($value)));
|
||||
}
|
||||
|
||||
private function pushNumber(string $key, int $value): self
|
||||
{
|
||||
if ($value < 0) {
|
||||
throw new InvalidArgumentException(sprintf('%s search criteria must not be negative.', $key));
|
||||
}
|
||||
|
||||
return $this->pushExpression(sprintf('%s %d', $key, $value));
|
||||
}
|
||||
|
||||
private function normalizeOperand(SearchCriteriaBuilder|array|string $criteria, bool $wrapComposite): string
|
||||
{
|
||||
if ($criteria instanceof self) {
|
||||
$expressions = $criteria->toArray();
|
||||
return $this->combineExpressions($expressions, $wrapComposite);
|
||||
}
|
||||
|
||||
if (is_string($criteria)) {
|
||||
$criteria = trim($criteria);
|
||||
return $criteria;
|
||||
}
|
||||
|
||||
$normalized = [];
|
||||
|
||||
foreach ($criteria as $criterion) {
|
||||
$criterion = trim((string) $criterion);
|
||||
if ($criterion === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$normalized[] = $criterion;
|
||||
}
|
||||
|
||||
return $this->combineExpressions($normalized, $wrapComposite);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $expressions
|
||||
*/
|
||||
private function combineExpressions(array $expressions, bool $wrapComposite): string
|
||||
{
|
||||
$expression = implode(' ', $expressions);
|
||||
|
||||
if ($expression === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$wrapComposite || count($expressions) === 1) {
|
||||
return $expression;
|
||||
}
|
||||
|
||||
return '(' . $expression . ')';
|
||||
}
|
||||
|
||||
private function formatDate(DateTimeInterface|string $value): string
|
||||
{
|
||||
if ($value instanceof DateTimeInterface) {
|
||||
return $value->format('d-M-Y');
|
||||
}
|
||||
|
||||
$value = trim($value);
|
||||
if ($value === '') {
|
||||
throw new InvalidArgumentException('Search dates cannot be empty.');
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function formatSequenceSet(int|string|SequenceSet $value): string
|
||||
{
|
||||
return match (true) {
|
||||
$value instanceof SequenceSet => $value->toCommand(),
|
||||
is_int($value) => SequenceSet::single($value)->toCommand(),
|
||||
default => SequenceSet::parse($value)->toCommand(),
|
||||
};
|
||||
}
|
||||
|
||||
private function formatString(string $value): string
|
||||
{
|
||||
return '"' . addcslashes($value, "\\\"") . '"';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user