5 * pm-updatestatus command implementation.
9 * Command callback. Displays update status info of installed projects.
11 * Pass specific projects as arguments, otherwise we show all that are
14 function drush_pm_updatestatus() {
15 // Get specific requests.
16 $args = pm_parse_arguments(func_get_args(), FALSE);
18 // Get installed extensions and projects.
19 $extensions = drush_get_extensions();
20 $projects = drush_get_projects($extensions);
22 // Parse out project name and version.
24 foreach ($args as $request) {
25 $request = pm_parse_request($request, NULL, $projects);
26 $requests[$request['name']] = $request;
29 // Get the engine instance.
30 $update_status = drush_get_engine('update_status');
32 // If the user doesn't provide a value for check-disabled option,
33 // and the update backend is 'drupal', use NULL, so the engine
34 // will respect update.module defaults.
35 $check_disabled_default = ($update_status->engine == 'drupal') ? NULL : FALSE;
36 $check_disabled = drush_get_option('check-disabled', $check_disabled_default);
38 $update_info = $update_status->getStatus($projects, $check_disabled);
40 foreach ($extensions as $name => $extension) {
41 // Add an item to $update_info for each enabled extension which was obtained
42 // from cvs or git and its project is unknown (because of cvs_deploy or
43 // git_deploy is not enabled).
44 if (!isset($extension->info['project'])) {
45 if ((isset($extension->vcs)) && ($extension->status)) {
46 $update_info[$name] = array(
48 'label' => $extension->label,
49 'existing_version' => 'Unknown',
50 'status' => DRUSH_UPDATESTATUS_PROJECT_NOT_PACKAGED,
51 'status_msg' => dt('Project was not packaged by drupal.org but obtained from !vcs. You need to enable !vcs_deploy module', array('!vcs' => $extension->vcs)),
53 // The user may have requested to update a project matching this
54 // extension. If it was by coincidence or error we don't mind as we've
55 // already added an item to $update_info. Just clean up $requests.
56 if (isset($requests[$name])) {
57 unset($requests[$name]);
61 // Additionally if the extension name is distinct to the project name and
62 // the user asked to update the extension, fix the request.
63 elseif ((isset($requests[$name])) && ($name != $extension->info['project'])) {
64 $requests[$extension->info['project']] = $requests[$name];
65 unset($requests[$name]);
68 // If specific project updates were requested then remove releases for all
70 $requested = func_get_args();
71 if (!empty($requested)) {
72 foreach ($update_info as $name => $project) {
73 if (!isset($requests[$name])) {
74 unset($update_info[$name]);
78 // Add an item to $update_info for each request not present in $update_info.
79 foreach ($requests as $name => $request) {
80 if (!isset($update_info[$name])) {
82 if ((isset($projects[$name])) && ($projects[$name]['status'] == 0)) {
83 $update_info[$name] = array(
85 'label' => $projects[$name]['label'],
86 'existing_version' => $projects[$name]['version'],
87 'status' => DRUSH_UPDATESTATUS_REQUESTED_PROJECT_NOT_UPDATEABLE,
89 unset($requests[$name]);
91 // At this point we are unable to find matching installed project.
92 // It does not exist at all or it is misspelled,...
94 $update_info[$name] = array(
97 'existing_version' => 'Unknown',
98 'status'=> DRUSH_UPDATESTATUS_REQUESTED_PROJECT_NOT_FOUND,
104 // If specific versions were requested, match the requested release.
105 foreach ($requests as $name => $request) {
106 if (!empty($request['version'])) {
107 if (empty($update_info[$name]['releases'][$request['version']])) {
108 $update_info[$name]['status'] = DRUSH_UPDATESTATUS_REQUESTED_VERSION_NOT_FOUND;
110 elseif ($request['version'] == $update_info[$name]['existing_version']) {
111 $update_info[$name]['status'] = DRUSH_UPDATESTATUS_REQUESTED_VERSION_CURRENT;
113 // TODO: should we warn/reject if this is a downgrade?
115 $update_info[$name]['status'] = DRUSH_UPDATESTATUS_REQUESTED_VERSION_NOT_CURRENT;
116 $update_info[$name]['candidate_version'] = $request['version'];
120 // Process locks specified on the command line.
121 $locked_list = drush_pm_update_lock($update_info, drush_get_option_list('lock'), drush_get_option_list('unlock'), drush_get_option('lock-message'));
123 // Build project updatable messages, set candidate version and mark
124 // 'updateable' in the project.
125 foreach ($update_info as $key => $project) {
126 switch($project['status']) {
127 case DRUSH_UPDATESTATUS_NOT_SECURE:
128 $status = dt('SECURITY UPDATE available');
129 pm_release_recommended($project);
131 case DRUSH_UPDATESTATUS_REVOKED:
132 $status = dt('Installed version REVOKED');
133 pm_release_recommended($project);
135 case DRUSH_UPDATESTATUS_NOT_SUPPORTED:
136 $status = dt('Installed version not supported');
137 pm_release_recommended($project);
139 case DRUSH_UPDATESTATUS_NOT_CURRENT:
140 $status = dt('Update available');
141 pm_release_recommended($project);
143 case DRUSH_UPDATESTATUS_CURRENT:
144 $status = dt('Up to date');
145 pm_release_recommended($project);
146 $project['updateable'] = FALSE;
148 case DRUSH_UPDATESTATUS_NOT_CHECKED:
149 case DRUSH_UPDATESTATUS_NOT_FETCHED:
150 case DRUSH_UPDATESTATUS_FETCH_PENDING:
151 $status = dt('Unable to check status');
153 case DRUSH_UPDATESTATUS_PROJECT_NOT_PACKAGED:
154 $status = $project['status_msg'];
156 case DRUSH_UPDATESTATUS_REQUESTED_PROJECT_NOT_UPDATEABLE:
157 $status = dt('Project has no enabled extensions and can\'t be updated');
159 case DRUSH_UPDATESTATUS_REQUESTED_PROJECT_NOT_FOUND:
160 $status = dt('Specified project not found');
162 case DRUSH_UPDATESTATUS_REQUESTED_VERSION_NOT_FOUND:
163 $status = dt('Specified version not found');
165 case DRUSH_UPDATESTATUS_REQUESTED_VERSION_CURRENT:
166 $status = dt('Specified version already installed');
168 case DRUSH_UPDATESTATUS_REQUESTED_VERSION_NOT_CURRENT:
169 $status = dt('Specified version available');
170 $project['updateable'] = TRUE;
173 $status = dt('Unknown');
177 if (isset($project['locked'])) {
178 $status = $project['locked'] . " ($status)";
180 // Persist candidate_version in $update_info (plural).
181 if (empty($project['candidate_version'])) {
182 $update_info[$key]['candidate_version'] = $project['existing_version']; // Default to no change
185 $update_info[$key]['candidate_version'] = $project['candidate_version'];
187 $update_info[$key]['status_msg'] = $status;
188 if (isset($project['updateable'])) {
189 $update_info[$key]['updateable'] = $project['updateable'];
193 // Filter projects to show.
194 return pm_project_filter($update_info, drush_get_option('security-only'));
198 * Filter projects based on verbosity level and $security_only flag.
200 * @param array $update_info
201 * Update info for projects.
202 * @param bool $security_only
203 * Whether to select only projects with security updates.
206 * Array of projects matching filter criteria.
208 function pm_project_filter($update_info, $security_only) {
210 foreach ($update_info as $key => $project) {
211 if ($security_only) {
212 if ($project['status'] == DRUSH_UPDATESTATUS_NOT_SECURE) {
213 $eligible[$key] = $project;
216 elseif (drush_get_context('DRUSH_VERBOSE')) {
217 $eligible[$key] = $project;
219 elseif ($project['status'] != DRUSH_UPDATESTATUS_CURRENT) {
220 $eligible[$key] = $project;
227 * Set a release to a recommended version (if available), and set as updateable.
229 function pm_release_recommended(&$project) {
230 if (isset($project['recommended'])) {
231 $project['candidate_version'] = $project['recommended'];
232 $project['updateable'] = TRUE;
234 // If installed version is dev and the candidate version is older, choose
235 // latest dev as candidate.
236 if (($project['install_type'] == 'dev') && isset($project['candidate_version'])) {
237 if ($project['releases'][$project['candidate_version']]['date'] < $project['datestamp']) {
238 $project['candidate_version'] = $project['latest_dev'];
239 if ($project['releases'][$project['candidate_version']]['date'] <= $project['datestamp']) {
240 $project['candidate_version'] = $project['existing_version'];
241 $project['updateable'] = FALSE;