Projet

Général

Profil

Paste
Télécharger (28,9 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / feeds / feeds.drush.inc @ ed9a13f1

1
<?php
2

    
3
/**
4
 * @file
5
 * Drush commands for Feeds module.
6
 */
7

    
8
/**
9
 * The default maximum number of feeds to list or import.
10
 *
11
 * @var int
12
 */
13
define('DRUSH_FEEDS_DEFAULT_LIMIT', 2147483647);
14

    
15
/**
16
 * Implements hook_drush_command().
17
 */
18
function feeds_drush_command() {
19
  $items = array();
20

    
21
  $items['feeds-list-importers'] = array(
22
    'description' => 'Get a list of all Feeds importers in the system.',
23
    'aliases' => array('feeds'),
24
  );
25

    
26
  $items['feeds-list-feeds'] = array(
27
    'description' => 'List all feed sources.',
28
    'arguments' => array(
29
      'importer' => 'The name of the Feeds importer whose instances will be listed. Optional.',
30
    ),
31
    'examples' => array(
32
      'drush feeds-list-feeds' => 'List all instances of all feeds.',
33
      'drush feeds-list-feeds rss_feed' => 'List all feed sources of the rss_feed importer.',
34
      'drush feeds-list-feeds --limit=3' => 'Only list the first three feed sources.',
35
    ),
36
    'options' => array(
37
      'limit' => 'Limit the number of feeds to show in the list. Optional.',
38
    ),
39
    'aliases' => array('feeds-lf'),
40
  );
41

    
42
  $items['feeds-import'] = array(
43
    'description' => 'Imports a feed.',
44
    'arguments' => array(
45
      'importer' => 'The name of the Feeds importer that will be refreshed. Mandatory.',
46
    ),
47
    'options' => array(
48
      'nid' => '(optional) The nid of the Feeds importer that will be imported.',
49
      'file' => '(optional) The file to import. Bypasses the configured fetcher and does *not* update the source configuration.',
50
      'url' => '(optional) The URL to import. Bypasses the configured fetcher and does *not* update the source configuration.',
51
      'stdin' => '(optional) Read the file to import from stdin. Bypasses the configured fetcher and does *not* update the source configuration.',
52
    ),
53
    'examples' => array(
54
      'drush feeds-import my_importer' => "Import items with the importer 'my_importer'.",
55
      'drush feeds-import my_importer --nid=2' => "Import items with the importer 'my_importer' for feed node 2.",
56
    ),
57
    'aliases' => array('feeds-im'),
58
  );
59

    
60
  $items['feeds-import-all'] = array(
61
    'description' => 'Import all instances of feeds of the given type.',
62
    'arguments' => array(
63
      'importer' => 'The name of the Feeds importer that will be refreshed. Omitting the importer will cause all instances of all feeds to be imported.',
64
    ),
65
    'examples' => array(
66
      'drush feeds-import-all' => 'Import all instances of all feeds.',
67
      'drush feeds-import-all my_importer' => "Import all instances of the importer 'my_importer'.",
68
      'drush feeds-import-all my_importer --limit=10' => "Import 10 instances of the feed 'my_importer'.",
69
    ),
70
    'options' => array(
71
      'limit' => 'Limit the number of feeds to import. Optional.',
72
    ),
73
    'aliases' => array('feeds-ia', 'feeds-im-all'),
74
  );
75

    
76
  $items['feeds-clear'] = array(
77
    'description' => 'Delete all items from a feed.',
78
    'arguments' => array(
79
      'importer' => 'The name of the Feeds importer that will be cleared. Mandatory.',
80
    ),
81
    'options' => array(
82
      'nid' => 'The ID of the Feed node that will be cleared. Required if the importer is attached to a content type.',
83
    ),
84
    'examples' => array(
85
      'drush feeds-clear my_importer' => "Deletes all items imported with the importer 'my_importer'. The importer must use the standalone import form.",
86
      'drush feeds-clear my_importer --nid=2' => "Deletes all items imported with the importer 'my_importer' for the feed node with ID 2. The importer must be attached to a content type.",
87
    ),
88
  );
89

    
90
  $items['feeds-enable'] = array(
91
    'description' => 'Enables one or more Feeds importers.',
92
    'arguments' => array(
93
      'importers' => 'A space delimited list of Feeds importers. Mandatory.',
94
    ),
95
    'examples' => array(
96
      'drush feeds-enable importer_1 importer_2' => "Enable Feeds importers 'importer_1' and 'importer_2'.",
97
    ),
98
    'aliases' => array('feeds-en'),
99
  );
100

    
101
  $items['feeds-disable'] = array(
102
    'description' => 'Disable one or more Feeds importers.',
103
    'arguments' => array(
104
      'importers' => 'A space delimited list of Feeds importers. Mandatory.',
105
    ),
106
    'examples' => array(
107
      'drush feeds-disable importer_1 importer_2' => "Disable Feeds importers 'importer_1' and 'importer_2'.",
108
    ),
109
    'aliases' => array('feeds-dis'),
110
  );
111

    
112
  $items['feeds-delete'] = array(
113
    'description' => 'Deletes one or more Feeds importers.',
114
    'arguments' => array(
115
      'importers' => 'A space delimited list of Feeds importers. Mandatory.',
116
    ),
117
    'examples' => array(
118
      'drush feeds-delete importer_1 importer_2' => "Delete Feeds importers 'importer_1' and 'importer_2'.",
119
    ),
120
  );
121

    
122
  $items['feeds-revert'] = array(
123
    'description' => 'Reverts one or more Feeds importers.',
124
    'arguments' => array(
125
      'importers' => 'A space delimited list of Feeds importers. Mandatory.',
126
    ),
127
    'examples' => array(
128
      'drush feeds-revert importer_1 importer_2' => "Revert Feeds importers 'importer_1' and 'importer_2'.",
129
    ),
130
  );
131

    
132
  return $items;
133
}
134

    
135
/**
136
 * Implements hook_drush_help().
137
 */
138
function feeds_drush_help($section) {
139
  switch ($section) {
140
    case 'drush:feeds-list-importers':
141
      return dt('Show a list of available Feeds importers with information about them.');
142

    
143
    case 'drush:feeds-list-feeds':
144
      return dt("List all feed sources. You can limit the number of feed sources to display by setting the option '--limit'.");
145

    
146
    case 'drush:feeds-import':
147
      $help = dt("Import items from a feed. Follow the command with the importer name to import items with. If the importer is attached to a content type, specify also the feed node with the option '--nid'.");
148
      $help .= "\n" . dt("Note that the options '--file', '--stdin' and '--url' temporary bypass the configured fetcher and do *not* update the source configuration. For example, if a file was uploaded for the feed source, that file will remain there even when you specify a different file using the '--file' option. Same story applies for when importing from a url. If you omit these options, the last stored source will be used.");
149
      return $help;
150

    
151
    case 'drush:feeds-import-all':
152
      return dt('Import items from all feeds. Optionally specify the importer name to import all feeds for.');
153

    
154
    case 'drush:feeds-clear':
155
      return dt("Delete all items from a feed. Follow the command with the importer name to delete items from. If the importer is attached to a content type, specify also the feed node with the option '--nid'.");
156

    
157
    case 'drush:feeds-enable':
158
      return dt('Enable the specified Feeds importers. Follow the command with a space delimited list of importer names.');
159

    
160
    case 'drush:feeds-disable':
161
      return dt('Disable the specified Feeds importers. Follow the command with a space delimited list of importer names.');
162

    
163
    case 'drush:feeds-delete':
164
      return dt('Delete the specified Feeds importers. Follow the command with a space delimited list of importer names.');
165

    
166
    case 'drush:feeds-revert':
167
      return dt('Revert the specified Feeds importers. Follow the command with a space delimited list of importer names.');
168
  }
169
}
170

    
171
/**
172
 * Prints a list of all Feeds importers.
173
 */
174
function drush_feeds_list_importers() {
175
  if (!$importers = feeds_importer_load_all(TRUE)) {
176
    drush_print(dt('No importers available.'));
177
    return;
178
  }
179

    
180
  $rows = array();
181

    
182
  $rows[] = array(
183
    dt('Name'),
184
    dt('Description'),
185
    dt('Attached to'),
186
    dt('Status'),
187
    dt('State'),
188
  );
189

    
190
  foreach ($importers as $importer) {
191
    if ($importer->export_type == EXPORT_IN_CODE) {
192
      $state = dt('Default');
193
    }
194
    elseif ($importer->export_type == EXPORT_IN_DATABASE) {
195
      $state = dt('Normal');
196
    }
197
    elseif ($importer->export_type == (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
198
      $state = dt('Overridden');
199
    }
200

    
201
    $rows[] = array(
202
      $importer->config['name'] . ' (' . $importer->id . ')',
203
      $importer->config['description'],
204
      $importer->config['content_type'] ? dt(node_type_get_name($importer->config['content_type'])) : dt('none'),
205
      $importer->disabled ? dt('Disabled') : dt('Enabled'),
206
      $state,
207
    );
208
  }
209

    
210
  drush_print_table($rows, TRUE);
211
}
212

    
213
/**
214
 * Lists all feeds.
215
 *
216
 * @param string $importer_id
217
 *   (optional) The importer id.
218
 */
219
function drush_feeds_list_feeds($importer_id = NULL) {
220
  if (!$limit = drush_get_option('limit')) {
221
    $limit = DRUSH_FEEDS_DEFAULT_LIMIT;
222
  }
223

    
224
  $header = array(
225
    'importer_id' => dt('Importer ID'),
226
    'feed_nid' => dt('Feed NID'),
227
    'feed_title' => dt('Feed title'),
228
    'imported' => dt('Last imported'),
229
    'source' => dt('Feed source'),
230
    'process_in_background' => dt('Process in background'),
231
  );
232

    
233
  $rows = array();
234
  $nids = array();
235

    
236
  foreach (_drush_feeds_get_all($importer_id, $limit) as $feed) {
237
    $feed_config = feeds_source($feed->id, $feed->feed_nid)->importer->getConfig();
238

    
239
    $rows[] = array(
240
      'importer_id' => $feed->id,
241
      'feed_nid' => $feed->feed_nid,
242
      'feed_title' => '',
243
      'imported' => $feed->imported ? date('Y-m-d H:i:s', $feed->imported) : dt('Never'),
244
      'source' => is_scalar($feed->source) ? $feed->source : gettype($feed->source),
245
      'process_in_background' => !empty($feed_config['process_in_background']) ? dt('Yes') : dt('No'),
246
    );
247

    
248
    // Collect node ID's to find titles for.
249
    if ($feed->feed_nid) {
250
      $nids[] = $feed->feed_nid;
251
    }
252
  }
253

    
254
  // Find titles for feed nodes.
255
  if (count($nids)) {
256
    $nodes = db_select('node')
257
      ->fields('node', array('nid', 'title'))
258
      ->condition('nid', $nids)
259
      ->execute()
260
      ->fetchAllKeyed();
261

    
262
    foreach ($rows as &$row) {
263
      $nid = $row['feed_nid'];
264
      if ($nid && isset($nodes[$nid])) {
265
        $row['feed_title'] = $nodes[$nid];
266
      }
267
    }
268
  }
269

    
270
  // Check if there were any results.
271
  if (count($rows) == 0) {
272
    if (empty($importer_id)) {
273
      drush_print(dt('There are no feed sources.'));
274
    }
275
    else {
276
      drush_print(dt("No feed sources exists for importer '@importer_id'.", array(
277
        '@importer_id' => $importer_id,
278
      )));
279
    }
280
    return FALSE;
281
  }
282

    
283
  // Create table.
284
  $table = array_merge(array($header), $rows);
285

    
286
  drush_print_table($table, TRUE);
287
}
288

    
289
/**
290
 * Imports a given importer/source.
291
 *
292
 * @param string $importer_id
293
 *   (optional) The importer id to filter on.
294
 */
295
function drush_feeds_import($importer_id = NULL) {
296
  if (!strlen($importer_id)) {
297
    drush_set_error(dt("Please specify the importer to import items with. If the importer is attached to a content type, specify also the feed node with the option '--nid'."));
298
    return FALSE;
299
  }
300

    
301
  if (!$feed_nid = drush_get_option('nid')) {
302
    $feed_nid = 0;
303
  }
304

    
305
  try {
306
    $source = feeds_source($importer_id, $feed_nid)->existing();
307
  }
308
  catch (FeedsNotExistingException $e) {
309
    $importer = feeds_importer_load($importer_id);
310
    if (!$importer) {
311
      drush_set_error(dt("The importer '@importer' does not exist.", array(
312
        '@importer' => $importer_id,
313
      )));
314
      return FALSE;
315
    }
316
    elseif (!$importer->isEnabled()) {
317
      drush_set_error(dt("The importer '@importer' is not enabled. You can enable it with the command '@command'.", array(
318
        '@importer' => $importer_id,
319
        '@command' => 'drush feeds-enable ' . $importer_id,
320
      )));
321
      return FALSE;
322
    }
323

    
324
    if ($feed_nid == 0) {
325
      // Check if the importer is a standalone importer.
326
      if ($importer->config['content_type']) {
327
        drush_set_error(dt("The importer '@importer' is attached to a content type. Please specify the feed node to import items for with the option '--nid'. To show a list of available feed nodes for this importer, use 'drush feeds-list-feeds @importer'.", array(
328
          '@importer' => $importer_id,
329
        )));
330
        return FALSE;
331
      }
332
      elseif (drush_get_option('file') || drush_get_option('url') || drush_get_option('stdin')) {
333
        // Create a new source.
334
        $source = feeds_source($importer_id);
335
        $source->save();
336
      }
337
    }
338
    elseif (!$importer->config['content_type']) {
339
      $message = dt("The importer '@importer' is not attached to a content type. Do you want to import items for this importer?", array(
340
        '@importer' => $importer_id,
341
      ));
342

    
343
      if (!drush_confirm($message)) {
344
        return drush_log(dt('Aborting.'), 'ok');
345
      }
346
      else {
347
        drush_set_option('nid', 0);
348
        // Avoid asking for confirmation twice.
349
        drush_set_option('feeds_import_skip_confirm', 1);
350
        return drush_feeds_import($importer_id);
351
      }
352
    }
353

    
354
    if (empty($source)) {
355
      // Only abort at this point when no source object exists. It can exist
356
      // when the importer is not attached to a content type and a file, url or
357
      // stdin is supplied.
358
      if ($feed_nid == 0) {
359
        drush_set_error(dt("No source exists yet for the importer '@importer'. There is nothing to import. You can import from a file or url using the options '--file' or '--url' or go to /import/@importer to configure the source to import. See 'drush help feeds-import' for more information.", array(
360
          '@importer' => $importer_id,
361
        )));
362
        return FALSE;
363
      }
364
      else {
365
        drush_set_error(dt("There is no feed node with ID @nid for importer '@importer'. To show a list of available feed nodes for this importer, use 'drush feeds-list-feeds @importer'.", array(
366
          '@importer' => $importer_id,
367
          '@nid' => $feed_nid,
368
        )));
369
        return FALSE;
370
      }
371
    }
372
  }
373

    
374
  // Propose confirmation message.
375
  $messages = array();
376
  $vars = array(
377
    '@importer' => $importer_id,
378
    '@feed_nid' => $feed_nid,
379
  );
380
  if ($feed_nid) {
381
    $messages[] = dt("Items will be imported with the importer '@importer' for the feed node @feed_nid.", $vars);
382
  }
383
  else {
384
    $messages[] = dt("Items will be imported with the importer '@importer'.", $vars);
385
  }
386

    
387
  $result = NULL;
388
  if ($filename = drush_get_option('file')) {
389
    $filepath = _drush_feeds_find_file($filename);
390
    if (!is_file($filepath)) {
391
      drush_set_error(dt("The file '@file' does not exist.", array('@file' => $filename)));
392
      return FALSE;
393
    }
394
    else {
395
      $filepath = realpath($filepath);
396
    }
397
    $result = new FeedsFileFetcherResult($filepath);
398

    
399
    $messages[] = dt("The items will be imported from the file '@file'.", array(
400
      '@file' => $filepath,
401
    ));
402
  }
403
  elseif ($url = drush_get_option('url')) {
404
    $result = new FeedsHTTPFetcherResult($url);
405

    
406
    $messages[] = dt("The items will be imported from the url '@url'.", array(
407
      '@url' => $url,
408
    ));
409
  }
410
  elseif (drush_get_option('stdin')) {
411
    $result = new FeedsFetcherResult(file_get_contents('php://stdin'));
412

    
413
    $messages[] = dt('The items will be imported from stdin.');
414
  }
415

    
416
  // Only ask for confirmation if it wasn't already asked before. See above.
417
  if (!drush_get_option('feeds_import_skip_confirm')) {
418
    $messages[] = dt('Do you really want to continue?');
419
    $message = implode(' ', $messages);
420
    if (!drush_confirm($message)) {
421
      return drush_log(dt('Aborting.'), 'ok');
422
    }
423
  }
424

    
425
  // Start the import!
426
  if ($result) {
427
    try {
428
      $source->pushImport($result);
429
    }
430
    catch (Exception $e) {
431
      drush_set_error($e->getMessage());
432
      return FALSE;
433
    }
434
  }
435
  else {
436
    _drush_feeds_create_import_batch($importer_id, $feed_nid);
437
    drush_backend_batch_process();
438
    return;
439
  }
440
}
441

    
442
/**
443
 * Imports all feeds.
444
 *
445
 * @param string $importer_id
446
 *   (optional) The importer id to filter on.
447
 */
448
function drush_feeds_import_all($importer_id = NULL) {
449
  if (!$limit = drush_get_option('limit')) {
450
    $limit = DRUSH_FEEDS_DEFAULT_LIMIT;
451
  }
452

    
453
  // Set flag for whether or not executing the batch. When all importers are not
454
  // not confirmed there are no batches set and in that case there are no
455
  // batches to process.
456
  $execute_batch = FALSE;
457

    
458
  foreach (_drush_feeds_get_all($importer_id, $limit) as $feed) {
459
    if (!isset($feed->source) || !strlen($feed->source)) {
460
      continue;
461
    }
462

    
463
    try {
464
      $source = feeds_source($feed->id, $feed->feed_nid)->existing();
465
    }
466
    catch (FeedsNotExistingException $e) {
467
      continue;
468
    }
469

    
470
    // Compose messages.
471
    $vars = array(
472
      '@importer_id' => $source->id,
473
      '@feed_nid' => $source->feed_nid,
474
    );
475
    if ($source->feed_nid) {
476
      $feed_node = node_load($source->feed_nid);
477
      if ($feed_node) {
478
        $vars['@title'] = $feed_node->title;
479
      }
480
      else {
481
        drush_set_error(dt('The feed node @feed_nid (@importer_id) does not exist.', $vars));
482
        continue;
483
      }
484
      $confirm_message = dt("Do you want to import items with the importer '@importer_id' for the feed '@title'?", $vars);
485
      $skip_message = dt("Skipping importer '@importer_id' for feed '@title'.", $vars);
486
    }
487
    else {
488
      $confirm_message = dt("Do you want to import items with the importer '@importer_id'?", $vars);
489
      $skip_message = dt("Skipping importer '@importer_id'.", $vars);
490
    }
491

    
492
    if (drush_confirm($confirm_message)) {
493
      _drush_feeds_create_import_batch($feed->id, $feed->feed_nid);
494
      $execute_batch = TRUE;
495
    }
496
    else {
497
      drush_log($skip_message, 'ok');
498
    }
499
  }
500

    
501
  if ($execute_batch) {
502
    drush_backend_batch_process();
503
  }
504
}
505

    
506
/**
507
 * Creates a batch job for an import.
508
 *
509
 * @param string $importer_id
510
 *   The importer id.
511
 * @param int $feed_nid
512
 *   The feed node id.
513
 */
514
function _drush_feeds_create_import_batch($importer_id, $feed_nid) {
515
  $feed_node = FALSE;
516
  if ($feed_nid) {
517
    if (!$feed_node = node_load($feed_nid)) {
518
      drush_set_error(dt('The feed node @feed_nid (@importer_id) does not exist.', array('@importer_id' => $importer_id, '@feed_nid' => $feed_nid)));
519
      return FALSE;
520
    }
521
  }
522

    
523
  $title = $feed_node ? $feed_node->title . ' (' . $importer_id . ')' : $importer_id;
524

    
525
  drush_log(dt('Importing: @title', array('@title' => $title)), 'ok');
526

    
527
  $batch = array(
528
    'title' => '',
529
    'operations' => array(
530
      array('feeds_batch', array('import', $importer_id, $feed_nid)),
531
    ),
532
    'progress_message' => '',
533
  );
534

    
535
  batch_set($batch);
536
}
537

    
538
/**
539
 * Clears a Feeds importer.
540
 *
541
 * @param string $importer_id
542
 *   The importer id to clean.
543
 */
544
function drush_feeds_clear($importer_id = NULL) {
545
  if (!strlen($importer_id)) {
546
    drush_set_error(dt("Please specify the importer to delete all imported items from. If the importer is attached to a content type, specify also the feed node with the option '--nid'."));
547
    return FALSE;
548
  }
549

    
550
  if (!$feed_nid = drush_get_option('nid')) {
551
    $feed_nid = 0;
552
  }
553

    
554
  try {
555
    feeds_source($importer_id, $feed_nid)->existing();
556
  }
557
  catch (FeedsNotExistingException $e) {
558
    $importer = feeds_importer_load($importer_id);
559
    if (!$importer) {
560
      drush_set_error(dt("The importer '@importer' does not exist.", array(
561
        '@importer' => $importer_id,
562
      )));
563
      return FALSE;
564
    }
565
    elseif (!$importer->isEnabled()) {
566
      drush_set_error(dt("The importer '@importer' is not enabled. You can enable it with the command '@command'.", array(
567
        '@importer' => $importer_id,
568
        '@command' => 'drush feeds-enable ' . $importer_id,
569
      )));
570
      return FALSE;
571
    }
572

    
573
    if ($feed_nid == 0) {
574
      // Check if the importer is a standalone importer.
575
      if ($importer->config['content_type']) {
576
        drush_set_error(dt("The importer '@importer' is attached to a content type. Please specify the feed node to delete items from with the option '--nid'. To show a list of available feed nodes for this importer, use 'drush feeds-list-feeds @importer'.", array(
577
          '@importer' => $importer_id,
578
        )));
579
        return FALSE;
580
      }
581
    }
582
    elseif (!$importer->config['content_type']) {
583
      $message = dt("The importer '@importer' is not attached to a content type. Do you want to clear all items for this importer?", array(
584
        '@importer' => $importer_id,
585
      ));
586

    
587
      if (!drush_confirm($message)) {
588
        return drush_log(dt('Aborting.'), 'ok');
589
      }
590
      else {
591
        drush_set_option('nid', 0);
592
        // Avoid asking for confirmation twice.
593
        drush_set_option('feeds_clear_skip_confirm', 1);
594
        return drush_feeds_clear($importer_id);
595
      }
596
    }
597

    
598
    drush_set_error(dt("There is no feed node with ID @nid for importer '@importer'. To show a list of available feed nodes for this importer, use 'drush feeds-list-feeds @importer'.", array(
599
      '@importer' => $importer_id,
600
      '@nid' => $feed_nid,
601
    )));
602
    return FALSE;
603
  }
604

    
605
  // Only ask for confirmation if it wasn't already asked before. See above.
606
  if (!drush_get_option('feeds_clear_skip_confirm')) {
607
    if ($feed_nid) {
608
      $message = dt("All items imported with the importer '@importer' for the feed node @feed_nid will be deleted. Do you really want to continue?", array(
609
        '@importer' => $importer_id,
610
        '@feed_nid' => $feed_nid,
611
      ));
612
    }
613
    else {
614
      $message = dt("All items imported with the importer '@importer' will be deleted. Do you really want to continue?", array(
615
        '@importer' => $importer_id,
616
      ));
617
    }
618
    if (!drush_confirm($message)) {
619
      return drush_log(dt('Aborting.'), 'ok');
620
    }
621
  }
622

    
623
  $batch = array(
624
    'title' => dt('Clearing !importer', array('!importer' => $importer_id)),
625
    'operations' => array(
626
      array('feeds_batch', array('clear', $importer_id, $feed_nid)),
627
    ),
628
  );
629

    
630
  batch_set($batch);
631
  drush_backend_batch_process();
632
}
633

    
634
/**
635
 * Enables a set of Feeds importers.
636
 */
637
function drush_feeds_enable() {
638
  $all = array_keys(feeds_importer_load_all(TRUE));
639
  $enabled = array_keys(feeds_importer_load_all());
640
  $missing = array_diff(func_get_args(), $all);
641
  $to_enable = array_diff(func_get_args(), $enabled, $missing);
642
  $already_enabled = array_intersect(func_get_args(), $enabled);
643

    
644
  if ($missing) {
645
    drush_print(dt('The following importers are missing: !importers', array('!importers' => implode(', ', $missing))));
646
  }
647

    
648
  if ($already_enabled) {
649
    drush_print(dt('The following importers are already enabled: !importers', array('!importers' => implode(', ', $already_enabled))));
650
  }
651

    
652
  if ($to_enable) {
653
    drush_print(dt('The following importers will be enabled: !importers', array('!importers' => implode(', ', $to_enable))));
654
  }
655
  elseif (count(func_get_args()) == 0) {
656
    return drush_set_error(dt('Please specify a space delimited list of importers to enable.'));
657
  }
658
  else {
659
    return drush_print(dt('There are no importers to enable.'));
660
  }
661

    
662
  if (!drush_confirm(dt('Do you really want to continue?'))) {
663
    return drush_log(dt('Aborting.'), 'ok');
664
  }
665

    
666
  $disabled = variable_get('default_feeds_importer', array());
667

    
668
  foreach ($to_enable as $importer_id) {
669
    unset($disabled[$importer_id]);
670
    drush_log(dt("The importer '!importer' has been enabled.", array('!importer' => $importer_id)), 'ok');
671
  }
672

    
673
  variable_set('default_feeds_importer', $disabled);
674
  feeds_cache_clear();
675
}
676

    
677
/**
678
 * Disables a set of Feeds importers.
679
 */
680
function drush_feeds_disable() {
681
  $all = array_keys(feeds_importer_load_all(TRUE));
682
  $enabled = array_keys(feeds_importer_load_all());
683
  $to_disable = array_intersect(func_get_args(), $enabled);
684
  $missing = array_diff(func_get_args(), $all);
685
  $already_disabled = array_diff(func_get_args(), $enabled, $missing);
686

    
687
  if ($missing) {
688
    drush_print(dt('The following importers are missing: !importers', array('!importers' => implode(', ', $missing))));
689
  }
690

    
691
  if ($already_disabled) {
692
    drush_print(dt('The following importers are already disabled: !importers', array('!importers' => implode(', ', $already_disabled))));
693
  }
694

    
695
  if ($to_disable) {
696
    drush_print(dt('The following importers will be disabled: !importers', array('!importers' => implode(', ', $to_disable))));
697
  }
698
  elseif (count(func_get_args()) == 0) {
699
    return drush_set_error(dt('Please specify a space delimited list of importers to disable.'));
700
  }
701
  else {
702
    return drush_print(dt('There are no importers to disable.'));
703
  }
704

    
705
  if (!drush_confirm(dt('Do you really want to continue?'))) {
706
    return drush_log(dt('Aborting.'), 'ok');
707
  }
708

    
709
  $disabled = variable_get('default_feeds_importer', array());
710
  foreach ($to_disable as $importer_id) {
711
    $disabled[$importer_id] = TRUE;
712
    drush_log(dt("The importer '!importer' has been disabled.", array('!importer' => $importer_id)), 'ok');
713
  }
714

    
715
  variable_set('default_feeds_importer', $disabled);
716
  feeds_cache_clear();
717
}
718

    
719
/**
720
 * Deletes a set of Feeds importers.
721
 */
722
function drush_feeds_delete() {
723
  $all = feeds_importer_load_all(TRUE);
724
  $to_delete = array_intersect_key($all, array_flip(func_get_args()));
725
  $missing = array_diff(func_get_args(), array_keys($all));
726
  $cant_delete = array();
727

    
728
  // Filter out default importers that are not overridden.
729
  foreach ($to_delete as $delta => $importer) {
730
    if ($importer->export_type === EXPORT_IN_CODE) {
731
      unset($to_delete[$delta]);
732
      $cant_delete[$importer->id] = $importer->id;
733
    }
734
  }
735

    
736
  if ($missing) {
737
    drush_print(dt('The following importers are missing: !importers', array('!importers' => implode(', ', $missing))));
738
  }
739

    
740
  if ($cant_delete) {
741
    drush_print(dt('The following importers cannot be deleted because they only exist in code: !importers', array('!importers' => implode(', ', array_keys($cant_delete)))));
742
  }
743

    
744
  if ($to_delete) {
745
    drush_print(dt('The following importers will be deleted: !importers', array('!importers' => implode(', ', array_keys($to_delete)))));
746
  }
747
  elseif (count(func_get_args()) == 0) {
748
    return drush_set_error(dt('Please specify a space delimited list of importers to delete.'));
749
  }
750
  else {
751
    return drush_print(dt('There are no importers to delete.'));
752
  }
753

    
754
  if (!drush_confirm(dt('Do you really want to continue?'))) {
755
    return drush_log(dt('Aborting.'), 'ok');
756
  }
757

    
758
  foreach ($to_delete as $importer) {
759
    $importer->delete();
760
    drush_log(dt("The importer '!importer' was deleted successfully.", array('!importer' => $importer->id)), 'ok');
761
  }
762

    
763
  feeds_cache_clear();
764
}
765

    
766
/**
767
 * Reverts a set of feeds.
768
 */
769
function drush_feeds_revert() {
770
  $all = feeds_importer_load_all(TRUE);
771
  $missing = array_diff(func_get_args(), array_keys($all));
772
  $to_revert = array_intersect_key($all, array_flip(func_get_args()));
773
  $cant_revert = array();
774
  $cant_revert_db = array();
775

    
776
  // Filter out non-overridden importers.
777
  foreach ($to_revert as $delta => $importer) {
778
    if ($importer->export_type !== (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
779
      unset($to_revert[$delta]);
780
      if ($importer->export_type == EXPORT_IN_DATABASE) {
781
        $cant_revert_db[$importer->id] = $importer->id;
782
      }
783
      else {
784
        $cant_revert[$importer->id] = $importer->id;
785
      }
786
    }
787
  }
788

    
789
  if ($missing) {
790
    drush_print(dt('The following importers are missing: !importers', array('!importers' => implode(', ', $missing))));
791
  }
792

    
793
  if ($cant_revert) {
794
    drush_print(dt('The following importers cannot be reverted because they are not overridden: !importers', array('!importers' => implode(', ', array_keys($cant_revert)))));
795
  }
796
  if ($cant_revert_db) {
797
    drush_print(dt('The following importers cannot be reverted because they only exist in the database: !importers', array('!importers' => implode(', ', array_keys($cant_revert_db)))));
798
  }
799

    
800
  if ($to_revert) {
801
    drush_print(dt('The following importers will be reverted: !importers', array('!importers' => implode(', ', array_keys($to_revert)))));
802
  }
803
  elseif (count(func_get_args()) == 0) {
804
    return drush_set_error(dt('Please specify a space delimited list of importers to revert.'));
805
  }
806
  else {
807
    return drush_print(dt('There are no importers to revert.'));
808
  }
809

    
810
  if (!drush_confirm(dt('Do you really want to continue?'))) {
811
    return drush_log(dt('Aborting.'), 'ok');
812
  }
813

    
814
  foreach ($to_revert as $importer) {
815
    $importer->delete();
816
    drush_log(dt("The importer '!importer' was reverted successfully.", array('!importer' => $importer->id)), 'ok');
817
  }
818

    
819
  feeds_cache_clear();
820
}
821

    
822
/**
823
 * Returns all feed instances filtered by an optional importer.
824
 *
825
 * @param string $importer_id
826
 *   (optional) The importer id.
827
 * @param int $limit
828
 *   (optional) The number of feeds to return.
829
 *
830
 * @return DatabaseStatementInterface
831
 *   A list of feeds objects.
832
 */
833
function _drush_feeds_get_all($importer_id = NULL, $limit = DRUSH_FEEDS_DEFAULT_LIMIT) {
834
  if (isset($importer_id)) {
835
    return db_query_range("SELECT * FROM {feeds_source} WHERE id = :importer ORDER BY imported ASC", 0, $limit, array(':importer' => $importer_id));
836
  }
837

    
838
  return db_query_range("SELECT * FROM {feeds_source} ORDER BY imported ASC", 0, $limit);
839
}
840

    
841
/**
842
 * Tries to find the specified file at several locations.
843
 *
844
 * @param string $filename
845
 *   The file to look for.
846
 *
847
 * @return string
848
 *   If found, the file that was found.
849
 *   NULL otherwise.
850
 */
851
function _drush_feeds_find_file($filename) {
852
  // If the full path to the file is specified, the file will be found right
853
  // away.
854
  if (is_file($filename)) {
855
    // Found!
856
    return $filename;
857
  }
858

    
859
  // Look for the file within the current active directory.
860
  $search = drush_cwd() . '/' . $filename;
861
  if (is_file($search)) {
862
    // Found!
863
    return $search;
864
  }
865

    
866
  // Look for the file within the directory Drupal is installed in.
867
  // bootstrap_drupal_root() sets the active directory to the Drupal root.
868
  $search = getcwd() . '/' . $filename;
869
  if (is_file($search)) {
870
    // Found!
871
    return $search;
872
  }
873
}