mirror of
https://github.com/stan220/chixana.git
synced 2026-09-08 15:28:46 +00:00
Added chix module.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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']) {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Service\ChixService;
|
||||
use Doctrine\ORM\EntityNotFoundException;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route("/chix", name="chix_")
|
||||
*/
|
||||
class ChixController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @var ChixService
|
||||
*/
|
||||
private $chixService;
|
||||
|
||||
public function __construct(ChixService $chixService)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Repository\ChixRepository")
|
||||
*/
|
||||
class Chix
|
||||
{
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\User")
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
private $created_at;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\ChixApprove", mappedBy="chix", orphanRemoval=true, fetch="EAGER")
|
||||
*/
|
||||
private $approves;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Repository\ChixApproveRepository")
|
||||
*/
|
||||
class ChixApprove
|
||||
{
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Chix", inversedBy="approves")
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private $chix;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\User", fetch="EAGER")
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
private $created_at;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -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;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20200111184153 extends AbstractMigration
|
||||
{
|
||||
public function getDescription() : string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema) : void
|
||||
{
|
||||
// this up() 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('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');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\ChixApprove;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method ChixApprove|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method ChixApprove|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method ChixApprove[] findAll()
|
||||
* @method ChixApprove[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ChixApproveRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ChixApprove::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
* @return ChixApprove[] Returns an array of ChixApprove objects
|
||||
*/
|
||||
public function findLast(int $count = 10): array
|
||||
{
|
||||
return $this->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()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Chix;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Doctrine\ORM\EntityNotFoundException;
|
||||
|
||||
/**
|
||||
* @method Chix|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Chix|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Chix[] findAll()
|
||||
* @method Chix[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ChixRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Chix::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Chix
|
||||
* @throws EntityNotFoundException
|
||||
*/
|
||||
public function get(int $id): Chix
|
||||
{
|
||||
if (!$chix = $this->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()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\Chix;
|
||||
use App\Entity\ChixApprove;
|
||||
use App\Entity\User;
|
||||
use App\Repository\ChixApproveRepository;
|
||||
use App\Repository\ChixRepository;
|
||||
use App\Value\FamousStatement;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
class ChixService
|
||||
{
|
||||
/** @var ChixRepository */
|
||||
private $chixRepository;
|
||||
|
||||
/** @var ChixApproveRepository */
|
||||
private $approveRepository;
|
||||
|
||||
/** @var EntityManagerInterface */
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(
|
||||
ChixRepository $chixRepository,
|
||||
ChixApproveRepository $approveRepository,
|
||||
EntityManagerInterface $entityManager
|
||||
|
||||
) {
|
||||
$this->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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Value;
|
||||
|
||||
class ChixBoard
|
||||
{
|
||||
private const FIVE_DIV_VALUE = 5;
|
||||
|
||||
private $fiveCount;
|
||||
|
||||
private $mod;
|
||||
|
||||
public function __construct($amount)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace App\Value;
|
||||
|
||||
class FamousStatement
|
||||
{
|
||||
private const STATEMENT_CONTENT = [
|
||||
'В молодости медицина должна помогать природе, в старости – противодействовать ей. Тадеуш Котарбиньский',
|
||||
'Прогресс медицины положит конец той либеральной эпохе, когда каждый умирал себе, когда пожелал. Станислав Ежи Лец',
|
||||
'Медицина быстро идет вперед, только наш организм не поспевает за ней. Владислав Катажиньский',
|
||||
'Мало записаться на прием к врачу – надо до него еще дожить. Константин Мелихан',
|
||||
'У нас много хороших женщин медиков. Это говорит не столько о высоком уровне женщин, сколько о низком уровне медицины. Хуго Штейнхаус',
|
||||
'Латынь: мертвый язык, используемый в медицине для спасения живых. Славомир Врублевский',
|
||||
'Врачевание излечивает только излечимые болезни. Китайское изречение',
|
||||
'Мертвец — это всего лишь пока что неизлечимый больной. Жан Ростан',
|
||||
'Прежде магию путали с медициной; ныне медицину путают с магией. Томас Сас',
|
||||
'Медицина: кошелек и жизнь. Карл Краус',
|
||||
'Врачу вовсе не обязательно верить в медицину – больной верит в нее за двоих. Жорж Элгози',
|
||||
'Цель медицины заключается в том, чтобы люди умирали настолько молодыми, насколько это возможно. Эрнст Уиндер',
|
||||
'Медицина заставляет нас умирать продолжительнее и мучительнее. Плутарх',
|
||||
'Медицинская наука добавляет годы жизни, но не добавляет жизни годам.',
|
||||
'Поликлиника: ускоренные курсы по обмену опытом между больными. Сильвия Чиз',
|
||||
'Чтобы у нас болеть, надо иметь лошадиное здоровье. Лион Измайлов',
|
||||
'Иных уж нет, а тех долечат. Борис Брайнин',
|
||||
'Возможности медицины безграничны. Ограниченны возможности пациентов. Роберт Шекли',
|
||||
'Врачебная наука популяризирует болезни, делает их общедоступными. Михаил Салтыков-Щедрин',
|
||||
'Цель медицины уже не здоровье, а расширение системы здравоохранения. Герхард Кохер',
|
||||
'Многие из нас умрут ради науки, даже не подозревая об этом. Герхард Кохер',
|
||||
'Человечество пережило все напасти, переживет и современную медицину. Герхард Кохер',
|
||||
'Больница — не лучшее место болеть. Приписывается Сэмюэлу Голдвину',
|
||||
'Прежде чем направить меня в больницу, врач заботливо расспросил, сколько недомоганий я могу себе позволить.',
|
||||
'Кровать в частной больнице — это припаркованное такси с включенным счетчиком. Граучо Маркс',
|
||||
'Нет искусства полезнее медицины. Плиний Старший',
|
||||
'Медицина — сестра философии. Демокрит',
|
||||
'Гимнастика есть целительная часть медицины. Платон',
|
||||
'Врач — философ; ведь нет большой разницы между мудростью и медициной. Гиппократ',
|
||||
'Искусство медицины состоит из трех элементов: болезнь, больной и врач. Гиппократ',
|
||||
'Медицина поистине есть самое благородное из всех искусств. Гиппократ',
|
||||
'Ничто так не обязательно всему роду человеческому, как медицина. Квинтилиан',
|
||||
'Если бы люди были склонны жить сообразно с природой, не нужна была бы медицинская помощь. Неизвестный автор',
|
||||
'Не вылечивается тот, кто имеет заботы. (Надпись на банях в Риме.) Неизвестный автор',
|
||||
'Медицина — одно из величайших заблуждений человечества. Мольер',
|
||||
'При помощи физических упражнений и воздержанности большая часть людей может обойтись без медицины. Джозеф Аддисон',
|
||||
'Будущее принадлежит медицине предохранительной. Эта наука, идя рука об руку с лечебной, принесет несомненную пользу человечеству. Николай Иванович Пирогов',
|
||||
'Свобода и здоровье имеют одно общее: по-настоящему ценишь их только тогда, когда их не хватает. Анри Бек',
|
||||
'Судите о своем здоровье по тому, как вы радуетесь утру и весне. Генри Торо',
|
||||
'Здоровье — это когда каждый день лучший. Франклин Адамс',
|
||||
'Здоровье — это максимальная производительность органов при сохранении качественных пределов их функций. Николай Амосов',
|
||||
'Здоровье не купишь, им можно только расплачиваться. Сергей Крытый',
|
||||
'Физические упражнения могут заменить множество лекарств, но ни одно лекарство в мире не может заменить физические упражнения. Анджело Моссо',
|
||||
'Надо стремиться к тому, чтобы в здоровом теле был здоровый дух. Ювенал',
|
||||
'Здоровье — это вопрос номер один. Если у вас слабое здоровье, что толку говорить о хорошей работе, хорошей защите прав, хорошем образовании! Сара Макклендон',
|
||||
'Здоровье так же заразительно, как и болезнь. Ромен Роллан',
|
||||
'Лучше быть здоровым, но богатым, чем бедным, но больным. Даниил Хармс',
|
||||
'Ничего лишнего. Рано ложиться и рано вставать — вот что делает человека здоровым, богатым и умным. Бенджамин Франклин',
|
||||
'Подобно тому, как существует болезнь тела, существует также и болезнь образа жизни. Демокрит',
|
||||
'Приятно поласкать дитя или собаку, но всего необходимее полоскать рот. Козьма Прутков',
|
||||
'Самое важное свойство для физического здоровья представляет бодрость духа. Упадок духа сродни смерти. Уильям Годвин',
|
||||
'Самый ценный плод здоровья — возможность получать удовольствие. Мишель де Монтень',
|
||||
'Самые здоровые и красивые люди — это те, которых ничего не раздражает. Георг Лихтенберг',
|
||||
'Скажи мне, что в твоем холодильнике, и я скажу, как твое здоровье. Степан Балакин',
|
||||
'Без здоровья невозможно и счастье. Виссарион Белинский',
|
||||
'Все здоровые люди любят жизнь. Генрих Гейне',
|
||||
'Главное для нашего здоровья — это то, чтобы в числе его врагов не оказались мы сами. Бауржан Тойшибеков',
|
||||
'Если ты здоров — это хорошо, если я — еще лучше. Эрик Берн',
|
||||
'Здоровый человек не тот, у которого ничего не болит, а тот, у которого каждый раз болит в другом месте. Мишель Крестьен',
|
||||
'Здоровье — великое дело как для того, кто им пользуется, так и для других. Томас Карлейль',
|
||||
'Тот, кто хочет быть здоровым, отчасти уже выздоравливает. Джованни Боккаччо',
|
||||
'Медицина — искусство обманывать пациента на период, пока природа сама справится с болезнью. Эван Эзар',
|
||||
'Надежда — лучший врач из всех, какие мне известны. Александр Дюма-отец',
|
||||
'Какая болезнь самая плохая из всех? Это — лекари. Только врач может безнаказанно убить человека. Эрнст Хайне',
|
||||
'Неудачная операция — половина удачного вскрытия. Хенрик Ягодзиньский',
|
||||
'Не всегда во власти врача исцелить больного. Публий Овидий Назон',
|
||||
'Радостное выражение лица врача — начало выздоровления больного. Фернандо де Рохас',
|
||||
'Почти у каждого врача есть свои излюбленные болезни. Генри Филдинг',
|
||||
'Самый чудесный врач — природа, хотя бы потому, что излечивает три четверти всех болезней и никогда не отзывается дурно о своих коллегах. Виктор Шербюлье',
|
||||
'Болезнь — своего рода преждевременная старость. Александр Поп',
|
||||
'В ревматизм и в настоящую любовь не верят до первого приступа. Мари Эбнер-Эшенбах',
|
||||
'Большая часть болезней наших — это дело наших собственных рук; мы могли бы почти всех их избежать, если бы сохранили образ жизни простой, однообразный и уединенный, который предписан нам был природою. Жан Жак Руссо',
|
||||
'Если человек начинает интересоваться смыслом жизни или ее ценностью — это значит, что он болен. Зигмунд Фрейд',
|
||||
'Кроме действительных болезней мы подвержены множеству болезней мнимых. Джонатан Свифт',
|
||||
];
|
||||
|
||||
/** @var int */
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* @param int|null $seed
|
||||
*/
|
||||
public function __construct(?int $seed = null)
|
||||
{
|
||||
if ($seed !== null) {
|
||||
$this->key = $seed % \count(self::STATEMENT_CONTENT);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->key = array_rand(self::STATEMENT_CONTENT);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return (string) self::STATEMENT_CONTENT[$this->key];
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||
<title>{% block title %}Chixana!{% endblock %}</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.1/build/pure-min.css" integrity="sha384-oAOxQR6DkCoMliIh8yFnu25d7Eq/PHS21PClpwjOTeU2jRSq11vu66rf90/cZr47" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
|
||||
|
||||
{% block stylesheets %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
{% extends 'main.html.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="pure-g" style="max-width: 980px">
|
||||
<div class="pure-u-3-5">
|
||||
<img style="width: 500px; padding-top: 100px" src="https://image.freepik.com/free-vector/happy-doctor-with-clipboard_23-2147798688.jpg">
|
||||
</div>
|
||||
<div class="pure-u-2-5">
|
||||
<h1>Инфа о чихе</h1>
|
||||
|
||||
<table class="pure-table pure-table-horizontal">
|
||||
<tr>
|
||||
<td>Id</td>
|
||||
<td>{{ chix.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Наблюдаемый</td>
|
||||
<td>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<img src="{{ chix.user.avatar }}" width="25px" height="25px" style="padding: 4px"/>
|
||||
<div>{{ chix.user.name }}</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Дата</td>
|
||||
<td>{{ chix.getCreatedAt|date('Y-m-d H:i:s') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Аппрувы</td>
|
||||
<td>
|
||||
{% for approve in chix.approves %}
|
||||
<div style="align-items: center; display: flex;">
|
||||
<img src="{{ approve.user.avatar }}" width="25px" height="25px" style="padding: 4px"/>
|
||||
<div>{{ approve.user.name }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Статус</td>
|
||||
<td><i class="fas fa-lg {{ chix.isVerified ? 'fa-check-circle color-green' : 'fa-times-circle color-red' }}">
|
||||
{{ chix.isVerified ? 'Утверждено' : 'В проработке' }}
|
||||
</i>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1> Текст </h1>
|
||||
|
||||
<blockquote class="content-quote">
|
||||
{{ statement }}
|
||||
</blockquote>
|
||||
|
||||
{% if isCanApprove %}
|
||||
<a class="pure-button my-button" href="{{ path('chix_app_chix_approve', {'chixId': chix.id}) }}" >
|
||||
<i class="fas fa-check-circle fa-lg"></i>
|
||||
Апрувнуть!
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,73 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block stylesheets %}
|
||||
<style type="text/css">
|
||||
BODY {
|
||||
margin: 0;
|
||||
}
|
||||
.top-layer {
|
||||
background: url(https://image.freepik.com/free-vector/seamless-pattern-microbes-virus-vector-illustration_53562-5156.jpg) repeat-x;
|
||||
height: 69px;
|
||||
border-bottom: 2px solid maroon;
|
||||
}
|
||||
.content-quote {
|
||||
font-family: "Georgia", serif;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
line-height: 1.8;
|
||||
border-left: 5px solid #ddd;
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
.my-button {
|
||||
background: rgb(66, 184, 221);
|
||||
font-size: 150%;
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
.color-green {
|
||||
color:green;
|
||||
}
|
||||
.color-red {
|
||||
color:brown;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="top-layer">
|
||||
<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgZGF0YS1uYW1lPSJMYXllciAxIiBoZWlnaHQ9IjI0IiBpZD0iTGF5ZXJfMSIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlLz48cmVjdCBoZWlnaHQ9IjMiIHJ4PSIxIiByeT0iMSIgc3R5bGU9ImZpbGw6I2IzYzFjOSIgd2lkdGg9IjIwIiB4PSIyIiB5PSIxMCIvPjxwYXRoIGQ9Ik0xNi41LDEzLjM2OTVINnY0LjcyNTZhMS45OTk4LDEuOTk5OCwwLDAsMCwuODMxMywxLjYyM0w5LjQ3NjQsMjEuNjIzQTIuMDAwMzIsMi4wMDAzMiwwLDAsMCwxMC42NDUyLDIyaDIuNzA5NmEyLjAwMDMyLDIuMDAwMzIsMCwwLDAsMS4xNjg4LS4zNzdsMi42NDUxLTEuOTA0OUExLjk5OTgxLDEuOTk5ODEsMCwwLDAsMTgsMTguMDk1MVYxMy4zNjk1WiIgc3R5bGU9ImZpbGw6IzRlYmE5NCIvPjxwYXRoIGQ9Ik0xNiwxNEg4djZhMSwxLDAsMCwwLC40LjhsMS4zMzMzLDFhMS4wMDAzMSwxLjAwMDMxLDAsMCwwLC42LjJoMy4zMzM0YTEuMDAwMywxLjAwMDMsMCwwLDAsLjYtLjJsMS4zMzMzLTFBMSwxLDAsMCwwLDE2LDIwWiIgc3R5bGU9ImZpbGw6IzY3YzdhNSIvPjxwYXRoIGQ9Ik0xNywxN0g3YTIuOTk5OTQsMi45OTk5NCwwLDAsMS0zLTNWNmEzLjk4MDYsMy45ODA2LDAsMCwxLC41OTM3LTIuMDk3OUM1LjI5ODEsMi43NjA3LDYuNTYwMiwzLDgsM2g4YzEuNDMyNSwwLDIuNjg5MS0uMjQ3LDMuMzk1Ni44ODQ4QTMuOTgwNTksMy45ODA1OSwwLDAsMSwyMCw2djhBMi45OTk5NCwyLjk5OTk0LDAsMCwxLDE3LDE3WiIgc3R5bGU9ImZpbGw6IzY3YzdhNSIvPjxjaXJjbGUgY3g9IjkiIGN5PSIxMSIgcj0iMi41IiBzdHlsZT0iZmlsbDojZmZmIi8+PGNpcmNsZSBjeD0iMTUiIGN5PSIxMSIgcj0iMi41IiBzdHlsZT0iZmlsbDojZmZmIi8+PGNpcmNsZSBjeD0iMTUiIGN5PSIxMSIgcj0iMC43NSIgc3R5bGU9ImZpbGw6IzczODM5NCIvPjxjaXJjbGUgY3g9IjkiIGN5PSIxMSIgcj0iMC43NSIgc3R5bGU9ImZpbGw6IzczODM5NCIvPjxwYXRoIGQ9Ik0xMywxOUgxMWExLDEsMCwwLDEtMS0xaDBhMSwxLDAsMCwxLDEtMWgyYTEsMSwwLDAsMSwxLDFoMEExLDEsMCwwLDEsMTMsMTlaIiBzdHlsZT0iZmlsbDojNDA5OTdhIi8+PHJlY3QgaGVpZ2h0PSIzIiBzdHlsZT0iZmlsbDojNjdjN2E1IiB3aWR0aD0iMTYiIHg9IjQiIHk9IjgiLz48cmVjdCBoZWlnaHQ9IjMiIHN0eWxlPSJmaWxsOiNmZmY0YWIiIHdpZHRoPSIxIiB4PSI3IiB5PSI2Ii8+PHJlY3QgaGVpZ2h0PSIzIiBzdHlsZT0iZmlsbDojZmZmNGFiIiB3aWR0aD0iMSIgeD0iMTAiIHk9IjYiLz48cmVjdCBoZWlnaHQ9IjMiIHN0eWxlPSJmaWxsOiNmZmY0YWIiIHdpZHRoPSIxIiB4PSIxMyIgeT0iNiIvPjxyZWN0IGhlaWdodD0iMSIgc3R5bGU9ImZpbGw6I2ZmZjRhYiIgd2lkdGg9IjkiIHg9IjYiIHk9IjciLz48cGF0aCBkPSJNNC41NTQ3LDQsNiw1LDgsNGwyLDEsMi0xLDIsMSwxLjk5OTYtMUwxOCw1bDEuNDQ1My0xQTMuOTgzMTUsMy45ODMxNSwwLDAsMCwxNiwySDhBMy45ODMxNiwzLjk4MzE2LDAsMCwwLDQuNTU0Nyw0WiIgc3R5bGU9ImZpbGw6IzRiNTY2MSIvPjwvc3ZnPg=="
|
||||
width="279" height="160" alt="Logo">
|
||||
</div>
|
||||
|
||||
<div style="margin: 0 64px;">
|
||||
<div class="pure-menu pure-menu-horizontal" style="margin-left: 160px">
|
||||
<ul class="pure-menu-list">
|
||||
<li class="pure-menu-item">
|
||||
<a href="{{ path('app_main_index') }}" class="pure-menu-link">
|
||||
Chixana!
|
||||
</a>
|
||||
</li>
|
||||
<li class="pure-menu-item">
|
||||
{% if is_granted('ROLE_USER') %}
|
||||
<a href="#" class="pure-menu-link" style="padding: 0">
|
||||
<div style="align-items: center; display: flex;">
|
||||
<img src="{{ app.user.avatar }}" width="25px" height="25px" style="padding: 4px"/>
|
||||
<div>{{ app.user.name }}</div>
|
||||
</div>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ path('connect_google') }}" class="pure-menu-link">
|
||||
Вход через Google
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% if is_granted('ROLE_USER') %}
|
||||
<li class="pure-menu-item"><a href="{{ path('app_logout') }}" class="pure-menu-link">Выход</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,39 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div style="margin: 0 64px; max-width: 680px;">
|
||||
<div class="pure-menu pure-menu-horizontal">
|
||||
<ul class="pure-menu-list">
|
||||
<li class="pure-menu-item">
|
||||
{% if is_granted('ROLE_USER') %}
|
||||
<a href="#" class="pure-menu-link"><div style="align-items: center; display: flex;">
|
||||
<img src="{{ app.user.avatar }}" width="25px" height="25px" style="padding: 4px"/>
|
||||
<div>{{ app.user.name }}</div>
|
||||
</div>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ path('connect_google') }}" class="pure-menu-link">
|
||||
Вход через Google
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% if is_granted('ROLE_USER') %}
|
||||
<li class="pure-menu-item"><a href="{{ path('app_logout') }}" class="pure-menu-link">Выход</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<h2 id="responsive-images" class="content-subhead">Content<a href="#responsive-images" class="content-link" title="Heading anchor"></a></h2>
|
||||
|
||||
<p>
|
||||
Content
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h1>Your lucky number is {{ number }}</h1>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user