Processes a task to fetch available update data for a single project.
Once the release history XML data is downloaded, it is parsed and saved in an entry just for that project.
$project: Associative array of information about the project to fetch data for.
TRUE if we fetched parsable XML, otherwise FALSE.
function _update_process_fetch_task($project) {
global $base_url;
$update_config = config('update.settings');
$fail =& drupal_static(__FUNCTION__, array());
// This can be in the middle of a long-running batch, so REQUEST_TIME won't
// necessarily be valid.
$request_time_difference = time() - REQUEST_TIME;
if (empty($fail)) {
// If we have valid data about release history XML servers that we have
// failed to fetch from on previous attempts, load that.
$fail = Drupal::keyValueExpirable('update')
->get('fetch_failures');
}
$max_fetch_attempts = $update_config
->get('fetch.max_attempts');
$success = FALSE;
$available = array();
$site_key = Crypt::hmacBase64($base_url, drupal_get_private_key());
$url = _update_build_fetch_url($project, $site_key);
$fetch_url_base = _update_get_fetch_url_base($project);
$project_name = $project['name'];
if (empty($fail[$fetch_url_base]) || $fail[$fetch_url_base] < $max_fetch_attempts) {
try {
$data = Drupal::httpClient()
->get($url, array(
'Accept' => 'text/xml',
))
->send()
->getBody(TRUE);
} catch (RequestException $exception) {
watchdog_exception('update', $exception);
}
}
if (!empty($data)) {
$available = update_parse_xml($data);
// @todo: Purge release data we don't need (http://drupal.org/node/238950).
if (!empty($available)) {
// Only if we fetched and parsed something sane do we return success.
$success = TRUE;
}
}
else {
$available['project_status'] = 'not-fetched';
if (empty($fail[$fetch_url_base])) {
$fail[$fetch_url_base] = 1;
}
else {
$fail[$fetch_url_base]++;
}
}
$frequency = $update_config
->get('check.interval_days');
$available['last_fetch'] = REQUEST_TIME + $request_time_difference;
Drupal::keyValueExpirable('update_available_releases')
->setWithExpire($project_name, $available, $request_time_difference + 60 * 60 * 24 * $frequency);
// Stash the $fail data back in the DB for the next 5 minutes.
Drupal::keyValueExpirable('update')
->setWithExpire('fetch_failures', $fail, $request_time_difference + 60 * 5);
// Whether this worked or not, we did just (try to) check for updates.
Drupal::state()
->set('update.last_check', REQUEST_TIME + $request_time_difference);
// Now that we processed the fetch task for this project, clear out the
// record for this task so we're willing to fetch again.
drupal_container()
->get('keyvalue')
->get('update_fetch_task')
->delete($project_name);
return $success;
}