* image upload handling

* old static image migrator implementation as cli command
* auth id fix, renew works now
* templates refactored to work with uploaded images
This commit is contained in:
Danyi Dávid 2018-05-13 22:34:15 +02:00
parent 26c74ec238
commit c4438f7e8c
20 changed files with 532 additions and 20 deletions

View File

@ -8,5 +8,9 @@ return [
'api.auth.login', 'api.auth.login',
'api.ping', 'api.ping',
], ],
'unguarded_paths' => [
'/api/awardee-image',
'/api/judge-image',
],
], ],
]; ];

View File

@ -44,10 +44,22 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
'api.judges' 'api.judges'
); );
$app->route( $app->route(
'/api/awardee[/{id:\d+}]', '/api/awardee[/{id:\d+}]',
App\Handler\Api\AwardeeHandler::class, App\Handler\Api\AwardeeHandler::class,
['GET','POST','PUT','DELETE'], ['GET','POST','PUT','DELETE'],
'api.awardees' 'api.awardees'
);
$app->route(
'/api/judge-image/{slug}',
App\Handler\Api\JudgeImageHandler::class,
['GET','POST','DELETE'],
'api.judge-image'
);
$app->route(
'/api/awardee-image/{type:profile|award}/{slug}',
App\Handler\Api\AwardeeImageHandler::class,
['GET','POST','DELETE'],
'api.awardee-image'
); );
$app->get('/the-prize', App\Handler\PrizeRedirectHandler::class, 'the-prize'); $app->get('/the-prize', App\Handler\PrizeRedirectHandler::class, 'the-prize');
@ -57,7 +69,6 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
'the-prize.article' 'the-prize.article'
); );
// $app->get('/judges', App\Handler\JudgesHandler::class, 'judges');
$app->get('/awards', App\Handler\AwardeeRedirectHandler::class, 'awardees'); $app->get('/awards', App\Handler\AwardeeRedirectHandler::class, 'awardees');
$app->get('/awards/{year:\d+}', App\Handler\AwardeeHandler::class, 'awardees-by-year'); $app->get('/awards/{year:\d+}', App\Handler\AwardeeHandler::class, 'awardees-by-year');
$app->get('/awardee/{slug}', App\Handler\ProfileHandler::class, 'awardee'); $app->get('/awardee/{slug}', App\Handler\ProfileHandler::class, 'awardee');

View File

@ -504,10 +504,12 @@ section.awardee {
"content content"; "content content";
} }
section.awardee ol,
section.awardee ul { section.awardee ul {
padding-left: 1.5em; padding-left: 1.5em;
} }
section.awardee ol > li,
section.awardee ul > li { section.awardee ul > li {
margin-bottom: 10px; margin-bottom: 10px;
} }

View File

