contrib modules security updates
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Distinguish exceptions occuring when handling locks.
|
||||
* Distinguish exceptions occurring when handling locks.
|
||||
*/
|
||||
class FeedsLockException extends Exception {}
|
||||
|
||||
@@ -18,6 +18,7 @@ define('FEEDS_FETCH', 'fetch');
|
||||
define('FEEDS_PARSE', 'parse');
|
||||
define('FEEDS_PROCESS', 'process');
|
||||
define('FEEDS_PROCESS_CLEAR', 'process_clear');
|
||||
define('FEEDS_PROCESS_EXPIRE', 'process_expire');
|
||||
|
||||
/**
|
||||
* Declares an interface for a class that defines default values and form
|
||||
@@ -86,9 +87,16 @@ class FeedsState {
|
||||
public $created;
|
||||
public $updated;
|
||||
public $deleted;
|
||||
public $unpublished;
|
||||
public $blocked;
|
||||
public $skipped;
|
||||
public $failed;
|
||||
|
||||
/**
|
||||
* IDs of entities to be removed.
|
||||
*/
|
||||
public $removeList;
|
||||
|
||||
/**
|
||||
* Constructor, initialize variables.
|
||||
*/
|
||||
@@ -98,6 +106,8 @@ class FeedsState {
|
||||
$this->created =
|
||||
$this->updated =
|
||||
$this->deleted =
|
||||
$this->unpublished =
|
||||
$this->blocked =
|
||||
$this->skipped =
|
||||
$this->failed = 0;
|
||||
}
|
||||
@@ -124,7 +134,7 @@ class FeedsState {
|
||||
$this->progress = FEEDS_BATCH_COMPLETE;
|
||||
}
|
||||
elseif ($total) {
|
||||
$this->progress = $progress / $total;
|
||||
$this->progress = (float) $progress / $total;
|
||||
if ($this->progress == FEEDS_BATCH_COMPLETE && $total != $progress) {
|
||||
$this->progress = 0.99;
|
||||
}
|
||||
@@ -178,13 +188,18 @@ class FeedsSource extends FeedsConfigurable {
|
||||
// Timestamp when this source was imported the last time.
|
||||
protected $imported;
|
||||
|
||||
// Holds an exception object in case an exception occurs during importing.
|
||||
protected $exception;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
$class = variable_get('feeds_source_class', 'FeedsSource');
|
||||
static $instances = array();
|
||||
|
||||
$instances = &drupal_static(__METHOD__, array());
|
||||
|
||||
if (!isset($instances[$class][$importer_id][$feed_nid])) {
|
||||
$instances[$class][$importer_id][$feed_nid] = new $class($importer_id, $feed_nid);
|
||||
}
|
||||
@@ -273,6 +288,7 @@ class FeedsSource extends FeedsConfigurable {
|
||||
*/
|
||||
public function schedule() {
|
||||
$this->scheduleImport();
|
||||
$this->scheduleExpire();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,19 +301,44 @@ class FeedsSource extends FeedsConfigurable {
|
||||
if (is_numeric($fetcher_period)) {
|
||||
$period = $fetcher_period;
|
||||
}
|
||||
$period = $this->progressImporting() === FEEDS_BATCH_COMPLETE ? $period : 0;
|
||||
$job = array(
|
||||
'type' => $this->id,
|
||||
'id' => $this->feed_nid,
|
||||
// Schedule as soon as possible if a batch is active.
|
||||
'period' => $period,
|
||||
'periodic' => TRUE,
|
||||
);
|
||||
if ($period != FEEDS_SCHEDULE_NEVER) {
|
||||
if ($period == FEEDS_SCHEDULE_NEVER && $this->progressImporting() === FEEDS_BATCH_COMPLETE) {
|
||||
JobScheduler::get('feeds_source_import')->remove($job);
|
||||
}
|
||||
elseif ($this->progressImporting() === FEEDS_BATCH_COMPLETE) {
|
||||
JobScheduler::get('feeds_source_import')->set($job);
|
||||
}
|
||||
else {
|
||||
JobScheduler::get('feeds_source_import')->remove($job);
|
||||
// Feed is not fully imported yet, so we put this job back in the queue
|
||||
// immediately for further processing.
|
||||
$queue = DrupalQueue::get('feeds_source_import');
|
||||
$queue->createItem($job);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule background expire tasks.
|
||||
*/
|
||||
public function scheduleExpire() {
|
||||
// Schedule as soon as possible if a batch is active.
|
||||
$period = $this->progressExpiring() === FEEDS_BATCH_COMPLETE ? 3600 : 0;
|
||||
|
||||
$job = array(
|
||||
'type' => $this->id,
|
||||
'id' => $this->feed_nid,
|
||||
'period' => $period,
|
||||
'periodic' => TRUE,
|
||||
);
|
||||
if ($this->importer->processor->expiryTime() == FEEDS_EXPIRE_NEVER) {
|
||||
JobScheduler::get('feeds_source_expire')->remove($job);
|
||||
}
|
||||
else {
|
||||
JobScheduler::get('feeds_source_expire')->set($job);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,6 +380,7 @@ class FeedsSource extends FeedsConfigurable {
|
||||
try {
|
||||
// If fetcher result is empty, we are starting a new import, log.
|
||||
if (empty($this->fetcher_result)) {
|
||||
module_invoke_all('feeds_before_import', $this);
|
||||
$this->state[FEEDS_START] = time();
|
||||
}
|
||||
|
||||
@@ -355,27 +397,91 @@ class FeedsSource extends FeedsConfigurable {
|
||||
|
||||
// Process.
|
||||
$this->importer->processor->process($this, $parser_result);
|
||||
|
||||
// Import finished without exceptions, so unset any potentially previously
|
||||
// recorded exceptions.
|
||||
unset($this->exception);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Do nothing.
|
||||
// $e is stored and re-thrown once we've had a chance to log our progress.
|
||||
// Set the exception so that other modules can check if an exception
|
||||
// occurred in hook_feeds_after_import().
|
||||
$this->exception = $e;
|
||||
}
|
||||
$this->releaseLock();
|
||||
|
||||
// Clean up.
|
||||
$result = $this->progressImporting();
|
||||
if ($result == FEEDS_BATCH_COMPLETE || isset($e)) {
|
||||
$this->imported = time();
|
||||
$this->log('import', 'Imported in !s s', array('!s' => $this->imported - $this->state[FEEDS_START]), WATCHDOG_INFO);
|
||||
$this->log('import', 'Imported in @s seconds.', array('@s' => $this->imported - $this->state[FEEDS_START]), WATCHDOG_INFO);
|
||||
module_invoke_all('feeds_after_import', $this);
|
||||
unset($this->fetcher_result, $this->state);
|
||||
}
|
||||
$this->save();
|
||||
|
||||
$this->releaseLock();
|
||||
|
||||
if (isset($e)) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports a fetcher result all at once in memory.
|
||||
*
|
||||
* @param FeedsFetcherResult $fetcher_result
|
||||
* The fetcher result to process.
|
||||
*
|
||||
* @throws Exception
|
||||
* Thrown if an error occurs when importing.
|
||||
*/
|
||||
public function pushImport(FeedsFetcherResult $fetcher_result) {
|
||||
// Since locks only work during a request, check if an import is active.
|
||||
if (!empty($this->fetcher_result) || !empty($this->state)) {
|
||||
throw new RuntimeException('The feed is currently importing.');
|
||||
}
|
||||
|
||||
$this->acquireLock();
|
||||
$start = time();
|
||||
|
||||
try {
|
||||
module_invoke_all('feeds_before_import', $this);
|
||||
|
||||
// Parse.
|
||||
do {
|
||||
$parser_result = $this->importer->parser->parse($this, $fetcher_result);
|
||||
module_invoke_all('feeds_after_parse', $this, $parser_result);
|
||||
|
||||
// Process.
|
||||
$this->importer->processor->process($this, $parser_result);
|
||||
|
||||
} while ($this->progressParsing() !== FEEDS_BATCH_COMPLETE);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// $e is stored and re-thrown once we've had a chance to log our progress.
|
||||
// Set the exception so that other modules can check if an exception
|
||||
// occurred in hook_feeds_after_import().
|
||||
$this->exception = $e;
|
||||
}
|
||||
|
||||
module_invoke_all('feeds_after_import', $this);
|
||||
|
||||
$this->imported = time();
|
||||
$this->log('import', 'Imported in @s seconds.', array('@s' => $this->imported - $start), WATCHDOG_INFO);
|
||||
|
||||
unset($this->fetcher_result, $this->state);
|
||||
|
||||
$this->save();
|
||||
|
||||
$this->releaseLock();
|
||||
|
||||
if (isset($e)) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from a feed.
|
||||
*
|
||||
@@ -398,7 +504,7 @@ class FeedsSource extends FeedsConfigurable {
|
||||
$this->importer->processor->clear($this);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Do nothing.
|
||||
// $e is stored and re-thrown once we've had a chance to log our progress.
|
||||
}
|
||||
$this->releaseLock();
|
||||
|
||||
@@ -415,6 +521,26 @@ class FeedsSource extends FeedsConfigurable {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all expired items from a feed.
|
||||
*/
|
||||
public function expire() {
|
||||
$this->acquireLock();
|
||||
try {
|
||||
$result = $this->importer->processor->expire($this);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Will throw after the lock is released.
|
||||
}
|
||||
$this->releaseLock();
|
||||
|
||||
if (isset($e)) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report progress as float between 0 and 1. 1 = FEEDS_BATCH_COMPLETE.
|
||||
*/
|
||||
@@ -449,6 +575,13 @@ class FeedsSource extends FeedsConfigurable {
|
||||
return $this->state(FEEDS_PROCESS_CLEAR)->progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report progress on expiry.
|
||||
*/
|
||||
public function progressExpiring() {
|
||||
return $this->state(FEEDS_PROCESS_EXPIRE)->progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a state object for a given stage. Lazy instantiates new states.
|
||||
*
|
||||
@@ -526,6 +659,9 @@ class FeedsSource extends FeedsConfigurable {
|
||||
if (!empty($record->state)) {
|
||||
$this->state = unserialize($record->state);
|
||||
}
|
||||
if (!is_array($this->state)) {
|
||||
$this->state = array();
|
||||
}
|
||||
if (!empty($record->fetcher_result)) {
|
||||
$this->fetcher_result = unserialize($record->fetcher_result);
|
||||
}
|
||||
@@ -552,6 +688,7 @@ class FeedsSource extends FeedsConfigurable {
|
||||
'id' => $this->feed_nid,
|
||||
);
|
||||
JobScheduler::get('feeds_source_import')->remove($job);
|
||||
JobScheduler::get('feeds_source_expire')->remove($job);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -722,4 +859,13 @@ class FeedsSource extends FeedsConfigurable {
|
||||
protected function releaseLock() {
|
||||
lock_release("feeds_source_{$this->id}_{$this->feed_nid}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements FeedsConfigurable::dependencies().
|
||||
*/
|
||||
public function dependencies() {
|
||||
$dependencies = parent::dependencies();
|
||||
return array_merge($dependencies, $this->importer()->dependencies());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user