Content
- -- Content -
-diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 5b8d00e..e946867 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -5,6 +5,13 @@ security: my_provider: entity: { class: App:User, property: username } + access_control: + - { path: '^/connect/google', roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: '^/connect/google/check', roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY } + + - { path: ^/(.+), roles: IS_AUTHENTICATED_FULLY } + firewalls: # disables authentication for assets and the profiler, adapt it according to your needs dev: @@ -21,3 +28,9 @@ security: guard: authenticators: - App\Security\GoogleAuthenticator + + form_login: + login_path: /connect/google + check_path: /connect/google/check + + access_denied_url: /connect/google diff --git a/config/services.yaml b/config/services.yaml index 5c4b417..4c5b1a7 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -15,7 +15,7 @@ services: # this creates a service per class whose id is the fully-qualified class name App\: resource: '../src/*' - exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}' + exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,Value}' # controllers are imported separately to make sure services can be injected # as action arguments even if you don't extend any base controller class diff --git a/public/index.php b/public/index.php index f094a9b..1030e44 100644 --- a/public/index.php +++ b/public/index.php @@ -4,6 +4,8 @@ use App\Kernel; use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\HttpFoundation\Request; +date_default_timezone_set('Europe/Minsk'); + require dirname(__DIR__).'/config/bootstrap.php'; if ($_SERVER['APP_DEBUG']) { diff --git a/src/Controller/ChixController.php b/src/Controller/ChixController.php new file mode 100644 index 0000000..401babd --- /dev/null +++ b/src/Controller/ChixController.php @@ -0,0 +1,87 @@ +chixService = $chixService; + } + + /** + * @Route("/{chixId}", requirements={"chixId"="\d+"}) + * @param Request $request + * @return Response + * @throws EntityNotFoundException + */ + public function view(Request $request): Response + { + $chixId = $this->getChixId($request); + $user = $this->getUser(); + + $result = $this->chixService->get($chixId, $user); + + return $this->render('chix/view.html.twig', $result); + } + + /** + * @Route("/add") + * @return Response + */ + public function add(): Response + { + $user = $this->getUser(); + + $chixId = $this->chixService->add($user); + + return $this->redirectToRoute('chix_app_chix_view', compact('chixId')); + + } + + /** + * @Route("/{chixId}/approve", requirements={"chixId"="\d+"}) + * @param Request $request + * @return Response + * @throws EntityNotFoundException + */ + public function approve(Request $request): Response + { + $chixId = $this->getChixId($request); + $user = $this->getUser(); + + $this->chixService->approve($chixId, $user); + + return $this->redirectToRoute('chix_app_chix_view', compact('chixId')); + } + + /** + * @param Request $request + * @return int + */ + private function getChixId(Request $request): int + { + $chixId = (int) $request->get('chixId'); + + if ($chixId < 1) { + throw new \InvalidArgumentException("Chix not found: $chixId"); + } + + return $chixId; + } +} diff --git a/src/Controller/MainController.php b/src/Controller/MainController.php index 71f3559..80c4982 100644 --- a/src/Controller/MainController.php +++ b/src/Controller/MainController.php @@ -2,21 +2,41 @@ namespace App\Controller; +use App\Repository\ChixApproveRepository; +use App\Repository\ChixRepository; +use App\Value\ChixBoard; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class MainController extends AbstractController { + /** @var ChixRepository */ + private $chixRepository; + + /** @var ChixApproveRepository */ + private $approveRepository; + + public function __construct( + ChixRepository $chixRepository, + ChixApproveRepository $approveRepository + ) + { + $this->chixRepository = $chixRepository; + $this->approveRepository = $approveRepository; + } + /** * @Route("/") + * @return Response + * @throws \Exception */ public function index(): Response { - $number = random_int(0, 100); + $chixi = $this->chixRepository->findAllForToday(); + $approves = $this->approveRepository->findLast(); + $board = new ChixBoard(\count($chixi)); - return $this->render('main.twig', [ - 'number' => $number, - ]); + return $this->render('index/index.html.twig', compact('board', 'chixi', 'approves')); } } diff --git a/src/Entity/Chix.php b/src/Entity/Chix.php new file mode 100644 index 0000000..c9e19a0 --- /dev/null +++ b/src/Entity/Chix.php @@ -0,0 +1,108 @@ +approves = new ArrayCollection(); + $this->setCreatedAt(new \DateTime()); + } + + public function isVerified(): bool + { + return !$this->approves->isEmpty(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getUser(): User + { + return $this->user; + } + + public function setUser(UserInterface $user): self + { + $this->user = $user; + + return $this; + } + + public function getCreatedAt(): \DateTimeInterface + { + return $this->created_at; + } + + public function setCreatedAt(\DateTimeInterface $created_at): self + { + $this->created_at = $created_at; + + return $this; + } + + /** + * @return Collection|ChixApprove[] + */ + public function getApproves(): Collection + { + return $this->approves; + } + + public function addApprove(ChixApprove $approve): self + { + if (!$this->approves->contains($approve)) { + $this->approves[] = $approve; + $approve->setChix($this); + } + + return $this; + } + + public function removeApprove(ChixApprove $approve): self + { + if ($this->approves->contains($approve)) { + $this->approves->removeElement($approve); + // set the owning side to null (unless already changed) + if ($approve->getChix() === $this) { + $approve->setChix(null); + } + } + + return $this; + } +} diff --git a/src/Entity/ChixApprove.php b/src/Entity/ChixApprove.php new file mode 100644 index 0000000..fdadd2a --- /dev/null +++ b/src/Entity/ChixApprove.php @@ -0,0 +1,82 @@ +setCreatedAt(new \DateTime()); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getChix(): ?Chix + { + return $this->chix; + } + + public function setChix(?Chix $chix): self + { + $this->chix = $chix; + + return $this; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function setUser(?UserInterface $user): self + { + $this->user = $user; + + return $this; + } + + public function getCreatedAt(): ?\DateTimeInterface + { + return $this->created_at; + } + + public function setCreatedAt(\DateTimeInterface $created_at): self + { + $this->created_at = $created_at; + + return $this; + } +} diff --git a/src/Entity/User.php b/src/Entity/User.php index 1a5080c..6f9916f 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -23,7 +23,7 @@ class User implements UserInterface private $email; /** - * @ORM\Column(type="string", length=20) + * @ORM\Column(type="string", length=30) */ private $name; @@ -42,6 +42,15 @@ class User implements UserInterface */ private $guid; + /** + * @param UserInterface $user + * @return bool + */ + public function isEqual(UserInterface $user): bool + { + return $this->getUsername() === $user->getUsername(); + } + public function getId(): ?int { return $this->id; diff --git a/src/Migrations/Version20200111184153.php b/src/Migrations/Version20200111184153.php new file mode 100644 index 0000000..bc740cd --- /dev/null +++ b/src/Migrations/Version20200111184153.php @@ -0,0 +1,41 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE chix_approve (id INT AUTO_INCREMENT NOT NULL, chix_id INT NOT NULL, user_id INT NOT NULL, created_at DATETIME NOT NULL, INDEX IDX_3DB0A505603C855C (chix_id), INDEX IDX_3DB0A505A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE chix (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, created_at DATETIME NOT NULL, INDEX IDX_A4F23489A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE chix_approve ADD CONSTRAINT FK_3DB0A505603C855C FOREIGN KEY (chix_id) REFERENCES chix (id)'); + $this->addSql('ALTER TABLE chix_approve ADD CONSTRAINT FK_3DB0A505A76ED395 FOREIGN KEY (user_id) REFERENCES user (id)'); + $this->addSql('ALTER TABLE chix ADD CONSTRAINT FK_A4F23489A76ED395 FOREIGN KEY (user_id) REFERENCES user (id)'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE chix_approve DROP FOREIGN KEY FK_3DB0A505603C855C'); + $this->addSql('DROP TABLE chix_approve'); + $this->addSql('DROP TABLE chix'); + } +} diff --git a/src/Repository/ChixApproveRepository.php b/src/Repository/ChixApproveRepository.php new file mode 100644 index 0000000..aabf06c --- /dev/null +++ b/src/Repository/ChixApproveRepository.php @@ -0,0 +1,64 @@ +createQueryBuilder('c') + ->orderBy('c.created_at', 'DESC') + ->setMaxResults($count) + ->getQuery() + ->getResult() + ; + } + + public function findOneByUserAndChix(int $userId, int $chixId): ?ChixApprove + { + return $this->createQueryBuilder('c') + ->andWhere('c.user = :userId') + ->andWhere('c.chix = :chixId') + ->setParameter('userId', $userId) + ->setParameter('chixId', $chixId) + ->getQuery() + ->getOneOrNullResult() + ; + } + + // /** + // * @return ChixApprove[] Returns an array of ChixApprove objects + // */ + /* + public function findByExampleField($value) + { + return $this->createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('c.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ +} diff --git a/src/Repository/ChixRepository.php b/src/Repository/ChixRepository.php new file mode 100644 index 0000000..f2441fd --- /dev/null +++ b/src/Repository/ChixRepository.php @@ -0,0 +1,79 @@ +find($id)) { + throw EntityNotFoundException::fromClassNameAndIdentifier($this->_entityName, [$id]); + } + + return $chix; + } + + /** + * @return Chix[] Returns an array of Chix objects + */ + public function findAllForToday(): array + { + return $this->createQueryBuilder('c') + ->andWhere('c.created_at >= :today') + ->setParameter('today', date('Y-m-d')) + ->orderBy('c.created_at', 'DESC') + ->getQuery() + ->getResult() + ; + } + + // /** + // * @return Chix[] Returns an array of Chix objects + // */ + /* + public function findByExampleField($value) + { + return $this->createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('c.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?Chix + { + return $this->createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/src/Service/ChixService.php b/src/Service/ChixService.php new file mode 100644 index 0000000..f98c075 --- /dev/null +++ b/src/Service/ChixService.php @@ -0,0 +1,101 @@ +chixRepository = $chixRepository; + $this->approveRepository = $approveRepository; + $this->entityManager = $entityManager; + } + + /** + * @param int $chixId + * @param User $user + * @return array + * @throws \Doctrine\ORM\EntityNotFoundException + */ + public function get(int $chixId, User $user): array + { + $chix = $this->chixRepository->get($chixId); + + $isCanApprove = !$chix->getUser()->isEqual($user); + + if ($isCanApprove) { + $approve = $this->approveRepository->findOneByUserAndChix($user->getId(), $chixId); + $isCanApprove = $approve === null; + } + + $statement = new FamousStatement($chix->getCreatedAt()->getTimestamp()); + + return compact('chix', 'isCanApprove', 'statement'); + } + + /** + * @param User $user + * @return int + */ + public function add(User $user): int + { + $chix = new Chix(); + $chix->setUser($user); + + $this->entityManager->persist($chix); + $this->entityManager->flush(); + + dump($chix); + + return $chix->getId(); + } + + /** + * @param int $chixId + * @param User $user + * @throws \Doctrine\ORM\EntityNotFoundException + */ + public function approve(int $chixId, User $user): void + { + $chix = $this->chixRepository->get($chixId); + + $username = $user->getUsername(); + if ($chix->getUser()->isEqual($user)) { + throw new \LogicException("Denied approve for yourself: $username"); + } + + $approve = $this->approveRepository->findOneByUserAndChix($user->getId(), $chixId); + + if ($approve) { + throw new \LogicException("Approve already has: {$approve->getId()}, user: $username"); + } + + $approve = new ChixApprove(); + $approve->setUser($user); + $approve->setChix($chix); + + $this->entityManager->persist($approve); + $this->entityManager->flush(); + } +} diff --git a/src/Value/ChixBoard.php b/src/Value/ChixBoard.php new file mode 100644 index 0000000..67da295 --- /dev/null +++ b/src/Value/ChixBoard.php @@ -0,0 +1,35 @@ +fiveCount = intdiv($amount, self::FIVE_DIV_VALUE); + $this->mod = $amount % self::FIVE_DIV_VALUE; + } + + /** + * @return int + */ + public function getFiveCount(): int + { + return $this->fiveCount; + } + + /** + * @return int + */ + public function getMod(): int + { + return $this->mod; + } + +} diff --git a/src/Value/FamousStatement.php b/src/Value/FamousStatement.php new file mode 100644 index 0000000..17fe642 --- /dev/null +++ b/src/Value/FamousStatement.php @@ -0,0 +1,104 @@ +key = $seed % \count(self::STATEMENT_CONTENT); + return; + } + + $this->key = array_rand(self::STATEMENT_CONTENT); + } + + public function __toString() + { + return (string) self::STATEMENT_CONTENT[$this->key]; + } +} diff --git a/templates/base.html.twig b/templates/base.html.twig index c61820a..5ff4945 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -2,8 +2,11 @@
-
+ | Id | +{{ chix.id }} | +
| Наблюдаемый | +
+
+
+ {{ chix.user.name }}
+ |
+
| Дата | +{{ chix.getCreatedAt|date('Y-m-d H:i:s') }} | +
| Аппрувы | +
+ {% for approve in chix.approves %}
+
+
+ {% endfor %}
+ {{ approve.user.name }}
+ |
+
| Статус | ++ {{ chix.isVerified ? 'Утверждено' : 'В проработке' }} + + | +
+ {{ statement }} ++ + {% if isCanApprove %} + + + Апрувнуть! + + {% endif %} +
| # | +Чел | +Когда | +Верифай | +
|---|---|---|---|
| {{ key + 1 }} | +
+
+
+ {{ chix.user.name }}
+ |
+ {{ chix.getCreatedAt|date('H:i:s') }} | ++ + |
| # | +Чел | +Дата | +
|---|---|---|
| {{ key + 1 }} | +
+
+
+ {{ approve.user.name }}
+ |
+ {{ approve.getCreatedAt|date('Y-m-d H:i:s') }} | + +
Помните! Нам важен каждый чих!
+Если вы чихнули, то, пожалуйста, зафиксируте время и факт произошедшенго.
+Будьте внимательны! Если чихнул Ваш коллега, то не забудьте напомнить ему о акте фиксации.
+ + + Зафиксировать себя! + + +Если заметили подозрительную активность, то проявите социальную ответственность.
+ + + Зарепортить о нарушении! + + {% else %} +Залогиньтесь чтоб делать годноту.
+ {% endif %} + +