Projet

Général

Profil

Révision ec2b0e7b

Ajouté par Assos Assos il y a presque 7 ans

Weekly update of contrib modules

Voir les différences:

drupal7/sites/all/modules/feeds/CHANGELOG.txt
1
Feeds 7.x 2.0 Beta 4, 2017-09-24
2
--------------------------------
3

  
4
- Issue #2911282 by MegaChriz: Fixed do not show bundle warning for non-entity
5
  processors.
6
- Issue #2911281 by MegaChriz: changed messages related to rescheduling imports.
7
- Issue #2879005 by MegaChriz, anup.singh: fixed array_flip() notice that
8
  occurred when mapping a float value to node author.
9
- Issue #1962006 by MegaChriz, gordon, twistor: Added hook
10
  hook_feeds_config_defaults() to allow other modules to add extra
11
  configuration.
12
- Issue #2884308 by ppavels: Fixed import links in admin menu for feed importers
13
  that are attached to a content type which name contains underscores.
14
- Issue #1360910 by MegaChriz, leendertdb: Added an option for the HTTP Fetcher
15
  to disable caching content fetched via HTTP.
16
- Issue #2877125 by MegaChriz: Replaced http_request_get() with
17
  feeds_http_request() in order to easier implement more options for HTTP
18
  requests.
19
- Issue #2662892 by MegaChriz: Do not cache downloaded source statically to
20
  improve PHP memory usage.
21
- Issue #2854548 by MegaChriz: Don't display a warning about "Attach to content
22
  type" setting being the same as the node processor's content type when the
23
  importer is not attached to a content type.
24
- Issue #2854548 by MegaChriz: Added warning when user has the "Attach to
25
  content type" setting the same as the node processor's content type.
26
- Issue #2445477 by MegaChriz: Added validation for combination of settings that
27
  causes the "Process in background" setting to have no effect.
28
- Issue #2630694 by MegaChriz, twistor: Run background jobs directly in queue.
29
- Issue #2868134 by MegaChriz: Show next time that the source will be imported.
30
- Issue #2450365 by MegaChriz, twistor, littledynamo: Fixed importer is not
31
  rescheduled for new sources when using attach to node.
32
- Issue #2871580 by MegaChriz: Fixed jobs for no longer existing feeds are kept
33
  being scheduled.
34
- Issue #2871583 by MegaChriz: Fixed feeds jobs are not cleaned up when
35
  uninstalling Feeds.
36
- Issue #2866377 by permanovd, MegaChriz: Fixed release file handle on
37
  exception.
38
- Issue #2320781 by MegaChriz: Added validation for feed importer configuration:
39
  check for invalid bundle and invalid language.
40
- Issue #2839706 by wmostrey, MegaChriz: Allow Feeds Importers to be edited even
41
  when disabled.
42
- Issue #2867182 by MegaChriz: Added a finishImport() method to FeedsSource to
43
  bundle tasks that need to be done at the end of an import.
44
- Issue #2867189 by MegaChriz: Added a method to FeedsSource to unlock a feed.
45
- Issue #2087091 by MegaChriz: Fixed clear states properly after import.
46
- Issue #2829097 by MegaChriz: fixed don't store raw source in feeds_source
47
  table.
48
- Issue #2863209 by MegaChriz: fixed class 'FeedsHTTPCache' not found in
49
  _cache_get_object() during/after performing database updates.
50
- Issue #2860047 by skessler, MegaChriz: Fixed link to feeds log page in
51
  watchdog call.
52
- Issue #2847312 by mikran, MegaChriz: Added entity metadata properties for
53
  feeds_item GUID and URL.
54
- Issue #2788125 by MegaChriz, PaulDinelle: Added support for i18n_node bundle
55
  language settings.
56
- Issue #2857935 by MegaChriz: Fixed failing test
57
  FeedsMapperMultilingualFieldsTestCase::testChangedLanguageImportForExistingNode().
58
- Issue #2854152 by renatog, MegaChriz: Delete feeds variables when uninstalling
59
  Feeds.
60
- Issue #2851707 by MegaChriz: Added user validation.
61
- Issue #2752661 by MegaChriz, geru: build the list of available sources and
62
  targets in feeds_ui_mapping_form() instead of in the theme function, so Feeds
63
  Tamper can alter the form to fix the bug of temporary targets not showing in
64
  the UI.
65
- Issue #1037188 by saurabh.tripathi.cs, msti, MegaChriz, twistor: Log
66
  exceptions that are thrown when trying to fetch from a HTTP source.
67
- Issue #2829096 by MegaChriz: Cache result of HTTP source on file system.
68
- Issue #2828605 by David_Rothstein: fixed "The following module has moved
69
  within the file system" warning that occurred when downloading or enabling a
70
  new module or when enabling a previously installed module that was moved on
71
  the file system.
72
- Issue #2762339 by MegaChriz: fixed feed node form inherits settings from the
73
  standalone importer when switching from standalone to attach to content type.
74
- Issue #2839464 by MegaChriz: improved error message for when a download from a
75
  url fails.
76
- Issue #2379631 by MegaChriz, cboyden, twistor, joelpittet, robhardwick,
77
  dsnopek: fixed field_attach_validate() must be called before programmatic
78
  entity saves.
79
- Issue #2445997 by MegaChriz: fixed do not load all Feeds plugins in
80
  feeds_forms() when no Feeds form is requested.
81
- Issue #2838283 by MegaChriz: Fixed failing test
82
  FeedsMapperDateMultipleTestCase::test().
83
- Issue #2834026 by bburg, MegaChriz: Fixed do not add blank column headers in
84
  CSV template.
85

  
1 86
Feeds 7.x 2.0 Beta 3, 2016-11-24
2 87
--------------------------------
3 88

  
......
488 573
- Issue #1739704 by axel.rutz: Fixed Node lookup by title in Nodeprocessor does
489 574
  not respect nodetype.
490 575
- Issue #1690434 by twistor | jzornig: Fixed Notice: Undefined variable: job in
491
  FeedsSource->scheduleClear() (line 319 of sites/all/modules/feeds/includes/FeedsSource.inc).
576
  FeedsSource->scheduleClear()
492 577
- Issue #1703074 by theduke: Added Include parser result in
493 578
  hook_feeds_presave().
494 579
- Issue #1070604 by Bobík: Added Feed's nid in mappings.
drupal7/sites/all/modules/feeds/README.txt
138 138
See "The developer's guide to Feeds":
139 139
http://drupal.org/node/622700
140 140

  
141
Running the Drush integration tests
142
===================================
143

  
144
In order the run Drush integration tests, Drush itself needs to be installed
145
with its *dev dependencies*. Furthermore, the phpunit version that comes with
146
Drush should be used for running the tests (instead of a globally installed
147
phpunit), as that one has proven to be compatible with the Drush tests.
148

  
149
  1. Git clone of Drush 8.
150

  
151
       git clone --branch 8.x https://github.com/drush-ops/drush.git
152
       cd drush
153

  
154
  2. Install Drush with dev dependencies using Composer.
155

  
156
       composer install
157

  
158
     And ensure that the following text is displayed:
159

  
160
       "Loading composer repositories with package information
161
       Installing dependencies (including require-dev) from lock file"
162

  
163
     Especially note that Composer says 'including require-dev'. This means that
164
     the Drush dev dependencies are installed (including phpunit).
165

  
166
  3. Execute a command like the following:
167

  
168
       UNISH_NO_TIMEOUTS=1 UNISH_DRUPAL_MAJOR_VERSION=7 /path/to/drush/vendor/bin/phpunit --configuration /path/to/drush/tests /path/to/feeds/tests/drush
169

  
170
     Replace '/path/to' with the appropriate path to the directory in question.
