Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / core / modules / content_moderation / tests / src / Kernel / ViewsModerationStateFilterTest.php
1 <?php
2
3 namespace Drupal\Tests\content_moderation\Kernel;
4
5 use Drupal\entity_test\Entity\EntityTestNoBundle;
6 use Drupal\language\Entity\ConfigurableLanguage;
7 use Drupal\node\Entity\Node;
8 use Drupal\node\Entity\NodeType;
9 use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
10 use Drupal\views\Views;
11 use Drupal\workflows\Entity\Workflow;
12
13 /**
14  * Tests the views 'moderation_state_filter' filter plugin.
15  *
16  * @coversDefaultClass \Drupal\content_moderation\Plugin\views\filter\ModerationStateFilter
17  *
18  * @group content_moderation
19  */
20 class ViewsModerationStateFilterTest extends ViewsKernelTestBase {
21
22   /**
23    * {@inheritdoc}
24    */
25   public static $modules = [
26     'content_moderation_test_views',
27     'node',
28     'content_moderation',
29     'workflows',
30     'workflow_type_test',
31     'entity_test',
32     'language',
33     'content_translation',
34   ];
35
36   /**
37    * {@inheritdoc}
38    */
39   protected function setUp($import_test_views = TRUE) {
40     parent::setUp(FALSE);
41
42     $this->installEntitySchema('user');
43     $this->installEntitySchema('node');
44     $this->installEntitySchema('content_moderation_state');
45     $this->installEntitySchema('entity_test_no_bundle');
46     $this->installSchema('node', 'node_access');
47     $this->installConfig('content_moderation_test_views');
48     $this->installConfig('content_moderation');
49
50     $node_type = NodeType::create([
51       'type' => 'example',
52     ]);
53     $node_type->save();
54
55     $node_type = NodeType::create([
56       'type' => 'another_example',
57     ]);
58     $node_type->save();
59
60     $node_type = NodeType::create([
61       'type' => 'example_non_moderated',
62     ]);
63     $node_type->save();
64
65     ConfigurableLanguage::createFromLangcode('fr')->save();
66   }
67
68   /**
69    * Tests the content moderation state filter.
70    */
71   public function testStateFilterViewsRelationship() {
72     $workflow = Workflow::load('editorial');
73     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
74     $workflow->getTypePlugin()->addState('translated_draft', 'Bar');
75     $configuration = $workflow->getTypePlugin()->getConfiguration();
76     $configuration['states']['translated_draft'] += [
77       'published' => FALSE,
78       'default_revision' => FALSE,
79     ];
80     $workflow->getTypePlugin()->setConfiguration($configuration);
81     $workflow->save();
82
83     // Create a published default revision and one forward draft revision.
84     $node = Node::create([
85       'type' => 'example',
86       'title' => 'Test Node',
87       'moderation_state' => 'published',
88     ]);
89     $node->save();
90     $node->setNewRevision();
91     $node->moderation_state = 'draft';
92     $node->save();
93
94     // Create a draft default revision.
95     $second_node = Node::create([
96       'type' => 'example',
97       'title' => 'Second Node',
98       'moderation_state' => 'draft',
99     ]);
100     $second_node->save();
101
102     // Create a published default revision.
103     $third_node = Node::create([
104       'type' => 'example',
105       'title' => 'Third node',
106       'moderation_state' => 'published',
107     ]);
108     $third_node->save();
109
110     // Add a non-moderated node.
111     $fourth_node = Node::create([
112       'type' => 'example_non_moderated',
113       'title' => 'Fourth node',
114     ]);
115     $fourth_node->save();
116
117     // Create a translated published revision.
118     $translated_forward_revision = $third_node->addTranslation('fr');
119     $translated_forward_revision->title = 'Translated Node';
120     $translated_forward_revision->setNewRevision(TRUE);
121     $translated_forward_revision->moderation_state = 'translated_draft';
122     $translated_forward_revision->save();
123
124     // The three default revisions are listed when no filter is specified.
125     $this->assertNodesWithFilters([$node, $second_node, $third_node], []);
126
127     // The default revision of node one and three are published.
128     $this->assertNodesWithFilters([$node, $third_node], [
129       'default_revision_state' => 'editorial-published',
130     ]);
131
132     // The default revision of node two is draft.
133     $this->assertNodesWithFilters([$second_node], [
134       'default_revision_state' => 'editorial-draft',
135     ]);
136
137     // Test the same three revisions on a view displaying content revisions.
138     // Both nodes have one draft revision.
139     $this->assertNodesWithFilters([$node, $second_node], [
140       'moderation_state' => 'editorial-draft',
141     ], 'test_content_moderation_state_filter_revision_table');
142     // Creating a new forward revision of node three, creates a second published
143     // revision of of the original language, hence there are two published
144     // revisions of node three.
145     $this->assertNodesWithFilters([$node, $third_node, $third_node], [
146       'moderation_state' => 'editorial-published',
147     ], 'test_content_moderation_state_filter_revision_table');
148     // There is a single forward translated revision with a new state, which is
149     // also filterable.
150     $this->assertNodesWithFilters([$translated_forward_revision], [
151       'moderation_state' => 'editorial-translated_draft',
152     ], 'test_content_moderation_state_filter_revision_table');
153   }
154
155   /**
156    * Test the moderation filter with a non-translatable entity type.
157    */
158   public function testNonTranslatableEntityType() {
159     $workflow = Workflow::load('editorial');
160     $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_no_bundle', 'entity_test_no_bundle');
161     $workflow->save();
162
163     $test_entity = EntityTestNoBundle::create([
164       'moderation_state' => 'draft',
165     ]);
166     $test_entity->save();
167
168     $view = Views::getView('test_content_moderation_state_filter_entity_test');
169     $view->setExposedInput([
170       'moderation_state' => 'editorial-draft',
171     ]);
172     $view->execute();
173     $this->assertIdenticalResultset($view, [['id' => $test_entity->id()]], ['id' => 'id']);
174   }
175
176   /**
177    * Tests the list of states in the filter plugin.
178    */
179   public function testStateFilterStatesList() {
180     // By default a view of nodes will not have states to filter.
181     $this->assertPluginStates([]);
182
183     // Adding a content type to the editorial workflow will enable all of the
184     // editorial states.
185     $workflow = Workflow::load('editorial');
186     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
187     $workflow->save();
188     $this->assertPluginStates([
189       'Editorial' => [
190         'editorial-draft' => 'Draft',
191         'editorial-published' => 'Published',
192         'editorial-archived' => 'Archived',
193       ],
194     ]);
195
196     // Adding a workflow which is not content moderation will not add any
197     // additional states to the views filter.
198     $workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_complex_test']);
199     $workflow->getTypePlugin()->addState('draft', 'Draft');
200     $workflow->save();
201     $this->assertPluginStates([
202       'Editorial' => [
203         'editorial-draft' => 'Draft',
204         'editorial-published' => 'Published',
205         'editorial-archived' => 'Archived',
206       ],
207     ]);
208
209     // Adding a new content moderation workflow will add additional states to
210     // filter.
211     $workflow = Workflow::create(['id' => 'moderation_test', 'type' => 'content_moderation', 'label' => 'Moderation test']);
212     $workflow->getTypePlugin()->addState('foo', 'Foo State');
213     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
214     $workflow->save();
215     $this->assertPluginStates([
216       'Editorial' => [
217         'editorial-draft' => 'Draft',
218         'editorial-published' => 'Published',
219         'editorial-archived' => 'Archived',
220       ],
221       'Moderation test' => [
222         'moderation_test-foo' => 'Foo State',
223         'moderation_test-draft' => 'Draft',
224         'moderation_test-published' => 'Published',
225       ],
226     ]);
227
228     // Deleting a workflow will remove the states from the filter.
229     $workflow = Workflow::load('moderation_test');
230     $workflow->delete();
231     $this->assertPluginStates([
232       'Editorial' => [
233         'editorial-draft' => 'Draft',
234         'editorial-published' => 'Published',
235         'editorial-archived' => 'Archived',
236       ],
237     ]);
238
239     // Deleting a state from a workflow will remove the state from the filter.
240     $workflow = Workflow::load('editorial');
241     $workflow->getTypePlugin()->deleteState('archived');
242     $workflow->save();
243     $this->assertPluginStates([
244       'Editorial' => [
245         'editorial-draft' => 'Draft',
246         'editorial-published' => 'Published',
247       ],
248     ]);
249   }
250
251   /**
252    * Assert the plugin states.
253    *
254    * @param string[] $states
255    *   The states which should appear in the filter.
256    */
257   protected function assertPluginStates($states) {
258     $plugin = Views::pluginManager('filter')->createInstance('moderation_state_filter', []);
259     $view = Views::getView('test_content_moderation_state_filter_base_table');
260     $plugin->init($view, $view->getDisplay());
261     $this->assertEquals($states, $plugin->getValueOptions());
262   }
263
264   /**
265    * Assert the nodes appear when the test view is executed.
266    *
267    * @param \Drupal\node\NodeInterface[] $nodes
268    *   Nodes to assert are in the views result.
269    * @param array $filters
270    *   An array of filters to apply to the view.
271    * @param string $view_id
272    *   The view to execute for the results.
273    */
274   protected function assertNodesWithFilters(array $nodes, array $filters, $view_id = 'test_content_moderation_state_filter_base_table') {
275     $view = Views::getView($view_id);
276     $view->setExposedInput($filters);
277     $view->execute();
278
279     // Verify the join configuration.
280     $query = $view->getQuery();
281     $join = $query->getTableInfo('content_moderation_state')['join'];
282     $configuration = $join->configuration;
283     $this->assertEquals('content_moderation_state_field_revision', $configuration['table']);
284     $this->assertEquals('content_entity_revision_id', $configuration['field']);
285     $this->assertEquals('vid', $configuration['left_field']);
286     $this->assertEquals('content_entity_type_id', $configuration['extra'][0]['field']);
287     $this->assertEquals('node', $configuration['extra'][0]['value']);
288     $this->assertEquals('langcode', $configuration['extra'][1]['field']);
289     $this->assertEquals('langcode', $configuration['extra'][1]['left_field']);
290
291     $expected_result = [];
292     foreach ($nodes as $node) {
293       $expected_result[] = ['nid' => $node->id()];
294     }
295     $this->assertIdenticalResultset($view, $expected_result, ['nid' => 'nid']);
296   }
297
298 }