Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / drush / drush / src / Commands / pm / SecurityUpdateCommands.php
diff --git a/vendor/drush/drush/src/Commands/pm/SecurityUpdateCommands.php b/vendor/drush/drush/src/Commands/pm/SecurityUpdateCommands.php
new file mode 100644 (file)
index 0000000..bd195f5
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+namespace Drush\Commands\pm;
+
+use Composer\Semver\Comparator;
+use Consolidation\AnnotatedCommand\CommandData;
+use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
+use Drush\Commands\DrushCommands;
+use Drush\Drush;
+use Exception;
+use Webmozart\PathUtil\Path;
+
+/**
+ * Check Drupal Composer packages for security updates.
+ */
+class SecurityUpdateCommands extends DrushCommands
+{
+
+    /**
+     * @var array
+     */
+    protected $securityUpdates;
+
+    /**
+     * Check Drupal Composer packages for pending security updates.
+     *
+     * This uses the Drupal security advisories package to determine if updates
+     * are available.
+     *
+     * @see https://github.com/drupal-composer/drupal-security-advisories
+     *
+     * @command pm:security
+     * @aliases sec,pm-security
+     * @bootstrap none
+     * @table-style default
+     * @field-labels
+     *   name: Name
+     *   version: Installed Version
+     *   min-version: Suggested version
+     * @default-fields name,version,min-version
+     *
+     * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
+     *
+     * @throws \Exception
+     */
+    public function security()
+    {
+        $this->securityUpdates = [];
+        try {
+            $response_body = file_get_contents('https://raw.githubusercontent.com/drupal-composer/drupal-security-advisories/8.x/composer.json');
+        } catch (Exception $e) {
+            throw new Exception("Unable to fetch drupal-security-advisories information.");
+        }
+        $security_advisories_composer_json = json_decode($response_body, true);
+        $composer_root = Drush::bootstrapManager()->getComposerRoot();
+        $composer_lock_file_name = getenv('COMPOSER') ? str_replace('.json', '', getenv('COMPOSER')) : 'composer';
+        $composer_lock_file_name .= '.lock';
+        $composer_lock_file_path = Path::join($composer_root, $composer_lock_file_name);
+        if (!file_exists($composer_lock_file_path)) {
+            throw new Exception("Cannot find $composer_lock_file_path!");
+        }
+        $composer_lock_contents = file_get_contents($composer_lock_file_path);
+        $composer_lock_data = json_decode($composer_lock_contents, true);
+        if (!array_key_exists('packages', $composer_lock_data)) {
+            throw new Exception("No packages were found in $composer_lock_file_path! Contents:\n $composer_lock_contents");
+        }
+        foreach ($composer_lock_data['packages'] as $key => $package) {
+            $name = $package['name'];
+            if (!empty($security_advisories_composer_json['conflict'][$name])) {
+                $conflict_constraints = explode(',', $security_advisories_composer_json['conflict'][$name]);
+                foreach ($conflict_constraints as $conflict_constraint) {
+                    // Only parse constraints that follow pattern like "<1.0.0".
+                    if (substr($conflict_constraint, 0, 1) == '<') {
+                        $min_version = substr($conflict_constraint, 1);
+                        if (Comparator::lessThan($package['version'], $min_version)) {
+                            $this->securityUpdates[$name] = [
+                                'name' => $name,
+                                'version' => $package['version'],
+                                'min-version' => $min_version,
+                            ];
+                        }
+                    } else {
+                        $this->logger()->warning("Could not parse drupal-security-advisories conflicting version constraint $conflict_constraint for package $name.");
+                    }
+                }
+            }
+        }
+        if ($this->securityUpdates) {
+            // @todo Modernize.
+            drush_set_context('DRUSH_EXIT_CODE', DRUSH_FRAMEWORK_ERROR);
+            $result = new RowsOfFields($this->securityUpdates);
+            return $result;
+        } else {
+            $this->logger()->success("<info>There are no outstanding security updates for Drupal projects.</info>");
+        }
+    }
+
+    /**
+     * Emit suggested Composer command for security updates.
+     *
+     * @hook post-command pm:security
+     */
+    public function suggestComposerCommand($result, CommandData $commandData)
+    {
+        if (!empty($this->securityUpdates)) {
+            $suggested_command = 'composer require ';
+            foreach ($this->securityUpdates as $package) {
+                $suggested_command .= $package['name'] . ':^' . $package['min-version'] . ' ';
+            }
+            $suggested_command .= '--update-with-dependencies';
+            $this->logger()->warning("One or more of your dependencies has an outstanding security update. Please apply update(s) immediately.");
+            $this->logger()->notice("Try running: <comment>$suggested_command</comment>");
+            $this->logger()->notice("If that fails due to a conflict then you must update one or more root dependencies.");
+        }
+    }
+}