Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\search\Tests;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
Chris@0
|
6 use Drupal\comment\Tests\CommentTestTrait;
|
Chris@0
|
7 use Drupal\Core\Url;
|
Chris@0
|
8 use Drupal\filter\Entity\FilterFormat;
|
Chris@0
|
9 use Drupal\search\Entity\SearchPage;
|
Chris@0
|
10
|
Chris@0
|
11 /**
|
Chris@0
|
12 * Indexes content and tests ranking factors.
|
Chris@0
|
13 *
|
Chris@0
|
14 * @group search
|
Chris@0
|
15 */
|
Chris@0
|
16 class SearchRankingTest extends SearchTestBase {
|
Chris@0
|
17
|
Chris@0
|
18 use CommentTestTrait;
|
Chris@0
|
19
|
Chris@0
|
20 /**
|
Chris@0
|
21 * The node search page.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @var \Drupal\search\SearchPageInterface
|
Chris@0
|
24 */
|
Chris@0
|
25 protected $nodeSearch;
|
Chris@0
|
26
|
Chris@0
|
27 /**
|
Chris@0
|
28 * Modules to enable.
|
Chris@0
|
29 *
|
Chris@0
|
30 * @var array
|
Chris@0
|
31 */
|
Chris@0
|
32 public static $modules = ['statistics', 'comment'];
|
Chris@0
|
33
|
Chris@0
|
34 protected function setUp() {
|
Chris@0
|
35 parent::setUp();
|
Chris@0
|
36
|
Chris@0
|
37 // Create a plugin instance.
|
Chris@0
|
38 $this->nodeSearch = SearchPage::load('node_search');
|
Chris@0
|
39
|
Chris@0
|
40 // Log in with sufficient privileges.
|
Chris@0
|
41 $this->drupalLogin($this->drupalCreateUser(['post comments', 'skip comment approval', 'create page content', 'administer search']));
|
Chris@0
|
42 }
|
Chris@0
|
43
|
Chris@0
|
44 public function testRankings() {
|
Chris@0
|
45 // Add a comment field.
|
Chris@0
|
46 $this->addDefaultCommentField('node', 'page');
|
Chris@0
|
47
|
Chris@0
|
48 // Build a list of the rankings to test.
|
Chris@0
|
49 $node_ranks = ['sticky', 'promote', 'relevance', 'recent', 'comments', 'views'];
|
Chris@0
|
50
|
Chris@0
|
51 // Create nodes for testing.
|
Chris@0
|
52 $nodes = [];
|
Chris@0
|
53 foreach ($node_ranks as $node_rank) {
|
Chris@0
|
54 $settings = [
|
Chris@0
|
55 'type' => 'page',
|
Chris@0
|
56 'comment' => [
|
Chris@0
|
57 ['status' => CommentItemInterface::HIDDEN],
|
Chris@0
|
58 ],
|
Chris@0
|
59 'title' => 'Drupal rocks',
|
Chris@0
|
60 'body' => [['value' => "Drupal's search rocks"]],
|
Chris@0
|
61 // Node is one day old.
|
Chris@0
|
62 'created' => REQUEST_TIME - 24 * 3600,
|
Chris@0
|
63 'sticky' => 0,
|
Chris@0
|
64 'promote' => 0,
|
Chris@0
|
65 ];
|
Chris@0
|
66 foreach ([0, 1] as $num) {
|
Chris@0
|
67 if ($num == 1) {
|
Chris@0
|
68 switch ($node_rank) {
|
Chris@0
|
69 case 'sticky':
|
Chris@0
|
70 case 'promote':
|
Chris@0
|
71 $settings[$node_rank] = 1;
|
Chris@0
|
72 break;
|
Chris@0
|
73 case 'relevance':
|
Chris@0
|
74 $settings['body'][0]['value'] .= " really rocks";
|
Chris@0
|
75 break;
|
Chris@0
|
76 case 'recent':
|
Chris@0
|
77 // Node is 1 hour hold.
|
Chris@0
|
78 $settings['created'] = REQUEST_TIME - 3600;
|
Chris@0
|
79 break;
|
Chris@0
|
80 case 'comments':
|
Chris@0
|
81 $settings['comment'][0]['status'] = CommentItemInterface::OPEN;
|
Chris@0
|
82 break;
|
Chris@0
|
83 }
|
Chris@0
|
84 }
|
Chris@0
|
85 $nodes[$node_rank][$num] = $this->drupalCreateNode($settings);
|
Chris@0
|
86 }
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 // Add a comment to one of the nodes.
|
Chris@0
|
90 $edit = [];
|
Chris@0
|
91 $edit['subject[0][value]'] = 'my comment title';
|
Chris@0
|
92 $edit['comment_body[0][value]'] = 'some random comment';
|
Chris@0
|
93 $this->drupalGet('comment/reply/node/' . $nodes['comments'][1]->id() . '/comment');
|
Chris@0
|
94 $this->drupalPostForm(NULL, $edit, t('Preview'));
|
Chris@0
|
95 $this->drupalPostForm(NULL, $edit, t('Save'));
|
Chris@0
|
96
|
Chris@0
|
97 // Enable counting of statistics.
|
Chris@0
|
98 $this->config('statistics.settings')->set('count_content_views', 1)->save();
|
Chris@0
|
99
|
Chris@0
|
100 // Simulating content views is kind of difficult in the test. Leave that
|
Chris@0
|
101 // to the Statistics module. So instead go ahead and manually update the
|
Chris@0
|
102 // counter for this node.
|
Chris@0
|
103 $nid = $nodes['views'][1]->id();
|
Chris@0
|
104 db_insert('node_counter')
|
Chris@0
|
105 ->fields(['totalcount' => 5, 'daycount' => 5, 'timestamp' => REQUEST_TIME, 'nid' => $nid])
|
Chris@0
|
106 ->execute();
|
Chris@0
|
107
|
Chris@0
|
108 // Run cron to update the search index and comment/statistics totals.
|
Chris@0
|
109 $this->cronRun();
|
Chris@0
|
110
|
Chris@0
|
111 // Test that the settings form displays the content ranking section.
|
Chris@0
|
112 $this->drupalGet('admin/config/search/pages/manage/node_search');
|
Chris@0
|
113 $this->assertText(t('Content ranking'));
|
Chris@0
|
114
|
Chris@0
|
115 // Check that all rankings are visible and set to 0.
|
Chris@0
|
116 foreach ($node_ranks as $node_rank) {
|
Chris@0
|
117 $this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="0"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 0.');
|
Chris@0
|
118 }
|
Chris@0
|
119
|
Chris@0
|
120 // Test each of the possible rankings.
|
Chris@0
|
121 $edit = [];
|
Chris@0
|
122 foreach ($node_ranks as $node_rank) {
|
Chris@0
|
123 // Enable the ranking we are testing.
|
Chris@0
|
124 $edit['rankings[' . $node_rank . '][value]'] = 10;
|
Chris@0
|
125 $this->drupalPostForm('admin/config/search/pages/manage/node_search', $edit, t('Save search page'));
|
Chris@0
|
126 $this->drupalGet('admin/config/search/pages/manage/node_search');
|
Chris@0
|
127 $this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="10"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 10.');
|
Chris@0
|
128
|
Chris@0
|
129 // Reload the plugin to get the up-to-date values.
|
Chris@0
|
130 $this->nodeSearch = SearchPage::load('node_search');
|
Chris@0
|
131 // Do the search and assert the results.
|
Chris@0
|
132 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
Chris@0
|
133 $set = $this->nodeSearch->getPlugin()->execute();
|
Chris@0
|
134 $this->assertEqual($set[0]['node']->id(), $nodes[$node_rank][1]->id(), 'Search ranking "' . $node_rank . '" order.');
|
Chris@0
|
135
|
Chris@0
|
136 // Clear this ranking for the next test.
|
Chris@0
|
137 $edit['rankings[' . $node_rank . '][value]'] = 0;
|
Chris@0
|
138 }
|
Chris@0
|
139
|
Chris@0
|
140 // Save the final node_rank change then check that all rankings are visible
|
Chris@0
|
141 // and have been set back to 0.
|
Chris@0
|
142 $this->drupalPostForm('admin/config/search/pages/manage/node_search', $edit, t('Save search page'));
|
Chris@0
|
143 $this->drupalGet('admin/config/search/pages/manage/node_search');
|
Chris@0
|
144 foreach ($node_ranks as $node_rank) {
|
Chris@0
|
145 $this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="0"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 0.');
|
Chris@0
|
146 }
|
Chris@0
|
147
|
Chris@0
|
148 // Try with sticky, then promoted. This is a test for issue
|
Chris@0
|
149 // https://www.drupal.org/node/771596.
|
Chris@0
|
150 $node_ranks = [
|
Chris@0
|
151 'sticky' => 10,
|
Chris@0
|
152 'promote' => 1,
|
Chris@0
|
153 'relevance' => 0,
|
Chris@0
|
154 'recent' => 0,
|
Chris@0
|
155 'comments' => 0,
|
Chris@0
|
156 'views' => 0,
|
Chris@0
|
157 ];
|
Chris@0
|
158 $configuration = $this->nodeSearch->getPlugin()->getConfiguration();
|
Chris@0
|
159 foreach ($node_ranks as $var => $value) {
|
Chris@0
|
160 $configuration['rankings'][$var] = $value;
|
Chris@0
|
161 }
|
Chris@0
|
162 $this->nodeSearch->getPlugin()->setConfiguration($configuration);
|
Chris@0
|
163 $this->nodeSearch->save();
|
Chris@0
|
164
|
Chris@0
|
165 // Do the search and assert the results. The sticky node should show up
|
Chris@0
|
166 // first, then the promoted node, then all the rest.
|
Chris@0
|
167 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
Chris@0
|
168 $set = $this->nodeSearch->getPlugin()->execute();
|
Chris@0
|
169 $this->assertEqual($set[0]['node']->id(), $nodes['sticky'][1]->id(), 'Search ranking for sticky first worked.');
|
Chris@0
|
170 $this->assertEqual($set[1]['node']->id(), $nodes['promote'][1]->id(), 'Search ranking for promoted second worked.');
|
Chris@0
|
171
|
Chris@0
|
172 // Try with recent, then comments. This is a test for issues
|
Chris@0
|
173 // https://www.drupal.org/node/771596 and
|
Chris@0
|
174 // https://www.drupal.org/node/303574.
|
Chris@0
|
175 $node_ranks = [
|
Chris@0
|
176 'sticky' => 0,
|
Chris@0
|
177 'promote' => 0,
|
Chris@0
|
178 'relevance' => 0,
|
Chris@0
|
179 'recent' => 10,
|
Chris@0
|
180 'comments' => 1,
|
Chris@0
|
181 'views' => 0,
|
Chris@0
|
182 ];
|
Chris@0
|
183 $configuration = $this->nodeSearch->getPlugin()->getConfiguration();
|
Chris@0
|
184 foreach ($node_ranks as $var => $value) {
|
Chris@0
|
185 $configuration['rankings'][$var] = $value;
|
Chris@0
|
186 }
|
Chris@0
|
187 $this->nodeSearch->getPlugin()->setConfiguration($configuration);
|
Chris@0
|
188 $this->nodeSearch->save();
|
Chris@0
|
189
|
Chris@0
|
190 // Do the search and assert the results. The recent node should show up
|
Chris@0
|
191 // first, then the commented node, then all the rest.
|
Chris@0
|
192 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
Chris@0
|
193 $set = $this->nodeSearch->getPlugin()->execute();
|
Chris@0
|
194 $this->assertEqual($set[0]['node']->id(), $nodes['recent'][1]->id(), 'Search ranking for recent first worked.');
|
Chris@0
|
195 $this->assertEqual($set[1]['node']->id(), $nodes['comments'][1]->id(), 'Search ranking for comments second worked.');
|
Chris@0
|
196
|
Chris@0
|
197 }
|
Chris@0
|
198
|
Chris@0
|
199 /**
|
Chris@0
|
200 * Test rankings of HTML tags.
|
Chris@0
|
201 */
|
Chris@0
|
202 public function testHTMLRankings() {
|
Chris@0
|
203 $full_html_format = FilterFormat::create([
|
Chris@0
|
204 'format' => 'full_html',
|
Chris@0
|
205 'name' => 'Full HTML',
|
Chris@0
|
206 ]);
|
Chris@0
|
207 $full_html_format->save();
|
Chris@0
|
208
|
Chris@0
|
209 // Test HTML tags with different weights.
|
Chris@0
|
210 $sorted_tags = ['h1', 'h2', 'h3', 'h4', 'a', 'h5', 'h6', 'notag'];
|
Chris@0
|
211 $shuffled_tags = $sorted_tags;
|
Chris@0
|
212
|
Chris@0
|
213 // Shuffle tags to ensure HTML tags are ranked properly.
|
Chris@0
|
214 shuffle($shuffled_tags);
|
Chris@0
|
215 $settings = [
|
Chris@0
|
216 'type' => 'page',
|
Chris@0
|
217 'title' => 'Simple node',
|
Chris@0
|
218 ];
|
Chris@0
|
219 $nodes = [];
|
Chris@0
|
220 foreach ($shuffled_tags as $tag) {
|
Chris@0
|
221 switch ($tag) {
|
Chris@0
|
222 case 'a':
|
Chris@0
|
223 $settings['body'] = [['value' => \Drupal::l('Drupal Rocks', new Url('<front>')), 'format' => 'full_html']];
|
Chris@0
|
224 break;
|
Chris@0
|
225 case 'notag':
|
Chris@0
|
226 $settings['body'] = [['value' => 'Drupal Rocks']];
|
Chris@0
|
227 break;
|
Chris@0
|
228 default:
|
Chris@0
|
229 $settings['body'] = [['value' => "<$tag>Drupal Rocks</$tag>", 'format' => 'full_html']];
|
Chris@0
|
230 break;
|
Chris@0
|
231 }
|
Chris@0
|
232 $nodes[$tag] = $this->drupalCreateNode($settings);
|
Chris@0
|
233 }
|
Chris@0
|
234
|
Chris@0
|
235 // Update the search index.
|
Chris@0
|
236 $this->nodeSearch->getPlugin()->updateIndex();
|
Chris@0
|
237 search_update_totals();
|
Chris@0
|
238
|
Chris@0
|
239 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
Chris@0
|
240 // Do the search and assert the results.
|
Chris@0
|
241 $set = $this->nodeSearch->getPlugin()->execute();
|
Chris@0
|
242
|
Chris@0
|
243 // Test the ranking of each tag.
|
Chris@0
|
244 foreach ($sorted_tags as $tag_rank => $tag) {
|
Chris@0
|
245 // Assert the results.
|
Chris@0
|
246 if ($tag == 'notag') {
|
Chris@0
|
247 $this->assertEqual($set[$tag_rank]['node']->id(), $nodes[$tag]->id(), 'Search tag ranking for plain text order.');
|
Chris@0
|
248 }
|
Chris@0
|
249 else {
|
Chris@0
|
250 $this->assertEqual($set[$tag_rank]['node']->id(), $nodes[$tag]->id(), 'Search tag ranking for "<' . $sorted_tags[$tag_rank] . '>" order.');
|
Chris@0
|
251 }
|
Chris@0
|
252 }
|
Chris@0
|
253
|
Chris@0
|
254 // Test tags with the same weight against the sorted tags.
|
Chris@0
|
255 $unsorted_tags = ['u', 'b', 'i', 'strong', 'em'];
|
Chris@0
|
256 foreach ($unsorted_tags as $tag) {
|
Chris@0
|
257 $settings['body'] = [['value' => "<$tag>Drupal Rocks</$tag>", 'format' => 'full_html']];
|
Chris@0
|
258 $node = $this->drupalCreateNode($settings);
|
Chris@0
|
259
|
Chris@0
|
260 // Update the search index.
|
Chris@0
|
261 $this->nodeSearch->getPlugin()->updateIndex();
|
Chris@0
|
262 search_update_totals();
|
Chris@0
|
263
|
Chris@0
|
264 $this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
Chris@0
|
265 // Do the search and assert the results.
|
Chris@0
|
266 $set = $this->nodeSearch->getPlugin()->execute();
|
Chris@0
|
267
|
Chris@0
|
268 // Ranking should always be second to last.
|
Chris@0
|
269 $set = array_slice($set, -2, 1);
|
Chris@0
|
270
|
Chris@0
|
271 // Assert the results.
|
Chris@0
|
272 $this->assertEqual($set[0]['node']->id(), $node->id(), 'Search tag ranking for "<' . $tag . '>" order.');
|
Chris@0
|
273
|
Chris@0
|
274 // Delete node so it doesn't show up in subsequent search results.
|
Chris@0
|
275 $node->delete();
|
Chris@0
|
276 }
|
Chris@0
|
277 }
|
Chris@0
|
278
|
Chris@0
|
279 }
|