@ -0,0 +1,66 @@
<?php
namespace App\Command;
use App\Service\AwardeeManager;
use App\Service\JudgeManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MigrateImages extends Command
{
/** @var AwardeeManager */
private $awardeeManager;
/** @var JudgeManager */
private $judgeManager;
public function __construct(AwardeeManager $awardeeManager, JudgeManager $judgeManager)
{
$this->awardeeManager = $awardeeManager;
$this->judgeManager = $judgeManager;
parent::__construct();
}
protected function configure()
{
$this->setName('image:migrate')
->setDescription('Migrate images from old format to new');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->write("Migrating awardee images ...");
$awardees = $this->awardeeManager->getAwardees();
$this->awardeeManager->ensureImageDirectoryExists();
foreach ($awardees as $awardee) {
if ($awardee->hasLegacyProfileImage() && !$awardee->hasProfileImage()) {
link(
sprintf('public/img/awardees/%s.jpg', $awardee->getSlug()),
sprintf('%s/%s-profile.jpg',AwardeeManager::IMAGE_DIRECTORY, $awardee->getId())
);
}
if ($awardee->hasLegacyAwardImage() && !$awardee->hasAwardImage()) {
link(
sprintf('public/img/awardees/%s-atadas.jpg', $awardee->getSlug()),
sprintf('%s/%s-award.jpg',AwardeeManager::IMAGE_DIRECTORY, $awardee->getId())
);
}
}
$output->writeln("done.");
$output->write("Migrating judge images ...");
$judges = $this->judgeManager->getJudges();
$this->judgeManager->ensureImageDirectoryExists();
foreach ($judges as $judge) {
if ($judge->hasLegacyProfileImage() && !$judge->hasProfileImage()) {
link(
sprintf('public/img/judges/%s.jpg', $judge->getSlug()),
sprintf('%s/%s.jpg',JudgeManager::IMAGE_DIRECTORY, $judge->getId())
);
}
}
$output->writeln("done.");
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Command;
use App\Service\AwardeeManager;
use App\Service\JudgeManager;
use Psr\Container\ContainerInterface;
class MigrateImagesFactory
{
/**
* @param ContainerInterface $container
* @return MigrateImages
*/
public function __invoke(ContainerInterface $container): MigrateImages
{
$awardeeManager = $container->get(AwardeeManager::class);
$judgeManager = $container->get(JudgeManager::class);
return new MigrateImages($awardeeManager, $judgeManager);
}
}

View File

@ -23,6 +23,7 @@ class ConfigProvider
return [ return [
'dependencies' => $this->getDependencies(), 'dependencies' => $this->getDependencies(),
'templates' => $this->getTemplates(), 'templates' => $this->getTemplates(),
'console' => $this->getConsoleCommands(),
]; ];
} }
@ -36,6 +37,8 @@ class ConfigProvider
Handler\PingHandler::class => Handler\PingHandler::class, Handler\PingHandler::class => Handler\PingHandler::class,
], ],
'factories' => [ 'factories' => [
Command\MigrateImages::class => Command\MigrateImagesFactory::class,
Handler\HomePageHandler::class => Handler\HomePageHandlerFactory::class, Handler\HomePageHandler::class => Handler\HomePageHandlerFactory::class,
Handler\ArticleHandler::class => Handler\ArticleHandlerFactory::class, Handler\ArticleHandler::class => Handler\ArticleHandlerFactory::class,
Handler\AwardeeHandler::class => Handler\AwardeeHandlerFactory::class, Handler\AwardeeHandler::class => Handler\AwardeeHandlerFactory::class,
@ -45,7 +48,9 @@ class ConfigProvider
Handler\PrizeRedirectHandler::class => Handler\PrizeRedirectHandlerFactory::class, Handler\PrizeRedirectHandler::class => Handler\PrizeRedirectHandlerFactory::class,
Handler\Api\AwardeeHandler::class => Handler\Api\AwardeeHandlerFactory::class, Handler\Api\AwardeeHandler::class => Handler\Api\AwardeeHandlerFactory::class,
Handler\Api\AwardeeImageHandler::class => Handler\Api\AwardeeImageHandlerFactory::class,
Handler\Api\JudgesHandler::class => Handler\Api\JudgesHandlerFactory::class, Handler\Api\JudgesHandler::class => Handler\Api\JudgesHandlerFactory::class,
Handler\Api\JudgeImageHandler::class => Handler\Api\JudgeImageHandlerFactory::class,
Handler\Api\YearsHandler::class => Handler\Api\YearsHandlerFactory::class, Handler\Api\YearsHandler::class => Handler\Api\YearsHandlerFactory::class,
Plates\StringExtension::class => Plates\StringExtensionFactory::class, Plates\StringExtension::class => Plates\StringExtensionFactory::class,
@ -71,4 +76,13 @@ class ConfigProvider
], ],
]; ];
} }
public function getConsoleCommands(): array
{
return [
'commands' => [
Command\MigrateImages::class,
]
];
}
} }

View File