171
     Also be sure to point to the phpunit version that comes with Drush.
172

  
173
     So if Drush is installed in /users/megachriz/drush and the Feeds module is
174
     located at /users/megachriz/Sites/drupal7/sites/all/modules/feeds:
175

  
176
       UNISH_NO_TIMEOUTS=1 UNISH_DRUPAL_MAJOR_VERSION=7 /users/megachriz/drush/vendor/bin/phpunit --configuration /users/megachriz/drush/tests /users/megachriz/Sites/drupal7/sites/all/modules/feeds/tests/drush
177

  
141 178
Debugging
142 179
=========
143 180

  
......
194 231
Description: Flag to stop feeds from using its cURL for http requests. See
195 232
             http_request_use_curl().
196 233

  
234
Name:        feeds_http_file_cache_dir
235
Default:     private://feeds/cache
236
Description: The location on the file system where results of HTTP requests are
237
             cached.
238

  
239
Name:        feeds_in_progress_dir
240
Default:     private://feeds/in_progress
241
Description: The location on the file system where temporary files are stored
242
             that are in progress of being imported.
243

  
244
Name:        feeds_sync_cache_feeds_http_interval
245
Default:     21600
246
Description: How often the feeds cache directory should be checked for orphaned
247
             cache files.
248

  
197 249
Name:        feeds_use_mbstring
198 250
Default:     TRUE
199 251
Description: The extension mbstring is used to convert encodings during parsing.
drupal7/sites/all/modules/feeds/feeds.api.php
522 522
  $mapping += array('setting_value' => TRUE);
523 523
}
524 524

  
525
/**
526
 * This hooks allows you add additional configuration keys to a
527
 * FeedsConfigurable.
528
 *
529
 * @param FeedsConfigurable $configurable
530
 *   The configurable item to add default configuration to.
531
 *
532
 * @return array
533
 *   Return an array of default configuration.
534
 */
535
function hook_feeds_config_defaults(FeedsConfigurable $configurable) {
536
  if ($configurable instanceof FeedsImporter) {
537
    return array(
538
      'my_module_extra_setting_1' => 0,
539
      'my_module_extra_setting_2' => NULL,
540
    );
541
  }
542
}
543

  
544
/**
545
 * A plugin-specific hook to add additional configuration keys instead of the
546
 * global hook_feeds_config_defaults().
547
 *
548
 * The plugin type can be:
549
 * - fetcher
550
 * - parser
551
 * - processor
552
 *
553
 * @param FeedsPlugin $plugin
554
 *   The plugin to add default configuration to.
555
 *
556
 * @return array
557
 *   Return an array of default configuration.
558
 */
559
function hook_feeds_PLUGIN_TYPE_config_defaults(FeedsPlugin $plugin) {
560
  if ($plugin instanceof FeedsCSVParser) {
561
    return array(
562
      'extra_csv_parser_setting' => NULL,
563
    );
564
  }
565
}
566

  
525 567
/**
526 568
 * @}
527 569
 */
