Initial commit

This commit is contained in:
2025-10-05 13:55:28 +02:00
commit 68d521677a
767 changed files with 46947 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
<?php
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true],
Gesdinet\JWTRefreshTokenBundle\GesdinetJWTRefreshTokenBundle::class => ['all' => true],
Sentry\SentryBundle\SentryBundle::class => ['prod' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle::class => ['test' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
];
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\Aggregator\Domain\Model\Entity\Article"
repository-class="App\Aggregator\Infrastructure\Persistence\Doctrine\ORM\ArticleOrmRepository"
table="article"
>
<id name="id" type="article_id">
<generator strategy="NONE" />
</id>
<indexes>
<index fields="hash" />
<index fields="publishedAt" />
<index name="IDX_PUBLISHED_AT_ID" fields="publishedAt, id" />
</indexes>
<field name="title" length="1024" />
<field name="body" type="text" />
<embedded name="link" class="App\Aggregator\Domain\Model\ValueObject\Link" use-column-prefix="false" />
<field name="hash" length="32" />
<field name="categories" nullable="true" />
<many-to-one field="source" target-entity="App\Aggregator\Domain\Model\Entity\Source">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<embedded name="credibility" class="App\Aggregator\Domain\Model\ValueObject\Scoring\Credibility" use-column-prefix="false" />
<field name="sentiment" enum-type="App\Aggregator\Domain\Model\ValueObject\Scoring\Sentiment" length="30">
<options>
<option name="default">neutral</option>
</options>
</field>
<field name="metadata" type="open_graph" nullable="true" />
<embedded name="readingTime" class="App\Aggregator\Domain\Model\ValueObject\ReadingTime" use-column-prefix="false" />
<field name="image"
insertable="false"
updatable="false"
column-definition="VARCHAR(1024) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.image'))) STORED"
/>
<field
name="excerpt"
insertable="false"
updatable="false"
column-definition="VARCHAR(255) GENERATED ALWAYS AS (CONCAT(LEFT(body, 200), '...')) STORED"
/>
<field name="publishedAt" type="datetime_immutable" />
<field name="crawledAt" type="datetime_immutable" />
<field name="updatedAt" type="datetime_immutable" nullable="true" />
</entity>
</doctrine-mapping>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\Aggregator\Domain\Model\Entity\Source"
repository-class="App\Aggregator\Infrastructure\Persistence\Doctrine\ORM\SourceOrmRepository"
table="source"
>
<id name="id" type="source_id">
<generator strategy="NONE"/>
</id>
<field name="url" />
<field name="name" unique="true" />
<embedded name="credibility" class="App\Aggregator\Domain\Model\ValueObject\Scoring\Credibility" use-column-prefix="false" />
<field name="displayName" nullable="true" />
<field name="description" length="1024" nullable="true" />
<field name="updatedAt" type="datetime_immutable" nullable="true"/>
</entity>
</doctrine-mapping>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<embeddable name="App\Aggregator\Domain\Model\ValueObject\Link">
<field name="link" length="1024" />
</embeddable>
</doctrine-mapping>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<embeddable name="App\Aggregator\Domain\Model\ValueObject\ReadingTime">
<field name="readingTime" type="integer" nullable="true">
<options>
<option name="default">1</option>
<option name="unsigned">true</option>
</options>
</field>
</embeddable>
</doctrine-mapping>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<embeddable name="App\Aggregator\Domain\Model\ValueObject\Scoring\Credibility">
<field name="bias" enum-type="App\Aggregator\Domain\Model\ValueObject\Scoring\Bias" length="30">
<options>
<option name="default">neutral</option>
</options>
</field>
<field name="reliability" enum-type="App\Aggregator\Domain\Model\ValueObject\Scoring\Reliability" length="30">
<options>
<option name="default">reliable</option>
</options>
</field>
<field name="transparency" enum-type="App\Aggregator\Domain\Model\ValueObject\Scoring\Transparency" length="30">
<options>
<option name="default">medium</option>
</options>
</field>
</embeddable>
</doctrine-mapping>
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\FeedManagement\Domain\Model\Entity\Bookmark"
repository-class="App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\ORM\BookmarkOrmRepository"
table="bookmark"
>
<id name="id" type="bookmark_id">
<generator strategy="NONE"/>
</id>
<!-- fetching eager cause will always need to check the user's id whenever we deal with a bookmark -->
<many-to-one field="user" target-entity="App\IdentityAndAccess\Domain\Model\Entity\User" fetch="EAGER">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<field name="name" length="255" />
<field name="description" length="512" nullable="true" />
<field name="isPublic" type="boolean">
<options>
<option name="default">0</option>
</options>
</field>
<many-to-many field="articles" target-entity="App\Aggregator\Domain\Model\Entity\Article">
<join-table name="bookmark_article">
<join-columns>
<join-column name="bookmark_id" referenced-column-name="id" on-delete="CASCADE" />
</join-columns>
<inverse-join-columns>
<join-column name="article_id" referenced-column-name="id" on-delete="CASCADE" />
</inverse-join-columns>
</join-table>
</many-to-many>
<field name="createdAt" type="datetime_immutable"/>
<field name="updatedAt" type="datetime_immutable" nullable="true"/>
</entity>
</doctrine-mapping>
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\FeedManagement\Domain\Model\Entity\Comment"
repository-class="App\FeedManagement\Infrastructure\Persistence\Doctrine\ORM\CommentOrmRepository"
table="comment"
>
<id name="id" type="comment_id">
<generator strategy="NONE"/>
</id>
<many-to-one field="user" target-entity="App\IdentityAndAccess\Domain\Model\Entity\User">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<many-to-one field="article" target-entity="App\Aggregator\Domain\Model\Entity\Article">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<field name="content" length="512" />
<field name="sentiment" enum-type="App\Aggregator\Domain\Model\ValueObject\Scoring\Sentiment" length="30">
<options>
<option name="default">neutral</option>
</options>
</field>
<field name="isSpam" type="boolean">
<options>
<option name="default">0</option>
</options>
</field>
<field name="createdAt" type="datetime_immutable"/>
</entity>
</doctrine-mapping>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\FeedManagement\Domain\Model\Entity\FollowedSource"
repository-class="App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\ORM\FollowedSourceOrmRepository"
table="followed_source"
>
<id name="id" type="followed_source_id">
<generator strategy="NONE"/>
</id>
<many-to-one field="follower" target-entity="App\IdentityAndAccess\Domain\Model\Entity\User">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<many-to-one field="source" target-entity="App\Aggregator\Domain\Model\Entity\Source">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<field name="createdAt" type="datetime_immutable"/>
</entity>
</doctrine-mapping>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\IdentityAndAccess\Domain\Model\Entity\LoginAttempt"
repository-class="App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\ORM\LoginAttemptOrmRepository"
table="login_attempt"
>
<id name="id" type="login_attempt_id">
<generator strategy="NONE"/>
</id>
<many-to-one field="user" target-entity="App\IdentityAndAccess\Domain\Model\Entity\User">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<field name="createdAt" type="datetime_immutable"/>
</entity>
</doctrine-mapping>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\IdentityAndAccess\Domain\Model\Entity\LoginHistory"
repository-class="App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\ORM\LoginAttemptOrmRepository"
table="login_history"
>
<id name="id" type="login_history_id">
<generator strategy="NONE"/>
</id>
<many-to-one field="user" target-entity="App\IdentityAndAccess\Domain\Model\Entity\User">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<field name="ipAddress" nullable="true" length="15" />
<embedded name="device" class="App\SharedKernel\Domain\Model\ValueObject\Tracking\Device" />
<embedded name="location" class="App\SharedKernel\Domain\Model\ValueObject\Tracking\GeoLocation" />
<field name="createdAt" type="datetime_immutable"/>
</entity>
</doctrine-mapping>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\IdentityAndAccess\Domain\Model\Entity\RefreshToken"
repository-class="Gesdinet\JWTRefreshTokenBundle\Entity\RefreshTokenRepository"
table="refresh_tokens"
>
</entity>
</doctrine-mapping>
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\IdentityAndAccess\Domain\Model\Entity\User"
repository-class="App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\ORM\UserOrmRepository"
table="user"
>
<id name="id" type="user_id">
<generator strategy="NONE" />
</id>
<field name="name"/>
<field name="email" type="email" />
<field name="password" length="512" />
<field name="isLocked" type="boolean">
<options>
<option name="default">0</option>
</options>
</field>
<field name="isConfirmed" type="boolean">
<options>
<option name="default">0</option>
</options>
</field>
<embedded name="roles" class="App\IdentityAndAccess\Domain\Model\ValueObject\Roles" use-column-prefix="false" />
<field name="createdAt" type="datetime_immutable" />
<field name="updatedAt" type="datetime_immutable" nullable="true" />
</entity>
</doctrine-mapping>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="App\IdentityAndAccess\Domain\Model\Entity\VerificationToken"
repository-class="App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\ORM\VerificationTokenOrmRepository"
table="verification_token"
>
<id name="id" type="verification_token_id">
<generator strategy="NONE"/>
</id>
<many-to-one field="user" target-entity="App\IdentityAndAccess\Domain\Model\Entity\User" fetch="EAGER">
<join-column nullable="false" on-delete="CASCADE" />
</many-to-one>
<field name="purpose" enum-type="App\IdentityAndAccess\Domain\Model\ValueObject\Secret\TokenPurpose" />
<embedded name="token" class="App\IdentityAndAccess\Domain\Model\ValueObject\Secret\GeneratedToken" use-column-prefix="false" />
<field name="createdAt" type="datetime_immutable"/>
</entity>
</doctrine-mapping>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<embeddable name="App\IdentityAndAccess\Domain\Model\ValueObject\Roles">
<field name="roles" type="json"/>
</embeddable>
</doctrine-mapping>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<embeddable name="App\IdentityAndAccess\Domain\Model\ValueObject\Secret\GeneratedToken">
<field name="token" length="60" nullable="true" />
</embeddable>
</doctrine-mapping>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<embeddable name="App\SharedKernel\Domain\Model\ValueObject\Tracking\Device">
<field name="operatingSystem" type="string" nullable="true" />
<field name="client" type="string" nullable="true" />
<field name="device" type="string" nullable="true" />
<field name="isBot" type="boolean" nullable="false" >
<options>
<option name="default">0</option>
</options>
</field>
</embeddable>
</doctrine-mapping>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<embeddable name="App\SharedKernel\Domain\Model\ValueObject\Tracking\GeoLocation">
<field name="timeZone" type="string" nullable="true"/>
<field name="longitude" type="float" nullable="true"/>
<field name="latitude" type="float" nullable="true" />
<field name="accuracyRadius" type="integer" nullable="true" />
</embeddable>
</doctrine-mapping>
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20241008030057.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20241008030057 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'Add article table';
}
#[\Override]
public function up(Schema $schema): void
{
$this->addSql('CREATE TABLE article (id BINARY(16) NOT NULL COMMENT \'(DC2Type:uuid)\', title VARCHAR(255) NOT NULL, body LONGTEXT NOT NULL, link VARCHAR(255) NOT NULL, source VARCHAR(255) NOT NULL, categories VARCHAR(255) DEFAULT NULL, published_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', crawled_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', UNIQUE INDEX UNIQ_23A0E6636AC99F1 (link), INDEX IDX_23A0E665F8A7F73 (source), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql('DROP TABLE article');
}
}
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20241010041217.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20241010041217 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'remove unique index on article link';
}
#[\Override]
public function up(Schema $schema): void
{
$this->addSql('DROP INDEX UNIQ_23A0E6636AC99F1 ON article');
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql('CREATE UNIQUE INDEX UNIQ_23A0E6636AC99F1 ON article (link)');
}
}
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20241010041432.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20241010041432 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'increase link column size';
}
#[\Override]
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE article CHANGE link link VARCHAR(2048) NOT NULL');
}
#[\Override]
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE article CHANGE link link VARCHAR(255) NOT NULL');
}
}
@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20241010042241.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20241010042241 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'add hash column to article';
}
#[\Override]
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE article ADD hash VARCHAR(32) NOT NULL');
$this->addSql('UPDATE article SET hash = MD5(link)');
$this->addSql('CREATE INDEX IDX_23A0E66D1B862B8 ON article (hash)');
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql('DROP INDEX IDX_23A0E66D1B862B8 ON article');
$this->addSql('ALTER TABLE article DROP hash');
}
}
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250314140326.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250314140326 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'add user table';
}
#[\Override]
public function up(Schema $schema): void
{
$this->addSql('CREATE TABLE user (id BINARY(16) NOT NULL COMMENT \'(DC2Type:user_id)\', name VARCHAR(255) NOT NULL, email VARCHAR(500) NOT NULL, password VARCHAR(4098) NOT NULL, created_at DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\', updated_at DATE DEFAULT NULL COMMENT \'(DC2Type:date_immutable)\', roles JSON NOT NULL COMMENT \'(DC2Type:json)\', password_reset_token_token VARCHAR(255) DEFAULT NULL, password_reset_token_generated_at DATE DEFAULT NULL COMMENT \'(DC2Type:date_immutable)\', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql('DROP TABLE user');
}
}
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250314145254.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250314145254 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'add refresh token';
}
#[\Override]
public function up(Schema $schema): void
{
$this->addSql('CREATE TABLE refresh_tokens (id INT AUTO_INCREMENT NOT NULL, refresh_token VARCHAR(128) NOT NULL, username VARCHAR(255) NOT NULL, valid DATETIME NOT NULL, UNIQUE INDEX UNIQ_9BACE7E1C74F2195 (refresh_token), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql('DROP TABLE refresh_tokens');
}
}
@@ -0,0 +1,32 @@
<?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 Version20250315154326 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'fix password_reset_token_generated_at column type';
}
#[\Override]
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE user CHANGE password_reset_token_generated_at password_reset_token_generated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\'');
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE user CHANGE password_reset_token_generated_at password_reset_token_generated_at DATE DEFAULT NULL COMMENT \'(DC2Type:date_immutable)\'');
}
}
@@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250423183329.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250423183329 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'refactoring identity and access module';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE TABLE login_attempt (id BINARY(16) NOT NULL COMMENT '(DC2Type:login_attempt_id)', user_id BINARY(16) NOT NULL COMMENT '(DC2Type:user_id)', created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)', INDEX IDX_8C11C1BA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE login_history (id BINARY(16) NOT NULL COMMENT '(DC2Type:login_history_id)', user_id BINARY(16) NOT NULL COMMENT '(DC2Type:user_id)', created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)', device_operating_system VARCHAR(255) DEFAULT NULL, device_client VARCHAR(255) DEFAULT NULL, device_device VARCHAR(255) DEFAULT NULL, device_is_bot TINYINT(1) DEFAULT 0 NOT NULL, location_time_zone VARCHAR(255) DEFAULT NULL, location_longitude DOUBLE PRECISION DEFAULT NULL, location_latitude DOUBLE PRECISION DEFAULT NULL, location_accuracy_radius INT DEFAULT NULL, INDEX IDX_37976E36A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE verification_token (id BINARY(16) NOT NULL COMMENT '(DC2Type:verification_token_id)', user_id BINARY(16) NOT NULL COMMENT '(DC2Type:user_id)', purpose VARCHAR(255) NOT NULL, created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)', token_token VARCHAR(255) DEFAULT NULL, INDEX IDX_C1CC006BA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_attempt ADD CONSTRAINT FK_8C11C1BA76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_history ADD CONSTRAINT FK_37976E36A76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE verification_token ADD CONSTRAINT FK_C1CC006BA76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE id id BINARY(16) NOT NULL COMMENT '(DC2Type:article_id)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE user ADD is_locked TINYINT(1) DEFAULT 0 NOT NULL, ADD is_confirmed TINYINT(1) DEFAULT 0 NOT NULL, DROP password_reset_token_token, DROP password_reset_token_generated_at
SQL);
$this->addSql(<<<'SQL'
UPDATE user SET is_locked = 0, is_confirmed = 1
SQL);
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE login_attempt DROP FOREIGN KEY FK_8C11C1BA76ED395
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_history DROP FOREIGN KEY FK_37976E36A76ED395
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE verification_token DROP FOREIGN KEY FK_C1CC006BA76ED395
SQL);
$this->addSql(<<<'SQL'
DROP TABLE login_attempt
SQL);
$this->addSql(<<<'SQL'
DROP TABLE login_history
SQL);
$this->addSql(<<<'SQL'
DROP TABLE verification_token
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE user ADD password_reset_token_token VARCHAR(255) DEFAULT NULL, ADD password_reset_token_generated_at DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)', DROP is_locked, DROP is_confirmed
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE id id BINARY(16) NOT NULL COMMENT '(DC2Type:uuid)'
SQL);
}
}
@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250423185205.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250423185205 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'add ip to login history';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE login_history ADD ip VARCHAR(45) DEFAULT NULL
SQL);
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE login_history DROP ip
SQL);
}
}
@@ -0,0 +1,35 @@
<?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 Version20250423190105 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'remove column prefix';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE verification_token CHANGE token_token token VARCHAR(255) DEFAULT NULL
SQL);
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE verification_token CHANGE token token_token VARCHAR(255) DEFAULT NULL
SQL);
}
}
@@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use Symfony\Component\Uid\Uuid;
/**
* Class Version20250501041246.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250501041246 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'introduce new source entity';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE TABLE source (name VARCHAR(255) NOT NULL, url VARCHAR(255) NOT NULL, updated_at DATE DEFAULT NULL COMMENT '(DC2Type:date_immutable)', bias VARCHAR(255) DEFAULT 'neutral' NOT NULL, reliability VARCHAR(255) DEFAULT 'reliable' NOT NULL, transparency VARCHAR(255) DEFAULT 'medium' NOT NULL, PRIMARY KEY(name)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE article ADD updated_at DATE DEFAULT NULL COMMENT '(DC2Type:date_immutable)', ADD bias VARCHAR(255) DEFAULT 'neutral' NOT NULL, ADD reliability VARCHAR(255) DEFAULT 'reliable' NOT NULL, ADD transparency VARCHAR(255) DEFAULT 'medium' NOT NULL
SQL);
$this->write("Fetching sources from crawled articles...");
$sources = $this->connection
->executeQuery("SELECT DISTINCT source FROM article WHERE source IS NOT NULL")
->fetchFirstColumn();
$this->write(sprintf("%d unique sources found", count($sources)));
foreach ($sources as $sourceName) {
$this->addSql("INSERT INTO source (name, url) VALUES (:name, :url)", [
"name" => $sourceName,
"url" => 'https://' . $sourceName
]);
}
$this->addSql("UPDATE article SET categories = LOWER(categories)");
$this->addSql(<<<'SQL'
ALTER TABLE article ADD CONSTRAINT FK_23A0E665F8A7F73 FOREIGN KEY (source) REFERENCES source (name) ON DELETE RESTRICT
SQL);
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article DROP FOREIGN KEY FK_23A0E665F8A7F73
SQL);
$this->addSql(<<<'SQL'
DROP TABLE source
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE article DROP updated_at, DROP bias, DROP reliability, DROP transparency
SQL);
}
}
@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250501041950.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250501041950 extends AbstractMigration
{
#[\Override]
public function getDescription(): string
{
return 'increase title length';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE title title VARCHAR(2048) NOT NULL
SQL);
}
#[\Override]
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE title title VARCHAR(255) NOT NULL
SQL);
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250501143015.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250501143015 extends AbstractMigration
{
public function getDescription(): string
{
return 'add sentiment score';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article ADD sentiment VARCHAR(255) DEFAULT 'neutral' NOT NULL
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article DROP sentiment
SQL);
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250502181706.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250502181706 extends AbstractMigration
{
public function getDescription(): string
{
return 'add metadata column to article table';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article ADD metadata JSON DEFAULT NULL COMMENT '(DC2Type:open_graph)'
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article DROP metadata
SQL);
}
}
@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250502184108.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250502184108 extends AbstractMigration
{
public function getDescription(): string
{
return 'relative url to absolue';
}
public function up(Schema $schema): void
{
$this->addSql('UPDATE article SET link = CONCAT("https://", source, "/", TRIM(BOTH "/" FROM link)) WHERE link NOT LIKE "http%"');
}
public function down(Schema $schema): void
{
$this->throwIrreversibleMigrationException(
'This migration is irreversible. You cannot revert the link to relative url.'
);
}
}
@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250513081958.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250513081958 extends AbstractMigration
{
public function getDescription(): string
{
return 'adding reading time to articles';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article ADD reading_time INT DEFAULT NULL
SQL);
$this->addSql(<<<'SQL'
UPDATE article SET reading_time = FLOOR(LENGTH(body) - LENGTH(REPLACE(body, ' ', '')) + 1) / 200
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article DROP reading_time
SQL);
}
}
@@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250514211949.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250514211949 extends AbstractMigration
{
public function getDescription(): string
{
return '[FeedManagement] add bookmark';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE TABLE bookmark (id BINARY(16) NOT NULL COMMENT '(DC2Type:bookmark_id)', user_id BINARY(16) NOT NULL COMMENT '(DC2Type:user_id)', name VARCHAR(255) NOT NULL, description VARCHAR(2048) DEFAULT NULL, is_public TINYINT(1) DEFAULT 0 NOT NULL, created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)', updated_at DATE DEFAULT NULL COMMENT '(DC2Type:date_immutable)', INDEX IDX_DA62921DA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE bookmark_article (bookmark_id BINARY(16) NOT NULL COMMENT '(DC2Type:bookmark_id)', article_id BINARY(16) NOT NULL COMMENT '(DC2Type:article_id)', INDEX IDX_6FE2655D92741D25 (bookmark_id), INDEX IDX_6FE2655D7294869C (article_id), PRIMARY KEY(bookmark_id, article_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark ADD CONSTRAINT FK_DA62921DA76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark_article ADD CONSTRAINT FK_6FE2655D92741D25 FOREIGN KEY (bookmark_id) REFERENCES bookmark (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark_article ADD CONSTRAINT FK_6FE2655D7294869C FOREIGN KEY (article_id) REFERENCES article (id) ON DELETE CASCADE
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE bookmark DROP FOREIGN KEY FK_DA62921DA76ED395
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark_article DROP FOREIGN KEY FK_6FE2655D92741D25
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark_article DROP FOREIGN KEY FK_6FE2655D7294869C
SQL);
$this->addSql(<<<'SQL'
DROP TABLE bookmark
SQL);
$this->addSql(<<<'SQL'
DROP TABLE bookmark_article
SQL);
}
}
@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250515023707.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250515023707 extends AbstractMigration
{
public function getDescription(): string
{
return 'date_immutable to datetime_immutable';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark CHANGE created_at created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_attempt CHANGE created_at created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_history CHANGE created_at created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE source CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE user CHANGE created_at created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE verification_token CHANGE created_at created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)'
SQL);
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE user CHANGE created_at created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)', CHANGE updated_at updated_at DATE DEFAULT NULL COMMENT '(DC2Type:date_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark CHANGE created_at created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)', CHANGE updated_at updated_at DATE DEFAULT NULL COMMENT '(DC2Type:date_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE source CHANGE updated_at updated_at DATE DEFAULT NULL COMMENT '(DC2Type:date_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_attempt CHANGE created_at created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE verification_token CHANGE created_at created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_history CHANGE created_at created_at DATE NOT NULL COMMENT '(DC2Type:date_immutable)'
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE updated_at updated_at DATE DEFAULT NULL COMMENT '(DC2Type:date_immutable)'
SQL);
}
}
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;final class Version20250516123343 extends AbstractMigration
{
public function getDescription(): string
{
return '[source] add display_name and description';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE source ADD display_name VARCHAR(255) DEFAULT NULL, ADD description VARCHAR(2048) DEFAULT NULL
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE source DROP display_name, DROP description
SQL);
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250517055913.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250517055913 extends AbstractMigration
{
public function getDescription(): string
{
return '[article] add index on publication date';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE INDEX IDX_23A0E66E0D4FDE1 ON article (published_at)
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
DROP INDEX IDX_23A0E66E0D4FDE1 ON article
SQL);
}
}
@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250522140030.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250522140030 extends AbstractMigration
{
public function getDescription(): string
{
return 'Create FollowedSource table';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE TABLE followed_source (id BINARY(16) NOT NULL COMMENT '(DC2Type:followed_source_id)', follower_id BINARY(16) NOT NULL COMMENT '(DC2Type:user_id)', source VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)', INDEX IDX_7A763A3EAC24F853 (follower_id), INDEX IDX_7A763A3E5F8A7F73 (source), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE followed_source ADD CONSTRAINT FK_7A763A3EAC24F853 FOREIGN KEY (follower_id) REFERENCES user (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE followed_source ADD CONSTRAINT FK_7A763A3E5F8A7F73 FOREIGN KEY (source) REFERENCES source (name) ON DELETE CASCADE
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE followed_source DROP FOREIGN KEY FK_7A763A3EAC24F853
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE followed_source DROP FOREIGN KEY FK_7A763A3E5F8A7F73
SQL);
$this->addSql(<<<'SQL'
DROP TABLE followed_source
SQL);
}
}
@@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250525183408.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250525183408 extends AbstractMigration
{
public function getDescription(): string
{
return 'optimize data lengths for various fields in the database schema';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE title title VARCHAR(1024) NOT NULL, CHANGE link link VARCHAR(1024) NOT NULL, CHANGE bias bias VARCHAR(30) DEFAULT 'neutral' NOT NULL, CHANGE reliability reliability VARCHAR(30) DEFAULT 'reliable' NOT NULL, CHANGE transparency transparency VARCHAR(30) DEFAULT 'medium' NOT NULL, CHANGE reading_time reading_time INT UNSIGNED DEFAULT 1
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark CHANGE description description VARCHAR(512) DEFAULT NULL
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_history ADD ip_address VARCHAR(15) DEFAULT NULL, DROP ip
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE source CHANGE bias bias VARCHAR(30) DEFAULT 'neutral' NOT NULL, CHANGE reliability reliability VARCHAR(30) DEFAULT 'reliable' NOT NULL, CHANGE transparency transparency VARCHAR(30) DEFAULT 'medium' NOT NULL, CHANGE description description VARCHAR(1024) DEFAULT NULL
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE user CHANGE email email VARCHAR(255) NOT NULL, CHANGE password password VARCHAR(512) NOT NULL
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE verification_token CHANGE token token VARCHAR(60) DEFAULT NULL
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE user CHANGE email email VARCHAR(500) NOT NULL, CHANGE password password VARCHAR(4098) NOT NULL
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE bookmark CHANGE description description VARCHAR(2048) DEFAULT NULL
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE source CHANGE description description VARCHAR(2048) DEFAULT NULL, CHANGE bias bias VARCHAR(255) DEFAULT 'neutral' NOT NULL, CHANGE reliability reliability VARCHAR(255) DEFAULT 'reliable' NOT NULL, CHANGE transparency transparency VARCHAR(255) DEFAULT 'medium' NOT NULL
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE verification_token CHANGE token token VARCHAR(255) DEFAULT NULL
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE login_history ADD ip VARCHAR(45) DEFAULT NULL, DROP ip_address
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE title title VARCHAR(2048) NOT NULL, CHANGE link link VARCHAR(2048) NOT NULL, CHANGE bias bias VARCHAR(255) DEFAULT 'neutral' NOT NULL, CHANGE reliability reliability VARCHAR(255) DEFAULT 'reliable' NOT NULL, CHANGE transparency transparency VARCHAR(255) DEFAULT 'medium' NOT NULL, CHANGE reading_time reading_time INT DEFAULT NULL
SQL);
}
}
@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250526101759.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250526101759 extends AbstractMigration
{
public function getDescription(): string
{
return 'add comment table with foreign keys to user and article tables';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE TABLE comment (id BINARY(16) NOT NULL COMMENT '(DC2Type:comment_id)', user_id BINARY(16) NOT NULL COMMENT '(DC2Type:user_id)', article_id BINARY(16) NOT NULL COMMENT '(DC2Type:article_id)', content VARCHAR(512) NOT NULL, sentiment VARCHAR(30) DEFAULT 'neutral' NOT NULL, is_spam TINYINT(1) DEFAULT 0 NOT NULL, created_at DATETIME NOT NULL COMMENT '(DC2Type:datetime_immutable)', INDEX IDX_9474526CA76ED395 (user_id), INDEX IDX_9474526C7294869C (article_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE comment ADD CONSTRAINT FK_9474526CA76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE comment ADD CONSTRAINT FK_9474526C7294869C FOREIGN KEY (article_id) REFERENCES article (id) ON DELETE CASCADE
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE comment DROP FOREIGN KEY FK_9474526CA76ED395
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE comment DROP FOREIGN KEY FK_9474526C7294869C
SQL);
$this->addSql(<<<'SQL'
DROP TABLE comment
SQL);
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250526102035.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250526102035 extends AbstractMigration
{
public function getDescription(): string
{
return 'optimize sentiment column in article table';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE sentiment sentiment VARCHAR(30) DEFAULT 'neutral' NOT NULL
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article CHANGE sentiment sentiment VARCHAR(255) DEFAULT 'neutral' NOT NULL
SQL);
}
}
@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250526164157.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250526164157 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add image and excerpt columns to article table';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article
ADD image VARCHAR(1024) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.image'))) STORED,
ADD excerpt VARCHAR(255) GENERATED ALWAYS AS (CONCAT(LEFT(body, 200), '...')) STORED
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article DROP image, DROP excerpt
SQL);
}
}
@@ -0,0 +1,73 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use App\Aggregator\Domain\Model\Identity\SourceId;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250526231341.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250526231341 extends AbstractMigration
{
public function getDescription(): string
{
return 'move from source_name to source_id in article and followed_source tables';
}
public function up(Schema $schema): void
{
$this->addSql("SET FOREIGN_KEY_CHECKS = 0");
// delete the old indexes and foreign keys
$this->addSql("DROP INDEX `primary` ON source");
$this->addSql("ALTER TABLE article DROP FOREIGN KEY FK_23A0E665F8A7F73");
$this->addSql("ALTER TABLE followed_source DROP FOREIGN KEY FK_7A763A3E5F8A7F73");
$this->addSql("DROP INDEX IDX_23A0E665F8A7F73 ON article");
$this->addSql("DROP INDEX IDX_7A763A3E5F8A7F73 ON followed_source");
// add the new id column to source table
$this->addSql("ALTER TABLE source ADD id BINARY(16) DEFAULT NULL COMMENT '(DC2Type:source_id)' FIRST");
$sources = $this->connection
->executeQuery("SELECT name FROM source")
->fetchFirstColumn();
foreach ($sources as $source) {
$this->addSql("UPDATE source SET id = :id WHERE name = :name", [
"id" => new SourceId()->toBinary(),
"name" => $source,
]);
}
// set the id column as NOT NULL and create a unique index
$this->addSql("ALTER TABLE source MODIFY id BINARY(16) NOT NULL COMMENT '(DC2Type:source_id)'");
$this->addSql("CREATE UNIQUE INDEX UNIQ_5F8A7F735E237E06 ON source (name)");
$this->addSql("ALTER TABLE source ADD PRIMARY KEY (id)");
// Update article table
$this->addSql("ALTER TABLE article ADD source_id BINARY(16) NOT NULL COMMENT '(DC2Type:source_id)'");
$this->addSql("UPDATE article JOIN source ON article.source = source.name SET article.source_id = source.id");
$this->addSql("ALTER TABLE article DROP source");
$this->addSql("ALTER TABLE article ADD CONSTRAINT FK_23A0E66953C1C61 FOREIGN KEY (source_id) REFERENCES source (id) ON DELETE CASCADE");
$this->addSql(" CREATE INDEX IDX_23A0E66953C1C61 ON article (source_id)");
// Update followed_source table
$this->addSql("ALTER TABLE followed_source ADD source_id BINARY(16) NOT NULL COMMENT '(DC2Type:source_id)'");
$this->addSql("ALTER TABLE followed_source DROP source");
$this->addSql("ALTER TABLE followed_source ADD CONSTRAINT FK_7A763A3E953C1C61 FOREIGN KEY (source_id) REFERENCES source (id) ON DELETE CASCADE");
$this->addSql("CREATE INDEX IDX_7A763A3E953C1C61 ON followed_source (source_id)");
// Re-enable foreign key checks
$this->addSql("SET FOREIGN_KEY_CHECKS = 1");
}
public function down(Schema $schema): void
{
$this->throwIrreversibleMigrationException('This migration is irreversible.');
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Class Version20250530121647.
*
* @author bernard-ng <bernard@devscast.tech>
*/
final class Version20250530121647 extends AbstractMigration
{
public function getDescription(): string
{
return 'Create index on article table for published_at and id columns';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE article ADD INDEX IDX_PUBLISHED_AT_ID (published_at DESC, id DESC);
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
DROP INDEX IDX_PUBLISHED_AT_ID ON article
SQL);
}
}
@@ -0,0 +1,5 @@
framework:
cache:
pools:
cache.dbal:
adapter: cache.adapter.filesystem
@@ -0,0 +1,86 @@
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '16'
profiling_collect_backtrace: false
use_savepoints: true
result_cache: 'cache.dbal'
types:
# Shared Kernel
email: App\SharedKernel\Infrastructure\Persistence\Doctrine\DBAL\Types\EmailType
# Aggregator
article_id: App\Aggregator\Infrastructure\Persistence\Doctrine\DBAL\Types\ArticleIdType
source_id: App\Aggregator\Infrastructure\Persistence\Doctrine\DBAL\Types\SourceIdType
open_graph: App\Aggregator\Infrastructure\Persistence\Doctrine\DBAL\Types\OpenGraphType
# Identity and Access
user_id: App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\DBAL\Types\UserIdType
login_attempt_id: App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\DBAL\Types\LoginAttemptIdType
login_history_id: App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\DBAL\Types\LoginHistoryIdType
verification_token_id: App\IdentityAndAccess\Infrastructure\Persistence\Doctrine\DBAL\Types\VerificationTokenIdType
# FeedManagement
bookmark_id: App\FeedManagement\Infrastructure\Persistence\Doctrine\DBAL\Types\BookmarkIdType
followed_source_id: App\FeedManagement\Infrastructure\Persistence\Doctrine\DBAL\Types\FollowedSourceIdType
comment_id: App\FeedManagement\Infrastructure\Persistence\Doctrine\DBAL\Types\CommentIdType
orm:
auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true
report_fields_where_declared: true
validate_xml_mapping: false
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
Aggregator:
is_bundle: false
type: xml
dir: '%kernel.project_dir%/config/doctrine/Aggregator'
prefix: 'App\Aggregator\Domain\Model'
IdentityAndAccess:
is_bundle: false
type: xml
dir: '%kernel.project_dir%/config/doctrine/IdentityAndAccess'
prefix: 'App\IdentityAndAccess\Domain\Model'
FeedManagement:
is_bundle: false
type: xml
dir: '%kernel.project_dir%/config/doctrine/FeedManagement'
prefix: 'App\FeedManagement\Domain\Model'
SharedKernel:
is_bundle: false
type: xml
dir: '%kernel.project_dir%/config/doctrine/SharedKernel'
prefix: 'App\SharedKernel\Domain\Model'
controller_resolver:
auto_mapping: false
when@test:
doctrine:
dbal:
# "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
when@prod:
doctrine:
orm:
auto_generate_proxy_classes: false
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: pool
pool: doctrine.result_cache_pool
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system
@@ -0,0 +1,6 @@
doctrine_migrations:
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/config/migrations'
enable_profiler: false
@@ -0,0 +1,25 @@
# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
secret: '%env(APP_SECRET)%'
#csrf_protection: true
http_method_override: false
handle_all_throwables: true
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: null
cookie_secure: auto
cookie_samesite: lax
storage_factory_id: session.storage.factory.native
#esi: true
#fragments: true
php_errors:
log: true
when@test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file
@@ -0,0 +1,4 @@
gesdinet_jwt_refresh_token:
refresh_token_class: App\IdentityAndAccess\Domain\Model\Entity\RefreshToken
ttl: 2592000 # 1 month
ttl_update: true
@@ -0,0 +1,5 @@
lexik_jwt_authentication:
secret_key: '%env(resolve:JWT_SECRET_KEY)%'
public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
pass_phrase: '%env(JWT_PASSPHRASE)%'
token_ttl: '%env(resolve:JWT_TTL)%'
@@ -0,0 +1,3 @@
framework:
mailer:
dsn: '%env(MAILER_DSN)%'
@@ -0,0 +1,39 @@
framework:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
failure_transport: failed
transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
retry_strategy:
max_retries: 3
delay: 1000
multiplier: 2
max_delay: 0
options:
auto_setup: true
failed:
dsn: 'doctrine://default?queue_name=failed'
options:
auto_setup: true
sync: 'sync://'
routing:
App\SharedKernel\Application\Messaging\AsyncMessage: async
Symfony\Component\Mailer\Messenger\SendEmailMessage: sync
default_bus: command.bus
buses:
command.bus: ~
query.bus: ~
message.bus: ~
when@test:
framework:
messenger:
transports:
# replace with your transport name here (e.g., my_transport: 'in-memory://')
# For more Messenger testing tools, see https://github.com/zenstruck/messenger-test
async: 'in-memory://'
@@ -0,0 +1,72 @@
monolog:
channels:
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
when@dev:
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!app"]
app:
type: stream
path: "%kernel.logs_dir%/app.%kernel.environment%.log"
level: debug
channels: ["app"]
console:
type: console
level: debug
process_psr_3_messages: false
channels: ["app"]
when@test:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
channels: ["!event"]
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
when@prod:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
telegram:
type: telegram
level: critical
channels: [ "!event" ]
token: "%env(DEVY_TOKEN)%"
channel: "%env(DEVY_CHANNEL)%"
topic: "%env(int:DEVY_TOPIC)%"
parse_mode: "MarkdownV2"
disable_webpage_preview: true
disable_notification: false
split_long_messages: false
formatter: App\SharedKernel\Infrastructure\Framework\Symfony\Logging\TelegramFormatter
nested:
type: rotating_file
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: error
max_files: 10
console:
type: console
level: info
process_psr_3_messages: false
channels: ["!event", "!doctrine"]
deprecation:
type: stream
channels: [deprecation]
path: "%kernel.logs_dir%/deprecation.log"
@@ -0,0 +1,12 @@
framework:
router:
utf8: true
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
#default_uri: http://localhost
when@prod:
framework:
router:
strict_requirements: null
@@ -0,0 +1,61 @@
security:
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
app_user_provider:
id: App\IdentityAndAccess\Infrastructure\Framework\Symfony\Security\SecurityUserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security:
login:
pattern: ^/api/login
stateless: true
json_login:
check_path: /api/login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
user_checker: App\IdentityAndAccess\Infrastructure\Framework\Symfony\Security\UserChecker
api:
pattern: ^/api
stateless: true
entry_point: jwt
jwt: ~
refresh_jwt:
check_path: /api/token/refresh
logout:
path: api_token_invalidate
user_checker: App\IdentityAndAccess\Infrastructure\Framework\Symfony\Security\UserChecker
main:
lazy: true
provider: app_user_provider
user_checker: App\IdentityAndAccess\Infrastructure\Framework\Symfony\Security\UserChecker
# 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: ^/api/register, roles: PUBLIC_ACCESS }
- { path: ^/api/login, roles: PUBLIC_ACCESS }
- { path: ^/api/token/refresh, roles: PUBLIC_ACCESS }
- { path: ^/api/password/(request|reset), roles: PUBLIC_ACCESS }
- { path: ^/api/account/(unlock|confirm), roles: PUBLIC_ACCESS }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
when@test:
security:
password_hashers:
# By default, password hashers are resource intensive and take time. This is
# important to generate secure password hashes. In tests however, secure hashes
# are not important, waste resources and increase test times. The following
# reduces the work factor to the lowest possible values.
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto
cost: 4 # Lowest possible value for bcrypt
time_cost: 3 # Lowest possible value for argon
memory_cost: 10 # Lowest possible value for argon
@@ -0,0 +1,24 @@
when@prod:
sentry:
dsn: "%env(SENTRY_DSN)%"
register_error_listener: false
register_error_handler: false
options:
traces_sample_rate: 0.1
ignore_exceptions:
- 'Symfony\Component\ErrorHandler\Error\FatalError'
- 'Symfony\Component\Debug\Exception\FatalErrorException'
monolog:
handlers:
sentry_fingers_crossed:
type: fingers_crossed
action_level: error
handler: sentry
excluded_http_codes: [404, 405]
buffer_size: 50
sentry:
type: sentry
level: !php/const Monolog\Logger::ERROR
hub_id: Sentry\State\HubInterface
fill_extra_context: true
process_psr_3_messages: false
@@ -0,0 +1,7 @@
framework:
default_locale: fr
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:
- en
providers:
@@ -0,0 +1,16 @@
twig:
file_name_pattern: '*.twig'
date:
format: 'd M Y'
interval_format: '%d days'
timezone: null
number_format:
decimals: 2
decimal_point: ','
thousands_separator: '.'
globals:
'application': '@App\SharedKernel\Domain\Application'
when@test:
twig:
strict_variables: true
@@ -0,0 +1,11 @@
framework:
validation:
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping:
# App\Entity\: []
when@test:
framework:
validation:
not_compromised_password: false
@@ -0,0 +1,11 @@
when@dev:
web_profiler:
toolbar: true
framework:
profiler:
collect_serializer_data: true
when@test:
framework:
profiler: { collect: false }
+5
View File
@@ -0,0 +1,5 @@
<?php
if (file_exists(dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php')) {
require dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php';
}
+27
View File
@@ -0,0 +1,27 @@
controllers:
resource: ../src/
type: attribute
schemes:
- HTTP
- HTTPS
identity_and_access_login_check:
path: /api/login_check
methods: [POST]
schemes:
- HTTP
- HTTPS
identity_and_access_refresh_token:
path: /api/token/refresh
methods: [POST]
schemes:
- HTTP
- HTTPS
identity_and_access_token_invalidate:
path: /api/token/invalidate
methods: [POST]
schemes:
- HTTP
- HTTPS
@@ -0,0 +1,4 @@
when@dev:
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error
@@ -0,0 +1,2 @@
gesdinet_jwt_refresh_token:
path: /api/token/refresh
@@ -0,0 +1,3 @@
_security_logout:
resource: security.route_loader.logout
type: service
@@ -0,0 +1,8 @@
when@dev:
web_profiler_wdt:
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
prefix: /_wdt
web_profiler_profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
prefix: /_profiler
+55
View File
@@ -0,0 +1,55 @@
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
app_crawling_notification_email: '%env(CRAWLING_NOTIFICATION_EMAIL)%'
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
$projectDir: '%kernel.project_dir%'
$crawlingNotificationEmail: '%app_crawling_notification_email%'
_instanceof:
App\SharedKernel\Application\Messaging\CommandHandler:
tags:
- { name: messenger.message_handler, bus: 'command.bus' }
App\SharedKernel\Application\Messaging\QueryHandler:
tags:
- { name: messenger.message_handler, bus: 'query.bus' }
App\SharedKernel\Application\Messaging\MessageHandler:
tags:
- { name: messenger.message_handler, bus: 'message.bus' }
App\SharedKernel\Domain\EventListener\EventListener:
tags:
- { name: kernel.event_listener }
Symfony\Bridge\Monolog\Processor\ConsoleCommandProcessor:
tags:
- { name: monolog.processor, channel: 'app' }
Symfony\Bridge\Monolog\Processor\RouteProcessor:
tags:
- { name: monolog.processor, channel: 'app' }
Symfony\Bridge\Monolog\Processor\TokenProcessor:
tags:
- { name: monolog.processor, channel: 'app' }
App\SharedKernel\Infrastructure\Framework\Symfony\Logging\TelegramFormatter:
tags:
- { name: monolog.formatter }
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/SharedKernel/Infrastructure/Framework/Symfony/Kernel.php'
- '../src/**/Domain/Model/Entity/*'
- '../src/**/Domain/Model/ValueObject/*'
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
@@ -0,0 +1,7 @@
services:
_defaults:
autowire: true
autoconfigure: true
Tests\Behat\:
resource: '../tests/Behat/*'