flag.test 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784
  1. <?php
  2. /**
  3. * @file
  4. * Tests for the Flag module.
  5. */
  6. /**
  7. * Base class for our tests with common methods.
  8. */
  9. abstract class FlagTestCaseBase extends DrupalWebTestCase {
  10. /**
  11. * Helper to create a flag from an array of data and clear caches etc.
  12. *
  13. * @param array $flag_data
  14. * An array of flag data.
  15. *
  16. * @return flag_flag
  17. * The flag object.
  18. */
  19. function createFlag($flag_data) {
  20. $flag = flag_flag::factory_by_array($flag_data);
  21. $flag->save();
  22. // Reset our cache so our permissions show up.
  23. drupal_static_reset('flag_get_flags');
  24. // Reset permissions so that permissions for this flag are available.
  25. $this->checkPermissions(array(), TRUE);
  26. return $flag;
  27. }
  28. }
  29. /**
  30. * Test CRUD operations on Flagging entities.
  31. */
  32. class FlagFlaggingCRUDTestCase extends FlagTestCaseBase {
  33. /**
  34. * Implements getInfo().
  35. */
  36. public static function getInfo() {
  37. return array(
  38. 'name' => 'CRUD API',
  39. 'description' => 'Basic CRUD operations on flagging entities.',
  40. 'group' => 'Flag',
  41. );
  42. }
  43. /**
  44. * Implements setUp().
  45. */
  46. function setUp() {
  47. parent::setUp('flag');
  48. $flag_data = array(
  49. 'entity_type' => 'node',
  50. 'name' => 'test_flag',
  51. 'title' => 'Test Flag',
  52. 'global' => 0,
  53. 'types' => array(
  54. 0 => 'article',
  55. ),
  56. 'flag_short' => 'Flag this item',
  57. 'flag_long' => '',
  58. 'flag_message' => '',
  59. 'unflag_short' => 'Unflag this item',
  60. 'unflag_long' => '',
  61. 'unflag_message' => '',
  62. 'unflag_denied_text' => 'You may not unflag this item',
  63. 'link_type' => 'normal',
  64. 'weight' => 0,
  65. 'show_on_form' => 0,
  66. 'access_author' => '',
  67. 'show_contextual_link' => 0,
  68. 'show_in_links' => array(
  69. 'full' => 1,
  70. 'teaser' => 1,
  71. ),
  72. 'i18n' => 0,
  73. 'api_version' => 3,
  74. );
  75. $this->flag = $this->createFlag($flag_data);
  76. // Create test user who can flag and unflag.
  77. $this->flag_unflag_user = $this->drupalCreateUser(array('flag test_flag', 'unflag test_flag'));
  78. $this->drupalLogin($this->flag_unflag_user);
  79. }
  80. /**
  81. * Test creation of a flagging entity with flagging_save().
  82. */
  83. function testFlaggingCreate() {
  84. // Create an article node that we try to create a flagging entity for.
  85. $title = $this->randomName(8);
  86. $node = array(
  87. 'title' => $title,
  88. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  89. 'uid' => 1,
  90. 'type' => 'article',
  91. 'is_new' => TRUE,
  92. );
  93. $node = node_submit((object) $node);
  94. node_save($node);
  95. // Create a flagging entity and save it.
  96. $flagging = array(
  97. 'fid' => $this->flag->fid,
  98. 'entity_type' => 'node',
  99. 'entity_id' => $node->nid,
  100. 'uid' => $this->flag_unflag_user->uid,
  101. );
  102. $flagging = (object) $flagging;
  103. flagging_save($flagging);
  104. // Test flagging has a flagging_id
  105. $this->assertTrue(!empty($flagging->flagging_id), 'The flagging entity has an entity id.');
  106. // Test the database record exists.
  107. $result = db_query("SELECT * FROM {flagging} WHERE fid = :fid AND entity_id = :nid AND uid = :uid", array(
  108. ':fid' => $this->flag->fid,
  109. ':nid' => $node->nid,
  110. ':uid' => $this->flag_unflag_user->uid,
  111. ));
  112. $records = $result->fetchAll();
  113. $this->assertTrue(count($records), 'The flagging record exists in the database.');
  114. // Test node is flagged.
  115. // The current user is not the same as the user logged into the internal
  116. // browser, so we have to pass the UID param explicitly.
  117. $this->assertTrue($this->flag->is_flagged($node->nid, $this->flag_unflag_user->uid), 'The node has been flagged by creating the flagging.');
  118. }
  119. /**
  120. * Test throwing of exceptions with flagging_save().
  121. */
  122. function testFlaggingCreateException() {
  123. // Create an article node that we try to create a flagging entity for.
  124. $title = $this->randomName(8);
  125. $node = array(
  126. 'title' => $title,
  127. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  128. 'uid' => 1,
  129. 'type' => 'article',
  130. 'is_new' => TRUE,
  131. );
  132. $node = node_submit((object) $node);
  133. node_save($node);
  134. // Create test user who can't use this flag.
  135. $no_flag_user = $this->drupalCreateUser(array());
  136. // Create a flagging entity with that tries to perform an flagging action
  137. // that is not permitted.
  138. $flagging = array(
  139. 'fid' => $this->flag->fid,
  140. 'entity_type' => 'node',
  141. 'entity_id' => $node->nid,
  142. 'uid' => $no_flag_user->uid,
  143. );
  144. $flagging = (object) $flagging;
  145. try {
  146. flagging_save($flagging);
  147. $this->fail(t('Expected exception has not been thrown.'));
  148. }
  149. catch (Exception $e) {
  150. $this->pass(t('Expected exception has been thrown.'));
  151. }
  152. }
  153. /**
  154. * Test creation of a flagging entity with flagging_save().
  155. */
  156. function testFlaggingUpdate() {
  157. // Create an article node that we try to create a flagging entity for.
  158. $title = $this->randomName(8);
  159. $node = array(
  160. 'title' => $title,
  161. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  162. 'uid' => 1,
  163. 'type' => 'article',
  164. 'is_new' => TRUE,
  165. );
  166. $node = node_submit((object) $node);
  167. node_save($node);
  168. // Flag the node as the user.
  169. $flag = flag_get_flag('test_flag');
  170. $flag->flag('flag', $node->nid, $this->flag_unflag_user);
  171. // Get the flagging record back from the database.
  172. $result = db_query("SELECT * FROM {flagging} WHERE fid = :fid AND entity_id = :nid AND uid = :uid", array(
  173. ':fid' => $this->flag->fid,
  174. ':nid' => $node->nid,
  175. ':uid' => $this->flag_unflag_user->uid,
  176. ));
  177. $record = $result->fetchObject();
  178. // Load the flagging entity we just created.
  179. $flagging = flagging_load($record->flagging_id);
  180. // Save it, as if we were updating field values.
  181. flagging_save($flagging);
  182. // This should have no effect: the node should still be flagged.
  183. $this->assertTrue($this->flag->is_flagged($node->nid, $this->flag_unflag_user->uid), 'The node is still flagged after updating the flagging.');
  184. }
  185. }
  186. /**
  187. * Test Flag admin UI.
  188. */
  189. class FlagAdminTestCase extends FlagTestCaseBase {
  190. public $_flag = FALSE;
  191. /**
  192. * Implements getInfo().
  193. */
  194. public static function getInfo() {
  195. return array(
  196. 'name' => 'Admin UI',
  197. 'description' => 'Add, edit and delete flags.',
  198. 'group' => 'Flag',
  199. );
  200. }
  201. /**
  202. * Implements setUp().
  203. */
  204. function setUp() {
  205. parent::setUp('flag');
  206. // Create and login user.
  207. $admin_user = $this->drupalCreateUser(array('access administration pages', 'administer flags'));
  208. $this->drupalLogin($admin_user);
  209. }
  210. /**
  211. * Create a flag through the UI and ensure that it is saved properly.
  212. */
  213. function testFlagAdmin() {
  214. // Add a new flag using the UI.
  215. $this->drupalGet(FLAG_ADMIN_PATH . '/add/node');
  216. // Check the form has the expected defaults.
  217. $this->assertFieldByName('flag_short', 'Flag this item', "The flag message default value shows in the form.");
  218. $this->assertFieldByName('unflag_short', 'Unflag this item', "The unflag message default value shows in the form.");
  219. $this->assertFieldByName('show_in_links[full]', 'full', "The view mode option is set to the node 'full' view mode by default.");
  220. $this->assertFieldByName('show_in_links[teaser]', 'teaser', "The view mode option is set to the node 'teaser' view mode by default.");
  221. $edit = array(
  222. 'name' => drupal_strtolower($this->randomName()),
  223. 'title' => $this->randomName(),
  224. 'flag_short' => 'flag short [node:nid]',
  225. 'flag_long' => 'flag long [node:nid]',
  226. 'flag_message' => 'flag message [node:nid]',
  227. 'unflag_short' => 'unflag short [node:nid]',
  228. 'unflag_long' => 'unflag long [node:nid]',
  229. 'unflag_message' => 'unflag message [node:nid]',
  230. 'roles[flag][2]' => TRUE,
  231. 'roles[unflag][2]' => TRUE,
  232. 'types[article]' => FALSE,
  233. 'types[page]' => TRUE,
  234. 'show_in_links[full]' => FALSE,
  235. 'show_in_links[teaser]' => FALSE,
  236. 'show_in_links[rss]' => FALSE,
  237. 'show_in_links[search_index]' => FALSE,
  238. 'show_in_links[search_result]' => FALSE,
  239. 'show_on_form' => FALSE,
  240. 'link_type' => 'toggle',
  241. );
  242. $saved = $edit;
  243. $saved['roles'] = array('flag' => array(2), 'unflag' => array(2));
  244. $saved['types'] = array('page');
  245. $saved['show_in_links'] = array(
  246. 'full' => 0,
  247. 'teaser' => 0,
  248. 'rss' => 0,
  249. 'search_index' => 0,
  250. 'search_result' => 0,
  251. );
  252. unset($saved['roles[flag][2]'], $saved['roles[unflag][2]'], $saved['types[article]'], $saved['types[page]'], $saved['show_in_links[full]'], $saved['show_in_links[teaser]'], $saved['show_in_links[rss]'], $saved['show_in_links[search_index]'], $saved['show_in_links[search_result]']);
  253. $this->drupalPost(FLAG_ADMIN_PATH . '/add/node', $edit, t('Save flag'));
  254. drupal_static_reset('flag_get_flags');
  255. $flag = flag_get_flag($edit['name']);
  256. // Load the roles array for checking it matches.
  257. $flag->fetch_roles();
  258. // Check that the flag object is in the database.
  259. $this->assertTrue($flag != FALSE, t('Flag object found in database'));
  260. // Check each individual property of the flag and make sure it was set.
  261. foreach ($saved as $property => $value) {
  262. $this->assertEqual($flag->$property, $value, t('Flag property %property properly saved.', array('%property' => $property)));
  263. }
  264. // Check permissions.
  265. $permissions = user_role_permissions(user_roles());
  266. foreach ($saved['roles'] as $action => $rids) {
  267. foreach ($rids as $rid) {
  268. $permission_string = "$action " . $saved['name'];
  269. $this->assertTrue(isset($permissions[$rid][$permission_string]), t('Permission %perm set for flag.', array(
  270. '%perm' => $permission_string,
  271. )));
  272. }
  273. }
  274. // Edit the flag through the UI.
  275. $edit = array(
  276. 'name' => drupal_strtolower($this->randomName()),
  277. 'title' => $this->randomName(),
  278. 'flag_short' => 'flag 2 short [node:nid]',
  279. 'flag_long' => 'flag 2 long [node:nid]',
  280. 'flag_message' => 'flag 2 message [node:nid]',
  281. 'unflag_short' => 'unflag 2 short [node:nid]',
  282. 'unflag_long' => 'unflag 2 long [node:nid]',
  283. 'unflag_message' => 'unflag 2 message [node:nid]',
  284. 'roles[flag][2]' => TRUE,
  285. 'roles[unflag][2]' => TRUE,
  286. 'types[article]' => TRUE,
  287. 'types[page]' => FALSE,
  288. 'show_in_links[full]' => TRUE,
  289. 'show_in_links[teaser]' => TRUE,
  290. 'show_in_links[rss]' => FALSE,
  291. 'show_in_links[search_index]' => FALSE,
  292. 'show_in_links[search_result]' => FALSE,
  293. 'show_on_form' => TRUE,
  294. 'link_type' => 'normal',
  295. );
  296. $saved = $edit;
  297. $saved['roles'] = array('flag' => array(2), 'unflag' => array(2));
  298. $saved['types'] = array('article');
  299. $saved['show_in_links'] = array(
  300. 'full' => TRUE,
  301. 'teaser' => TRUE,
  302. 'rss' => 0,
  303. 'search_index' => 0,
  304. 'search_result' => 0,
  305. );
  306. unset($saved['roles[flag][2]'], $saved['roles[unflag][2]'], $saved['types[article]'], $saved['types[page]'], $saved['show_in_links[full]'], $saved['show_in_links[teaser]'], $saved['show_in_links[rss]'], $saved['show_in_links[search_index]'], $saved['show_in_links[search_result]']);
  307. $this->drupalPost(FLAG_ADMIN_PATH . '/manage/' . $flag->name, $edit, t('Save flag'));
  308. drupal_static_reset('flag_get_flags');
  309. $flag = flag_get_flag($edit['name']);
  310. // Load the roles array for checking it matches.
  311. $flag->fetch_roles();
  312. // Check that the flag object is in the database.
  313. $this->assertTrue($flag != FALSE, t('Flag object found in database'));
  314. // Check each individual property of the flag and make sure it was set.
  315. foreach ($saved as $property => $value) {
  316. $this->assertEqual($flag->$property, $value, t('Flag property %property properly saved.', array('%property' => $property)));
  317. }
  318. // Clear the user access cache so our changes to permissions are noticed.
  319. drupal_static_reset('user_access');
  320. drupal_static_reset('user_role_permissions');
  321. // Check permissions.
  322. $permissions = user_role_permissions(user_roles());
  323. foreach ($saved['roles'] as $action => $rids) {
  324. foreach ($rids as $rid) {
  325. $permission_string = "$action " . $saved['name'];
  326. $this->assertTrue(isset($permissions[$rid][$permission_string]), t('Permission %perm set for flag.', array(
  327. '%perm' => $permission_string,
  328. )));
  329. }
  330. }
  331. // Delete the flag through the UI.
  332. $this->drupalPost(FLAG_ADMIN_PATH . '/manage/' . $flag->name . '/delete', array(), t('Delete'));
  333. drupal_static_reset('flag_get_flags');
  334. $this->assertFalse(flag_get_flag($flag->name), t('Flag successfully deleted.'));
  335. }
  336. }
  337. /**
  338. * Access to flags using the entity forms.
  339. *
  340. * @todo: complete this test class.
  341. */
  342. class FlagAccessFormTestCase extends FlagTestCaseBase {
  343. /**
  344. * Implements getInfo().
  345. */
  346. public static function getInfo() {
  347. return array(
  348. 'name' => 'Access to flags via entity forms',
  349. 'description' => 'Access to flag and unflag entities via entity forms.',
  350. 'group' => 'Flag',
  351. );
  352. }
  353. /**
  354. * Implements setUp().
  355. */
  356. function setUp() {
  357. parent::setUp('flag');
  358. }
  359. /**
  360. * Test scenarios with no access to a global flag.
  361. */
  362. function testFlagAccessGlobalNone() {
  363. // Create a global flag on article nodes.
  364. $flag_data = array(
  365. 'entity_type' => 'node',
  366. 'name' => 'global_flag',
  367. 'title' => 'Global Flag',
  368. 'global' => 1,
  369. 'types' => array(
  370. 0 => 'article',
  371. ),
  372. 'flag_short' => 'Flag this item',
  373. 'flag_long' => '',
  374. 'flag_message' => '',
  375. 'unflag_short' => 'Unflag this item',
  376. 'unflag_long' => '',
  377. 'unflag_message' => '',
  378. 'unflag_denied_text' => 'You may not unflag this item',
  379. 'link_type' => 'normal',
  380. 'weight' => 0,
  381. // Show the flag on the form.
  382. 'show_on_form' => 1,
  383. 'access_author' => '',
  384. 'show_contextual_link' => 0,
  385. 'show_in_links' => array(
  386. 'full' => 1,
  387. 'teaser' => 1,
  388. ),
  389. 'i18n' => 0,
  390. 'api_version' => 3,
  391. );
  392. $flag = $this->createFlag($flag_data);
  393. // Create test user who can't us this flag, but can create nodes.
  394. $no_flag_user = $this->drupalCreateUser(array('create article content'));
  395. $this->drupalLogin($no_flag_user);
  396. $this->drupalGet('node/add/article');
  397. // Check that the flag form element cannot be seen.
  398. $this->assertNoText('Flag this item', t('Flag form element was not found.'));
  399. // Have the user create a node.
  400. $edit = array(
  401. 'title' => 'node 1',
  402. );
  403. $this->drupalPost('node/add/article', $edit, t('Save'));
  404. $node = $this->drupalGetNodeByTitle($edit["title"]);
  405. // Check the new node has not been flagged.
  406. $this->assertFalse($flag->is_flagged($node->nid), t('New node is not flagged.'));
  407. // Now set the variable so that the flag is set by default on new nodes.
  408. variable_set('flag_' . $flag->name . '_default_' . 'article', 1);
  409. // Create another new node.
  410. $edit = array(
  411. 'title' => 'node 2',
  412. );
  413. $this->drupalPost('node/add/article', $edit, t('Save'));
  414. $node = $this->drupalGetNodeByTitle($edit["title"]);
  415. // Check the new node has been flagged, despite the user not having access
  416. // to the flag.
  417. $this->assertTrue($flag->is_flagged($node->nid), t('New node is flagged.'));
  418. }
  419. }
  420. /**
  421. * Tokens we provide on generic entities.
  422. */
  423. class FlagEntityTokensTestCase extends FlagTestCaseBase {
  424. /**
  425. * Implements getInfo().
  426. */
  427. public static function getInfo() {
  428. return array(
  429. 'name' => 'Entity tokens',
  430. 'description' => 'Tokens for flag count on entities.',
  431. 'group' => 'Flag',
  432. );
  433. }
  434. /**
  435. * Implements setUp().
  436. */
  437. function setUp() {
  438. // Our entity tokens require token module.
  439. parent::setUp('flag', 'token');
  440. }
  441. /**
  442. * Test tokens on nodes.
  443. */
  444. function testNodeFlagToken() {
  445. // Create a flag on article nodes.
  446. $flag_data = array(
  447. 'entity_type' => 'node',
  448. 'name' => 'node_flag',
  449. 'title' => 'Node Flag',
  450. 'global' => 0,
  451. 'types' => array(
  452. 0 => 'article',
  453. ),
  454. 'flag_short' => 'Flag this item',
  455. 'flag_long' => '',
  456. 'flag_message' => '',
  457. 'unflag_short' => 'Unflag this item',
  458. 'unflag_long' => '',
  459. 'unflag_message' => '',
  460. 'unflag_denied_text' => 'You may not unflag this item',
  461. 'link_type' => 'normal',
  462. 'weight' => 0,
  463. // Show the flag on the form.
  464. 'show_on_form' => 1,
  465. 'access_author' => '',
  466. 'show_contextual_link' => 0,
  467. 'show_in_links' => array(
  468. 'full' => 1,
  469. 'teaser' => 1,
  470. ),
  471. 'i18n' => 0,
  472. 'api_version' => 3,
  473. );
  474. $flag = $this->createFlag($flag_data);
  475. // Create a node to flag.
  476. $node = (object) array(
  477. 'type' => 'article',
  478. 'title' => $this->randomName(),
  479. );
  480. node_save($node);
  481. // Flag it by several users.
  482. $flag_user_1 = $this->drupalCreateUser(array('flag node_flag',));
  483. // Flag the node as the user.
  484. $flag = flag_get_flag('node_flag');
  485. $flag->flag('flag', $node->nid, $flag_user_1);
  486. $flag_user_2 = $this->drupalCreateUser(array('flag node_flag',));
  487. // Flag the node as the user.
  488. $flag->flag('flag', $node->nid, $flag_user_2);
  489. $text = '[node:flag-node-flag-count]';
  490. $replaced_text = token_replace($text, array('node' => $node));
  491. $this->assertEqual($replaced_text, 2, "The flag count token for the node is correct.");
  492. }
  493. /**
  494. * Test tokens on taxonomy terms.
  495. *
  496. * These are worthy of a separate test, as the token type is a special case.
  497. */
  498. function testTaxonomyTermFlagToken() {
  499. // Create a flag on tag terms.
  500. $flag_data = array(
  501. 'entity_type' => 'taxonomy_term',
  502. 'name' => 'term_flag',
  503. 'title' => 'Term Flag',
  504. 'global' => 0,
  505. 'types' => array(
  506. 0 => 'tags',
  507. ),
  508. 'flag_short' => 'Flag this item',
  509. 'flag_long' => '',
  510. 'flag_message' => '',
  511. 'unflag_short' => 'Unflag this item',
  512. 'unflag_long' => '',
  513. 'unflag_message' => '',
  514. 'unflag_denied_text' => 'You may not unflag this item',
  515. 'link_type' => 'normal',
  516. 'weight' => 0,
  517. // Show the flag on the form.
  518. 'show_on_form' => 1,
  519. 'access_author' => '',
  520. 'show_contextual_link' => 0,
  521. 'show_in_links' => array(
  522. 'full' => 1,
  523. 'teaser' => 1,
  524. ),
  525. 'i18n' => 0,
  526. 'api_version' => 3,
  527. );
  528. $flag = $this->createFlag($flag_data);
  529. $vocabulary = taxonomy_vocabulary_load(1);
  530. // Create a term to flag.
  531. $term = (object) array(
  532. 'name' => $this->randomName(),
  533. 'vid' => 1,
  534. );
  535. taxonomy_term_save($term);
  536. // Flag it by several users.
  537. $flag_user_1 = $this->drupalCreateUser(array('flag term_flag',));
  538. // Flag the term as the user.
  539. $flag = flag_get_flag('term_flag');
  540. $flag->flag('flag', $term->tid, $flag_user_1);
  541. $flag_user_2 = $this->drupalCreateUser(array('flag term_flag',));
  542. // Flag the term as the user.
  543. $flag = flag_get_flag('term_flag');
  544. $flag->flag('flag', $term->tid, $flag_user_2);
  545. $text = '[term:flag-term-flag-count]';
  546. $replaced_text = token_replace($text, array('term' => $term));
  547. debug($replaced_text);
  548. $this->assertEqual($replaced_text, 2, "The flag count token for the term is correct.");
  549. }
  550. }
  551. /**
  552. * Access to flags using the basic flag link.
  553. */
  554. class FlagAccessLinkTestCase extends FlagTestCaseBase {
  555. /**
  556. * Implements getInfo().
  557. */
  558. public static function getInfo() {
  559. return array(
  560. 'name' => 'Access to flags via basic link',
  561. 'description' => 'Access to flag and unflag entities using the basic link.',
  562. 'group' => 'Flag',
  563. );
  564. }
  565. /**
  566. * Implements setUp().
  567. */
  568. function setUp() {
  569. parent::setUp('flag');
  570. // Create a test flag on article nodes.
  571. $flag_data = array(
  572. 'entity_type' => 'node',
  573. 'name' => 'test_flag',
  574. 'title' => 'Test Flag',
  575. 'global' => 0,
  576. 'types' => array(
  577. 0 => 'article',
  578. ),
  579. 'flag_short' => 'Flag this item',
  580. 'flag_long' => '',
  581. 'flag_message' => '',
  582. 'unflag_short' => 'Unflag this item',
  583. 'unflag_long' => '',
  584. 'unflag_message' => '',
  585. 'unflag_denied_text' => 'You may not unflag this item',
  586. // Use the normal link type as it involves no intermediary page loads.
  587. 'link_type' => 'normal',
  588. 'weight' => 0,
  589. 'show_on_form' => 0,
  590. 'access_author' => '',
  591. 'show_contextual_link' => 0,
  592. 'show_in_links' => array(
  593. 'full' => 1,
  594. 'teaser' => 1,
  595. ),
  596. 'i18n' => 0,
  597. 'api_version' => 3,
  598. );
  599. $flag = $this->createFlag($flag_data);
  600. // Create an article node that various users will try to flag.
  601. $title = $this->randomName(8);
  602. $node = array(
  603. 'title' => $title,
  604. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  605. 'uid' => 1,
  606. 'type' => 'article',
  607. 'is_new' => TRUE,
  608. );
  609. $node = node_submit((object) $node);
  610. node_save($node);
  611. $this->nid = $node->nid;
  612. }
  613. /**
  614. * Test that a user without flag access can't see the flag.
  615. */
  616. function testFlagAccessNone() {
  617. // Create test user who can't flag at all.
  618. $no_flag_user = $this->drupalCreateUser(array());
  619. $this->drupalLogin($no_flag_user);
  620. // Look at our node.
  621. $this->drupalGet('node/' . $this->nid);
  622. $this->assertNoLink('Flag this item', 0, 'The flag link does not appear on the page');
  623. }
  624. /**
  625. * Test that a user with only flag access can flag but not unflag.
  626. */
  627. function testFlagAccessFlagOnly() {
  628. // Create test user who can flag but not unflag.
  629. $flag_user = $this->drupalCreateUser(array('flag test_flag',));
  630. $this->drupalLogin($flag_user);
  631. // Look at our node.
  632. $this->drupalGet('node/' . $this->nid);
  633. $this->assertLink('Flag this item', 0, 'The flag link appears on the page.');
  634. // Click the link to flag the node.
  635. $this->clickLink(t('Flag this item'));
  636. $this->assertText('You may not unflag this item', 0, 'The unflag denied text appears on the page after flagging.');
  637. }
  638. /**
  639. * Test that a user with flag access can flag and unflag.
  640. */
  641. function testFlagAccessFlagUnflag() {
  642. // Create test user who can flag and unflag.
  643. $flag_unflag_user = $this->drupalCreateUser(array('flag test_flag', 'unflag test_flag'));
  644. $this->drupalLogin($flag_unflag_user);
  645. // Look at our node.
  646. $this->drupalGet('node/' . $this->nid);
  647. $this->assertLink('Flag this item', 0, 'The flag link appears on the page.');
  648. // Click the link to flag the node.
  649. $this->clickLink(t('Flag this item'));
  650. $this->assertLink('Unflag this item', 0, 'The unflag link appears on the page after flagging.');
  651. // Click the link to unflag the node.
  652. $this->clickLink(t('Unflag this item'));
  653. $this->assertLink('Flag this item', 0, 'The flag link appears on the page after unflagging.');
  654. }
  655. }
  656. /**
  657. * Test the 'confirm form' link type.
  658. */
  659. class FlagLinkTypeConfirmTestCase extends DrupalWebTestCase {
  660. /**
  661. * Implements getInfo().
  662. */
  663. public static function getInfo() {
  664. return array(
  665. 'name' => 'Confirm form',
  666. 'description' => 'Flag confirm form link type.',
  667. 'group' => 'Flag',
  668. );
  669. }
  670. /**
  671. * Implements setUp().
  672. */
  673. function setUp() {
  674. parent::setUp('flag');
  675. // Create a test flag on article nodes.
  676. // Keep the original data so we can compare strings.
  677. $this->flag_data = array(
  678. 'entity_type' => 'node',
  679. 'name' => 'test_flag',
  680. 'title' => 'Test Flag',
  681. 'global' => 0,
  682. 'types' => array(
  683. 0 => 'article',
  684. ),
  685. 'flag_short' => 'Flag <em>this</em> item',
  686. 'flag_long' => '',
  687. 'flag_message' => 'You have flagged this item.',
  688. 'unflag_short' => 'Unflag this item',
  689. 'unflag_long' => '',
  690. 'unflag_message' => 'You have unflagged this item',
  691. 'unflag_denied_text' => 'You may not unflag this item',
  692. 'link_type' => 'confirm',
  693. 'flag_confirmation' => 'Are you sure you want to flag this item?',
  694. 'unflag_confirmation' => 'Are you sure you want to unflag this item?',
  695. 'weight' => 0,
  696. 'show_on_form' => 0,
  697. 'access_author' => '',
  698. 'show_contextual_link' => 0,
  699. 'show_in_links' => array(
  700. 'full' => 1,
  701. 'teaser' => 1,
  702. ),
  703. 'i18n' => 0,
  704. 'api_version' => 3,
  705. );
  706. $this->flag = flag_flag::factory_by_array($this->flag_data);
  707. $this->flag->save();
  708. // Reset our cache so our permissions show up.
  709. drupal_static_reset('flag_get_flags');
  710. // Reset permissions so that permissions for this flag are available.
  711. $this->checkPermissions(array(), TRUE);
  712. // Create test user who can flag and unflag.
  713. $this->flag_unflag_user = $this->drupalCreateUser(array('flag test_flag', 'unflag test_flag'));
  714. $this->drupalLogin($this->flag_unflag_user);
  715. // Create an article node to flag and unflag.
  716. $title = $this->randomName(8);
  717. $node = array(
  718. 'title' => $title,
  719. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  720. 'uid' => 1,
  721. 'type' => 'article',
  722. 'is_new' => TRUE,
  723. );
  724. $node = node_submit((object) $node);
  725. node_save($node);
  726. $this->nid = $node->nid;
  727. }
  728. /**
  729. * Test usage of the flag confirm form.
  730. */
  731. function testFlag() {
  732. // Look at our node.
  733. $this->drupalGet('node/' . $this->nid);
  734. $flag_short_label = strip_tags($this->flag_data['flag_short']);
  735. $this->assertRaw($this->flag_data['flag_short'], 'The flag text, including HTML, appears on the page.');
  736. // assertLink() appears to have interesting problems dealing with an A
  737. // element which contains other tags. However, the xpath it uses appears to
  738. // be fine with being given just the portion of the link text that comes
  739. // before the interior tag.
  740. // Fortunately, there will be no other text on the page that matches 'Flag'.
  741. $this->assertLink('Flag', 0, 'The flag link appears on the page.');
  742. // Click the link to flag the node.
  743. // clickLink() has the same problem, as it uses the same xpath expression as
  744. // assertLink().
  745. $this->clickLink('Flag');
  746. $this->assertUrl('flag/confirm/flag/test_flag/' . $this->nid, array(
  747. 'query' => array(
  748. 'destination' => 'node/' . $this->nid,
  749. ),
  750. ), 'On confirm flagging form page.');
  751. $this->assertText($this->flag_data['flag_confirmation'], 'The flag confirmation text appears as the confirmation page title.');
  752. $this->assertPattern('@<input [^>]* value="' . $flag_short_label . '" [^>]*>@', 'The flag text, excluding HTML, is shown in the button.');
  753. // Click the button to confirm the flagging.
  754. $this->drupalPost(NULL, array(), $flag_short_label);
  755. $this->assertText($this->flag_data['flag_message'], 'The flag message appears once the item has been flagged.');
  756. $this->assertLink($this->flag_data['unflag_short'], 0, 'The unflag link appears once the item has been flagged.');
  757. // Reset the static cache before we get data from it.
  758. drupal_static_reset('flag_get_user_flags');
  759. $this->assertTrue($this->flag->is_flagged($this->nid, $this->flag_unflag_user->uid), "The node is recorded as flagged by the user.");
  760. // Click the link to unflag the node.
  761. $this->clickLink($this->flag_data['unflag_short']);
  762. $this->assertUrl('flag/confirm/unflag/test_flag/' . $this->nid, array(
  763. 'query' => array(
  764. 'destination' => 'node/' . $this->nid,
  765. ),
  766. ), t('On confirm unflagging form page.'));
  767. $this->assertText($this->flag_data['unflag_confirmation'], 'The unflag confirmation text appears as the confirmation page title.');
  768. // Click the button to confirm the flagging.
  769. $this->drupalPost(NULL, array(), $this->flag_data['unflag_short']);
  770. $this->assertText($this->flag_data['unflag_message'], 'The unflag message appears once the item has been flagged.');
  771. // Reset the static cache before we get data from it.
  772. drupal_static_reset('flag_get_user_flags');
  773. $this->assertFalse($this->flag->is_flagged($this->nid, $this->flag_unflag_user->uid), "The node is recorded as not flagged by the user.");
  774. }
  775. }
  776. /**
  777. * Verifies the implementation of hook_flag_access().
  778. */
  779. class FlagHookFlagAccessTestCase extends FlagTestCaseBase {
  780. /**
  781. * Implements getInfo().
  782. */
  783. public static function getInfo() {
  784. return array(
  785. 'name' => 'hook_flag_access()',
  786. 'description' => 'Checks the ability of modules to use hook_flag_access().',
  787. 'group' => 'Flag',
  788. );
  789. }
  790. /**
  791. * Implements setUp().
  792. */
  793. function setUp() {
  794. parent::setUp('flag');
  795. $success = module_enable(array('flagaccesstest'), FALSE);
  796. // Create a test flag on article nodes.
  797. $flag_data = array(
  798. 'entity_type' => 'node',
  799. 'name' => 'test_flag',
  800. 'title' => 'Test Flag',
  801. 'global' => 0,
  802. 'types' => array(
  803. 0 => 'article',
  804. ),
  805. 'flag_short' => 'Flag this item',
  806. 'flag_long' => '',
  807. 'flag_message' => '',
  808. 'unflag_short' => 'Unflag this item',
  809. 'unflag_long' => '',
  810. 'unflag_message' => '',
  811. 'unflag_denied_text' => 'You may not unflag this item',
  812. // Use the normal link type as it involves no intermediary page loads.
  813. 'link_type' => 'normal',
  814. 'weight' => 0,
  815. 'show_on_form' => 0,
  816. 'access_author' => '',
  817. 'show_contextual_link' => 0,
  818. 'show_in_links' => array(
  819. 'full' => 1,
  820. 'teaser' => 1,
  821. ),
  822. 'i18n' => 0,
  823. 'api_version' => 3,
  824. );
  825. $flag = $this->createFlag($flag_data);
  826. // Create an article node that various users will try to flag.
  827. $title = $this->randomName(8);
  828. $node = array(
  829. 'title' => $title,
  830. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  831. 'uid' => 1,
  832. 'type' => 'article',
  833. 'is_new' => TRUE,
  834. );
  835. $node = node_submit((object) $node);
  836. node_save($node);
  837. $this->nid = $node->nid;
  838. }
  839. /**
  840. * Verifies that the user sees the flag if a module returns NULL (Ignore).
  841. */
  842. function testFlagAccessIgnore() {
  843. variable_set('FlagHookFlagAccessTestCaseMode', 'ignore');
  844. $flag_user = $this->drupalCreateUser(array('flag test_flag', 'unflag test_flag'));
  845. $this->drupalLogin($flag_user);
  846. // Look at our node.
  847. $this->drupalGet('node/' . $this->nid);
  848. $this->assertLink('Flag this item', 0, 'The flag link appears on the page.');
  849. // Click the link to flag the node.
  850. $this->clickLink(t('Flag this item'));
  851. $this->assertLink('Unflag this item', 0, 'The unflag link appears on the page after flagging.');
  852. // Click the link to unflag the node.
  853. $this->clickLink(t('Unflag this item'));
  854. $this->assertLink('Flag this item', 0, 'The flag link appears on the page after unflagging.');
  855. }
  856. /**
  857. * Verifies that the user sees the flag if a module returns TRUE (Allow).
  858. */
  859. function testFlagAccessAllow() {
  860. variable_set('FlagHookFlagAccessTestCaseMode', 'allow');
  861. $flag_user = $this->drupalCreateUser(array('flag test_flag', 'unflag test_flag'));
  862. $this->drupalLogin($flag_user);
  863. // Look at our node.
  864. $this->drupalGet('node/' . $this->nid);
  865. $this->assertLink('Flag this item', 0, 'The flag link appears on the page.');
  866. // Click the link to flag the node.
  867. $this->clickLink(t('Flag this item'));
  868. $this->assertLink('Unflag this item', 0, 'The unflag link appears on the page after flagging.');
  869. // Click the link to unflag the node.
  870. $this->clickLink(t('Unflag this item'));
  871. $this->assertLink('Flag this item', 0, 'The flag link appears on the page after unflagging.');
  872. }
  873. /**
  874. * Verifies that the user sees the flag if a module returns TRUE (Allow) to
  875. * override default access check.
  876. */
  877. function testFlagAccessAllowOverride() {
  878. variable_set('FlagHookFlagAccessTestCaseMode', 'allow');
  879. $flag_user = $this->drupalCreateUser(array());
  880. $this->drupalLogin($flag_user);
  881. // Look at our node.
  882. $this->drupalGet('node/' . $this->nid);
  883. $this->assertLink('Flag this item', 0, 'The flag link appears on the page.');
  884. // Click the link to flag the node.
  885. $this->clickLink(t('Flag this item'));
  886. $this->assertLink('Unflag this item', 0, 'The unflag link appears on the page after flagging.');
  887. // Click the link to unflag the node.
  888. $this->clickLink(t('Unflag this item'));
  889. $this->assertLink('Flag this item', 0, 'The flag link appears on the page after unflagging.');
  890. }
  891. /**
  892. * Verifies that the user does not see the flag if a module returns FALSE
  893. * (Deny).
  894. */
  895. function testFlagAccessDeny() {
  896. variable_set('FlagHookFlagAccessTestCaseMode', 'deny');
  897. $flag_user = $this->drupalCreateUser(array('flag test_flag', 'unflag test_flag'));
  898. $this->drupalLogin($flag_user);
  899. // Look at our node.
  900. $this->drupalGet('node/' . $this->nid);
  901. $this->assertNoLink('Flag this item', 0, 'The flag link does not appear on the page.');
  902. }
  903. }
  904. /**
  905. * Test use of fields on flagging entities.
  906. */
  907. class FlagFlaggingFieldTestCase extends FlagTestCaseBase {
  908. /**
  909. * Implements getInfo().
  910. */
  911. public static function getInfo() {
  912. return array(
  913. 'name' => 'Flagging fields',
  914. 'description' => 'Fields on Flagging entities.',
  915. 'group' => 'Flag',
  916. );
  917. }
  918. /**
  919. * Implements setUp().
  920. */
  921. function setUp() {
  922. parent::setUp('flag', 'flag_fields_test');
  923. }
  924. function testFlaggingFields() {
  925. $this->assertTrue(1);
  926. $flag_user = $this->drupalCreateUser(array(
  927. 'flag flag_fields_test_flag',
  928. 'unflag flag_fields_test_flag',
  929. ));
  930. $this->drupalLogin($flag_user);
  931. $node = $this->drupalCreateNode();
  932. $this->drupalGet('node/' . $node->nid);
  933. $this->clickLink('Flag with the test flag');
  934. // Try to fail the form validation by providing something non-numeric.
  935. // This validation is only present in the widget validation: this is a core
  936. // bug, but lets us test widget validation works correctly until it's fixed.
  937. $edit = array(
  938. 'flag_fields_test_integer[und][0][value]' => 'banana',
  939. );
  940. $this->drupalPost(NULL, $edit, 'Flag with the test flag');
  941. $this->assertText("Only numbers are allowed in Test integer.", "Form validation correctly failed the input.");
  942. // Try to fail the form validation by a number that's out of bounds.
  943. $edit = array(
  944. 'flag_fields_test_integer[und][0][value]' => 12,
  945. );
  946. $this->drupalPost(NULL, $edit, 'Flag with the test flag');
  947. $this->assertText("Test integer: the value may be no greater than 11.", "Form validation correctly failed the input.");
  948. $edit = array(
  949. 'flag_fields_test_integer[und][0][value]' => 6,
  950. );
  951. $this->drupalPost(NULL, $edit, 'Flag with the test flag');
  952. $this->assertUrl('node/' . $node->nid, array(), "The flagging form submission succeeded.");
  953. // Try to load the flagging, querying for the field value.
  954. $query = new EntityFieldQuery();
  955. $query->entityCondition('entity_type', 'flagging')
  956. ->entityCondition('bundle', 'flag_fields_test_flag')
  957. ->propertyCondition('entity_id', $node->nid)
  958. ->fieldCondition('flag_fields_test_integer', 'value', 6);
  959. $result = $query->execute();
  960. $this->assertEqual(count($result['flagging']), 1, "The Flagging entity was found with the correct field values.");
  961. }
  962. }
  963. /**
  964. * Test use of EntityFieldQueries with flagging entities.
  965. */
  966. class FlagEntityFieldQueryTestCase extends FlagTestCaseBase {
  967. /**
  968. * Implements getInfo().
  969. */
  970. public static function getInfo() {
  971. return array(
  972. 'name' => 'Entity Field Query',
  973. 'description' => 'Entity Field Query for flagging entities.',
  974. 'group' => 'Flag',
  975. );
  976. }
  977. /**
  978. * Implements setUp().
  979. */
  980. function setUp() {
  981. parent::setUp('flag');
  982. $flag_data = array(
  983. 'entity_type' => 'node',
  984. 'name' => 'test_flag_1',
  985. 'title' => 'Test Flag',
  986. 'global' => 0,
  987. 'types' => array(
  988. 0 => 'article',
  989. ),
  990. 'flag_short' => 'Flag this item',
  991. 'flag_long' => '',
  992. 'flag_message' => '',
  993. 'unflag_short' => 'Unflag this item',
  994. 'unflag_long' => '',
  995. 'unflag_message' => '',
  996. 'unflag_denied_text' => 'You may not unflag this item',
  997. // Use the normal link type as it involves no intermediary page loads.
  998. 'link_type' => 'normal',
  999. 'weight' => 0,
  1000. 'show_on_form' => 0,
  1001. 'access_author' => '',
  1002. 'show_contextual_link' => 0,
  1003. 'show_in_links' => array(
  1004. 'full' => 1,
  1005. 'teaser' => 1,
  1006. ),
  1007. 'i18n' => 0,
  1008. 'api_version' => 3,
  1009. );
  1010. $this->flag1 = $this->createFlag($flag_data);
  1011. $flag_data['name'] = 'test_flag_2';
  1012. $this->flag2 = $this->createFlag($flag_data);
  1013. $flag_data['name'] = 'test_flag_3';
  1014. $this->flag3 = $this->createFlag($flag_data);
  1015. // Create test user who can flag and unflag.
  1016. $this->flag_unflag_user = $this->drupalCreateUser(array(
  1017. 'flag test_flag_1',
  1018. 'unflag test_flag_1',
  1019. 'flag test_flag_2',
  1020. 'unflag test_flag_2',
  1021. ));
  1022. $this->drupalLogin($this->flag_unflag_user);
  1023. }
  1024. /**
  1025. * Test use of EntityFieldQuery with flagging entities.
  1026. */
  1027. function testEntityFieldQuery() {
  1028. $node_settings = array(
  1029. 'title' => $this->randomName(),
  1030. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  1031. 'uid' => 1,
  1032. 'type' => 'article',
  1033. 'is_new' => TRUE,
  1034. );
  1035. $node = $this->drupalCreateNode($node_settings);
  1036. flag('flag', 'test_flag_1', $node->nid, $this->flag_unflag_user);
  1037. flag('flag', 'test_flag_2', $node->nid, $this->flag_unflag_user);
  1038. $query = new EntityFieldQuery();
  1039. $query->entityCondition('entity_type', 'flagging')
  1040. ->entityCondition('bundle', 'test_flag_1');
  1041. $flagged = $query->execute();
  1042. $this->assertEqual(count($flagged['flagging']), 1);
  1043. $query = new EntityFieldQuery();
  1044. $query->entityCondition('entity_type', 'flagging')
  1045. ->entityCondition('bundle', 'test%', 'like');
  1046. $flagged = $query->execute();
  1047. $this->assertEqual(count($flagged['flagging']), 2);
  1048. $query = new EntityFieldQuery();
  1049. $query->entityCondition('entity_type', 'flagging')
  1050. ->entityCondition('bundle', array('test_flag_1', 'test_flag_2'), 'IN');
  1051. $this->assertEqual(count($flagged['flagging']), 2);
  1052. }
  1053. }
  1054. /**
  1055. * Verifies the invocation of hooks when performing flagging and unflagging.
  1056. */
  1057. class FlagHookInvocationsTestCase extends FlagTestCaseBase {
  1058. /**
  1059. * Implements getInfo().
  1060. */
  1061. public static function getInfo() {
  1062. return array(
  1063. 'name' => 'Hook invocations',
  1064. 'description' => 'Invocation of flag and entity hooks and rules during flagging and unflagging.',
  1065. 'group' => 'Flag',
  1066. );
  1067. }
  1068. /**
  1069. * Implements setUp().
  1070. */
  1071. function setUp() {
  1072. parent::setUp('flag', 'rules', 'flag_hook_test');
  1073. // Note the test module contains our test flag.
  1074. // Create test user who can flag and unflag.
  1075. $this->flag_unflag_user = $this->drupalCreateUser(array('flag flag_hook_test_flag', 'unflag flag_hook_test_flag'));
  1076. $this->drupalLogin($this->flag_unflag_user);
  1077. }
  1078. /**
  1079. * Test invocation of hooks and their data during flagging and unflagging.
  1080. *
  1081. * For each operation (flagging, re-flagging, unflagging) we test:
  1082. * - the order in which Flag hooks, entity hooks, and rules are invoked.
  1083. * - the parameters each hook receives
  1084. * - the data that a hook implementation obtains when it calls the Flag data
  1085. * API functions.
  1086. */
  1087. function testHookInvocation() {
  1088. // Create an article node that we try to create a flagging entity for.
  1089. $title = $this->randomName(8);
  1090. $node = array(
  1091. 'title' => $title,
  1092. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  1093. 'uid' => 1,
  1094. 'type' => 'article',
  1095. 'is_new' => TRUE,
  1096. );
  1097. $node = node_submit((object) $node);
  1098. node_save($node);
  1099. // Initialize a tracking variable. The test module will update this when
  1100. // its hooks are invoked.
  1101. variable_set('flag_hook_test_hook_tracking', array());
  1102. // Flag the node as the user.
  1103. $flag = flag_get_flag('flag_hook_test_flag');
  1104. $flag->flag('flag', $node->nid, $this->flag_unflag_user);
  1105. // Get the variable the test module sets the hook order into.
  1106. $hook_data_variable = variable_get('flag_hook_test_hook_tracking', array());
  1107. //debug($hook_data_variable['hook_entity_presave']);
  1108. //debug($hook_data_variable['hook_entity_insert']);
  1109. $expected_hook_order = array(
  1110. 'hook_entity_presave',
  1111. 'hook_entity_insert',
  1112. 'hook_flag_flag',
  1113. 'rules_event',
  1114. );
  1115. // Check the hooks are invoked in the correct order.
  1116. $this->assertIdentical($expected_hook_order, array_keys($hook_data_variable), "The hooks are invoked in the correct order when flagging a node.");
  1117. // Check the parameters received by hook_entity_presave().
  1118. // Param 0: $flagging.
  1119. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->flag_name, $flag->name, "The Flagging entity passed to hook_entity_presave() has the expected flag name property.");
  1120. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->fid, $flag->fid, "The Flagging entity passed to hook_entity_presave() has the expected fid property.");
  1121. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->entity_type, 'node', "The Flagging entity passed to hook_entity_presave() has the expected entity type property.");
  1122. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->entity_id, $node->nid, "The Flagging entity passed to hook_entity_presave() has the expected entity ID property.");
  1123. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->uid, $this->flag_unflag_user->uid, "The Flagging entity passed to hook_entity_presave() has the expected uid property.");
  1124. // Param 1: $entity_type.
  1125. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][1], 'flagging', "hook_entity_presave() is passed the correct entity type.");
  1126. // Check the API data available to hook_entity_presave().
  1127. //debug($hook_data_variable['hook_entity_presave']['api_calls']);
  1128. $this->assertEqual($hook_data_variable['hook_entity_presave']['api_calls']['flag_get_entity_flags'], array(), "hook_entity_presave() gets no data from from flag_get_entity_flags(), as the flagging has not yet taken place.");
  1129. $this->assertEqual($hook_data_variable['hook_entity_presave']['api_calls']['flag_get_user_flags'], array(), "hook_entity_presave() gets no data from from flag_get_user_flags(), as the flagging has not yet taken place.");
  1130. // The flag counts have not yet been increased.
  1131. $this->assertEqual($hook_data_variable['hook_entity_presave']['api_calls']['flag_get_counts'], array(), "hook_entity_presave() gets no data from from flag_get_counts(), as the flagging has not yet taken place.");
  1132. $this->assertEqual($hook_data_variable['hook_entity_presave']['api_calls']['flag_get_flag_counts'], 0, "hook_entity_presave() gets no data from from flag_get_flag_counts(), as the flagging has not yet taken place.");
  1133. $this->assertEqual($hook_data_variable['hook_entity_presave']['api_calls']['flag_get_entity_flag_counts'], 0, "hook_entity_presave() gets no data from from flag_get_entity_flag_counts(), as the flagging has not yet taken place.");
  1134. $this->assertEqual($hook_data_variable['hook_entity_presave']['api_calls']['flag_get_user_flag_counts'], 0, "hook_entity_presave() gets no data from from flag_get_user_flag_counts(), as the flagging has not yet taken place.");
  1135. // Check the parameters received by hook_entity_insert().
  1136. // Param 0: $flagging.
  1137. $this->assertEqual($hook_data_variable['hook_entity_insert']['parameters'][0]->flag_name, $flag->name, "The Flagging entity passed to hook_entity_insert() has the expected flag name property.");
  1138. $this->assertEqual($hook_data_variable['hook_entity_insert']['parameters'][0]->fid, $flag->fid, "The Flagging entity passed to hook_entity_insert() has the expected fid property.");
  1139. $this->assertEqual($hook_data_variable['hook_entity_insert']['parameters'][0]->entity_type, 'node', "The Flagging entity passed to hook_entity_insert() has the expected entity type property.");
  1140. $this->assertEqual($hook_data_variable['hook_entity_insert']['parameters'][0]->entity_id, $node->nid, "The Flagging entity passed to hook_entity_insert() has the expected entity ID property.");
  1141. $this->assertEqual($hook_data_variable['hook_entity_insert']['parameters'][0]->uid, $this->flag_unflag_user->uid, "The Flagging entity passed to hook_entity_insert() has the expected uid property.");
  1142. $this->assertTrue(!empty($hook_data_variable['hook_entity_insert']['parameters'][0]->flagging_id), "The Flagging entity passed to hook_entity_insert() has the flagging ID set.");
  1143. // Param 1: $entity_type.
  1144. $this->assertEqual($hook_data_variable['hook_entity_insert']['parameters'][1], 'flagging', "hook_entity_insert() is passed the correct entity type.");
  1145. // Check the API data available to hook_entity_insert().
  1146. //debug($hook_data_variable['hook_entity_insert']['api_calls']);
  1147. $flag_get_entity_flags = $hook_data_variable['hook_entity_insert']['api_calls']['flag_get_entity_flags'];
  1148. $flag_get_entity_flags_uids = array_keys($flag_get_entity_flags);
  1149. $this->assertEqual($flag_get_entity_flags_uids, array($this->flag_unflag_user->uid), "hook_entity_insert() gets correct data for flagging users from flag_get_entity_flags()");
  1150. $flag_get_entity_flags_flagging = $flag_get_entity_flags[$this->flag_unflag_user->uid];
  1151. $this->assertEqual($flag_get_entity_flags_flagging->fid, $flag->fid, "hook_entity_insert() gets a correct fid on the Flagging obtained from flag_get_entity_flags()");
  1152. $this->assertEqual($flag_get_entity_flags_flagging->entity_type, 'node', "hook_entity_insert() gets a correct entity type on the Flagging obtained from flag_get_entity_flags()");
  1153. $this->assertEqual($flag_get_entity_flags_flagging->entity_id, $node->nid, "hook_entity_insert() gets a correct entity ID on the Flagging obtained from flag_get_entity_flags()");
  1154. $flag_get_user_flags = $hook_data_variable['hook_entity_insert']['api_calls']['flag_get_user_flags'];
  1155. $flag_get_user_flags_flagging = $flag_get_user_flags[$flag->name];
  1156. $this->assertEqual($flag_get_user_flags_flagging->fid, $flag->fid, "hook_entity_insert() gets a correct fid on the Flagging obtained from flag_get_user_flags()");
  1157. $this->assertEqual($flag_get_user_flags_flagging->entity_type, 'node', "hook_entity_insert() gets a correct entity type on the Flagging obtained from flag_get_user_flags()");
  1158. $this->assertEqual($flag_get_user_flags_flagging->entity_id, $node->nid, "hook_entity_insert() gets a correct entity ID on the Flagging obtained from flag_get_user_flags()");
  1159. // The flag counts have been increased.
  1160. $flag_get_counts = $hook_data_variable['hook_entity_insert']['api_calls']['flag_get_counts'];
  1161. $this->assertEqual($flag_get_counts[$flag->name], 1, "hook_entity_insert() gets a correct flag count from flag_get_counts().");
  1162. $flag_get_flag_counts = $hook_data_variable['hook_entity_insert']['api_calls']['flag_get_flag_counts'];
  1163. $this->assertEqual($flag_get_flag_counts, 1, "hook_entity_insert() gets a correct flag count from flag_get_flag_counts().");
  1164. $flag_get_entity_flag_counts = $hook_data_variable['hook_entity_insert']['api_calls']['flag_get_entity_flag_counts'];
  1165. $this->assertEqual($flag_get_entity_flag_counts, 1, "hook_entity_insert() gets a correct flag count from flag_get_entity_flag_counts().");
  1166. $flag_get_user_flag_counts = $hook_data_variable['hook_entity_insert']['api_calls']['flag_get_user_flag_counts'];
  1167. $this->assertEqual($flag_get_user_flag_counts, 1, "hook_entity_insert() gets a correct flag count from flag_get_user_flag_counts().");
  1168. // Check the parameters received by hook_flag_flag().
  1169. // Param 0: $flag.
  1170. $this->assertEqual($hook_data_variable['hook_flag_flag']['parameters'][0], $flag, "The flag object is passed to hook_flag_flag().");
  1171. // Param 1: $entity_id.
  1172. $this->assertEqual($hook_data_variable['hook_flag_flag']['parameters'][1], $node->nid, "The entity ID is passed to hook_flag_flag().");
  1173. // Param 2: $account.
  1174. $this->assertEqual($hook_data_variable['hook_flag_flag']['parameters'][2]->uid, $this->flag_unflag_user->uid, "The user account is passed to hook_flag_flag().");
  1175. // Param 3: $flagging.
  1176. $this->assertEqual($hook_data_variable['hook_flag_flag']['parameters'][3]->flag_name, $flag->name, "The Flagging entity passed to hook_flag_flag() has the expected flag name property.");
  1177. $this->assertEqual($hook_data_variable['hook_flag_flag']['parameters'][3]->fid, $flag->fid, "The Flagging entity passed to hook_flag_flag() has the expected fid property.");
  1178. $this->assertEqual($hook_data_variable['hook_flag_flag']['parameters'][3]->entity_type, 'node', "The Flagging entity passed to hook_flag_flag() has the expected entity type property.");
  1179. $this->assertEqual($hook_data_variable['hook_flag_flag']['parameters'][3]->entity_id, $node->nid, "The Flagging entity passed to hook_flag_flag() has the expected entity ID property.");
  1180. $this->assertEqual($hook_data_variable['hook_flag_flag']['parameters'][3]->uid, $this->flag_unflag_user->uid, "The Flagging entity passed to hook_flag_flag() has the expected uid property.");
  1181. // Check the API data available to hook_flag_flag().
  1182. //debug($hook_data_variable['hook_flag_flag']['api_calls']);
  1183. $flag_get_entity_flags = $hook_data_variable['hook_flag_flag']['api_calls']['flag_get_entity_flags'];
  1184. $flag_get_entity_flags_uids = array_keys($flag_get_entity_flags);
  1185. $this->assertEqual($flag_get_entity_flags_uids, array($this->flag_unflag_user->uid), "hook_flag_flag() gets correct data for flagging users from flag_get_entity_flags()");
  1186. $flag_get_entity_flags_flagging = $flag_get_entity_flags[$this->flag_unflag_user->uid];
  1187. $this->assertEqual($flag_get_entity_flags_flagging->fid, $flag->fid, "hook_flag_flag() gets a correct fid on the Flagging obtained from flag_get_entity_flags()");
  1188. $this->assertEqual($flag_get_entity_flags_flagging->entity_type, 'node', "hook_flag_flag() gets a correct entity type on the Flagging obtained from flag_get_entity_flags()");
  1189. $this->assertEqual($flag_get_entity_flags_flagging->entity_id, $node->nid, "hook_flag_flag() gets a correct entity ID on the Flagging obtained from flag_get_entity_flags()");
  1190. $flag_get_user_flags = $hook_data_variable['hook_flag_flag']['api_calls']['flag_get_user_flags'];
  1191. $flag_get_user_flags_flagging = $flag_get_user_flags[$flag->name];
  1192. $this->assertEqual($flag_get_user_flags_flagging->fid, $flag->fid, "hook_flag_flag() gets a correct fid on the Flagging obtained from flag_get_user_flags()");
  1193. $this->assertEqual($flag_get_user_flags_flagging->entity_type, 'node', "hook_flag_flag() gets a correct entity type on the Flagging obtained from flag_get_user_flags()");
  1194. $this->assertEqual($flag_get_user_flags_flagging->entity_id, $node->nid, "hook_flag_flag() gets a correct entity ID on the Flagging obtained from flag_get_user_flags()");
  1195. // The flag counts have been increased.
  1196. $flag_get_counts = $hook_data_variable['hook_flag_flag']['api_calls']['flag_get_counts'];
  1197. $this->assertEqual($flag_get_counts[$flag->name], 1, "hook_flag_flag() gets a correct flag count from flag_get_counts().");
  1198. $flag_get_flag_counts = $hook_data_variable['hook_flag_flag']['api_calls']['flag_get_flag_counts'];
  1199. $this->assertEqual($flag_get_flag_counts, 1, "hook_flag_flag() gets a correct flag count from flag_get_flag_counts().");
  1200. $flag_get_entity_flag_counts = $hook_data_variable['hook_flag_flag']['api_calls']['flag_get_entity_flag_counts'];
  1201. $this->assertEqual($flag_get_entity_flag_counts, 1, "hook_flag_flag() gets a correct flag count from flag_get_entity_flag_counts().");
  1202. $flag_get_user_flag_counts = $hook_data_variable['hook_flag_flag']['api_calls']['flag_get_user_flag_counts'];
  1203. $this->assertEqual($flag_get_user_flag_counts, 1, "hook_flag_flag() gets a correct flag count from flag_get_user_flag_counts().");
  1204. // Clear the tracking variable.
  1205. variable_set('flag_hook_test_hook_tracking', array());
  1206. // Get the Flagging, and re-flag the node.
  1207. // This does nothing in our case, but is the API for updating a Flagging
  1208. // entity with changes to its Field API fields.
  1209. // Query the database to get the Flagging ID rather than Flag API so we
  1210. // don't interefere with any caches.
  1211. $query = db_select('flagging', 'f');
  1212. $query->addField('f', 'flagging_id');
  1213. $query->condition('fid', $flag->fid)
  1214. ->condition('entity_id', $node->nid);
  1215. $flagging_id = $query
  1216. ->execute()
  1217. ->fetchField();
  1218. $flagging = flagging_load($flagging_id);
  1219. // Re-flag the node passing in the flagging entity.
  1220. $flag->flag('flag', $node->nid, $this->flag_unflag_user, FALSE, $flagging);
  1221. // Get the variable the test module sets the hook order into.
  1222. $hook_data_variable = variable_get('flag_hook_test_hook_tracking', array());
  1223. //debug($hook_data_variable);
  1224. $expected_hook_order = array(
  1225. 'hook_entity_presave',
  1226. 'hook_entity_update',
  1227. // Note that hook_flag() and the rule are not invoked, as this is not a
  1228. // new act of flagging.
  1229. );
  1230. // Check the hooks are invoked in the correct order.
  1231. $this->assertIdentical($expected_hook_order, array_keys($hook_data_variable), "The hooks are invoked in the correct order when re-flagging a node.");
  1232. // Check the parameters received by hook_entity_presave().
  1233. // Param 0: $flagging.
  1234. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->flag_name, $flag->name, "The Flagging entity passed to hook_entity_presave() has the expected flag name property.");
  1235. //$this->assertEqual($hook_data_variable['hook_entity_insert']['parameters'][0]->fid, $flag->fid);
  1236. //$this->assertEqual($hook_data_variable['hook_entity_insert']['parameters'][0]->entity_type, 'node');
  1237. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->entity_id, $node->nid, "The Flagging entity passed to hook_entity_presave() has the expected entity ID property.");
  1238. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->uid, $this->flag_unflag_user->uid, "The Flagging entity passed to hook_entity_presave() has the expected uid property.");
  1239. // Param 1: $entity_type.
  1240. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][1], 'flagging', "hook_entity_presave() is passed the correct entity type.");
  1241. // Check the API data available to hook_entity_presave().
  1242. //debug($hook_data_variable['hook_entity_presave']['api_calls']);
  1243. $flag_get_entity_flags = $hook_data_variable['hook_entity_presave']['api_calls']['flag_get_entity_flags'];
  1244. $flag_get_entity_flags_uids = array_keys($flag_get_entity_flags);
  1245. $this->assertEqual($flag_get_entity_flags_uids, array($this->flag_unflag_user->uid), "hook_entity_presave() gets correct data for flagging users from flag_get_entity_flags()");
  1246. $flag_get_entity_flags_flagging = $flag_get_entity_flags[$this->flag_unflag_user->uid];
  1247. $this->assertEqual($flag_get_entity_flags_flagging->fid, $flag->fid, "hook_entity_presave() gets a correct fid on the Flagging obtained from flag_get_entity_flags()");
  1248. $this->assertEqual($flag_get_entity_flags_flagging->entity_type, 'node', "hook_entity_presave() gets a correct entity type on the Flagging obtained from flag_get_entity_flags()");
  1249. $this->assertEqual($flag_get_entity_flags_flagging->entity_id, $node->nid, "hook_entity_presave() gets a correct entity ID on the Flagging obtained from flag_get_entity_flags()");
  1250. $flag_get_user_flags = $hook_data_variable['hook_entity_presave']['api_calls']['flag_get_user_flags'];
  1251. $flag_get_user_flags_flagging = $flag_get_user_flags[$flag->name];
  1252. $this->assertEqual($flag_get_user_flags_flagging->fid, $flag->fid, "hook_entity_presave() gets a correct fid on the Flagging obtained from flag_get_user_flags()");
  1253. $this->assertEqual($flag_get_user_flags_flagging->entity_type, 'node', "hook_entity_presave() gets a correct entity type on the Flagging obtained from flag_get_user_flags()");
  1254. $this->assertEqual($flag_get_user_flags_flagging->entity_id, $node->nid, "hook_entity_presave() gets a correct entity ID on the Flagging obtained from flag_get_user_flags()");
  1255. // The flag counts have not changed.
  1256. $flag_get_counts = $hook_data_variable['hook_entity_presave']['api_calls']['flag_get_counts'];
  1257. $this->assertEqual($flag_get_counts[$flag->name], 1, "hook_entity_presave() gets a correct flag count from flag_get_counts().");
  1258. $flag_get_flag_counts = $hook_data_variable['hook_entity_presave']['api_calls']['flag_get_flag_counts'];
  1259. $this->assertEqual($flag_get_flag_counts, 1, "hook_entity_presave() gets a correct flag count from flag_get_flag_counts().");
  1260. $flag_get_entity_flag_counts = $hook_data_variable['hook_entity_presave']['api_calls']['flag_get_entity_flag_counts'];
  1261. $this->assertEqual($flag_get_entity_flag_counts, 1, "hook_entity_presave() gets a correct flag count from flag_get_entity_flag_counts().");
  1262. $flag_get_user_flag_counts = $hook_data_variable['hook_entity_presave']['api_calls']['flag_get_user_flag_counts'];
  1263. $this->assertEqual($flag_get_user_flag_counts, 1, "hook_entity_presave() gets a correct flag count from flag_get_user_flag_counts().");
  1264. // Check the parameters received by hook_entity_update().
  1265. // Param 0: $flagging.
  1266. $this->assertEqual($hook_data_variable['hook_entity_update']['parameters'][0]->flag_name, $flag->name, "The Flagging entity passed to hook_entity_update() has the expected flag name property.");
  1267. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->fid, $flag->fid, "The Flagging entity passed to hook_entity_presave() has the expected fid property.");
  1268. $this->assertEqual($hook_data_variable['hook_entity_presave']['parameters'][0]->entity_type, 'node', "The Flagging entity passed to hook_entity_presave() has the expected entity type property.");
  1269. $this->assertEqual($hook_data_variable['hook_entity_update']['parameters'][0]->entity_id, $node->nid, "The Flagging entity passed to hook_entity_update() has the expected entity ID property.");
  1270. $this->assertEqual($hook_data_variable['hook_entity_update']['parameters'][0]->uid, $this->flag_unflag_user->uid, "The Flagging entity passed to hook_entity_update() has the expected uid property.");
  1271. $this->assertTrue(!empty($hook_data_variable['hook_entity_update']['parameters'][0]->flagging_id), "The Flagging entity passed to hook_entity_update() has the flagging ID set.");
  1272. // Param 1: $entity_type.
  1273. $this->assertEqual($hook_data_variable['hook_entity_update']['parameters'][1], 'flagging', "hook_entity_update() is passed the correct entity type.");
  1274. // Check the API data available to hook_entity_update().
  1275. //debug($hook_data_variable['hook_entity_update']['api_calls']);
  1276. $flag_get_entity_flags = $hook_data_variable['hook_entity_update']['api_calls']['flag_get_entity_flags'];
  1277. $flag_get_entity_flags_uids = array_keys($flag_get_entity_flags);
  1278. $this->assertEqual($flag_get_entity_flags_uids, array($this->flag_unflag_user->uid), "hook_entity_update() gets correct data for flagging users from flag_get_entity_flags()");
  1279. $flag_get_entity_flags_flagging = $flag_get_entity_flags[$this->flag_unflag_user->uid];
  1280. $this->assertEqual($flag_get_entity_flags_flagging->fid, $flag->fid, "hook_entity_update() gets a correct fid on the Flagging obtained from flag_get_entity_flags()");
  1281. $this->assertEqual($flag_get_entity_flags_flagging->entity_type, 'node', "hook_entity_update() gets a correct entity type on the Flagging obtained from flag_get_entity_flags()");
  1282. $this->assertEqual($flag_get_entity_flags_flagging->entity_id, $node->nid, "hook_entity_update() gets a correct entity ID on the Flagging obtained from flag_get_entity_flags()");
  1283. $flag_get_user_flags = $hook_data_variable['hook_entity_update']['api_calls']['flag_get_user_flags'];
  1284. $flag_get_user_flags_flagging = $flag_get_user_flags[$flag->name];
  1285. $this->assertEqual($flag_get_user_flags_flagging->fid, $flag->fid, "hook_entity_update() gets a correct fid on the Flagging obtained from flag_get_user_flags()");
  1286. $this->assertEqual($flag_get_user_flags_flagging->entity_type, 'node', "hook_entity_update() gets a correct entity type on the Flagging obtained from flag_get_user_flags()");
  1287. $this->assertEqual($flag_get_user_flags_flagging->entity_id, $node->nid, "hook_entity_update() gets a correct entity ID on the Flagging obtained from flag_get_user_flags()");
  1288. // The flag counts have not changed.
  1289. $flag_get_counts = $hook_data_variable['hook_entity_update']['api_calls']['flag_get_counts'];
  1290. $this->assertEqual($flag_get_counts[$flag->name], 1, "hook_entity_update() gets a correct flag count from flag_get_counts().");
  1291. $flag_get_flag_counts = $hook_data_variable['hook_entity_update']['api_calls']['flag_get_flag_counts'];
  1292. $this->assertEqual($flag_get_flag_counts, 1, "hook_entity_update() gets a correct flag count from flag_get_flag_counts().");
  1293. $flag_get_entity_flag_counts = $hook_data_variable['hook_entity_update']['api_calls']['flag_get_entity_flag_counts'];
  1294. $this->assertEqual($flag_get_entity_flag_counts, 1, "hook_entity_update() gets a correct flag count from flag_get_entity_flag_counts().");
  1295. $flag_get_user_flag_counts = $hook_data_variable['hook_entity_update']['api_calls']['flag_get_user_flag_counts'];
  1296. $this->assertEqual($flag_get_user_flag_counts, 1, "hook_entity_update() gets a correct flag count from flag_get_user_flag_counts().");
  1297. // Clear the tracking variable.
  1298. variable_set('flag_hook_test_hook_tracking', array());
  1299. // Unflag the node as the user.
  1300. $flag->flag('unflag', $node->nid, $this->flag_unflag_user);
  1301. // Get the variable the test module sets the hook order into.
  1302. $hook_data_variable = variable_get('flag_hook_test_hook_tracking', array());
  1303. //debug($hook_data_variable);
  1304. $expected_hook_order = array(
  1305. 'hook_flag_unflag',
  1306. 'rules_event',
  1307. 'hook_entity_delete',
  1308. );
  1309. // Check the hooks are invoked in the correct order.
  1310. $this->assertIdentical($expected_hook_order, array_keys($hook_data_variable), "The hooks are invoked in the correct order when unflagging a node.");
  1311. // Check the parameters received by hook_flag_unflag().
  1312. // Param 0: $flag.
  1313. $this->assertEqual($hook_data_variable['hook_flag_unflag']['parameters'][0], $flag, "The flag object is passed to hook_flag_unflag().");
  1314. // Param 1: $entity_id.
  1315. $this->assertEqual($hook_data_variable['hook_flag_unflag']['parameters'][1], $node->nid, "The entity ID is passed to hook_flag_unflag().");
  1316. // Param 2: $account.
  1317. $this->assertEqual($hook_data_variable['hook_flag_unflag']['parameters'][2]->uid, $this->flag_unflag_user->uid, "The user account is passed to hook_flag_unflag().");
  1318. // Param 3: $flagging.
  1319. $this->assertEqual($hook_data_variable['hook_flag_unflag']['parameters'][3]->flag_name, $flag->name, "The Flagging entity passed to hook_flag_unflag() has the expected flag name property.");
  1320. $this->assertEqual($hook_data_variable['hook_flag_unflag']['parameters'][3]->fid, $flag->fid, "The Flagging entity passed to hook_entity_presave() has the expected fid property.");
  1321. $this->assertEqual($hook_data_variable['hook_flag_unflag']['parameters'][3]->entity_type, 'node', "The Flagging entity passed to hook_entity_presave() has the expected entity type property.");
  1322. $this->assertEqual($hook_data_variable['hook_flag_unflag']['parameters'][3]->entity_id, $node->nid, "The Flagging entity passed to hook_flag_unflag() has the expected entity ID property.");
  1323. $this->assertEqual($hook_data_variable['hook_flag_unflag']['parameters'][3]->uid, $this->flag_unflag_user->uid, "The Flagging entity passed to hook_flag_unflag() has the expected uid property.");
  1324. // Check the API data available to hook_flag_unflag().
  1325. //debug($hook_data_variable['hook_flag_unflag']['api_calls']);
  1326. // The unflagging is not yet done, so flag_get_entity_flags() will find the
  1327. // flagging data.
  1328. $flag_get_entity_flags = $hook_data_variable['hook_flag_unflag']['api_calls']['flag_get_entity_flags'];
  1329. $flag_get_entity_flags_uids = array_keys($flag_get_entity_flags);
  1330. $this->assertEqual($flag_get_entity_flags_uids, array($this->flag_unflag_user->uid), "hook_flag_unflag() gets correct data for flagging users from flag_get_entity_flags()");
  1331. $flag_get_entity_flags_flagging = $flag_get_entity_flags[$this->flag_unflag_user->uid];
  1332. $this->assertEqual($flag_get_entity_flags_flagging->fid, $flag->fid, "hook_flag_unflag() gets a correct fid on the Flagging obtained from flag_get_entity_flags(): the Flagging has not yet been deleted.");
  1333. $this->assertEqual($flag_get_entity_flags_flagging->entity_type, 'node', "hook_flag_unflag() gets a correct entity type on the Flagging obtained from flag_get_entity_flags()");
  1334. $this->assertEqual($flag_get_entity_flags_flagging->entity_id, $node->nid, "hook_flag_unflag() gets a correct entity ID on the Flagging obtained from flag_get_entity_flags()");
  1335. $flag_get_user_flags = $hook_data_variable['hook_flag_unflag']['api_calls']['flag_get_user_flags'];
  1336. $flag_get_user_flags_flagging = $flag_get_user_flags[$flag->name];
  1337. $this->assertEqual($flag_get_user_flags_flagging->fid, $flag->fid, "hook_flag_unflag() gets a correct fid on the Flagging obtained from flag_get_user_flags()");
  1338. $this->assertEqual($flag_get_user_flags_flagging->entity_type, 'node', "hook_flag_unflag() gets a correct entity type on the Flagging obtained from flag_get_user_flags()");
  1339. $this->assertEqual($flag_get_user_flags_flagging->entity_id, $node->nid, "hook_flag_unflag() gets a correct entity ID on the Flagging obtained from flag_get_user_flags()");
  1340. // The flag counts have already been decreased.
  1341. $flag_get_counts = $hook_data_variable['hook_flag_unflag']['api_calls']['flag_get_counts'];
  1342. $this->assertEqual($flag_get_counts, array(), "hook_flag_unflag() gets a correct flag count from flag_get_counts().");
  1343. $flag_get_flag_counts = $hook_data_variable['hook_flag_unflag']['api_calls']['flag_get_flag_counts'];
  1344. $this->assertEqual($flag_get_flag_counts, 0, "hook_flag_unflag() gets a correct flag count from flag_get_flag_counts().");
  1345. // flag_get_entity_flag_counts() queries the {flagging} table, so is not
  1346. // updated yet.
  1347. $flag_get_entity_flag_counts = $hook_data_variable['hook_flag_unflag']['api_calls']['flag_get_entity_flag_counts'];
  1348. $this->assertEqual($flag_get_entity_flag_counts, 1, "hook_flag_unflag() gets a correct flag count from flag_get_entity_flag_counts().");
  1349. // flag_get_user_flag_counts() queries the {flagging} table, so is not
  1350. // updated yet.
  1351. $flag_get_user_flag_counts = $hook_data_variable['hook_flag_unflag']['api_calls']['flag_get_user_flag_counts'];
  1352. $this->assertEqual($flag_get_user_flag_counts, 1, "hook_flag_unflag() gets a correct flag count from flag_get_user_flag_counts().");
  1353. // Check the parameters received by hook_entity_delete().
  1354. // Param 0: $flagging.
  1355. $this->assertEqual($hook_data_variable['hook_entity_delete']['parameters'][0]->flag_name, $flag->name, "The Flagging entity passed to hook_entity_delete() has the expected flag name property.");
  1356. $this->assertEqual($hook_data_variable['hook_entity_delete']['parameters'][0]->fid, $flag->fid, "The Flagging entity passed to hook_entity_presave() has the expected fid property.");
  1357. $this->assertEqual($hook_data_variable['hook_entity_delete']['parameters'][0]->entity_type, 'node', "The Flagging entity passed to hook_entity_presave() has the expected entity type property.");
  1358. $this->assertEqual($hook_data_variable['hook_entity_delete']['parameters'][0]->entity_id, $node->nid, "The Flagging entity passed to hook_entity_delete() has the expected entity ID property.");
  1359. $this->assertEqual($hook_data_variable['hook_entity_delete']['parameters'][0]->uid, $this->flag_unflag_user->uid, "The Flagging entity passed to hook_entity_delete() has the expected uid property.");
  1360. $this->assertTrue(!empty($hook_data_variable['hook_entity_delete']['parameters'][0]->flagging_id), "The Flagging entity passed to hook_entity_delete() has the flagging ID set.");
  1361. // Param 1: $entity_type.
  1362. $this->assertEqual($hook_data_variable['hook_entity_delete']['parameters'][1], 'flagging', "hook_entity_delete() is passed the correct entity type.");
  1363. // Check the API data available to hook_entity_delete().
  1364. //debug($hook_data_variable['hook_entity_delete']['api_calls']);
  1365. // The unflagging is not yet done, so hook_entity_delete() will find the
  1366. // flagging data.
  1367. $flag_get_entity_flags = $hook_data_variable['hook_entity_delete']['api_calls']['flag_get_entity_flags'];
  1368. $flag_get_entity_flags_uids = array_keys($flag_get_entity_flags);
  1369. $this->assertEqual($flag_get_entity_flags_uids, array($this->flag_unflag_user->uid), "hook_entity_delete() gets correct data for flagging users from flag_get_entity_flags()");
  1370. $flag_get_entity_flags_flagging = $flag_get_entity_flags[$this->flag_unflag_user->uid];
  1371. $this->assertEqual($flag_get_entity_flags_flagging->fid, $flag->fid, "hook_entity_delete() gets a correct fid on the Flagging obtained from flag_get_entity_flags()");
  1372. $this->assertEqual($flag_get_entity_flags_flagging->entity_type, 'node', "hook_entity_delete() gets a correct entity type on the Flagging obtained from flag_get_entity_flags()");
  1373. $this->assertEqual($flag_get_entity_flags_flagging->entity_id, $node->nid, "hook_entity_delete() gets a correct entity ID on the Flagging obtained from flag_get_entity_flags()");
  1374. $flag_get_user_flags = $hook_data_variable['hook_entity_delete']['api_calls']['flag_get_user_flags'];
  1375. $flag_get_user_flags_flagging = $flag_get_user_flags[$flag->name];
  1376. $this->assertEqual($flag_get_user_flags_flagging->fid, $flag->fid, "hook_entity_delete() gets a correct fid on the Flagging obtained from flag_get_user_flags()");
  1377. $this->assertEqual($flag_get_user_flags_flagging->entity_type, 'node', "hook_entity_delete() gets a correct entity type on the Flagging obtained from flag_get_user_flags()");
  1378. $this->assertEqual($flag_get_user_flags_flagging->entity_id, $node->nid, "hook_entity_delete() gets a correct entity ID on the Flagging obtained from flag_get_user_flags()");
  1379. // The flag counts have already been decreased.
  1380. $flag_get_counts = $hook_data_variable['hook_entity_delete']['api_calls']['flag_get_counts'];
  1381. $this->assertEqual($flag_get_counts, array(), "hook_entity_delete() gets a correct flag count from flag_get_counts().");
  1382. $flag_get_flag_counts = $hook_data_variable['hook_entity_delete']['api_calls']['flag_get_flag_counts'];
  1383. $this->assertEqual($flag_get_flag_counts, 0, "hook_entity_delete() gets a correct flag count from flag_get_flag_counts().");
  1384. // flag_get_entity_flag_counts() queries the {flagging} table, so is not
  1385. // updated yet.
  1386. $flag_get_entity_flag_counts = $hook_data_variable['hook_entity_delete']['api_calls']['flag_get_entity_flag_counts'];
  1387. $this->assertEqual($flag_get_entity_flag_counts, 1, "hook_entity_delete() gets a correct flag count from flag_get_entity_flag_counts().");
  1388. // flag_get_user_flag_counts() queries the {flagging} table, so is not
  1389. // updated yet.
  1390. $flag_get_user_flag_counts = $hook_data_variable['hook_entity_delete']['api_calls']['flag_get_user_flag_counts'];
  1391. $this->assertEqual($flag_get_user_flag_counts, 1, "hook_entity_delete() gets a correct flag count from flag_get_user_flag_counts().");
  1392. }
  1393. }
  1394. /**
  1395. * Verifies the optimization for comment viewing.
  1396. */
  1397. class FlagCommentOptimizationTestCase extends FlagTestCaseBase {
  1398. /**
  1399. * Implements getInfo().
  1400. */
  1401. public static function getInfo() {
  1402. return array(
  1403. 'name' => 'Comment view optimization',
  1404. 'description' => 'Tests that loading of flagging records when viewing all comments on a node works correctly.',
  1405. 'group' => 'Flag',
  1406. );
  1407. }
  1408. /**
  1409. * Implements setUp().
  1410. */
  1411. function setUp() {
  1412. parent::setUp(array(
  1413. 'flag',
  1414. 'comment',
  1415. 'flag_comment_flag_test',
  1416. ));
  1417. $flag_data = array(
  1418. 'entity_type' => 'comment',
  1419. 'name' => 'test_flag',
  1420. 'title' => 'Test Flag',
  1421. 'global' => 0,
  1422. 'types' => array(),
  1423. 'flag_short' => 'Flag this item',
  1424. 'flag_long' => '',
  1425. 'flag_message' => '',
  1426. 'unflag_short' => 'Unflag this item',
  1427. 'unflag_long' => '',
  1428. 'unflag_message' => '',
  1429. 'unflag_denied_text' => 'You may not unflag this item',
  1430. 'link_type' => 'normal',
  1431. 'weight' => 0,
  1432. 'show_on_form' => 0,
  1433. 'access_author' => '',
  1434. 'show_contextual_link' => 0,
  1435. 'show_in_links' => array(
  1436. 'full' => 1,
  1437. 'teaser' => 1,
  1438. ),
  1439. 'i18n' => 0,
  1440. 'api_version' => 3,
  1441. );
  1442. $this->flag = $this->createFlag($flag_data);
  1443. // Set up comments on article nodes.
  1444. variable_set('comment_form_location_article', COMMENT_FORM_BELOW);
  1445. // Create test user who can flag and unflag.
  1446. $this->user = $this->drupalCreateUser(array(
  1447. 'access comments',
  1448. 'post comments',
  1449. 'flag test_flag',
  1450. 'unflag test_flag',
  1451. ));
  1452. $this->drupalLogin($this->user);
  1453. // Create an article node.
  1454. $title = $this->randomName(8);
  1455. $node = array(
  1456. 'title' => $title,
  1457. 'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
  1458. 'uid' => $this->user->uid,
  1459. 'type' => 'article',
  1460. 'is_new' => TRUE,
  1461. 'comment' => COMMENT_NODE_OPEN,
  1462. );
  1463. $node = node_submit((object) $node);
  1464. node_save($node);
  1465. $this->nid = $node->nid;
  1466. // Create some comments on the node.
  1467. $this->cids = array();
  1468. foreach (range(1, 10) as $i) {
  1469. $comment = (object) array(
  1470. 'cid' => NULL,
  1471. 'nid' => $node->nid,
  1472. 'pid' => 0,
  1473. 'uid' => $this->user->uid,
  1474. 'status' => COMMENT_PUBLISHED,
  1475. 'subject' => $this->randomName(),
  1476. 'language' => LANGUAGE_NONE,
  1477. 'comment_body' => array(LANGUAGE_NONE => array($this->randomName())),
  1478. );
  1479. comment_save($comment);
  1480. $this->cids[$comment->cid] = $comment->cid;
  1481. }
  1482. // Flag one comment.
  1483. $this->flag->flag('flag', reset($this->cids));
  1484. }
  1485. /**
  1486. * Test viewing multiple comments on a node is optimized.
  1487. */
  1488. function testCommentView() {
  1489. // View the node.
  1490. $this->drupalGet('node/' . $this->nid);
  1491. // Inspect the tracking variable.
  1492. // Hooks in the flag_comment_flag_test module will have populated this with
  1493. // data at various points in the lifecycle of the loaded page.
  1494. $tracking_variable = variable_get('flag_comment_flag_test_user_flags_cache_tracking', array());
  1495. $this->assertNull($tracking_variable['hook_comment_load'], "The flag_get_user_flags() static cache is empty when the comments are being loaded.");
  1496. // The test module's hook_entity_view() runs after flag's implementation, so
  1497. // for the first comment view, the cache should be fully populated: all
  1498. // comments should have an entry.
  1499. foreach ($this->cids as $cid) {
  1500. $this->assertNotNull($tracking_variable['hook_entity_view_1'][$this->user->uid][0]['comment'][$cid], "The static cache contained data for comment $cid when comment 1 was being viewed.");
  1501. }
  1502. }
  1503. }