@ -3,6 +3,7 @@
namespace App\Entity; namespace App\Entity;
use App\Service\AwardeeManager;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo; use Gedmo\Mapping\Annotation as Gedmo;
use JsonSerializable; use JsonSerializable;
@ -15,6 +16,7 @@ use JsonSerializable;
* @ORM\Index(name="a_name_idx", columns={"name"}) * @ORM\Index(name="a_name_idx", columns={"name"})
* } * }
* ) * )
* @ORM\HasLifecycleCallbacks
*/ */
class Awardee implements JsonSerializable class Awardee implements JsonSerializable
{ {
@ -45,7 +47,7 @@ class Awardee implements JsonSerializable
private $text; private $text;
/** /**
* @ORM\Column(name="image_label", type="string", length=255, unique=true) * @ORM\Column(name="image_label", type="string", length=255)
* @var string * @var string
*/ */
private $imageLabel; private $imageLabel;
@ -165,6 +167,51 @@ class Awardee implements JsonSerializable
return $this; return $this;
} }
/**
* @return bool
*/
public function hasProfileImage(): bool
{
return file_exists(sprintf('%s/%s-profile.jpg', AwardeeManager::IMAGE_DIRECTORY, $this->getId()));
}
/**
* @return bool
*/
public function hasLegacyProfileImage(): bool
{
return file_exists(sprintf('public/img/awardees/%s.jpg', $this->getSlug()));
}
/**
* @return bool
*/
public function hasAwardImage(): bool
{
return file_exists(sprintf('%s/%s-award.jpg', AwardeeManager::IMAGE_DIRECTORY, $this->getId()));
}
/**
* @return bool
*/
public function hasLegacyAwardImage(): bool
{
return file_exists(sprintf('public/img/awardees/%s-atadas.jpg', $this->getSlug()));
}
/**
* @ORM\PreRemove
*/
public function cleanUpImagesBeforeDelete()
{
if ($this->hasProfileImage()) {
unlink(sprintf('%s/%s-profile.jpg', AwardeeManager::IMAGE_DIRECTORY, $this->getId()));
}
if ($this->hasAwardImage()) {
unlink(sprintf('%s/%s-award.jpg', AwardeeManager::IMAGE_DIRECTORY, $this->getId()));
}
}
/** /**
* @return array * @return array
*/ */
@ -177,6 +224,8 @@ class Awardee implements JsonSerializable
'text' => $this->getText(), 'text' => $this->getText(),
'imageLabel' => $this->getImageLabel(), 'imageLabel' => $this->getImageLabel(),
'slug' => $this->getSlug(), 'slug' => $this->getSlug(),
'hasProfileImage' => $this->hasProfileImage(),
'hasAwardImage' => $this->hasAwardImage(),
]; ];
} }
} }

View File

@ -3,6 +3,7 @@
namespace App\Entity; namespace App\Entity;
use App\Service\JudgeManager;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
@ -17,6 +18,7 @@ use JsonSerializable;
* @ORM\Index(name="j_name_idx", columns={"name"}) * @ORM\Index(name="j_name_idx", columns={"name"})
* } * }
* ) * )
* @ORM\HasLifecycleCallbacks
*/ */
class Judge implements JsonSerializable class Judge implements JsonSerializable
{ {
@ -198,6 +200,26 @@ class Judge implements JsonSerializable
return $this; return $this;
} }
public function hasProfileImage(): bool
{
return file_exists(sprintf('%s/%s.jpg', JudgeManager::IMAGE_DIRECTORY, $this->getId()));
}
public function hasLegacyProfileImage(): bool
{
return file_exists(sprintf('public/img/judges/%s.jpg', $this->getSlug()));
}
/**
* @ORM\PreRemove
*/
public function cleanUpImagesBeforeDelete()
{
if ($this->hasProfileImage()) {
unlink(sprintf('%s/%s.jpg', JudgeManager::IMAGE_DIRECTORY, $this->getId()));
}
}
/** /**
* @return array * @return array
*/ */
@ -209,6 +231,7 @@ class Judge implements JsonSerializable
'prefix' => $this->getPrefix(), 'prefix' => $this->getPrefix(),
'titles' => $this->getTitles()->getValues(), 'titles' => $this->getTitles()->getValues(),
'slug' => $this->getSlug(), 'slug' => $this->getSlug(),
'hasProfileImage' => $this->hasProfileImage(),
]; ];
} }
} }

