diff --git a/composer.phar b/composer.phar new file mode 100755 index 0000000..6d812d6 Binary files /dev/null and b/composer.phar differ diff --git a/composer_2.phar b/composer_2.phar new file mode 100644 index 0000000..6d812d6 Binary files /dev/null and b/composer_2.phar differ diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 7b38924..e7168f5 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -34,7 +34,8 @@ security: # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used access_control: - - { path: ^/task/*, roles: ROLE_USER } + - { path: ^/tasks/*, roles: ROLE_USER } + - { path: ^/projects/*, roles: ROLE_USER } # - { path: ^/admin, roles: ROLE_ADMIN } # - { path: ^/profile, roles: ROLE_USER } diff --git a/migrations/Version20220408194827.php b/migrations/Version20220408194827.php deleted file mode 100644 index 6a2aa37..0000000 --- a/migrations/Version20220408194827.php +++ /dev/null @@ -1,31 +0,0 @@ -addSql('CREATE TABLE task (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, description TINYTEXT NOT NULL, due_date DATE NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('DROP TABLE task'); - } -} diff --git a/migrations/Version20220409071443.php b/migrations/Version20220409071443.php deleted file mode 100644 index 8f72bf1..0000000 --- a/migrations/Version20220409071443.php +++ /dev/null @@ -1,31 +0,0 @@ -addSql('ALTER TABLE task ADD is_completed TINYINT(1) DEFAULT NULL'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE task DROP is_completed'); - } -} diff --git a/migrations/Version20220409072039.php b/migrations/Version20220409072039.php deleted file mode 100644 index 9fad974..0000000 --- a/migrations/Version20220409072039.php +++ /dev/null @@ -1,32 +0,0 @@ -addSql('UPDATE task set is_completed = 0'); - - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - - } -} diff --git a/migrations/Version20220423060135.php b/migrations/Version20220423060135.php deleted file mode 100644 index 53a57a5..0000000 --- a/migrations/Version20220423060135.php +++ /dev/null @@ -1,31 +0,0 @@ -addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(180) NOT NULL, roles LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\', password VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('DROP TABLE user'); - } -} diff --git a/migrations/Version20220529203600.php b/migrations/Version20220529203600.php new file mode 100644 index 0000000..92eb6ed --- /dev/null +++ b/migrations/Version20220529203600.php @@ -0,0 +1,65 @@ +abortIf( + !$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MariaDb1027Platform, + "Migration can only be executed safely on '\Doctrine\DBAL\Platforms\MariaDb1027Platform'." + ); + + $this->addSql('CREATE TABLE project (id INT AUTO_INCREMENT NOT NULL, owner_id INT DEFAULT NULL, token VARCHAR(5) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, name VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, INDEX IDX_2FB3D0EE7E3C61F9 (owner_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); + $this->abortIf( + !$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MariaDb1027Platform, + "Migration can only be executed safely on '\Doctrine\DBAL\Platforms\MariaDb1027Platform'." + ); + + $this->addSql('CREATE TABLE task (id INT AUTO_INCREMENT NOT NULL, author_id INT DEFAULT NULL, name VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, description TINYTEXT CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, due_date DATE NOT NULL, is_completed TINYINT(1) DEFAULT 0 NOT NULL, INDEX IDX_527EDB25F675F31B (author_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); + $this->abortIf( + !$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MariaDb1027Platform, + "Migration can only be executed safely on '\Doctrine\DBAL\Platforms\MariaDb1027Platform'." + ); + + $this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(180) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, roles LONGTEXT CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci` COMMENT \'(DC2Type:json)\', password VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf( + !$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MariaDb1027Platform, + "Migration can only be executed safely on '\Doctrine\DBAL\Platforms\MariaDb1027Platform'." + ); + + $this->addSql('DROP TABLE project'); + $this->abortIf( + !$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MariaDb1027Platform, + "Migration can only be executed safely on '\Doctrine\DBAL\Platforms\MariaDb1027Platform'." + ); + + $this->addSql('DROP TABLE task'); + $this->abortIf( + !$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MariaDb1027Platform, + "Migration can only be executed safely on '\Doctrine\DBAL\Platforms\MariaDb1027Platform'." + ); + + $this->addSql('DROP TABLE user'); + } +} diff --git a/migrations/Version20220423072607.php b/migrations/Version20220529203620.php similarity index 59% rename from migrations/Version20220423072607.php rename to migrations/Version20220529203620.php index e8775c0..b8d9234 100644 --- a/migrations/Version20220423072607.php +++ b/migrations/Version20220529203620.php @@ -10,7 +10,7 @@ /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20220423072607 extends AbstractMigration +final class Version20220529203620 extends AbstractMigration { public function getDescription(): string { @@ -20,16 +20,16 @@ public function getDescription(): string public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE task ADD author_id INT DEFAULT NULL'); - $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25F675F31B FOREIGN KEY (author_id) REFERENCES user (id)'); - $this->addSql('CREATE INDEX IDX_527EDB25F675F31B ON task (author_id)'); + $this->addSql('ALTER TABLE task ADD project_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25166D1F9C FOREIGN KEY (project_id) REFERENCES project (id)'); + $this->addSql('CREATE INDEX IDX_527EDB25166D1F9C ON task (project_id)'); } public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE task DROP FOREIGN KEY FK_527EDB25F675F31B'); - $this->addSql('DROP INDEX IDX_527EDB25F675F31B ON task'); - $this->addSql('ALTER TABLE task DROP author_id, CHANGE is_completed is_completed TINYINT(1) DEFAULT NULL'); + $this->addSql('ALTER TABLE task DROP FOREIGN KEY FK_527EDB25166D1F9C'); + $this->addSql('DROP INDEX IDX_527EDB25166D1F9C ON task'); + $this->addSql('ALTER TABLE task DROP project_id'); } } diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php new file mode 100644 index 0000000..1ac1433 --- /dev/null +++ b/src/Controller/ProjectController.php @@ -0,0 +1,77 @@ +createForm(ProjectType::class, $project); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + + $project->setOwner($this->getUser()); + + $this->getDoctrine()->getManager()->persist($project); + $this->getDoctrine()->getManager()->flush(); + + return $this->redirectToRoute('project_list'); + } + + return $this->render("project/create.html.twig", [ + 'form' => $form->createView() + ]); + + } + + /** + * @Route("/projects", name = "project_list") + * @return Response + */ + public function list(Request $request): Response + { + $projects = $this->getDoctrine()->getManager() + ->getRepository(Project::class)->findAllByUser($this->getUser()); + return $this->render('project/list.html.twig', [ + 'projects' => $projects, + ]); + } + + /** + * @Route("/projects/{id}", name="project_page") + * @param $id + * @return Response + */ + public function projectPage($id): Response + { + $project = $this->getDoctrine()->getManager() + ->getRepository(Project::class)->findOneBy(['token' => $id]); + + $tasks = $this->getDoctrine()->getManager() + ->getRepository(Task::class)->findAllByProject($project); + + return $this->render('project/project.html.twig', [ + 'project' => $project, + 'tasks' => $tasks + ]); + } +} \ No newline at end of file diff --git a/src/Controller/TaskController.php b/src/Controller/TaskController.php index 0d9f9ad..3e45f9e 100644 --- a/src/Controller/TaskController.php +++ b/src/Controller/TaskController.php @@ -2,6 +2,7 @@ namespace App\Controller; +use App\Entity\Project; use App\Entity\Task; use App\Type\TaskFilterType; use App\Type\TaskType; @@ -22,13 +23,21 @@ class TaskController extends AbstractController public function create(Request $request): Response { $task = new Task(); - $form = $this->createForm(TaskType::class, $task); + $form = $this->createForm(TaskType::class, $task, ["data" => $this->getDoctrine()->getManager() + ->getRepository(Project::class)->findAllByUser($this->getUser())]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { +// var_dump($form); + $task->setAuthor($this->getUser()); + $task->setName($form->get('name')->getData()); + $task->setDueDate($form->get('dueDate')->getData()); + $task->setDescription($form->get('description')->getData()); + $task->setProject($this->getDoctrine()->getManager() + ->getRepository(Project::class)->find($form->get('project')->getData())); $this->getDoctrine()->getManager()->persist($task); $this->getDoctrine()->getManager()->flush(); @@ -74,7 +83,6 @@ public function list(Request $request): Response } - return $this->render('task/list.html.twig', [ 'tasks' => $tasks, 'filterForm' => $taskFilterForm->createView() @@ -86,8 +94,11 @@ public function list(Request $request): Response * @IsGranted("ROLE_USER") * @return Response */ - public function complete($id): Response + public function complete(Request $request): Response { + $id = $request->get('id'); + $token = $request->get('token'); + /** @var Task $task */ $task = $this->getDoctrine()->getManager()->find(Task::class, $id); @@ -102,6 +113,10 @@ public function complete($id): Response $this->getDoctrine()->getManager()->persist($task); $this->getDoctrine()->getManager()->flush(); + if ($token !== null) { + return $this->redirectToRoute('project_page', ["id" => $token]); + } + return $this->redirectToRoute('task_list'); } } \ No newline at end of file diff --git a/src/Entity/Project.php b/src/Entity/Project.php new file mode 100644 index 0000000..4097db9 --- /dev/null +++ b/src/Entity/Project.php @@ -0,0 +1,105 @@ +id; + } + + /** + * @param mixed $name + */ + public function setToken($token): void + { + $this->token = $token; + } + + /** + * @return mixed + */ + public function getToken() + { + return $this->token; + } + + /** + * @param mixed $name + */ + public function setName($name): void + { + $this->name = $name; + } + + /** + * @return mixed + */ + public function getName() + { + return $this->name; + } + + /** + * Set task Author + * @param User|null $author + * @return void + */ + public function setOwner(UserInterface $owner = null) + { + $this->owner = $owner; + } + + /** + * Return task author + * @return User|null + */ + public function getOwner() + { + return $this->owner; + } +} diff --git a/src/Entity/Task.php b/src/Entity/Task.php index 66a4b57..2312c33 100644 --- a/src/Entity/Task.php +++ b/src/Entity/Task.php @@ -55,6 +55,12 @@ class Task */ protected $author; + /** + * @ORM\ManyToOne(targetEntity="App\Entity\Project", inversedBy="project") + * @var Project + */ + protected $project; + /** * Create empty task */ @@ -161,7 +167,25 @@ public function setIsCompleted(bool $isCompleted = false) $this->isCompleted = $isCompleted; } + /** + * Set task Project + * @param Project|null $project + * @return void + */ + public function setProject(Project $project = null) + { + $this->project = $project; + } + + /** + * Return task author + * @return Project|null + */ + public function getProject(): ?Project + { + return $this->project; + } } \ No newline at end of file diff --git a/src/Repository/ProjectRepository.php b/src/Repository/ProjectRepository.php new file mode 100644 index 0000000..64844d7 --- /dev/null +++ b/src/Repository/ProjectRepository.php @@ -0,0 +1,38 @@ +findAll(); + if(in_array('ROLE_ADMIN', $user->getRoles())) { + return $allProjects; + } + + return $this->filterByUser($allProjects, $user); + } + + private function filterByUser(array $projects, User $user): array{ + $result = array(); + foreach ($projects as $project ){ + if ($project->getOwner()->getEmail() === $user->getEmail()){ + array_push($result, $project); + } + } + return $result; +// return $project->getOwner()->getEmail() === $user->getEmail(); + } +} \ No newline at end of file diff --git a/src/Repository/TaskRepository.php b/src/Repository/TaskRepository.php index 43cc1ba..125231a 100644 --- a/src/Repository/TaskRepository.php +++ b/src/Repository/TaskRepository.php @@ -2,6 +2,7 @@ namespace App\Repository; +use App\Entity\Project; use App\Entity\Task; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\EntityRepository; @@ -14,5 +15,20 @@ public function __construct(ManagerRegistry $registry) parent::__construct($registry, Task::class); } + public function findAllByProject(Project $project): array + { + $allTasks = $this->findAll(); + return $this->filterByProject($allTasks, $project); + } + private function filterByProject(array $tasks, Project $project): array{ + $result = array(); + foreach ($tasks as $task){ + if ($task->getProject()->getToken() === $project->getToken()){ + array_push($result, $task); + } + } + return $result; +// return $project->getOwner()->getEmail() === $user->getEmail(); + } } \ No newline at end of file diff --git a/src/Type/ProjectType.php b/src/Type/ProjectType.php new file mode 100644 index 0000000..a61bf92 --- /dev/null +++ b/src/Type/ProjectType.php @@ -0,0 +1,22 @@ +add('token', TextType::class) + ->add('name', TextType::class) + ->add('save', SubmitType::class) + ; + } +} \ No newline at end of file diff --git a/src/Type/TaskType.php b/src/Type/TaskType.php index 3b58193..897348f 100644 --- a/src/Type/TaskType.php +++ b/src/Type/TaskType.php @@ -3,6 +3,7 @@ namespace App\Type; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\DateType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; @@ -13,13 +14,18 @@ class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { + $builder ->add('name', TextType::class) ->add('description', TextareaType::class) + ->add('project', ChoiceType::class, [ + 'choices' => $options["data"], + 'choice_label' => 'name', + 'choice_value' => 'token' + ]) ->add('dueDate', DateType::class, [ - 'years' => range(2022,2023) + 'years' => range(2022, 2023) ]) - ->add('save', SubmitType::class) - ; + ->add('save', SubmitType::class); } } \ No newline at end of file diff --git a/templates/project/create.html.twig b/templates/project/create.html.twig new file mode 100644 index 0000000..fa54bb7 --- /dev/null +++ b/templates/project/create.html.twig @@ -0,0 +1,16 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +
| ID Token | +Ключ | +Название | +Владелец | +Страница проекта | +
|---|---|---|---|---|
| {{ project.id }} | +{{ project.token }} | +{{ project.name }} | +{{ project.owner.email }} | +{{ project.name }} | +
Page of project {{ project.name }}
+ +| # | +Название | +Описание | +Срок выполнения | +Автор | +Выполнена | +Действия | +
|---|---|---|---|---|---|---|
| {{ task.id }} | +{{ task.name }} | +{{ task.description }} | +{{ task.dueDate|date("d.m.Y") }} | +{{ task.author }} | +{{ task.isCompleted ? 'Выполнена' : 'Не выполнена' }} | ++ {% if not (task.isCompleted) %} +{# Сделано#} + Сделано + {% endif %} + | +