wpPrivacySendErasureFulfillmentNotification.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <?php
  2. /**
  3. * Test cases for the `_wp_privacy_send_erasure_fulfillment_notification()` function.
  4. *
  5. * @package WordPress
  6. * @subpackage UnitTests
  7. * @since 5.1.0
  8. */
  9. /**
  10. * Tests_Privacy_WpPrivacySendErasureFulfillmentNotification class.
  11. *
  12. * @group privacy
  13. * @covers ::_wp_privacy_send_erasure_fulfillment_notification
  14. *
  15. * @since 5.1.0
  16. */
  17. class Tests_Privacy_WpPrivacySendErasureFulfillmentNotification extends WP_UnitTestCase {
  18. /**
  19. * Request ID.
  20. *
  21. * @since 5.1.0
  22. *
  23. * @var int $request_id
  24. */
  25. protected static $request_id;
  26. /**
  27. * Requester Email.
  28. *
  29. * @since 5.1.0
  30. *
  31. * @var string $requester_email
  32. */
  33. protected static $requester_email;
  34. /**
  35. * Request user.
  36. *
  37. * @since 5.2.0
  38. *
  39. * @var WP_User $request_user
  40. */
  41. protected static $request_user;
  42. /**
  43. * Test administrator user.
  44. *
  45. * @since 5.2.0
  46. *
  47. * @var WP_User $admin_user
  48. */
  49. protected static $admin_user;
  50. /**
  51. * Create user request fixtures shared by test methods.
  52. *
  53. * @since 5.1.0
  54. *
  55. * @param WP_UnitTest_Factory $factory Factory.
  56. */
  57. public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
  58. self::$requester_email = 'erase-my-data@local.test';
  59. self::$request_user = $factory->user->create_and_get(
  60. array(
  61. 'user_email' => self::$requester_email,
  62. 'role' => 'subscriber',
  63. )
  64. );
  65. self::$admin_user = $factory->user->create_and_get(
  66. array(
  67. 'user_email' => 'admin@local.dev',
  68. 'role' => 'administrator',
  69. )
  70. );
  71. self::$request_id = wp_create_user_request( self::$requester_email, 'remove_personal_data' );
  72. wp_update_post(
  73. array(
  74. 'ID' => self::$request_id,
  75. 'post_status' => 'request-completed',
  76. )
  77. );
  78. }
  79. /**
  80. * Reset the mocked PHPMailer instance before each test method.
  81. *
  82. * @since 5.1.0
  83. */
  84. public function setUp() {
  85. parent::setUp();
  86. reset_phpmailer_instance();
  87. }
  88. /**
  89. * Reset the mocked PHPMailer instance after each test method.
  90. *
  91. * @since 5.1.0
  92. */
  93. public function tearDown() {
  94. reset_phpmailer_instance();
  95. restore_previous_locale();
  96. parent::tearDown();
  97. }
  98. /**
  99. * The function should send an email when a valid request ID is passed.
  100. *
  101. * @ticket 44234
  102. */
  103. public function test_should_send_email_no_privacy_policy() {
  104. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  105. $mailer = tests_retrieve_phpmailer_instance();
  106. $this->assertContains( self::$requester_email, $mailer->get_recipient( 'to' )->address );
  107. $this->assertContains( 'Erasure Request Fulfilled', $mailer->get_sent()->subject );
  108. $this->assertContains( 'Your request to erase your personal data', $mailer->get_sent()->body );
  109. $this->assertContains( 'has been completed.', $mailer->get_sent()->body );
  110. $this->assertContains( wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $mailer->get_sent()->body );
  111. $this->assertContains( home_url(), $mailer->get_sent()->body );
  112. $this->assertNotContains( 'you can also read our privacy policy', $mailer->get_sent()->body );
  113. $this->assertTrue( (bool) get_post_meta( self::$request_id, '_wp_user_notified', true ) );
  114. }
  115. /**
  116. * The email should include a link to the site's privacy policy when set.
  117. *
  118. * @ticket 44234
  119. */
  120. public function test_should_send_email_with_privacy_policy() {
  121. $privacy_policy = $this->factory->post->create(
  122. array(
  123. 'post_type' => 'page',
  124. 'title' => 'Site Privacy Policy',
  125. 'post_status' => 'publish',
  126. )
  127. );
  128. update_option( 'wp_page_for_privacy_policy', $privacy_policy );
  129. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  130. $mailer = tests_retrieve_phpmailer_instance();
  131. $this->assertContains( self::$requester_email, $mailer->get_recipient( 'to' )->address );
  132. $this->assertContains( 'you can also read our privacy policy', $mailer->get_sent()->body );
  133. $this->assertContains( get_privacy_policy_url(), $mailer->get_sent()->body );
  134. $this->assertTrue( (bool) get_post_meta( self::$request_id, '_wp_user_notified', true ) );
  135. }
  136. /**
  137. * The function should send a fulfillment email only once.
  138. *
  139. * @ticket 44234
  140. */
  141. public function test_should_send_email_only_once() {
  142. // First function call.
  143. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  144. $mailer = tests_retrieve_phpmailer_instance();
  145. // Should send an email.
  146. $this->assertContains( self::$requester_email, $mailer->get_recipient( 'to' )->address );
  147. $this->assertContains( 'Erasure Request Fulfilled', $mailer->get_sent()->subject );
  148. $this->assertTrue( (bool) get_post_meta( self::$request_id, '_wp_user_notified', true ) );
  149. reset_phpmailer_instance();
  150. // Second function call.
  151. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  152. $mailer = tests_retrieve_phpmailer_instance();
  153. // Should not send an email.
  154. $this->assertEmpty( $mailer->mock_sent );
  155. $this->assertTrue( metadata_exists( 'post', self::$request_id, '_wp_user_notified' ) );
  156. }
  157. /**
  158. * The email address of the recipient of the fulfillment notification should be filterable.
  159. *
  160. * @ticket 44234
  161. */
  162. public function test_email_address_of_recipient_should_be_filterable() {
  163. add_filter( 'user_erasure_fulfillment_email_to', array( $this, 'filter_email_address' ) );
  164. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  165. $mailer = tests_retrieve_phpmailer_instance();
  166. $this->assertSame( 'modified-' . self::$requester_email, $mailer->get_recipient( 'to' )->address );
  167. }
  168. /**
  169. * Filter callback that modifies the email address of the recipient of the fulfillment notification.
  170. *
  171. * @since 5.1.0
  172. *
  173. * @param string $user_email The email address of the notification recipient.
  174. * @return string The email address of the notification recipient.
  175. */
  176. public function filter_email_address( $user_email ) {
  177. return 'modified-' . $user_email;
  178. }
  179. /**
  180. * The email subject of the fulfillment notification should be filterable.
  181. *
  182. * @ticket 44234
  183. */
  184. public function test_email_subject_should_be_filterable() {
  185. add_filter( 'user_erasure_complete_email_subject', array( $this, 'filter_email_subject' ) );
  186. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  187. $mailer = tests_retrieve_phpmailer_instance();
  188. $this->assertSame( 'Modified subject', $mailer->get_sent()->subject );
  189. }
  190. /**
  191. * Filter callback that modifies the email subject of the data erasure fulfillment notification.
  192. *
  193. * @since 5.1.0
  194. *
  195. * @param string $subject The email subject.
  196. * @return string The email subject.
  197. */
  198. public function filter_email_subject( $subject ) {
  199. return 'Modified subject';
  200. }
  201. /**
  202. * The email body text of the fulfillment notification should be filterable.
  203. *
  204. * @ticket 44234
  205. */
  206. public function test_email_body_text_should_be_filterable() {
  207. add_filter( 'user_confirmed_action_email_content', array( $this, 'filter_email_body_text' ) );
  208. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  209. $mailer = tests_retrieve_phpmailer_instance();
  210. $this->assertSame( 'Modified text', trim( $mailer->get_sent()->body ) );
  211. }
  212. /**
  213. * Filter callback that modifies the email body text of the data erasure fulfillment notification.
  214. *
  215. * @since 5.1.0
  216. *
  217. * @param string $email_text Text in the email.
  218. * @return string Text in the email.
  219. */
  220. public function filter_email_body_text( $email_text ) {
  221. return 'Modified text';
  222. }
  223. /**
  224. * The email headers of the fulfillment notification should be filterable.
  225. *
  226. * @since 5.4.0
  227. *
  228. * @ticket 44501
  229. */
  230. public function test_email_headers_should_be_filterable() {
  231. add_filter( 'user_erasure_complete_email_headers', array( $this, 'modify_email_headers' ) );
  232. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  233. $mailer = tests_retrieve_phpmailer_instance();
  234. $this->assertContains( 'From: Tester <tester@example.com>', $mailer->get_sent()->header );
  235. }
  236. /**
  237. * Filter callback that modifies the email headers of the data erasure fulfillment notification.
  238. *
  239. * @since 5.4.0
  240. *
  241. * @param string|array $headers The email headers.
  242. * @return array The new email headers.
  243. */
  244. public function modify_email_headers( $headers ) {
  245. $headers = array(
  246. 'From: Tester <tester@example.com>',
  247. );
  248. return $headers;
  249. }
  250. /**
  251. * The function should not send an email when the request ID does not exist.
  252. *
  253. * @ticket 44234
  254. */
  255. public function test_should_not_send_email_when_passed_invalid_request_id() {
  256. _wp_privacy_send_erasure_fulfillment_notification( 1234567890 );
  257. $mailer = tests_retrieve_phpmailer_instance();
  258. $this->assertEmpty( $mailer->mock_sent );
  259. }
  260. /**
  261. * The function should not send an email when the ID passed does not correspond to a user request.
  262. *
  263. * @ticket 44234
  264. */
  265. public function test_should_not_send_email_when_not_user_request() {
  266. $post_id = $this->factory->post->create(
  267. array(
  268. 'post_type' => 'post', // Should be 'user_request'.
  269. )
  270. );
  271. _wp_privacy_send_erasure_fulfillment_notification( $post_id );
  272. $mailer = tests_retrieve_phpmailer_instance();
  273. $this->assertEmpty( $mailer->mock_sent );
  274. }
  275. /**
  276. * The function should not send an email when the request is not completed.
  277. *
  278. * @ticket 44234
  279. */
  280. public function test_should_not_send_email_when_request_not_completed() {
  281. wp_update_post(
  282. array(
  283. 'ID' => self::$request_id,
  284. 'post_status' => 'request-confirmed', // Should be 'request-completed'.
  285. )
  286. );
  287. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  288. $mailer = tests_retrieve_phpmailer_instance();
  289. $this->assertEmpty( $mailer->mock_sent );
  290. $this->assertFalse( metadata_exists( 'post', self::$request_id, '_wp_user_notified' ) );
  291. }
  292. /**
  293. * The function should respect the user locale settings when the site uses the default locale.
  294. *
  295. * @since 5.2.0
  296. * @ticket 44721
  297. * @group l10n
  298. */
  299. public function test_should_send_fulfillment_email_in_user_locale() {
  300. update_user_meta( self::$request_user->ID, 'locale', 'es_ES' );
  301. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  302. $mailer = tests_retrieve_phpmailer_instance();
  303. $this->assertContains( 'Solicitud de borrado completada', $mailer->get_sent()->subject );
  304. }
  305. /**
  306. * The function should respect the user locale settings when the site does not use en_US, the administrator
  307. * uses the site's default locale, and the user has a different locale.
  308. *
  309. * @since 5.2.0
  310. * @ticket 44721
  311. * @group l10n
  312. */
  313. public function test_should_send_fulfillment_email_in_user_locale_when_site_is_not_en_us() {
  314. update_option( 'WPLANG', 'es_ES' );
  315. switch_to_locale( 'es_ES' );
  316. update_user_meta( self::$request_user->ID, 'locale', 'de_DE' );
  317. wp_set_current_user( self::$admin_user->ID );
  318. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  319. $mailer = tests_retrieve_phpmailer_instance();
  320. $this->assertContains( 'Löschauftrag ausgeführt', $mailer->get_sent()->subject );
  321. }
  322. /**
  323. * The function should respect the user locale settings when the site is not en_US, the administrator
  324. * has a different selected locale, and the user uses the site's default locale.
  325. *
  326. * @since 5.2.0
  327. * @ticket 44721
  328. * @group l10n
  329. */
  330. public function test_should_send_fulfillment_email_in_user_locale_when_admin_and_site_have_different_locales() {
  331. update_option( 'WPLANG', 'es_ES' );
  332. switch_to_locale( 'es_ES' );
  333. update_user_meta( self::$admin_user->ID, 'locale', 'de_DE' );
  334. wp_set_current_user( self::$admin_user->ID );
  335. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  336. $mailer = tests_retrieve_phpmailer_instance();
  337. $this->assertContains( 'Solicitud de borrado completada', $mailer->get_sent()->subject );
  338. }
  339. /**
  340. * The function should respect the user locale settings when the site is not en_US and both the
  341. * administrator and the user use different locales.
  342. *
  343. * @since 5.2.0
  344. * @ticket 44721
  345. * @group l10n
  346. */
  347. public function test_should_send_fulfillment_email_in_user_locale_when_both_have_different_locales_than_site() {
  348. update_option( 'WPLANG', 'es_ES' );
  349. switch_to_locale( 'es_ES' );
  350. update_user_meta( self::$admin_user->ID, 'locale', 'en_US' );
  351. update_user_meta( self::$request_user->ID, 'locale', 'de_DE' );
  352. wp_set_current_user( self::$admin_user->ID );
  353. _wp_privacy_send_erasure_fulfillment_notification( self::$request_id );
  354. $mailer = tests_retrieve_phpmailer_instance();
  355. $this->assertContains( 'Löschauftrag ausgeführt', $mailer->get_sent()->subject );
  356. }
  357. /**
  358. * The function should respect the site's locale when the request is for an unregistered user and the
  359. * administrator does not use the site's locale.
  360. *
  361. * @since 5.2.0
  362. * @ticket 44721
  363. * @group l10n
  364. */
  365. public function test_should_send_fulfillment_email_in_site_locale() {
  366. update_user_meta( self::$admin_user->ID, 'locale', 'es_ES' );
  367. wp_set_current_user( self::$admin_user->ID );
  368. $request_id = wp_create_user_request( 'erase-user-not-registered@example.com', 'remove_personal_data' );
  369. wp_update_post(
  370. array(
  371. 'ID' => $request_id,
  372. 'post_status' => 'request-completed',
  373. )
  374. );
  375. _wp_privacy_send_erasure_fulfillment_notification( $request_id );
  376. $mailer = tests_retrieve_phpmailer_instance();
  377. $this->assertContains( 'Erasure Request Fulfilled', $mailer->get_sent()->subject );
  378. }
  379. /**
  380. * The function should respect the site's locale when it is not en_US, the request is for an
  381. * unregistered user, and the administrator does not use the site's default locale.
  382. *
  383. * @since 5.2.0
  384. * @ticket 44721
  385. * @group l10n
  386. */
  387. public function test_should_send_fulfillment_email_in_site_locale_when_not_en_us_and_admin_has_different_locale() {
  388. update_option( 'WPLANG', 'es_ES' );
  389. switch_to_locale( 'es_ES' );
  390. update_user_meta( self::$admin_user->ID, 'locale', 'de_DE' );
  391. wp_set_current_user( self::$admin_user->ID );
  392. $request_id = wp_create_user_request( 'erase-user-not-registered@example.com', 'remove_personal_data' );
  393. wp_update_post(
  394. array(
  395. 'ID' => $request_id,
  396. 'post_status' => 'request-completed',
  397. )
  398. );
  399. _wp_privacy_send_erasure_fulfillment_notification( $request_id );
  400. $mailer = tests_retrieve_phpmailer_instance();
  401. $this->assertContains( 'Solicitud de borrado completada', $mailer->get_sent()->subject );
  402. }
  403. }