summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Weipert <code@drogueronin.de>2022-01-14 18:21:36 +0100
committerDaniel Weipert <code@drogueronin.de>2022-01-14 18:21:36 +0100
commit4cacc94240944ff316104bfd1b5e8e00fad14517 (patch)
tree2559dc3aa121d70bd645ff0a2fe56e1ae0695daa /src
parent9c0893cb65df986b9edf0f48a6d4d2d65f27b8ef (diff)
Add Artworks, Votes and better routing
Diffstat (limited to 'src')
-rw-r--r--src/Controller/Card.php42
-rw-r--r--src/Controller/Home.php11
-rw-r--r--src/Model/Artwork.php101
-rw-r--r--src/Model/Card.php49
-rw-r--r--src/Model/Vote.php30
-rw-r--r--src/Model/VoteArtwork.php26
-rw-r--r--src/Model/VoteCard.php26
-rw-r--r--src/Router.php81
8 files changed, 330 insertions, 36 deletions
diff --git a/src/Controller/Card.php b/src/Controller/Card.php
index 39560bb..d4ee393 100644
--- a/src/Controller/Card.php
+++ b/src/Controller/Card.php
@@ -3,8 +3,12 @@
namespace Elements\Controller;
use Elements\DB;
+use Elements\Model\Artwork;
use Elements\Model\Card as CardModel;
use Elements\Model\CardMeta;
+use Elements\Model\VoteArtwork;
+use Elements\Model\VoteCard;
+use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -21,11 +25,49 @@ class Card
DB::save($meta);
}
+ /**@var UploadedFile[] $files*/
+ if ($files = $request->files->get('images')) {
+ foreach ($files as $file) {
+ $image = Artwork::fromUploadedFile($file);
+
+ /*TEST*/
+ for ($i = 0; $i <= rand(0, 40); $i++) {
+ $vote = new VoteArtwork();
+ $vote->value = rand(-1, 1) >= 0 ? 1 : -1;
+ $image->addVote($vote);
+ DB::save($vote);
+ }
+ /*TEST*/
+
+ $card->addArtwork($image);
+ DB::save($image);
+ }
+ }
+
+ /*TEST*/
+ for ($i = 0; $i <= rand(0, 60); $i++) {
+ $vote = new VoteCard();
+ $vote->value = rand(-1, 1) > 0 ? 1 : -1;
+ $card->addVote($vote);
+ DB::save($vote);
+ }
+ /*TEST*/
+
DB::save($card);
$response = new RedirectResponse('/');
return $response;
}
+
+ public static function get(Request $request)
+ {
+ $route = $request->attributes->get('route');
+ $cardId = $route['id'];
+
+ $card = DB::$entityManager->getRepository(CardModel::class)->find($cardId);
+
+ return $card->getMeta('name');
+ }
}
diff --git a/src/Controller/Home.php b/src/Controller/Home.php
index 511b89b..1c1500c 100644
--- a/src/Controller/Home.php
+++ b/src/Controller/Home.php
@@ -14,9 +14,18 @@ class Home
echo "<pre>";
$c && var_dump(
array_map(fn ($item) => [$item->key, $item->value], $c->meta->toArray()),
+ array_map(fn ($item) => "<img style='max-width: 100%;max-height:300px;' src='$item->path'> Votes: " . $item->getVotesTotal(), $c->artworks->toArray()),
+ array_map(fn ($item) => $item->value, $c->votes->toArray()),
+ 'Votes: ' . $c->getVotesTotal(),
);
- return Template::render('home.twig');
+ return Template::render('home.twig', [
+ 'fields' => [
+ 'name' => 'meta[name]',
+ 'converted mana cost' => 'meta[cmc]',
+ 'is uno reverse' => 'meta[is_uno_reverse]',
+ ],
+ ]);
}
}
diff --git a/src/Model/Artwork.php b/src/Model/Artwork.php
new file mode 100644
index 0000000..25f6ee5
--- /dev/null
+++ b/src/Model/Artwork.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace Elements\Model;
+
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\DBAL\Schema\Column;
+use Doctrine\DBAL\Schema\Table;
+use Doctrine\ORM\Mapping\Entity;
+use Doctrine\ORM\Mapping\GeneratedValue;
+use Doctrine\ORM\Mapping\Id;
+use Doctrine\ORM\Mapping\ManyToOne;
+use Doctrine\ORM\PersistentCollection;
+use Elements\DB;
+use Symfony\Component\HttpFoundation\File\UploadedFile;
+
+#[Entity]
+#[Table(name: 'artworks')]
+/**
+ * @Entity
+ * @Table(name="artworks")
+ */
+class Artwork
+{
+ #[Id]
+ #[Column(type: 'integer')]
+ #[GeneratedValue]
+ /**
+ * @Id
+ * @Column(type="integer")
+ * @GeneratedValue
+ */
+ public int $id;
+
+ #[Column(type: 'string')]
+ /**
+ * @Column(type="string")
+ */
+ public string $path;
+
+ #[ManyToOne(targetEntity: Card::class, inversedBy: 'artworks')]
+ /**
+ * @ManyToOne(targetEntity="Card", inversedBy="artworks", cascade={"persist"})
+ */
+ public Card $card;
+
+ #[OneToMany(targetEntity: VoteArtwork::class, mappedBy: 'artwork')]
+ /**
+ * @OneToMany(targetEntity="VoteArtwork", mappedBy="artwork")
+ */
+ public Collection|ArrayCollection|PersistentCollection $votes;
+
+ /**
+ * Artwork constructor.
+ */
+ public function __construct(string $path)
+ {
+ $this->path = $path;
+ $this->votes = new ArrayCollection();
+ }
+
+ /**
+ * @param UploadedFile $file
+ *
+ * @return self
+ */
+ public static function fromUploadedFile(UploadedFile $file): self
+ {
+ $artworksDir = dirname(dirname(__DIR__)) . '/public/artworks/';
+ $path = str_replace($_SERVER['DOCUMENT_ROOT'], '', $artworksDir . $file->getClientOriginalName());
+ $file->move($artworksDir, $file->getClientOriginalName());
+
+ return new self($path);
+ }
+
+ /**
+ * @param VoteArtwork $vote
+ */
+ public function addVote(VoteArtwork $vote)
+ {
+ $vote->artwork = $this;
+ $this->votes[] = $vote;
+ }
+
+ /**
+ * @return int
+ */
+ public function getVotesTotal(): int
+ {
+ $result = DB::$entityManager
+ ->createQuery(
+ 'SELECT sum(v.value) as total
+ FROM Elements\Model\VoteArtwork v
+ WHERE v.artwork = :artwork'
+ )
+ ->setParameter('artwork', $this)
+ ->getOneOrNullResult();
+
+ return $result['total'] ?? 0;
+ }
+}
+
diff --git a/src/Model/Card.php b/src/Model/Card.php
index ab421ab..9707e16 100644
--- a/src/Model/Card.php
+++ b/src/Model/Card.php
@@ -37,12 +37,26 @@ class Card
*/
public Collection|ArrayCollection|PersistentCollection $meta;
+ #[OneToMany(targetEntity: Artwork::class, mappedBy: 'card')]
+ /**
+ * @OneToMany(targetEntity="Artwork", mappedBy="card")
+ */
+ public Collection|ArrayCollection|PersistentCollection $artworks;
+
+ #[OneToMany(targetEntity: VoteCard::class, mappedBy: 'card')]
+ /**
+ * @OneToMany(targetEntity="VoteCard", mappedBy="card")
+ */
+ public Collection|ArrayCollection|PersistentCollection $votes;
+
/**
* Card constructor.
*/
public function __construct()
{
$this->meta = new ArrayCollection();
+ $this->artworks = new ArrayCollection();
+ $this->votes = new ArrayCollection();
}
/**
@@ -55,6 +69,24 @@ class Card
}
/**
+ * @param Artwork $artwork
+ */
+ public function addArtwork(Artwork $artwork)
+ {
+ $artwork->card = $this;
+ $this->artworks[] = $artwork;
+ }
+
+ /**
+ * @param VoteCard $vote
+ */
+ public function addVote(VoteCard $vote)
+ {
+ $vote->card = $this;
+ $this->votes[] = $vote;
+ }
+
+ /**
* @param string $key
*
* @return string
@@ -83,5 +115,22 @@ class Card
return $result['value'] ?? null;
}
+
+ /**
+ * @return int
+ */
+ public function getVotesTotal(): int
+ {
+ $result = DB::$entityManager
+ ->createQuery(
+ 'SELECT sum(v.value) as total
+ FROM Elements\Model\VoteCard v
+ WHERE v.card = :card'
+ )
+ ->setParameter('card', $this)
+ ->getOneOrNullResult();
+
+ return $result['total'] ?? 0;
+ }
}
diff --git a/src/Model/Vote.php b/src/Model/Vote.php
new file mode 100644
index 0000000..c5415aa
--- /dev/null
+++ b/src/Model/Vote.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Elements\Model;
+
+use Doctrine\DBAL\Schema\Column;
+use Doctrine\DBAL\Schema\Table;
+use Doctrine\ORM\Mapping\Entity;
+use Doctrine\ORM\Mapping\GeneratedValue;
+use Doctrine\ORM\Mapping\Id;
+use Doctrine\ORM\Mapping\ManyToOne;
+
+class Vote
+{
+ #[Id]
+ #[Column(type: 'integer')]
+ #[GeneratedValue]
+ /**
+ * @Id
+ * @Column(type="integer")
+ * @GeneratedValue
+ */
+ public int $id;
+
+ #[Column(type: 'integer')]
+ /**
+ * @Column(type="integer")
+ */
+ public int $value;
+}
+
diff --git a/src/Model/VoteArtwork.php b/src/Model/VoteArtwork.php
new file mode 100644
index 0000000..ee6ac8b
--- /dev/null
+++ b/src/Model/VoteArtwork.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Elements\Model;
+
+use Doctrine\DBAL\Schema\Column;
+use Doctrine\DBAL\Schema\Table;
+use Doctrine\ORM\Mapping\Entity;
+use Doctrine\ORM\Mapping\GeneratedValue;
+use Doctrine\ORM\Mapping\Id;
+use Doctrine\ORM\Mapping\ManyToOne;
+
+#[Entity]
+#[Table(name: 'votes_artwork')]
+/**
+ * @Entity
+ * @Table(name="votes_artwork")
+ */
+class VoteArtwork extends Vote
+{
+ #[ManyToOne(targetEntity: Artwork::class, inversedBy: 'votes')]
+ /**
+ * @ManyToOne(targetEntity="Artwork", inversedBy="votes", cascade={"persist"})
+ */
+ public Artwork $artwork;
+}
+
diff --git a/src/Model/VoteCard.php b/src/Model/VoteCard.php
new file mode 100644
index 0000000..e9b3e60
--- /dev/null
+++ b/src/Model/VoteCard.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Elements\Model;
+
+use Doctrine\DBAL\Schema\Column;
+use Doctrine\DBAL\Schema\Table;
+use Doctrine\ORM\Mapping\Entity;
+use Doctrine\ORM\Mapping\GeneratedValue;
+use Doctrine\ORM\Mapping\Id;
+use Doctrine\ORM\Mapping\ManyToOne;
+
+#[Entity]
+#[Table(name: 'votes_card')]
+/**
+ * @Entity
+ * @Table(name="votes_card")
+ */
+class VoteCard extends Vote
+{
+ #[ManyToOne(targetEntity: Card::class, inversedBy: 'votes')]
+ /**
+ * @ManyToOne(targetEntity="Card", inversedBy="votes", cascade={"persist"})
+ */
+ public Card $card;
+}
+
diff --git a/src/Router.php b/src/Router.php
index 377c00b..5635d5c 100644
--- a/src/Router.php
+++ b/src/Router.php
@@ -7,64 +7,75 @@ use Elements\Controller\Home;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCollection;
class Router
{
- private $routes = [
- 'GET' => [
- '/' => [Home::class, 'index'],
- ],
-
- 'POST' => [
- '/card/add' => [Card::class, 'add'],
- ],
- ];
+ private ?RouteCollection $routes;
+ private array $routeFunctions = [];
/**
* Router constructor.
*/
public function __construct()
{
+ /**@var Request $request*/
$request = Request::createFromGlobals();
$response = new Response();
- $method = $request->getMethod();
- $path = $request->getPathInfo();
+ $this->routes = new RouteCollection();
+ $this->addRoute('GET', '/', [Home::class, 'index']);
+ $this->addRoute('GET', '/card/{id}', [Card::class, 'get']);
+ $this->addRoute('POST', '/card/add', [Card::class, 'add']);
+
+ $context = new RequestContext();
+ $context->fromRequest($request);
+ $matcher = new UrlMatcher($this->routes, $context);
- // if the route is defined
- if (isset($this->routes[$method][$path])) {
- try {
- // run controller function
- $content = call_user_func($this->routes[$method][$path], $request);
+ try {
+ $match = $matcher->match($request->getPathInfo());
+ $request->attributes->set('route', $match);
- // set response to new response
- if ($content instanceof Response) {
- $response = $content;
- }
+ // run controller function
+ $content = call_user_func($this->routeFunctions[$match['_route']], $request);
- // set content directly otherwise
- else {
- $response->setContent($content);
- }
+ // set response to new response
+ if ($content instanceof Response) {
+ $response = $content;
}
- // catch any errors
- catch (AppException $exception) {
- $response->setStatusCode($exception->getCode());
- $response->setContent($exception->getMessage());
- } catch (\Exception $exception) {
- $response->setStatusCode(Response::HTTP_BAD_REQUEST);
- $response->setContent($exception->getMessage());
+ // set content directly otherwise
+ else {
+ $response->setContent($content);
}
}
- // route is not defined
- else {
- $response->setStatusCode(Response::HTTP_NOT_FOUND);
- $response->setContent('Not Found');
+ // catch any errors
+ catch (AppException $exception) {
+ $response->setStatusCode($exception->getCode());
+ $response->setContent($exception->getMessage());
+ } catch (\Exception $exception) {
+ $response->setStatusCode(Response::HTTP_BAD_REQUEST);
+ $response->setContent($exception->getMessage());
}
$response->send();
}
+
+ /**
+ * @param string|array $methods
+ * @param string $path
+ * @param callable $function
+ */
+ public function addRoute(string|array $methods, string $path, array $function)
+ {
+ $name = "$function[0]::$function[1]";
+
+ $this->routes->add($name, new Route($path, methods: (array)$methods));
+ $this->routeFunctions[$name] = $function;
+ }
}