PageRenderTime 73ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/library/Respect/Relational/MapperTest.php

https://github.com/Respect/Relational
PHP | 1015 lines | 943 code | 69 blank | 3 comment | 0 complexity | c3e6c914d10e5aca2c8fa109ac7385fb MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. namespace Respect\Relational;
  3. use PDO;
  4. use Respect\Data\Collections\Filtered;
  5. use Respect\Data\Collections\Mixed;
  6. use Respect\Data\Collections\Typed;
  7. use Respect\Data\Styles;
  8. class MapperTest extends \PHPUnit_Framework_TestCase {
  9. protected $mapper, $posts, $authors, $comments, $categories, $postsCategories;
  10. public function setUp() {
  11. $conn = new PDO('sqlite::memory:');
  12. $db = new Db($conn);
  13. $conn->exec((string) Sql::createTable('post', array(
  14. 'id INTEGER PRIMARY KEY',
  15. 'title VARCHAR(255)',
  16. 'text TEXT',
  17. 'author_id INTEGER'
  18. )));
  19. $conn->exec((string) Sql::createTable('author', array(
  20. 'id INTEGER PRIMARY KEY',
  21. 'name VARCHAR(255)'
  22. )));
  23. $conn->exec((string) Sql::createTable('comment', array(
  24. 'id INTEGER PRIMARY KEY',
  25. 'post_id INTEGER',
  26. 'text TEXT',
  27. 'datetime DATETIME'
  28. )));
  29. $conn->exec((string) Sql::createTable('category', array(
  30. 'id INTEGER PRIMARY KEY',
  31. 'name VARCHAR(255)',
  32. 'category_id INTEGER'
  33. )));
  34. $conn->exec((string) Sql::createTable('post_category', array(
  35. 'id INTEGER PRIMARY KEY',
  36. 'post_id INTEGER',
  37. 'category_id INTEGER'
  38. )));
  39. $conn->exec((string) Sql::createTable('issues', array(
  40. 'id INTEGER PRIMARY KEY',
  41. 'type VARCHAR(255)',
  42. 'title VARCHAR(22)'
  43. )));
  44. $this->posts = array(
  45. (object) array(
  46. 'id' => 5,
  47. 'title' => 'Post Title',
  48. 'text' => 'Post Text',
  49. 'author_id' => 1
  50. )
  51. );
  52. $this->authors = array(
  53. (object) array(
  54. 'id' => 1,
  55. 'name' => 'Author 1'
  56. )
  57. );
  58. $this->comments = array(
  59. (object) array(
  60. 'id' => 7,
  61. 'post_id' => 5,
  62. 'text' => 'Comment Text',
  63. 'datetime' => '2012-06-19 00:35:42'
  64. ),
  65. (object) array(
  66. 'id' => 8,
  67. 'post_id' => 4,
  68. 'text' => 'Comment Text 2',
  69. 'datetime' => '2012-06-19 00:35:42'
  70. )
  71. );
  72. $this->categories = array(
  73. (object) array(
  74. 'id' => 2,
  75. 'name' => 'Sample Category',
  76. 'category_id' => null
  77. ),
  78. (object) array(
  79. 'id' => 3,
  80. 'name' => 'NONON',
  81. 'category_id' => null
  82. )
  83. );
  84. $this->postsCategories = array(
  85. (object) array(
  86. 'id' => 66,
  87. 'post_id' => 5,
  88. 'category_id' => 2
  89. )
  90. );
  91. $this->issues = array(
  92. (object) array(
  93. 'id' => 1,
  94. 'type' => 'bug',
  95. 'title' => 'Bug 1'
  96. ),
  97. (object) array(
  98. 'id' => 2,
  99. 'type' => 'improvement',
  100. 'title' => 'Improvement 1'
  101. )
  102. );
  103. foreach ($this->authors as $author)
  104. $db->insertInto('author', (array) $author)->values((array) $author)->exec();
  105. foreach ($this->posts as $post)
  106. $db->insertInto('post', (array) $post)->values((array) $post)->exec();
  107. foreach ($this->comments as $comment)
  108. $db->insertInto('comment', (array) $comment)->values((array) $comment)->exec();
  109. foreach ($this->categories as $category)
  110. $db->insertInto('category', (array) $category)->values((array) $category)->exec();
  111. foreach ($this->postsCategories as $postCategory)
  112. $db->insertInto('post_category', (array) $postCategory)->values((array) $postCategory)->exec();
  113. foreach ($this->issues as $issue)
  114. $db->insertInto('issues', (array) $issue)->values((array) $issue)->exec();
  115. $mapper = new Mapper($conn);
  116. $this->mapper = $mapper;
  117. $this->conn = $conn;
  118. }
  119. public function test_creating_with_db_instance()
  120. {
  121. $db = new Db($this->conn);
  122. $mapper = new Mapper($db);
  123. $this->assertAttributeSame($db, 'db', $mapper);
  124. }
  125. public function test_get_defined_db_instance()
  126. {
  127. $db = new Db($this->conn);
  128. $mapper = new Mapper($db);
  129. $this->assertSame($db, $mapper->getDb());
  130. }
  131. public function test_creating_with_invalid_args_should_throw_exception()
  132. {
  133. $this->setExpectedException('InvalidArgumentException');
  134. $mapper = new Mapper('foo');
  135. }
  136. public function test_rolling_back_transaction()
  137. {
  138. $conn = $this->getMock(
  139. 'PDO',
  140. array('beginTransaction', 'rollback', 'prepare', 'execute'),
  141. array('sqlite::memory:')
  142. );
  143. $conn->expects($this->any())
  144. ->method('prepare')
  145. ->will($this->throwException(new \Exception));
  146. $conn->expects($this->once())
  147. ->method('rollback');
  148. $mapper = new Mapper($conn);
  149. $obj = new \stdClass();
  150. $obj->id = null;
  151. $mapper->foo->persist($obj);
  152. try {
  153. $mapper->flush();
  154. } catch (\Exception $e) {
  155. //OK!
  156. }
  157. }
  158. public function test_ignoring_last_insert_id_errors()
  159. {
  160. $conn = $this->getMock(
  161. 'PDO',
  162. array('lastInsertId'),
  163. array('sqlite::memory:')
  164. );
  165. $conn->exec('CREATE TABLE foo(id INTEGER PRIMARY KEY)');
  166. $conn->expects($this->any())
  167. ->method('lastInsertId')
  168. ->will($this->throwException(new \PDOException));
  169. $mapper = new Mapper($conn);
  170. $obj = new \stdClass();
  171. $obj->id = null;
  172. $mapper->foo->persist($obj);
  173. $mapper->flush();
  174. //Ok, should not throw PDOException on this.
  175. }
  176. public function test_removing_untracked_object()
  177. {
  178. $comment = new \stdClass();
  179. $comment->id = 7;
  180. $this->assertNotEmpty($this->mapper->comment[7]->fetch());
  181. $this->mapper->comment->remove($comment);
  182. $this->mapper->flush();
  183. $this->assertEmpty($this->mapper->comment[7]->fetch());
  184. }
  185. public function test_fetching_single_entity_from_collection_should_return_first_record_from_table()
  186. {
  187. $expectedFirstComment = reset($this->comments);
  188. $fetchedFirstComment = $this->mapper->comment->fetch();
  189. $this->assertEquals($expectedFirstComment, $fetchedFirstComment);
  190. }
  191. public function test_fetching_all_entites_from_collection_should_return_all_records()
  192. {
  193. $expectedCategories = $this->categories;
  194. $fetchedCategories = $this->mapper->category->fetchAll();
  195. $this->assertEquals($expectedCategories, $fetchedCategories);
  196. }
  197. public function test_extra_sql_on_single_fetch_should_be_applied_on_mapper_sql()
  198. {
  199. $expectedLast = end($this->comments);
  200. $fetchedLast = $this->mapper->comment->fetch(Sql::orderBy('id DESC'));
  201. $this->assertEquals($expectedLast, $fetchedLast);
  202. }
  203. public function test_extra_sql_on_fetchAll_should_be_applied_on_mapper_sql()
  204. {
  205. $expectedComments = array_reverse($this->comments);
  206. $fetchedComments = $this->mapper->comment->fetchAll(Sql::orderBy('id DESC'));
  207. $this->assertEquals($expectedComments, $fetchedComments);
  208. }
  209. public function test_nested_collections_should_hydrate_results() {
  210. $mapper = $this->mapper;
  211. $comment = $mapper->comment->post[5]->fetch();
  212. $this->assertEquals(7, $comment->id);
  213. $this->assertEquals('Comment Text', $comment->text);
  214. $this->assertEquals(4, count(get_object_vars($comment)));
  215. $this->assertEquals(5, $comment->post_id->id);
  216. $this->assertEquals('Post Title', $comment->post_id->title);
  217. $this->assertEquals('Post Text', $comment->post_id->text);
  218. $this->assertEquals(4, count(get_object_vars($comment->post_id)));
  219. }
  220. public function testOneToN() {
  221. $mapper = $this->mapper;
  222. $comments = $mapper->comment->post($mapper->author)->fetchAll();
  223. $comment = current($comments);
  224. $this->assertEquals(1, count($comments));
  225. $this->assertEquals(7, $comment->id);
  226. $this->assertEquals('Comment Text', $comment->text);
  227. $this->assertEquals(4, count(get_object_vars($comment)));
  228. $this->assertEquals(5, $comment->post_id->id);
  229. $this->assertEquals('Post Title', $comment->post_id->title);
  230. $this->assertEquals('Post Text', $comment->post_id->text);
  231. $this->assertEquals(4, count(get_object_vars($comment->post_id)));
  232. $this->assertEquals(1, $comment->post_id->author_id->id);
  233. $this->assertEquals('Author 1', $comment->post_id->author_id->name);
  234. $this->assertEquals(2, count(get_object_vars($comment->post_id->author_id)));
  235. }
  236. public function testNtoN() {
  237. $mapper = $this->mapper;
  238. $comments = $mapper->comment->post->post_category->category[2]->fetchAll();
  239. $comment = current($comments);
  240. $this->assertEquals(1, count($comments));
  241. $this->assertEquals(7, $comment->id);
  242. $this->assertEquals('Comment Text', $comment->text);
  243. $this->assertEquals(4, count(get_object_vars($comment)));
  244. $this->assertEquals(5, $comment->post_id->id);
  245. $this->assertEquals('Post Title', $comment->post_id->title);
  246. $this->assertEquals('Post Text', $comment->post_id->text);
  247. $this->assertEquals(4, count(get_object_vars($comment->post_id)));
  248. }
  249. public function testNtoNReverse() {
  250. $mapper = $this->mapper;
  251. $cat = $mapper->category->post_category->post[5]->fetch();
  252. $this->assertEquals(2, $cat->id);
  253. $this->assertEquals('Sample Category', $cat->name);
  254. }
  255. public function testSimplePersist() {
  256. $mapper = $this->mapper;
  257. $entity = (object) array('id' => 4, 'name' => 'inserted', 'category_id' => null);
  258. $mapper->category->persist($entity);
  259. $mapper->flush();
  260. $result = $this->conn->query('select * from category where id=4')->fetch(PDO::FETCH_OBJ);
  261. $this->assertEquals($entity, $result);
  262. }
  263. public function testSimplePersistCollection() {
  264. $mapper = $this->mapper;
  265. $entity = (object) array('id' => 4, 'name' => 'inserted', 'category_id' => null);
  266. $mapper->category->persist($entity);
  267. $mapper->flush();
  268. $result = $this->conn->query('select * from category where id=4')->fetch(PDO::FETCH_OBJ);
  269. $this->assertEquals($entity, $result);
  270. }
  271. public function testNestedPersistCollection() {
  272. $postWithAuthor = (object) array(
  273. 'id' => null,
  274. 'title' => 'hi',
  275. 'text' => 'hi text',
  276. 'author_id' => (object) array(
  277. 'id' => null,
  278. 'name' => 'New'
  279. )
  280. );
  281. $this->mapper->post->author->persist($postWithAuthor);
  282. $this->mapper->flush();
  283. $author = $this->conn->query('select * from author order by id desc limit 1')->fetch(PDO::FETCH_OBJ);
  284. $post = $this->conn->query('select * from post order by id desc limit 1')->fetch(PDO::FETCH_OBJ);
  285. $this->assertEquals('New', $author->name);
  286. $this->assertEquals('hi', $post->title);
  287. }
  288. public function testNestedPersistCollectionShortcut() {
  289. $postWithAuthor = (object) array(
  290. 'id' => null,
  291. 'title' => 'hi',
  292. 'text' => 'hi text',
  293. 'author_id' => (object) array(
  294. 'id' => null,
  295. 'name' => 'New'
  296. )
  297. );
  298. $this->mapper->postAuthor = $this->mapper->post->author;
  299. $this->mapper->postAuthor->persist($postWithAuthor);
  300. $this->mapper->flush();
  301. $author = $this->conn->query('select * from author order by id desc limit 1')->fetch(PDO::FETCH_OBJ);
  302. $post = $this->conn->query('select * from post order by id desc limit 1')->fetch(PDO::FETCH_OBJ);
  303. $this->assertEquals('New', $author->name);
  304. $this->assertEquals('hi', $post->title);
  305. }
  306. public function testNestedPersistCollectionWithChildrenShortcut() {
  307. $postWithAuthor = (object) array(
  308. 'id' => null,
  309. 'title' => 'hi',
  310. 'text' => 'hi text',
  311. 'author_id' => (object) array(
  312. 'id' => null,
  313. 'name' => 'New'
  314. )
  315. );
  316. $this->mapper->postAuthor = $this->mapper->post($this->mapper->author);
  317. $this->mapper->postAuthor->persist($postWithAuthor);
  318. $this->mapper->flush();
  319. $author = $this->conn->query('select * from author order by id desc limit 1')->fetch(PDO::FETCH_OBJ);
  320. $post = $this->conn->query('select * from post order by id desc limit 1')->fetch(PDO::FETCH_OBJ);
  321. $this->assertEquals('New', $author->name);
  322. $this->assertEquals('hi', $post->title);
  323. }
  324. public function testSubCategory() {
  325. $mapper = $this->mapper;
  326. $entity = (object) array('id' => 8, 'name' => 'inserted', 'category_id' => 2);
  327. $mapper->category->persist($entity);
  328. $mapper->flush();
  329. $result = $this->conn->query('select * from category where id=8')->fetch(PDO::FETCH_OBJ);
  330. $result2 = $mapper->category[8]->category->fetch();
  331. $this->assertEquals($result->id, $result2->id);
  332. $this->assertEquals($result->name, $result2->name);
  333. $this->assertEquals($entity, $result);
  334. }
  335. public function testSubCategoryCondition() {
  336. $mapper = $this->mapper;
  337. $entity = (object) array('id' => 8, 'name' => 'inserted', 'category_id' => 2);
  338. $mapper->category->persist($entity);
  339. $mapper->flush();
  340. $result = $this->conn->query('select * from category where id=8')->fetch(PDO::FETCH_OBJ);
  341. $result2 = $mapper->category(array("id"=>8))->category->fetch();
  342. $this->assertEquals($result->id, $result2->id);
  343. $this->assertEquals($result->name, $result2->name);
  344. $this->assertEquals($entity, $result);
  345. }
  346. public function testAutoIncrementPersist() {
  347. $mapper = $this->mapper;
  348. $entity = (object) array('id' => null, 'name' => 'inserted', 'category_id' => null);
  349. $mapper->category->persist($entity);
  350. $mapper->flush();
  351. $result = $this->conn->query('select * from category where name="inserted"')->fetch(PDO::FETCH_OBJ);
  352. $this->assertEquals($entity, $result);
  353. $this->assertEquals(4, $result->id);
  354. }
  355. public function testPassedIdentity() {
  356. $mapper = $this->mapper;
  357. $post = new \stdClass;
  358. $post->id = null;
  359. $post->title = 12345;
  360. $post->text = 'text abc';
  361. $comment = new \stdClass;
  362. $comment->id = null;
  363. $comment->post_id = $post;
  364. $comment->text = 'abc';
  365. $mapper->post->persist($post);
  366. $mapper->comment->persist($comment);
  367. $mapper->flush();
  368. $postId = $this->conn
  369. ->query('select id from post where title = 12345')
  370. ->fetchColumn(0);
  371. $comment = $this->conn->query('select * from comment where post_id = ' . $postId)
  372. ->fetchObject();
  373. $this->assertEquals('abc', $comment->text);
  374. }
  375. public function testJoinedPersist() {
  376. $mapper = $this->mapper;
  377. $entity = $mapper->comment[8]->fetch();
  378. $entity->text = 'HeyHey';
  379. $mapper->comment->persist($entity);
  380. $mapper->flush();
  381. $result = $this->conn->query('select text from comment where id=8')->fetchColumn(0);
  382. $this->assertEquals('HeyHey', $result);
  383. }
  384. public function testRemove() {
  385. $mapper = $this->mapper;
  386. $c8 = $mapper->comment[8]->fetch();
  387. $pre = $this->conn->query('select count(*) from comment')->fetchColumn(0);
  388. $mapper->comment->remove($c8);
  389. $mapper->flush();
  390. $total = $this->conn->query('select count(*) from comment')->fetchColumn(0);
  391. $this->assertEquals($total, $pre - 1);
  392. }
  393. public function test_fetching_entity_typed()
  394. {
  395. $mapper = $this->mapper;
  396. $mapper->entityNamespace = '\Respect\Relational\\';
  397. $comment = $mapper->comment[8]->fetch();
  398. $this->assertInstanceOf('\Respect\Relational\Comment', $comment);
  399. }
  400. public function test_fetching_all_entity_typed()
  401. {
  402. $mapper = $this->mapper;
  403. $mapper->entityNamespace = '\Respect\Relational\\';
  404. $comment = $mapper->comment->fetchAll();
  405. $this->assertInstanceOf('\Respect\Relational\Comment', $comment[1]);
  406. }
  407. public function test_fetching_all_entity_typed_nested()
  408. {
  409. $mapper = $this->mapper;
  410. $mapper->entityNamespace = '\Respect\Relational\\';
  411. $comment = $mapper->comment->post->fetchAll();
  412. $this->assertInstanceOf('\Respect\Relational\Comment', $comment[0]);
  413. $this->assertInstanceOf('\Respect\Relational\Post', $comment[0]->post_id);
  414. }
  415. public function test_persisting_entity_typed()
  416. {
  417. $mapper = $this->mapper;
  418. $mapper->entityNamespace = '\Respect\Relational\\';
  419. $comment = $mapper->comment[8]->fetch();
  420. $comment->text = 'HeyHey';
  421. $mapper->comment->persist($comment);
  422. $mapper->flush();
  423. $result = $this->conn->query('select text from comment where id=8')->fetchColumn(0);
  424. $this->assertEquals('HeyHey', $result);
  425. }
  426. public function test_persisting_new_entity_typed()
  427. {
  428. $mapper = $this->mapper;
  429. $mapper->entityNamespace = '\Respect\Relational\\';
  430. $comment = new Comment();
  431. $comment->text = 'HeyHey';
  432. $mapper->comment->persist($comment);
  433. $mapper->flush();
  434. $result = $this->conn->query('select text from comment where id=9')->fetchColumn(0);
  435. $this->assertEquals('HeyHey', $result);
  436. }
  437. public function test_setters_and_getters_datetime_as_object()
  438. {
  439. $mapper = $this->mapper;
  440. $mapper->entityNamespace = '\Respect\Relational\\';
  441. $post = new Post();
  442. $post->id = 44;
  443. $post->text = "Test using datetime setters";
  444. $post->setDatetime(new \Datetime('now'));
  445. $mapper->post->persist($post);
  446. $mapper->flush();
  447. $result = $mapper->post[44]->fetch();
  448. $this->assertInstanceOf('\Datetime', $result->getDatetime());
  449. $this->assertEquals(date('Y-m-d'), $result->getDatetime()->format('Y-m-d'));
  450. }
  451. public function test_style()
  452. {
  453. $this->assertInstanceOf('Respect\Data\Styles\Stylable', $this->mapper->getStyle());
  454. $this->assertInstanceOf('Respect\Data\Styles\Standard', $this->mapper->getStyle());
  455. $styles = array(
  456. new Styles\CakePHP(),
  457. new Styles\NorthWind(),
  458. new Styles\Sakila(),
  459. new Styles\Standard(),
  460. );
  461. foreach ($styles as $style) {
  462. $this->mapper->setStyle($style);
  463. $this->assertEquals($style, $this->mapper->getStyle());
  464. }
  465. }
  466. public function test_feching_a_single_filtered_collection_should_not_bring_filtered_children() {
  467. $mapper = $this->mapper;
  468. $mapper->authorsWithPosts = Filtered::post()->author();
  469. $author = $mapper->authorsWithPosts->fetch();
  470. $this->assertEquals($this->authors[0], $author);
  471. }
  472. public function test_persisting_a_previously_fetched_filtered_entity_back_into_its_collection() {
  473. $mapper = $this->mapper;
  474. $mapper->authorsWithPosts = Filtered::post()->author();
  475. $author = $mapper->authorsWithPosts->fetch();
  476. $author->name = 'Author Changed';
  477. $mapper->authorsWithPosts->persist($author);
  478. $mapper->flush();
  479. $result = $this->conn->query('select name from author where id=1')->fetch(PDO::FETCH_OBJ);
  480. $this->assertEquals('Author Changed', $result->name);
  481. }
  482. public function test_persisting_a_previously_fetched_filtered_entity_back_into_a_foreign_compatible_collection() {
  483. $mapper = $this->mapper;
  484. $mapper->authorsWithPosts = Filtered::post()->author();
  485. $author = $mapper->authorsWithPosts->fetch();
  486. $author->name = 'Author Changed';
  487. $mapper->author->persist($author);
  488. $mapper->flush();
  489. $result = $this->conn->query('select name from author where id=1')->fetch(PDO::FETCH_OBJ);
  490. $this->assertEquals('Author Changed', $result->name);
  491. }
  492. public function test_persisting_a_newly_created_filtered_entity_into_its_collection() {
  493. $mapper = $this->mapper;
  494. $mapper->authorsWithPosts = Filtered::post()->author();
  495. $author = new \stdClass;
  496. $author->id = null;
  497. $author->name = 'Author Changed';
  498. $mapper->authorsWithPosts->persist($author);
  499. $mapper->flush();
  500. $result = $this->conn->query('select name from author order by id desc')->fetch(PDO::FETCH_OBJ);
  501. $this->assertEquals('Author Changed', $result->name);
  502. }
  503. public function test_persisting_a_newly_created_filtered_entity_into_a_foreig_compatible_collection() {
  504. $mapper = $this->mapper;
  505. $mapper->authorsWithPosts = Filtered::post()->author();
  506. $author = new \stdClass;
  507. $author->id = null;
  508. $author->name = 'Author Changed';
  509. $mapper->author->persist($author);
  510. $mapper->flush();
  511. $result = $this->conn->query('select name from author order by id desc')->fetch(PDO::FETCH_OBJ);
  512. $this->assertEquals('Author Changed', $result->name);
  513. }
  514. public function test_feching_multiple_filtered_collections_should_not_bring_filtered_children() {
  515. $mapper = $this->mapper;
  516. $mapper->authorsWithPosts = Filtered::post()->author();
  517. $authors = $mapper->authorsWithPosts->fetchAll();
  518. $this->assertEquals($this->authors, $authors);
  519. }
  520. public function test_filtered_collections_should_hydrate_non_filtered_parts_as_usual() {
  521. $mapper = $this->mapper;
  522. $mapper->postsFromAuthorsWithComments = Filtered::comment()->post()->author();
  523. $post = $mapper->postsFromAuthorsWithComments->fetch();
  524. $this->assertEquals((object) (array('author_id' => $post->author_id) + (array) $this->posts[0]), $post);
  525. $this->assertEquals($this->authors[0], $post->author_id);
  526. }
  527. public function test_filtered_collections_should_persist_hydrated_non_filtered_parts_as_usual() {
  528. $mapper = $this->mapper;
  529. $mapper->postsFromAuthorsWithComments = Filtered::comment()->post()->author();
  530. $post = $mapper->postsFromAuthorsWithComments->fetch();
  531. $this->assertEquals((object) (array('author_id' => $post->author_id) + (array) $this->posts[0]), $post);
  532. $this->assertEquals($this->authors[0], $post->author_id);
  533. $post->title = 'Title Changed';
  534. $post->author_id->name = 'John';
  535. $mapper->postsFromAuthorsWithComments->persist($post);
  536. $mapper->flush();
  537. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  538. $this->assertEquals('Title Changed', $result->title);
  539. $result = $this->conn->query('select name from author where id=1')->fetch(PDO::FETCH_OBJ);
  540. $this->assertEquals('John', $result->name);
  541. }
  542. public function test_multiple_filtered_collections_dont_persist() {
  543. $mapper = $this->mapper;
  544. $mapper->authorsWithPosts = Filtered::comment()->post->stack(Filtered::author());
  545. $post = $mapper->authorsWithPosts->fetch();
  546. $this->assertEquals((object) array('id' => '5', 'author_id' => 1, 'text' => 'Post Text', 'title' => 'Post Title'), $post);
  547. $post->title = 'Title Changed';
  548. $post->author_id = $mapper->author[1]->fetch();
  549. $post->author_id->name = 'A';
  550. $mapper->postsFromAuthorsWithComments->persist($post);
  551. $mapper->flush();
  552. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  553. $this->assertEquals('Title Changed', $result->title);
  554. $result = $this->conn->query('select name from author where id=1')->fetch(PDO::FETCH_OBJ);
  555. $this->assertNotEquals('A', $result->name);
  556. }
  557. public function test_multiple_filtered_collections_dont_persist_newly_create_objects() {
  558. $mapper = $this->mapper;
  559. $mapper->authorsWithPosts = Filtered::comment()->post->stack(Filtered::author());
  560. $post = $mapper->authorsWithPosts->fetch();
  561. $this->assertEquals((object) array('id' => '5', 'author_id' => 1, 'text' => 'Post Text', 'title' => 'Post Title'), $post);
  562. $post->title = 'Title Changed';
  563. $post->author_id = new \stdClass;
  564. $post->author_id->id = null;
  565. $post->author_id->name = 'A';
  566. $mapper->postsFromAuthorsWithComments->persist($post);
  567. $mapper->flush();
  568. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  569. $this->assertEquals('Title Changed', $result->title);
  570. $result = $this->conn->query('select name from author order by id desc')->fetch(PDO::FETCH_OBJ);
  571. $this->assertNotEquals('A', $result->name);
  572. }
  573. public function test_multiple_filtered_collections_fetch_at_once_dont_persist() {
  574. $mapper = $this->mapper;
  575. $mapper->authorsWithPosts = Filtered::comment()->post->stack(Filtered::author());
  576. $post = $mapper->authorsWithPosts->fetchAll();
  577. $post = $post[0];
  578. $this->assertEquals((object) array('id' => '5', 'author_id' => 1, 'text' => 'Post Text', 'title' => 'Post Title'), $post);
  579. $post->title = 'Title Changed';
  580. $post->author_id = $mapper->author[1]->fetch();
  581. $post->author_id->name = 'A';
  582. $mapper->postsFromAuthorsWithComments->persist($post);
  583. $mapper->flush();
  584. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  585. $this->assertEquals('Title Changed', $result->title);
  586. $result = $this->conn->query('select name from author where id=1')->fetch(PDO::FETCH_OBJ);
  587. $this->assertNotEquals('A', $result->name);
  588. }
  589. public function test_reusing_registered_filtered_collections_keeps_their_filtering() {
  590. $mapper = $this->mapper;
  591. $mapper->commentFil = Filtered::comment();
  592. $mapper->author = Filtered::author();
  593. $post = $mapper->commentFil->post->author->fetch();
  594. $this->assertEquals((object) array('id' => '5', 'author_id' => 1, 'text' => 'Post Text', 'title' => 'Post Title'), $post);
  595. $post->title = 'Title Changed';
  596. $mapper->postsFromAuthorsWithComments->persist($post);
  597. $mapper->flush();
  598. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  599. $this->assertEquals('Title Changed', $result->title);
  600. }
  601. public function test_reusing_registered_filtered_collections_keeps_their_filtering_on_fetchAll() {
  602. $mapper = $this->mapper;
  603. $mapper->commentFil = Filtered::comment();
  604. $mapper->author = Filtered::author();
  605. $post = $mapper->commentFil->post->author->fetchAll();
  606. $post = $post[0];
  607. $this->assertEquals((object) array('id' => '5', 'author_id' => 1, 'text' => 'Post Text', 'title' => 'Post Title'), $post);
  608. $post->title = 'Title Changed';
  609. $mapper->postsFromAuthorsWithComments->persist($post);
  610. $mapper->flush();
  611. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  612. $this->assertEquals('Title Changed', $result->title);
  613. }
  614. public function test_registered_filtered_collections_by_column_keeps_their_filtering() {
  615. $mapper = $this->mapper;
  616. $mapper->post = Filtered::by('title')->post();
  617. $post = $mapper->post->fetch();
  618. $this->assertEquals((object) array('id' => '5', 'title' => 'Post Title'), $post);
  619. $post->title = 'Title Changed';
  620. $mapper->postsFromAuthorsWithComments->persist($post);
  621. $mapper->flush();
  622. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  623. $this->assertEquals('Title Changed', $result->title);
  624. }
  625. public function test_registered_filtered_collections_by_column_keeps_their_filtering_on_fetchAll() {
  626. $mapper = $this->mapper;
  627. $mapper->post = Filtered::by('title')->post();
  628. $post = $mapper->post->fetchAll();
  629. $post = $post[0];
  630. $this->assertEquals((object) array('id' => '5', 'title' => 'Post Title'), $post);
  631. $post->title = 'Title Changed';
  632. $mapper->postsFromAuthorsWithComments->persist($post);
  633. $mapper->flush();
  634. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  635. $this->assertEquals('Title Changed', $result->title);
  636. }
  637. public function test_registered_filtered_wildcard_collections_keeps_their_filtering() {
  638. $mapper = $this->mapper;
  639. $mapper->post = Filtered::by('*')->post();
  640. $post = $mapper->post->fetch();
  641. $this->assertEquals((object) array('id' => '5'), $post);
  642. $post->title = 'Title Changed';
  643. $mapper->postsFromAuthorsWithComments->persist($post);
  644. $mapper->flush();
  645. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  646. $this->assertEquals('Title Changed', $result->title);
  647. }
  648. public function test_registered_filtered_wildcard_collections_keeps_their_filtering_on_fetchAll() {
  649. $mapper = $this->mapper;
  650. $mapper->post = Filtered::by('*')->post();
  651. $post = $mapper->post->fetchAll();
  652. $post = $post[0];
  653. $this->assertEquals((object) array('id' => '5'), $post);
  654. $post->title = 'Title Changed';
  655. $mapper->postsFromAuthorsWithComments->persist($post);
  656. $mapper->flush();
  657. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  658. $this->assertEquals('Title Changed', $result->title);
  659. }
  660. public function test_fetching_registered_filtered_collections_alongside_normal() {
  661. $mapper = $this->mapper;
  662. $mapper->post = Filtered::by('*')->post()->author();
  663. $post = $mapper->post->fetchAll();
  664. $post = $post[0];
  665. $this->assertEquals((object) array('id' => '5', 'author_id' => $post->author_id), $post);
  666. $this->assertEquals((object) array('name' => 'Author 1', 'id' => 1), $post->author_id);
  667. $post->title = 'Title Changed';
  668. $mapper->postsFromAuthorsWithComments->persist($post);
  669. $mapper->flush();
  670. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  671. $this->assertEquals('Title Changed', $result->title);
  672. }
  673. public function test_mixins_bring_results_from_two_tables() {
  674. $mapper = $this->mapper;
  675. $mapper->postComment = Mixed::with(array('comment' => array('text')))->post()->author();
  676. $post = $mapper->postComment->fetch();
  677. $this->assertEquals((object) array('name' => 'Author 1', 'id' => 1), $post->author_id);
  678. $this->assertEquals((object) array('id' => '5', 'author_id' => $post->author_id, 'text' => 'Comment Text', 'title' => 'Post Title', 'comment_id' => 7), $post);
  679. }
  680. public function test_mixins_persists_results_on_two_tables() {
  681. $mapper = $this->mapper;
  682. $mapper->postComment = Mixed::with(array('comment' => array('text')))->post()->author();
  683. $post = $mapper->postComment->fetch();
  684. $this->assertEquals((object) array('name' => 'Author 1', 'id' => 1), $post->author_id);
  685. $this->assertEquals((object) array('id' => '5', 'author_id' => $post->author_id, 'text' => 'Comment Text', 'title' => 'Post Title', 'comment_id' => 7), $post);
  686. $post->title = 'Title Changed';
  687. $post->text = 'Comment Changed';
  688. $mapper->postsFromAuthorsWithComments->persist($post);
  689. $mapper->flush();
  690. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  691. $this->assertEquals('Title Changed', $result->title);
  692. $result = $this->conn->query('select text from comment where id=7')->fetch(PDO::FETCH_OBJ);
  693. $this->assertEquals('Comment Changed', $result->text);
  694. }
  695. public function test_mixins_persists_newly_created_entities_on_two_tables() {
  696. $mapper = $this->mapper;
  697. $mapper->postComment = Mixed::with(array('comment' => array('text')))->post()->author();
  698. $post = (object) array('text' => 'Comment X', 'title' => 'Post X', 'id' => null);
  699. $post->author_id = (object) array('name' => 'Author X', 'id' => null);
  700. $mapper->postComment->persist($post);
  701. $mapper->flush();
  702. $result = $this->conn->query('select title, text from post order by id desc')->fetch(PDO::FETCH_OBJ);
  703. $this->assertEquals('Post X', $result->title);
  704. $this->assertEquals('', $result->text);
  705. $result = $this->conn->query('select text from comment order by id desc')->fetch(PDO::FETCH_OBJ);
  706. $this->assertEquals('Comment X', $result->text);
  707. }
  708. public function test_mixins_all() {
  709. $mapper = $this->mapper;
  710. $mapper->postComment = Mixed::with(array('comment' => array('text')))->post()->author();
  711. $post = $mapper->postComment->fetchAll();
  712. $post = $post[0];
  713. $this->assertEquals((object) array('name' => 'Author 1', 'id' => 1), $post->author_id);
  714. $this->assertEquals((object) array('id' => '5', 'author_id' => $post->author_id, 'text' => 'Comment Text', 'title' => 'Post Title', 'comment_id' => 7), $post);
  715. $post->title = 'Title Changed';
  716. $post->text = 'Comment Changed';
  717. $mapper->postsFromAuthorsWithComments->persist($post);
  718. $mapper->flush();
  719. $result = $this->conn->query('select title from post where id=5')->fetch(PDO::FETCH_OBJ);
  720. $this->assertEquals('Title Changed', $result->title);
  721. $result = $this->conn->query('select text from comment where id=7')->fetch(PDO::FETCH_OBJ);
  722. $this->assertEquals('Comment Changed', $result->text);
  723. }
  724. public function test_typed() {
  725. $mapper = $this->mapper;
  726. $mapper->entityNamespace = '\Respect\Relational\\';
  727. $mapper->typedIssues = Typed::by('type')->issues();
  728. $issues = $mapper->typedIssues->fetchAll();
  729. $this->assertInstanceOf('\\Respect\Relational\\Bug', $issues[0]);
  730. $this->assertInstanceOf('\\Respect\Relational\\Improvement', $issues[1]);
  731. $this->assertEquals((array) $this->issues[0], (array) $issues[0]);
  732. $this->assertEquals((array) $this->issues[1], (array) $issues[1]);
  733. $issues[0]->title = 'Title Changed';
  734. $mapper->typedIssues->persist($issues[0]);
  735. $mapper->flush();
  736. $result = $this->conn->query('select title from issues where id=1')->fetch(PDO::FETCH_OBJ);
  737. $this->assertEquals('Title Changed', $result->title);
  738. }
  739. public function test_typed_single() {
  740. $mapper = $this->mapper;
  741. $mapper->entityNamespace = '\Respect\Relational\\';
  742. $mapper->typedIssues = Typed::by('type')->issues();
  743. $issue = $mapper->typedIssues->fetch();
  744. $this->assertInstanceOf('\\Respect\Relational\\Bug', $issue);
  745. $this->assertEquals((array) $this->issues[0], (array) $issue);
  746. $issue->title = 'Title Changed';
  747. $mapper->typedIssues->persist($issue);
  748. $mapper->flush();
  749. $result = $this->conn->query('select title from issues where id=1')->fetch(PDO::FETCH_OBJ);
  750. $this->assertEquals('Title Changed', $result->title);
  751. }
  752. public function test_persist_new_with_arrayobject()
  753. {
  754. $mapper = $this->mapper;
  755. $arrayEntity = array('id' => 10, 'name' => 'array_object_category', 'category_id' => null);
  756. $entity = new \ArrayObject($arrayEntity);
  757. $mapper->category->persist($entity);
  758. $mapper->flush();
  759. $result = $this->conn->query('select * from category where id=10')->fetch(PDO::FETCH_OBJ);
  760. $this->assertEquals('array_object_category', $result->name);
  761. }
  762. // --------------------------------------------------------------
  763. public function testFetchingEntityWithoutPublicPropertiesTyped()
  764. {
  765. $mapper = $this->mapper;
  766. $mapper->entityNamespace = '\Respect\Relational\OtherEntity\\';
  767. $post = $mapper->post[5]->fetch();
  768. $this->assertInstanceOf('\Respect\Relational\OtherEntity\Post', $post);
  769. }
  770. public function testFetchingAllEntityWithoutPublicPropertiesTyped()
  771. {
  772. $mapper = $this->mapper;
  773. $mapper->entityNamespace = '\Respect\Relational\OtherEntity\\';
  774. $posts = $mapper->post->fetchAll();
  775. $this->assertInstanceOf('\Respect\Relational\OtherEntity\Post', $posts[0]);
  776. }
  777. public function testFetchingAllEntityWithoutPublicPropertiesTypedNested()
  778. {
  779. $mapper = $this->mapper;
  780. $mapper->entityNamespace = '\Respect\Relational\OtherEntity\\';
  781. $posts = $mapper->post->author->fetchAll();
  782. $this->assertInstanceOf('\Respect\Relational\OtherEntity\Post', $posts[0]);
  783. $this->assertInstanceOf('\Respect\Relational\OtherEntity\Author', $posts[0]->getAuthor());
  784. }
  785. public function testPersistingEntityWithoutPublicPropertiesTyped()
  786. {
  787. $mapper = $this->mapper;
  788. $mapper->entityNamespace = '\Respect\Relational\OtherEntity\\';
  789. $post = $mapper->post[5]->fetch();
  790. $post->setText('HeyHey');
  791. $mapper->post->persist($post);
  792. $mapper->flush();
  793. $result = $this->conn->query('select text from post where id=5')->fetchColumn(0);
  794. $this->assertEquals('HeyHey', $result);
  795. }
  796. public function testPersistingNewEntityWithoutPublicPropertiesTyped()
  797. {
  798. $mapper = $this->mapper;
  799. $mapper->entityNamespace = '\Respect\Relational\OtherEntity\\';
  800. $author = new OtherEntity\Author();
  801. $author->setId(1);
  802. $author->setName('Author 1');
  803. $post = new OtherEntity\Post();
  804. $post->setAuthor($author);
  805. $post->setTitle('My New Post Title');
  806. $post->setText('My new Post Text');
  807. $mapper->post->persist($post);
  808. $mapper->flush();
  809. $result = $this->conn->query('select text from post where id=6')->fetchColumn(0);
  810. $this->assertEquals('My new Post Text', $result);
  811. }
  812. public function testShouldExecuteEntityConstructorByDefault()
  813. {
  814. $mapper = $this->mapper;
  815. $mapper->entityNamespace = 'Respect\\Relational\\OtherEntity\\';
  816. try {
  817. $mapper->comment->fetch();
  818. $this->fail('This should throws exception');
  819. } catch (\DomainException $e) {
  820. $this->assertEquals('Exception from __construct', $e->getMessage());
  821. }
  822. }
  823. public function testShouldNotExecuteEntityConstructorWhenDisabled()
  824. {
  825. $mapper = $this->mapper;
  826. $mapper->entityNamespace = 'Respect\\Relational\\OtherEntity\\';
  827. $mapper->disableEntityConstructor = true;
  828. $this->assertInstanceOf('Respect\\Relational\\OtherEntity\\Comment', $mapper->comment->fetch());
  829. }
  830. }
  831. class Postcomment {
  832. public $id=null;
  833. }
  834. class Bug {
  835. public $id=null, $title;
  836. }
  837. class Improvement {
  838. public $id=null, $title;
  839. }
  840. class Comment {
  841. public $id=null, $post_id=null, $text=null;
  842. private $datetime;
  843. public function setDatetime(\Datetime $datetime)
  844. {
  845. $this->datetime = $datetime->format('Y-m-d H:i:s');
  846. }
  847. public function getDatetime()
  848. {
  849. return new \Datetime($this->datetime);
  850. }
  851. }
  852. class Post {
  853. public $id=null, $author_id=null, $text=null;
  854. /** @Relational\isNotColumn -> annotation because generate a sql error case column not exists in db. */
  855. private $datetime;
  856. public function setDatetime(\Datetime $datetime)
  857. {
  858. $this->datetime = $datetime->format('Y-m-d H:i:s');
  859. }
  860. public function getDatetime()
  861. {
  862. return new \Datetime($this->datetime);
  863. }
  864. }
  865. namespace Respect\Relational\OtherEntity;
  866. class Post {
  867. private $id, $author_id, $title, $text;
  868. public function getTitle()
  869. {
  870. return $this->title;
  871. }
  872. public function setTitle($title)
  873. {
  874. $this->title = $title;
  875. }
  876. public function getId()
  877. {
  878. return $this->id;
  879. }
  880. public function getAuthor()
  881. {
  882. return $this->author_id;
  883. }
  884. public function getText()
  885. {
  886. return $this->text;
  887. }
  888. public function setId($id)
  889. {
  890. $this->id = $id;
  891. }
  892. public function setAuthor(Author $author)
  893. {
  894. $this->author_id = $author;
  895. }
  896. public function setText($text)
  897. {
  898. $this->text = $text;
  899. }
  900. }
  901. class Author {
  902. private $id, $name;
  903. public function getId()
  904. {
  905. return $this->id;
  906. }
  907. public function getName()
  908. {
  909. return $this->name;
  910. }
  911. public function setId($id)
  912. {
  913. $this->id = $id;
  914. }
  915. public function setName($name)
  916. {
  917. $this->name = $name;
  918. }
  919. }
  920. class Comment
  921. {
  922. public function __construct()
  923. {
  924. throw new \DomainException('Exception from __construct');
  925. }
  926. }