From a28c1d17c5943a3fd6042a14fb5f826f44ac611b Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sun, 16 Dec 2018 12:08:03 +0100 Subject: [PATCH 1/2] Moved entities mappings from annotations to external config files --- .../src/Factory/EntityManagerFactory.php | 12 ++-- .../Shlinkio.Shlink.Core.Entity.ShortUrl.php | 63 +++++++++++++++++++ .../Shlinkio.Shlink.Core.Entity.Tag.php | 25 ++++++++ .../Shlinkio.Shlink.Core.Entity.Visit.php | 52 +++++++++++++++ ...inkio.Shlink.Core.Entity.VisitLocation.php | 37 +++++++++++ module/Core/config/entity-manager.config.php | 4 +- module/Core/src/Entity/ShortUrl.php | 61 +++--------------- module/Core/src/Entity/Tag.php | 15 +---- module/Core/src/Entity/Visit.php | 42 ++----------- module/Core/src/Entity/VisitLocation.php | 44 +++---------- .../Shlinkio.Shlink.Rest.Entity.ApiKey.php | 33 ++++++++++ module/Rest/config/entity-manager.config.php | 4 +- module/Rest/src/Entity/ApiKey.php | 24 +------ 13 files changed, 244 insertions(+), 172 deletions(-) create mode 100644 module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.ShortUrl.php create mode 100644 module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.Tag.php create mode 100644 module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.Visit.php create mode 100644 module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.VisitLocation.php create mode 100644 module/Rest/config/entities-mappings/Shlinkio.Shlink.Rest.Entity.ApiKey.php diff --git a/module/Common/src/Factory/EntityManagerFactory.php b/module/Common/src/Factory/EntityManagerFactory.php index bb0c1b14..13580a44 100644 --- a/module/Common/src/Factory/EntityManagerFactory.php +++ b/module/Common/src/Factory/EntityManagerFactory.php @@ -5,6 +5,7 @@ namespace Shlinkio\Shlink\Common\Factory; use Doctrine\Common\Cache\ArrayCache; use Doctrine\Common\Cache\Cache; +use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Types\Type; use Doctrine\ORM\EntityManager; @@ -37,12 +38,9 @@ class EntityManagerFactory implements FactoryInterface Type::addType(ChronosDateTimeType::CHRONOS_DATETIME, ChronosDateTimeType::class); } - return EntityManager::create($connectionConfig, Setup::createAnnotationMetadataConfiguration( - $ormConfig['entities_paths'] ?? [], - $isDevMode, - $ormConfig['proxies_dir'] ?? null, - $cache, - false - )); + $config = Setup::createConfiguration($isDevMode, $ormConfig['proxies_dir'] ?? null, $cache); + $config->setMetadataDriverImpl(new PHPDriver($ormConfig['entities_mappings'] ?? [])); + + return EntityManager::create($connectionConfig, $config); } } diff --git a/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.ShortUrl.php b/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.ShortUrl.php new file mode 100644 index 00000000..c6bdcb86 --- /dev/null +++ b/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.ShortUrl.php @@ -0,0 +1,63 @@ +setTable('short_urls') + ->setCustomRepositoryClass(Repository\ShortUrlRepository::class); + +$builder->createField('id', Type::BIGINT) + ->columnName('id') + ->makePrimaryKey() + ->generatedValue('IDENTITY') + ->option('unsigned', true) + ->build(); + +$builder->createField('longUrl', Type::STRING) + ->columnName('original_url') + ->length(1024) + ->build(); + +$builder->createField('shortCode', Type::STRING) + ->columnName('short_code') + ->unique() + ->length(255) + ->build(); + +$builder->createField('dateCreated', ChronosDateTimeType::CHRONOS_DATETIME) + ->columnName('date_created') + ->build(); + +$builder->createField('validSince', ChronosDateTimeType::CHRONOS_DATETIME) + ->columnName('valid_since') + ->nullable() + ->build(); + +$builder->createField('validUntil', ChronosDateTimeType::CHRONOS_DATETIME) + ->columnName('valid_until') + ->nullable() + ->build(); + +$builder->createField('maxVisits', Type::INTEGER) + ->columnName('max_visits') + ->nullable() + ->build(); + +$builder->createOneToMany('visits', Entity\Visit::class) + ->mappedBy('shortUrl') + ->fetchExtraLazy() + ->build(); + +$builder->createManyToMany('tags', Entity\Tag::class) + ->setJoinTable('short_urls_in_tags') + ->addInverseJoinColumn('tag_id', 'id') + ->addJoinColumn('short_url_id', 'id') + ->build(); diff --git a/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.Tag.php b/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.Tag.php new file mode 100644 index 00000000..e78ead58 --- /dev/null +++ b/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.Tag.php @@ -0,0 +1,25 @@ +setTable('tags') + ->setCustomRepositoryClass(Repository\TagRepository::class); + +$builder->createField('id', Type::BIGINT) + ->columnName('id') + ->makePrimaryKey() + ->generatedValue('IDENTITY') + ->option('unsigned', true) + ->build(); + +$builder->createField('name', Type::STRING) + ->unique() + ->build(); diff --git a/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.Visit.php b/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.Visit.php new file mode 100644 index 00000000..5e0c4c31 --- /dev/null +++ b/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.Visit.php @@ -0,0 +1,52 @@ +setTable('visits') + ->setCustomRepositoryClass(Repository\VisitRepository::class); + +$builder->createField('id', Type::BIGINT) + ->columnName('id') + ->makePrimaryKey() + ->generatedValue('IDENTITY') + ->option('unsigned', true) + ->build(); + +$builder->createField('referer', Type::STRING) + ->nullable() + ->length(256) + ->build(); + +$builder->createField('date', ChronosDateTimeType::CHRONOS_DATETIME) + ->columnName('`date`') + ->build(); + +$builder->createField('remoteAddr', Type::STRING) + ->columnName('remote_addr') + ->length(256) + ->nullable() + ->build(); + +$builder->createField('userAgent', Type::STRING) + ->columnName('user_agent') + ->length(512) + ->nullable() + ->build(); + +$builder->createManyToOne('shortUrl', Entity\ShortUrl::class) + ->addJoinColumn('short_url_id', 'id', false) + ->build(); + +$builder->createManyToOne('visitLocation', Entity\VisitLocation::class) + ->addJoinColumn('visit_location_id', 'id') + ->cascadePersist() + ->build(); diff --git a/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.VisitLocation.php b/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.VisitLocation.php new file mode 100644 index 00000000..ced3b393 --- /dev/null +++ b/module/Core/config/entities-mappings/Shlinkio.Shlink.Core.Entity.VisitLocation.php @@ -0,0 +1,37 @@ +setTable('visit_locations'); + +$builder->createField('id', Type::BIGINT) + ->columnName('id') + ->makePrimaryKey() + ->generatedValue('IDENTITY') + ->option('unsigned', true) + ->build(); + +$columns = [ + 'country_code' => 'countryCode', + 'country_name' => 'countryName', + 'region_name' => 'regionName', + 'city_name' => 'cityName', + 'latitude' => 'latitude', + 'longitude' => 'longitude', + 'timezone' => 'timezone', +]; + +foreach ($columns as $columnName => $fieldName) { + $builder->createField($fieldName, Type::STRING) + ->columnName($columnName) + ->nullable() + ->build(); +} diff --git a/module/Core/config/entity-manager.config.php b/module/Core/config/entity-manager.config.php index e5008568..4d331494 100644 --- a/module/Core/config/entity-manager.config.php +++ b/module/Core/config/entity-manager.config.php @@ -5,8 +5,8 @@ return [ 'entity_manager' => [ 'orm' => [ - 'entities_paths' => [ - __DIR__ . '/../src/Entity', + 'entities_mappings' => [ + __DIR__ . '/../config/entities-mappings', ], ], ], diff --git a/module/Core/src/Entity/ShortUrl.php b/module/Core/src/Entity/ShortUrl.php index 15e9f594..0e75ad1b 100644 --- a/module/Core/src/Entity/ShortUrl.php +++ b/module/Core/src/Entity/ShortUrl.php @@ -6,72 +6,27 @@ namespace Shlinkio\Shlink\Core\Entity; use Cake\Chronos\Chronos; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; -use Doctrine\ORM\Mapping as ORM; use Shlinkio\Shlink\Common\Entity\AbstractEntity; use Shlinkio\Shlink\Core\Model\ShortUrlMeta; -use Shlinkio\Shlink\Core\Repository\ShortUrlRepository; use function count; -/** - * Class ShortUrl - * @author - * @link - * - * @ORM\Entity(repositoryClass=ShortUrlRepository::class) - * @ORM\Table(name="short_urls") - */ class ShortUrl extends AbstractEntity { - /** - * @var string - * @ORM\Column(name="original_url", type="string", nullable=false, length=1024) - */ + /** @var string */ private $longUrl; - /** - * @var string - * @ORM\Column( - * name="short_code", - * type="string", - * nullable=false, - * length=255, - * unique=true - * ) - */ + /** @var string */ private $shortCode; - /** - * @var Chronos - * @ORM\Column(name="date_created", type="chronos_datetime") - */ + /** @var Chronos */ private $dateCreated; - /** - * @var Collection|Visit[] - * @ORM\OneToMany(targetEntity=Visit::class, mappedBy="shortUrl", fetch="EXTRA_LAZY") - */ + /** @var Collection|Visit[] */ private $visits; - /** - * @var Collection|Tag[] - * @ORM\ManyToMany(targetEntity=Tag::class, cascade={"persist"}) - * @ORM\JoinTable(name="short_urls_in_tags", joinColumns={ - * @ORM\JoinColumn(name="short_url_id", referencedColumnName="id") - * }, inverseJoinColumns={ - * @ORM\JoinColumn(name="tag_id", referencedColumnName="id") - * }) - */ + /** @var Collection|Tag[] */ private $tags; - /** - * @var Chronos|null - * @ORM\Column(name="valid_since", type="chronos_datetime", nullable=true) - */ + /** @var Chronos|null */ private $validSince; - /** - * @var Chronos|null - * @ORM\Column(name="valid_until", type="chronos_datetime", nullable=true) - */ + /** @var Chronos|null */ private $validUntil; - /** - * @var integer - * @ORM\Column(name="max_visits", type="integer", nullable=true) - */ + /** @var integer|null */ private $maxVisits; public function __construct(string $longUrl, ShortUrlMeta $meta = null) diff --git a/module/Core/src/Entity/Tag.php b/module/Core/src/Entity/Tag.php index 78ddad80..67fd6e3c 100644 --- a/module/Core/src/Entity/Tag.php +++ b/module/Core/src/Entity/Tag.php @@ -3,25 +3,12 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Entity; -use Doctrine\ORM\Mapping as ORM; use JsonSerializable; use Shlinkio\Shlink\Common\Entity\AbstractEntity; -use Shlinkio\Shlink\Core\Repository\TagRepository; -/** - * Class Tag - * @author - * @link - * - * @ORM\Entity(repositoryClass=TagRepository::class) - * @ORM\Table(name="tags") - */ class Tag extends AbstractEntity implements JsonSerializable { - /** - * @var string - * @ORM\Column(unique=true) - */ + /** @var string */ private $name; public function __construct(string $name) diff --git a/module/Core/src/Entity/Visit.php b/module/Core/src/Entity/Visit.php index f8008f8c..928a243a 100644 --- a/module/Core/src/Entity/Visit.php +++ b/module/Core/src/Entity/Visit.php @@ -4,57 +4,27 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Entity; use Cake\Chronos\Chronos; -use Doctrine\ORM\Mapping as ORM; use JsonSerializable; use Shlinkio\Shlink\Common\Entity\AbstractEntity; use Shlinkio\Shlink\Common\Exception\WrongIpException; use Shlinkio\Shlink\Common\Util\IpAddress; use Shlinkio\Shlink\Core\Model\Visitor; -use Shlinkio\Shlink\Core\Repository\VisitRepository; use Shlinkio\Shlink\Core\Visit\Model\UnknownVisitLocation; use Shlinkio\Shlink\Core\Visit\Model\VisitLocationInterface; -/** - * Class Visit - * @author - * @link - * - * @ORM\Entity(repositoryClass=VisitRepository::class) - * @ORM\Table(name="visits") - */ class Visit extends AbstractEntity implements JsonSerializable { - /** - * @var string - * @ORM\Column(type="string", length=256, nullable=true) - */ + /** @var string */ private $referer; - /** - * @var Chronos - * @ORM\Column(type="chronos_datetime", nullable=false) - */ + /** @var Chronos */ private $date; - /** - * @var string|null - * @ORM\Column(type="string", length=256, name="remote_addr", nullable=true) - */ + /** @var string|null */ private $remoteAddr; - /** - * @var string - * @ORM\Column(type="string", length=512, name="user_agent", nullable=true) - */ + /** @var string */ private $userAgent; - /** - * @var ShortUrl - * @ORM\ManyToOne(targetEntity=ShortUrl::class) - * @ORM\JoinColumn(name="short_url_id", referencedColumnName="id") - */ + /** @var ShortUrl */ private $shortUrl; - /** - * @var VisitLocation - * @ORM\ManyToOne(targetEntity=VisitLocation::class, cascade={"persist"}) - * @ORM\JoinColumn(name="visit_location_id", referencedColumnName="id", nullable=true) - */ + /** @var VisitLocation */ private $visitLocation; public function __construct(ShortUrl $shortUrl, Visitor $visitor, ?Chronos $date = null) diff --git a/module/Core/src/Entity/VisitLocation.php b/module/Core/src/Entity/VisitLocation.php index 472de2ee..ad68117b 100644 --- a/module/Core/src/Entity/VisitLocation.php +++ b/module/Core/src/Entity/VisitLocation.php @@ -3,55 +3,25 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Core\Entity; -use Doctrine\ORM\Mapping as ORM; use Shlinkio\Shlink\Common\Entity\AbstractEntity; use Shlinkio\Shlink\Core\Visit\Model\VisitLocationInterface; use function array_key_exists; -/** - * Class VisitLocation - * @author - * @link - * - * @ORM\Entity() - * @ORM\Table(name="visit_locations") - */ class VisitLocation extends AbstractEntity implements VisitLocationInterface { - /** - * @var string - * @ORM\Column(nullable=true, name="country_code") - */ + /** @var string */ private $countryCode; - /** - * @var string - * @ORM\Column(nullable=true, name="country_name") - */ + /** @var string */ private $countryName; - /** - * @var string - * @ORM\Column(nullable=true, name="region_name") - */ + /** @var string */ private $regionName; - /** - * @var string - * @ORM\Column(nullable=true, name="city_name") - */ + /** @var string */ private $cityName; - /** - * @var string - * @ORM\Column(nullable=true, name="latitude") - */ + /** @var string */ private $latitude; - /** - * @var string - * @ORM\Column(nullable=true, name="longitude") - */ + /** @var string */ private $longitude; - /** - * @var string - * @ORM\Column(nullable=true, name="timezone") - */ + /** @var string */ private $timezone; public function __construct(array $locationInfo) diff --git a/module/Rest/config/entities-mappings/Shlinkio.Shlink.Rest.Entity.ApiKey.php b/module/Rest/config/entities-mappings/Shlinkio.Shlink.Rest.Entity.ApiKey.php new file mode 100644 index 00000000..f790d925 --- /dev/null +++ b/module/Rest/config/entities-mappings/Shlinkio.Shlink.Rest.Entity.ApiKey.php @@ -0,0 +1,33 @@ +setTable('api_keys'); + +$builder->createField('id', Type::BIGINT) + ->makePrimaryKey() + ->generatedValue('IDENTITY') + ->option('unsigned', true) + ->build(); + +$builder->createField('key', Type::STRING) + ->columnName('`key`') + ->unique() + ->build(); + +$builder->createField('expirationDate', ChronosDateTimeType::CHRONOS_DATETIME) + ->columnName('expiration_date') + ->nullable() + ->build(); + +$builder->createField('enabled', Type::BOOLEAN) + ->build(); diff --git a/module/Rest/config/entity-manager.config.php b/module/Rest/config/entity-manager.config.php index e5008568..4d331494 100644 --- a/module/Rest/config/entity-manager.config.php +++ b/module/Rest/config/entity-manager.config.php @@ -5,8 +5,8 @@ return [ 'entity_manager' => [ 'orm' => [ - 'entities_paths' => [ - __DIR__ . '/../src/Entity', + 'entities_mappings' => [ + __DIR__ . '/../config/entities-mappings', ], ], ], diff --git a/module/Rest/src/Entity/ApiKey.php b/module/Rest/src/Entity/ApiKey.php index ea48605f..c0f86c67 100644 --- a/module/Rest/src/Entity/ApiKey.php +++ b/module/Rest/src/Entity/ApiKey.php @@ -4,36 +4,18 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Rest\Entity; use Cake\Chronos\Chronos; -use Doctrine\ORM\Mapping as ORM; use Shlinkio\Shlink\Common\Entity\AbstractEntity; use Shlinkio\Shlink\Common\Util\StringUtilsTrait; -/** - * Class ApiKey - * @author Shlink - * @link http://shlink.io - * - * @ORM\Entity() - * @ORM\Table(name="api_keys") - */ class ApiKey extends AbstractEntity { use StringUtilsTrait; - /** - * @var string - * @ORM\Column(name="`key`", nullable=false, unique=true) - */ + /** @var string */ private $key; - /** - * @var Chronos|null - * @ORM\Column(name="expiration_date", nullable=true, type="chronos_datetime") - */ + /** @var Chronos|null */ private $expirationDate; - /** - * @var bool - * @ORM\Column(type="boolean") - */ + /** @var bool */ private $enabled; public function __construct(?Chronos $expirationDate = null) From a6ec93f88329a276d12f694ec7b7e617c718a448 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sun, 16 Dec 2018 12:14:13 +0100 Subject: [PATCH 2/2] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32955747..6118280a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), * [#312](https://github.com/shlinkio/shlink/issues/312) Now all config files both in `php` and `json` format are loaded from `config/params` folder, easing users to provided customizations to docker image. * [#226](https://github.com/shlinkio/shlink/issues/226) Updated how table are rendered in CLI commands, making use of new features in Symfony 4.2. +* [#321](https://github.com/shlinkio/shlink/issues/321) Extracted entities mappings from entities to external config files. #### Deprecated