PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php

http://github.com/doctrine/doctrine2
PHP | 1396 lines | 1012 code | 223 blank | 161 comment | 4 complexity | f3a617a01b036e78d044753bde8026d2 MD5 | raw file
Possible License(s): Unlicense

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\Tests\ORM\Mapping;
  4. use ArrayObject;
  5. use Doctrine\ORM\Events;
  6. use Doctrine\ORM\Mapping\ClassMetadata;
  7. use Doctrine\ORM\Mapping\Column;
  8. use Doctrine\ORM\Mapping\DefaultNamingStrategy;
  9. use Doctrine\ORM\Mapping\MappedSuperclass;
  10. use Doctrine\ORM\Mapping\MappingException;
  11. use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
  12. use Doctrine\Persistence\Mapping\RuntimeReflectionService;
  13. use Doctrine\Persistence\Mapping\StaticReflectionService;
  14. use Doctrine\Tests\Models\CMS;
  15. use Doctrine\Tests\Models\CMS\CmsEmail;
  16. use Doctrine\Tests\Models\Company\CompanyContract;
  17. use Doctrine\Tests\Models\CustomType\CustomTypeParent;
  18. use Doctrine\Tests\Models\DDC117\DDC117Article;
  19. use Doctrine\Tests\Models\DDC117\DDC117ArticleDetails;
  20. use Doctrine\Tests\Models\DDC6412\DDC6412File;
  21. use Doctrine\Tests\Models\DDC964\DDC964Admin;
  22. use Doctrine\Tests\Models\DDC964\DDC964Guest;
  23. use Doctrine\Tests\Models\Routing\RoutingLeg;
  24. use Doctrine\Tests\Models\TypedProperties;
  25. use Doctrine\Tests\OrmTestCase;
  26. use DoctrineGlobalArticle;
  27. use ReflectionClass;
  28. use function assert;
  29. use function count;
  30. use function serialize;
  31. use function str_replace;
  32. use function strpos;
  33. use function strtolower;
  34. use function strtoupper;
  35. use function unserialize;
  36. use const CASE_UPPER;
  37. use const PHP_VERSION_ID;
  38. require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
  39. class ClassMetadataTest extends OrmTestCase
  40. {
  41. public function testClassMetadataInstanceSerialization(): void
  42. {
  43. $cm = new ClassMetadata(CMS\CmsUser::class);
  44. $cm->initializeReflection(new RuntimeReflectionService());
  45. // Test initial state
  46. self::assertTrue(count($cm->getReflectionProperties()) === 0);
  47. self::assertInstanceOf('ReflectionClass', $cm->reflClass);
  48. self::assertEquals(CMS\CmsUser::class, $cm->name);
  49. self::assertEquals(CMS\CmsUser::class, $cm->rootEntityName);
  50. self::assertEquals([], $cm->subClasses);
  51. self::assertEquals([], $cm->parentClasses);
  52. self::assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $cm->inheritanceType);
  53. // Customize state
  54. $cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
  55. $cm->setSubclasses(['One', 'Two', 'Three']);
  56. $cm->setParentClasses(['UserParent']);
  57. $cm->setCustomRepositoryClass('UserRepository');
  58. $cm->setDiscriminatorColumn(['name' => 'disc', 'type' => 'integer']);
  59. $cm->mapOneToOne(['fieldName' => 'phonenumbers', 'targetEntity' => 'CmsAddress', 'mappedBy' => 'foo']);
  60. $cm->markReadOnly();
  61. $cm->addNamedQuery(['name' => 'dql', 'query' => 'foo']);
  62. self::assertEquals(1, count($cm->associationMappings));
  63. $serialized = serialize($cm);
  64. $cm = unserialize($serialized);
  65. $cm->wakeupReflection(new RuntimeReflectionService());
  66. // Check state
  67. self::assertTrue(count($cm->getReflectionProperties()) > 0);
  68. self::assertEquals('Doctrine\Tests\Models\CMS', $cm->namespace);
  69. self::assertInstanceOf(ReflectionClass::class, $cm->reflClass);
  70. self::assertEquals(CMS\CmsUser::class, $cm->name);
  71. self::assertEquals('UserParent', $cm->rootEntityName);
  72. self::assertEquals([CMS\One::class, CMS\Two::class, CMS\Three::class], $cm->subClasses);
  73. self::assertEquals(['UserParent'], $cm->parentClasses);
  74. self::assertEquals(CMS\UserRepository::class, $cm->customRepositoryClassName);
  75. self::assertEquals(['name' => 'disc', 'type' => 'integer', 'fieldName' => 'disc'], $cm->discriminatorColumn);
  76. self::assertTrue($cm->associationMappings['phonenumbers']['type'] === ClassMetadata::ONE_TO_ONE);
  77. self::assertEquals(1, count($cm->associationMappings));
  78. $oneOneMapping = $cm->getAssociationMapping('phonenumbers');
  79. self::assertTrue($oneOneMapping['fetch'] === ClassMetadata::FETCH_LAZY);
  80. self::assertEquals('phonenumbers', $oneOneMapping['fieldName']);
  81. self::assertEquals(CMS\CmsAddress::class, $oneOneMapping['targetEntity']);
  82. self::assertTrue($cm->isReadOnly);
  83. self::assertEquals(['dql' => ['name' => 'dql', 'query' => 'foo', 'dql' => 'foo']], $cm->namedQueries);
  84. }
  85. public function testFieldIsNullable(): void
  86. {
  87. $cm = new ClassMetadata(CMS\CmsUser::class);
  88. $cm->initializeReflection(new RuntimeReflectionService());
  89. // Explicit Nullable
  90. $cm->mapField(['fieldName' => 'status', 'nullable' => true, 'type' => 'string', 'length' => 50]);
  91. self::assertTrue($cm->isNullable('status'));
  92. // Explicit Not Nullable
  93. $cm->mapField(['fieldName' => 'username', 'nullable' => false, 'type' => 'string', 'length' => 50]);
  94. self::assertFalse($cm->isNullable('username'));
  95. // Implicit Not Nullable
  96. $cm->mapField(['fieldName' => 'name', 'type' => 'string', 'length' => 50]);
  97. self::assertFalse($cm->isNullable('name'), 'By default a field should not be nullable.');
  98. }
  99. public function testFieldIsNullableByType(): void
  100. {
  101. if (PHP_VERSION_ID < 70400) {
  102. self::markTestSkipped('requies PHP 7.4');
  103. }
  104. $cm = new ClassMetadata(TypedProperties\UserTyped::class);
  105. $cm->initializeReflection(new RuntimeReflectionService());
  106. $cm->mapOneToOne(['fieldName' => 'email', 'joinColumns' => [[]]]);
  107. self::assertEquals(CmsEmail::class, $cm->getAssociationMapping('email')['targetEntity']);
  108. $cm->mapManyToOne(['fieldName' => 'mainEmail']);
  109. self::assertEquals(CmsEmail::class, $cm->getAssociationMapping('mainEmail')['targetEntity']);
  110. $cm->mapEmbedded(['fieldName' => 'contact']);
  111. self::assertEquals(TypedProperties\Contact::class, $cm->embeddedClasses['contact']['class']);
  112. }
  113. public function testFieldTypeFromReflection(): void
  114. {
  115. if (PHP_VERSION_ID < 70400) {
  116. self::markTestSkipped('requies PHP 7.4');
  117. }
  118. $cm = new ClassMetadata(TypedProperties\UserTyped::class);
  119. $cm->initializeReflection(new RuntimeReflectionService());
  120. // Integer
  121. $cm->mapField(['fieldName' => 'id']);
  122. self::assertEquals('integer', $cm->getTypeOfField('id'));
  123. // String
  124. $cm->mapField(['fieldName' => 'username', 'length' => 50]);
  125. self::assertEquals('string', $cm->getTypeOfField('username'));
  126. // DateInterval object
  127. $cm->mapField(['fieldName' => 'dateInterval']);
  128. self::assertEquals('dateinterval', $cm->getTypeOfField('dateInterval'));
  129. // DateTime object
  130. $cm->mapField(['fieldName' => 'dateTime']);
  131. self::assertEquals('datetime', $cm->getTypeOfField('dateTime'));
  132. // DateTimeImmutable object
  133. $cm->mapField(['fieldName' => 'dateTimeImmutable']);
  134. self::assertEquals('datetime_immutable', $cm->getTypeOfField('dateTimeImmutable'));
  135. // array as JSON
  136. $cm->mapField(['fieldName' => 'array']);
  137. self::assertEquals('json', $cm->getTypeOfField('array'));
  138. // bool
  139. $cm->mapField(['fieldName' => 'boolean']);
  140. self::assertEquals('boolean', $cm->getTypeOfField('boolean'));
  141. // float
  142. $cm->mapField(['fieldName' => 'float']);
  143. self::assertEquals('float', $cm->getTypeOfField('float'));
  144. }
  145. /**
  146. * @group DDC-115
  147. */
  148. public function testMapAssociationInGlobalNamespace(): void
  149. {
  150. require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
  151. $cm = new ClassMetadata('DoctrineGlobalArticle');
  152. $cm->initializeReflection(new RuntimeReflectionService());
  153. $cm->mapManyToMany(
  154. [
  155. 'fieldName' => 'author',
  156. 'targetEntity' => 'DoctrineGlobalUser',
  157. 'joinTable' => [
  158. 'name' => 'bar',
  159. 'joinColumns' => [['name' => 'bar_id', 'referencedColumnName' => 'id']],
  160. 'inverseJoinColumns' => [['name' => 'baz_id', 'referencedColumnName' => 'id']],
  161. ],
  162. ]
  163. );
  164. self::assertEquals('DoctrineGlobalUser', $cm->associationMappings['author']['targetEntity']);
  165. }
  166. public function testMapManyToManyJoinTableDefaults(): void
  167. {
  168. $cm = new ClassMetadata(CMS\CmsUser::class);
  169. $cm->initializeReflection(new RuntimeReflectionService());
  170. $cm->mapManyToMany(
  171. [
  172. 'fieldName' => 'groups',
  173. 'targetEntity' => 'CmsGroup',
  174. ]
  175. );
  176. $assoc = $cm->associationMappings['groups'];
  177. self::assertEquals(
  178. [
  179. 'name' => 'cmsuser_cmsgroup',
  180. 'joinColumns' => [['name' => 'cmsuser_id', 'referencedColumnName' => 'id', 'onDelete' => 'CASCADE']],
  181. 'inverseJoinColumns' => [['name' => 'cmsgroup_id', 'referencedColumnName' => 'id', 'onDelete' => 'CASCADE']],
  182. ],
  183. $assoc['joinTable']
  184. );
  185. self::assertTrue($assoc['isOnDeleteCascade']);
  186. }
  187. public function testSerializeManyToManyJoinTableCascade(): void
  188. {
  189. $cm = new ClassMetadata(CMS\CmsUser::class);
  190. $cm->initializeReflection(new RuntimeReflectionService());
  191. $cm->mapManyToMany(
  192. [
  193. 'fieldName' => 'groups',
  194. 'targetEntity' => 'CmsGroup',
  195. ]
  196. );
  197. $assoc = $cm->associationMappings['groups'];
  198. $assoc = unserialize(serialize($assoc));
  199. self::assertTrue($assoc['isOnDeleteCascade']);
  200. }
  201. /**
  202. * @group DDC-115
  203. */
  204. public function testSetDiscriminatorMapInGlobalNamespace(): void
  205. {
  206. require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
  207. $cm = new ClassMetadata('DoctrineGlobalUser');
  208. $cm->initializeReflection(new RuntimeReflectionService());
  209. $cm->setDiscriminatorMap(['descr' => 'DoctrineGlobalArticle', 'foo' => 'DoctrineGlobalUser']);
  210. self::assertEquals('DoctrineGlobalArticle', $cm->discriminatorMap['descr']);
  211. self::assertEquals('DoctrineGlobalUser', $cm->discriminatorMap['foo']);
  212. }
  213. /**
  214. * @group DDC-115
  215. */
  216. public function testSetSubClassesInGlobalNamespace(): void
  217. {
  218. require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
  219. $cm = new ClassMetadata('DoctrineGlobalUser');
  220. $cm->initializeReflection(new RuntimeReflectionService());
  221. $cm->setSubclasses(['DoctrineGlobalArticle']);
  222. self::assertEquals('DoctrineGlobalArticle', $cm->subClasses[0]);
  223. }
  224. /**
  225. * @group DDC-268
  226. */
  227. public function testSetInvalidVersionMappingThrowsException(): void
  228. {
  229. $field = [];
  230. $field['fieldName'] = 'foo';
  231. $field['type'] = 'string';
  232. $cm = new ClassMetadata(CMS\CmsUser::class);
  233. $cm->initializeReflection(new RuntimeReflectionService());
  234. $this->expectException(MappingException::class);
  235. $cm->setVersionMapping($field);
  236. }
  237. public function testGetSingleIdentifierFieldNameMultipleIdentifierEntityThrowsException(): void
  238. {
  239. $cm = new ClassMetadata(CMS\CmsUser::class);
  240. $cm->initializeReflection(new RuntimeReflectionService());
  241. $cm->isIdentifierComposite = true;
  242. $this->expectException(MappingException::class);
  243. $cm->getSingleIdentifierFieldName();
  244. }
  245. public function testGetSingleIdentifierFieldNameNoIdEntityThrowsException(): void
  246. {
  247. $cm = new ClassMetadata(DDC6412File::class);
  248. $cm->initializeReflection(new RuntimeReflectionService());
  249. $this->expectException(MappingException::class);
  250. $cm->getSingleIdentifierFieldName();
  251. }
  252. public function testDuplicateAssociationMappingException(): void
  253. {
  254. $cm = new ClassMetadata(CMS\CmsUser::class);
  255. $cm->initializeReflection(new RuntimeReflectionService());
  256. $a1 = ['fieldName' => 'foo', 'sourceEntity' => 'stdClass', 'targetEntity' => 'stdClass', 'mappedBy' => 'foo'];
  257. $a2 = ['fieldName' => 'foo', 'sourceEntity' => 'stdClass', 'targetEntity' => 'stdClass', 'mappedBy' => 'foo'];
  258. $cm->addInheritedAssociationMapping($a1);
  259. $this->expectException(MappingException::class);
  260. $cm->addInheritedAssociationMapping($a2);
  261. }
  262. public function testDuplicateColumnNameThrowsMappingException(): void
  263. {
  264. $cm = new ClassMetadata(CMS\CmsUser::class);
  265. $cm->initializeReflection(new RuntimeReflectionService());
  266. $cm->mapField(['fieldName' => 'name', 'columnName' => 'name']);
  267. $this->expectException(MappingException::class);
  268. $cm->mapField(['fieldName' => 'username', 'columnName' => 'name']);
  269. }
  270. public function testDuplicateColumnNameDiscriminatorColumnThrowsMappingException(): void
  271. {
  272. $cm = new ClassMetadata(CMS\CmsUser::class);
  273. $cm->initializeReflection(new RuntimeReflectionService());
  274. $cm->mapField(['fieldName' => 'name', 'columnName' => 'name']);
  275. $this->expectException(MappingException::class);
  276. $cm->setDiscriminatorColumn(['name' => 'name']);
  277. }
  278. public function testDuplicateColumnNameDiscriminatorColumn2ThrowsMappingException(): void
  279. {
  280. $cm = new ClassMetadata(CMS\CmsUser::class);
  281. $cm->initializeReflection(new RuntimeReflectionService());
  282. $cm->setDiscriminatorColumn(['name' => 'name']);
  283. $this->expectException(MappingException::class);
  284. $cm->mapField(['fieldName' => 'name', 'columnName' => 'name']);
  285. }
  286. public function testDuplicateFieldAndAssociationMapping1ThrowsException(): void
  287. {
  288. $cm = new ClassMetadata(CMS\CmsUser::class);
  289. $cm->initializeReflection(new RuntimeReflectionService());
  290. $cm->mapField(['fieldName' => 'name', 'columnName' => 'name']);
  291. $this->expectException(MappingException::class);
  292. $cm->mapOneToOne(['fieldName' => 'name', 'targetEntity' => 'CmsUser']);
  293. }
  294. public function testDuplicateFieldAndAssociationMapping2ThrowsException(): void
  295. {
  296. $cm = new ClassMetadata(CMS\CmsUser::class);
  297. $cm->initializeReflection(new RuntimeReflectionService());
  298. $cm->mapOneToOne(['fieldName' => 'name', 'targetEntity' => 'CmsUser']);
  299. $this->expectException(MappingException::class);
  300. $cm->mapField(['fieldName' => 'name', 'columnName' => 'name']);
  301. }
  302. /**
  303. * @group DDC-1224
  304. */
  305. public function testGetTemporaryTableNameSchema(): void
  306. {
  307. $cm = new ClassMetadata(CMS\CmsUser::class);
  308. $cm->initializeReflection(new RuntimeReflectionService());
  309. $cm->setTableName('foo.bar');
  310. self::assertEquals('foo_bar_id_tmp', $cm->getTemporaryIdTableName());
  311. }
  312. public function testDefaultTableName(): void
  313. {
  314. $cm = new ClassMetadata(CMS\CmsUser::class);
  315. $cm->initializeReflection(new RuntimeReflectionService());
  316. // When table's name is not given
  317. $primaryTable = [];
  318. $cm->setPrimaryTable($primaryTable);
  319. self::assertEquals('CmsUser', $cm->getTableName());
  320. self::assertEquals('CmsUser', $cm->table['name']);
  321. $cm = new ClassMetadata(CMS\CmsAddress::class);
  322. $cm->initializeReflection(new RuntimeReflectionService());
  323. // When joinTable's name is not given
  324. $cm->mapManyToMany(
  325. [
  326. 'fieldName' => 'user',
  327. 'targetEntity' => 'CmsUser',
  328. 'inversedBy' => 'users',
  329. 'joinTable' => [
  330. 'joinColumns' => [['referencedColumnName' => 'id']],
  331. 'inverseJoinColumns' => [['referencedColumnName' => 'id']],
  332. ],
  333. ]
  334. );
  335. self::assertEquals('cmsaddress_cmsuser', $cm->associationMappings['user']['joinTable']['name']);
  336. }
  337. public function testDefaultJoinColumnName(): void
  338. {
  339. $cm = new ClassMetadata(CMS\CmsAddress::class);
  340. $cm->initializeReflection(new RuntimeReflectionService());
  341. // this is really dirty, but it's the simplest way to test whether
  342. // joinColumn's name will be automatically set to user_id
  343. $cm->mapOneToOne(
  344. [
  345. 'fieldName' => 'user',
  346. 'targetEntity' => 'CmsUser',
  347. 'joinColumns' => [['referencedColumnName' => 'id']],
  348. ]
  349. );
  350. self::assertEquals('user_id', $cm->associationMappings['user']['joinColumns'][0]['name']);
  351. $cm = new ClassMetadata(CMS\CmsAddress::class);
  352. $cm->initializeReflection(new RuntimeReflectionService());
  353. $cm->mapManyToMany(
  354. [
  355. 'fieldName' => 'user',
  356. 'targetEntity' => 'CmsUser',
  357. 'inversedBy' => 'users',
  358. 'joinTable' => [
  359. 'name' => 'user_CmsUser',
  360. 'joinColumns' => [['referencedColumnName' => 'id']],
  361. 'inverseJoinColumns' => [['referencedColumnName' => 'id']],
  362. ],
  363. ]
  364. );
  365. self::assertEquals('cmsaddress_id', $cm->associationMappings['user']['joinTable']['joinColumns'][0]['name']);
  366. self::assertEquals('cmsuser_id', $cm->associationMappings['user']['joinTable']['inverseJoinColumns'][0]['name']);
  367. }
  368. /**
  369. * @group DDC-559
  370. */
  371. public function testUnderscoreNamingStrategyDefaults(): void
  372. {
  373. $namingStrategy = new UnderscoreNamingStrategy(CASE_UPPER);
  374. $oneToOneMetadata = new ClassMetadata(CMS\CmsAddress::class, $namingStrategy);
  375. $manyToManyMetadata = new ClassMetadata(CMS\CmsAddress::class, $namingStrategy);
  376. $oneToOneMetadata->mapOneToOne(
  377. [
  378. 'fieldName' => 'user',
  379. 'targetEntity' => 'CmsUser',
  380. ]
  381. );
  382. $manyToManyMetadata->mapManyToMany(
  383. [
  384. 'fieldName' => 'user',
  385. 'targetEntity' => 'CmsUser',
  386. ]
  387. );
  388. self::assertEquals(['USER_ID' => 'ID'], $oneToOneMetadata->associationMappings['user']['sourceToTargetKeyColumns']);
  389. self::assertEquals(['USER_ID' => 'USER_ID'], $oneToOneMetadata->associationMappings['user']['joinColumnFieldNames']);
  390. self::assertEquals(['ID' => 'USER_ID'], $oneToOneMetadata->associationMappings['user']['targetToSourceKeyColumns']);
  391. self::assertEquals('USER_ID', $oneToOneMetadata->associationMappings['user']['joinColumns'][0]['name']);
  392. self::assertEquals('ID', $oneToOneMetadata->associationMappings['user']['joinColumns'][0]['referencedColumnName']);
  393. self::assertEquals('CMS_ADDRESS_CMS_USER', $manyToManyMetadata->associationMappings['user']['joinTable']['name']);
  394. self::assertEquals(['CMS_ADDRESS_ID', 'CMS_USER_ID'], $manyToManyMetadata->associationMappings['user']['joinTableColumns']);
  395. self::assertEquals(['CMS_ADDRESS_ID' => 'ID'], $manyToManyMetadata->associationMappings['user']['relationToSourceKeyColumns']);
  396. self::assertEquals(['CMS_USER_ID' => 'ID'], $manyToManyMetadata->associationMappings['user']['relationToTargetKeyColumns']);
  397. self::assertEquals('CMS_ADDRESS_ID', $manyToManyMetadata->associationMappings['user']['joinTable']['joinColumns'][0]['name']);
  398. self::assertEquals('CMS_USER_ID', $manyToManyMetadata->associationMappings['user']['joinTable']['inverseJoinColumns'][0]['name']);
  399. self::assertEquals('ID', $manyToManyMetadata->associationMappings['user']['joinTable']['joinColumns'][0]['referencedColumnName']);
  400. self::assertEquals('ID', $manyToManyMetadata->associationMappings['user']['joinTable']['inverseJoinColumns'][0]['referencedColumnName']);
  401. $cm = new ClassMetadata('DoctrineGlobalArticle', $namingStrategy);
  402. $cm->mapManyToMany(['fieldName' => 'author', 'targetEntity' => CMS\CmsUser::class]);
  403. self::assertEquals('DOCTRINE_GLOBAL_ARTICLE_CMS_USER', $cm->associationMappings['author']['joinTable']['name']);
  404. }
  405. /**
  406. * @group DDC-886
  407. */
  408. public function testSetMultipleIdentifierSetsComposite(): void
  409. {
  410. $cm = new ClassMetadata(CMS\CmsUser::class);
  411. $cm->initializeReflection(new RuntimeReflectionService());
  412. $cm->mapField(['fieldName' => 'name']);
  413. $cm->mapField(['fieldName' => 'username']);
  414. $cm->setIdentifier(['name', 'username']);
  415. self::assertTrue($cm->isIdentifierComposite);
  416. }
  417. /**
  418. * @group DDC-944
  419. */
  420. public function testMappingNotFound(): void
  421. {
  422. $cm = new ClassMetadata(CMS\CmsUser::class);
  423. $cm->initializeReflection(new RuntimeReflectionService());
  424. $this->expectException(MappingException::class);
  425. $this->expectExceptionMessage("No mapping found for field 'foo' on class '" . CMS\CmsUser::class . "'.");
  426. $cm->getFieldMapping('foo');
  427. }
  428. /**
  429. * @group DDC-961
  430. */
  431. public function testJoinTableMappingDefaults(): void
  432. {
  433. $cm = new ClassMetadata('DoctrineGlobalArticle');
  434. $cm->initializeReflection(new RuntimeReflectionService());
  435. $cm->mapManyToMany(['fieldName' => 'author', 'targetEntity' => CMS\CmsUser::class]);
  436. self::assertEquals('doctrineglobalarticle_cmsuser', $cm->associationMappings['author']['joinTable']['name']);
  437. }
  438. /**
  439. * @group DDC-117
  440. */
  441. public function testMapIdentifierAssociation(): void
  442. {
  443. $cm = new ClassMetadata(DDC117ArticleDetails::class);
  444. $cm->initializeReflection(new RuntimeReflectionService());
  445. $cm->mapOneToOne(
  446. [
  447. 'fieldName' => 'article',
  448. 'id' => true,
  449. 'targetEntity' => DDC117Article::class,
  450. 'joinColumns' => [],
  451. ]
  452. );
  453. self::assertTrue($cm->containsForeignIdentifier, "Identifier Association should set 'containsForeignIdentifier' boolean flag.");
  454. self::assertEquals(['article'], $cm->identifier);
  455. }
  456. /**
  457. * @group DDC-117
  458. */
  459. public function testOrphanRemovalIdentifierAssociation(): void
  460. {
  461. $cm = new ClassMetadata(DDC117ArticleDetails::class);
  462. $cm->initializeReflection(new RuntimeReflectionService());
  463. $this->expectException(MappingException::class);
  464. $this->expectExceptionMessage('The orphan removal option is not allowed on an association that');
  465. $cm->mapOneToOne(
  466. [
  467. 'fieldName' => 'article',
  468. 'id' => true,
  469. 'targetEntity' => DDC117Article::class,
  470. 'orphanRemoval' => true,
  471. 'joinColumns' => [],
  472. ]
  473. );
  474. }
  475. /**
  476. * @group DDC-117
  477. */
  478. public function testInverseIdentifierAssociation(): void
  479. {
  480. $cm = new ClassMetadata(DDC117ArticleDetails::class);
  481. $cm->initializeReflection(new RuntimeReflectionService());
  482. $this->expectException(MappingException::class);
  483. $this->expectExceptionMessage('An inverse association is not allowed to be identifier in');
  484. $cm->mapOneToOne(
  485. [
  486. 'fieldName' => 'article',
  487. 'id' => true,
  488. 'mappedBy' => 'details', // INVERSE!
  489. 'targetEntity' => DDC117Article::class,
  490. 'joinColumns' => [],
  491. ]
  492. );
  493. }
  494. /**
  495. * @group DDC-117
  496. */
  497. public function testIdentifierAssociationManyToMany(): void
  498. {
  499. $cm = new ClassMetadata(DDC117ArticleDetails::class);
  500. $cm->initializeReflection(new RuntimeReflectionService());
  501. $this->expectException(MappingException::class);
  502. $this->expectExceptionMessage('Many-to-many or one-to-many associations are not allowed to be identifier in');
  503. $cm->mapManyToMany(
  504. [
  505. 'fieldName' => 'article',
  506. 'id' => true,
  507. 'targetEntity' => DDC117Article::class,
  508. 'joinColumns' => [],
  509. ]
  510. );
  511. }
  512. /**
  513. * @group DDC-996
  514. */
  515. public function testEmptyFieldNameThrowsException(): void
  516. {
  517. $this->expectException(MappingException::class);
  518. $this->expectExceptionMessage("The field or association mapping misses the 'fieldName' attribute in entity '" . CMS\CmsUser::class . "'.");
  519. $cm = new ClassMetadata(CMS\CmsUser::class);
  520. $cm->initializeReflection(new RuntimeReflectionService());
  521. $cm->mapField(['fieldName' => '']);
  522. }
  523. public function testRetrievalOfNamedQueries(): void
  524. {
  525. $cm = new ClassMetadata(CMS\CmsUser::class);
  526. $cm->initializeReflection(new RuntimeReflectionService());
  527. self::assertCount(0, $cm->getNamedQueries());
  528. $cm->addNamedQuery(
  529. [
  530. 'name' => 'userById',
  531. 'query' => 'SELECT u FROM __CLASS__ u WHERE u.id = ?1',
  532. ]
  533. );
  534. self::assertCount(1, $cm->getNamedQueries());
  535. }
  536. /**
  537. * @group DDC-1663
  538. */
  539. public function testRetrievalOfResultSetMappings(): void
  540. {
  541. $cm = new ClassMetadata(CMS\CmsUser::class);
  542. $cm->initializeReflection(new RuntimeReflectionService());
  543. self::assertCount(0, $cm->getSqlResultSetMappings());
  544. $cm->addSqlResultSetMapping(
  545. [
  546. 'name' => 'find-all',
  547. 'entities' => [
  548. [
  549. 'entityClass' => CMS\CmsUser::class,
  550. ],
  551. ],
  552. ]
  553. );
  554. self::assertCount(1, $cm->getSqlResultSetMappings());
  555. }
  556. public function testExistanceOfNamedQuery(): void
  557. {
  558. $cm = new ClassMetadata(CMS\CmsUser::class);
  559. $cm->initializeReflection(new RuntimeReflectionService());
  560. $cm->addNamedQuery(
  561. [
  562. 'name' => 'all',
  563. 'query' => 'SELECT u FROM __CLASS__ u',
  564. ]
  565. );
  566. self::assertTrue($cm->hasNamedQuery('all'));
  567. self::assertFalse($cm->hasNamedQuery('userById'));
  568. }
  569. /**
  570. * @group DDC-1663
  571. */
  572. public function testRetrieveOfNamedNativeQuery(): void
  573. {
  574. $cm = new ClassMetadata(CMS\CmsUser::class);
  575. $cm->initializeReflection(new RuntimeReflectionService());
  576. $cm->addNamedNativeQuery(
  577. [
  578. 'name' => 'find-all',
  579. 'query' => 'SELECT * FROM cms_users',
  580. 'resultSetMapping' => 'result-mapping-name',
  581. 'resultClass' => CMS\CmsUser::class,
  582. ]
  583. );
  584. $cm->addNamedNativeQuery(
  585. [
  586. 'name' => 'find-by-id',
  587. 'query' => 'SELECT * FROM cms_users WHERE id = ?',
  588. 'resultClass' => '__CLASS__',
  589. 'resultSetMapping' => 'result-mapping-name',
  590. ]
  591. );
  592. $mapping = $cm->getNamedNativeQuery('find-all');
  593. self::assertEquals('SELECT * FROM cms_users', $mapping['query']);
  594. self::assertEquals('result-mapping-name', $mapping['resultSetMapping']);
  595. self::assertEquals(CMS\CmsUser::class, $mapping['resultClass']);
  596. $mapping = $cm->getNamedNativeQuery('find-by-id');
  597. self::assertEquals('SELECT * FROM cms_users WHERE id = ?', $mapping['query']);
  598. self::assertEquals('result-mapping-name', $mapping['resultSetMapping']);
  599. self::assertEquals(CMS\CmsUser::class, $mapping['resultClass']);
  600. }
  601. /**
  602. * @group DDC-1663
  603. */
  604. public function testRetrieveOfSqlResultSetMapping(): void
  605. {
  606. $cm = new ClassMetadata(CMS\CmsUser::class);
  607. $cm->initializeReflection(new RuntimeReflectionService());
  608. $cm->addSqlResultSetMapping(
  609. [
  610. 'name' => 'find-all',
  611. 'entities' => [
  612. [
  613. 'entityClass' => '__CLASS__',
  614. 'fields' => [
  615. [
  616. 'name' => 'id',
  617. 'column' => 'id',
  618. ],
  619. [
  620. 'name' => 'name',
  621. 'column' => 'name',
  622. ],
  623. ],
  624. ],
  625. [
  626. 'entityClass' => CMS\CmsEmail::class,
  627. 'fields' => [
  628. [
  629. 'name' => 'id',
  630. 'column' => 'id',
  631. ],
  632. [
  633. 'name' => 'email',
  634. 'column' => 'email',
  635. ],
  636. ],
  637. ],
  638. ],
  639. 'columns' => [
  640. ['name' => 'scalarColumn'],
  641. ],
  642. ]
  643. );
  644. $mapping = $cm->getSqlResultSetMapping('find-all');
  645. self::assertEquals(CMS\CmsUser::class, $mapping['entities'][0]['entityClass']);
  646. self::assertEquals(['name' => 'id', 'column' => 'id'], $mapping['entities'][0]['fields'][0]);
  647. self::assertEquals(['name' => 'name', 'column' => 'name'], $mapping['entities'][0]['fields'][1]);
  648. self::assertEquals(CMS\CmsEmail::class, $mapping['entities'][1]['entityClass']);
  649. self::assertEquals(['name' => 'id', 'column' => 'id'], $mapping['entities'][1]['fields'][0]);
  650. self::assertEquals(['name' => 'email', 'column' => 'email'], $mapping['entities'][1]['fields'][1]);
  651. self::assertEquals('scalarColumn', $mapping['columns'][0]['name']);
  652. }
  653. /**
  654. * @group DDC-1663
  655. */
  656. public function testExistanceOfSqlResultSetMapping(): void
  657. {
  658. $cm = new ClassMetadata(CMS\CmsUser::class);
  659. $cm->initializeReflection(new RuntimeReflectionService());
  660. $cm->addSqlResultSetMapping(
  661. [
  662. 'name' => 'find-all',
  663. 'entities' => [
  664. [
  665. 'entityClass' => CMS\CmsUser::class,
  666. ],
  667. ],
  668. ]
  669. );
  670. self::assertTrue($cm->hasSqlResultSetMapping('find-all'));
  671. self::assertFalse($cm->hasSqlResultSetMapping('find-by-id'));
  672. }
  673. /**
  674. * @group DDC-1663
  675. */
  676. public function testExistanceOfNamedNativeQuery(): void
  677. {
  678. $cm = new ClassMetadata(CMS\CmsUser::class);
  679. $cm->initializeReflection(new RuntimeReflectionService());
  680. $cm->addNamedNativeQuery(
  681. [
  682. 'name' => 'find-all',
  683. 'query' => 'SELECT * FROM cms_users',
  684. 'resultClass' => CMS\CmsUser::class,
  685. 'resultSetMapping' => 'result-mapping-name',
  686. ]
  687. );
  688. self::assertTrue($cm->hasNamedNativeQuery('find-all'));
  689. self::assertFalse($cm->hasNamedNativeQuery('find-by-id'));
  690. }
  691. public function testRetrieveOfNamedQuery(): void
  692. {
  693. $cm = new ClassMetadata(CMS\CmsUser::class);
  694. $cm->initializeReflection(new RuntimeReflectionService());
  695. $cm->addNamedQuery(
  696. [
  697. 'name' => 'userById',
  698. 'query' => 'SELECT u FROM __CLASS__ u WHERE u.id = ?1',
  699. ]
  700. );
  701. self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1', $cm->getNamedQuery('userById'));
  702. }
  703. /**
  704. * @group DDC-1663
  705. */
  706. public function testRetrievalOfNamedNativeQueries(): void
  707. {
  708. $cm = new ClassMetadata(CMS\CmsUser::class);
  709. $cm->initializeReflection(new RuntimeReflectionService());
  710. self::assertCount(0, $cm->getNamedNativeQueries());
  711. $cm->addNamedNativeQuery(
  712. [
  713. 'name' => 'find-all',
  714. 'query' => 'SELECT * FROM cms_users',
  715. 'resultClass' => CMS\CmsUser::class,
  716. 'resultSetMapping' => 'result-mapping-name',
  717. ]
  718. );
  719. self::assertCount(1, $cm->getNamedNativeQueries());
  720. }
  721. /**
  722. * @group DDC-2451
  723. */
  724. public function testSerializeEntityListeners(): void
  725. {
  726. $metadata = new ClassMetadata(CompanyContract::class);
  727. $metadata->initializeReflection(new RuntimeReflectionService());
  728. $metadata->addEntityListener(Events::prePersist, 'CompanyContractListener', 'prePersistHandler');
  729. $metadata->addEntityListener(Events::postPersist, 'CompanyContractListener', 'postPersistHandler');
  730. $serialize = serialize($metadata);
  731. $unserialize = unserialize($serialize);
  732. self::assertEquals($metadata->entityListeners, $unserialize->entityListeners);
  733. }
  734. public function testNamingCollisionNamedQueryShouldThrowException(): void
  735. {
  736. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  737. $this->expectExceptionMessage('Query named "userById" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once');
  738. $cm = new ClassMetadata(CMS\CmsUser::class);
  739. $cm->initializeReflection(new RuntimeReflectionService());
  740. $cm->addNamedQuery(
  741. [
  742. 'name' => 'userById',
  743. 'query' => 'SELECT u FROM __CLASS__ u WHERE u.id = ?1',
  744. ]
  745. );
  746. $cm->addNamedQuery(
  747. [
  748. 'name' => 'userById',
  749. 'query' => 'SELECT u FROM __CLASS__ u WHERE u.id = ?1',
  750. ]
  751. );
  752. }
  753. /**
  754. * @group DDC-1663
  755. */
  756. public function testNamingCollisionNamedNativeQueryShouldThrowException(): void
  757. {
  758. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  759. $this->expectExceptionMessage('Query named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once');
  760. $cm = new ClassMetadata(CMS\CmsUser::class);
  761. $cm->initializeReflection(new RuntimeReflectionService());
  762. $cm->addNamedNativeQuery(
  763. [
  764. 'name' => 'find-all',
  765. 'query' => 'SELECT * FROM cms_users',
  766. 'resultClass' => CMS\CmsUser::class,
  767. 'resultSetMapping' => 'result-mapping-name',
  768. ]
  769. );
  770. $cm->addNamedNativeQuery(
  771. [
  772. 'name' => 'find-all',
  773. 'query' => 'SELECT * FROM cms_users',
  774. 'resultClass' => CMS\CmsUser::class,
  775. 'resultSetMapping' => 'result-mapping-name',
  776. ]
  777. );
  778. }
  779. /**
  780. * @group DDC-1663
  781. */
  782. public function testNamingCollisionSqlResultSetMappingShouldThrowException(): void
  783. {
  784. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  785. $this->expectExceptionMessage('Result set mapping named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once');
  786. $cm = new ClassMetadata(CMS\CmsUser::class);
  787. $cm->initializeReflection(new RuntimeReflectionService());
  788. $cm->addSqlResultSetMapping(
  789. [
  790. 'name' => 'find-all',
  791. 'entities' => [
  792. [
  793. 'entityClass' => CMS\CmsUser::class,
  794. ],
  795. ],
  796. ]
  797. );
  798. $cm->addSqlResultSetMapping(
  799. [
  800. 'name' => 'find-all',
  801. 'entities' => [
  802. [
  803. 'entityClass' => CMS\CmsUser::class,
  804. ],
  805. ],
  806. ]
  807. );
  808. }
  809. /**
  810. * @group DDC-1068
  811. */
  812. public function testClassCaseSensitivity(): void
  813. {
  814. $user = new CMS\CmsUser();
  815. $cm = new ClassMetadata(strtoupper(CMS\CmsUser::class));
  816. $cm->initializeReflection(new RuntimeReflectionService());
  817. self::assertEquals(CMS\CmsUser::class, $cm->name);
  818. }
  819. /**
  820. * @group DDC-659
  821. */
  822. public function testLifecycleCallbackNotFound(): void
  823. {
  824. $cm = new ClassMetadata(CMS\CmsUser::class);
  825. $cm->initializeReflection(new RuntimeReflectionService());
  826. $cm->addLifecycleCallback('notfound', 'postLoad');
  827. $this->expectException(MappingException::class);
  828. $this->expectExceptionMessage("Entity '" . CMS\CmsUser::class . "' has no method 'notfound' to be registered as lifecycle callback.");
  829. $cm->validateLifecycleCallbacks(new RuntimeReflectionService());
  830. }
  831. /**
  832. * @group ImproveErrorMessages
  833. */
  834. public function testTargetEntityNotFound(): void
  835. {
  836. $cm = new ClassMetadata(CMS\CmsUser::class);
  837. $cm->initializeReflection(new RuntimeReflectionService());
  838. $cm->mapManyToOne(['fieldName' => 'address', 'targetEntity' => 'UnknownClass']);
  839. $this->expectException(MappingException::class);
  840. $this->expectExceptionMessage("The target-entity Doctrine\\Tests\\Models\\CMS\\UnknownClass cannot be found in '" . CMS\CmsUser::class . "#address'.");
  841. $cm->validateAssociations();
  842. }
  843. /**
  844. * @group DDC-1663
  845. */
  846. public function testNameIsMandatoryForNamedQueryMappingException(): void
  847. {
  848. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  849. $this->expectExceptionMessage('Query name on entity class \'Doctrine\Tests\Models\CMS\CmsUser\' is not defined.');
  850. $cm = new ClassMetadata(CMS\CmsUser::class);
  851. $cm->initializeReflection(new RuntimeReflectionService());
  852. $cm->addNamedQuery(
  853. ['query' => 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u']
  854. );
  855. }
  856. /**
  857. * @group DDC-1663
  858. */
  859. public function testNameIsMandatoryForNameNativeQueryMappingException(): void
  860. {
  861. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  862. $this->expectExceptionMessage('Query name on entity class \'Doctrine\Tests\Models\CMS\CmsUser\' is not defined.');
  863. $cm = new ClassMetadata(CMS\CmsUser::class);
  864. $cm->initializeReflection(new RuntimeReflectionService());
  865. $cm->addNamedQuery(
  866. [
  867. 'query' => 'SELECT * FROM cms_users',
  868. 'resultClass' => CMS\CmsUser::class,
  869. 'resultSetMapping' => 'result-mapping-name',
  870. ]
  871. );
  872. }
  873. /**
  874. * @group DDC-1663
  875. */
  876. public function testNameIsMandatoryForEntityNameSqlResultSetMappingException(): void
  877. {
  878. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  879. $this->expectExceptionMessage('Result set mapping named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser requires a entity class name.');
  880. $cm = new ClassMetadata(CMS\CmsUser::class);
  881. $cm->initializeReflection(new RuntimeReflectionService());
  882. $cm->addSqlResultSetMapping(
  883. [
  884. 'name' => 'find-all',
  885. 'entities' => [
  886. [
  887. 'fields' => [],
  888. ],
  889. ],
  890. ]
  891. );
  892. }
  893. public function testNameIsMandatoryForDiscriminatorColumnsMappingException(): void
  894. {
  895. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  896. $this->expectExceptionMessage('Discriminator column name on entity class \'Doctrine\Tests\Models\CMS\CmsUser\' is not defined.');
  897. $cm = new ClassMetadata(CMS\CmsUser::class);
  898. $cm->initializeReflection(new RuntimeReflectionService());
  899. $cm->setDiscriminatorColumn([]);
  900. }
  901. /**
  902. * @group DDC-984
  903. * @group DDC-559
  904. * @group DDC-1575
  905. */
  906. public function testFullyQualifiedClassNameShouldBeGivenToNamingStrategy(): void
  907. {
  908. $namingStrategy = new MyNamespacedNamingStrategy();
  909. $addressMetadata = new ClassMetadata(CMS\CmsAddress::class, $namingStrategy);
  910. $articleMetadata = new ClassMetadata(DoctrineGlobalArticle::class, $namingStrategy);
  911. $routingMetadata = new ClassMetadata(RoutingLeg::class, $namingStrategy);
  912. $addressMetadata->initializeReflection(new RuntimeReflectionService());
  913. $articleMetadata->initializeReflection(new RuntimeReflectionService());
  914. $routingMetadata->initializeReflection(new RuntimeReflectionService());
  915. $addressMetadata->mapManyToMany(
  916. [
  917. 'fieldName' => 'user',
  918. 'targetEntity' => 'CmsUser',
  919. ]
  920. );
  921. $articleMetadata->mapManyToMany(
  922. [
  923. 'fieldName' => 'author',
  924. 'targetEntity' => CMS\CmsUser::class,
  925. ]
  926. );
  927. self::assertEquals('routing_routingleg', $routingMetadata->table['name']);
  928. self::assertEquals('cms_cmsaddress_cms_cmsuser', $addressMetadata->associationMappings['user']['joinTable']['name']);
  929. self::assertEquals('doctrineglobalarticle_cms_cmsuser', $articleMetadata->associationMappings['author']['joinTable']['name']);
  930. }
  931. /**
  932. * @group DDC-984
  933. * @group DDC-559
  934. */
  935. public function testFullyQualifiedClassNameShouldBeGivenToNamingStrategyPropertyToColumnName(): void
  936. {
  937. $namingStrategy = new MyPrefixNamingStrategy();
  938. $metadata = new ClassMetadata(CMS\CmsAddress::class, $namingStrategy);
  939. $metadata->initializeReflection(new RuntimeReflectionService());
  940. $metadata->mapField(['fieldName' => 'country']);
  941. $metadata->mapField(['fieldName' => 'city']);
  942. self::assertEquals($metadata->fieldNames, [
  943. 'cmsaddress_country' => 'country',
  944. 'cmsaddress_city' => 'city',
  945. ]);
  946. }
  947. /**
  948. * @group DDC-1746
  949. */
  950. public function testInvalidCascade(): void
  951. {
  952. $cm = new ClassMetadata(CMS\CmsUser::class);
  953. $cm->initializeReflection(new RuntimeReflectionService());
  954. $this->expectException(MappingException::class);
  955. $this->expectExceptionMessage('You have specified invalid cascade options for ' . CMS\CmsUser::class . "::\$address: 'invalid'; available options: 'remove', 'persist', 'refresh', 'merge', and 'detach'");
  956. $cm->mapManyToOne(['fieldName' => 'address', 'targetEntity' => 'UnknownClass', 'cascade' => ['invalid']]);
  957. }
  958. /**
  959. * @group DDC-964
  960. */
  961. public function testInvalidPropertyAssociationOverrideNameException(): void
  962. {
  963. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  964. $this->expectExceptionMessage('Invalid field override named \'invalidPropertyName\' for class \'Doctrine\Tests\Models\DDC964\DDC964Admin');
  965. $cm = new ClassMetadata(DDC964Admin::class);
  966. $cm->initializeReflection(new RuntimeReflectionService());
  967. $cm->mapManyToOne(['fieldName' => 'address', 'targetEntity' => 'DDC964Address']);
  968. $cm->setAssociationOverride('invalidPropertyName', []);
  969. }
  970. /**
  971. * @group DDC-964
  972. */
  973. public function testInvalidPropertyAttributeOverrideNameException(): void
  974. {
  975. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  976. $this->expectExceptionMessage('Invalid field override named \'invalidPropertyName\' for class \'Doctrine\Tests\Models\DDC964\DDC964Guest\'.');
  977. $cm = new ClassMetadata(DDC964Guest::class);
  978. $cm->initializeReflection(new RuntimeReflectionService());
  979. $cm->mapField(['fieldName' => 'name']);
  980. $cm->setAttributeOverride('invalidPropertyName', []);
  981. }
  982. /**
  983. * @group DDC-964
  984. */
  985. public function testInvalidOverrideAttributeFieldTypeException(): void
  986. {
  987. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  988. $this->expectExceptionMessage('The column type of attribute \'name\' on class \'Doctrine\Tests\Models\DDC964\DDC964Guest\' could not be changed.');
  989. $cm = new ClassMetadata(DDC964Guest::class);
  990. $cm->initializeReflection(new RuntimeReflectionService());
  991. $cm->mapField(['fieldName' => 'name', 'type' => 'string']);
  992. $cm->setAttributeOverride('name', ['type' => 'date']);
  993. }
  994. /**
  995. * @group DDC-1955
  996. */
  997. public function testInvalidEntityListenerClassException(): void
  998. {
  999. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  1000. $this->expectExceptionMessage('Entity Listener "\InvalidClassName" declared on "Doctrine\Tests\Models\CMS\CmsUser" not found.');
  1001. $cm = new ClassMetadata(CMS\CmsUser::class);
  1002. $cm->initializeReflection(new RuntimeReflectionService());
  1003. $cm->addEntityListener(Events::postLoad, '\InvalidClassName', 'postLoadHandler');
  1004. }
  1005. /**
  1006. * @group DDC-1955
  1007. */
  1008. public function testInvalidEntityListenerMethodException(): void
  1009. {
  1010. $this->expectException('Doctrine\ORM\Mapping\MappingException');
  1011. $this->expectExceptionMessage('Entity Listener "\Doctrine\Tests\Models\Company\CompanyContractListener" declared on "Doctrine\Tests\Models\CMS\CmsUser" has no method "invalidMethod".');
  1012. $cm = new ClassMetadata(CMS\CmsUser::class);
  1013. $cm->initializeReflection(new RuntimeReflectionService());
  1014. $cm->addEntityListener(Events::postLoad, '\Doctrine\Tests\Models\Company\CompanyContractListener', 'invalidMethod');
  1015. }
  1016. public function testManyToManySelfReferencingNamingStrategyDefaults(): void
  1017. {
  1018. $cm = new ClassMetadata(CustomTypeParent::class);
  1019. $cm->initializeReflection(new RuntimeReflectionService());
  1020. $cm->mapManyToMany(
  1021. [
  1022. 'fieldName' => 'friendsWithMe',
  1023. 'targetEntity' => 'CustomTypeParent',
  1024. ]
  1025. );
  1026. self::assertEquals(
  1027. [
  1028. 'name' => 'customtypeparent_customtypeparent',
  1029. 'joinColumns' => [['name' => 'customtypeparent_source', 'referencedColumnName' => 'id', 'onDelete' => 'CASCADE']],
  1030. 'inverseJoinColumns' => [['name' => 'customtypeparent_target', 'referencedColumnName' => 'id', 'onDelete' => 'CASCADE']],
  1031. ],
  1032. $cm->associationMappings['friendsWithMe']['joinTable']
  1033. );
  1034. self::assertEquals(['customtypeparent_source', 'customtypeparent_target'], $cm->associationMappings['friendsWithMe']['joinTableColumns']);
  1035. self::assertEquals(['customtypeparent_source' => 'id'], $cm->associationMappings['friendsWithMe']['relationToSourceKeyColumns']);
  1036. self::assertEquals(['customtypeparent_target' => 'id'], $cm->associationMappings['friendsWithMe']['relationToTargetKeyColumns']);
  1037. }
  1038. /**
  1039. * @group DDC-2608
  1040. */
  1041. public function testSetSequenceGeneratorThrowsExceptionWhenSequenceNameIsMissing(): void
  1042. {
  1043. $cm = new ClassMetadata(CMS\CmsUser::class);
  1044. $cm->initializeReflection(new RuntimeReflectionService());
  1045. $this->expectException(MappingException::class);
  1046. $cm->setSequenceGeneratorDefinition([]);
  1047. }
  1048. /**
  1049. * @group DDC-2662
  1050. * @group 6682
  1051. */
  1052. public function testQuotedSequenceName(): void
  1053. {
  1054. $cm = new ClassMetadata(CMS\CmsUser::class);
  1055. $cm->initializeReflection(new RuntimeReflectionService());
  1056. $cm->setSequenceGeneratorDefinition(['sequenceName' => '`foo`']);
  1057. self::assertSame(
  1058. ['sequenceName' => 'foo', 'quoted' => true, 'allocationSize' => '1', 'initialValue' => '1'],
  1059. $cm->sequenceGeneratorDefinition
  1060. );
  1061. }
  1062. /**
  1063. * @group DDC-2700
  1064. */
  1065. public function testIsIdentifierMappedSuperClass(): void
  1066. {
  1067. $class = new ClassMetadata(DDC2700MappedSuperClass::class);
  1068. self::assertFalse($class->isIdentifier('foo'));
  1069. }
  1070. /**
  1071. * @group DDC-3120
  1072. */
  1073. public function testCanInstantiateInternalPhpClassSubclass(): void
  1074. {
  1075. $classMetadata = new ClassMetadata(MyArrayObjectEntity::class);
  1076. self::assertInstanceOf(MyArrayObjectEntity::class, $classMetadata->newInstance());
  1077. }
  1078. /**
  1079. * @group DDC-3120
  1080. */
  1081. public function testCanInstantiateInternalPhpClassSubclassFromUnserializedMetadata(): void
  1082. {
  1083. $classMetadata = unserialize(serialize(new ClassMetadata(MyArrayObjectEntity::class)));
  1084. assert($classMetadata instanceof ClassMetadata);
  1085. $classMetadata->wakeupReflection(new RuntimeReflectionService());
  1086. self::assertInstanceOf(MyArrayObjectEntity::class, $classMetadata->newInstance());
  1087. }
  1088. public function testWakeupReflectionWithEmbeddableAndStaticReflectionService(): void
  1089. {
  1090. $classMetadata = new ClassMetadata(TestEntity1::class);
  1091. $classMetadata->mapEmbedded(
  1092. [
  1093. 'fieldName' => 'test',
  1094. 'class' => TestEntity1::class,
  1095. 'columnPrefix' => false,
  1096. ]
  1097. );
  1098. $field = [
  1099. 'fieldName' => 'test.embeddedProperty',
  1100. 'type' => 'string',
  1101. 'originalClass' => TestEntity1::class,
  1102. 'declaredField' => 'test',
  1103. 'originalField' => 'embeddedProperty',
  1104. ];
  1105. $classMetadata->mapField($field);
  1106. $classMetadata->wakeupReflection(new StaticReflectionService());
  1107. self::assertEquals(['test' => null, 'test.embeddedProperty' => null], $classMetadata->getReflectionProperties());
  1108. }
  1109. public function testGetColumnNamesWithGivenFieldNames(): void
  1110. {
  1111. $metadata = new ClassMetadata(CMS\CmsUser::class);
  1112. $metadata->initializeReflection(new RuntimeReflectionService());
  1113. $metadata->mapField(['fieldName' => 'status', 'type' => 'string', 'columnName' => 'foo']);
  1114. $metadata->mapField(['fieldName' => 'username', 'type' => 'string', 'columnNam…

Large files files are truncated, but you can click here to view the full file