Compare commits

...

10 commits

Author SHA1 Message Date
mitsuha_s 6640112c54 bug fix 2023-07-21 23:09:10 +03:00
mitsuha_s 21d651f377 bug fix 2023-07-21 22:58:24 +03:00
mitsuha_s 8bb77fbe6c main migration changed 2023-07-21 20:48:42 +03:00
mitsuha_s 1d08cfdc09 DTO for paste data added, Paste Entity changed 2023-07-21 20:47:24 +03:00
mitsuha_s ffcfa29968 code style changes 2023-07-21 18:00:14 +03:00
mitsuha_s 561b016e38 save() method in PasteRepository implemented 2023-07-21 17:13:05 +03:00
mitsuha_s 78ebba425b strict types added 2023-07-21 16:35:48 +03:00
mitsuha_s 5b306cfd54 migrations merged 2023-07-21 16:27:04 +03:00
mitsuha_s 0d7c5487f4 APP_SECRET variable in .env changed 2023-07-21 16:19:20 +03:00
mitsuha_s 9a98436eb8 unnecessary .gitignore files removed, double quotes changed to single quotes 2023-07-21 16:16:16 +03:00
13 changed files with 157 additions and 259 deletions

2
.env
View file

@ -16,7 +16,7 @@
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=90c78b17302e6ff2e14213f129e3f5f4
APP_SECRET=your_secret_please_set_on_local_env
###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###

View file

View file

@ -7,9 +7,7 @@ namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20230720115905 extends AbstractMigration
{
public function getDescription(): string
@ -19,14 +17,12 @@ final class Version20230720115905 extends AbstractMigration
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SEQUENCE paste_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE paste (id INT NOT NULL, text TEXT NOT NULL, private BOOLEAN NOT NULL, language VARCHAR(25) NOT NULL, description TEXT NOT NULL, filename VARCHAR(128) NOT NULL, author VARCHAR(128) NOT NULL, publish_date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, expiration_date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, ip VARCHAR(15) NOT NULL, secret VARCHAR(40) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE paste (id INT NOT NULL, text TEXT NOT NULL, language VARCHAR(25), description TEXT, filename VARCHAR(128), author VARCHAR(128) NOT NULL, publish_date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, expiration_date TIMESTAMP(0) WITHOUT TIME ZONE, ip VARCHAR(15) NOT NULL, secret VARCHAR(40), PRIMARY KEY(id))');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('DROP SEQUENCE paste_id_seq CASCADE');
$this->addSql('DROP TABLE paste');

View file

@ -1,38 +0,0 @@
<?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 Version20230720125632 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->addSql('ALTER TABLE paste ALTER language DROP NOT NULL');
$this->addSql('ALTER TABLE paste ALTER description DROP NOT NULL');
$this->addSql('ALTER TABLE paste ALTER filename DROP NOT NULL');
$this->addSql('ALTER TABLE paste ALTER expiration_date DROP NOT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('ALTER TABLE paste ALTER language SET NOT NULL');
$this->addSql('ALTER TABLE paste ALTER description SET NOT NULL');
$this->addSql('ALTER TABLE paste ALTER filename SET NOT NULL');
$this->addSql('ALTER TABLE paste ALTER expiration_date SET NOT NULL');
}
}

View file

@ -1,32 +0,0 @@
<?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 Version20230720130259 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->addSql('ALTER TABLE paste ALTER secret DROP NOT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('ALTER TABLE paste ALTER secret SET NOT NULL');
}
}

View file

View file