drupal7/sites/all/modules/feeds/feeds.drush.inc
300 300
  catch (FeedsNotExistingException $e) {
301 301
    $importer = feeds_importer_load($importer_id);
302 302
    if (!$importer) {
303
      drush_set_error(dt("The importer '@importer' does not exist or is not enabled.", array(
303
      drush_set_error(dt("The importer '@importer' does not exist.", array(
304 304
        '@importer' => $importer_id,
305 305
      )));
306 306
      return FALSE;
307 307
    }
308
    elseif (!$importer->isEnabled()) {
309
      drush_set_error(dt("The importer '@importer' is not enabled. You can enable it with the command '@command'.", array(
310
        '@importer' => $importer_id,
311
        '@command' => 'drush feeds-enable ' . $importer_id,
312
      )));
313
      return FALSE;
314
    }
308 315

  
309 316
    if ($feed_nid == 0) {
310 317
      // Check if the importer is a standalone importer.
......
542 549
  catch (FeedsNotExistingException $e) {
543 550
    $importer = feeds_importer_load($importer_id);
544 551
    if (!$importer) {
545
      drush_set_error(dt("The importer '@importer' does not exist or is not enabled.", array(
552
      drush_set_error(dt("The importer '@importer' does not exist.", array(
553
        '@importer' => $importer_id,
554
      )));
555
      return FALSE;
556
    }
557
    elseif (!$importer->isEnabled()) {
558
      drush_set_error(dt("The importer '@importer' is not enabled. You can enable it with the command '@command'.", array(
546 559
        '@importer' => $importer_id,
560
        '@command' => 'drush feeds-enable ' . $importer_id,
547 561
      )));
548 562
      return FALSE;
549 563
    }
drupal7/sites/all/modules/feeds/feeds.info
14 14
test_dependencies[] = variable:variable
15 15

  
16 16
files[] = includes/FeedsConfigurable.inc
17
files[] = includes/FeedsHTTPCache.inc
18
files[] = includes/FeedsHTTPCacheItem.inc
17 19
files[] = includes/FeedsImporter.inc
18 20
files[] = includes/FeedsSource.inc
19 21
files[] = libraries/ParserCSV.inc
......
41 43
files[] = tests/common_syndication_parser.test
42 44
files[] = tests/feeds_content_type.test
43 45
files[] = tests/feeds_date_time.test
46
files[] = tests/feeds_entity.test
47
files[] = tests/feeds_hooks.test
44 48
files[] = tests/feeds_mapper_date.test
45 49
files[] = tests/feeds_mapper_date_multiple.test
46 50
files[] = tests/feeds_mapper_field.test
......
60 64
files[] = tests/feeds_i18n.test
61 65
files[] = tests/feeds_i18n_node.test
62 66
files[] = tests/feeds_i18n_taxonomy.test
67
files[] = tests/feeds_install.test
63 68
files[] = tests/feeds_parser_csv.test
64 69
files[] = tests/feeds_parser_sitemap.test
65 70
files[] = tests/feeds_parser_syndication.test
......
73 78
files[] = tests/feeds_mapper_summary.test
74 79
files[] = tests/feeds_mapper_taxonomy.test
75 80
files[] = tests/feeds_tokens.test
81
files[] = tests/FeedsEnclosureTest.test
82
files[] = tests/FeedsFetcherResultTest.test
83
files[] = tests/FeedsHTTPCacheTest.test
84
files[] = tests/FeedsSourceTest.test
76 85
files[] = tests/http_request.test
77 86
files[] = tests/parser_csv.test
78 87

  
......
85 94
files[] = views/feeds_views_handler_filter_severity.inc
86 95
files[] = views/feeds_views_plugin_argument_validate_feed_nid.inc
87 96

  
88
; Information added by Drupal.org packaging script on 2016-11-24
89
version = "7.x-2.0-beta3"
97
; Information added by Drupal.org packaging script on 2017-09-24
98
version = "7.x-2.0-beta4"
90 99
core = "7.x"
91 100
project = "feeds"
92
datestamp = "1479993785"
101
datestamp = "1506257048"
93 102

  
drupal7/sites/all/modules/feeds/feeds.install
55 55
}
56 56

  
57 57
/**
58
  * Implement hook_uninstall()
59
  */
58
 * Implements hook_install().
59
 */
60
function feeds_install() {
61
  // Activate our custom cache handler for the HTTP cache.
62
  variable_set('cache_class_cache_feeds_http', 'FeedsHTTPCache');
63
}
64

  
65
/**
66
 * Implements hook_uninstall().
67
 */
60 68
function feeds_uninstall() {
61
  variable_del('http_request_timeout');
69
  variable_del('cache_class_cache_feeds_http');
70
  variable_del('cache_flush_cache_feeds_http');
71
  variable_del('default_feeds_importer');
72
  variable_del('feeds_debug');
73
  variable_del('feeds_http_file_cache_dir');
74
  variable_del('feeds_importer_class');
75
  variable_del('feeds_in_progress_dir');
76
  variable_del('feeds_library_dir');
77
  variable_del('feeds_never_use_curl');
78
  variable_del('feeds_process_limit');
62 79
  variable_del('feeds_reschedule');
80
  variable_del('feeds_source_class');
81
  variable_del('feeds_sync_cache_feeds_http_interval');
82
  variable_del('feeds_sync_cache_feeds_http_last_check');
63 83
  variable_del('feeds_use_mbstring');
84
  variable_del('http_request_timeout');
85

  
86
  // Remove Feeds related jobs from job scheduler.
87
  $names = db_or()
88
    ->condition('name', 'feeds_source_import')
89
    ->condition('name', 'feeds_source_clear')
90
    ->condition('name', 'feeds_source_expire')
91
    ->condition('name', 'feeds_push_unsubscribe');
92

  
93
  db_delete('job_schedule')
94
    ->condition($names)
95
    ->execute();
64 96
}
65 97

  
66 98
/**
......
706 738
    db_create_table('cache_feeds_http', $schema);
707 739
  }
708 740
}
741

  
742
/**
743
 * Set cache class for Feeds HTTP cache.
744
 */
745
function feeds_update_7213() {
746
  // Perform a registry rebuild so the system hopefully discovers the
747
  // FeedsHTTPCache class.
748
  if (function_exists('registry_rebuild')) {
749
    registry_rebuild();
750
  }
751

  
752
  // Abort when the FeedsHTTPCache class is not yet found to avoid fatal errors
753
  // in _cache_get_object().
754
  if (!class_exists('FeedsHTTPCache')) {
755
    throw new DrupalUpdateException('Setting the cache class for the cache_feeds_http bin failed because the FeedsHTTPCache class could not be found. Please rebuild the Drupal class registry and perform database updates again.');
756
  }
757

  
758
  // Activate our custom cache handler for the HTTP cache.
759
  variable_set('cache_class_cache_feeds_http', 'FeedsHTTPCache');
760
}
drupal7/sites/all/modules/feeds/feeds.module
38 38
    'feeds_processor_targets',
39 39
    'feeds_processor_targets_alter',
40 40
    'feeds_parser_sources_alter',
41
    'feeds_config_defaults',
42
    'feeds_fetcher_config_defaults',
43
    'feeds_parser_config_defaults',
44
    'feeds_processor_config_defaults',
41 45
  );
42 46

  
43 47
  return array_fill_keys($hooks, array('group' => 'feeds'));
......
53 57
    ->execute();
54 58

  
55 59
  // Find importers that need to be rescheduled.
56
  if (!$importers = feeds_reschedule()) {
57
    return;
58
  }
59

  
60
  // @todo Maybe we should queue this somehow as well. This could be potentially
61
  // very long.
62
  $sources = db_query("SELECT feed_nid, id FROM {feeds_source} WHERE id IN (:ids)", array(':ids' => $importers));
60
  $importers = feeds_reschedule();
61
  if ($importers) {
62
    // @todo Maybe we should queue this somehow as well. This could be potentially
63
    // very long.
64
    $sources = db_query("SELECT feed_nid, id FROM {feeds_source} WHERE id IN (:ids)", array(':ids' => $importers));
65

  
66
    foreach ($sources as $source) {
67
      feeds_source($source->id, $source->feed_nid)->schedule();
68
    }
63 69

  
64
  foreach ($sources as $source) {
65
    feeds_source($source->id, $source->feed_nid)->schedule();
70
    feeds_reschedule(FALSE);
66 71
  }
67 72

  
68
  feeds_reschedule(FALSE);
73
  // Sync the files in the cache directory with entries in the cache every now
74
  // and then. By default: every six hours.
75
  $last_check = variable_get('feeds_sync_cache_feeds_http_last_check');
76
  $interval = variable_get('feeds_sync_cache_feeds_http_interval', 21600);
77
  if ($last_check < (REQUEST_TIME - $interval)) {
78
    // Check first if the task isn't already queued.
79
    $queue = DrupalQueue::get('feeds_sync_cache_feeds_http');
80
    if ($queue->numberOfItems() < 1) {
81
      // Queue sync task.
82
      FeedsHTTPCache::getInstance('cache_feeds_http')->startSync();
83
    }
84
    variable_set('feeds_sync_cache_feeds_http_last_check', REQUEST_TIME);
85
  }
69 86
}
70 87

  
71 88
/**
......
78 95
  $info['feeds_source_import'] = array(
79 96
    'queue name' => 'feeds_source_import',
80 97
  );
98
  // feeds_source_clear never gets called, since we now use the queue directly.
99
  // This is left in case any background jobs still running after an
100
  // upgrade.
81 101
  $info['feeds_source_clear'] = array(
82 102
    'queue name' => 'feeds_source_clear',
83 103
  );
......
108 128
  $queues['feeds_push_unsubscribe'] = array(
109 129
    'worker callback' => 'feeds_push_unsubscribe',
110 130
  );
131
  $queues['feeds_sync_cache_feeds_http'] = array(
132
    'worker callback' => 'feeds_sync_cache_feeds_http',
133
  );
111 134

  
112 135
  return $queues;
113 136
}
......
117 140
 */
118 141
function feeds_source_import(array $job) {
119 142
  $source = _feeds_queue_worker_helper($job, 'import');
120
  $source->scheduleImport();
143
  if ($source->doesExist()) {
144
    $source->scheduleImport();
145
  }
121 146
}
122 147

  
123 148
/**
......
125 150
 */
126 151
function feeds_source_clear(array $job) {
127 152
  $source = _feeds_queue_worker_helper($job, 'clear');
128
  $source->scheduleClear();
153
  if ($source->doesExist()) {
154
    $source->scheduleClear();
155
  }
129 156
}
130 157

  
131 158
/**
......
133 160
 */
134 161
function feeds_source_expire(array $job) {
135 162
  $source = _feeds_queue_worker_helper($job, 'expire');
136
  $source->scheduleExpire();
163
  if ($source->doesExist()) {
164
    $source->scheduleExpire();
165
  }
137 166
}
138 167

  
139 168
/**
......
150 179
    $source->existing()->$method();
151 180
  }
152 181
  catch (FeedsNotExistingException $e) {
153
    // Do nothing.
182
    // Eventually remove the job from job scheduler.
183
    JobScheduler::get('feeds_source_import')->remove($job);
154 184
  }
155 185
  catch (Exception $e) {
156 186
    $source->log($method, $e->getMessage(), array(), WATCHDOG_ERROR);
......
159 189
  return $source;
160 190
}
161 191

  
192
/**
193
 * Scheduler callback for syncing the feeds cache directory with the entries in
194
 * the cache.
195
 */
196
function feeds_sync_cache_feeds_http(array $job) {
197
  FeedsHTTPCache::getInstance('cache_feeds_http')->sync($job['files']);
198
}
199

  
162 200
/**
163 201
 * Scheduler callback for unsubscribing from PuSH hubs.
164 202
 */
......
261 299
 *
262 300
 * Declare form callbacks for all known classes derived from FeedsConfigurable.
263 301
 */
264
function feeds_forms() {
302
function feeds_forms($form_id, $args) {
303
  // Check if the requested form is a Feeds form.
304
  if (!stripos($form_id, '_feeds_form')) {
305
    return;
306
  }
307

  
265 308
  $forms = array();
266 309
  $forms['FeedsImporter_feeds_form']['callback'] = 'feeds_form';
267 310
  $plugins = FeedsPlugin::all();
......
379 422
 */
380 423
function feeds_importer_load($id) {
381 424
  try {
382
    return feeds_importer($id)->existing();
425
    $importer = feeds_importer($id);
426
    if ($importer->doesExist()) {
427
      return $importer;
428
    }
383 429
  }
384
  catch (FeedsNotExistingException $e) {}
385 430
  catch (InvalidArgumentException $e) {}
386 431

  
387 432
  return FALSE;
......
491 536
  }
492 537

  
493 538
  if (drupal_static('feeds_log_error', FALSE)) {
494
    watchdog('feeds', 'Feeds reported errors, visit the Feeds log for details.', array(), WATCHDOG_ERROR, 'admin/reports/dblog/feeds');
539
    watchdog('feeds', 'Feeds reported errors, visit the Feeds log for details.', array(), WATCHDOG_ERROR, l(t('view'), 'admin/reports/feeds'));
495 540
  }
496 541
}
497 542

  
......
650 695
 */
651 696
function feeds_node_insert($node) {
652 697
  // Source attached to node.
653
  feeds_node_update($node);
654 698
  if (isset($node->feeds) && $importer_id = feeds_get_importer_id($node->type)) {
655 699
    $source = feeds_source($importer_id, $node->nid);
700
    $source->addConfig($node->feeds);
701
    $source->save();
702

  
656 703
    // Start import if requested.
657 704
    if (feeds_importer($importer_id)->config['import_on_create'] && !isset($node->feeds['suppress_import'])) {
658 705
      $source->startImport();
......
671 718
    $source = feeds_source($importer_id, $node->nid);
672 719
    $source->addConfig($node->feeds);
673 720
    $source->save();
721
    $source->ensureSchedule();
674 722
  }
675 723
}
676 724

  
......
696 744
    $form['#attributes']['enctype'] = 'multipart/form-data';
697 745

  
698 746
    // Build form.
699
    $source = feeds_source($importer_id, empty($form['#node']->nid) ? 0 : $form['#node']->nid);
747
    $source = feeds_source($importer_id, empty($form['#node']->nid) ? NULL : $form['#node']->nid);
700 748
    $form['feeds'] = array(
701 749
      '#type' => 'fieldset',
702 750
      '#title' => t('Feed'),
......
753 801
 * required if there are any importers using those plugins.
754 802
 */
755 803
function feeds_system_info_alter(array &$info, $file, $type) {
756
  if ($type !== 'module' || !module_hook($file->name, 'feeds_plugins')) {
804
  if ($type !== 'module' || !module_exists($file->name) || !module_hook($file->name, 'feeds_plugins')) {
757 805
    return;
758 806
  }
759 807

  
......
883 931
  foreach (feeds_importer_load_all() as $importer) {
884 932
    $content['menu']['admin/content']['admin/content/feeds_import'][$importer->id] = array(
885 933
      '#title' => t($importer->config['name']),
886
      '#href' => !empty($importer->config['content_type']) ? 'node/add/' . $importer->config['content_type'] : 'import/' . check_plain($importer->id),
934
      '#href' => !empty($importer->config['content_type']) ? 'node/add/' . str_replace('_', '-', $importer->config['content_type']) : 'import/' . check_plain($importer->id),
887 935
      '#access' => user_access('administer feeds') || user_access("import $importer->id feeds"),
888 936
    );
889 937
  }
......
1412 1460
function feeds_entity_property_info_alter(&$info) {
1413 1461

  
1414 1462
  foreach ($info as $entity_type => $entity_info) {
1463
    $info[$entity_type]['properties']['feeds_item_guid'] = array(
1464
      'label' => 'Feeds Item GUID',
1465
      'type' => 'text',
1466
      'description' => t('Feeds Item GUID.'),
1467
      'getter callback' => 'feeds_get_feeds_item_property',
1468
    );
1469
    $info[$entity_type]['properties']['feeds_item_url'] = array(
1470
      'label' => 'Feeds Item URL',
1471
      'type' => 'text',
1472
      'description' => t('Feeds Item URL.'),
1473
      'getter callback' => 'feeds_get_feeds_item_property',
1474
    );
1415 1475
    $info[$entity_type]['properties']['feed_nid'] = array(
1416 1476
      'label' => 'Feed NID',
1417 1477
      'type' => 'integer',
1418 1478
      'description' => t('Nid of the Feed Node that imported this entity.'),
1419
      'getter callback' => 'feeds_get_feed_nid_entity_callback',
1479
      'getter callback' => 'feeds_get_feeds_item_property',
1420 1480
    );
1421 1481
    $info[$entity_type]['properties']['feed_node'] = array(
1422 1482
      'label' => 'Feed node',
1423 1483
      'type' => 'node',
1424 1484
      'description' => t('Feed Node that imported this entity.'),
1425
      'getter callback' => 'feeds_get_feed_nid_entity_callback',
1485
      'getter callback' => 'feeds_get_feeds_item_property',
1426 1486
    );
1427 1487
  }
1428 1488
}
1429 1489

  
1430 1490
/**
1431
 * Gets the feed_nid for an entity for use in entity metadata.
1432
 */
1433
function feeds_get_feed_nid_entity_callback($entity, array $options, $name, $entity_type) {
1434
  list($entity_id, , ) = entity_extract_ids($entity_type, $entity);
1491
 * Entity API getter callback for getting a feeds_item property on an entity.
1492
 *
1493
 * @param object $entity
1494
 *   An entity object.
1495
 * @param array $options
1496
 *   Options are ignored, but it is a param that is given by the Entiy API.
1497
 * @param string $name
1498
 *   The name of the property to get.
1499
 * @param string $entity_type
1500
 *   The entity's type.
1501
 *
1502
 * @return mixed
1503
 *   The feeds_item property.
1504
 */
1505
function feeds_get_feeds_item_property($entity, array $options, $name, $entity_type) {
1506
  // Map property name to actual feeds_item column.
1507
  $property_map = array(
1508
    'feed_node' => 'feed_nid',
1509
    'feed_nid' => 'feed_nid',
1510
    'feeds_item_guid' => 'guid',
1511
    'feeds_item_url' => 'url',
1512
  );
1513
  $property_name = $property_map[$name];
1514

  
1515
  // First check if the entity has already the feeds item loaded with the
1516
  // requested property and return its value if it does.
1517
  if (isset($entity->feeds_item->$property_name)) {
1518
    return $entity->feeds_item->$property_name;
1519
  }
1435 1520

  
1436
  $feed_nid = NULL;
1521
  // No feed item. Try to load the feed item if the entity has an ID.
1522
  list($entity_id, , ) = entity_extract_ids($entity_type, $entity);
1437 1523
  if ($entity_id) {
1438
    $feed_nid = feeds_get_feed_nid($entity_id, $entity_type);
1439
    if ($feed_nid === FALSE) {
1440
      return NULL;
1524
    $feeds_item = feeds_item_info_load($entity_type, $entity_id);
1525

  
1526
    // Check again for the requested property and return its value if it exists.
1527
    if (isset($feeds_item->$property_name)) {
1528
      return $feeds_item->$property_name;
1441 1529
    }
1442 1530
  }
1443
  // If the entity has no ID (yet) try read the feed nid from the object
1444
  // directly.
1445
  elseif (isset($entity->feeds_item->feed_nid)) {
1446
    $feed_nid = $entity->feeds_item->feed_nid;
1447
  }
1448
  return $feed_nid;
1449 1531
}
1450 1532

  
1451 1533
/**
drupal7/sites/all/modules/feeds/feeds.pages.inc
85 85
    ) + $source_form;
86 86
  }
87 87

  
88
  // Set submit button label based on settings.
89
  if ($source->importer->config['import_on_create']) {
90
    $submit = t('Import');
91
    if ($source->importer->config['process_in_background']) {
92
      // When processing the import in background, the import job is put in the queue.
93
      $submit = t('Schedule import');
94
    }
95
  }
96
  elseif ($source->importer->config['import_period'] != FEEDS_SCHEDULE_NEVER) {
97
    // The import would be scheduled according to the periodic import setting.
98
    $submit = t('Schedule import');
99
  }
100
  else {
101
    drupal_set_message(t('For this importer both "@import_period" and "@import_on_create" are turned off. It is possible that Feeds will not import the provided source.', array(
102
      '@import_period' => t('Periodic import'),
103
      '@import_on_create' => t('Import on submission'),
104
    )), 'warning', FALSE);
105
    $submit = t('Save');
106
  }
107

  
88 108
  $form['submit'] = array(
89 109
    '#type' => 'submit',
90
    '#value' => t('Import'),
110
    '#value' => $submit,
91 111
  );
112

  
113
  // Disable submit button if import is initiated.
92 114
  $progress = $source->progressImporting();
93 115
  if ($progress !== FEEDS_BATCH_COMPLETE) {
94 116
    $form['submit']['#disabled'] = TRUE;
95 117
    $form['submit']['#value'] =
96 118
      t('Importing (@progress %)', array('@progress' => number_format(100 * $progress, 0)));
119

  
120
    // Check if import task is queued.
121
    if ($source->isQueued()) {
122
      $form['source_status']['#value'] .= t('Run cron to continue the import.');
123
    }
97 124
  }
125

  
98 126
  return $form;
99 127
}
100 128

  
......
121 149
  // Refresh feed if import on create is selected.
122 150
  if ($source->importer->config['import_on_create']) {
123 151
    $source->startImport();
152
    if ($source->importer->config['process_in_background']) {
153
      drupal_set_message(t('Import scheduled.'));
154
    }
124 155
  }
125 156

  
126 157
  // Add to schedule, make sure importer is scheduled, too.
127
  $source->schedule();
158
  $source->ensureSchedule();
159

  
160
  // If an import is only triggered by periodic import, check if it is about to
161
  // be rescheduled so there is at least a message.
162
  if (!$source->importer->config['import_on_create']) {
163
    // Check if the importer is about to be rescheduled.
164
    $importers = feeds_reschedule();
165
    if (isset($importers[$form['#importer_id']])) {
166
      drupal_set_message(t('Rescheduling the import will happen on the next cron run.'), 'status');
167
    }
168
  }
128 169
}
129 170

  
130 171
/**
......
145 186
    '#value' => feeds_source_status($source),
146 187
  );
147 188
  $form = confirm_form($form, t('Import all content from source?'), 'node/' . $node->nid, '', t('Import'), t('Cancel'), 'confirm feeds update');
189

  
190
  // Change submit button label if processing in background.
191
  if ($source->importer->config['process_in_background']) {
192
    $form['actions']['submit']['#value'] = t('Schedule import');
193
  }
194

  
195
  // Disable submit button if import is initiated.
148 196
  $progress = $source->progressImporting();
149 197
  if ($progress !== FEEDS_BATCH_COMPLETE) {
150 198
    $form['actions']['submit']['#disabled'] = TRUE;
151 199
    $form['actions']['submit']['#value'] =
152 200
      t('Importing (@progress %)', array('@progress' => number_format(100 * $progress, 0)));
201

  
202
    // Check if import task is queued.
203
    if ($source->isQueued()) {
204
      $form['source_status']['#value'] .= t('Run cron to continue the import.');
205
    }
153 206
  }
207

  
154 208
  return $form;
155 209
}
156 210

  
......
159 213
 */
160 214
function feeds_import_tab_form_submit($form, &$form_state) {
161 215
  $form_state['redirect'] = $form['#redirect'];
162
  feeds_source($form['#importer_id'], $form['#feed_nid'])->startImport();
216
  $source = feeds_source($form['#importer_id'], $form['#feed_nid']);
217
  $source->startImport();
218
  $source->ensureSchedule();
219

  
220
  if ($source->importer->config['process_in_background']) {
221
    drupal_set_message(t('Import scheduled.'));
222
  }
163 223
}
164 224

  
165 225
/**
......
188 248
    '#value' => feeds_source_status($source),
189 249
  );
190 250
  $form = confirm_form($form, t('Delete all items from source?'), $form['#redirect'], '', t('Delete'), t('Cancel'), 'confirm feeds update');
251

  
252
  // Change submit button label if processing in background.
253
  if ($source->importer->config['process_in_background']) {
254
    $form['actions']['submit']['#value'] = t('Schedule delete');
255
  }
256

  
257
  // Disable submit button if clearing is initiated.
191 258
  $progress = $source->progressClearing();
192 259
  if ($progress !== FEEDS_BATCH_COMPLETE) {
193 260
    $form['actions']['submit']['#disabled'] = TRUE;
194 261
    $form['actions']['submit']['#value'] =
195 262
      t('Deleting (@progress %)', array('@progress' => number_format(100 * $progress, 0)));
263
    $form['source_status']['#value'] .= t('Run cron to continue the deletion of items.');
196 264
  }
265

  
197 266
  return $form;
198 267
}
199 268

  
......
203 272
function feeds_delete_tab_form_submit($form, &$form_state) {
204 273
  $form_state['redirect'] = $form['#redirect'];
205 274
  $feed_nid = empty($form['#feed_nid']) ? 0 : $form['#feed_nid'];
206
  feeds_source($form['#importer_id'], $feed_nid)->startClear();
275
  $source = feeds_source($form['#importer_id'], $feed_nid);
276
  $source->startClear();
277
  $source->ensureSchedule();
278

  
279
  if ($source->importer->config['process_in_background']) {
280
    drupal_set_message(t('Deletion of items scheduled.'));
281
  }
207 282
}
208 283

  
209 284
/**
......
252 327
 * Form submit handler. Resets all feeds state.
253 328
 */
254 329
function feeds_unlock_tab_form_submit($form, &$form_state) {
255
  drupal_set_message(t('Import Unlocked'));
256 330
  $form_state['redirect'] = $form['#redirect'];
257 331
  $feed_nid = empty($form['#feed_nid']) ? 0 : $form['#feed_nid'];
258 332
  $importer_id = $form['#importer_id'];
259 333

  
260
  //Is there a more API-friendly way to set the state?
261
  db_update('feeds_source')
262
    ->condition('id', $importer_id)
263
    ->condition('feed_nid', $feed_nid)
264
    ->fields(array('state' => FALSE))
265
    ->execute();
334
  feeds_source($importer_id, $feed_nid)
335
    ->unlock();
336
  drupal_set_message(t('Importer unlocked.'));
266 337
}
267 338

  
268 339
/**
......
305 376
  }
306 377
  $v['imported'] = $source->imported;
307 378
  $v['count'] = $source->itemCount();
379
  $v['next'] = $source->getNextImportTimeDetails();
308 380
  if (!empty($v)) {
309 381
    return theme('feeds_source_status', $v);
310 382
  }
......
335 407
      $items[] = t('No imported items.');
336 408
    }
337 409
  }
410

  
411
  if ($v['next']) {
412
    // Check if medium date format contains hours/minutes.
413
    $date_format = variable_get('date_format_medium');
414
    $use_custom_date_format = $date_format && !strpos($date_format, 'H:i');
415

  
416
    if (!empty($v['next']['message'])) {
417
      $items[] = t('Next import: @message.', array(
418
        '@message' => $v['next']['message'],
419
      ));
420
    }
421
    elseif ($v['next']['time'] > REQUEST_TIME) {
422
      $items[] = t('Next import: @date (via @method)', array(
423
        '@date' => $use_custom_date_format ? format_date($v['next']['time'], 'custom', 'Y/m/d H:i:s') : format_date($v['next']['time']),
424
        '@method' => $v['next']['method'],
425
      ));
426
    }
427
    else {
428
      $items[] = t('Next import: on next cron run (via @method).', array(
429
        '@method' => $v['next']['method'],
430
      ));
431
    }
432
  }
433
  else {
434
    $items[] = t('Next import: not scheduled.');
435
  }
338 436
  $output .= theme('item_list', array('items' => $items));
339 437
  $output .= '</div>';
340 438
  return $output;
drupal7/sites/all/modules/feeds/feeds_import/feeds_import.info
10 10
features[feeds_importer][] = user
11 11
files[] = feeds_import.test
12 12

  
13
; Information added by Drupal.org packaging script on 2016-11-24
14
version = "7.x-2.0-beta3"
13
; Information added by Drupal.org packaging script on 2017-09-24
14
version = "7.x-2.0-beta4"
15 15
core = "7.x"
16 16
project = "feeds"
17
datestamp = "1479993785"
17
datestamp = "1506257048"
18 18

  
drupal7/sites/all/modules/feeds/feeds_news/feeds_news.info
19 19
files[] = feeds_news.module
20 20
files[] = feeds_news.test
21 21

  
22
; Information added by Drupal.org packaging script on 2016-11-24
23
version = "7.x-2.0-beta3"
22
; Information added by Drupal.org packaging script on 2017-09-24
23
version = "7.x-2.0-beta4"
24 24
core = "7.x"
25 25
project = "feeds"
26
datestamp = "1479993785"
26
datestamp = "1506257048"
27 27

  
drupal7/sites/all/modules/feeds/feeds_ui/feeds_ui.admin.inc
401 401
  $info['actions'] = array(l(t('Change'), $path . '/processor'));
402 402
  $config_info[] = $info;
403 403

  
404
  // Validate configuration.
405
  $errors = $importer->validateConfig();
406
  if (count($errors)) {
407
    $message = t('There are some issues with the importer configuration: !errors', array(
408
      '!errors' => theme('item_list', array('items' => $errors)),
409
    ));
410
    drupal_set_message($message, 'warning');
411
  }
412

  
404 413
  return theme('feeds_ui_edit_page', array(
405 414
    'info' => $config_info,
406 415
    'active' => $active_container,
......
493 502
function feeds_ui_mapping_form($form, &$form_state, $importer) {
494 503
  $form['#importer'] = $importer->id;
495 504
  $form['#mappings'] = $mappings = $importer->processor->getMappings();
505
  $form['#feeds_targets'] = $importer->processor->getMappingTargets();
506
  $form['#feeds_sources'] = $importer->parser->getMappingSources();
496 507
  $form['help']['#markup'] = feeds_ui_mapping_help();
497 508
  $form['#prefix'] = '<div id="feeds-ui-mapping-form-wrapper">';
498 509
  $form['#suffix'] = '</div>';
......
1032 1043
function theme_feeds_ui_mapping_form($variables) {
1033 1044
  $form = $variables['form'];
1034 1045

  
1035
  $targets = feeds_importer($form['#importer'])->processor->getMappingTargets();
1046
  $targets = $form['#feeds_targets'];
1036 1047
  $targets = _feeds_ui_format_options($targets, TRUE);
1037 1048

  
1038
  $sources = feeds_importer($form['#importer'])->parser->getMappingSources();
1049
  $sources = $form['#feeds_sources'];
1039 1050
  // Some parsers do not define source options.
1040 1051
  $sources = $sources ? _feeds_ui_format_options($sources, TRUE) : array();
1041 1052

  
......
1205 1216
  }
1206 1217

  
1207 1218
  if (!$form_state['values']['bypass_validation']) {
1219
    $errors = array();
1220

  
1221
    $importer = feeds_importer($feeds_importer->id);
1222
    $importer->setConfig($feeds_importer->config);
1208 1223
    foreach (array('fetcher', 'parser', 'processor') as $type) {
1209 1224
      $plugin = feeds_plugin($feeds_importer->config[$type]['plugin_key'], $feeds_importer->id);
1210
      if (get_class($plugin) == 'FeedsMissingPlugin') {
1211
        form_error($form['importer'], t('The plugin %plugin is unavailable.', array('%plugin' => $feeds_importer->config[$type]['plugin_key'])));
1225
      if (!($plugin instanceof FeedsMissingPlugin)) {
1226
        $importer->setPlugin($feeds_importer->config[$type]['plugin_key']);
1227
        $importer->$type->setConfig($feeds_importer->config[$type]['config']);
1212 1228
      }
1213 1229
    }
1230
    $errors = array_merge($errors, $importer->validateConfig());
1231
    if (!empty($errors)) {
1232
      form_error($form['importer'], theme('item_list', array('items' => $errors)));
1233
    }
1214 1234
  }
1215 1235

  
1216 1236
  $form_state['importer'] = $feeds_importer;
drupal7/sites/all/modules/feeds/feeds_ui/feeds_ui.info
7 7

  
8 8
files[] = feeds_ui.test
9 9

  
10
; Information added by Drupal.org packaging script on 2016-11-24
11
version = "7.x-2.0-beta3"
10
; Information added by Drupal.org packaging script on 2017-09-24
11
version = "7.x-2.0-beta4"
12 12
core = "7.x"
13 13
project = "feeds"
14
datestamp = "1479993785"
14
datestamp = "1506257048"
15 15

  
drupal7/sites/all/modules/feeds/feeds_ui/feeds_ui.test
18 18
  }
19 19

  
20 20
  public function setUp() {
21
    parent::setUp(array('php'), array('use PHP for settings'));
21
    parent::setUp(array('php', 'locale'), array('use PHP for settings', 'administer languages'));
22
  }
23

  
24
  /**
25
   * UI functionality tests on disabled feeds.
26
   */
27
  public function testEditDisabledImporter() {
28
    // Create an importer.
29
    $this->createImporterConfiguration('Test feed', 'test_feed');
30
    // Disable the importer.
31
    $edit = array(
32
      'test_feed' => FALSE,
33
    );
34
    $this->drupalPost('admin/structure/feeds', $edit, t('Save'));
35
    // Try to edit the importer.
36
    $this->doEditFeedsConfiguration('Test feed', 'test_feed');
22 37
  }
23 38

  
24 39
  /**
......
32 47
    // Create an importer.
33 48
    $this->createImporterConfiguration('Test feed', 'test_feed');
34 49

  
35
    // Assert UI elements.
36
    $this->drupalGet('admin/structure/feeds/test_feed');
37
    $this->assertText('Basic settings');
38
    $this->assertText('Fetcher');
39
    $this->assertText('HTTP Fetcher');
40
    $this->assertText('Parser');
41
    $this->assertText('Common syndication parser');
42
    $this->assertText('Processor');
43
    $this->assertText('Node processor');
44
    $this->assertText('Getting started');
45
    $this->assertRaw('admin/structure/feeds/test_feed/settings');
46
    $this->assertRaw('admin/structure/feeds/test_feed/settings/FeedsNodeProcessor');
47
    $this->assertRaw('admin/structure/feeds/test_feed/fetcher');
48
    $this->assertRaw('admin/structure/feeds/test_feed/parser');
49
    $this->assertRaw('admin/structure/feeds/test_feed/processor');
50
    // Try to edit the importer.
51
    $this->doEditFeedsConfiguration('Test feed', 'test_feed');
52

  
53
    // Check if importer is available on /import.
50 54
    $this->drupalGet('import');
51 55
    $this->assertText('Basic page');
52 56

  
......
116 120
    // @todo Refreshing/deleting feed items. Needs to live in feeds.test
117 121
  }
118 122

  
123
  /**
124
   * Tests if the user is warned when an invalid plugin is used.
125
   */
126
  public function testInvalidPlugin() {
127
    // Create an importer.
128
    $this->createImporterConfiguration('Test feed', 'test_feed');
129

  
130
    // Assert that there is no error message yet.
131
    $this->drupalGet('admin/structure/feeds/test_feed');
132
    $this->assertNoText('There are some issues with the importer configuration');
133

  
134
    // Add invalid fetcher plugin.
135
    $invalid_plugin = $this->randomName();
136
    $importer = feeds_importer('test_feed');
137
    $importer->addConfig(array(
138
      'fetcher' => array(
139
        'plugin_key' => $invalid_plugin,
140
        'config' => array(),
141
      ),
142
    ));
143
    $importer->save();
144

  
145
    // Assert error message on importer page.
146
    $this->drupalGet('admin/structure/feeds/test_feed');
147
    $this->assertText(format_string('The plugin @invalid_plugin is unavailable.', array(
148
      '@invalid_plugin' => $invalid_plugin,
149
    )));
150
  }
151

  
152
  /**
153
   * Tests if the user is warned when an invalid bundle is selected.
154
   */
155
  public function testInvalidBundle() {
156
    // Create an importer.
157
    $this->createImporterConfiguration('Test feed', 'test_feed');
158

  
159
    // Set invalid bundle.
160
    $invalid_bundle = drupal_strtolower($this->randomName());
161
    $importer = feeds_importer('test_feed');
162
    $importer->processor->addConfig(array(
163
      'bundle' => $invalid_bundle,
164
    ));
165
    $importer->save();
166

  
167
    // Assert error message on processor settings page.
168
    $this->drupalGet('admin/structure/feeds/test_feed/settings/FeedsNodeProcessor');
169
    $this->assertText(format_string('Invalid value @invalid_bundle for config option Bundle.', array(
170
      '@invalid_bundle' => $invalid_bundle,
171
    )));
172

  
173
    // But the option should still be selected.
174
    $this->assertFieldByName('bundle', $invalid_bundle);
175
  }
176

  
177
  /**
178
   * Tests if the user is warned when an invalid language is selected.
179
   */
180
  public function testInvalidLanguage() {
181
    // Add the Dutch language.
182
    $edit = array(
183
      'langcode' => 'nl',
184
    );
185
    $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
186

  
187
    // Create an importer.
188
    $this->createImporterConfiguration('Test feed', 'test_feed');
189
    // Change processor's language to Dutch.
190
    $this->setSettings('test_feed', 'FeedsNodeProcessor', array('language' => 'nl'));
191
    // Assert that there is no error message yet.
192
    $this->assertNoText('There are some issues with the importer configuration');
193

  
194
    // Now remove the Dutch language.
195
    $path = 'admin/config/regional/language/delete/nl';
196
    $this->drupalPost($path, array(), t('Delete'));
197

  
198
    // Assert error message on processor settings page.
199
    $this->drupalGet('admin/structure/feeds/test_feed/settings/FeedsNodeProcessor');
200
    $this->assertText(format_string('Invalid value @invalid_lang for config option Language.', array(
201
      '@invalid_lang' => 'nl',
202
    )));
203

  
204
    // But the option should still be selected.
205
    $this->assertFieldByName('language', 'nl');
206
  }
207

  
208
  /**
209
   * Tests if the user is warned when having both "Import on submission" and
210
   * "Periodic import" turned off.
211
   */
212
  public function testWarningPeriodicImportAndImportOnSubmissionTurnedOff() {
213
    // Create an importer.
214
    $this->createImporterConfiguration('Test feed', 'test_feed');
215

  
216
    $this->setSettings('test_feed', NULL, array(
217
      'content_type' => '',
218
      'import_period' => FEEDS_SCHEDULE_NEVER,
219
      'import_on_create' => FALSE,
220
    ));
221

  
222
    // Assert error message.
223
    $this->assertText(t('"@import_period" and "@import_on_create" are both turned off and the importer is not attached to a content type. Unless you have alternative methods of running imports for this importer, Feeds will not import anything for this importer.', array(
224
      '@import_period' => t('Periodic import'),
225
      '@import_on_create' => t('Import on submission'),
226
    )));
227
  }
228

  
229
  /**
230
   * Tests if the user is warned when having "Import on submission" turned off,
231
   * "Process in background" turned on and using the standalone form.
232
   */
233
  public function testWarningImportOnSubmissionTurnedOffAndProcessInBackgroundTurnedOn() {
234
    // Create an importer.
235
    $this->createImporterConfiguration('Test feed', 'test_feed');
236

  
237
    $this->setSettings('test_feed', NULL, array(
238
      'content_type' => '',
239
      'import_on_create' => FALSE,
240
      'process_in_background' => TRUE,
241
    ));
242

  
243
    // Assert error message.
244
    $this->assertText(t('Since "@import_on_create" is turned off and the importer is not attached to a content type, the "@process_in_background" setting may have no effect. When submitting the standalone form with the "@import_on_create" setting turned off, the feed is only scheduled for periodic import.', array(
245
      '@import_on_create' => t('Import on submission'),
246
      '@process_in_background' => t('Process in background'),
247
    )));
248
  }
249

  
250
  /**
251
   * Tests if the user is warned when the importer is attached to the same
252
   * content type as the one selected on the node processor.
253
   */
254
  public function testWarningWhenAttachImporterToContentTypeAlsoOnTheNodeProcessor() {
255
    // Create content type.
256
    $type = $this->drupalCreateContentType();
257
    $typename = $type->type;
258

  
259
    // Create an importer.
260
    $this->createImporterConfiguration('Test feed', 'test_feed');
261

  
262
    // Attach to content type.
263
    $this->setSettings('test_feed', NULL, array(
264
      'content_type' => $typename,
265
    ));
266

  
267
    // Select the same content type on the node processor.
268
    $this->setSettings('test_feed', 'FeedsNodeProcessor', array(
269
      'bundle' => $typename,
270
    ));
271

  
272
    $this->assertText('The importer is attached to the same content type as the content type selected on the node processor. Unless you have a very advanced use case, these two should never be the same.');
273
  }
274

  
119 275
  public function testImporterImport() {
120 276
    $name = $this->randomString();
121 277
    $id = drupal_strtolower($this->randomName());
......
157 313
    $this->assertTrue($config['skip_hash_check']);
158 314
  }
159 315

  
316
  /**
317
   * Tests if the user is warned when importing an importer with invalid configuration.
318
   */
319
  public function testInvalidConfigurationWhenImportingImporter() {
320
    $name = $this->randomString();
321
    $id = drupal_strtolower($this->randomName());
322
    $this->createImporterConfiguration($name, $id);
323
    $this->setPlugin($id, 'FeedsCSVParser');
324
    $this->setPlugin($id, 'FeedsFileFetcher');
325

  
326
    $this->drupalGet('admin/structure/feeds/' . $id . '/export');
327

  
328
    $export = $this->xpath('//textarea[1]/text()');
329
    $export = (string) $export[0];
330

  
331
    // Add in some invalid configuration in the export.
332
    $invalid_plugin = $this->randomName();
333
    $invalid_bundle = strtolower($this->randomName());
334
    $invalid_language = 'de';
335
    $export = str_replace('FeedsFileFetcher', $invalid_plugin, $export);
336
    $export = str_replace("'bundle' => 'article'", "'bundle' => '" . $invalid_bundle . "'", $export);
337
    $export = str_replace("'language' => 'und'", "'language' => '" . $invalid_language . "'", $export);
338

  
339
    // Delete this importer.
340
    $this->drupalPost('admin/structure/feeds/' . $id . '/delete', array(), t('Delete'));
341

  
342
    // Try to import.
343
    $edit = array(
344
      'importer' => $export,
345
    );
346
    $this->drupalPost('admin/structure/feeds/import', $edit, t('Import'));
347

  
348
    // Assert that the importer was not imported.
349
    $this->assertNoText("Successfully imported the $id feeds importer.");
350
    $this->assertFalse(feeds_importer_load($id), 'The importer was not created.');
351

  
352
    // Assert error messages.
353
    $this->assertText(format_string('The plugin @invalid_plugin is unavailable.', array(
354
      '@invalid_plugin' => $invalid_plugin,
355
    )));
356
    $this->assertText(format_string('Invalid value @invalid_bundle for config option Bundle.', array(
357
      '@invalid_bundle' => $invalid_bundle,
358
    )));
359
    $this->assertText(format_string('Invalid value @invalid_lang for config option Language.', array(
360
      '@invalid_lang' => $invalid_language,
361
    )));
362

  
363
    // Try if the importer is imported when ignoring validation.
364
    $edit['bypass_validation'] = 1;
365
    $this->drupalPost(NULL, $edit, t('Import'));
366

  
367
    // Assert that the importer has been imported now.
368
    drupal_static_reset();
369
    $this->assertTrue(feeds_importer_load($id) instanceof FeedsImporter, 'The importer was created.');
370

  
371
    // But the warnings should still be displayed.
372
    $this->drupalGet('admin/structure/feeds/' . $id);
373
    $this->assertText(format_string('The plugin @invalid_plugin is unavailable.', array(
374
      '@invalid_plugin' => $invalid_plugin,
375
    )));
376
    $this->assertText(format_string('Invalid value @invalid_bundle for config option Bundle.', array(
377
      '@invalid_bundle' => $invalid_bundle,
378
    )));
379
    $this->assertText(format_string('Invalid value @invalid_lang for config option Language.', array(
380
      '@invalid_lang' => $invalid_language,
381
    )));
382
  }
383

  
384
  /**
385
   * Edits an importer configuration.
386
   *
387
   * @param string $name
388
   *   The natural name of the feed.
389
   * @param string $id
390
   *   The persistent id of the feed.
391
   */
392
  protected function doEditFeedsConfiguration($name = 'Syndication', $id = 'syndication') {
393
    // Assert UI elements.
394
    $this->drupalGet('admin/structure/feeds/'. $id);
395
    $this->assertText($name);
396
    $this->assertText('Basic settings');
397
    $this->assertText('Fetcher');
398
    $this->assertText('HTTP Fetcher');
399
    $this->assertText('Parser');
400
    $this->assertText('Common syndication parser');
401
    $this->assertText('Processor');
402
    $this->assertText('Node processor');
403
    $this->assertText('Getting started');
404
    $this->assertRaw('admin/structure/feeds/'. $id .'/settings');
405
    $this->assertRaw('admin/structure/feeds/'. $id .'/settings/FeedsNodeProcessor');
406
    $this->assertRaw('admin/structure/feeds/'. $id .'/fetcher');
407
    $this->assertRaw('admin/structure/feeds/'. $id .'/parser');
408
    $this->assertRaw('admin/structure/feeds/'. $id .'/processor');
409
  }
410

  
160 411
}
drupal7/sites/all/modules/feeds/includes/FeedsConfigurable.inc
89 89
    return isset($this->$name) ? TRUE : FALSE;
90 90
  }
91 91

  
92
  /**
93
   * Determine whether this object is persistent.
94
   *
95
   * @return bool
96
   *   True if the object is persistent.
97
   *   False otherwise.
98
   */
99
  public function doesExist() {
100
    return ($this->export_type == FEEDS_EXPORT_NONE) ? FALSE : TRUE;
101
  }
102

  
103
  /**
104
   * Determine whether this object is enabled.
105
   *
106
   * @return bool
107
   *   True if the object is enabled.
108
   *   False otherwise.
109
   */
110
  public function isEnabled() {
111
    return $this->disabled ? FALSE : TRUE;
112
  }
113

  
92 114
  /**
93 115
   * Determine whether this object is persistent and enabled. I. e. it is
94 116
   * defined either in code or in the database and it is enabled.
95 117
   */
96 118
  public function existing() {
97
    if ($this->export_type == FEEDS_EXPORT_NONE) {
119
    if (!$this->doesExist()) {
98 120
      throw new FeedsNotExistingException(t('Object is not persistent.'));
99 121
    }
100
    if ($this->disabled) {
122
    if (!$this->isEnabled()) {
101 123
      throw new FeedsNotExistingException(t('Object is disabled.'));
102 124
    }
103 125
    return $this;
......
173 195
   *
174 196
   * @todo rename to getConfigDefaults().
175 197
   *
176
   * @return
198
   * @return array
177 199
   *   Array where keys are the variable names of the configuration elements and
178 200
   *   values are their default values.
179 201
   */
180 202
  public function configDefaults() {
203
    return array() + module_invoke_all('feeds_config_defaults', $this);
204
  }
205

  
206
  /**
207
   * Validates the configuration.
208
   *
209
   * @return array
210
   *   A list of errors.
211
   */
212
  public function validateConfig() {
181 213
    return array();
182 214
  }
183 215

  
drupal7/sites/all/modules/feeds/includes/FeedsHTTPCache.inc
1
<?php
2

  
3
/**
4
 * Cache implementation for the Feeds HTTP cache.
5
 */
6
class FeedsHTTPCache extends DrupalDatabaseCache {
7

  
8
  /**
9
   * Returns cache object.
10
   *
11
   * @param string $bin
12
   *   The cache bin.
13
   *
14
   * @return FeedsHTTPCache
15
   *   An instance of FeedsHTTPCache.
16
   */
17
  public static function getInstance($bin) {
18
    $cache_object = _cache_get_object($bin);
19
    if (!($cache_object instanceof self)) {
20
      // A different cache class could be used for the cache_feeds_http bin that
21
      // does not extend FeedsHTTPCache. In this case, just instantiate the
22
      // FeedsHTTPCache class.
23
      $cache_object = new self($bin);
24
    }
25
    return $cache_object;
26
  }
27

  
28
  /**
29
   * Returns cache dir.
30
   *
31
   * @return string
32
   *   The cache dir to use.
33
   */
34
  public function getCacheDir() {
35
    $dir = variable_get('feeds_http_file_cache_dir', NULL);
36
    if ($dir) {
37
      return $dir;
38
    }
39
    else {
40
      $schemes = file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE);
41
      $scheme = isset($schemes['private']) ? 'private' : 'public';
42
      return $scheme . '://feeds/cache';
43
    }
44
  }
45

  
46
  /**
47
   * Returns a list of file names in the cache directory.
48
   *
49
   * @return array
50
   *   A list of files.
51
   */
52
  public function getFileList() {
53
    $files = array();
54

  
55
    $file_cache_dir = $this->getCacheDir();
56
    if (is_dir($file_cache_dir)) {
57
      $dir = dir($file_cache_dir);
58
      while (($entry = $dir->read()) !== FALSE) {
59
        if ($entry == '.' || $entry == '..') {
60
          continue;
61
        }
62
        $files[] = $entry;
63
      }
64
      $dir->close();
65
    }
66

  
67
    return $files;
68
  }
69

  
... Ce différentiel a été tronqué car il excède la taille maximale pouvant être affichée.

Formats disponibles : Unified diff