class FeedsSource in Feeds 7
Same name and namespace in other branches
- 6 includes/FeedsSource.inc \FeedsSource
- 7.2 includes/FeedsSource.inc \FeedsSource
This class encapsulates a source of a feed. It stores where the feed can be found and how to import it.
Information on how to import a feed is encapsulated in a FeedsImporter object which is identified by the common id of the FeedsSource and the FeedsImporter. More than one FeedsSource can use the same FeedsImporter therefore a FeedsImporter never holds a pointer to a FeedsSource object, nor does it hold any other information for a particular FeedsSource object.
Classes extending FeedsPlugin can implement a sourceForm to expose configuration for a FeedsSource object. This is for instance how FeedsFetcher exposes a text field for a feed URL or how FeedsCSVParser exposes a select field for choosing between colon or semicolon delimiters.
It is important that a FeedsPlugin does not directly hold information about a source but leave all storage up to FeedsSource. An instance of a FeedsPlugin class only exists once per FeedsImporter configuration, while an instance of a FeedsSource class exists once per feed_nid to be imported.
As with FeedsImporter, the idea with FeedsSource is that it can be used without actually saving the object to the database.
Hierarchy
- class \FeedsConfigurable
- class \FeedsSource
Expanded class hierarchy of FeedsSource
1 string reference to 'FeedsSource'
- FeedsSource::instance in includes/
FeedsSource.inc - Instantiate a unique object per class/id/feed_nid. Don't use directly, use feeds_source() instead.
File
- includes/
FeedsSource.inc, line 76 - Definition of FeedsSourceInterface and FeedsSource class.
View source
class FeedsSource extends FeedsConfigurable {
// Contains the node id of the feed this source info object is attached to.
// Equals 0 if not attached to any node - i. e. if used on a
// standalone import form within Feeds or by other API users.
protected $feed_nid;
// The FeedsImporter object that this source is expected to be used with.
protected $importer;
// A FeedsBatch object. NULL if there is no active batch.
protected $batch;
/**
* Instantiate a unique object per class/id/feed_nid. Don't use
* directly, use feeds_source() instead.
*/
public static function instance($importer_id, $feed_nid = 0) {
$class = variable_get('feeds_source_class', 'FeedsSource');
static $instances = array();
if (!isset($instances[$class][$importer_id][$feed_nid])) {
$instances[$class][$importer_id][$feed_nid] = new $class($importer_id, $feed_nid);
}
return $instances[$class][$importer_id][$feed_nid];
}
/**
* Constructor.
*/
protected function __construct($importer_id, $feed_nid) {
$this->feed_nid = $feed_nid;
$this->importer = feeds_importer($importer_id);
parent::__construct($importer_id);
$this
->load();
}
/**
* Preview = fetch and parse a feed.
*
* @return
* FeedsImportBatch object, fetched and parsed.
*
* @throws
* Throws Exception if an error occurs when fetching or parsing.
*/
public function preview() {
$this->batch = $this->importer->fetcher
->fetch($this);
$this->importer->parser
->parse($this->batch, $this);
module_invoke_all('feeds_after_parse', $this->importer, $this);
$batch = $this->batch;
unset($this->batch);
return $batch;
}
/**
* Import a feed: execute fetching, parsing and processing stage.
*
* @return
* FEEDS_BATCH_COMPLETE if the import process finished. A decimal between
* 0.0 and 0.9 periodic if import is still in progress.
*
* @throws
* Throws Exception if an error occurs when importing.
*/
public function import() {
try {
if (!$this->batch || !$this->batch instanceof FeedsImportBatch) {
$this->batch = $this->importer->fetcher
->fetch($this);
$this->importer->parser
->parse($this->batch, $this);
module_invoke_all('feeds_after_parse', $this->importer, $this);
}
$this->importer->processor
->process($this->batch, $this);
$result = $this->batch
->getProgress();
if ($result == FEEDS_BATCH_COMPLETE) {
unset($this->batch);
module_invoke_all('feeds_after_import', $this->importer, $this);
}
} catch (Exception $e) {
unset($this->batch);
$this
->save();
throw $e;
}
$this
->save();
return $result;
}
/**
* Remove all items from a feed.
*
* @return
* FEEDS_BATCH_COMPLETE if the clearing process finished. A decimal between
* 0.0 and 0.9 periodic if clearing is still in progress.
*
* @throws
* Throws Exception if an error occurs when clearing.
*/
public function clear() {
try {
$this->importer->fetcher
->clear($this);
$this->importer->parser
->clear($this);
if (!$this->batch || !$this->batch instanceof FeedsClearBatch) {
$this->batch = new FeedsClearBatch();
}
$this->importer->processor
->clear($this->batch, $this);
$result = $this->batch
->getProgress();
if ($result == FEEDS_BATCH_COMPLETE) {
unset($this->batch);
module_invoke_all('feeds_after_clear', $this->importer, $this);
}
} catch (Exception $e) {
unset($this->batch);
$this
->save();
throw $e;
}
$this
->save();
return $result;
}
/**
* Schedule this source.
*/
public function schedule() {
// Check whether any fetcher is overriding the import period.
$period = $this->importer->config['import_period'];
$fetcher_period = $this->importer->fetcher
->importPeriod($this);
if (is_numeric($fetcher_period)) {
$period = $fetcher_period;
}
$job = array(
'callback' => 'feeds_source_import',
'type' => $this->id,
'id' => $this->feed_nid,
// Schedule as soon as possible if a batch is active.
'period' => $this->batch ? 0 : $period,
'periodic' => TRUE,
);
if ($job['period'] != FEEDS_SCHEDULE_NEVER) {
job_scheduler()
->set($job);
}
else {
job_scheduler()
->remove($job);
}
}
/**
* Save configuration.
*/
public function save() {
// Alert implementers of FeedsSourceInterface to the fact that we're saving.
foreach ($this->importer->plugin_types as $type) {
$this->importer->{$type}
->sourceSave($this);
}
$config = $this
->getConfig();
// Store the source property of the fetcher in a separate column so that we
// can do fast lookups on it.
$source = '';
if (isset($config[get_class($this->importer->fetcher)]['source'])) {
$source = $config[get_class($this->importer->fetcher)]['source'];
}
$object = array(
'id' => $this->id,
'feed_nid' => $this->feed_nid,
'config' => $config,
'source' => $source,
'batch' => isset($this->batch) ? $this->batch : FALSE,
);
if (db_query_range("SELECT 1 FROM {feeds_source} WHERE id = :id AND feed_nid = :nid", 0, 1, array(
':id' => $this->id,
':nid' => $this->feed_nid,
))
->fetchField()) {
drupal_write_record('feeds_source', $object, array(
'id',
'feed_nid',
));
}
else {
drupal_write_record('feeds_source', $object);
}
}
/**
* Load configuration and unpack.
*
* @todo Patch CTools to move constants from export.inc to ctools.module.
*/
public function load() {
if ($record = db_query("SELECT config, batch FROM {feeds_source} WHERE id = :id AND feed_nid = :nid", array(
':id' => $this->id,
':nid' => $this->feed_nid,
))
->fetch()) {
// While FeedsSource cannot be exported, we still use CTool's export.inc
// export definitions.
ctools_include('export');
$this->export_type = EXPORT_IN_DATABASE;
$this->config = unserialize($record->config);
$this->batch = unserialize($record->batch);
}
}
/**
* Delete configuration. Removes configuration information
* from database, does not delete configuration itself.
*/
public function delete() {
// Alert implementers of FeedsSourceInterface to the fact that we're
// deleting.
foreach ($this->importer->plugin_types as $type) {
$this->importer->{$type}
->sourceDelete($this);
}
db_delete('feeds_source')
->condition('id', $this->id)
->condition('feed_nid', $this->feed_nid)
->execute();
// Remove from schedule.
$job = array(
'callback' => 'feeds_source_import',
'type' => $this->id,
'id' => $this->feed_nid,
);
job_scheduler()
->remove($job);
}
/**
* Only return source if configuration is persistent and valid.
*
* @see FeedsConfigurable::existing().
*/
public function existing() {
// If there is no feed nid given, there must be no content type specified.
// If there is a feed nid given, there must be a content type specified.
// Ensure that importer is persistent (= defined in code or DB).
// Ensure that source is persistent (= defined in DB).
if (empty($this->feed_nid) && empty($this->importer->config['content_type']) || !empty($this->feed_nid) && !empty($this->importer->config['content_type'])) {
$this->importer
->existing();
return parent::existing();
}
}
/**
* Returns the configuration for a specific client class.
*
* @param FeedsSourceInterface $client
* An object that is an implementer of FeedsSourceInterface.
*
* @return
* An array stored for $client.
*/
public function getConfigFor(FeedsSourceInterface $client) {
return $this->config[get_class($client)];
}
/**
* Sets the configuration for a specific client class.
*
* @param FeedsSourceInterface $client
* An object that is an implementer of FeedsSourceInterface.
* @param $config
* The configuration for $client.
*
* @return
* An array stored for $client.
*/
public function setConfigFor(FeedsSourceInterface $client, $config) {
$this->config[get_class($client)] = $config;
}
/**
* Return defaults for feed configuration.
*/
public function configDefaults() {
// Collect information from plugins.
$defaults = array();
foreach ($this->importer->plugin_types as $type) {
if ($this->importer->{$type}
->hasSourceConfig()) {
$defaults[get_class($this->importer->{$type})] = $this->importer->{$type}
->sourceDefaults();
}
}
return $defaults;
}
/**
* Override parent::configForm().
*/
public function configForm(&$form_state) {
// Collect information from plugins.
$form = array();
foreach ($this->importer->plugin_types as $type) {
if ($this->importer->{$type}
->hasSourceConfig()) {
$class = get_class($this->importer->{$type});
$config = isset($this->config[$class]) ? $this->config[$class] : array();
$form[$class] = $this->importer->{$type}
->sourceForm($config);
$form[$class]['#tree'] = TRUE;
}
}
return $form;
}
/**
* Override parent::configFormValidate().
*/
public function configFormValidate(&$values) {
foreach ($this->importer->plugin_types as $type) {
$class = get_class($this->importer->{$type});
if (isset($values[$class]) && $this->importer->{$type}
->hasSourceConfig()) {
$this->importer->{$type}
->sourceFormValidate($values[$class]);
}
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
FeedsConfigurable:: |
protected | property | ||
FeedsConfigurable:: |
protected | property | CTools export enabled status of this object. | |
FeedsConfigurable:: |
protected | property | ||
FeedsConfigurable:: |
protected | property | ||
FeedsConfigurable:: |
public | function | Similar to setConfig but adds to existing configuration. | |
FeedsConfigurable:: |
public | function | Submission handler for configForm(). | 2 |
FeedsConfigurable:: |
public | function | Copy a configuration. | 1 |
FeedsConfigurable:: |
public | function | Implements getConfig(). | 1 |
FeedsConfigurable:: |
public | function | Set configuration. | |
FeedsConfigurable:: |
public | function | Override magic method __get(). Make sure that $this->config goes through getConfig() | |
FeedsSource:: |
protected | property | ||
FeedsSource:: |
protected | property | ||
FeedsSource:: |
protected | property | ||
FeedsSource:: |
public | function | Remove all items from a feed. | |
FeedsSource:: |
public | function |
Return defaults for feed configuration. Overrides FeedsConfigurable:: |
|
FeedsSource:: |
public | function |
Override parent::configForm(). Overrides FeedsConfigurable:: |
|
FeedsSource:: |
public | function |
Override parent::configFormValidate(). Overrides FeedsConfigurable:: |
|
FeedsSource:: |
public | function | Delete configuration. Removes configuration information from database, does not delete configuration itself. | |
FeedsSource:: |
public | function |
Only return source if configuration is persistent and valid. Overrides FeedsConfigurable:: |
|
FeedsSource:: |
public | function | Returns the configuration for a specific client class. | |
FeedsSource:: |
public | function | Import a feed: execute fetching, parsing and processing stage. | |
FeedsSource:: |
public static | function |
Instantiate a unique object per class/id/feed_nid. Don't use
directly, use feeds_source() instead. Overrides FeedsConfigurable:: |
|
FeedsSource:: |
public | function | Load configuration and unpack. | |
FeedsSource:: |
public | function | Preview = fetch and parse a feed. | |
FeedsSource:: |
public | function |
Save configuration. Overrides FeedsConfigurable:: |
|
FeedsSource:: |
public | function | Schedule this source. | |
FeedsSource:: |
public | function | Sets the configuration for a specific client class. | |
FeedsSource:: |
protected | function |
Constructor. Overrides FeedsConfigurable:: |