Version 1
[yaffs-website] / web / core / modules / views / tests / src / Functional / Handler / HandlerTest.php
1 <?php
2
3 namespace Drupal\Tests\views\Functional\Handler;
4
5 use Drupal\comment\Tests\CommentTestTrait;
6 use Drupal\Tests\views\Functional\ViewTestBase;
7 use Drupal\views\Entity\View;
8 use Drupal\views\ViewExecutable;
9 use Drupal\views\Plugin\views\HandlerBase;
10 use Drupal\views\Views;
11
12 /**
13  * Tests abstract handler definitions.
14  *
15  * @group views
16  */
17 class HandlerTest extends ViewTestBase {
18
19   use CommentTestTrait;
20
21   /**
22    * Views used by this test.
23    *
24    * @var array
25    */
26   public static $testViews = ['test_view', 'test_view_handler_weight', 'test_handler_relationships', 'test_handler_test_access', 'test_filter_in_operator_ui'];
27
28   /**
29    * Modules to enable.
30    *
31    * @var array
32    */
33   public static $modules = ['views_ui', 'comment', 'node'];
34
35   protected function setUp($import_test_views = TRUE) {
36     parent::setUp($import_test_views);
37     $this->drupalCreateContentType(['type' => 'page']);
38     $this->addDefaultCommentField('node', 'page');
39     $this->enableViewsTestModule();
40   }
41
42   /**
43    * {@inheritdoc}
44    */
45   protected function viewsData() {
46     $data = parent::viewsData();
47     // Override the name handler to be able to call placeholder() from outside.
48     $data['views_test_data']['name']['field']['id'] = 'test_field';
49
50     // Setup one field with an access callback and one with an access callback
51     // and arguments.
52     $data['views_test_data']['access_callback'] = $data['views_test_data']['id'];
53     $data['views_test_data']['access_callback_arguments'] = $data['views_test_data']['id'];
54     foreach (ViewExecutable::getHandlerTypes() as $type => $info) {
55       if (isset($data['views_test_data']['access_callback'][$type]['id'])) {
56         $data['views_test_data']['access_callback'][$type]['access callback'] = 'views_test_data_handler_test_access_callback';
57
58         $data['views_test_data']['access_callback_arguments'][$type]['access callback'] = 'views_test_data_handler_test_access_callback_argument';
59         $data['views_test_data']['access_callback_arguments'][$type]['access arguments'] = [TRUE];
60       }
61     }
62
63     return $data;
64   }
65
66   /**
67    * Tests the breakString method.
68    */
69   public function testBreakString() {
70     // Check defaults.
71     $this->assertEqual((object) ['value' => [], 'operator' => NULL], HandlerBase::breakString(''));
72
73     // Test ors
74     $handler = HandlerBase::breakString('word1 word2+word');
75     $this->assertEqualValue(['word1', 'word2', 'word'], $handler);
76     $this->assertEqual('or', $handler->operator);
77     $handler = HandlerBase::breakString('word1+word2+word');
78     $this->assertEqualValue(['word1', 'word2', 'word'], $handler);
79     $this->assertEqual('or', $handler->operator);
80     $handler = HandlerBase::breakString('word1 word2 word');
81     $this->assertEqualValue(['word1', 'word2', 'word'], $handler);
82     $this->assertEqual('or', $handler->operator);
83     $handler = HandlerBase::breakString('word-1+word-2+word');
84     $this->assertEqualValue(['word-1', 'word-2', 'word'], $handler);
85     $this->assertEqual('or', $handler->operator);
86     $handler = HandlerBase::breakString('wõrd1+wõrd2+wõrd');
87     $this->assertEqualValue(['wõrd1', 'wõrd2', 'wõrd'], $handler);
88     $this->assertEqual('or', $handler->operator);
89
90     // Test ands.
91     $handler = HandlerBase::breakString('word1,word2,word');
92     $this->assertEqualValue(['word1', 'word2', 'word'], $handler);
93     $this->assertEqual('and', $handler->operator);
94     $handler = HandlerBase::breakString('word1 word2,word');
95     $this->assertEqualValue(['word1 word2', 'word'], $handler);
96     $this->assertEqual('and', $handler->operator);
97     $handler = HandlerBase::breakString('word1,word2 word');
98     $this->assertEqualValue(['word1', 'word2 word'], $handler);
99     $this->assertEqual('and', $handler->operator);
100     $handler = HandlerBase::breakString('word-1,word-2,word');
101     $this->assertEqualValue(['word-1', 'word-2', 'word'], $handler);
102     $this->assertEqual('and', $handler->operator);
103     $handler = HandlerBase::breakString('wõrd1,wõrd2,wõrd');
104     $this->assertEqualValue(['wõrd1', 'wõrd2', 'wõrd'], $handler);
105     $this->assertEqual('and', $handler->operator);
106
107     // Test a single word
108     $handler = HandlerBase::breakString('word');
109     $this->assertEqualValue(['word'], $handler);
110     $this->assertEqual('and', $handler->operator);
111
112     $s1 = $this->randomMachineName();
113     // Generate three random numbers which can be used below;
114     $n1 = rand(0, 100);
115     $n2 = rand(0, 100);
116     $n3 = rand(0, 100);
117
118     // Test "or"s.
119     $handlerBase = HandlerBase::breakString("$s1 $n2+$n3");
120     $this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
121     $this->assertEqual('or', $handlerBase->operator);
122
123     $handlerBase = HandlerBase::breakString("$s1+$n2+$n3");
124     $this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
125     $this->assertEqual('or', $handlerBase->operator);
126
127     $handlerBase = HandlerBase::breakString("$s1 $n2 $n3");
128     $this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
129     $this->assertEqual('or', $handlerBase->operator);
130
131     $handlerBase = HandlerBase::breakString("$s1 $n2++$n3");
132     $this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
133     $this->assertEqual('or', $handlerBase->operator);
134
135     // Test "and"s.
136     $handlerBase = HandlerBase::breakString("$s1,$n2,$n3");
137     $this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
138     $this->assertEqual('and', $handlerBase->operator);
139
140     $handlerBase = HandlerBase::breakString("$s1,,$n2,$n3");
141     $this->assertEqualValue([$s1, $n2, $n3], $handlerBase);
142     $this->assertEqual('and', $handlerBase->operator);
143
144     // Enforce int values.
145     $handlerBase = HandlerBase::breakString("$n1,$n2,$n3", TRUE);
146     $this->assertEqualValue([$n1, $n2, $n3], $handlerBase);
147     $this->assertEqual('and', $handlerBase->operator);
148
149     $handlerBase = HandlerBase::breakString("$n1+$n2+$n3", TRUE);
150     $this->assertEqualValue([$n1, $n2, $n3], $handlerBase);
151     $this->assertEqual('or', $handlerBase->operator);
152
153     $handlerBase = HandlerBase::breakString("$s1,$n2,$n3", TRUE);
154     $this->assertEqualValue([(int) $s1, $n2, $n3], $handlerBase);
155     $this->assertEqual('and', $handlerBase->operator);
156
157     $handlerBase = HandlerBase::breakString("$s1+$n2+$n3", TRUE);
158     $this->assertEqualValue([(int) $s1, $n2, $n3], $handlerBase);
159     $this->assertEqual('or', $handlerBase->operator);
160
161     // Generate three random decimals which can be used below;
162     $d1 = rand(0, 10) / 10;
163     $d2 = rand(0, 10) / 10;
164     $d3 = rand(0, 10) / 10;
165
166     // Test "or"s.
167     $handlerBase = HandlerBase::breakString("$s1 $d1+$d2");
168     $this->assertEqualValue([$s1, $d1, $d2], $handlerBase);
169     $this->assertEqual('or', $handlerBase->operator);
170
171     $handlerBase = HandlerBase::breakString("$s1+$d1+$d3");
172     $this->assertEqualValue([$s1, $d1, $d3], $handlerBase);
173     $this->assertEqual('or', $handlerBase->operator);
174
175     $handlerBase = HandlerBase::breakString("$s1 $d2 $d3");
176     $this->assertEqualValue([$s1, $d2, $d3], $handlerBase);
177     $this->assertEqual('or', $handlerBase->operator);
178
179     $handlerBase = HandlerBase::breakString("$s1 $d2++$d3");
180     $this->assertEqualValue([$s1, $d2, $d3], $handlerBase);
181     $this->assertEqual('or', $handlerBase->operator);
182
183     // Test "and"s.
184     $handlerBase = HandlerBase::breakString("$s1,$d2,$d3");
185     $this->assertEqualValue([$s1, $d2, $d3], $handlerBase);
186     $this->assertEqual('and', $handlerBase->operator);
187
188     $handlerBase = HandlerBase::breakString("$s1,,$d2,$d3");
189     $this->assertEqualValue([$s1, $d2, $d3], $handlerBase);
190     $this->assertEqual('and', $handlerBase->operator);
191   }
192
193   /**
194    * Tests the order of handlers is the same before and after saving.
195    */
196   public function testHandlerWeights() {
197     $handler_types = ['fields', 'filters', 'sorts'];
198
199     $view = Views::getView('test_view_handler_weight');
200     $view->initDisplay();
201
202     // Store the order of handlers before saving the view.
203     $original_order = [];
204     foreach ($handler_types as $type) {
205       $original_order[$type] = array_keys($view->display_handler->getOption($type));
206     }
207
208     // Save the view and see if our filters are in the same order.
209     $view->save();
210     $view = views::getView('test_view_handler_weight');
211     $view->initDisplay();
212
213     foreach ($handler_types as $type) {
214       $loaded_order = array_keys($view->display_handler->getOption($type));
215       $this->assertIdentical($original_order[$type], $loaded_order);
216     }
217   }
218
219   /**
220    * Check to see if a value is the same as the value on a certain handler.
221    *
222    * @param $expected
223    *   The expected value to check.
224    * @param \Drupal\views\Plugin\views\ViewsHandlerInterface $handler
225    *   The handler that has the $handler->value property to compare with first.
226    * @param string $message
227    *   The message to display along with the assertion.
228    * @param string $group
229    *   The type of assertion - examples are "Browser", "PHP".
230    *
231    * @return bool
232    *   TRUE if the assertion succeeded, FALSE otherwise.
233    */
234   protected function assertEqualValue($expected, $handler, $message = '', $group = 'Other') {
235     if (empty($message)) {
236       $message = t('Comparing @first and @second', ['@first' => implode(',', $expected), '@second' => implode(',', $handler->value)]);
237     }
238
239     return $this->assert($expected == $handler->value, $message, $group);
240   }
241
242   /**
243    * Tests the relationship ui for field/filter/argument/relationship.
244    */
245   public function testRelationshipUI() {
246     $views_admin = $this->drupalCreateUser(['administer views']);
247     $this->drupalLogin($views_admin);
248
249     // Make sure the link to the field options exists.
250     $handler_options_path = 'admin/structure/views/nojs/handler/test_handler_relationships/default/field/title';
251     $view_edit_path = 'admin/structure/views/view/test_handler_relationships/edit';
252     $this->drupalGet($view_edit_path);
253     $this->assertLinkByHref($handler_options_path);
254
255     // The test view has a relationship to node_revision so the field should
256     // show a relationship selection.
257
258     $this->drupalGet($handler_options_path);
259     $relationship_name = 'options[relationship]';
260     $this->assertFieldByName($relationship_name);
261
262     // Check for available options.
263     $fields = $this->getSession()->getPage()->findAll('named_exact', ['field', $relationship_name]);
264     $options = [];
265     foreach ($fields as $field) {
266       $items = $field->findAll('css', 'option');
267       foreach ($items as $item) {
268         $options[] = $item->getAttribute('value');
269       }
270     }
271     $expected_options = ['none', 'nid'];
272     $this->assertEqual($options, $expected_options);
273
274     // Remove the relationship and make sure no relationship option appears.
275     $this->drupalPostForm('admin/structure/views/nojs/handler/test_handler_relationships/default/relationship/nid', [], t('Remove'));
276     $this->drupalGet($handler_options_path);
277     $this->assertNoFieldByName($relationship_name, NULL, 'Make sure that no relationship option is available');
278
279     // Create a view of comments with node relationship.
280     View::create(['base_table' => 'comment_field_data', 'id' => 'test_get_entity_type'])->save();
281     $this->drupalPostForm('admin/structure/views/nojs/add-handler/test_get_entity_type/default/relationship', ['name[comment_field_data.node]' => 'comment_field_data.node'], t('Add and configure relationships'));
282     $this->drupalPostForm(NULL, [], t('Apply'));
283     // Add a content type filter.
284     $this->drupalPostForm('admin/structure/views/nojs/add-handler/test_get_entity_type/default/filter', ['name[node_field_data.type]' => 'node_field_data.type'], t('Add and configure filter criteria'));
285     $this->assertOptionSelected('edit-options-relationship', 'node');
286     $this->drupalPostForm(NULL, ['options[value][page]' => 'page'], t('Apply'));
287     // Check content type filter options.
288     $this->drupalGet('admin/structure/views/nojs/handler/test_get_entity_type/default/filter/type');
289     $this->assertOptionSelected('edit-options-relationship', 'node');
290     $this->assertFieldChecked('edit-options-value-page');
291   }
292
293   /**
294    * Tests the relationship method on the base class.
295    */
296   public function testSetRelationship() {
297     $view = Views::getView('test_handler_relationships');
298     $view->setDisplay();
299     // Setup a broken relationship.
300     $view->addHandler('default', 'relationship', $this->randomMachineName(), $this->randomMachineName(), [], 'broken_relationship');
301     // Setup a valid relationship.
302     $view->addHandler('default', 'relationship', 'comment_field_data', 'node', ['relationship' => 'cid'], 'valid_relationship');
303     $view->initHandlers();
304     $field = $view->field['title'];
305
306     $field->options['relationship'] = NULL;
307     $field->setRelationship();
308     $this->assertFalse($field->relationship, 'Make sure that an empty relationship does not create a relationship on the field.');
309
310     $field->options['relationship'] = $this->randomMachineName();
311     $field->setRelationship();
312     $this->assertFalse($field->relationship, 'Make sure that a random relationship does not create a relationship on the field.');
313
314     $field->options['relationship'] = 'broken_relationship';
315     $field->setRelationship();
316     $this->assertFalse($field->relationship, 'Make sure that a broken relationship does not create a relationship on the field.');
317
318     $field->options['relationship'] = 'valid_relationship';
319     $field->setRelationship();
320     $this->assertFalse(!empty($field->relationship), 'Make sure that the relationship alias was not set without building a views query before.');
321
322     // Remove the invalid relationship.
323     unset($view->relationship['broken_relationship']);
324
325     $view->build();
326     $field->setRelationship();
327     $this->assertEqual($field->relationship, $view->relationship['valid_relationship']->alias, 'Make sure that a valid relationship does create the right relationship query alias.');
328   }
329
330   /**
331    * Tests the placeholder function.
332    *
333    * @see \Drupal\views\Plugin\views\HandlerBase::placeholder()
334    */
335   public function testPlaceholder() {
336     $view = Views::getView('test_view');
337     $view->initHandlers();
338     $view->initQuery();
339
340     $handler = $view->field['name'];
341     $table = $handler->table;
342     $field = $handler->field;
343     $string = ':' . $table . '_' . $field;
344
345     // Make sure the placeholder variables are like expected.
346     $this->assertEqual($handler->getPlaceholder(), $string);
347     $this->assertEqual($handler->getPlaceholder(), $string . 1);
348     $this->assertEqual($handler->getPlaceholder(), $string . 2);
349
350     // Set another table/field combination and make sure there are new
351     // placeholders.
352     $table = $handler->table = $this->randomMachineName();
353     $field = $handler->field = $this->randomMachineName();
354     $string = ':' . $table . '_' . $field;
355
356     // Make sure the placeholder variables are like expected.
357     $this->assertEqual($handler->getPlaceholder(), $string);
358     $this->assertEqual($handler->getPlaceholder(), $string . 1);
359     $this->assertEqual($handler->getPlaceholder(), $string . 2);
360   }
361
362   /**
363    * Tests access to a handler.
364    *
365    * @see views_test_data_handler_test_access_callback
366    */
367   public function testAccess() {
368     $view = Views::getView('test_handler_test_access');
369     $views_data = $this->viewsData();
370     $views_data = $views_data['views_test_data'];
371
372     // Enable access to callback only field and deny for callback + arguments.
373     $this->config('views_test_data.tests')->set('handler_access_callback', TRUE)->save();
374     $this->config('views_test_data.tests')->set('handler_access_callback_argument', FALSE)->save();
375     $view->initDisplay();
376     $view->initHandlers();
377
378     foreach ($views_data['access_callback'] as $type => $info) {
379       if (!in_array($type, ['title', 'help'])) {
380         $this->assertTrue($view->field['access_callback'] instanceof HandlerBase, 'Make sure the user got access to the access_callback field ');
381         $this->assertFalse(isset($view->field['access_callback_arguments']), 'Make sure the user got no access to the access_callback_arguments field ');
382       }
383     }
384
385     // Enable access to the callback + argument handlers and deny for callback.
386     $this->config('views_test_data.tests')->set('handler_access_callback', FALSE)->save();
387     $this->config('views_test_data.tests')->set('handler_access_callback_argument', TRUE)->save();
388     $view->destroy();
389     $view->initDisplay();
390     $view->initHandlers();
391
392     foreach ($views_data['access_callback'] as $type => $info) {
393       if (!in_array($type, ['title', 'help'])) {
394         $this->assertFalse(isset($view->field['access_callback']), 'Make sure the user got no access to the access_callback field ');
395         $this->assertTrue($view->field['access_callback_arguments'] instanceof HandlerBase, 'Make sure the user got access to the access_callback_arguments field ');
396       }
397     }
398   }
399
400 }