diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php index 5bdc4c81..a6774018 100644 --- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php +++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php @@ -73,14 +73,25 @@ class ListShortUrlsCommand extends Command ->addOption( 'tags', 't', - InputOption::VALUE_REQUIRED, - 'A comma-separated list of tags to filter results.', + InputOption::VALUE_REQUIRED, // TODO Should be InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY + 'A comma-separated list of tags that short URLs need to include.', + ) + ->addOption('including-all-tags', 'i', InputOption::VALUE_NONE, '[DEPRECATED] Use --tags-all instead') + ->addOption( + 'tags-all', + mode: InputOption::VALUE_NONE, + description: 'If --tags is provided, returns only short URLs including ALL of them', ) ->addOption( - 'including-all-tags', - 'i', - InputOption::VALUE_NONE, - 'If tags is provided, returns only short URLs having ALL tags.', + 'exclude-tags', + 'et', + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'A comma-separated list of tags that short URLs should not have.', + ) + ->addOption( + 'exclude-tags-all', + mode: InputOption::VALUE_NONE, + description: 'If --exclude-tags is provided, returns only short URLs not including ANY of them', ) ->addOption( 'exclude-max-visits-reached', @@ -136,9 +147,16 @@ class ListShortUrlsCommand extends Command $page = (int) $input->getOption('page'); $searchTerm = $input->getOption('search-term'); $domain = $input->getOption('domain'); + $tags = $input->getOption('tags'); - $tagsMode = $input->getOption('including-all-tags') === true ? TagsMode::ALL->value : TagsMode::ANY->value; $tags = ! empty($tags) ? explode(',', $tags) : []; + $tagsMode = $input->getOption('tags-all') === true || $input->getOption('including-all-tags') === true + ? TagsMode::ALL->value + : TagsMode::ANY->value; + + $excludeTags = $input->getOption('exclude-tags'); + $excludeTagsMode = $input->getOption('exclude-tags-all') === true ? TagsMode::ALL->value : TagsMode::ANY->value; + $all = $input->getOption('all'); $startDate = $this->startDateOption->get($input, $output); $endDate = $this->endDateOption->get($input, $output); @@ -150,6 +168,8 @@ class ListShortUrlsCommand extends Command ShortUrlsParamsInputFilter::DOMAIN => $domain, ShortUrlsParamsInputFilter::TAGS => $tags, ShortUrlsParamsInputFilter::TAGS_MODE => $tagsMode, + ShortUrlsParamsInputFilter::EXCLUDE_TAGS => $excludeTags, + ShortUrlsParamsInputFilter::EXCLUDE_TAGS_MODE => $excludeTagsMode, ShortUrlsParamsInputFilter::ORDER_BY => $orderBy, ShortUrlsParamsInputFilter::START_DATE => $startDate?->toAtomString(), ShortUrlsParamsInputFilter::END_DATE => $endDate?->toAtomString(), diff --git a/module/Core/src/ShortUrl/Model/ShortUrlsParams.php b/module/Core/src/ShortUrl/Model/ShortUrlsParams.php index 1b1aea85..5b84ee10 100644 --- a/module/Core/src/ShortUrl/Model/ShortUrlsParams.php +++ b/module/Core/src/ShortUrl/Model/ShortUrlsParams.php @@ -63,6 +63,10 @@ final class ShortUrlsParams excludePastValidUntil: $inputFilter->getValue(ShortUrlsParamsInputFilter::EXCLUDE_PAST_VALID_UNTIL), tagsMode: self::resolveTagsMode($inputFilter->getValue(ShortUrlsParamsInputFilter::TAGS_MODE)), domain: $inputFilter->getValue(ShortUrlsParamsInputFilter::DOMAIN), + excludeTags: (array) $inputFilter->getValue(ShortUrlsParamsInputFilter::EXCLUDE_TAGS), + excludeTagsMode: self::resolveTagsMode( + $inputFilter->getValue(ShortUrlsParamsInputFilter::EXCLUDE_TAGS_MODE), + ), ); } diff --git a/module/Core/src/ShortUrl/Model/Validation/ShortUrlsParamsInputFilter.php b/module/Core/src/ShortUrl/Model/Validation/ShortUrlsParamsInputFilter.php index 1f44db48..7d29607c 100644 --- a/module/Core/src/ShortUrl/Model/Validation/ShortUrlsParamsInputFilter.php +++ b/module/Core/src/ShortUrl/Model/Validation/ShortUrlsParamsInputFilter.php @@ -48,9 +48,9 @@ class ShortUrlsParamsInputFilter extends InputFilter $this->add(InputFactory::numeric(self::ITEMS_PER_PAGE, Paginator::ALL_ITEMS)); $this->add(InputFactory::tags(self::TAGS)); - $this->add(InputFactory::tags(self::EXCLUDE_TAGS)); - $this->add($this->createTagsModeInput(self::TAGS_MODE)); + + $this->add(InputFactory::tags(self::EXCLUDE_TAGS)); $this->add($this->createTagsModeInput(self::EXCLUDE_TAGS_MODE)); $this->add(InputFactory::orderBy(self::ORDER_BY, enumValues(OrderableField::class)));