/tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH453Test.php

https://github.com/tecbot/mongodb-odm · PHP · 347 lines · 240 code · 75 blank · 32 comment · 5 complexity · 2dc87691bc80b6234eb11acf83e9a540 MD5 · raw file

  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\ODM\MongoDB\Tests\Functional\Ticket;
  4. use Doctrine\Common\Collections\ArrayCollection;
  5. use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
  6. use Doctrine\ODM\MongoDB\Tests\BaseTest;
  7. use function array_values;
  8. use function get_class;
  9. use function sprintf;
  10. class GH453Test extends BaseTest
  11. {
  12. public function testHashWithStringKeys()
  13. {
  14. $hash = ['a' => 'x', 'b' => 'y', 'c' => 'z'];
  15. $doc = new GH453Document();
  16. $doc->hash = $hash;
  17. $this->dm->persist($doc);
  18. $this->dm->flush();
  19. $this->dm->clear();
  20. $this->assertBsonObjectAndValue($hash, $doc->id, 'hash');
  21. // Check that the value is hydrated properly
  22. $doc = $this->dm->find(get_class($doc), $doc->id);
  23. $this->assertSame($hash, $doc->hash);
  24. $this->dm->clear();
  25. // Check that the value is changed properly
  26. unset($hash['b']);
  27. $doc = $this->dm->merge($doc);
  28. $doc->hash = $hash;
  29. $this->dm->flush();
  30. $this->dm->clear();
  31. $this->assertBsonObjectAndValue($hash, $doc->id, 'hash');
  32. }
  33. public function testHashWithNumericKeys()
  34. {
  35. $hash = [0 => 'x', 1 => 'y', 2 => 'z'];
  36. $doc = new GH453Document();
  37. $doc->hash = $hash;
  38. $this->dm->persist($doc);
  39. $this->dm->flush();
  40. $this->dm->clear();
  41. $this->assertBsonObjectAndValue($hash, $doc->id, 'hash');
  42. // Check that the value is hydrated properly
  43. $doc = $this->dm->find(get_class($doc), $doc->id);
  44. $this->assertSame($hash, $doc->hash);
  45. $this->dm->clear();
  46. // Check that the value is changed properly
  47. unset($hash[1]);
  48. $doc = $this->dm->merge($doc);
  49. $doc->hash = $hash;
  50. $this->dm->flush();
  51. $this->dm->clear();
  52. $this->assertBsonObjectAndValue($hash, $doc->id, 'hash');
  53. }
  54. public function testCollection()
  55. {
  56. $col = ['x', 'y', 'z'];
  57. $doc = new GH453Document();
  58. $doc->colPush = $col;
  59. $doc->colSet = $col;
  60. $this->dm->persist($doc);
  61. $this->dm->flush();
  62. $this->dm->clear();
  63. $this->assertBsonArrayAndValue($col, $doc->id, 'colPush');
  64. $this->assertBsonArrayAndValue($col, $doc->id, 'colSet');
  65. // Check that the value is hydrated properly
  66. $doc = $this->dm->find(get_class($doc), $doc->id);
  67. $this->assertSame($col, $doc->colPush);
  68. $this->assertSame($col, $doc->colSet);
  69. $this->dm->clear();
  70. // Check that the value is changed properly
  71. unset($col[1]);
  72. $doc = $this->dm->merge($doc);
  73. $doc->colPush = $col;
  74. $doc->colSet = $col;
  75. $this->dm->flush();
  76. $this->dm->clear();
  77. $this->assertBsonArrayAndValue($col, $doc->id, 'colPush');
  78. $this->assertBsonArrayAndValue($col, $doc->id, 'colSet');
  79. }
  80. public function testEmbedMany()
  81. {
  82. $colPush = new ArrayCollection([
  83. new GH453EmbeddedDocument(),
  84. new GH453EmbeddedDocument(),
  85. new GH453EmbeddedDocument(),
  86. ]);
  87. $colSet = $colPush->map(static function ($v) {
  88. return clone $v;
  89. });
  90. $colSetArray = $colPush->map(static function ($v) {
  91. return clone $v;
  92. });
  93. $colAddToSet = $colPush->map(static function ($v) {
  94. return clone $v;
  95. });
  96. $doc = new GH453Document();
  97. $doc->embedManyPush = $colPush;
  98. $doc->embedManySet = $colSet;
  99. $doc->embedManySetArray = $colSetArray;
  100. $doc->embedManyAddToSet = $colAddToSet;
  101. $this->dm->persist($doc);
  102. $this->dm->flush();
  103. $this->dm->clear();
  104. // No need to assert the value of the embedded document structure
  105. $this->assertBsonArray($doc->id, 'embedManyPush');
  106. $this->assertBsonArray($doc->id, 'embedManySet');
  107. $this->assertBsonArray($doc->id, 'embedManySetArray');
  108. $this->assertBsonArray($doc->id, 'embedManyAddToSet');
  109. // Check that the value is changed properly
  110. unset($colPush[1], $colSet[1], $colSetArray[1], $colAddToSet['1']);
  111. $doc = $this->dm->merge($doc);
  112. $doc->embedManyPush = $colPush;
  113. $doc->embedManySet = $colSet;
  114. $doc->embedManySetArray = $colSetArray;
  115. $doc->embedManyAddToSet = $colAddToSet;
  116. $this->dm->flush();
  117. $this->dm->clear();
  118. $this->assertBsonArray($doc->id, 'embedManyPush');
  119. $this->assertBsonObject($doc->id, 'embedManySet');
  120. $this->assertBsonArray($doc->id, 'embedManySetArray');
  121. $this->assertBsonArray($doc->id, 'embedManyAddToSet');
  122. }
  123. public function testReferenceMany()
  124. {
  125. $colPush = new ArrayCollection([
  126. new GH453ReferencedDocument(),
  127. new GH453ReferencedDocument(),
  128. new GH453ReferencedDocument(),
  129. ]);
  130. $colSet = $colPush->map(static function ($v) {
  131. return clone $v;
  132. });
  133. $colSetArray = $colPush->map(static function ($v) {
  134. return clone $v;
  135. });
  136. $colAddToSet = $colPush->map(static function ($v) {
  137. return clone $v;
  138. });
  139. $dm = $this->dm;
  140. $colPush->forAll(static function ($k, $v) use ($dm) {
  141. $dm->persist($v);
  142. return true;
  143. });
  144. $colSet->forAll(static function ($k, $v) use ($dm) {
  145. $dm->persist($v);
  146. return true;
  147. });
  148. $colSetArray->forAll(static function ($k, $v) use ($dm) {
  149. $dm->persist($v);
  150. return true;
  151. });
  152. $colAddToSet->forAll(static function ($k, $v) use ($dm) {
  153. $dm->persist($v);
  154. return true;
  155. });
  156. $doc = new GH453Document();
  157. $doc->referenceManyPush = $colPush;
  158. $doc->referenceManySet = $colSet;
  159. $doc->referenceManySetArray = $colSetArray;
  160. $doc->referenceManyAddToSet = $colAddToSet;
  161. $this->dm->persist($doc);
  162. $this->dm->flush();
  163. $this->dm->clear();
  164. // No need to assert the value of the referenced document structure
  165. $this->assertBsonArray($doc->id, 'referenceManyPush');
  166. $this->assertBsonArray($doc->id, 'referenceManySet');
  167. $this->assertBsonArray($doc->id, 'referenceManySetArray');
  168. $this->assertBsonArray($doc->id, 'referenceManyAddToSet');
  169. // Check that the value is changed properly
  170. unset($colPush[1], $colSet[1], $colSetArray[1], $colAddToSet[1]);
  171. $doc->referenceManyPush = $colPush;
  172. $doc->referenceManySet = $colSet;
  173. $doc->referenceManySetArray = $colSetArray;
  174. $doc->referenceManyAddToSet = $colAddToSet;
  175. /* Merging must be done after re-assigning the collections, as the
  176. * referenced documents must be re-persisted through the merge cascade.
  177. */
  178. $doc = $this->dm->merge($doc);
  179. $this->dm->flush();
  180. $this->dm->clear();
  181. $this->assertBsonArray($doc->id, 'referenceManyPush');
  182. $this->assertBsonObject($doc->id, 'referenceManySet');
  183. $this->assertBsonArray($doc->id, 'referenceManySetArray');
  184. $this->assertBsonArray($doc->id, 'referenceManyAddToSet');
  185. }
  186. private function assertBsonArray($documentId, $fieldName)
  187. {
  188. $this->assertBsonType(4, $documentId, $fieldName);
  189. }
  190. private function assertBsonObject($documentId, $fieldName)
  191. {
  192. $this->assertBsonType(3, $documentId, $fieldName);
  193. }
  194. private function assertBsonType($bsonType, $documentId, $fieldName)
  195. {
  196. $criteria = ['_id' => $documentId];
  197. if ($bsonType === 4) {
  198. // See: https://jira.mongodb.org/browse/SERVER-1475
  199. $criteria['$where'] = sprintf('Array.isArray(this.%s)', $fieldName);
  200. } else {
  201. $criteria[$fieldName] = ['$type' => $bsonType];
  202. }
  203. $this->assertNotNull($this->dm->getRepository(GH453Document::class)->findOneBy($criteria));
  204. }
  205. private function assertBsonArrayAndValue($expectedValue, $documentId, $fieldName)
  206. {
  207. $this->assertBsonTypeAndValue(4, $expectedValue, $documentId, $fieldName);
  208. }
  209. private function assertBsonObjectAndValue($expectedValue, $documentId, $fieldName)
  210. {
  211. $this->assertBsonTypeAndValue(3, $expectedValue, $documentId, $fieldName);
  212. }
  213. private function assertBsonTypeAndValue($bsonType, $expectedValue, $documentId, $fieldName)
  214. {
  215. if ($bsonType === 4) {
  216. $expectedValue = array_values((array) $expectedValue);
  217. } elseif ($bsonType === 3) {
  218. $expectedValue = (object) $expectedValue;
  219. }
  220. $criteria = [
  221. '_id' => $documentId,
  222. '$and' => [[$fieldName => $expectedValue]],
  223. ];
  224. if ($bsonType === 4) {
  225. // See: https://jira.mongodb.org/browse/SERVER-1475
  226. $criteria['$and'][] = ['$where' => sprintf('Array.isArray(this.%s)', $fieldName)];
  227. } else {
  228. $criteria['$and'][] = [$fieldName => ['$type' => $bsonType]];
  229. }
  230. $this->assertNotNull($this->dm->getRepository(GH453Document::class)->findOneBy($criteria));
  231. }
  232. }
  233. /** @ODM\Document */
  234. class GH453Document
  235. {
  236. /** @ODM\Id */
  237. public $id;
  238. /** @ODM\Field(type="hash") */
  239. public $hash;
  240. /** @ODM\Field(type="collection") */
  241. public $colPush;
  242. /** @ODM\Field(type="collection") */
  243. public $colSet;
  244. /** @ODM\EmbedMany(strategy="pushAll")) */
  245. public $embedManyPush;
  246. /** @ODM\EmbedMany(strategy="set") */
  247. public $embedManySet;
  248. /** @ODM\EmbedMany(strategy="setArray") */
  249. public $embedManySetArray;
  250. /** @ODM\EmbedMany(strategy="addToSet") */
  251. public $embedManyAddToSet;
  252. /** @ODM\ReferenceMany(strategy="pushAll")) */
  253. public $referenceManyPush;
  254. /** @ODM\ReferenceMany(strategy="set") */
  255. public $referenceManySet;
  256. /** @ODM\ReferenceMany(strategy="setArray") */
  257. public $referenceManySetArray;
  258. /** @ODM\ReferenceMany(strategy="addToSet") */
  259. public $referenceManyAddToSet;
  260. }
  261. /** @ODM\EmbeddedDocument */
  262. class GH453EmbeddedDocument
  263. {
  264. /** @ODM\Id */
  265. public $id;
  266. }
  267. /** @ODM\Document */
  268. class GH453ReferencedDocument
  269. {
  270. /** @ODM\Id */
  271. public $id;
  272. }