View File

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace App\Handler\Api;
use App\Service\AwardeeManager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UploadedFileInterface;
use UtilityModule\Handler\AbstractCrudHandler;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\Response\TextResponse;
class AwardeeImageHandler extends AbstractCrudHandler
{
const IDENTIFIER_NAME = 'slug';
/** @var AwardeeManager */
private $awardeeManager;
public function __construct(
AwardeeManager $awardeeManager
) {
$this->awardeeManager = $awardeeManager;
}
/**
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function get(ServerRequestInterface $request): ResponseInterface
{
$slug = $request->getAttribute(static::IDENTIFIER_NAME);
$type = $request->getAttribute('type');
$imageResponse = new TextResponse($this->awardeeManager->getProfileImage($slug, $type));
return $imageResponse
->withHeader('Content-Type', 'image/jpeg')
->withHeader('Cache-Control', 'must-revalidate')
;
}
/**
* @param ServerRequestInterface $request
* @return JsonResponse
*/
public function create(ServerRequestInterface $request): ResponseInterface
{
$slug = $request->getAttribute(static::IDENTIFIER_NAME);
$type = $request->getAttribute('type');
/** @var UploadedFileInterface[] $files */
$files = $request->getUploadedFiles();
$imageData = $files['image']->getStream()->getContents();
$entity = $this->awardeeManager->setProfileImage($slug, $imageData, $type);
return new JsonResponse($entity);
}
/**
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function delete(ServerRequestInterface $request): ResponseInterface
{
$slug = $request->getAttribute(static::IDENTIFIER_NAME);
$type = $request->getAttribute('type');
return new JsonResponse($this->awardeeManager->deleteProfileImage($slug, $type));
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\Handler\Api;
use App\Service\AwardeeManager;
use Psr\Container\ContainerInterface;
use Psr\Http\Server\RequestHandlerInterface;
class AwardeeImageHandlerFactory
{
public function __invoke(ContainerInterface $container): RequestHandlerInterface
{
$awardeeManager = $container->get(AwardeeManager::class);
return new AwardeeImageHandler($awardeeManager);
}
}

View File

@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
namespace App\Handler\Api;
use App\Service\JudgeManager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UploadedFileInterface;
use UtilityModule\Handler\AbstractCrudHandler;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\Response\TextResponse;
class JudgeImageHandler extends AbstractCrudHandler
{
const IDENTIFIER_NAME = 'slug';
/** @var JudgeManager */
private $judgeManager;
public function __construct(
JudgeManager $judgeManager
) {
$this->judgeManager = $judgeManager;
}
/**
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function get(ServerRequestInterface $request): ResponseInterface
{
$slug = $request->getAttribute(static::IDENTIFIER_NAME);
$imageResponse = new TextResponse($this->judgeManager->getProfileImage($slug));
return $imageResponse
->withHeader('Content-Type', 'image/jpeg')
->withHeader('Cache-Control', 'must-revalidate')
;
}
/**
* @param ServerRequestInterface $request
* @return JsonResponse
*/
public function create(ServerRequestInterface $request): ResponseInterface
{
$slug = $request->getAttribute(static::IDENTIFIER_NAME);
/** @var UploadedFileInterface[] $files */
$files = $request->getUploadedFiles();
$imageData = $files['image']->getStream()->getContents();
$entity = $this->judgeManager->setProfileImage($slug, $imageData);
return new JsonResponse($entity);
}
/**
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function delete(ServerRequestInterface $request): ResponseInterface
{
$slug = $request->getAttribute(static::IDENTIFIER_NAME);
return new JsonResponse($this->judgeManager->deleteProfileImage($slug));
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\Handler\Api;
use App\Service\JudgeManager;
use Psr\Container\ContainerInterface;
use Psr\Http\Server\RequestHandlerInterface;
class JudgeImageHandlerFactory
{
public function __invoke(ContainerInterface $container): RequestHandlerInterface
{
$judgeManager = $container->get(JudgeManager::class);
return new JudgeImageHandler($judgeManager);
}
}

View File

@ -10,6 +10,8 @@ use UtilityModule\Hydrator\DoctrineObject;
class AwardeeManager class AwardeeManager
{ {
const IMAGE_DIRECTORY = 'data/user-data/images/awardee';
/** @var EntityManager */ /** @var EntityManager */
private $entityManager; private $entityManager;
@ -24,6 +26,9 @@ class AwardeeManager
$this->hydrator = $hydrator; $this->hydrator = $hydrator;
} }
/**
* @return Awardee[]|null
*/
public function getAwardees(): ?array public function getAwardees(): ?array
{ {
return $this->entityManager->getRepository(Awardee::class)->findBy([], [ return $this->entityManager->getRepository(Awardee::class)->findBy([], [
@ -42,6 +47,10 @@ class AwardeeManager
]); ]);
} }
/**
* @param int $id
* @return Awardee|null
*/
public function getAwardee(int $id): ?Awardee public function getAwardee(int $id): ?Awardee
{ {
/** @var Awardee $awardee */ /** @var Awardee $awardee */
@ -63,12 +72,14 @@ class AwardeeManager
} }
/** /**
* @param $data
* @return Awardee * @return Awardee
* @throws \Doctrine\ORM\ORMException * @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException * @throws \Doctrine\ORM\OptimisticLockException
*/ */
public function create($data): Awardee public function create($data): Awardee
{ {
unset($data['slug']);
/** @var Awardee $awardee */ /** @var Awardee $awardee */
$awardee = $this->hydrator->hydrate($data, new Awardee()); $awardee = $this->hydrator->hydrate($data, new Awardee());
$this->entityManager->persist($awardee); $this->entityManager->persist($awardee);
@ -85,6 +96,7 @@ class AwardeeManager
*/ */
public function update(int $id, $data): Awardee public function update(int $id, $data): Awardee
{ {
unset($data['slug']);
$awardee = $this->entityManager->getRepository(Awardee::class)->find($id); $awardee = $this->entityManager->getRepository(Awardee::class)->find($id);
/** @var Awardee $awardee */ /** @var Awardee $awardee */
$awardee = $this->hydrator->hydrate($data, $awardee); $awardee = $this->hydrator->hydrate($data, $awardee);
@ -99,7 +111,8 @@ class AwardeeManager
* @throws \Doctrine\ORM\ORMException * @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException * @throws \Doctrine\ORM\OptimisticLockException
*/ */
public function delete(int $id): bool { public function delete(int $id): bool
{
if (null !== ($entity = $this->getAwardee($id))) { if (null !== ($entity = $this->getAwardee($id))) {
$this->entityManager->remove($entity); $this->entityManager->remove($entity);
$this->entityManager->flush(); $this->entityManager->flush();
@ -107,4 +120,69 @@ class AwardeeManager
} }
return false; return false;
} }
/**
* @param string $slug
* @param string $type
* @return string
*/
public function getProfileImage(string $slug, string $type): string
{
/** @var Awardee $entity */
$entity = $this->entityManager->getRepository(Awardee::class)->findOneBy([
'slug' => $slug,
]);
$fileName = $this->getImageFileName($entity->getId(), $type);
if (file_exists($fileName)) {
return file_get_contents($fileName);
}
throw new \InvalidArgumentException("$fileName not found");
}
/**
* @param string $slug
* @param string $imageData
* @param string $type
* @return bool
*/
public function setProfileImage(string $slug, string $imageData, string $type): bool
{
/** @var Awardee $entity */
$entity = $this->entityManager->getRepository(Awardee::class)->findOneBy([
'slug' => $slug,
]);
$this->ensureImageDirectoryExists();
$fileName = $this->getImageFileName($entity->getId(), $type);
return false !== file_put_contents($fileName, $imageData);
}
/**
* @param string $slug
* @param string $type
* @return bool
*/
public function deleteProfileImage(string $slug, string $type): bool
{
/** @var Awardee $entity */
$entity = $this->entityManager->getRepository(Awardee::class)->findOneBy([
'slug' => $slug,
]);
$fileName = $this->getImageFileName($entity->getId(), $type);
if (file_exists($fileName)) {
return unlink($fileName);
}
throw new \InvalidArgumentException();
}
public function ensureImageDirectoryExists()
{
if (!is_dir(self::IMAGE_DIRECTORY)) {
mkdir(self::IMAGE_DIRECTORY, 0755, true);
}
}
private function getImageFileName(int $id, string $type): string
{
return sprintf('%s/%s-%s.jpg', self::IMAGE_DIRECTORY, $id, $type);
}
} }

View File

@ -10,6 +10,8 @@ use UtilityModule\Hydrator\DoctrineObject;
class JudgeManager class JudgeManager
{ {
const IMAGE_DIRECTORY = 'data/user-data/images/judge';
/** @var EntityManager */ /** @var EntityManager */
private $entityManager; private $entityManager;
@ -24,7 +26,10 @@ class JudgeManager
$this->hydrator = $hydrator; $this->hydrator = $hydrator;
} }
public function getJudges() /**
* @return Judge[]|null
*/
public function getJudges(): ?array
{ {
$qb = $this->entityManager->createQueryBuilder(); $qb = $this->entityManager->createQueryBuilder();
return $qb->select('j, t') return $qb->select('j, t')
@ -32,14 +37,14 @@ class JudgeManager
->leftJoin('j.titles', 't') ->leftJoin('j.titles', 't')
->orderBy('j.name', 'ASC') ->orderBy('j.name', 'ASC')
->getQuery() ->getQuery()
->getArrayResult(); ->getResult();
} }
/** /**
* @param int $year * @param int $year
* @return array * @return Judge[]|null
*/ */
public function getJudgesByYear(int $year) public function getJudgesByYear(int $year): ?array
{ {
$qb = $this->entityManager->createQueryBuilder(); $qb = $this->entityManager->createQueryBuilder();
return $qb->select('j,t') return $qb->select('j,t')
@ -49,7 +54,7 @@ class JudgeManager
->orderBy('j.name', 'ASC') ->orderBy('j.name', 'ASC')
->setParameter('year', $year) ->setParameter('year', $year)
->getQuery() ->getQuery()
->getArrayResult(); ->getResult();
} }
/** /**
@ -71,6 +76,7 @@ class JudgeManager
*/ */
public function create($data): Judge public function create($data): Judge
{ {
unset($data['slug']);
/** @var Judge $judge */ /** @var Judge $judge */
$judge = $this->hydrator->hydrate($data, new Judge()); $judge = $this->hydrator->hydrate($data, new Judge());
$this->entityManager->persist($judge); $this->entityManager->persist($judge);
@ -87,6 +93,7 @@ class JudgeManager
*/ */
public function update(int $id, $data): Judge public function update(int $id, $data): Judge
{ {
unset($data['slug']);
$judge = $this->entityManager->getRepository(Judge::class)->find($id); $judge = $this->entityManager->getRepository(Judge::class)->find($id);
/** @var Judge $judge */ /** @var Judge $judge */
$judge = $this->hydrator->hydrate($data, $judge); $judge = $this->hydrator->hydrate($data, $judge);
@ -110,4 +117,66 @@ class JudgeManager
} }
return false; return false;
} }
/**
* @param string $slug
* @return string
*/
public function getProfileImage(string $slug): string
{
/** @var Judge $entity */
$entity = $this->entityManager->getRepository(Judge::class)->findOneBy([
'slug' => $slug,
]);
$fileName = $this->getImageFileName($entity->getId());
if (file_exists($fileName)) {
return file_get_contents($fileName);
}
throw new \InvalidArgumentException();
}
/**
* @param string $slug
* @param string $imageData
* @return bool
*/
public function setProfileImage(string $slug, string $imageData): bool
{
/** @var Judge $entity */
$entity = $this->entityManager->getRepository(Judge::class)->findOneBy([
'slug' => $slug,
]);
$this->ensureImageDirectoryExists();
$fileName = $this->getImageFileName($entity->getId());
return false !== file_put_contents($fileName, $imageData);
}
/**
* @param string $slug
* @return bool
*/
public function deleteProfileImage(string $slug): bool
{
/** @var Judge $entity */
$entity = $this->entityManager->getRepository(Judge::class)->findOneBy([
'slug' => $slug,
]);
$fileName = $this->getImageFileName($entity->getId());
if (file_exists($fileName)) {
return unlink($fileName);
}
throw new \InvalidArgumentException();
}
public function ensureImageDirectoryExists()
{
if (!is_dir(self::IMAGE_DIRECTORY)) {
mkdir(self::IMAGE_DIRECTORY, 0755, true);
}
}
private function getImageFileName(int $id): string
{
return sprintf('%s/%s.jpg', self::IMAGE_DIRECTORY, $id);
}
} }

