TaskSchema module
This commit is contained in:
@@ -38,3 +38,10 @@ CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1|haushalt\.ddev\.site)(:[0-9
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> symfony/messenger ###
|
||||
# Choose one of the transports below
|
||||
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
||||
###< symfony/messenger ###
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
"symfony/dotenv": "7.4.*",
|
||||
"symfony/flex": "^2",
|
||||
"symfony/framework-bundle": "7.4.*",
|
||||
"symfony/messenger": "7.4.*",
|
||||
"symfony/property-access": "7.4.*",
|
||||
"symfony/property-info": "7.4.*",
|
||||
"symfony/runtime": "7.4.*",
|
||||
"symfony/scheduler": "7.4.*",
|
||||
"symfony/serializer": "7.4.*",
|
||||
"symfony/validator": "7.4.*",
|
||||
"symfony/yaml": "7.4.*"
|
||||
|
||||
307
backend/composer.lock
generated
307
backend/composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "36cb2b820400a518223222a28461ff75",
|
||||
"content-hash": "3faf0714de84c701cf5b3c444ce28e8b",
|
||||
"packages": [
|
||||
{
|
||||
"name": "doctrine/collections",
|
||||
@@ -1456,6 +1456,54 @@
|
||||
},
|
||||
"time": "2021-02-03T23:26:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/clock",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/clock.git",
|
||||
"reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
|
||||
"reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.0 || ^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Clock\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for reading the clock.",
|
||||
"homepage": "https://github.com/php-fig/clock",
|
||||
"keywords": [
|
||||
"clock",
|
||||
"now",
|
||||
"psr",
|
||||
"psr-20",
|
||||
"time"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/clock/issues",
|
||||
"source": "https://github.com/php-fig/clock/tree/1.0.0"
|
||||
},
|
||||
"time": "2022-11-25T14:36:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "2.0.2",
|
||||
@@ -1789,6 +1837,84 @@
|
||||
],
|
||||
"time": "2025-03-13T15:25:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/clock",
|
||||
"version": "v7.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/clock.git",
|
||||
"reference": "674fa3b98e21531dd040e613479f5f6fa8f32111"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111",
|
||||
"reference": "674fa3b98e21531dd040e613479f5f6fa8f32111",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"psr/clock": "^1.0",
|
||||
"symfony/polyfill-php83": "^1.28"
|
||||
},
|
||||
"provide": {
|
||||
"psr/clock-implementation": "1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/now.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Clock\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Decouples applications from the system clock",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"clock",
|
||||
"psr20",
|
||||
"time"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/clock/tree/v7.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-24T13:12:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v7.4.7",
|
||||
@@ -3121,6 +3247,100 @@
|
||||
],
|
||||
"time": "2026-03-06T16:33:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/messenger",
|
||||
"version": "v7.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/messenger.git",
|
||||
"reference": "ddf5ab29bc0329ece30e16f01c86abb6241e92d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/messenger/zipball/ddf5ab29bc0329ece30e16f01c86abb6241e92d8",
|
||||
"reference": "ddf5ab29bc0329ece30e16f01c86abb6241e92d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/clock": "^6.4|^7.0|^8.0",
|
||||
"symfony/deprecation-contracts": "^2.5|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<7.2",
|
||||
"symfony/event-dispatcher": "<6.4",
|
||||
"symfony/event-dispatcher-contracts": "<2.5",
|
||||
"symfony/framework-bundle": "<6.4",
|
||||
"symfony/http-kernel": "<7.3",
|
||||
"symfony/lock": "<7.4",
|
||||
"symfony/serializer": "<6.4.32|>=7.3,<7.3.10|>=7.4,<7.4.4|>=8.0,<8.0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/cache": "^1.0|^2.0|^3.0",
|
||||
"symfony/console": "^7.2|^8.0",
|
||||
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
|
||||
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
||||
"symfony/http-kernel": "^7.3|^8.0",
|
||||
"symfony/lock": "^7.4|^8.0",
|
||||
"symfony/process": "^6.4|^7.0|^8.0",
|
||||
"symfony/property-access": "^6.4|^7.0|^8.0",
|
||||
"symfony/rate-limiter": "^6.4|^7.0|^8.0",
|
||||
"symfony/routing": "^6.4|^7.0|^8.0",
|
||||
"symfony/serializer": "^6.4.32|~7.3.10|^7.4.4|^8.0.4",
|
||||
"symfony/service-contracts": "^2.5|^3",
|
||||
"symfony/stopwatch": "^6.4|^7.0|^8.0",
|
||||
"symfony/validator": "^6.4|^7.0|^8.0",
|
||||
"symfony/var-dumper": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Messenger\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Samuel Roze",
|
||||
"email": "samuel.roze@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Helps applications send and receive messages to/from other applications or via message queues",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/messenger/tree/v7.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-30T12:55:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.33.0",
|
||||
@@ -3952,6 +4172,91 @@
|
||||
],
|
||||
"time": "2025-12-05T14:04:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/scheduler",
|
||||
"version": "v7.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/scheduler.git",
|
||||
"reference": "f95e696edaad466db9b087a6480ef936c766c3de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/scheduler/zipball/f95e696edaad466db9b087a6480ef936c766c3de",
|
||||
"reference": "f95e696edaad466db9b087a6480ef936c766c3de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/clock": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dragonmantank/cron-expression": "^3.1",
|
||||
"symfony/cache": "^6.4|^7.0|^8.0",
|
||||
"symfony/console": "^6.4|^7.0|^8.0",
|
||||
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
|
||||
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
||||
"symfony/lock": "^6.4|^7.0|^8.0",
|
||||
"symfony/messenger": "^6.4|^7.0|^8.0",
|
||||
"symfony/serializer": "^6.4|^7.1|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Scheduler\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sergey Rabochiy",
|
||||
"email": "upyx.00@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides scheduling through Symfony Messenger",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"cron",
|
||||
"schedule",
|
||||
"scheduler"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/scheduler/tree/v7.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-24T13:12:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/serializer",
|
||||
"version": "v7.4.7",
|
||||
|
||||
8
backend/config/packages/messenger.yaml
Normal file
8
backend/config/packages/messenger.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
framework:
|
||||
messenger:
|
||||
transports:
|
||||
sync: 'sync://'
|
||||
scheduler_default: 'scheduler://default'
|
||||
|
||||
routing:
|
||||
App\Message\GenerateTasksMessage: scheduler_default
|
||||
@@ -426,7 +426,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* resources?: array<string, scalar|Param|null>,
|
||||
* },
|
||||
* messenger?: bool|array{ // Messenger configuration
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* enabled?: bool|Param, // Default: true
|
||||
* routing?: array<string, string|array{ // Default: []
|
||||
* senders?: list<scalar|Param|null>,
|
||||
* }>,
|
||||
@@ -468,7 +468,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* }>,
|
||||
* },
|
||||
* scheduler?: bool|array{ // Scheduler configuration
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* enabled?: bool|Param, // Default: true
|
||||
* },
|
||||
* disallow_search_engine_index?: bool|Param, // Enabled by default when debug is enabled. // Default: true
|
||||
* http_client?: bool|array{ // HTTP Client configuration
|
||||
|
||||
37
backend/migrations/Version20260412094958.php
Normal file
37
backend/migrations/Version20260412094958.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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 Version20260412094958 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('CREATE TABLE task_schema (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, status VARCHAR(255) NOT NULL, task_status VARCHAR(255) NOT NULL, date DATE DEFAULT NULL, `repeat` JSON DEFAULT NULL, start DATE DEFAULT NULL, end DATE DEFAULT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
|
||||
$this->addSql('ALTER TABLE task ADD schema_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25EA1BEF35 FOREIGN KEY (schema_id) REFERENCES task_schema (id) ON DELETE SET NULL');
|
||||
$this->addSql('CREATE INDEX IDX_527EDB25EA1BEF35 ON task (schema_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP TABLE task_schema');
|
||||
$this->addSql('ALTER TABLE task DROP FOREIGN KEY FK_527EDB25EA1BEF35');
|
||||
$this->addSql('DROP INDEX IDX_527EDB25EA1BEF35 ON task');
|
||||
$this->addSql('ALTER TABLE task DROP schema_id');
|
||||
}
|
||||
}
|
||||
BIN
backend/public/app/haushalt.apk
Normal file
BIN
backend/public/app/haushalt.apk
Normal file
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"versionCode": 1,
|
||||
"versionCode": 2,
|
||||
"apkFile": "haushalt.apk"
|
||||
}
|
||||
|
||||
29
backend/src/Collection/TaskSchemaCollection.php
Normal file
29
backend/src/Collection/TaskSchemaCollection.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Collection;
|
||||
|
||||
use App\Entity\TaskSchema;
|
||||
|
||||
/**
|
||||
* @implements \IteratorAggregate<int, TaskSchema>
|
||||
*/
|
||||
final class TaskSchemaCollection implements \IteratorAggregate
|
||||
{
|
||||
/** @var list<TaskSchema> */
|
||||
private array $schemas = [];
|
||||
|
||||
/**
|
||||
* @param list<TaskSchema> $schemas
|
||||
*/
|
||||
public function __construct(array $schemas = [])
|
||||
{
|
||||
foreach ($schemas as $schema) {
|
||||
$this->schemas[] = $schema;
|
||||
}
|
||||
}
|
||||
|
||||
public function getIterator(): \Iterator
|
||||
{
|
||||
return new \ArrayIterator($this->schemas);
|
||||
}
|
||||
}
|
||||
@@ -45,14 +45,6 @@ class TaskController extends AbstractController
|
||||
return $this->json($task, 200, [], ['groups' => ['task:read']]);
|
||||
}
|
||||
|
||||
#[Route('', methods: ['POST'])]
|
||||
public function create(#[Payload] TaskRequest $dto): JsonResponse
|
||||
{
|
||||
$task = $this->manager->create($dto);
|
||||
|
||||
return $this->json($task, 201, [], ['groups' => ['task:read']]);
|
||||
}
|
||||
|
||||
#[Route('/{id}', methods: ['PUT'], requirements: ['id' => '\d+'])]
|
||||
public function update(Task $task, #[Payload] TaskRequest $dto): JsonResponse
|
||||
{
|
||||
|
||||
60
backend/src/Controller/Api/TaskSchemaController.php
Normal file
60
backend/src/Controller/Api/TaskSchemaController.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Api;
|
||||
|
||||
use App\DTO\TaskSchemaRequest;
|
||||
use App\Entity\TaskSchema;
|
||||
use App\Repository\TaskSchemaRepository;
|
||||
use App\Service\TaskSchemaManager;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload as Payload;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/api/task-schemas')]
|
||||
class TaskSchemaController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TaskSchemaRepository $repo,
|
||||
private readonly TaskSchemaManager $manager,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('', methods: ['GET'])]
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$schemas = $this->repo->allSchemas();
|
||||
|
||||
return $this->json($schemas, 200, [], ['groups' => ['task_schema:read']]);
|
||||
}
|
||||
|
||||
#[Route('/{id}', methods: ['GET'], requirements: ['id' => '\d+'])]
|
||||
public function show(TaskSchema $schema): JsonResponse
|
||||
{
|
||||
return $this->json($schema, 200, [], ['groups' => ['task_schema:read']]);
|
||||
}
|
||||
|
||||
#[Route('', methods: ['POST'])]
|
||||
public function create(#[Payload] TaskSchemaRequest $dto): JsonResponse
|
||||
{
|
||||
$this->manager->create($dto);
|
||||
|
||||
return new JsonResponse(null, 201);
|
||||
}
|
||||
|
||||
#[Route('/{id}', methods: ['PUT'], requirements: ['id' => '\d+'])]
|
||||
public function update(TaskSchema $schema, #[Payload] TaskSchemaRequest $dto): JsonResponse
|
||||
{
|
||||
$this->manager->update($schema, $dto);
|
||||
|
||||
return $this->json($schema, 200, [], ['groups' => ['task_schema:read']]);
|
||||
}
|
||||
|
||||
#[Route('/{id}', methods: ['DELETE'], requirements: ['id' => '\d+'])]
|
||||
public function delete(TaskSchema $schema): JsonResponse
|
||||
{
|
||||
$this->manager->delete($schema);
|
||||
|
||||
return new JsonResponse(null, 204);
|
||||
}
|
||||
}
|
||||
36
backend/src/DTO/TaskSchemaRequest.php
Normal file
36
backend/src/DTO/TaskSchemaRequest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\DTO;
|
||||
|
||||
use App\Enum\TaskSchemaStatus;
|
||||
use App\Enum\TaskStatus;
|
||||
use Symfony\Component\Serializer\Attribute\Context;
|
||||
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
class TaskSchemaRequest
|
||||
{
|
||||
public function __construct(
|
||||
#[Assert\NotBlank]
|
||||
#[Assert\Length(max: 255)]
|
||||
public readonly string $name,
|
||||
|
||||
#[Assert\NotNull]
|
||||
public readonly TaskSchemaStatus $status = TaskSchemaStatus::Active,
|
||||
|
||||
#[Assert\NotNull]
|
||||
public readonly TaskStatus $taskStatus = TaskStatus::Active,
|
||||
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => '!Y-m-d'])]
|
||||
public readonly ?\DateTimeImmutable $date = null,
|
||||
|
||||
public readonly ?array $repeat = null,
|
||||
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => '!Y-m-d'])]
|
||||
public readonly ?\DateTimeImmutable $start = null,
|
||||
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => '!Y-m-d'])]
|
||||
public readonly ?\DateTimeImmutable $end = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ use App\Enum\TaskStatus;
|
||||
use App\Repository\TaskRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
use Symfony\Component\Serializer\Attribute\Ignore;
|
||||
|
||||
#[ORM\Entity(repositoryClass: TaskRepository::class)]
|
||||
class Task
|
||||
@@ -27,6 +28,11 @@ class Task
|
||||
#[ORM\Column(enumType: TaskStatus::class)]
|
||||
private TaskStatus $status = TaskStatus::Active;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TaskSchema::class, inversedBy: 'tasks')]
|
||||
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
|
||||
#[Ignore]
|
||||
private ?TaskSchema $schema = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@@ -77,4 +83,16 @@ class Task
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSchema(): ?TaskSchema
|
||||
{
|
||||
return $this->schema;
|
||||
}
|
||||
|
||||
public function setSchema(?TaskSchema $schema): self
|
||||
{
|
||||
$this->schema = $schema;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
158
backend/src/Entity/TaskSchema.php
Normal file
158
backend/src/Entity/TaskSchema.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Enum\TaskSchemaStatus;
|
||||
use App\Enum\TaskStatus;
|
||||
use App\Repository\TaskSchemaRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
|
||||
#[ORM\Entity(repositoryClass: TaskSchemaRepository::class)]
|
||||
class TaskSchema
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
#[Groups(['task_schema:read'])]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
#[Groups(['task_schema:read'])]
|
||||
private string $name = '';
|
||||
|
||||
#[ORM\Column(enumType: TaskSchemaStatus::class)]
|
||||
#[Groups(['task_schema:read'])]
|
||||
private TaskSchemaStatus $status = TaskSchemaStatus::Active;
|
||||
|
||||
#[ORM\Column(enumType: TaskStatus::class)]
|
||||
#[Groups(['task_schema:read'])]
|
||||
private TaskStatus $taskStatus = TaskStatus::Active;
|
||||
|
||||
#[ORM\Column(type: 'date_immutable', nullable: true)]
|
||||
#[Groups(['task_schema:read'])]
|
||||
private ?\DateTimeImmutable $date = null;
|
||||
|
||||
#[ORM\Column(name: '`repeat`', type: 'json', nullable: true)]
|
||||
#[Groups(['task_schema:read'])]
|
||||
private ?array $repeat = null;
|
||||
|
||||
#[ORM\Column(name: '`start`', type: 'date_immutable', nullable: true)]
|
||||
#[Groups(['task_schema:read'])]
|
||||
private ?\DateTimeImmutable $start = null;
|
||||
|
||||
#[ORM\Column(name: '`end`', type: 'date_immutable', nullable: true)]
|
||||
#[Groups(['task_schema:read'])]
|
||||
private ?\DateTimeImmutable $end = null;
|
||||
|
||||
/** @var Collection<int, Task> */
|
||||
#[ORM\OneToMany(targetEntity: Task::class, mappedBy: 'schema')]
|
||||
private Collection $tasks;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->tasks = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStatus(): TaskSchemaStatus
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function setStatus(TaskSchemaStatus $status): self
|
||||
{
|
||||
$this->status = $status;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTaskStatus(): TaskStatus
|
||||
{
|
||||
return $this->taskStatus;
|
||||
}
|
||||
|
||||
public function setTaskStatus(TaskStatus $taskStatus): self
|
||||
{
|
||||
$this->taskStatus = $taskStatus;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDate(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
public function setDate(?\DateTimeImmutable $date): self
|
||||
{
|
||||
$this->date = $date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRepeat(): ?array
|
||||
{
|
||||
return $this->repeat;
|
||||
}
|
||||
|
||||
public function getRepeatType(): ?string
|
||||
{
|
||||
return $this->repeat !== null ? array_key_first($this->repeat) : null;
|
||||
}
|
||||
|
||||
public function setRepeat(?array $repeat): self
|
||||
{
|
||||
$this->repeat = $repeat;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStart(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
public function setStart(?\DateTimeImmutable $start): self
|
||||
{
|
||||
$this->start = $start;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEnd(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->end;
|
||||
}
|
||||
|
||||
public function setEnd(?\DateTimeImmutable $end): self
|
||||
{
|
||||
$this->end = $end;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return Collection<int, Task> */
|
||||
public function getTasks(): Collection
|
||||
{
|
||||
return $this->tasks;
|
||||
}
|
||||
}
|
||||
9
backend/src/Enum/TaskSchemaStatus.php
Normal file
9
backend/src/Enum/TaskSchemaStatus.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enum;
|
||||
|
||||
enum TaskSchemaStatus: string
|
||||
{
|
||||
case Active = 'active';
|
||||
case Inactive = 'inactive';
|
||||
}
|
||||
7
backend/src/Message/GenerateTasksMessage.php
Normal file
7
backend/src/Message/GenerateTasksMessage.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Message;
|
||||
|
||||
final class GenerateTasksMessage
|
||||
{
|
||||
}
|
||||
20
backend/src/MessageHandler/GenerateTasksMessageHandler.php
Normal file
20
backend/src/MessageHandler/GenerateTasksMessageHandler.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\MessageHandler;
|
||||
|
||||
use App\Message\GenerateTasksMessage;
|
||||
use App\Service\TaskGenerator;
|
||||
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
||||
|
||||
#[AsMessageHandler]
|
||||
final class GenerateTasksMessageHandler
|
||||
{
|
||||
public function __construct(private TaskGenerator $generator)
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(GenerateTasksMessage $message): void
|
||||
{
|
||||
$this->generator->generateNewTasks();
|
||||
}
|
||||
}
|
||||
36
backend/src/Repository/TaskSchemaRepository.php
Normal file
36
backend/src/Repository/TaskSchemaRepository.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Collection\TaskSchemaCollection;
|
||||
use App\Entity\TaskSchema;
|
||||
use App\Enum\TaskSchemaStatus;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<TaskSchema>
|
||||
*/
|
||||
class TaskSchemaRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, TaskSchema::class);
|
||||
}
|
||||
|
||||
public function allSchemas(): TaskSchemaCollection
|
||||
{
|
||||
return new TaskSchemaCollection(parent::findAll());
|
||||
}
|
||||
|
||||
/** @return list<TaskSchema> */
|
||||
public function findActiveWithRepeat(): array
|
||||
{
|
||||
return $this->createQueryBuilder('s')
|
||||
->andWhere('s.status = :status')
|
||||
->andWhere('s.repeat IS NOT NULL')
|
||||
->setParameter('status', TaskSchemaStatus::Active)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
27
backend/src/Schedule.php
Normal file
27
backend/src/Schedule.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use App\Message\GenerateTasksMessage;
|
||||
use Symfony\Component\Scheduler\Attribute\AsSchedule;
|
||||
use Symfony\Component\Scheduler\RecurringMessage;
|
||||
use Symfony\Component\Scheduler\Schedule as SymfonySchedule;
|
||||
use Symfony\Component\Scheduler\ScheduleProviderInterface;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
|
||||
#[AsSchedule]
|
||||
class Schedule implements ScheduleProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private CacheInterface $cache,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getSchedule(): SymfonySchedule
|
||||
{
|
||||
return (new SymfonySchedule())
|
||||
->stateful($this->cache)
|
||||
->processOnlyLastMissedRun(true)
|
||||
->add(RecurringMessage::cron('0 3 * * *', new GenerateTasksMessage()));
|
||||
}
|
||||
}
|
||||
87
backend/src/Service/TaskGenerator.php
Normal file
87
backend/src/Service/TaskGenerator.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\Task;
|
||||
use App\Entity\TaskSchema;
|
||||
use App\Enum\TaskStatus;
|
||||
use App\Repository\TaskSchemaRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
class TaskGenerator
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $em,
|
||||
private TaskSchemaRepository $schemaRepo,
|
||||
) {
|
||||
}
|
||||
|
||||
public function generateNewTasks(): void
|
||||
{
|
||||
$schemas = $this->schemaRepo->findActiveWithRepeat();
|
||||
|
||||
foreach ($schemas as $schema) {
|
||||
$this->removeTasks($schema);
|
||||
$this->generateTasks($schema);
|
||||
}
|
||||
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
public function removeTasks(TaskSchema $schema): void
|
||||
{
|
||||
foreach ($schema->getTasks() as $task) {
|
||||
if ($task->getStatus() === TaskStatus::Past) continue;
|
||||
$this->em->remove($task);
|
||||
}
|
||||
}
|
||||
|
||||
public function generateTasks(TaskSchema $schema): void
|
||||
{
|
||||
$dates = $this->getDates($schema);
|
||||
|
||||
foreach ($dates as $date) {
|
||||
$task = new Task();
|
||||
$task->setName($schema->getName());
|
||||
$task->setDate($date);
|
||||
$task->setStatus($schema->getTaskStatus());
|
||||
$task->setSchema($schema);
|
||||
$this->em->persist($task);
|
||||
}
|
||||
}
|
||||
|
||||
/** @return array{\DateTimeImmutable, \DateTimeImmutable} */
|
||||
private function getDateRange(TaskSchema $schema): array
|
||||
{
|
||||
$today = new \DateTimeImmutable('today');
|
||||
$from = max($today, $schema->getStart() ?? $today);
|
||||
$end = min($today->modify('+14 days'), $schema->getEnd() ?? $today->modify('+14 days'));
|
||||
|
||||
return [$from, $end];
|
||||
}
|
||||
|
||||
/** @return list<\DateTimeImmutable> */
|
||||
private function getDates(TaskSchema $schema): array
|
||||
{
|
||||
[$from, $end] = $this->getDateRange($schema);
|
||||
$type = $schema->getRepeatType();
|
||||
$repeat = $schema->getRepeat();
|
||||
|
||||
$dates = [];
|
||||
for ($date = $from; $date <= $end; $date = $date->modify('+1 day')) {
|
||||
|
||||
if ($type === 'weekly') {
|
||||
$weekday = (int) $date->format('N') - 1;
|
||||
if(!$repeat['weekly'][$weekday]) continue;
|
||||
}
|
||||
if ($type === 'monthly') {
|
||||
$monthday = (int) $date->format('j') - 1;
|
||||
if(!$repeat['monthly'][$monthday]) continue;
|
||||
}
|
||||
|
||||
$dates[] = $date;
|
||||
}
|
||||
|
||||
return $dates;
|
||||
}
|
||||
}
|
||||
@@ -13,19 +13,6 @@ class TaskManager
|
||||
{
|
||||
}
|
||||
|
||||
public function create(TaskRequest $req): Task
|
||||
{
|
||||
$task = new Task();
|
||||
$task->setName($req->name);
|
||||
$task->setDate($req->date);
|
||||
$task->setStatus($req->status);
|
||||
|
||||
$this->em->persist($task);
|
||||
$this->em->flush();
|
||||
|
||||
return $task;
|
||||
}
|
||||
|
||||
public function update(Task $task, TaskRequest $req): Task
|
||||
{
|
||||
$task->setName($req->name);
|
||||
|
||||
79
backend/src/Service/TaskSchemaManager.php
Normal file
79
backend/src/Service/TaskSchemaManager.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\DTO\TaskSchemaRequest;
|
||||
use App\Entity\Task;
|
||||
use App\Entity\TaskSchema;
|
||||
use App\Enum\TaskSchemaStatus;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
class TaskSchemaManager
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $em,
|
||||
private TaskGenerator $generator,
|
||||
) {
|
||||
}
|
||||
|
||||
public function create(TaskSchemaRequest $req): void
|
||||
{
|
||||
if ($req->repeat === null) {
|
||||
$task = new Task();
|
||||
$task->setName($req->name);
|
||||
$task->setDate($req->date);
|
||||
$task->setStatus($req->taskStatus);
|
||||
$this->em->persist($task);
|
||||
$this->em->flush();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$schema = new TaskSchema();
|
||||
$schema->setName($req->name);
|
||||
$schema->setStatus($req->status);
|
||||
$schema->setTaskStatus($req->taskStatus);
|
||||
$schema->setDate($req->date);
|
||||
$schema->setRepeat($req->repeat);
|
||||
$schema->setStart($req->start);
|
||||
$schema->setEnd($req->end);
|
||||
$this->em->persist($schema);
|
||||
$this->em->flush();
|
||||
|
||||
if ($schema->getStatus() === TaskSchemaStatus::Inactive) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->generator->generateTasks($schema);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
public function update(TaskSchema $schema, TaskSchemaRequest $req): void
|
||||
{
|
||||
$schema->setName($req->name);
|
||||
$schema->setStatus($req->status);
|
||||
$schema->setTaskStatus($req->taskStatus);
|
||||
$schema->setDate($req->date);
|
||||
$schema->setRepeat($req->repeat);
|
||||
$schema->setStart($req->start);
|
||||
$schema->setEnd($req->end);
|
||||
|
||||
if ($schema->getStatus() === TaskSchemaStatus::Inactive) {
|
||||
$this->em->flush();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->generator->removeTasks($schema);
|
||||
$this->generator->generateTasks($schema);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
public function delete(TaskSchema $schema): void
|
||||
{
|
||||
$this->generator->removeTasks($schema);
|
||||
$this->em->remove($schema);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,6 +101,18 @@
|
||||
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
|
||||
}
|
||||
},
|
||||
"symfony/messenger": {
|
||||
"version": "7.4",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.0",
|
||||
"ref": "d8936e2e2230637ef97e5eecc0eea074eecae58b"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/messenger.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/property-info": {
|
||||
"version": "7.4",
|
||||
"recipe": {
|
||||
@@ -126,6 +138,18 @@
|
||||
"config/routes.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/scheduler": {
|
||||
"version": "7.4",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.2",
|
||||
"ref": "caea3c928ee9e1b21288fd76aef36f16ea355515"
|
||||
},
|
||||
"files": [
|
||||
"src/Schedule.php"
|
||||
]
|
||||
},
|
||||
"symfony/validator": {
|
||||
"version": "7.4",
|
||||
"recipe": {
|
||||
|
||||
3
backend/vendor/composer/autoload_files.php
vendored
3
backend/vendor/composer/autoload_files.php
vendored
@@ -13,6 +13,7 @@ return array(
|
||||
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
|
||||
'9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
|
||||
'662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php',
|
||||
'9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
|
||||
'2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php',
|
||||
);
|
||||
|
||||
4
backend/vendor/composer/autoload_psr4.php
vendored
4
backend/vendor/composer/autoload_psr4.php
vendored
@@ -28,11 +28,13 @@ return array(
|
||||
'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'),
|
||||
'Symfony\\Component\\Stopwatch\\' => array($vendorDir . '/symfony/stopwatch'),
|
||||
'Symfony\\Component\\Serializer\\' => array($vendorDir . '/symfony/serializer'),
|
||||
'Symfony\\Component\\Scheduler\\' => array($vendorDir . '/symfony/scheduler'),
|
||||
'Symfony\\Component\\Runtime\\' => array($vendorDir . '/symfony/runtime'),
|
||||
'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
|
||||
'Symfony\\Component\\PropertyInfo\\' => array($vendorDir . '/symfony/property-info'),
|
||||
'Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'),
|
||||
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
|
||||
'Symfony\\Component\\Messenger\\' => array($vendorDir . '/symfony/messenger'),
|
||||
'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
|
||||
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
|
||||
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
|
||||
@@ -43,6 +45,7 @@ return array(
|
||||
'Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'),
|
||||
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
|
||||
'Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'),
|
||||
'Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'),
|
||||
'Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'),
|
||||
'Symfony\\Bundle\\MakerBundle\\' => array($vendorDir . '/symfony/maker-bundle/src'),
|
||||
'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'),
|
||||
@@ -50,6 +53,7 @@ return array(
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
|
||||
'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'),
|
||||
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
||||
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
|
||||
'PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'),
|
||||
|
||||
23
backend/vendor/composer/autoload_static.php
vendored
23
backend/vendor/composer/autoload_static.php
vendored
@@ -14,8 +14,9 @@ class ComposerStaticInit75e7f8d848176580e9902a32f6f14640
|
||||
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
|
||||
'9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php',
|
||||
'662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php',
|
||||
'9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php',
|
||||
'2203a247e6fda86070a5e4e07aed533a' => __DIR__ . '/..' . '/symfony/clock/Resources/now.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
@@ -49,11 +50,13 @@ class ComposerStaticInit75e7f8d848176580e9902a32f6f14640
|
||||
'Symfony\\Component\\String\\' => 25,
|
||||
'Symfony\\Component\\Stopwatch\\' => 28,
|
||||
'Symfony\\Component\\Serializer\\' => 29,
|
||||
'Symfony\\Component\\Scheduler\\' => 28,
|
||||
'Symfony\\Component\\Runtime\\' => 26,
|
||||
'Symfony\\Component\\Routing\\' => 26,
|
||||
'Symfony\\Component\\PropertyInfo\\' => 31,
|
||||
'Symfony\\Component\\PropertyAccess\\' => 33,
|
||||
'Symfony\\Component\\Process\\' => 26,
|
||||
'Symfony\\Component\\Messenger\\' => 28,
|
||||
'Symfony\\Component\\HttpKernel\\' => 29,
|
||||
'Symfony\\Component\\HttpFoundation\\' => 33,
|
||||
'Symfony\\Component\\Finder\\' => 25,
|
||||
@@ -64,6 +67,7 @@ class ComposerStaticInit75e7f8d848176580e9902a32f6f14640
|
||||
'Symfony\\Component\\DependencyInjection\\' => 38,
|
||||
'Symfony\\Component\\Console\\' => 26,
|
||||
'Symfony\\Component\\Config\\' => 25,
|
||||
'Symfony\\Component\\Clock\\' => 24,
|
||||
'Symfony\\Component\\Cache\\' => 24,
|
||||
'Symfony\\Bundle\\MakerBundle\\' => 27,
|
||||
'Symfony\\Bundle\\FrameworkBundle\\' => 31,
|
||||
@@ -74,6 +78,7 @@ class ComposerStaticInit75e7f8d848176580e9902a32f6f14640
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\EventDispatcher\\' => 20,
|
||||
'Psr\\Container\\' => 14,
|
||||
'Psr\\Clock\\' => 10,
|
||||
'Psr\\Cache\\' => 10,
|
||||
'PhpParser\\' => 10,
|
||||
'PHPStan\\PhpDocParser\\' => 21,
|
||||
@@ -196,6 +201,10 @@ class ComposerStaticInit75e7f8d848176580e9902a32f6f14640
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/serializer',
|
||||
),
|
||||
'Symfony\\Component\\Scheduler\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/scheduler',
|
||||
),
|
||||
'Symfony\\Component\\Runtime\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/runtime',
|
||||
@@ -216,6 +225,10 @@ class ComposerStaticInit75e7f8d848176580e9902a32f6f14640
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/process',
|
||||
),
|
||||
'Symfony\\Component\\Messenger\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/messenger',
|
||||
),
|
||||
'Symfony\\Component\\HttpKernel\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/http-kernel',
|
||||
@@ -256,6 +269,10 @@ class ComposerStaticInit75e7f8d848176580e9902a32f6f14640
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/config',
|
||||
),
|
||||
'Symfony\\Component\\Clock\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/clock',
|
||||
),
|
||||
'Symfony\\Component\\Cache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/cache',
|
||||
@@ -284,6 +301,10 @@ class ComposerStaticInit75e7f8d848176580e9902a32f6f14640
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/container/src',
|
||||
),
|
||||
'Psr\\Clock\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/clock/src',
|
||||
),
|
||||
'Psr\\Cache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/cache/src',
|
||||
|
||||
317
backend/vendor/composer/installed.json
vendored
317
backend/vendor/composer/installed.json
vendored
@@ -1568,6 +1568,57 @@
|
||||
},
|
||||
"install-path": "../psr/cache"
|
||||
},
|
||||
{
|
||||
"name": "psr/clock",
|
||||
"version": "1.0.0",
|
||||
"version_normalized": "1.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/clock.git",
|
||||
"reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
|
||||
"reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.0 || ^8.0"
|
||||
},
|
||||
"time": "2022-11-25T14:36:26+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Clock\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for reading the clock.",
|
||||
"homepage": "https://github.com/php-fig/clock",
|
||||
"keywords": [
|
||||
"clock",
|
||||
"now",
|
||||
"psr",
|
||||
"psr-20",
|
||||
"time"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/clock/issues",
|
||||
"source": "https://github.com/php-fig/clock/tree/1.0.0"
|
||||
},
|
||||
"install-path": "../psr/clock"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "2.0.2",
|
||||
@@ -1916,6 +1967,87 @@
|
||||
],
|
||||
"install-path": "../symfony/cache-contracts"
|
||||
},
|
||||
{
|
||||
"name": "symfony/clock",
|
||||
"version": "v7.4.8",
|
||||
"version_normalized": "7.4.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/clock.git",
|
||||
"reference": "674fa3b98e21531dd040e613479f5f6fa8f32111"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111",
|
||||
"reference": "674fa3b98e21531dd040e613479f5f6fa8f32111",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"psr/clock": "^1.0",
|
||||
"symfony/polyfill-php83": "^1.28"
|
||||
},
|
||||
"provide": {
|
||||
"psr/clock-implementation": "1.0"
|
||||
},
|
||||
"time": "2026-03-24T13:12:05+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/now.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Clock\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Decouples applications from the system clock",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"clock",
|
||||
"psr20",
|
||||
"time"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/clock/tree/v7.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../symfony/clock"
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v7.4.7",
|
||||
@@ -3395,6 +3527,103 @@
|
||||
],
|
||||
"install-path": "../symfony/maker-bundle"
|
||||
},
|
||||
{
|
||||
"name": "symfony/messenger",
|
||||
"version": "v7.4.8",
|
||||
"version_normalized": "7.4.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/messenger.git",
|
||||
"reference": "ddf5ab29bc0329ece30e16f01c86abb6241e92d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/messenger/zipball/ddf5ab29bc0329ece30e16f01c86abb6241e92d8",
|
||||
"reference": "ddf5ab29bc0329ece30e16f01c86abb6241e92d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/clock": "^6.4|^7.0|^8.0",
|
||||
"symfony/deprecation-contracts": "^2.5|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<7.2",
|
||||
"symfony/event-dispatcher": "<6.4",
|
||||
"symfony/event-dispatcher-contracts": "<2.5",
|
||||
"symfony/framework-bundle": "<6.4",
|
||||
"symfony/http-kernel": "<7.3",
|
||||
"symfony/lock": "<7.4",
|
||||
"symfony/serializer": "<6.4.32|>=7.3,<7.3.10|>=7.4,<7.4.4|>=8.0,<8.0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/cache": "^1.0|^2.0|^3.0",
|
||||
"symfony/console": "^7.2|^8.0",
|
||||
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
|
||||
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
||||
"symfony/http-kernel": "^7.3|^8.0",
|
||||
"symfony/lock": "^7.4|^8.0",
|
||||
"symfony/process": "^6.4|^7.0|^8.0",
|
||||
"symfony/property-access": "^6.4|^7.0|^8.0",
|
||||
"symfony/rate-limiter": "^6.4|^7.0|^8.0",
|
||||
"symfony/routing": "^6.4|^7.0|^8.0",
|
||||
"symfony/serializer": "^6.4.32|~7.3.10|^7.4.4|^8.0.4",
|
||||
"symfony/service-contracts": "^2.5|^3",
|
||||
"symfony/stopwatch": "^6.4|^7.0|^8.0",
|
||||
"symfony/validator": "^6.4|^7.0|^8.0",
|
||||
"symfony/var-dumper": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"time": "2026-03-30T12:55:43+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Messenger\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Samuel Roze",
|
||||
"email": "samuel.roze@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Helps applications send and receive messages to/from other applications or via message queues",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/messenger/tree/v7.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../symfony/messenger"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.33.0",
|
||||
@@ -4324,6 +4553,94 @@
|
||||
],
|
||||
"install-path": "../symfony/runtime"
|
||||
},
|
||||
{
|
||||
"name": "symfony/scheduler",
|
||||
"version": "v7.4.8",
|
||||
"version_normalized": "7.4.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/scheduler.git",
|
||||
"reference": "f95e696edaad466db9b087a6480ef936c766c3de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/scheduler/zipball/f95e696edaad466db9b087a6480ef936c766c3de",
|
||||
"reference": "f95e696edaad466db9b087a6480ef936c766c3de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/clock": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dragonmantank/cron-expression": "^3.1",
|
||||
"symfony/cache": "^6.4|^7.0|^8.0",
|
||||
"symfony/console": "^6.4|^7.0|^8.0",
|
||||
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
|
||||
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
||||
"symfony/lock": "^6.4|^7.0|^8.0",
|
||||
"symfony/messenger": "^6.4|^7.0|^8.0",
|
||||
"symfony/serializer": "^6.4|^7.1|^8.0"
|
||||
},
|
||||
"time": "2026-03-24T13:12:05+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Scheduler\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sergey Rabochiy",
|
||||
"email": "upyx.00@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides scheduling through Symfony Messenger",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"cron",
|
||||
"schedule",
|
||||
"scheduler"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/scheduler/tree/v7.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../symfony/scheduler"
|
||||
},
|
||||
{
|
||||
"name": "symfony/serializer",
|
||||
"version": "v7.4.7",
|
||||
|
||||
46
backend/vendor/composer/installed.php
vendored
46
backend/vendor/composer/installed.php
vendored
@@ -3,7 +3,7 @@
|
||||
'name' => 'symfony/skeleton',
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '2f96caaa233f92fb18ffcdc3f13805d0e7e41369',
|
||||
'reference' => '4e81cea8317097bcd2f8ce85decd6b78e5156e8a',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -196,6 +196,21 @@
|
||||
0 => '2.0|3.0',
|
||||
),
|
||||
),
|
||||
'psr/clock' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/clock',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/clock-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/container' => array(
|
||||
'pretty_version' => '2.0.2',
|
||||
'version' => '2.0.2.0',
|
||||
@@ -271,6 +286,15 @@
|
||||
0 => '1.1|2.0|3.0',
|
||||
),
|
||||
),
|
||||
'symfony/clock' => array(
|
||||
'pretty_version' => 'v7.4.8',
|
||||
'version' => '7.4.8.0',
|
||||
'reference' => '674fa3b98e21531dd040e613479f5f6fa8f32111',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/clock',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/config' => array(
|
||||
'pretty_version' => 'v7.4.7',
|
||||
'version' => '7.4.7.0',
|
||||
@@ -421,6 +445,15 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
),
|
||||
'symfony/messenger' => array(
|
||||
'pretty_version' => 'v7.4.8',
|
||||
'version' => '7.4.8.0',
|
||||
'reference' => 'ddf5ab29bc0329ece30e16f01c86abb6241e92d8',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/messenger',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-ctype' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
@@ -568,6 +601,15 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/scheduler' => array(
|
||||
'pretty_version' => 'v7.4.8',
|
||||
'version' => '7.4.8.0',
|
||||
'reference' => 'f95e696edaad466db9b087a6480ef936c766c3de',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/scheduler',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/serializer' => array(
|
||||
'pretty_version' => 'v7.4.7',
|
||||
'version' => '7.4.7.0',
|
||||
@@ -595,7 +637,7 @@
|
||||
'symfony/skeleton' => array(
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '2f96caaa233f92fb18ffcdc3f13805d0e7e41369',
|
||||
'reference' => '4e81cea8317097bcd2f8ce85decd6b78e5156e8a',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
||||
Reference in New Issue
Block a user