Version 1
[yaffs-website] / vendor / drush / drush / lib / Drush / UpdateService / ReleaseInfo.php
1 <?php
2
3 /**
4  * @file
5  * Drush release info engine for update.drupal.org and compatible services.
6  *
7  * This engine does connect directly to the update service. It doesn't depend
8  * on a bootstrapped site.
9  */
10
11 namespace Drush\UpdateService;
12
13 use Drush\Log\LogLevel;
14
15 /**
16  * Release info engine class.
17  */
18 class ReleaseInfo {
19   const DEFAULT_URL = 'https://updates.drupal.org/release-history';
20
21   // Cache release xml files for 24h by default.
22   const CACHE_LIFETIME = 86400;
23
24   private $cache;
25   private $engine_config;
26
27   /**
28    * Constructor.
29    */
30   public function __construct($type, $engine, $config) {
31     $this->engine_type = $type;
32     $this->engine = $engine;
33
34     if (is_null($config)) {
35       $config = array();
36     }
37     $config += array(
38       'cache-duration' => drush_get_option('cache-duration-releasexml', self::CACHE_LIFETIME),
39     );
40     $this->engine_config = $config;
41     $this->cache = array();
42   }
43
44   /**
45    * Returns configured cache duration.
46    */
47   public function getCacheDuration() {
48     return $this->engine_config['cache-duration'];
49   }
50
51   /**
52    * Returns a project's release info from the update service.
53    *
54    * @param array $request
55    *   A request array.
56    *
57    * @param bool $refresh
58    *   Whether to discard cached object.
59    *
60    * @return \Drush\UpdateService\Project
61    */
62   public function get($request, $refresh = FALSE) {
63     if ($refresh || !isset($this->cache[$request['name']])) {
64       $project_release_info = Project::getInstance($request, $this->getCacheDuration());
65       if ($project_release_info && !$project_release_info->isValid()) {
66         $project_release_info = FALSE;
67       }
68       $this->cache[$request['name']] = $project_release_info;
69     }
70     return $this->cache[$request['name']];
71   }
72
73   /**
74    * Delete cached update service file of a project.
75    *
76    * @param array $request
77    *   A request array.
78    */
79   public function clearCached(array $request) {
80     if (isset($this->cache[$request['name']])) {
81       unset($this->cache[$request['name']]);
82     }
83     $url = Project::buildFetchUrl($request);
84     $cache_file = drush_download_file_name($url);
85     if (file_exists($cache_file)) {
86       unlink($cache_file);
87     }
88   }
89
90   /**
91    * Select the most appropriate release for a project, based on a strategy.
92    *
93    * @param Array &$request
94    *   A request array.
95    *   The array will be expanded with the project type.
96    * @param String $restrict_to
97    *   One of:
98    *     'dev': Forces choosing a -dev release.
99    *     'version': Forces choosing a point release.
100    *     '': No restriction.
101    *   Default is ''.
102    * @param String $select
103    *   Strategy for selecting a release, should be one of:
104    *    - auto: Try to select the latest release, if none found allow the user
105    *            to choose.
106    *    - always: Force the user to choose a release.
107    *    - never: Try to select the latest release, if none found then fail.
108    *    - ignore: Ignore and return NULL.
109    *   If no supported release is found, allow to ask the user to choose one.
110    * @param Boolean $all
111    *   In case $select = TRUE this indicates that all available releases will be
112    *  offered the user to choose.
113    *
114    * @return array
115    *  The selected release.
116    */
117   public function selectReleaseBasedOnStrategy($request, $restrict_to = '', $select = 'never', $all = FALSE, $version = NULL) {
118     if (!in_array($select, array('auto', 'never', 'always', 'ignore'))) {
119       return drush_set_error('DRUSH_PM_UNKNOWN_SELECT_STRATEGY', dt("Error: select strategy must be one of: auto, never, always, ignore", array()));
120     }
121
122     $project_release_info = $this->get($request);
123     if (!$project_release_info) {
124       return FALSE;
125     }
126
127     if ($select != 'always') {
128       if (isset($request['version'])) {
129         $release = $project_release_info->getSpecificRelease($request['version']);
130         if ($release === FALSE) {
131           return drush_set_error('DRUSH_PM_COULD_NOT_FIND_VERSION', dt("Could not locate !project version !version.", array(
132             '!project' => $request['name'],
133             '!version' => $request['version'],
134           )));
135         }
136       }
137       if ($restrict_to == 'dev') {
138         // If you specified a specific release AND --dev, that is either
139         // redundant (okay), or contradictory (error).
140         if (!empty($release)) {
141           if ($release['version_extra'] != 'dev') {
142             return drush_set_error('DRUSH_PM_COULD_NOT_FIND_VERSION', dt("You requested both --dev and !project version !version, which is not a '-dev' release.", array(
143               '!project' => $request['name'],
144               '!version' => $request['version'],
145            )));
146          }
147         }
148         else {
149           $release = $project_release_info->getDevRelease();
150           if ($release === FALSE) {
151             return drush_set_error('DRUSH_PM_NO_DEV_RELEASE', dt('There is no development release for project !project.', array('!project' => $request['name'])));
152           }
153         }
154       }
155       // If there was no specific release requested, try to identify the most appropriate release.
156       if (empty($release)) {
157         $release = $project_release_info->getRecommendedOrSupportedRelease();
158       }
159       if ($release) {
160         return $release;
161       }
162       else {
163         $message = dt('There are no stable releases for project !project.', array('!project' => $request['name']));
164         if ($select == 'never') {
165           return drush_set_error('DRUSH_PM_NO_STABLE_RELEASE', $message);
166         }
167         drush_log($message, LogLevel::WARNING);
168         if ($select == 'ignore') {
169           return NULL;
170         }
171       }
172     }
173
174     // At this point the only chance is to ask the user to choose a release.
175     if ($restrict_to == 'dev') {
176       $filter = 'dev';
177     }
178     elseif ($all) {
179       $filter = 'all';
180     }
181     else {
182       $filter = '';
183     }
184     $releases = $project_release_info->filterReleases($filter, $version);
185
186     // Special checking: Drupal 6 is EOL, so there are no stable
187     // releases for ANY contrib project. In this case, we'll default
188     // to the best release, unless the user specified --select.
189     $version_major = drush_drupal_major_version();
190     if (($select != 'always') && ($version_major < 7)) {
191       $bestRelease = Project::getBestRelease($releases);
192       if (!empty($bestRelease)) {
193         $message = dt('Drupal !major has reached EOL, so there are no stable releases for any contrib projects. Selected the best release, !project.', array('!major' => $version_major, '!project' => $bestRelease['name']));
194         drush_log($message, LogLevel::WARNING);
195         return $bestRelease;
196       }
197     }
198
199     $options = array();
200     foreach($releases as $release) {
201       $options[$release['version']] = array($release['version'], '-', gmdate('Y-M-d', $release['date']), '-', implode(', ', $release['release_status']));
202     }
203     $choice = drush_choice($options, dt('Choose one of the available releases for !project:', array('!project' => $request['name'])));
204     if (!$choice) {
205       return drush_user_abort();
206     }
207
208     return $releases[$choice];
209   }
210
211   /**
212    * Check if a project is available in the update service.
213    *
214    * Optionally check for consistency by comparing given project type and
215    * the type obtained from the update service.
216    *
217    * @param array $request
218    *   A request array.
219    * @param string $type
220    *   Optional. If provided, will do a consistent check of the project type.
221    *
222    * @return boolean
223    *   True if the project exists and type matches.
224    */
225   public function checkProject($request, $type = NULL) {
226     $project_release_info = $this->get($request);
227     if (!$project_release_info) {
228       return FALSE;
229     }
230     if ($type) {
231       if ($project_release_info->getType() != $type) {
232         return FALSE;
233       }
234     }
235
236     return TRUE;
237   }
238 }