Projet

Général

Profil

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

root / drupal7 / sites / all / modules / feeds / plugins / FeedsPlugin.inc @ ed9a13f1

1
<?php
2

    
3
/**
4
 * @file
5
 * Definition of FeedsPlugin class.
6
 */
7

    
8
/**
9
 * Base class for a fetcher, parser or processor result.
10
 */
11
class FeedsResult {}
12

    
13
/**
14
 * Implement source interface for all plugins.
15
 *
16
 * Note how this class does not attempt to store source information locally.
17
 * Doing this would break the model where source information is represented by
18
 * an object that is being passed into a Feed object and its plugins.
19
 */
20
abstract class FeedsPlugin extends FeedsConfigurable implements FeedsSourceInterface {
21

    
22
  /**
23
   * The plugin definition.
24
   *
25
   * @var array
26
   */
27
  protected $pluginDefinition;
28

    
29
  /**
30
   * Constructs a FeedsPlugin object.
31
   *
32
   * A copy of FeedsConfigurable::__construct() that doesn't call
33
   * configDefaults() so that we avoid circular dependencies.
34
   *
35
   * @param string $id
36
   *   The importer id.
37
   */
38
  protected function __construct($id) {
39
    $this->id = $id;
40
    $this->export_type = FEEDS_EXPORT_NONE;
41
    $this->disabled = FALSE;
42
  }
43

    
44
  /**
45
   * Instantiates a FeedsPlugin object.
46
   *
47
   * Don't use directly, use feeds_plugin() instead.
48
   *
49
   * @see feeds_plugin()
50
   */
51
  public static function instance($class, $id, array $plugin_definition = array()) {
52
    if (!strlen($id)) {
53
      throw new InvalidArgumentException(t('Empty configuration identifier.'));
54
    }
55

    
56
    $instances = &drupal_static(__METHOD__, array());
57

    
58
    if (!isset($instances[$class][$id])) {
59
      $instance = new $class($id);
60

    
61
      // The ordering here is important. The plugin definition should be usable
62
      // in getConfig().
63
      $instance->setPluginDefinition($plugin_definition);
64
      $instance->setConfig($instance->configDefaults());
65
      $instances[$class][$id] = $instance;
66
    }
67

    
68
    return $instances[$class][$id];
69
  }
70

    
71
  /**
72
   * Returns the type of plugin.
73
   *
74
   * @return string
75
   *   One of either 'fetcher', 'parser', or 'processor'.
76
   */
77
  abstract public function pluginType();
78

    
79
  /**
80
   * Returns the plugin definition.
81
   *
82
   * @return array
83
   *   The plugin definition array.
84
   *
85
   * @see ctools_get_plugins()
86
   */
87
  public function pluginDefinition() {
88
    return $this->pluginDefinition;
89
  }
90

    
91
  /**
92
   * Sets the plugin definition.
93
   *
94
   * This is protected since we're only using it in FeedsPlugin::instance().
95
   *
96
   * @param array $plugin_definition
97
   *   The plugin definition.
98
   */
99
  protected function setPluginDefinition(array $plugin_definition) {
100
    $this->pluginDefinition = $plugin_definition;
101
  }
102

    
103
  /**
104
   * Save changes to the configuration of this object.
105
   * Delegate saving to parent (= Feed) which will collect
106
   * information from this object by way of getConfig() and store it.
107
   */
108
  public function save() {
109
    feeds_importer($this->id)->save();
110
  }
111

    
112
  /**
113
   * Overrides FeedsConfigurable::configDefaults().
114
   *
115
   * Invokes a hook to add in additional default configuration.
116
   */
117
  public function configDefaults() {
118
    $hook = 'feeds_' . $this->pluginType() . '_config_defaults';
119
    return module_invoke_all($hook, $this) + parent::configDefaults();
120
  }
121

    
122
  /**
123
   * Returns TRUE if $this->sourceForm() returns a form.
124
   */
125
  public function hasSourceConfig() {
126
    $form = $this->sourceForm(array());
127
    return !empty($form);
128
  }
129

    
130
  /**
131
   * Implements FeedsSourceInterface::sourceDefaults().
132
   */
133
  public function sourceDefaults() {
134
    $values = array_flip(array_keys($this->sourceForm(array())));
135
    foreach ($values as $k => $v) {
136
      $values[$k] = '';
137
    }
138
    return $values;
139
  }
140

    
141
  /**
142
   * Callback methods, exposes source form.
143
   */
144
  public function sourceForm($source_config) {
145
    return array();
146
  }
147

    
148
  /**
149
   * Validation handler for sourceForm.
150
   */
151
  public function sourceFormValidate(&$source_config) {}
152

    
153
  /**
154
   * A source is being saved.
155
   */
156
  public function sourceSave(FeedsSource $source) {}
157

    
158
  /**
159
   * A source is being deleted.
160
   */
161
  public function sourceDelete(FeedsSource $source) {}
162

    
163
  /**
164
   * Loads on-behalf implementations from mappers/ directory.
165
   *
166
   * FeedsProcessor::map() does not load from mappers/ as only node and user
167
   * processor ship with on-behalf implementations.
168
   *
169
   * @see FeedsNodeProcessor::map()
170
   * @see FeedsUserProcessor::map()
171
   *
172
   * @todo: Use CTools Plugin API.
173
   */
174
  public static function loadMappers() {
175
    static $loaded = FALSE;
176
    if (!$loaded) {
177
      $path = drupal_get_path('module', 'feeds') . '/mappers';
178
      $files = drupal_system_listing('/.*\.inc$/', $path, 'name', 0);
179
      foreach ($files as $file) {
180
        if (strstr($file->uri, '/mappers/')) {
181
          require_once DRUPAL_ROOT . '/' . $file->uri;
182
        }
183
      }
184
    }
185
    $loaded = TRUE;
186
  }
187

    
188
  /**
189
   * Get all available plugins.
190
   */
191
  public static function all() {
192
    ctools_include('plugins');
193
    $plugins = ctools_get_plugins('feeds', 'plugins');
194

    
195
    $result = array();
196
    foreach ($plugins as $key => $info) {
197
      if (!empty($info['hidden'])) {
198
        continue;
199
      }
200
      $result[$key] = $info;
201
    }
202

    
203
    // Sort plugins by name and return.
204
    uasort($result, 'feeds_plugin_compare');
205
    return $result;
206
  }
207

    
208
  /**
209
   * Determines whether given plugin is derived from given base plugin.
210
   *
211
   * @param $plugin_key
212
   *   String that identifies a Feeds plugin key.
213
   * @param $parent_plugin
214
   *   String that identifies a Feeds plugin key to be tested against.
215
   *
216
   * @return
217
   *   TRUE if $parent_plugin is directly *or indirectly* a parent of $plugin,
218
   *   FALSE otherwise.
219
   */
220
  public static function child($plugin_key, $parent_plugin) {
221
    ctools_include('plugins');
222
    $plugins = ctools_get_plugins('feeds', 'plugins');
223

    
224
    if (!isset($plugins[$plugin_key])) {
225
      // Plugin is not available.
226
      return FALSE;
227
    }
228

    
229
    $info = $plugins[$plugin_key];
230

    
231
    if (empty($info['handler']['parent'])) {
232
      return FALSE;
233
    }
234
    elseif ($info['handler']['parent'] == $parent_plugin) {
235
      return TRUE;
236
    }
237
    else {
238
      return self::child($info['handler']['parent'], $parent_plugin);
239
    }
240
  }
241

    
242
  /**
243
   * Determines the type of a plugin.
244
   *
245
   * @todo PHP5.3: Implement self::type() and query with $plugin_key::type().
246
   *
247
   * @param $plugin_key
248
   *   String that identifies a Feeds plugin key.
249
   *
250
   * @return
251
   *   One of the following values:
252
   *   'fetcher' if the plugin is a fetcher
253
   *   'parser' if the plugin is a parser
254
   *   'processor' if the plugin is a processor
255
   *   FALSE otherwise.
256
   */
257
  public static function typeOf($plugin_key) {
258
    if (self::child($plugin_key, 'FeedsFetcher')) {
259
      return 'fetcher';
260
    }
261
    elseif (self::child($plugin_key, 'FeedsParser')) {
262
      return 'parser';
263
    }
264
    elseif (self::child($plugin_key, 'FeedsProcessor')) {
265
      return 'processor';
266
    }
267
    return FALSE;
268
  }
269

    
270
  /**
271
   * Gets all available plugins of a particular type.
272
   *
273
   * @param $type
274
   *   'fetcher', 'parser' or 'processor'
275
   */
276
  public static function byType($type) {
277
    $plugins = self::all();
278

    
279
    $result = array();
280
    foreach ($plugins as $key => $info) {
281
      if ($type == self::typeOf($key)) {
282
        $result[$key] = $info;
283
      }
284
    }
285
    return $result;
286
  }
287

    
288
  /**
289
   * Implements FeedsConfigurable::dependencies().
290
   */
291
  public function dependencies() {
292
    $dependencies = parent::dependencies();
293

    
294
    // Find out which module provides this plugin.
295
    $plugin_info = $this->pluginDefinition();
296
    if (isset($plugin_info['module'])) {
297
      $dependencies[$plugin_info['module']] = $plugin_info['module'];
298
    }
299

    
300
    return $dependencies;
301
  }
302

    
303
}
304

    
305
/**
306
 * Used when a plugin is missing.
307
 */
