mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-14 04:00:57 +03:00
Added Create and Delete tag actions
This commit is contained in:
parent
6717102dd2
commit
b2d9f2fc01
10 changed files with 286 additions and 11 deletions
|
@ -31,7 +31,65 @@
|
|||
},
|
||||
"examples": {
|
||||
"application/json": {
|
||||
"shortUrls": {
|
||||
"tags": {
|
||||
"data": [
|
||||
"games",
|
||||
"php",
|
||||
"shlink",
|
||||
"tech"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Unexpected error.",
|
||||
"schema": {
|
||||
"$ref": "../definitions/Error.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"Tags"
|
||||
],
|
||||
"summary": "Create tags",
|
||||
"description": "Provided a list of tags, creates all that do not yet exist",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "../parameters/Authorization.json"
|
||||
},
|
||||
{
|
||||
"name": "tags[]",
|
||||
"in": "formData",
|
||||
"description": "The list of tag names to create",
|
||||
"required": true,
|
||||
"type": "array"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The list of tags",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tags": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"application/json": {
|
||||
"tags": {
|
||||
"data": [
|
||||
"games",
|
||||
"php",
|
||||
|
|
|
@ -3,13 +3,14 @@ namespace Shlinkio\Shlink\Core\Entity;
|
|||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Shlinkio\Shlink\Common\Entity\AbstractEntity;
|
||||
use Shlinkio\Shlink\Core\Repository\TagRepository;
|
||||
|
||||
/**
|
||||
* Class Tag
|
||||
* @author
|
||||
* @link
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @ORM\Entity(repositoryClass=TagRepository::class)
|
||||
* @ORM\Table(name="tags")
|
||||
*/
|
||||
class Tag extends AbstractEntity implements \JsonSerializable
|
||||
|
|
29
module/Core/src/Repository/TagRepository.php
Normal file
29
module/Core/src/Repository/TagRepository.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Shlinkio\Shlink\Core\Entity\Tag;
|
||||
|
||||
class TagRepository extends EntityRepository implements TagRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Delete the tags identified by provided names
|
||||
*
|
||||
* @param array $names
|
||||
* @return int The number of affected entries
|
||||
*/
|
||||
public function deleteByName(array $names)
|
||||
{
|
||||
if (empty($names)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb->delete(Tag::class, 't')
|
||||
->where($qb->expr()->in('t.name', $names));
|
||||
|
||||
return $qb->getQuery()->execute();
|
||||
}
|
||||
}
|
17
module/Core/src/Repository/TagRepositoryInterface.php
Normal file
17
module/Core/src/Repository/TagRepositoryInterface.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Repository;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectRepository;
|
||||
|
||||
interface TagRepositoryInterface extends ObjectRepository
|
||||
{
|
||||
/**
|
||||
* Delete the tags identified by provided names
|
||||
*
|
||||
* @param array $names
|
||||
* @return int The number of affected entries
|
||||
*/
|
||||
public function deleteByName(array $names);
|
||||
}
|
|
@ -2,11 +2,16 @@
|
|||
namespace Shlinkio\Shlink\Core\Service\Tag;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation as DI;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Shlinkio\Shlink\Core\Entity\Tag;
|
||||
use Shlinkio\Shlink\Core\Repository\TagRepository;
|
||||
use Shlinkio\Shlink\Core\Util\TagManagerTrait;
|
||||
|
||||
class TagService implements TagServiceInterface
|
||||
{
|
||||
use TagManagerTrait;
|
||||
|
||||
/**
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
|
@ -31,4 +36,29 @@ class TagService implements TagServiceInterface
|
|||
{
|
||||
return $this->em->getRepository(Tag::class)->findBy([], ['name' => 'ASC']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tagNames
|
||||
* @return void
|
||||
*/
|
||||
public function deleteTags(array $tagNames)
|
||||
{
|
||||
/** @var TagRepository $repo */
|
||||
$repo = $this->em->getRepository(Tag::class);
|
||||
$repo->deleteByName($tagNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provided a list of tag names, creates all that do not exist yet
|
||||
*
|
||||
* @param string[] $tagNames
|
||||
* @return Collection|Tag[]
|
||||
*/
|
||||
public function createTags(array $tagNames)
|
||||
{
|
||||
$tags = $this->tagNamesToEntities($this->em, $tagNames);
|
||||
$this->em->flush();
|
||||
|
||||
return $tags;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
namespace Shlinkio\Shlink\Core\Service\Tag;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Shlinkio\Shlink\Core\Entity\Tag;
|
||||
|
||||
interface TagServiceInterface
|
||||
|
@ -9,4 +10,18 @@ interface TagServiceInterface
|
|||
* @return Tag[]
|
||||
*/
|
||||
public function listTags();
|
||||
|
||||
/**
|
||||
* @param string[] $tagNames
|
||||
* @return void
|
||||
*/
|
||||
public function deleteTags(array $tagNames);
|
||||
|
||||
/**
|
||||
* Provided a list of tag names, creates all that do not exist yet
|
||||
*
|
||||
* @param string[] $tagNames
|
||||
* @return Collection|Tag[]
|
||||
*/
|
||||
public function createTags(array $tagNames);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ return [
|
|||
Action\ListShortcodesAction::class => AnnotatedFactory::class,
|
||||
Action\EditShortcodeTagsAction::class => AnnotatedFactory::class,
|
||||
Action\Tag\ListTagsAction::class => AnnotatedFactory::class,
|
||||
Action\Tag\DeleteTagsAction::class => AnnotatedFactory::class,
|
||||
Action\Tag\CreateTagsAction::class => AnnotatedFactory::class,
|
||||
|
||||
Middleware\BodyParserMiddleware::class => AnnotatedFactory::class,
|
||||
Middleware\CrossDomainMiddleware::class => InvokableFactory::class,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
use Shlinkio\Shlink\Rest\Action;
|
||||
use Fig\Http\Message\RequestMethodInterface as RequestMethod;
|
||||
|
||||
return [
|
||||
|
||||
|
@ -8,7 +9,7 @@ return [
|
|||
'name' => Action\AuthenticateAction::class,
|
||||
'path' => '/rest/v{version:1}/authenticate',
|
||||
'middleware' => Action\AuthenticateAction::class,
|
||||
'allowed_methods' => ['POST'],
|
||||
'allowed_methods' => [RequestMethod::METHOD_POST],
|
||||
],
|
||||
|
||||
// Short codes
|
||||
|
@ -16,25 +17,25 @@ return [
|
|||
'name' => Action\CreateShortcodeAction::class,
|
||||
'path' => '/rest/v{version:1}/short-codes',
|
||||
'middleware' => Action\CreateShortcodeAction::class,
|
||||
'allowed_methods' => ['POST'],
|
||||
'allowed_methods' => [RequestMethod::METHOD_POST],
|
||||
],
|
||||
[
|
||||
'name' => Action\ResolveUrlAction::class,
|
||||
'path' => '/rest/v{version:1}/short-codes/{shortCode}',
|
||||
'middleware' => Action\ResolveUrlAction::class,
|
||||
'allowed_methods' => ['GET'],
|
||||
'allowed_methods' => [RequestMethod::METHOD_GET],
|
||||
],
|
||||
[
|
||||
'name' => Action\ListShortcodesAction::class,
|
||||
'path' => '/rest/v{version:1}/short-codes',
|
||||
'middleware' => Action\ListShortcodesAction::class,
|
||||
'allowed_methods' => ['GET'],
|
||||
'allowed_methods' => [RequestMethod::METHOD_GET],
|
||||
],
|
||||
[
|
||||
'name' => Action\EditShortcodeTagsAction::class,
|
||||
'path' => '/rest/v{version:1}/short-codes/{shortCode}/tags',
|
||||
'middleware' => Action\EditShortcodeTagsAction::class,
|
||||
'allowed_methods' => ['PUT'],
|
||||
'allowed_methods' => [RequestMethod::METHOD_PUT],
|
||||
],
|
||||
|
||||
// Visits
|
||||
|
@ -42,15 +43,27 @@ return [
|
|||
'name' => Action\GetVisitsAction::class,
|
||||
'path' => '/rest/v{version:1}/short-codes/{shortCode}/visits',
|
||||
'middleware' => Action\GetVisitsAction::class,
|
||||
'allowed_methods' => ['GET'],
|
||||
'allowed_methods' => [RequestMethod::METHOD_GET],
|
||||
],
|
||||
|
||||
// Tags
|
||||
[
|
||||
'name' => Action\ListTagsAction::class,
|
||||
'name' => Action\Tag\ListTagsAction::class,
|
||||
'path' => '/rest/v{version:1}/tags',
|
||||
'middleware' => Action\ListTagsAction::class,
|
||||
'allowed_methods' => ['GET'],
|
||||
'middleware' => Action\Tag\ListTagsAction::class,
|
||||
'allowed_methods' => [RequestMethod::METHOD_GET],
|
||||
],
|
||||
[
|
||||
'name' => Action\Tag\DeleteTagsAction::class,
|
||||
'path' => '/rest/v{version:1}/tags',
|
||||
'middleware' => Action\Tag\DeleteTagsAction::class,
|
||||
'allowed_methods' => [RequestMethod::METHOD_DELETE],
|
||||
],
|
||||
[
|
||||
'name' => Action\Tag\CreateTagsAction::class,
|
||||
'path' => '/rest/v{version:1}/tags',
|
||||
'middleware' => Action\Tag\CreateTagsAction::class,
|
||||
'allowed_methods' => [RequestMethod::METHOD_POST],
|
||||
],
|
||||
],
|
||||
|
||||
|
|
57
module/Rest/src/Action/Tag/CreateTagsAction.php
Normal file
57
module/Rest/src/Action/Tag/CreateTagsAction.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Rest\Action\Tag;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation as DI;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Core\Service\Tag\TagService;
|
||||
use Shlinkio\Shlink\Core\Service\Tag\TagServiceInterface;
|
||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
|
||||
class CreateTagsAction extends AbstractRestAction
|
||||
{
|
||||
/**
|
||||
* @var TagServiceInterface
|
||||
*/
|
||||
private $tagService;
|
||||
|
||||
/**
|
||||
* CreateTagsAction constructor.
|
||||
* @param TagServiceInterface $tagService
|
||||
* @param LoggerInterface|null $logger
|
||||
*
|
||||
* @DI\Inject({TagService::class, LoggerInterface::class})
|
||||
*/
|
||||
public function __construct(TagServiceInterface $tagService, LoggerInterface $logger = null)
|
||||
{
|
||||
parent::__construct($logger);
|
||||
$this->tagService = $tagService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
$body = $request->getParsedBody();
|
||||
$tags = isset($body['tags']) ? $body['tags'] : [];
|
||||
|
||||
return new JsonResponse([
|
||||
'tags' => [
|
||||
'data' => $this->tagService->createTags($tags)->toArray(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
53
module/Rest/src/Action/Tag/DeleteTagsAction.php
Normal file
53
module/Rest/src/Action/Tag/DeleteTagsAction.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Rest\Action\Tag;
|
||||
|
||||
use Acelaya\ZsmAnnotatedServices\Annotation as DI;
|
||||
use Interop\Http\ServerMiddleware\DelegateInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Shlinkio\Shlink\Core\Service\Tag\TagService;
|
||||
use Shlinkio\Shlink\Core\Service\Tag\TagServiceInterface;
|
||||
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class DeleteTagsAction extends AbstractRestAction
|
||||
{
|
||||
/**
|
||||
* @var TagServiceInterface
|
||||
*/
|
||||
private $tagService;
|
||||
|
||||
/**
|
||||
* DeleteTagsAction constructor.
|
||||
* @param TagServiceInterface $tagService
|
||||
* @param LoggerInterface|null $logger
|
||||
*
|
||||
* @DI\Inject({TagService::class, LoggerInterface::class})
|
||||
*/
|
||||
public function __construct(TagServiceInterface $tagService, LoggerInterface $logger = null)
|
||||
{
|
||||
parent::__construct($logger);
|
||||
$this->tagService = $tagService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param DelegateInterface $delegate
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
|
||||
{
|
||||
$query = $request->getQueryParams();
|
||||
$tags = isset($query['tags']) ? $query['tags'] : [];
|
||||
|
||||
$this->tagService->deleteTags($tags);
|
||||
return new EmptyResponse();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue