Projet

Général

Profil

Paste
Télécharger (18,7 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / feeds / tests / feeds_processor_node.test @ 13755f8d

1
<?php
2

    
3
/**
4
 * @file
5
 * Tests for plugins/FeedsNodeProcessor.inc.
6
 */
7

    
8
/**
9
 * Test aggregating a feed as node items.
10
 */
11
class FeedsRSStoNodesTest extends FeedsWebTestCase {
12

    
13
  public static function getInfo() {
14
    return array(
15
      'name' => 'RSS import to nodes',
16
      'description' => 'Tests a feed configuration that is attached to a content type, uses HTTP fetcher, common syndication parser and a node processor. Repeats the same test for an importer configuration that is not attached to a content type and for a configuration that is attached to a content type and uses the file fetcher.',
17
      'group' => 'Feeds',
18
    );
19
  }
20

    
21
  /**
22
   * Set up test.
23
   */
24
  public function setUp() {
25
    parent::setUp();
26

    
27
    // Set the front page to show 20 nodes so we can easily see what is aggregated.
28
    variable_set('default_nodes_main', 20);
29

    
30
    // Set the teaser length display to unlimited otherwise tests looking for
31
    // text on nodes will fail.
32
    $edit = array('fields[body][type]' => 'text_default');
33
    $this->drupalPost('admin/structure/types/manage/article/display/teaser', $edit, 'Save');
34

    
35
    // Create an importer configuration.
36
    $this->createImporterConfiguration('Syndication', 'syndication');
37
    $this->addMappings('syndication',
38
      array(
39
        0 => array(
40
          'source' => 'title',
41
          'target' => 'title',
42
          'unique' => FALSE,
43
        ),
44
        1 => array(
45
          'source' => 'description',
46
          'target' => 'body',
47
        ),
48
        2 => array(
49
          'source' => 'timestamp',
50
          'target' => 'created',
51
        ),
52
        3 => array(
53
          'source' => 'url',
54
          'target' => 'url',
55
          'unique' => TRUE,
56
        ),
57
        4 => array(
58
          'source' => 'guid',
59
          'target' => 'guid',
60
          'unique' => TRUE,
61
        ),
62
      )
63
    );
64
  }
65

    
66
  /**
67
   * Test node creation, refreshing/deleting feeds and feed items.
68
   */
69
  public function test() {
70
    $nid = $this->createFeedNode();
71

    
72
    // Assert 10 items aggregated after creation of the node.
73
    $this->assertText('Created 10 nodes');
74
    $article_nid = db_query_range("SELECT nid FROM {node} WHERE type = 'article'", 0, 1)->fetchField();
75
    $this->assertEqual("Created by FeedsNodeProcessor", db_query("SELECT nr.log FROM {node} n JOIN {node_revision} nr ON n.vid = nr.vid WHERE n.nid = :nid", array(':nid' => $article_nid))->fetchField());
76

    
77
    // Navigate to feed node, there should be Feeds tabs visible.
78
    $this->drupalGet("node/$nid");
79
    $this->assertRaw("node/$nid/import");
80
    $this->assertRaw("node/$nid/delete-items");
81

    
82
    // Assert accuracy of aggregated information.
83
    $this->drupalGet('node');
84
    $this->assertRaw('<span class="username">Anonymous (not verified)</span>');
85
    $this->assertDevseedFeedContent();
86

    
87
    // Assert DB status.
88
    $count = db_query("SELECT COUNT(*) FROM {node} n INNER JOIN {feeds_item} fi ON fi.entity_type = 'node' AND n.nid = fi.entity_id")->fetchField();
89
    $this->assertEqual($count, 10, 'Accurate number of items in database.');
90

    
91
    // Assert default input format on first imported feed node.
92

    
93
    // NEEDS update.
94
    // $format = db_query_range("SELECT nr.format FROM {feeds_node_item} fi JOIN {node} n ON fi.nid = n.nid JOIN {node_revision} nr ON n.vid = nr.vid", 0, 1)->fetchField();
95
    // $this->assertEqual($format, filter_fallback_format(), 'Using default Input format.');
96

    
97
    // Import again.
98
    $this->drupalPost("node/$nid/import", array(), 'Import');
99
    $this->assertText('There are no new nodes');
100

    
101
    // Assert DB status, there still shouldn't be more than 10 items.
102
    $count = db_query("SELECT COUNT(*) FROM {node} n INNER JOIN {feeds_item} fi ON fi.entity_type = 'node' AND n.nid = fi.entity_id")->fetchField();
103
    $this->assertEqual($count, 10, 'Accurate number of items in database.');
104

    
105
    // All of the above tests should have produced published nodes, set default
106
    // to unpublished, import again.
107
    $count = db_query("SELECT COUNT(*) FROM {node} n INNER JOIN {feeds_item} fi ON fi.entity_type = 'node' AND n.nid = fi.entity_id WHERE n.status = 1")->fetchField();
108
    $this->assertEqual($count, 10, 'All items are published.');
109
    $edit = array(
110
      'node_options[status]' => FALSE,
111
    );
112
    $this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
113
    $this->drupalPost("node/$nid/delete-items", array(), 'Delete');
114
    $this->drupalPost("node/$nid/import", array(), 'Import');
115
    $count = db_query("SELECT COUNT(*) FROM {node} n INNER JOIN {feeds_item} fi ON fi.entity_type = 'node' AND n.nid = fi.entity_id WHERE n.status = 0")->fetchField();
116
    $this->assertEqual($count, 10, 'No items are published.');
117
    $edit = array(
118
      'node_options[status]' => TRUE,
119
    );
120
    $this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
121
    $this->drupalPost("node/$nid/delete-items", array(), 'Delete');
122

    
123
    // Enable replace existing and import updated feed file.
124
    $this->drupalPost("node/$nid/import", array(), 'Import');
125
    $this->setSettings('syndication', 'FeedsNodeProcessor', array('update_existing' => 1));
126
    $feed_url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed_changes.rss2';
127
    $this->editFeedNode($nid, $feed_url);
128
    $this->drupalPost("node/$nid/import", array(), 'Import');
129
    $this->assertText('Updated 2 nodes');
130

    
131
    // Assert accuracy of aggregated content (check 2 updates, one original).
132
    $this->drupalGet('node');
133
    $this->assertText('Managing News Translation Workflow: Two Way Translation Updates');
134
    $this->assertText('Presenting on Features in Drupal and Managing News');
135
    $this->assertText('Scaling the Open Atrium UI');
136

    
137
    // Import again.
138
    $this->drupalPost("node/$nid/import", array(), 'Import');
139
    $this->assertText('There are no new nodes');
140
    $this->assertFeedItemCount(10);
141

    
142
    // Now delete all items.
143
    $this->drupalPost("node/$nid/delete-items", array(), 'Delete');
144
    $this->assertText('Deleted 10 nodes');
145
    $this->assertFeedItemCount(0);
146

    
147
    // Change author and turn off authorization.
148
    $this->auth_user = $this->drupalCreateUser(array('access content'));
149
    $this->setSettings('syndication', 'FeedsNodeProcessor', array('author' => $this->auth_user->name, 'authorize' => FALSE));
150

    
151
    // Change input format.
152
    $this->setSettings('syndication', 'FeedsNodeProcessor', array('input_format' => 'plain_text'));
153

    
154
    // Import again.
155
    $this->drupalPost("node/$nid/import", array(), 'Import');
156
    $this->assertText('Created 10 nodes');
157

    
158
    // Assert author.
159
    $this->drupalGet('node');
160
    $this->assertPattern('/<span class="username">' . check_plain($this->auth_user->name) . '<\/span>/');
161
    $count = db_query("SELECT COUNT(*) FROM {feeds_item} fi JOIN {node} n ON fi.entity_type = 'node' AND fi.entity_id = n.nid WHERE n.uid = :uid", array(':uid' => $this->auth_user->uid))->fetchField();
162
    $this->assertEqual($count, 10, 'Accurate number of items in database.');
163

    
164
    // Assert input format.
165

    
166
    // NEEDS update.
167
    // $format = db_query_range("SELECT nr.format FROM {feeds_node_item} fi JOIN {node} n ON fi.nid = n.nid JOIN {node_revision} nr ON n.vid = nr.vid", 0, 1)->fetchField();
168
    // $this->assertEqual($format, filter_fallback_format() + 1, 'Set non-default Input format.');
169

    
170
    // Set to update existing, remove authorship of above nodes and import again.
171
    $this->setSettings('syndication', 'FeedsNodeProcessor', array('update_existing' => 2));
172
    $nids = db_query("SELECT nid FROM {node} n INNER JOIN {feeds_item} fi ON fi.entity_type = 'node' AND n.nid = fi.entity_id")->fetchCol();
173
    db_update('node')
174
      ->fields(array('uid' => 0))
175
      ->condition('nid', $nids, 'IN')
176
      ->execute();
177
    db_update('feeds_item')
178
      ->fields(array('hash' => ''))
179
      ->condition('entity_type', 'node')
180
      ->condition('entity_id', $nids, 'IN')
181
      ->execute();
182
    $this->drupalPost("node/$nid/import", array(), 'Import');
183
    $this->drupalGet('node');
184
    $this->assertNoPattern('/<span class="username">' . check_plain($this->auth_user->name) . '<\/span>/');
185
    $count = db_query("SELECT COUNT(*) FROM {feeds_item} fi JOIN {node} n ON fi.entity_type = 'node' AND fi.entity_id = n.nid WHERE n.uid = :uid", array(':uid' => $this->auth_user->uid))->fetchField();
186
    $this->assertEqual($count, 0, 'Accurate number of items in database.');
187

    
188
    // Map feed node's author to feed item author, update - feed node's items
189
    // should now be assigned to feed node author.
190
    $this->addMappings('syndication',
191
      array(
192
        5 => array(
193
          'source' => 'parent:uid',
194
          'target' => 'uid',
195
        ),
196
      )
197
    );
198
    $this->drupalPost("node/$nid/import", array(), 'Import');
199
    $this->drupalGet('node');
200
    $this->assertNoPattern('/<span class="username">' . check_plain($this->auth_user->name) . '<\/span>/');
201
    $uid = db_query("SELECT uid FROM {node} WHERE nid = :nid", array(':nid' => $nid))->fetchField();
202
    $count = db_query("SELECT COUNT(*) FROM {node} WHERE uid = :uid", array(':uid' => $uid))->fetchField();
203
    $this->assertEqual($count, 11, 'All feed item nodes are assigned to feed node author.');
204

    
205
    // Login with new user with only access content permissions.
206
    $this->drupalLogin($this->auth_user);
207

    
208
    // Navigate to feed node, there should be no Feeds tabs visible.
209
    $this->drupalGet("node/$nid");
210
    $this->assertNoRaw("node/$nid/import");
211
    $this->assertNoRaw("node/$nid/delete-items");
212

    
213
    // Now create a second feed configuration that is not attached to a content
214
    // type and run tests on importing/purging.
215

    
216
    // Login with sufficient permissions.
217
    $this->drupalLogin($this->admin_user);
218
    // Remove all items again so that next test can check for them.
219
    $this->drupalPost("node/$nid/delete-items", array(), 'Delete');
220

    
221
    // Create an importer, not attached to content type.
222
    $this->createImporterConfiguration('Syndication standalone', 'syndication_standalone');
223
    $edit = array(
224
      'content_type' => '',
225
    );
226
    $this->drupalPost('admin/structure/feeds/syndication_standalone/settings', $edit, 'Save');
227
    $this->addMappings('syndication_standalone',
228
      array(
229
        0 => array(
230
          'source' => 'title',
231
          'target' => 'title',
232
          'unique' => FALSE,
233
        ),
234
        1 => array(
235
          'source' => 'description',
236
          'target' => 'body',
237
        ),
238
        2 => array(
239
          'source' => 'timestamp',
240
          'target' => 'created',
241
        ),
242
        3 => array(
243
          'source' => 'url',
244
          'target' => 'url',
245
          'unique' => TRUE,
246
        ),
247
        4 => array(
248
          'source' => 'guid',
249
          'target' => 'guid',
250
          'unique' => TRUE,
251
        ),
252
      )
253
    );
254

    
255
    // Import, assert 10 items aggregated after creation of the node.
256
    $this->importURL('syndication_standalone');
257
    $this->assertText('Created 10 nodes');
258

    
259
    // Assert accuracy of aggregated information.
260
    $this->drupalGet('node');
261
    $this->assertDevseedFeedContent();
262
    $this->assertFeedItemCount(10);
263

    
264
    // Import again.
265
    $this->drupalPost('import/syndication_standalone', array(), 'Import');
266
    $this->assertText('There are no new nodes');
267
    $this->assertFeedItemCount(10);
268

    
269
    // Enable replace existing and import updated feed file.
270
    $this->setSettings('syndication_standalone', 'FeedsNodeProcessor', array('update_existing' => 1));
271
    $feed_url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed_changes.rss2';
272
    $this->importURL('syndication_standalone', $feed_url);
273
    $this->assertText('Updated 2 nodes');
274

    
275
    // Assert accuracy of aggregated information (check 2 updates, one orig).
276
    $this->drupalGet('node');
277
    $this->assertText('Managing News Translation Workflow: Two Way Translation Updates');
278
    $this->assertText('Presenting on Features in Drupal and Managing News');
279
    $this->assertText('Scaling the Open Atrium UI');
280

    
281
    // Import again.
282
    $this->drupalPost('import/syndication_standalone', array(), 'Import');
283
    $this->assertText('There are no new nodes');
284
    $this->assertFeedItemCount(10);
285

    
286
    // Now delete all items.
287
    $this->drupalPost('import/syndication_standalone/delete-items', array(), 'Delete');
288
    $this->assertText('Deleted 10 nodes');
289
    $this->assertFeedItemCount(0);
290

    
291
    // Import again, we should find new content.
292
    $this->drupalPost('import/syndication_standalone', array(), 'Import');
293
    $this->assertText('Created 10 nodes');
294
    $this->assertFeedItemCount(10);
295

    
296
    // Login with new user with only access content permissions.
297
    $this->drupalLogin($this->auth_user);
298

    
299
    // Navigate to feed import form, access should be denied.
300
    $this->drupalGet('import/syndication_standalone');
301
    $this->assertResponse(403);
302

    
303
    // Use File Fetcher.
304
    $this->drupalLogin($this->admin_user);
305

    
306
    $edit = array('plugin_key' => 'FeedsFileFetcher');
307
    $this->drupalPost('admin/structure/feeds/syndication_standalone/fetcher', $edit, 'Save');
308

    
309
    $edit = array(
310
      'allowed_extensions' => 'rss2',
311
    );
312
    $this->drupalPost('admin/structure/feeds/syndication_standalone/settings/FeedsFileFetcher', $edit, 'Save');
313

    
314
    // Create a feed node.
315
    $edit = array(
316
      'files[feeds]' => $this->absolutePath() . '/tests/feeds/drupalplanet.rss2',
317
    );
318
    $this->drupalPost('import/syndication_standalone', $edit, 'Import');
319
    $this->assertText('Created 25 nodes');
320
  }
321

    
322
  /**
323
   * Check that the total number of entries in the feeds_item table is correct.
324
   */
325
  function assertFeedItemCount($num) {
326
    $count = db_query("SELECT COUNT(*) FROM {feeds_item} WHERE entity_type = 'node'")->fetchField();
327
    $this->assertEqual($count, $num, 'Accurate number of items in database.');
328
  }
329

    
330
  /**
331
   * Check thet contents of the current page for the DS feed.
332
   */
333
  function assertDevseedFeedContent() {
334
    $this->assertText('Open Atrium Translation Workflow: Two Way Translation Updates');
335
    $this->assertText('Tue, 10/06/2009');
336
    $this->assertText('A new translation process for Open Atrium &amp; integration with Localize Drupal');
337
    $this->assertText('Week in DC Tech: October 5th Edition');
338
    $this->assertText('Mon, 10/05/2009');
339
    $this->assertText('There are some great technology events happening this week');
340
    $this->assertText('Mapping Innovation at the World Bank with Open Atrium');
341
    $this->assertText('Fri, 10/02/2009');
342
    $this->assertText('is being used as a base platform for collaboration at the World Bank');
343
    $this->assertText('September GeoDC Meetup Tonight');
344
    $this->assertText('Wed, 09/30/2009');
345
    $this->assertText('Today is the last Wednesday of the month');
346
    $this->assertText('Week in DC Tech: September 28th Edition');
347
    $this->assertText('Mon, 09/28/2009');
348
    $this->assertText('Looking to geek out this week? There are a bunch of');
349
    $this->assertText('Open Data for Microfinance: The New MIXMarket.org');
350
    $this->assertText('Thu, 09/24/2009');
351
    $this->assertText('There are profiles for every country that the MIX Market is hosting.');
352
    $this->assertText('Integrating the Siteminder Access System in an Open Atrium-based Intranet');
353
    $this->assertText('Tue, 09/22/2009');
354
    $this->assertText('In addition to authentication, the Siteminder system');
355
    $this->assertText('Week in DC Tech: September 21 Edition');
356
    $this->assertText('Mon, 09/21/2009');
357
    $this->assertText('an interesting variety of technology events happening in Washington, DC ');
358
    $this->assertText('s Software Freedom Day: Impressions &amp; Photos');
359
    $this->assertText('Mon, 09/21/2009');
360
    $this->assertText('Presenting on Features in Drupal and Open Atrium');
361
    $this->assertText('Scaling the Open Atrium UI');
362
    $this->assertText('Fri, 09/18/2009');
363
    $this->assertText('The first major change is switching');
364
  }
365

    
366
  /**
367
   * Test validation of feed URLs.
368
   */
369
  function testFeedURLValidation() {
370
    $edit['feeds[FeedsHTTPFetcher][source]'] = 'invalid://url';
371
    $this->drupalPost('node/add/page', $edit, 'Save');
372
    $this->assertText('The URL invalid://url is invalid.');
373
  }
374

    
375
  /**
376
   * Test using non-normal URLs like feed:// and webcal://.
377
   */
378
  function testOddFeedSchemes() {
379
    $url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed.rss2';
380

    
381
    $schemes = array('feed', 'webcal');
382
    $item_count = 0;
383
    foreach ($schemes as $scheme) {
384
      $feed_url = strtr($url, array('http://' => $scheme . '://', 'https://' => $scheme . '://'));
385

    
386
      $edit['feeds[FeedsHTTPFetcher][source]'] = $feed_url;
387
      $this->drupalPost('node/add/page', $edit, 'Save');
388
      $this->assertText('Basic page Development Seed - Technological Solutions for Progressive Organizations has been created.');
389
      $this->assertText('Created 10 nodes.');
390
      $this->assertFeedItemCount($item_count + 10);
391
      $item_count += 10;
392
    }
393
  }
394

    
395
  /**
396
   * Test that feed elements and links are not found on non-feed nodes.
397
   */
398
  function testNonFeedNodeUI() {
399
    // There should not be feed links on an article node.
400
    $non_feed_node = $this->drupalCreateNode(array('type' => 'article'));
401
    $this->drupalGet('node/' . $non_feed_node->nid);
402
    $this->assertNoLinkByHref('node/' . $non_feed_node->nid . '/import');
403
    $this->assertNoLink('Delete items');
404

    
405
    // Navigate to a non-feed node form, there should be no Feed field visible.
406
    $this->drupalGet('node/add/article');
407
    $this->assertNoFieldByName('feeds[FeedsHTTPFetcher][source]');
408
  }
409

    
410
  /**
411
   * Test that nodes will not be created if the user is unauthorized to create
412
   * them.
413
   */
414
  public function testAuthorize() {
415

    
416
    // Create a user with limited permissions. We can't use
417
    // $this->drupalCreateUser here because we need to to set a specific user
418
    // name.
419
    $edit = array(
420
      'name' => 'Development Seed',
421
      'mail' => 'devseed@example.com',
422
      'pass' => user_password(),
423
      'status' => 1,
424
    );
425

    
426
   $account = user_save(drupal_anonymous_user(), $edit);
427

    
428
    // Adding a mapping to the user_name will invoke authorization.
429
    $this->addMappings('syndication',
430
      array(
431
        5 => array(
432
          'source' => 'author_name',
433
          'target' => 'user_name',
434
        ),
435
      )
436
    );
437

    
438
    $nid = $this->createFeedNode();
439

    
440
    $this->assertText('Failed importing 10 nodes.');
441
    $this->assertText('User ' . $account->name . ' is not authorized to create content type article.');
442
    $node_count = db_query("SELECT COUNT(*) FROM {node}")->fetchField();
443

    
444
    // We should have 1 node, the feed node.
445
    $this->assertEqual($node_count, 1, t('Correct number of nodes in the database.'));
446

    
447
    // Give the user our admin powers.
448
    $edit = array(
449
      'roles' => $this->admin_user->roles,
450
    );
451
    $account = user_save($account, $edit);
452

    
453
    $this->drupalPost("node/$nid/import", array(), 'Import');
454
    $this->assertText('Created 10 nodes.');
455
    $node_count = db_query("SELECT COUNT(*) FROM {node}")->fetchField();
456
    $this->assertEqual($node_count, 11, t('Correct number of nodes in the database.'));
457
  }
458
}