{"action":"created","comment":{"url":"https://api.github.com/repos/amitaibu/og/pulls/comments/58677796","id":58677796,"diff_hunk":"@@ -0,0 +1,212 @@\n+<?php\n+\n+namespace Drupal\\Tests\\og\\Kernel;\n+\n+use Drupal\\Component\\Utility\\Unicode;\n+use Drupal\\Core\\Entity\\Entity;\n+use Drupal\\KernelTests\\KernelTestBase;\n+use Drupal\\node\\Entity\\Node;\n+use Drupal\\node\\Entity\\NodeType;\n+use Drupal\\og\\Og;\n+use Drupal\\og\\OgGroupAudienceHelper;\n+\n+/**\n+ * Tests deletion of orphaned group content.\n+ *\n+ * @group og\n+ */\n+class OgDeleteOrphanedGroupContentTest extends KernelTestBase {\n+\n+  /**\n+   * {@inheritdoc}\n+   */\n+  public static $modules = ['system', 'user', 'field', 'entity_reference', 'node', 'og'];\n+\n+  /**\n+   * The plugin manager for OgDeleteOrphans plugins.\n+   *\n+   * @var \\Drupal\\Component\\Plugin\\PluginManagerInterface\n+   */\n+  protected $ogDeleteOrphansPluginManager;\n+\n+  /**\n+   * {@inheritdoc}\n+   */\n+  public function setUp() {\n+    parent::setUp();\n+\n+    // Add membership and config schema.\n+    $this->installConfig(['og']);\n+    $this->installEntitySchema('og_membership');\n+    $this->installEntitySchema('user');\n+    $this->installEntitySchema('node');\n+    $this->installSchema('node', 'node_access');\n+    $this->installSchema('system', ['queue', 'sequences']);\n+\n+    /** @var \\Drupal\\og\\OgDeleteOrphansPluginManager ogDeleteOrphansPluginManager */\n+    $this->ogDeleteOrphansPluginManager = \\Drupal::service('plugin.manager.og.delete_orphans');\n+\n+    // Create a group entity type.\n+    $this->groupBundle = Unicode::strtolower($this->randomMachineName());\n+    NodeType::create([\n+      'type' => $this->groupBundle,\n+      'name' => $this->randomString(),\n+    ])->save();\n+    Og::groupManager()->addGroup('node', $this->groupBundle);\n+\n+    // Create a group content entity type.\n+    $this->groupContentBundle = Unicode::strtolower($this->randomMachineName());\n+    NodeType::create([\n+      'type' => $this->groupContentBundle,\n+      'name' => $this->randomString(),\n+    ])->save();\n+    Og::createField(OgGroupAudienceHelper::DEFAULT_FIELD, 'node', $this->groupContentBundle);\n+\n+    // Create a group.\n+    $this->group = Node::create([\n+      'title' => $this->randomString(),\n+      'type' => $this->groupBundle,\n+    ]);\n+    $this->group->save();\n+\n+    // Create a group content item.\n+    $this->groupContent = Node::create([\n+      'title' => $this->randomString(),\n+      'type' => $this->groupContentBundle,\n+      OgGroupAudienceHelper::DEFAULT_FIELD => [['target_id' => $this->group->id()]],\n+    ]);\n+    $this->groupContent->save();\n+  }\n+\n+  /**\n+   * Tests that orphaned group content is deleted when the group is deleted.\n+   *\n+   * @dataProvider ogDeleteOrphansPluginProvider\n+   *\n+   * @param string $plugin_id\n+   *   The machine name of the plugin under test.\n+   * @param bool $run_cron\n+   *   Whether or not cron jobs should be run as part of the test.\n+   * @param string $queue_id\n+   *   The ID of the queue that is used by the plugin under test.\n+   */\n+  public function testDeleteOrphans($plugin_id, $run_cron, $queue_id) {\n+    // Turn on deletion of orphans in the configuration and configure the chosen\n+    // plugin.\n+    $this->config('og.settings')\n+      ->set('delete_orphans', TRUE)\n+      ->set('delete_orphans_plugin_id', $plugin_id)\n+      ->save();\n+\n+    // Delete the group.\n+    $this->group->delete();\n+\n+    // Check that the orphan is queued.\n+    /** @var \\Drupal\\Core\\Queue\\QueueInterface $queue */\n+    $queue = $this->container->get('queue')->get($queue_id);\n+    $this->assertEquals(1, $queue->numberOfItems());\n+\n+    // Run cron jobs if needed.\n+    if ($run_cron) {\n+      $this->container->get('cron')->run();\n+    }\n+\n+    // Invoke the processing of the orphans.\n+    /** @var \\Drupal\\og\\OgDeleteOrphansInterface $plugin */\n+    $plugin = $this->ogDeleteOrphansPluginManager->createInstance($plugin_id, []);\n+    $plugin->process();\n+\n+    // Verify the group content is deleted.\n+    $this->assertFalse($this->group_content, 'The orphaned node is deleted.');\n+\n+    // Check that the queue is now empty.\n+    $this->assertEquals(0, $queue->numberOfItems());\n+  }\n+\n+  /**\n+   * Tests that orphaned content is not deleted when the option is disabled.\n+   *\n+   * @dataProvider ogDeleteOrphansPluginProvider\n+   */\n+  function testDisabled($plugin_id) {\n+    $this->markTestSkipped();\n+    return;\n+    // Disable deletion of orphans in the configuration and configure the chosen\n+    // plugin.\n+    $this->config('og.settings')\n+      ->set('delete_orphans', FALSE)\n+      ->set('delete_orphans_plugin_id', $plugin_id)\n+      ->save();\n+\n+    // Delete the group.\n+    $this->group->delete();\n+\n+    // Invoke the processing of the orphans.\n+    /** @var \\Drupal\\og\\OgDeleteOrphansInterface $plugin */\n+    $plugin = $this->ogDeleteOrphansPluginManager->createInstance($plugin_id, []);\n+    $plugin->process();\n+\n+    // Reload the group content that was used during the test.\n+    $group_content = Node::load($this->group_content->id());\n+\n+    // Verify the orphaned node is not deleted.\n+    $this->assertTrue($group_content, 'The orphaned node is not deleted.');\n+  }\n+\n+  /**\n+   * Provides OgDeleteOrphans plugins for the tests.\n+   *\n+   * @return array\n+   *   An array of test properties. Each property is an indexed array with the\n+   *   following items:\n+   *   - A string containing the plugin name being tested.\n+   *   - A boolean indicating whether or not cron jobs should be run.\n+   *   - A string defining the queue that is used by the plugin.\n+   */\n+  public function ogDeleteOrphansPluginProvider() {\n+    return [\n+      ['batch', FALSE, 'og_orphaned_group_content'],\n+      ['cron', TRUE, 'og_orphaned_group_content_cron'],\n+      ['simple', FALSE, 'og_orphaned_group_content'],\n+    ];\n+  }\n+\n+  /**\n+   * Tests the moving of the node to another group when deleting a group.\n+   *\n+   * @todo This test doesn't make any sense to me. The way I read it is that if\n+   *   multiple groups are present and one of the groups is deleted then its\n+   *   content is expected to be moved into a random other group? This seems\n+   *   dangerous, it might expose private data.\n+   *\n+   *   This might be useful for child groups that are related to parent groups,\n+   *   so that when a child group is deleted its content will be moved to the\n+   *   parent, but then there should be a very clear indication of the parent-\n+   *   child relation which is missing in this test. Here the content just moves\n+   *   to whatever random group that is available.\n+   */\n+  function _testMoveOrphans() {","path":"tests/src/Kernel/OgDeleteOrphanedGroupContentTest.php","position":188,"original_position":188,"commit_id":"e63d671f0da502e2d394fbc4a379869e1aaba5ee","original_commit_id":"6539cfa5a17dc072c70749e66b6bd33be7b3b19e","user":{"login":"amitaibu","id":125707,"avatar_url":"https://avatars.githubusercontent.com/u/125707?v=3","gravatar_id":"","url":"https://api.github.com/users/amitaibu","html_url":"https://github.com/amitaibu","followers_url":"https://api.github.com/users/amitaibu/followers","following_url":"https://api.github.com/users/amitaibu/following{/other_user}","gists_url":"https://api.github.com/users/amitaibu/gists{/gist_id}","starred_url":"https://api.github.com/users/amitaibu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amitaibu/subscriptions","organizations_url":"https://api.github.com/users/amitaibu/orgs","repos_url":"https://api.github.com/users/amitaibu/repos","events_url":"https://api.github.com/users/amitaibu/events{/privacy}","received_events_url":"https://api.github.com/users/amitaibu/received_events","type":"User","site_admin":false},"body":"yeah, I see that there's something missing there -- telling it where to move. I'll have to refresh my memory..","created_at":"2016-04-06T09:39:18Z","updated_at":"2016-04-06T09:39:18Z","html_url":"https://github.com/amitaibu/og/pull/162#discussion_r58677796","pull_request_url":"https://api.github.com/repos/amitaibu/og/pulls/162","_links":{"self":{"href":"https://api.github.com/repos/amitaibu/og/pulls/comments/58677796"},"html":{"href":"https://github.com/amitaibu/og/pull/162#discussion_r58677796"},"pull_request":{"href":"https://api.github.com/repos/amitaibu/og/pulls/162"}}},"pull_request":{"url":"https://api.github.com/repos/amitaibu/og/pulls/162","id":62255097,"html_url":"https://github.com/amitaibu/og/pull/162","diff_url":"https://github.com/amitaibu/og/pull/162.diff","patch_url":"https://github.com/amitaibu/og/pull/162.patch","issue_url":"https://api.github.com/repos/amitaibu/og/issues/162","number":162,"state":"open","locked":false,"title":"WIP: Delete memberships when a group is deleted","user":{"login":"pfrenssen","id":442924,"avatar_url":"https://avatars.githubusercontent.com/u/442924?v=3","gravatar_id":"","url":"https://api.github.com/users/pfrenssen","html_url":"https://github.com/pfrenssen","followers_url":"https://api.github.com/users/pfrenssen/followers","following_url":"https://api.github.com/users/pfrenssen/following{/other_user}","gists_url":"https://api.github.com/users/pfrenssen/gists{/gist_id}","starred_url":"https://api.github.com/users/pfrenssen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pfrenssen/subscriptions","organizations_url":"https://api.github.com/users/pfrenssen/orgs","repos_url":"https://api.github.com/users/pfrenssen/repos","events_url":"https://api.github.com/users/pfrenssen/events{/privacy}","received_events_url":"https://api.github.com/users/pfrenssen/received_events","type":"User","site_admin":false},"body":"When a group is deleted we also need to delete the memberships. This was originally handled in `og_entity_delete()`. The roles and content was also deleted, but let's do this in separate PRs.\r\n\r\nThere are two ways of deleting memberships, depending on how large the site is: queued and non-queued. There is also a mechanism of preventing the deletion from taking place, to allow developers to provide their own implementation.","created_at":"2016-03-09T16:26:40Z","updated_at":"2016-04-06T09:39:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"74afbd30801e48c60a6cc1e1b29f15ee5acf64ae","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/amitaibu/og/pulls/162/commits","review_comments_url":"https://api.github.com/repos/amitaibu/og/pulls/162/comments","review_comment_url":"https://api.github.com/repos/amitaibu/og/pulls/comments{/number}","comments_url":"https://api.github.com/repos/amitaibu/og/issues/162/comments","statuses_url":"https://api.github.com/repos/amitaibu/og/statuses/e63d671f0da502e2d394fbc4a379869e1aaba5ee","head":{"label":"amitaibu:delete-memberships","ref":"delete-memberships","sha":"e63d671f0da502e2d394fbc4a379869e1aaba5ee","user":{"login":"amitaibu","id":125707,"avatar_url":"https://avatars.githubusercontent.com/u/125707?v=3","gravatar_id":"","url":"https://api.github.com/users/amitaibu","html_url":"https://github.com/amitaibu","followers_url":"https://api.github.com/users/amitaibu/followers","following_url":"https://api.github.com/users/amitaibu/following{/other_user}","gists_url":"https://api.github.com/users/amitaibu/gists{/gist_id}","starred_url":"https://api.github.com/users/amitaibu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amitaibu/subscriptions","organizations_url":"https://api.github.com/users/amitaibu/orgs","repos_url":"https://api.github.com/users/amitaibu/repos","events_url":"https://api.github.com/users/amitaibu/events{/privacy}","received_events_url":"https://api.github.com/users/amitaibu/received_events","type":"User","site_admin":false},"repo":{"id":42034806,"name":"og","full_name":"amitaibu/og","owner":{"login":"amitaibu","id":125707,"avatar_url":"https://avatars.githubusercontent.com/u/125707?v=3","gravatar_id":"","url":"https://api.github.com/users/amitaibu","html_url":"https://github.com/amitaibu","followers_url":"https://api.github.com/users/amitaibu/followers","following_url":"https://api.github.com/users/amitaibu/following{/other_user}","gists_url":"https://api.github.com/users/amitaibu/gists{/gist_id}","starred_url":"https://api.github.com/users/amitaibu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amitaibu/subscriptions","organizations_url":"https://api.github.com/users/amitaibu/orgs","repos_url":"https://api.github.com/users/amitaibu/repos","events_url":"https://api.github.com/users/amitaibu/events{/privacy}","received_events_url":"https://api.github.com/users/amitaibu/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/amitaibu/og","description":"https://www.drupal.org/project/og","fork":true,"url":"https://api.github.com/repos/amitaibu/og","forks_url":"https://api.github.com/repos/amitaibu/og/forks","keys_url":"https://api.github.com/repos/amitaibu/og/keys{/key_id}","collaborators_url":"https://api.github.com/repos/amitaibu/og/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/amitaibu/og/teams","hooks_url":"https://api.github.com/repos/amitaibu/og/hooks","issue_events_url":"https://api.github.com/repos/amitaibu/og/issues/events{/number}","events_url":"https://api.github.com/repos/amitaibu/og/events","assignees_url":"https://api.github.com/repos/amitaibu/og/assignees{/user}","branches_url":"https://api.github.com/repos/amitaibu/og/branches{/branch}","tags_url":"https://api.github.com/repos/amitaibu/og/tags","blobs_url":"https://api.github.com/repos/amitaibu/og/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/amitaibu/og/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/amitaibu/og/git/refs{/sha}","trees_url":"https://api.github.com/repos/amitaibu/og/git/trees{/sha}","statuses_url":"https://api.github.com/repos/amitaibu/og/statuses/{sha}","languages_url":"https://api.github.com/repos/amitaibu/og/languages","stargazers_url":"https://api.github.com/repos/amitaibu/og/stargazers","contributors_url":"https://api.github.com/repos/amitaibu/og/contributors","subscribers_url":"https://api.github.com/repos/amitaibu/og/subscribers","subscription_url":"https://api.github.com/repos/amitaibu/og/subscription","commits_url":"https://api.github.com/repos/amitaibu/og/commits{/sha}","git_commits_url":"https://api.github.com/repos/amitaibu/og/git/commits{/sha}","comments_url":"https://api.github.com/repos/amitaibu/og/comments{/number}","issue_comment_url":"https://api.github.com/repos/amitaibu/og/issues/comments{/number}","contents_url":"https://api.github.com/repos/amitaibu/og/contents/{+path}","compare_url":"https://api.github.com/repos/amitaibu/og/compare/{base}...{head}","merges_url":"https://api.github.com/repos/amitaibu/og/merges","archive_url":"https://api.github.com/repos/amitaibu/og/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/amitaibu/og/downloads","issues_url":"https://api.github.com/repos/amitaibu/og/issues{/number}","pulls_url":"https://api.github.com/repos/amitaibu/og/pulls{/number}","milestones_url":"https://api.github.com/repos/amitaibu/og/milestones{/number}","notifications_url":"https://api.github.com/repos/amitaibu/og/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/amitaibu/og/labels{/name}","releases_url":"https://api.github.com/repos/amitaibu/og/releases{/id}","deployments_url":"https://api.github.com/repos/amitaibu/og/deployments","created_at":"2015-09-07T06:16:12Z","updated_at":"2016-03-24T20:36:18Z","pushed_at":"2016-04-06T07:35:24Z","git_url":"git://github.com/amitaibu/og.git","ssh_url":"git@github.com:amitaibu/og.git","clone_url":"https://github.com/amitaibu/og.git","svn_url":"https://github.com/amitaibu/og","homepage":"","size":5770,"stargazers_count":18,"watchers_count":18,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":51,"forks":11,"open_issues":51,"watchers":18,"default_branch":"8.x-1.x"}},"base":{"label":"amitaibu:8.x-1.x","ref":"8.x-1.x","sha":"a9296943febeb86014e42857421a0ad982de5e26","user":{"login":"amitaibu","id":125707,"avatar_url":"https://avatars.githubusercontent.com/u/125707?v=3","gravatar_id":"","url":"https://api.github.com/users/amitaibu","html_url":"https://github.com/amitaibu","followers_url":"https://api.github.com/users/amitaibu/followers","following_url":"https://api.github.com/users/amitaibu/following{/other_user}","gists_url":"https://api.github.com/users/amitaibu/gists{/gist_id}","starred_url":"https://api.github.com/users/amitaibu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amitaibu/subscriptions","organizations_url":"https://api.github.com/users/amitaibu/orgs","repos_url":"https://api.github.com/users/amitaibu/repos","events_url":"https://api.github.com/users/amitaibu/events{/privacy}","received_events_url":"https://api.github.com/users/amitaibu/received_events","type":"User","site_admin":false},"repo":{"id":42034806,"name":"og","full_name":"amitaibu/og","owner":{"login":"amitaibu","id":125707,"avatar_url":"https://avatars.githubusercontent.com/u/125707?v=3","gravatar_id":"","url":"https://api.github.com/users/amitaibu","html_url":"https://github.com/amitaibu","followers_url":"https://api.github.com/users/amitaibu/followers","following_url":"https://api.github.com/users/amitaibu/following{/other_user}","gists_url":"https://api.github.com/users/amitaibu/gists{/gist_id}","starred_url":"https://api.github.com/users/amitaibu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amitaibu/subscriptions","organizations_url":"https://api.github.com/users/amitaibu/orgs","repos_url":"https://api.github.com/users/amitaibu/repos","events_url":"https://api.github.com/users/amitaibu/events{/privacy}","received_events_url":"https://api.github.com/users/amitaibu/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/amitaibu/og","description":"https://www.drupal.org/project/og","fork":true,"url":"https://api.github.com/repos/amitaibu/og","forks_url":"https://api.github.com/repos/amitaibu/og/forks","keys_url":"https://api.github.com/repos/amitaibu/og/keys{/key_id}","collaborators_url":"https://api.github.com/repos/amitaibu/og/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/amitaibu/og/teams","hooks_url":"https://api.github.com/repos/amitaibu/og/hooks","issue_events_url":"https://api.github.com/repos/amitaibu/og/issues/events{/number}","events_url":"https://api.github.com/repos/amitaibu/og/events","assignees_url":"https://api.github.com/repos/amitaibu/og/assignees{/user}","branches_url":"https://api.github.com/repos/amitaibu/og/branches{/branch}","tags_url":"https://api.github.com/repos/amitaibu/og/tags","blobs_url":"https://api.github.com/repos/amitaibu/og/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/amitaibu/og/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/amitaibu/og/git/refs{/sha}","trees_url":"https://api.github.com/repos/amitaibu/og/git/trees{/sha}","statuses_url":"https://api.github.com/repos/amitaibu/og/statuses/{sha}","languages_url":"https://api.github.com/repos/amitaibu/og/languages","stargazers_url":"https://api.github.com/repos/amitaibu/og/stargazers","contributors_url":"https://api.github.com/repos/amitaibu/og/contributors","subscribers_url":"https://api.github.com/repos/amitaibu/og/subscribers","subscription_url":"https://api.github.com/repos/amitaibu/og/subscription","commits_url":"https://api.github.com/repos/amitaibu/og/commits{/sha}","git_commits_url":"https://api.github.com/repos/amitaibu/og/git/commits{/sha}","comments_url":"https://api.github.com/repos/amitaibu/og/comments{/number}","issue_comment_url":"https://api.github.com/repos/amitaibu/og/issues/comments{/number}","contents_url":"https://api.github.com/repos/amitaibu/og/contents/{+path}","compare_url":"https://api.github.com/repos/amitaibu/og/compare/{base}...{head}","merges_url":"https://api.github.com/repos/amitaibu/og/merges","archive_url":"https://api.github.com/repos/amitaibu/og/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/amitaibu/og/downloads","issues_url":"https://api.github.com/repos/amitaibu/og/issues{/number}","pulls_url":"https://api.github.com/repos/amitaibu/og/pulls{/number}","milestones_url":"https://api.github.com/repos/amitaibu/og/milestones{/number}","notifications_url":"https://api.github.com/repos/amitaibu/og/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/amitaibu/og/labels{/name}","releases_url":"https://api.github.com/repos/amitaibu/og/releases{/id}","deployments_url":"https://api.github.com/repos/amitaibu/og/deployments","created_at":"2015-09-07T06:16:12Z","updated_at":"2016-03-24T20:36:18Z","pushed_at":"2016-04-06T07:35:24Z","git_url":"git://github.com/amitaibu/og.git","ssh_url":"git@github.com:amitaibu/og.git","clone_url":"https://github.com/amitaibu/og.git","svn_url":"https://github.com/amitaibu/og","homepage":"","size":5770,"stargazers_count":18,"watchers_count":18,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":51,"forks":11,"open_issues":51,"watchers":18,"default_branch":"8.x-1.x"}},"_links":{"self":{"href":"https://api.github.com/repos/amitaibu/og/pulls/162"},"html":{"href":"https://github.com/amitaibu/og/pull/162"},"issue":{"href":"https://api.github.com/repos/amitaibu/og/issues/162"},"comments":{"href":"https://api.github.com/repos/amitaibu/og/issues/162/comments"},"review_comments":{"href":"https://api.github.com/repos/amitaibu/og/pulls/162/comments"},"review_comment":{"href":"https://api.github.com/repos/amitaibu/og/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/amitaibu/og/pulls/162/commits"},"statuses":{"href":"https://api.github.com/repos/amitaibu/og/statuses/e63d671f0da502e2d394fbc4a379869e1aaba5ee"}}}}