diff --git a/docs/en/dao.md b/docs/en/dao.md deleted file mode 100644 index b1c0ea73..00000000 --- a/docs/en/dao.md +++ /dev/null @@ -1,56 +0,0 @@ -# EntityDao - -It extends the `Kdyby\Doctrine\EntityRepository`, and is the default "repository" class for all entities. -Please prefer using `EntityRepository` only, unless you really know what you're doing. - - -## `->add($entity)` - -This is alias for `EntityManager::persist()`, but it checks that you've given it entity that belongs to the DAO you've used. - - -## `->save($entity)` - -This method persist the entity, and at the same time, it flushes all the entities that belong to this DAO. - -**Warning:** the default behaviour that sadly cannot be changed easily is that when you provide new entity, -the relations are also persisted (if they're configured to cascade), but when you provide already managed entity, -then the **relations are not saved**! - -This method is strictly for prototyping, or when you know you need to save only one entity, or when you really know what you're doing. -You should almost always prefer calling the `EntityManager::flush()`. - - -## `->safePersist($entity)` - -This method solves the problem, that when you flush entity, that violates unique constraint, the UnitOfWork throws and locks itself and EntityManager. -And there is no way to unlock it, you have to create new instance of EntityManager. - -So this method finds all the columns in the entity that had to be inserted (unique, not-nullable and identifier columns), -and then reads their values and builds SQL query that is safely ran against the database. - -If the query fails, it means that entity with that value of some of it's unique indexes is already in database, -which means that you'll get an exception, but it won't kill the EntityManager. - -If the query runs and returns newly inserted identifier, the identifier is forced to the entity and the entity is merged to the EntityManager. -This also means that you will always get new instance of your entity, -because merging cannot merge references of two entities and it has to drop one of them (so it drops reference to the one you've provided). - - -## `->delete($entity)` - -Marks entity that it should be deleted and flushes the EntityManager. - - -## `->transactional($callback)` - -You can pass a closure and be sure that it's execution will be wrapped in transaction. - -```php -$dao->transactional(function ($dao, $entityManager) { - $article = $dao->findOneBy(['author' => $author]); - $dao->delete($article); -}); -``` - -The same method is also on EntityManager, but this one has the `$dao` as first argument. diff --git a/src/Kdyby/Doctrine/DI/OrmExtension.php b/src/Kdyby/Doctrine/DI/OrmExtension.php index 298191dc..10b3018c 100644 --- a/src/Kdyby/Doctrine/DI/OrmExtension.php +++ b/src/Kdyby/Doctrine/DI/OrmExtension.php @@ -56,7 +56,7 @@ class OrmExtension extends Nette\DI\CompilerExtension 'logging' => '%debugMode%', ], 'classMetadataFactory' => 'Kdyby\Doctrine\Mapping\ClassMetadataFactory', - 'defaultRepositoryClassName' => 'Kdyby\Doctrine\EntityDao', + 'defaultRepositoryClassName' => 'Kdyby\Doctrine\EntityRepository', 'repositoryFactoryClassName' => 'Kdyby\Doctrine\RepositoryFactory', 'queryBuilderClassName' => 'Kdyby\Doctrine\QueryBuilder', 'autoGenerateProxyClasses' => '%debugMode%', @@ -417,23 +417,6 @@ protected function processEntityManager($name, array $defaults) $entityManager->addSetup('?->bindEntityManager(?)', [$this->prefix('@' . $name . '.diagnosticsPanel'), '@self']); } - if ($isDefault && $config['defaultRepositoryClassName'] === 'Kdyby\Doctrine\EntityDao') { - // syntax sugar for config - $builder->addDefinition($this->prefix('dao')) - ->setClass('Kdyby\Doctrine\EntityDao') - ->setFactory('@Kdyby\Doctrine\EntityManager::getDao', [new Code\PhpLiteral('$entityName')]) - ->setParameters(['entityName']) - ->setInject(FALSE); - - // interface for models & presenters - $builder->addDefinition($this->prefix('daoFactory')) - ->setClass('Kdyby\Doctrine\EntityDao') - ->setFactory('@Kdyby\Doctrine\EntityManager::getDao', [new Code\PhpLiteral('$entityName')]) - ->setParameters(['entityName']) - ->setImplement('Kdyby\Doctrine\EntityDaoFactory') - ->setInject(FALSE)->setAutowired(TRUE); - } - $builder->addDefinition($this->prefix('repositoryFactory.' . $name . '.defaultRepositoryFactory')) ->setClass($config['defaultRepositoryClassName']) ->setImplement('Kdyby\Doctrine\DI\IRepositoryFactory') @@ -709,7 +692,7 @@ protected function processRepositories() } $factory = $originalDef->getFactory() ? $originalDef->getFactory()->getEntity() : $originalDef->getClass(); - if (stripos($factory, '::getRepository') !== FALSE || stripos($factory, '::getDao') !== FALSE) { + if (stripos($factory, '::getRepository') !== FALSE) { continue; // ignore } diff --git a/src/Kdyby/Doctrine/EntityDao.php b/src/Kdyby/Doctrine/EntityDao.php deleted file mode 100644 index 59433478..00000000 --- a/src/Kdyby/Doctrine/EntityDao.php +++ /dev/null @@ -1,216 +0,0 @@ - - */ -class EntityDao extends EntityRepository implements Persistence\ObjectDao -{ - - /** - * Persists given entities, but does not flush. - * - * @param object|array|\Traversable $entity - * @param object|array|\Traversable $relations - * @throws InvalidArgumentException - * @return array - */ - public function add($entity, $relations = NULL) - { - foreach ($relations = self::iterableArgs($relations) as $item) { - $this->getEntityManager()->persist($item); - } - - foreach ($entity = self::iterableArgs($entity) as $item) { - if (!$item instanceof $this->_entityName) { - throw new InvalidArgumentException('Entity is not instanceof ' . $this->_entityName . ', instanceof ' . get_class($item) . ' given.'); - } - - $this->getEntityManager()->persist($item); - } - - return array_merge($entity, $relations); - } - - - - /** - * Persists given entities and flushes them, and only them, to the storage. - * If no entities are passed, all the entities of current type are persisted. - * - * @deprecated I won't remove this method for BC, but please stop using it ASAP! Use EntityManager->persist() and ->flush(), this is only a dumb shortcut for VERY specific use-cases! - * - * @param object|array|\Traversable $entity - * @param object|array|\Traversable $relations - * @throws InvalidArgumentException - * @return array - */ - public function save($entity = NULL, $relations = NULL) - { - if ($entity !== NULL) { - $result = $this->add($entity, $relations); - $this->getEntityManager()->flush(array_merge($result, $this->getLoadedEntities())); - - return (empty($relations) && !is_array($entity) && !$entity instanceof \Traversable) ? $entity : $result; - } - - $this->flush(); - return []; - } - - - - /** - * @param object $entity - * @throws InvalidArgumentException - * @return bool|object - */ - public function safePersist($entity) - { - if (!$entity instanceof $this->_entityName) { - throw new InvalidArgumentException('Entity is not instanceof ' . $this->_entityName . ', ' . get_class($entity) . ' given.'); - } - - return $this->getEntityManager()->safePersist($entity); - } - - - - /** - * @deprecated I won't remove this method for BC, but please stop using it ASAP! Use EntityManager->remove() and ->flush(), this is only a dumb shortcut for VERY specific use-cases! - * - * @param object|array|\Traversable $entity - * @param object|array|\Traversable|bool $relations - * @param bool $flush - * @throws InvalidArgumentException - */ - public function delete($entity, $relations = NULL, $flush = Persistence\ObjectDao::FLUSH) - { - if (is_bool($relations)) { - $flush = $relations; - $relations = NULL; - } - - foreach (self::iterableArgs($relations) as $item) { - $this->getEntityManager()->remove($item); - } - - foreach (self::iterableArgs($entity) as $item) { - if (!$item instanceof $this->_entityName) { - throw new InvalidArgumentException('Entity is not instanceof ' . $this->_entityName . ', ' . get_class($item) . ' given.'); - } - - $this->getEntityManager()->remove($item); - } - - $this->flush($flush); - } - - - - /** - * @param boolean $flush - */ - protected function flush($flush = Persistence\ObjectDao::FLUSH) - { - if ($flush === Persistence\ObjectDao::FLUSH) { - $this->getEntityManager()->flush($this->getLoadedEntities()); - } - } - - - - /** - * @return object[] - */ - private function getLoadedEntities() - { - $em = $this->getEntityManager(); - $UoW = $em->getUnitOfWork(); - $im = $UoW->getIdentityMap(); - - return array_merge( - $UoW->getScheduledEntityDeletions(), - $UoW->getScheduledEntityInsertions(), - !empty($im[$this->_entityName]) ? Arrays::flatten($im[$this->_entityName]) : [] - ); - } - - - - /** - * @deprecated I won't remove this method for BC, but please stop using it ASAP! Use EntityManager->transactional(), this is only a dumb shortcut for VERY specific use-cases! - * - * @param callable $callback - * @throws \Exception - * @return mixed|boolean - */ - public function transactional($callback) - { - $connection = $this->getEntityManager()->getConnection(); - $connection->beginTransaction(); - - try { - $return = Callback::invoke($callback, $this, $this->getEntityManager()); - $this->flush(); - $connection->commit(); - - return $return ? : TRUE; - - } catch (\Exception $e) { - $connection->rollback(); - throw $e; - } - } - - - - /** - * @param array|string|\Traversable $args - * @return array|\Traversable - */ - private static function iterableArgs($args) - { - if (empty($args)) { - return []; - } - - return !is_array($args) && !$args instanceof \Traversable ? [$args] : $args; - } - -} diff --git a/src/Kdyby/Doctrine/EntityDaoFactory.php b/src/Kdyby/Doctrine/EntityDaoFactory.php deleted file mode 100644 index 9b7db399..00000000 --- a/src/Kdyby/Doctrine/EntityDaoFactory.php +++ /dev/null @@ -1,30 +0,0 @@ - - */ -interface EntityDaoFactory -{ - - /** - * @param string $className - * @return EntityDao - */ - function create($className); - -} diff --git a/src/Kdyby/Doctrine/EntityManager.php b/src/Kdyby/Doctrine/EntityManager.php index fcaa2f78..475b6509 100644 --- a/src/Kdyby/Doctrine/EntityManager.php +++ b/src/Kdyby/Doctrine/EntityManager.php @@ -34,12 +34,6 @@ class EntityManager extends Doctrine\ORM\EntityManager implements Persistence\QueryExecutor, Persistence\Queryable { - /** - * @deprecated - * @var array - */ - public $onDaoCreate = []; - /** * @var NonLockingUniqueInserter */ @@ -209,19 +203,6 @@ public function safePersist($entity) - /** - * @deprecated Use the EntityManager::getRepository(), this is a useless alias. - * - * @param string $entityName - * @return EntityDao - */ - public function getDao($entityName) - { - return $this->getRepository($entityName); - } - - - /** * @param int $hydrationMode * @return Doctrine\ORM\Internal\Hydration\AbstractHydrator @@ -279,16 +260,6 @@ public static function create($conn, Doctrine\ORM\Configuration $config, Doctrin - /** - * @deprecated - */ - public function onDaoCreate(EntityManager $em, Doctrine\Common\Persistence\ObjectRepository $dao) - { - $this->__call(__FUNCTION__, func_get_args()); - } - - - /****************** Kdyby\Persistence\QueryExecutor *****************/ diff --git a/src/Kdyby/Doctrine/EntityRepository.php b/src/Kdyby/Doctrine/EntityRepository.php index 0539d2e1..51e73916 100644 --- a/src/Kdyby/Doctrine/EntityRepository.php +++ b/src/Kdyby/Doctrine/EntityRepository.php @@ -353,14 +353,14 @@ public function getEntityManager() /** * @param string $relation - * @return EntityDao + * @return EntityRepository */ public function related($relation) { $meta = $this->getClassMetadata(); $targetClass = $meta->getAssociationTargetClass($relation); - return $this->getEntityManager()->getDao($targetClass); + return $this->getEntityManager()->getRepository($targetClass); } diff --git a/src/Kdyby/Doctrine/QueryObject.php b/src/Kdyby/Doctrine/QueryObject.php index 929f3ff0..bac1f378 100644 --- a/src/Kdyby/Doctrine/QueryObject.php +++ b/src/Kdyby/Doctrine/QueryObject.php @@ -43,7 +43,7 @@ * * $productsQuery->size = 'big'; * - * $this->template->products = $this->productsDao->fetch($productsQuery); + * $this->template->products = $this->productsRepository->fetch($productsQuery); * * * @method onPostFetch(QueryObject $self, Queryable $repository, \Iterator $iterator) diff --git a/src/Kdyby/Doctrine/Registry.php b/src/Kdyby/Doctrine/Registry.php index ad35f036..6edf239e 100644 --- a/src/Kdyby/Doctrine/Registry.php +++ b/src/Kdyby/Doctrine/Registry.php @@ -23,7 +23,7 @@ * @method EntityManager getManager($name = NULL) * @method EntityManager getManagerForClass($class) * @method EntityManager[] getManagers() - * @method EntityRepository|EntityDao getRepository($persistentObjectName, $persistentManagerName = NULL) + * @method EntityRepository getRepository($persistentObjectName, $persistentManagerName = NULL) * @method Connection getConnection($name = NULL) * @method Connection[] getConnections() */ diff --git a/src/Kdyby/Doctrine/RepositoryFactory.php b/src/Kdyby/Doctrine/RepositoryFactory.php index 6a444d74..45e47bc4 100644 --- a/src/Kdyby/Doctrine/RepositoryFactory.php +++ b/src/Kdyby/Doctrine/RepositoryFactory.php @@ -85,9 +85,7 @@ public function getRepository(EntityManagerInterface $entityManager, $entityName /** @var Doctrine\ORM\Mapping\ClassMetadata $metadata */ $metadata = $entityManager->getClassMetadata($entityName); - $repository = $this->createRepository($entityManager, $metadata); - $entityManager->onDaoCreate($entityManager, $repository); return $this->repositoryList[$emId][$entityName] = $repository; } diff --git a/src/Kdyby/Doctrine/ResultSet.php b/src/Kdyby/Doctrine/ResultSet.php index 1cae6659..4d879b44 100644 --- a/src/Kdyby/Doctrine/ResultSet.php +++ b/src/Kdyby/Doctrine/ResultSet.php @@ -27,7 +27,7 @@ * * public function renderDefault() * { - * $articles = $this->articlesDao->fetch(new ArticlesQuery()); + * $articles = $this->articlesRepository->fetch(new ArticlesQuery()); * $articles->applyPaginator($this['vp']->paginator); * $this->template->articles = $articles; * } diff --git a/src/Kdyby/Persistence/ObjectDao.php b/src/Kdyby/Persistence/ObjectDao.php deleted file mode 100644 index 84240fa0..00000000 --- a/src/Kdyby/Persistence/ObjectDao.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ -interface ObjectDao extends Doctrine\Common\Persistence\ObjectRepository -{ - - const FLUSH = TRUE; - const NO_FLUSH = FALSE; - - - /** - * Persists given entities, but does not flush. - * - * @param array|Doctrine\Common\Collections\Collection|\Traversable - */ - function add($entity); - - - /** - * Persists given entities and flushes them down to the storage. - * - * @param array|Doctrine\Common\Collections\Collection|\Traversable|NULL - */ - function save($entity = NULL); - - - /** - * @param array|Doctrine\Common\Collections\Collection|\Traversable - * @param boolean $flush - */ - function delete($entity, $flush = self::FLUSH); - -} diff --git a/tests/KdybyTests/Doctrine/EntityDao.phpt b/tests/KdybyTests/Doctrine/EntityDao.phpt deleted file mode 100644 index ecb2fdc1..00000000 --- a/tests/KdybyTests/Doctrine/EntityDao.phpt +++ /dev/null @@ -1,162 +0,0 @@ - - * @package Kdyby\Doctrine - */ - -namespace KdybyTests\Doctrine; - -use Doctrine\ORM\Query\Parameter; -use Kdyby; -use KdybyTests\Doctrine\ORMTestCase; -use Nette; -use Tester; -use Tester\Assert; - -require_once __DIR__ . '/../bootstrap.php'; -require_once __DIR__ . '/models/cms.php'; - - - -/** - * @author Filip Procházka - */ -class EntityDaoTest extends ORMTestCase -{ - - /** - * @var Kdyby\Doctrine\EntityManager - */ - private $em; - - - - protected function setUp() - { - $this->em = $this->createMemoryManager(); - } - - - - public function testSave_New() - { - $user = new CmsUser(); - $user->username = 'hosiplan'; - $user->name = 'Filip Procházka'; - - $users = $this->em->getDao('KdybyTests\Doctrine\CmsUser'); - $newId = $users->save($user)->id; - Assert::match('%d%', $newId); - - $this->em->clear(); - - Assert::same('hosiplan', $users->find($newId)->username); - Assert::same('Filip Procházka', $users->find($newId)->name); - } - - - - public function testSave_Managed() - { - $user = new CmsUser(); - $user->username = 'hosiplan'; - $user->name = 'Filip Procházka'; - - $this->em->persist($user); - $this->em->flush(); - - $newId = $user->id; - Assert::match('%d%', $newId); - - $this->em->clear(); - - $users = $this->em->getDao('KdybyTests\Doctrine\CmsUser'); - $user = $users->find($newId); - - Assert::null($user->status); - $user->status = 'admin'; - $users->save($user); - - $this->em->clear(); - - $user = $users->find($newId); - Assert::same('admin', $user->status); - } - - - - public function testSelect() - { - $users = $this->em->getDao('KdybyTests\Doctrine\CmsUser'); - $qb = $users->select('u'); - - Assert::same('SELECT u FROM KdybyTests\Doctrine\CmsUser u', $qb->getDQL()); - } - - - - public function testSelectIndexed() - { - $users = $this->em->getDao('KdybyTests\Doctrine\CmsUser'); - $qb = $users->select('u', 'id'); - - Assert::same('SELECT u FROM KdybyTests\Doctrine\CmsUser u INDEX BY u.id', $qb->getDQL()); - } - - - - public function testSelectWithoutParameters() - { - $users = $this->em->getDao('KdybyTests\Doctrine\CmsUser'); - $qb = $users->select(); - - Assert::same('SELECT c FROM KdybyTests\Doctrine\CmsUser c', $qb->getDQL()); - } - - - - public function testFindPairs() - { - $dao = $this->em->getDao('KdybyTests\Doctrine\CmsUser'); - $dao->save([ - new CmsUser('c', 'new'), - new CmsUser('a', 'old'), - new CmsUser('b', 'new'), - ]); - - $this->em->clear(); - - Assert::same([ - 1 => 'c', - 3 => 'b', - ], $dao->findPairs(['status' => 'new'], 'name')); - - Assert::same([ - 3 => 'b', - 1 => 'c', - ], $dao->findPairs(['status' => 'new'], 'name', ['name'])); - - Assert::same([ - 3 => 'b', - 1 => 'c', - ], $dao->findPairs(['status' => 'new'], 'name', ['name' => 'ASC'])); - } - - public function testCountBy() - { - $dao = $this->em->getDao('KdybyTests\Doctrine\CmsUser'); - $dao->save([ - new CmsUser('c', 'new'), - new CmsUser('a', 'old'), - new CmsUser('b', 'new'), - ]); - Assert::same(2, $dao->countBy(['status' => 'new'])); - } - -} - -\run(new EntityDaoTest()); diff --git a/tests/KdybyTests/Doctrine/EntityRepository.phpt b/tests/KdybyTests/Doctrine/EntityRepository.phpt new file mode 100644 index 00000000..5cb1d372 --- /dev/null +++ b/tests/KdybyTests/Doctrine/EntityRepository.phpt @@ -0,0 +1,116 @@ + + * @package Kdyby\Doctrine + */ + +namespace KdybyTests\Doctrine; + +use Doctrine\ORM\Query\Parameter; +use Kdyby; +use KdybyTests\Doctrine\ORMTestCase; +use Nette; +use Tester; +use Tester\Assert; + +require_once __DIR__ . '/../bootstrap.php'; +require_once __DIR__ . '/models/cms.php'; + + + +/** + * @author Filip Procházka + */ +class EntityRepositoryTest extends ORMTestCase +{ + + /** + * @var Kdyby\Doctrine\EntityManager + */ + private $em; + + + + protected function setUp() + { + $this->em = $this->createMemoryManager(); + } + + + + public function testSelect() + { + $users = $this->em->getRepository('KdybyTests\Doctrine\CmsUser'); + $qb = $users->select('u'); + + Assert::same('SELECT u FROM KdybyTests\Doctrine\CmsUser u', $qb->getDQL()); + } + + + + public function testSelectIndexed() + { + $users = $this->em->getRepository('KdybyTests\Doctrine\CmsUser'); + $qb = $users->select('u', 'id'); + + Assert::same('SELECT u FROM KdybyTests\Doctrine\CmsUser u INDEX BY u.id', $qb->getDQL()); + } + + + + public function testSelectWithoutParameters() + { + $users = $this->em->getRepository('KdybyTests\Doctrine\CmsUser'); + $qb = $users->select(); + + Assert::same('SELECT c FROM KdybyTests\Doctrine\CmsUser c', $qb->getDQL()); + } + + + + public function testFindPairs() + { + $this->em->persist(new CmsUser('c', 'new')); + $this->em->persist(new CmsUser('a', 'old')); + $this->em->persist(new CmsUser('b', 'new')); + $this->em->flush(); + $this->em->clear(); + + $repository = $this->em->getRepository('KdybyTests\Doctrine\CmsUser'); + + Assert::same([ + 1 => 'c', + 3 => 'b', + ], $repository->findPairs(['status' => 'new'], 'name')); + + Assert::same([ + 3 => 'b', + 1 => 'c', + ], $repository->findPairs(['status' => 'new'], 'name', ['name'])); + + Assert::same([ + 3 => 'b', + 1 => 'c', + ], $repository->findPairs(['status' => 'new'], 'name', ['name' => 'ASC'])); + } + + public function testCountBy() + { + $this->em->persist(new CmsUser('c', 'new')); + $this->em->persist(new CmsUser('a', 'old')); + $this->em->persist(new CmsUser('b', 'new')); + $this->em->flush(); + $this->em->clear(); + + $repository = $this->em->getRepository('KdybyTests\Doctrine\CmsUser'); + + Assert::same(2, $repository->countBy(['status' => 'new'])); + } + +} + +\run(new EntityRepositoryTest()); diff --git a/tests/KdybyTests/Doctrine/Extension.phpt b/tests/KdybyTests/Doctrine/Extension.phpt index b02996fc..6a990029 100644 --- a/tests/KdybyTests/Doctrine/Extension.phpt +++ b/tests/KdybyTests/Doctrine/Extension.phpt @@ -54,8 +54,8 @@ class ExtensionTest extends Tester\TestCase $default = $container->getByType('Kdyby\Doctrine\EntityManager'); Assert::true($default instanceof Kdyby\Doctrine\EntityManager); - $userDao = $default->getRepository('KdybyTests\Doctrine\CmsUser'); - Assert::true($userDao instanceof Kdyby\Doctrine\EntityDao); + $userRepository = $default->getRepository('KdybyTests\Doctrine\CmsUser'); + Assert::true($userRepository instanceof Kdyby\Doctrine\EntityRepository); } diff --git a/tests/KdybyTests/Doctrine/config/repository-factory.manual.neon b/tests/KdybyTests/Doctrine/config/repository-factory.manual.neon index f019e141..dc344e47 100644 --- a/tests/KdybyTests/Doctrine/config/repository-factory.manual.neon +++ b/tests/KdybyTests/Doctrine/config/repository-factory.manual.neon @@ -13,4 +13,4 @@ services: - class: KdybyTests\Doctrine\CmsGroupRepository - factory: @Kdyby\Doctrine\EntityManager::getDao(KdybyTests\Doctrine\CmsGroup) + factory: @Kdyby\Doctrine\EntityManager::getRepository(KdybyTests\Doctrine\CmsGroup) diff --git a/tests/KdybyTests/Doctrine/config/repository-factory.neon b/tests/KdybyTests/Doctrine/config/repository-factory.neon index e2e50dd5..e9d917dd 100644 --- a/tests/KdybyTests/Doctrine/config/repository-factory.neon +++ b/tests/KdybyTests/Doctrine/config/repository-factory.neon @@ -16,4 +16,4 @@ services: - class: KdybyTests\Doctrine\CmsGroupRepository - factory: @Kdyby\Doctrine\EntityManager::getDao(KdybyTests\Doctrine\CmsGroup) + factory: @Kdyby\Doctrine\EntityManager::getRepository(KdybyTests\Doctrine\CmsGroup)