You are here

public function SecurityAdvisoriesFetcher::getSecurityAdvisories in Drupal 9

Gets security advisories that are applicable for the current site.

Parameters

bool $allow_outgoing_request: (optional) Whether to allow an outgoing request to fetch the advisories if there is no stored JSON response. Defaults to TRUE.

int $timeout: (optional) The timeout in seconds for the request. Defaults to 0, which is no timeout.

Return value

\Drupal\system\SecurityAdvisories\SecurityAdvisory[]|null The upstream security advisories, if any. NULL if there was a problem retrieving the JSON feed, or if there was no stored response and $allow_outgoing_request was set to FALSE.

Throws

\GuzzleHttp\Exception\TransferException Thrown if an error occurs while retrieving security advisories.

File

core/modules/system/src/SecurityAdvisories/SecurityAdvisoriesFetcher.php, line 120

Class

SecurityAdvisoriesFetcher
Defines a service to get security advisories.

Namespace

Drupal\system\SecurityAdvisories

Code

public function getSecurityAdvisories(bool $allow_outgoing_request = TRUE, int $timeout = 0) : ?array {
  $advisories = [];
  $json_payload = $this->keyValueExpirable
    ->get(self::ADVISORIES_JSON_EXPIRABLE_KEY);

  // If $json_payload is not an array then it was not set in this method or
  // has expired in which case we should try to retrieve the advisories.
  if (!is_array($json_payload)) {
    if (!$allow_outgoing_request) {
      return NULL;
    }
    $response = $this
      ->doRequest($timeout);
    $interval_seconds = $this->config
      ->get('interval_hours') * 60 * 60;
    $json_payload = Json::decode($response);
    if (is_array($json_payload)) {

      // Only store and use the response if it could be successfully
      // decoded to an array from the JSON string.
      // This value will be deleted if the 'advisories.interval_hours' config
      // is changed to a lower value.
      // @see \Drupal\update\EventSubscriber\ConfigSubscriber::onConfigSave()
      $this->keyValueExpirable
        ->setWithExpire(self::ADVISORIES_JSON_EXPIRABLE_KEY, $json_payload, $interval_seconds);
    }
    else {
      $this->logger
        ->error('The security advisory JSON feed from Drupal.org could not be decoded.');
      return NULL;
    }
  }
  foreach ($json_payload as $advisory_data) {
    try {
      $sa = SecurityAdvisory::createFromArray($advisory_data);
    } catch (\UnexpectedValueException $unexpected_value_exception) {

      // Ignore items in the feed that are in an invalid format. Although
      // this is highly unlikely we should still display the items that are
      // in the correct format.
      watchdog_exception('system', $unexpected_value_exception, 'Invalid security advisory format: ' . Json::encode($advisory_data));
      continue;
    }
    if ($this
      ->isApplicable($sa)) {
      $advisories[] = $sa;
    }
  }
  return $advisories;
}