View File

@ -41,7 +41,7 @@ class AuthHandler extends AbstractCrudHandler
* @param ServerRequestInterface $request * @param ServerRequestInterface $request
* @return \Zend\Diactoros\Response\JsonResponse * @return \Zend\Diactoros\Response\JsonResponse
*/ */
public function get(ServerRequestInterface $request) public function getList(ServerRequestInterface $request)
{ {
$token = $request->getAttribute('token'); $token = $request->getAttribute('token');
return new JsonResponse($this->authService->renewToken($token)); return new JsonResponse($this->authService->renewToken($token));

View File

@ -64,6 +64,11 @@ class JwtMiddlewareFactory
} }
} }
$unguardedPaths = $this->aclConfig->get('unguarded_paths', new Config([]))->toArray();
foreach ($unguardedPaths as $path) {
$passThroughRoutes[] = $path;
}
return $passThroughRoutes; return $passThroughRoutes;
} }
} }

View File

@ -62,6 +62,7 @@ class AuthService
/** @var string $hmacKey */ /** @var string $hmacKey */
$hmacKey = $this->config->get('hmac_key'); $hmacKey = $this->config->get('hmac_key');
return JWT::encode([ return JWT::encode([
"jti" => uniqid(),
"iat" => time(), "iat" => time(),
"nbf" => time(), "nbf" => time(),
"exp" => time() + 3600, "exp" => time() + 3600,
@ -77,7 +78,7 @@ class AuthService
/** @var string $hmacKey */ /** @var string $hmacKey */
$hmacKey = $this->config->get('hmac_key'); $hmacKey = $this->config->get('hmac_key');
return JWT::encode([ return JWT::encode([
"jti" => $token->jti, "jti" => $token['jti'],
"iat" => time(), "iat" => time(),
"nbf" => time(), "nbf" => time(),
"exp" => time() + 3600, "exp" => time() + 3600,

View File

@ -2,7 +2,7 @@
<section class="awardees"> <section class="awardees">
<?php foreach ($awardees as $awardee): ?> <?php foreach ($awardees as $awardee): ?>
<a class="awardee" href="<?= $this->url('awardee', ['slug' => $awardee->getSlug()]) ?>"> <a class="awardee" href="<?= $this->url('awardee', ['slug' => $awardee->getSlug()]) ?>">
<img class="profile" src="<?= $this->serverurl(sprintf('/img/awardees/%s.jpg', $awardee->getSlug())) ?>"> <img class="profile" src="<?= $this->url('api.awardee-image', ['slug' => $awardee->getSlug(), 'type' => 'profile']) ?>">
<div class="year"><?= $year ?></div> <div class="year"><?= $year ?></div>
<div class="name"><?= $awardee->getName() ?></div> <div class="name"><?= $awardee->getName() ?></div>
<div class="description"><?= $this->batch($awardee->getText(), 'excerpt|mdtohtml') ?></div> <div class="description"><?= $this->batch($awardee->getText(), 'excerpt|mdtohtml') ?></div>

View File

@ -2,9 +2,9 @@
<h1><?=$year?> judges</h1> <h1><?=$year?> judges</h1>
<?php foreach ($judges as $judge): ?> <?php foreach ($judges as $judge): ?>
<section class="judge"> <section class="judge">
<img class="profile" src="<?= $this->serverurl(sprintf('/img/judges/%s.jpg', $judge['slug'])) ?>"> <img class="profile" src="<?= $this->url('api.judge-image', ['slug' => $judge->getSlug()]) ?>">
<span class="title"><?= $judge['prefix'].$judge['name']?></span><br> <span class="title"><?= $judge->getPrefix().$judge->getName()?></span><br>
<span class="description"><?= $judge['titles'][0]['title']?></span> <span class="description"><?= $judge->getTitles()[0]->getTitle()?></span>
</section> </section>
<?php endforeach; ?> <?php endforeach; ?>
</section> </section>

View File

@ -1,13 +1,13 @@
<?php $this->layout('layout::default', ['title' => $awardee->getName()]) ?> <?php $this->layout('layout::default', ['title' => $awardee->getName()]) ?>
<section class="profile"> <section class="profile">
<section class="awardee"> <section class="awardee">
<img class="profile" src="<?= $this->serverurl(sprintf('/img/awardees/%s.jpg', $awardee->getSlug())) ?>"> <img class="profile" src="<?= $this->url('api.awardee-image', ['slug' => $awardee->getSlug(), 'type' => 'profile']) ?>">
<div class="year"><?= $awardee->getYear() ?></div> <div class="year"><?= $awardee->getYear() ?></div>
<div class="name"><?= $awardee->getName() ?></div> <div class="name"><?= $awardee->getName() ?></div>
<div class="description"><?= $this->mdtohtml($awardee->getText()) ?></div> <div class="description"><?= $this->mdtohtml($awardee->getText()) ?></div>
</section> </section>
<aside class="sidebar"> <aside class="sidebar">
<img src="<?= $this->serverurl(sprintf('/img/awardees/%s-atadas.jpg', $awardee->getSlug())) ?>"> <img src="<?= $this->url('api.awardee-image', ['slug' => $awardee->getSlug(), 'type' => 'award']) ?>">
<div class="image-label"> <div class="image-label">
<?= $this->e($awardee->getImageLabel()) ?> <?= $this->e($awardee->getImageLabel()) ?>
</div> </div>