@ -1,54 +1,65 @@
<?php
declare(strict_types = 1);
namespace App\Controller;
namespace App\Controller;
use App\Form\Type\PasteForm;
use App\Entity\Paste;
use App\Repository\PasteRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use App\DTO\PasteFormData;
use App\Entity\Paste;
use App\Form\Type\PasteForm;
use App\Repository\PasteRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
class PasteController extends AbstractController
{
#[Route('/')]
public function new(Request $request, EntityManagerInterface $entityManager): Response {
$paste = new Paste();
$form = $this->createForm(PasteForm::class, $paste);
public function new(Request $request, PasteRepository $pasteRepository): Response
{
$pasteData = new PasteFormData();
$form = $this->createForm(PasteForm::class, $pasteData);
$form->handleRequest($request);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$paste = $form->getData();
$paste->setIp($request->getClientIp());
$paste->setPublishDate(new \DateTime());
$pasteData = $form->getData();
if ($paste->isPrivate()) {
$paste->setSecret(hash("sha1", random_bytes(25)));
$secret = null;
if ($pasteData->private) {
$secret = hash('sha1', random_bytes(25));
}
$entityManager->persist($paste);
$entityManager->flush();
$paste = new Paste(
$pasteData->text,
$pasteData->language,
$pasteData->description,
$pasteData->filename,
$pasteData->author,
new \DateTimeImmutable(),
$pasteData->expirationDate,
$request->getClientIp(),
$secret
);
$pasteRepository->save($paste);
return $this->redirectToRoute($request->attributes->get('_route'));
return $this->redirectToRoute($request->attributes->get('_route'));
}
return $this->render('paste.html.twig', [
'form' => $form,
]);
]);
}
#[Route('/{id}/{secret}')]
public function show_paste(PasteRepository $pasteRepository, Request $request, string $id, ?string $secret=NULL): Response {
$paste = $pasteRepository->findOneBy(["id" => $id, "secret" => $secret]);
$form = $this->createForm(PasteForm::class, $paste);
public function showPaste(PasteRepository $pasteRepository, string $id, ?string $secret=NULL): Response
{
$paste = $pasteRepository->findOneBy(['id' => $id, 'secret' => $secret]);
$pasteData = new PasteFormData($paste);
$form = $this->createForm(PasteForm::class, $pasteData);
return $this->render('paste.html.twig', [
'form' => $form,
]);
]);
}
}

38
src/DTO/PasteFormData.php Normal file
View file

@ -0,0 +1,38 @@
<?php
declare(strict_types = 1);
namespace App\DTO;
use App\Entity\Paste;
use Symfony\Component\Validator\Constraints as Assert;
class PasteFormData
{
#[Assert\NotBlank]
public string $text;
#[Assert\Type(\boolean::class)]
public bool $private;
public ?string $language = null;
public ?string $description = null;
public ?string $filename = null;
#[Assert\NotBlank]
public string $author = 'anonymous';
#[Assert\Type(\DateTimeImmutable::class)]
public ?\DateTimeImmutable $expirationDate;
public function __construct(?Paste $paste=null)
{
if ($paste === null)
{
return;
}
$this->text = $paste->text;
$this->private = $paste->secret !== null;
$this->language = $paste->language;
$this->description = $paste->description;
$this->filename = $paste->filename;
$this->author = $paste->author;
$this->expirationDate = $paste->expirationDate;
}
}

View file

View file

