diff --git a/migrations/Version20250510142748.php b/migrations/Version20250510142748.php
new file mode 100644
index 0000000..76c46e1
--- /dev/null
+++ b/migrations/Version20250510142748.php
@@ -0,0 +1,44 @@
+addSql(<<<'SQL'
+ ALTER TABLE snip DROP INDEX IDX_FEBD97966A1E45F3, ADD UNIQUE INDEX UNIQ_FEBD97966A1E45F3 (active_version_id)
+ SQL);
+ $this->addSql(<<<'SQL'
+ ALTER TABLE snip ADD archived TINYINT(1) NOT NULL
+ SQL);
+ $this->addSql(<<<'SQL'
+ UPDATE snip SET archived = 0
+ SQL);
+ }
+
+ public function down(Schema $schema): void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->addSql(<<<'SQL'
+ ALTER TABLE snip DROP INDEX UNIQ_FEBD97966A1E45F3, ADD INDEX IDX_FEBD97966A1E45F3 (active_version_id)
+ SQL);
+ $this->addSql(<<<'SQL'
+ ALTER TABLE snip DROP archived
+ SQL);
+ }
+}
diff --git a/src/Controller/SnipController.php b/src/Controller/SnipController.php
index 9316153..418229b 100644
--- a/src/Controller/SnipController.php
+++ b/src/Controller/SnipController.php
@@ -151,4 +151,19 @@ class SnipController extends AbstractController
'form' => $form->createView(),
]);
}
+
+ #[Route('/archive/{snip}', name: '_archive')]
+ public function archive(Snip $snip): Response
+ {
+ $this->denyAccessUnlessGranted(SnipVoter::EDIT, $snip);
+ $snip->setArchived(!$snip->isArchived());
+ $this->repository->save($snip);
+ if ($snip->isArchived()) {
+ $this->addFlash('success', sprintf('Snip "%s" archived', $snip));
+ } else {
+ $this->addFlash('success', sprintf('Snip "%s" unarchived', $snip));
+ }
+
+ return $this->redirectToRoute('snip_single', ['snip' => $snip->getId()]);
+ }
}
\ No newline at end of file
diff --git a/src/Dto/SnipFilterRequest.php b/src/Dto/SnipFilterRequest.php
index 9326b91..e9b8dae 100644
--- a/src/Dto/SnipFilterRequest.php
+++ b/src/Dto/SnipFilterRequest.php
@@ -7,6 +7,7 @@ readonly class SnipFilterRequest implements CachableDtoInterface
public const string VISIBILITY_ALL = 'all';
public const string VISIBILITY_VISIBLE = 'visible';
public const string VISIBILITY_HIDDEN = 'hidden';
+ public const string VISIBILITY_ARCHIVED = 'archived';
public const string SORT_NAME = 'name';
public const string SORT_DATE = 'date';
diff --git a/src/Entity/Snip.php b/src/Entity/Snip.php
index ca38fa4..4a559d7 100644
--- a/src/Entity/Snip.php
+++ b/src/Entity/Snip.php
@@ -36,6 +36,9 @@ class Snip
#[ORM\Column]
private bool $visible = true;
+ #[ORM\Column]
+ private bool $archived = false;
+
public function __construct()
{
$this->snipContents = new ArrayCollection();
@@ -145,4 +148,16 @@ class Snip
return $this;
}
+
+ public function isArchived(): ?bool
+ {
+ return $this->archived;
+ }
+
+ public function setArchived(bool $archived): static
+ {
+ $this->archived = $archived;
+
+ return $this;
+ }
}
diff --git a/src/Repository/SnipRepository.php b/src/Repository/SnipRepository.php
index 71cf64f..0326184 100644
--- a/src/Repository/SnipRepository.php
+++ b/src/Repository/SnipRepository.php
@@ -50,6 +50,7 @@ class SnipRepository extends ServiceEntityRepository
->setParameter('user', $user)
;
+ $showArchived = false;
switch ($request->visibility) {
case SnipFilterRequest::VISIBILITY_ALL:
break;
@@ -59,9 +60,13 @@ class SnipRepository extends ServiceEntityRepository
case SnipFilterRequest::VISIBILITY_HIDDEN:
$qb->andWhere('s.visible = false');
break;
+ case SnipFilterRequest::VISIBILITY_ARCHIVED:
+ $showArchived = true;
+ break;
default:
throw new \InvalidArgumentException('Invalid visibility option: ', $request->visibility);
}
+ $qb->andWhere('s.archived = ' . ($showArchived ? 'true' : 'false'));
switch ($request->sort) {
case SnipFilterRequest::SORT_NAME:
@@ -73,6 +78,7 @@ class SnipRepository extends ServiceEntityRepository
default:
throw new \InvalidArgumentException('Invalid sort option: ', $request->sort);
}
+
return $qb->getQuery()->getResult();
}
@@ -82,6 +88,7 @@ class SnipRepository extends ServiceEntityRepository
->createQueryBuilder('s')
->where('s.public = true')
->andWhere('s.visible = true')
+ ->andWhere('s.archived = false')
->orderBy('s.createdAt', 'DESC')
;
diff --git a/templates/snip/badge.html.twig b/templates/snip/badge.html.twig
index 18dcb61..9169691 100644
--- a/templates/snip/badge.html.twig
+++ b/templates/snip/badge.html.twig
@@ -16,4 +16,10 @@
+{% endif %}
+
+{% if snip.archived %}
+
+ Archived
+
{% endif %}
\ No newline at end of file
diff --git a/templates/snip/index.html.twig b/templates/snip/index.html.twig
index 2c275ac..2e1e74c 100644
--- a/templates/snip/index.html.twig
+++ b/templates/snip/index.html.twig
@@ -33,11 +33,11 @@
{% endfor %}
-
+