308
class FeedsMissingPlugin extends FeedsPlugin {
309

    
310
  /**
311
   * {@inheritdoc}
312
   */
313
  public function pluginType() {
314
    return 'missing';
315
  }
316

    
317
  /**
318
   * {@inheritdoc}
319
   */
320
  public function save() {}
321

    
322
  /**
323
   * Fetcher methods.
324
   */
325
  public function fetch(FeedsSource $source) {
326
    return new FeedsFetcherResult('');
327
  }
328

    
329
  /**
330
   * {@inheritdoc}
331
   */
332
  public function clear(FeedsSource $source) {}
333

    
334
  /**
335
   * {@inheritdoc}
336
   */
337
  public function request($feed_nid = 0) {
338
    drupal_access_denied();
339
  }
340

    
341
  /**
342
   * {@inheritdoc}
343
   */
344
  public function menuItem() {
345
    return array();
346
  }
347

    
348
  /**
349
   * {@inheritdoc}
350
   */
351
  public function subscribe(FeedsSource $source) {}
352

    
353
  /**
354
   * {@inheritdoc}
355
   */
356
  public function unsubscribe(FeedsSource $source) {}
357

    
358
  /**
359
   * {@inheritdoc}
360
   */
361
  public function importPeriod(FeedsSource $source) {}
362

    
363
  /**
364
   * Parser methods.
365
   */
366
  public function parse(FeedsSource $source, FeedsFetcherResult $fetcher_result) {
367
    return new FeedsParserResult();
368
  }
369

    
370
  /**
371
   * {@inheritdoc}
372
   */
373
  public function getMappingSources() {
374
    return array();
375
  }
376

    
377
  /**
378
   * Processor methods.
379
   */
380
  public function process(FeedsSource $source, FeedsParserResult $parser_result) {}
381

    
382
  /**
383
   * {@inheritdoc}
384
   */
385
  public function entityType() {}
386

    
387
  /**
388
   * {@inheritdoc}
389
   */
390
  public function bundle() {}
391

    
392
  /**
393
   * {@inheritdoc}
394
   */
395
  public function bundleOptions() {
396
    return array();
397
  }
398

    
399
  /**
400
   * {@inheritdoc}
401
   */
402
  public function getLimit() {
403
    return 0;
404
  }
405

    
406
  /**
407
   * {@inheritdoc}
408
   */
409
  public function getMappings() {
410
    return array();
411
  }
412

    
413
  /**
414
   * {@inheritdoc}
415
   */
416
  public function getMappingTargets() {
417
    return array();
418
  }
419

    
420
  /**
421
   * {@inheritdoc}
422
   */
423
  public function expire(FeedsSource $source, $time = NULL) {}
424

    
425
  /**
426
   * {@inheritdoc}
427
   */
428
  public function itemCount(FeedsSource $source) {
429
    return 0;
430
  }
431

    
432
  /**
433
   * {@inheritdoc}
434
   */
435
  public function expiryTime() {
436
    return FEEDS_EXPIRE_NEVER;
437
  }
438

    
439
}
440

    
441
/**
442
 * Sort callback for FeedsPlugin::all().
443
 */
444
function feeds_plugin_compare($a, $b) {
445
  return strcasecmp($a['name'], $b['name']);
446
}