@ -1,139 +1,38 @@
<?php
namespace App\Entity;
declare(strict_types = 1);
use App\Repository\PasteRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
namespace App\Entity;
use App\Repository\PasteRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: PasteRepository::class)]
class Paste
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(nullable: false)]
private int $id;
#[ORM\Column]
public readonly int $id;
#[ORM\Column(type: "text", nullable: false)]
#[Assert\NotBlank]
private string $text;
#[ORM\Column(type: "boolean", nullable: false)]
#[Assert\Type(\boolean::class)]
private bool $private;
#[ORM\Column(length: 25, nullable: true)]
private ?string $language;
#[ORM\Column(type: "text", nullable: true)]
private ?string $description;
#[ORM\Column(length: 128, nullable: true)]
private ?string $filename;
#[ORM\Column(length: 128, nullable: false)]
#[Assert\NotBlank]
private string $author = "anonymous";
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: false)]
#[Assert\Type(\DateTime::class)]
private \DateTime $publishDate;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
#[Assert\Type(\DateTime::class)]
private ?\DateTime $expirationDate;
#[ORM\Column(length: 15, nullable: false)]
private string $ip;
#[ORM\Column(length: 40, nullable: true)]
private ?string $secret;
public function getId(): int {
return $this->id;
}
public function setId(int $id): void {
$this->id = $id;
}
public function getText(): string {
return $this->text;
}
public function setText(string $text): void {
$this->text = $text;
}
public function getLanguage(): ?string {
return $this->language;
}
public function setLanguage(?string $language): void {
$this->language = $language;
}
public function getDescription(): ?string {
return $this->description;
}
public function setDescription(?string $description): void {
$this->description = $description;
}
public function getFilename(): ?string {
return $this->filename;
}
public function setFilename(?string $filename): void {
$this->filename = $filename;
}
public function getAuthor(): string {
return $this->author;
}
public function setAuthor(string $author): void {
$this->author = $author;
}
public function getPublishDate(): \DateTime {
return $this->publishDate;
}
public function setPublishDate(\DateTime $date): void {
$this->publishDate = $date;
}
public function getExpirationDate(): ?\DateTime {
return $this->expirationDate;
}
public function setExpirationDate(?\DateTime $date): void {
$this->expirationDate = $date;
}
public function getIp(): string {
return $this->ip;
}
public function setIP(string $ip): void {
$this->ip = $ip;
}
public function getSecret(): ?string {
return $this->secret;
}
public function setSecret(?string $secret): void {
$this->secret = $secret;
}
public function isPrivate(): bool {
return $this->private;
}
public function setPrivate(bool $private): void {
$this->private = $private;
}
public function __construct(
#[ORM\Column(type: 'text', nullable: false)]
public readonly string $text,
#[ORM\Column(length: 25, nullable: true)]
public readonly ?string $language,
#[ORM\Column(type: 'text', nullable: true)]
public readonly ?string $description,
#[ORM\Column(length: 128, nullable: true)]
public readonly ?string $filename,
#[ORM\Column(length: 128, nullable: false)]
public readonly string $author,
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: false)]
public readonly \DateTimeImmutable $publishDate,
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)]
public readonly ?\DateTimeImmutable $expirationDate,
#[ORM\Column(length: 15, nullable: false)]
public readonly string $ip,
#[ORM\Column(length: 40, nullable: true)]
public readonly ?string $secret,
) {}
}

View file

@ -1,28 +1,43 @@
<?php
namespace App\Form\Type;
declare(strict_types = 1);
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
class PasteForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void {
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add("language", ChoiceType::class, ["choices" => ["Python" => "python", "PHP" => "php", "Plain text" => NULL]])
->add("description", TextType::class, ["required" => false])
->add("text", TextareaType::class)
->add("author", TextType::class, ["attr" => ["maxlength" =>128]])
->add("filename", TextType::class, ["required" => false, "attr" => ["maxlength" =>128]])
->add("expirationDate", DateTimeType::class, ["required" => false, "date_widget" => "single_text", "input" => "datetime"])
->add("private", CheckboxType::class, ["required" => false])
->add("save", SubmitType::class)
;
->add('language', ChoiceType::class, [
'choices' => [
'Python' => 'python',
'PHP' => 'php',
'Plain text' => NULL,
]
]
)
->add('description', TextType::class, ['required' => false])
->add('text', TextareaType::class)
->add('author', TextType::class, ['attr' => ['maxlength' =>128]])
->add('filename', TextType::class, ['required' => false, 'attr' => ['maxlength' =>128]])
->add('expirationDate', DateTimeType::class, [
'required' => false,
'date_widget' => 'single_text',
'input' => 'datetime_immutable',
]
)
->add('private', CheckboxType::class, ['required' => false])
->add('save', SubmitType::class)
;
}
}

View file

View file

@ -1,14 +1,23 @@
<?php
declare(strict_types = 1);
namespace App\Repository;
namespace App\Repository;
use App\Entity\Paste;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use App\Entity\Paste;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class PasteRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry) {
parent::__construct($registry, Paste::class);
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Paste::class);
}
public function save(Paste $paste): void
{
$entityManager = $this->getEntityManager();
$entityManager->persist($paste);
$entityManager->flush();
}
}