diff --git a/composer.json b/composer.json index d3f0dc1..80b9d1c 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ "presta/sitemap-bundle": "^1.7", "sensio/framework-extra-bundle": "^5.3", "snc/redis-bundle": "^2.1", + "stof/doctrine-extensions-bundle": "^1.5", "symfony/cache": "4.4.*", "symfony/config": "4.4.*", "symfony/console": "4.4.*", diff --git a/composer.lock b/composer.lock index 2b45f39..89ae0e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,57 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5ae67020c6a0f7b7733417dc8e3d622f", + "content-hash": "dd42be5bde13636718899c5177463f1d", "packages": [ + { + "name": "behat/transliterator", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Transliterator.git", + "reference": "3c4ec1d77c3d05caa1f0bf8fb3aae4845005c7fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Transliterator/zipball/3c4ec1d77c3d05caa1f0bf8fb3aae4845005c7fc", + "reference": "3c4ec1d77c3d05caa1f0bf8fb3aae4845005c7fc", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "chuyskywalker/rolling-curl": "^3.1", + "php-yaoi/php-yaoi": "^1.0", + "phpunit/phpunit": "^4.8.36|^6.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Transliterator\\": "src/Behat/Transliterator" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Artistic-1.0" + ], + "description": "String transliterator", + "keywords": [ + "i18n", + "slug", + "transliterator" + ], + "support": { + "issues": "https://github.com/Behat/Transliterator/issues", + "source": "https://github.com/Behat/Transliterator/tree/v1.3.0" + }, + "time": "2020-01-14T16:39:13+00:00" + }, { "name": "clue/stream-filter", "version": "v1.5.0", @@ -1553,6 +1602,103 @@ ], "time": "2019-12-23T15:31:36+00:00" }, + { + "name": "gedmo/doctrine-extensions", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/Atlantic18/DoctrineExtensions.git", + "reference": "be551985759946a45d052777c2906aa52db64532" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Atlantic18/DoctrineExtensions/zipball/be551985759946a45d052777c2906aa52db64532", + "reference": "be551985759946a45d052777c2906aa52db64532", + "shasum": "" + }, + "require": { + "behat/transliterator": "~1.2", + "doctrine/annotations": "^1.2", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/common": "^2.13 || ^3.0", + "doctrine/event-manager": "^1.0", + "php": "^7.2" + }, + "conflict": { + "doctrine/mongodb": "<1.3", + "doctrine/mongodb-odm": "<2.0", + "sebastian/comparator": "<2.0" + }, + "provide": { + "ext-mongo": "1.6.12" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/mongodb-odm": "^2.0", + "doctrine/orm": "^2.6.3", + "friendsofphp/php-cs-fixer": "^2.16", + "phpunit/phpunit": "^8.5", + "symfony/yaml": "^4.1" + }, + "suggest": { + "doctrine/mongodb-odm": "to use the extensions with the MongoDB ODM", + "doctrine/orm": "to use the extensions with the ORM" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Gedmo\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gediminas Morkevicius", + "email": "gediminas.morkevicius@gmail.com" + }, + { + "name": "Gustavo Falco", + "email": "comfortablynumb84@gmail.com" + }, + { + "name": "David Buchmann", + "email": "david@liip.ch" + } + ], + "description": "Doctrine2 behavioral extensions", + "homepage": "http://gediminasm.org/", + "keywords": [ + "Blameable", + "behaviors", + "doctrine2", + "extensions", + "gedmo", + "loggable", + "nestedset", + "sluggable", + "sortable", + "timestampable", + "translatable", + "tree", + "uploadable" + ], + "support": { + "email": "gediminas.morkevicius@gmail.com", + "issues": "https://github.com/Atlantic18/DoctrineExtensions/issues", + "source": "https://github.com/Atlantic18/DoctrineExtensions/tree/v3.0.0", + "wiki": "https://github.com/Atlantic18/DoctrineExtensions/tree/master/doc" + }, + "time": "2020-09-23T16:40:45+00:00" + }, { "name": "google/recaptcha", "version": "1.2.4", @@ -3736,6 +3882,76 @@ ], "time": "2019-12-09T12:56:15+00:00" }, + { + "name": "stof/doctrine-extensions-bundle", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/stof/StofDoctrineExtensionsBundle.git", + "reference": "c01e73e49cee5eac3353b6c4ebdbb0a151348c85" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stof/StofDoctrineExtensionsBundle/zipball/c01e73e49cee5eac3353b6c4ebdbb0a151348c85", + "reference": "c01e73e49cee5eac3353b6c4ebdbb0a151348c85", + "shasum": "" + }, + "require": { + "gedmo/doctrine-extensions": "^2.3.4 || ^3.0.0", + "php": "^7.1.3", + "symfony/framework-bundle": "^4.3 || ^5.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4", + "symfony/security-bundle": "^4.3 || ^5.0" + }, + "suggest": { + "doctrine/doctrine-bundle": "to use the ORM extensions", + "doctrine/mongodb-odm-bundle": "to use the MongoDB ODM extensions", + "symfony/mime": "To use the Mime component integration for Uploadable" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Stof\\DoctrineExtensionsBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christophe Coevoet", + "email": "stof@notk.org" + } + ], + "description": "Integration of the gedmo/doctrine-extensions with Symfony2", + "homepage": "https://github.com/stof/StofDoctrineExtensionsBundle", + "keywords": [ + "behaviors", + "doctrine2", + "extensions", + "gedmo", + "loggable", + "nestedset", + "sluggable", + "sortable", + "timestampable", + "translatable", + "tree" + ], + "support": { + "issues": "https://github.com/stof/StofDoctrineExtensionsBundle/issues", + "source": "https://github.com/stof/StofDoctrineExtensionsBundle/tree/v1.5.0" + }, + "time": "2020-09-30T13:25:17+00:00" + }, { "name": "swiftmailer/swiftmailer", "version": "v6.2.3", @@ -9706,5 +9922,5 @@ "ext-iconv": "*" }, "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/config/bundles.php b/config/bundles.php index 038a204..4cf74cd 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -25,4 +25,5 @@ Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'test' => true], Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['dev' => true, 'test' => true], Hautelook\AliceBundle\HautelookAliceBundle::class => ['dev' => true, 'test' => true], + Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true], ]; diff --git a/config/packages/stof_doctrine_extensions.yaml b/config/packages/stof_doctrine_extensions.yaml new file mode 100644 index 0000000..5fcc5aa --- /dev/null +++ b/config/packages/stof_doctrine_extensions.yaml @@ -0,0 +1,5 @@ +stof_doctrine_extensions: + default_locale: en_US + orm: + default: + sluggable: true \ No newline at end of file diff --git a/src/Entity/MeetupEvent.php b/src/Entity/MeetupEvent.php index f3a25f8..8c30725 100644 --- a/src/Entity/MeetupEvent.php +++ b/src/Entity/MeetupEvent.php @@ -8,6 +8,7 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\HttpFoundation\File\File; use Vich\UploaderBundle\Mapping\Annotation as Vich; +use Gedmo\Mapping\Annotation as Gdemo; /** * @ORM\Entity(repositoryClass=MeetupEventRepository::class) @@ -122,6 +123,12 @@ class MeetupEvent */ private $updatedAt; + /** + * @ORM\Column(type="string", length=255, unique=true) + * @Gdemo\Slug(fields={"title"}) + */ + private $slug; + public function getId(): ?int { return $this->id; @@ -388,4 +395,16 @@ public function getUpdatedAt(): ?DateTimeInterface { return $this->updatedAt; } + + public function getSlug(): ?string + { + return $this->slug; + } + + public function setSlug(string $slug): self + { + $this->slug = $slug; + + return $this; + } } diff --git a/src/Migrations/Version20201127130925.php b/src/Migrations/Version20201127130925.php new file mode 100644 index 0000000..bf60d3c --- /dev/null +++ b/src/Migrations/Version20201127130925.php @@ -0,0 +1,35 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE meetup_event ADD slug VARCHAR(255) NOT NULL, CHANGE created_at created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE meetup_event DROP slug, CHANGE created_at created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL'); + } +} diff --git a/src/Migrations/Version20201127131115.php b/src/Migrations/Version20201127131115.php new file mode 100644 index 0000000..24d5ab7 --- /dev/null +++ b/src/Migrations/Version20201127131115.php @@ -0,0 +1,61 @@ +addSql($sql); + $this->addSql('CREATE UNIQUE INDEX UNIQ_7EA6C459989D9B62 ON meetup_event (slug)'); + } + + public function down(Schema $schema) : void + { + $this->addSql('DROP INDEX UNIQ_7EA6C459989D9B62 ON meetup_event'); + $this->addSql('UPDATE meetup_event SET slug = ""'); + } +} diff --git a/symfony.lock b/symfony.lock index b613015..d5406a3 100644 --- a/symfony.lock +++ b/symfony.lock @@ -1,4 +1,7 @@ { + "behat/transliterator": { + "version": "v1.3.0" + }, "clue/stream-filter": { "version": "v1.4.1" }, @@ -148,6 +151,9 @@ "config/packages/fos_ckeditor.yaml" ] }, + "gedmo/doctrine-extensions": { + "version": "v3.0.0" + }, "google/recaptcha": { "version": "1.1", "recipe": { @@ -385,6 +391,18 @@ "config/packages/snc_redis.yaml" ] }, + "stof/doctrine-extensions-bundle": { + "version": "1.2", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "1.2", + "ref": "6c1ceb662f8997085f739cd089bfbef67f245983" + }, + "files": [ + "config/packages/stof_doctrine_extensions.yaml" + ] + }, "swiftmailer/swiftmailer": { "version": "v6.2.1" }, diff --git a/tests/Unit/Entity/MeetupEventTest.php b/tests/Unit/Entity/MeetupEventTest.php new file mode 100644 index 0000000..0dd63fb --- /dev/null +++ b/tests/Unit/Entity/MeetupEventTest.php @@ -0,0 +1,66 @@ +setTitle('Hello world!') + ->setMeetupId(123456789) + ->setScheduledAt(new DateTime()) + ->setUrl('http://example.com'); + $this->em->persist($meetupEvent); + $this->em->flush(); + + $this->assertSame('hello-world', $meetupEvent->getSlug()); + } + + /** @test */ + public function theSlugShouldBeUnique(): void + { + $meetupEvent = new MeetupEvent(); + $meetupEvent + ->setTitle('Hello world!') + ->setMeetupId(123456789) + ->setScheduledAt(new DateTime()) + ->setUrl('http://example.com'); + + $duplicateMeetupEvent = new MeetupEvent(); + $duplicateMeetupEvent + ->setTitle('Hello world!') + ->setMeetupId(123456788) + ->setScheduledAt(new DateTime()) + ->setUrl('http://example.com'); + + $this->em->persist($meetupEvent); + $this->em->persist($duplicateMeetupEvent); + $this->em->flush(); + + $this->assertSame('hello-world-1', $duplicateMeetupEvent->getSlug()); + } + + protected function setUp(): void + { + $this->em = $this->bootKernel() + ->getContainer() + ->get('doctrine') + ->getManager(); + } +} \ No newline at end of file