| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @file 5 * Code required only when comparing available updates to existing data. 6 */ 7 8 /** 9 * Fetch an array of installed and enabled projects. 10 * 11 * This is only responsible for generating an array of projects (taking into 12 * account projects that include more than one module or theme). Other 13 * information like the specific version and install type (official release, 14 * dev snapshot, etc) is handled later in update_process_project_info() since 15 * that logic is only required when preparing the status report, not for 16 * fetching the available release data. 17 * 18 * This array is fairly expensive to construct, since it involves a lot of 19 * disk I/O, so we cache the results into the {cache_update} table using the 20 * 'update_project_projects' cache ID. However, since this is not the data 21 * about available updates fetched from the network, it is ok to invalidate it 22 * somewhat quickly. If we keep this data for very long, site administrators 23 * are more likely to see incorrect results if they upgrade to a newer version 24 * of a module or theme but do not visit certain pages that automatically 25 * clear this cache. 26 * 27 * @see update_process_project_info() 28 * @see update_calculate_project_data() 29 * @see update_project_cache() 30 */ 31 function update_get_projects() { 32 static $projects = array(); 33 if (empty($projects)) { 34 // Retrieve the projects from cache, if present. 35 $projects = update_project_cache('update_project_projects'); 36 if (empty($projects)) { 37 // Still empty, so we have to rebuild the cache. 38 _update_process_info_list($projects, module_rebuild_cache(), 'module'); 39 _update_process_info_list($projects, system_theme_data(), 'theme'); 40 // Allow other modules to alter projects before fetching and comparing. 41 drupal_alter('update_projects', $projects); 42 // Cache the site's project data for at most 1 hour. 43 _update_cache_set('update_project_projects', $projects, time() + 3600); 44 } 45 } 46 return $projects; 47 } 48 49 /** 50 * Populate an array of project data. 51 */ 52 function _update_process_info_list(&$projects, $list, $project_type) { 53 foreach ($list as $file) { 54 // A disabled base theme of an enabled sub-theme still has all of its code 55 // run by the sub-theme, so we include it in our "enabled" projects list. 56 if (!$file->status && !empty($file->sub_themes)) { 57 foreach ($file->sub_themes as $key => $name) { 58 // Build a list of enabled sub-themes. 59 if ($list[$key]->status) { 60 $file->enabled_sub_themes[$key] = $name; 61 } 62 } 63 // If there are no enabled subthemes, we should ingore this theme and go 64 // on to the next one. 65 if (empty($file->enabled_sub_themes)) { 66 continue; 67 } 68 } 69 elseif (empty($file->status)) { 70 // Skip disabled modules or themes. 71 continue; 72 } 73 74 // Skip if the .info file is broken. 75 if (empty($file->info)) { 76 continue; 77 } 78 79 // If the .info doesn't define the 'project', try to figure it out. 80 if (!isset($file->info['project'])) { 81 $file->info['project'] = update_get_project_name($file); 82 } 83 84 // If we still don't know the 'project', give up. 85 if (empty($file->info['project'])) { 86 continue; 87 } 88 89 // If we don't already know it, grab the change time on the .info file 90 // itself. Note: we need to use the ctime, not the mtime (modification 91 // time) since many (all?) tar implementations will go out of their way to 92 // set the mtime on the files it creates to the timestamps recorded in the 93 // tarball. We want to see the last time the file was changed on disk, 94 // which is left alone by tar and correctly set to the time the .info file 95 // was unpacked. 96 if (!isset($file->info['_info_file_ctime'])) { 97 $info_filename = dirname($file->filename) .'/'. $file->name .'.info'; 98 $file->info['_info_file_ctime'] = filectime($info_filename); 99 } 100 101 if (!isset($file->info['datestamp'])) { 102 $file->info['datestamp'] = 0; 103 } 104 105 $project_name = $file->info['project']; 106 107 // Add a list of sub-themes that "depend on" the project and a list of base 108 // themes that are "required by" the project. 109 if ($project_name == 'drupal') { 110 // Drupal core is always required, so this extra info would be noise. 111 $sub_themes = array(); 112 $base_themes = array(); 113 } 114 else { 115 // Add list of enabled sub-themes. 116 $sub_themes = !empty($file->enabled_sub_themes) ? $file->enabled_sub_themes : array(); 117 // Add list of base themes. 118 $base_themes = !empty($file->base_themes) ? $file->base_themes : array(); 119 } 120 121 if (!isset($projects[$project_name])) { 122 // Only process this if we haven't done this project, since a single 123 // project can have multiple modules or themes. 124 $projects[$project_name] = array( 125 'name' => $project_name, 126 // Only save attributes from the .info file we care about so we do not 127 // bloat our RAM usage needlessly. 128 'info' => update_filter_project_info($file->info), 129 'datestamp' => $file->info['datestamp'], 130 'includes' => array($file->name => $file->info['name']), 131 'project_type' => $project_name == 'drupal' ? 'core' : $project_type, 132 'sub_themes' => $sub_themes, 133 'base_themes' => $base_themes, 134 ); 135 } 136 else { 137 $projects[$project_name]['includes'][$file->name] = $file->info['name']; 138 $projects[$project_name]['info']['_info_file_ctime'] = max($projects[$project_name]['info']['_info_file_ctime'], $file->info['_info_file_ctime']); 139 $projects[$project_name]['datestamp'] = max($projects[$project_name]['datestamp'], $file->info['datestamp']); 140 $projects[$project_name]['sub_themes'] = array_merge($projects[$project_name]['sub_themes'], $sub_themes); 141 $projects[$project_name]['base_themes'] = array_merge($projects[$project_name]['base_themes'], $base_themes); 142 } 143 } 144 } 145 146 /** 147 * Given a $file object (as returned by system_get_files_database()), figure 148 * out what project it belongs to. 149 * 150 * @see system_get_files_database() 151 */ 152 function update_get_project_name($file) { 153 $project_name = ''; 154 if (isset($file->info['project'])) { 155 $project_name = $file->info['project']; 156 } 157 elseif (isset($file->info['package']) && (strpos($file->info['package'], 'Core -') !== FALSE)) { 158 $project_name = 'drupal'; 159 } 160 elseif (in_array($file->name, array('bluemarine', 'chameleon', 'garland', 'marvin', 'minnelli', 'pushbutton'))) { 161 // Unfortunately, there's no way to tell if a theme is part of core, 162 // so we must hard-code a list here. 163 $project_name = 'drupal'; 164 } 165 return $project_name; 166 } 167 168 /** 169 * Process the list of projects on the system to figure out the currently 170 * installed versions, and other information that is required before we can 171 * compare against the available releases to produce the status report. 172 * 173 * @param $projects 174 * Array of project information from update_get_projects(). 175 */ 176 function update_process_project_info(&$projects) { 177 foreach ($projects as $key => $project) { 178 // Assume an official release until we see otherwise. 179 $install_type = 'official'; 180 181 $info = $project['info']; 182 183 if (isset($info['version'])) { 184 // Check for development snapshots 185 if (preg_match('@(dev|HEAD)@', $info['version'])) { 186 $install_type = 'dev'; 187 } 188 189 // Figure out what the currently installed major version is. We need 190 // to handle both contribution (e.g. "5.x-1.3", major = 1) and core 191 // (e.g. "5.1", major = 5) version strings. 192 $matches = array(); 193 if (preg_match('/^(\d+\.x-)?(\d+)\..*$/', $info['version'], $matches)) { 194 $info['major'] = $matches[2]; 195 } 196 elseif (!isset($info['major'])) { 197 // This would only happen for version strings that don't follow the 198 // drupal.org convention. We let contribs define "major" in their 199 // .info in this case, and only if that's missing would we hit this. 200 $info['major'] = -1; 201 } 202 } 203 else { 204 // No version info available at all. 205 $install_type = 'unknown'; 206 $info['version'] = t('Unknown'); 207 $info['major'] = -1; 208 } 209 210 // Finally, save the results we care about into the $projects array. 211 $projects[$key]['existing_version'] = $info['version']; 212 $projects[$key]['existing_major'] = $info['major']; 213 $projects[$key]['install_type'] = $install_type; 214 } 215 } 216 217 /** 218 * Given the installed projects and the available release data retrieved from 219 * remote servers, calculate the current status. 220 * 221 * This function is the heart of the update status feature. It iterates over 222 * every currently installed project. For each one, it first checks if the 223 * project has been flagged with a special status like "unsupported" or 224 * "insecure", or if the project node itself has been unpublished. In any of 225 * those cases, the project is marked with an error and the next project is 226 * considered. 227 * 228 * If the project itself is valid, the function decides what major release 229 * series to consider. The project defines what the currently supported major 230 * versions are for each version of core, so the first step is to make sure 231 * the current version is still supported. If so, that's the target version. 232 * If the current version is unsupported, the project maintainer's recommended 233 * major version is used. There's also a check to make sure that this function 234 * never recommends an earlier release than the currently installed major 235 * version. 236 * 237 * Given a target major version, it scans the available releases looking for 238 * the specific release to recommend (avoiding beta releases and development 239 * snapshots if possible). This is complicated to describe, but an example 240 * will help clarify. For the target major version, find the highest patch 241 * level. If there is a release at that patch level with no extra ("beta", 242 * etc), then we recommend the release at that patch level with the most 243 * recent release date. If every release at that patch level has extra (only 244 * betas), then recommend the latest release from the previous patch 245 * level. For example: 246 * 247 * 1.6-bugfix <-- recommended version because 1.6 already exists. 248 * 1.6 249 * 250 * or 251 * 252 * 1.6-beta 253 * 1.5 <-- recommended version because no 1.6 exists. 254 * 1.4 255 * 256 * It also looks for the latest release from the same major version, even a 257 * beta release, to display to the user as the "Latest version" option. 258 * Additionally, it finds the latest official release from any higher major 259 * versions that have been released to provide a set of "Also available" 260 * options. 261 * 262 * Finally, and most importantly, it keeps scanning the release history until 263 * it gets to the currently installed release, searching for anything marked 264 * as a security update. If any security updates have been found between the 265 * recommended release and the installed version, all of the releases that 266 * included a security fix are recorded so that the site administrator can be 267 * warned their site is insecure, and links pointing to the release notes for 268 * each security update can be included (which, in turn, will link to the 269 * official security announcements for each vulnerability). 270 * 271 * This function relies on the fact that the .xml release history data comes 272 * sorted based on major version and patch level, then finally by release date 273 * if there are multiple releases such as betas from the same major.patch 274 * version (e.g. 5.x-1.5-beta1, 5.x-1.5-beta2, and 5.x-1.5). Development 275 * snapshots for a given major version are always listed last. 276 * 277 * The results of this function are expensive to compute, especially on sites 278 * with lots of modules or themes, since it involves a lot of comparisons and 279 * other operations. Therefore, we cache the results into the {cache_update} 280 * table using the 'update_project_data' cache ID. However, since this is not 281 * the data about available updates fetched from the network, it is ok to 282 * invalidate it somewhat quickly. If we keep this data for very long, site 283 * administrators are more likely to see incorrect results if they upgrade to 284 * a newer version of a module or theme but do not visit certain pages that 285 * automatically clear this cache. 286 * 287 * @param $available 288 * Array of data about available project releases. 289 * 290 * @see update_get_available() 291 * @see update_get_projects() 292 * @see update_process_project_info() 293 * @see update_project_cache() 294 */ 295 function update_calculate_project_data($available) { 296 // Retrieve the projects from cache, if present. 297 $projects = update_project_cache('update_project_data'); 298 // If $projects is empty, then the cache must be rebuilt. 299 // Otherwise, return the cached data and skip the rest of the function. 300 if (!empty($projects)) { 301 return $projects; 302 } 303 $projects = update_get_projects(); 304 update_process_project_info($projects); 305 foreach ($projects as $project => $project_info) { 306 if (isset($available[$project])) { 307 308 // If the project status is marked as something bad, there's nothing 309 // else to consider. 310 if (isset($available[$project]['project_status'])) { 311 switch ($available[$project]['project_status']) { 312 case 'insecure': 313 $projects[$project]['status'] = UPDATE_NOT_SECURE; 314 if (empty($projects[$project]['extra'])) { 315 $projects[$project]['extra'] = array(); 316 } 317 $projects[$project]['extra'][] = array( 318 'class' => 'project-not-secure', 319 'label' => t('Project not secure'), 320 'data' => t('This project has been labeled insecure by the Drupal security team, and is no longer available for download. Immediately disabling everything included by this project is strongly recommended!'), 321 ); 322 break; 323 case 'unpublished': 324 case 'revoked': 325 $projects[$project]['status'] = UPDATE_REVOKED; 326 if (empty($projects[$project]['extra'])) { 327 $projects[$project]['extra'] = array(); 328 } 329 $projects[$project]['extra'][] = array( 330 'class' => 'project-revoked', 331 'label' => t('Project revoked'), 332 'data' => t('This project has been revoked, and is no longer available for download. Disabling everything included by this project is strongly recommended!'), 333 ); 334 break; 335 case 'unsupported': 336 $projects[$project]['status'] = UPDATE_NOT_SUPPORTED; 337 if (empty($projects[$project]['extra'])) { 338 $projects[$project]['extra'] = array(); 339 } 340 $projects[$project]['extra'][] = array( 341 'class' => 'project-not-supported', 342 'label' => t('Project not supported'), 343 'data' => t('This project is no longer supported, and is no longer available for download. Disabling everything included by this project is strongly recommended!'), 344 ); 345 break; 346 case 'not-fetched': 347 $projects[$project]['status'] = UPDATE_NOT_FETCHED; 348 $projects[$project]['reason'] = t('Failed to fetch available update data'); 349 break; 350 351 default: 352 // Assume anything else (e.g. 'published') is valid and we should 353 // perform the rest of the logic in this function. 354 break; 355 } 356 } 357 358 if (!empty($projects[$project]['status'])) { 359 // We already know the status for this project, so there's nothing 360 // else to compute. Just record everything else we fetched from the 361 // XML file into our projects array and move to the next project. 362 $projects[$project] += $available[$project]; 363 continue; 364 } 365 366 // Figure out the target major version. 367 $existing_major = $project_info['existing_major']; 368 $supported_majors = array(); 369 if (isset($available[$project]['supported_majors'])) { 370 $supported_majors = explode(',', $available[$project]['supported_majors']); 371 } 372 elseif (isset($available[$project]['default_major'])) { 373 // Older release history XML file without supported or recommended. 374 $supported_majors[] = $available[$project]['default_major']; 375 } 376 377 if (in_array($existing_major, $supported_majors)) { 378 // Still supported, stay at the current major version. 379 $target_major = $existing_major; 380 } 381 elseif (isset($available[$project]['recommended_major'])) { 382 // Since 'recommended_major' is defined, we know this is the new XML 383 // format. Therefore, we know the current release is unsupported since 384 // its major version was not in the 'supported_majors' list. We should 385 // find the best release from the recommended major version. 386 $target_major = $available[$project]['recommended_major']; 387 $projects[$project]['status'] = UPDATE_NOT_SUPPORTED; 388 } 389 elseif (isset($available[$project]['default_major'])) { 390 // Older release history XML file without recommended, so recommend 391 // the currently defined "default_major" version. 392 $target_major = $available[$project]['default_major']; 393 } 394 else { 395 // Malformed XML file? Stick with the current version. 396 $target_major = $existing_major; 397 } 398 399 // Make sure we never tell the admin to downgrade. If we recommended an 400 // earlier version than the one they're running, they'd face an 401 // impossible data migration problem, since Drupal never supports a DB 402 // downgrade path. In the unfortunate case that what they're running is 403 // unsupported, and there's nothing newer for them to upgrade to, we 404 // can't print out a "Recommended version", but just have to tell them 405 // what they have is unsupported and let them figure it out. 406 $target_major = max($existing_major, $target_major); 407 408 $version_patch_changed = ''; 409 $patch = ''; 410 411 // Defend ourselves from XML history files that contain no releases. 412 if (empty($available[$project]['releases'])) { 413 $projects[$project]['status'] = UPDATE_UNKNOWN; 414 $projects[$project]['reason'] = t('No available releases found'); 415 continue; 416 } 417 foreach ($available[$project]['releases'] as $version => $release) { 418 // First, if this is the existing release, check a few conditions. 419 if ($projects[$project]['existing_version'] === $version) { 420 if (isset($release['terms']['Release type']) && 421 in_array('Insecure', $release['terms']['Release type'])) { 422 $projects[$project]['status'] = UPDATE_NOT_SECURE; 423 } 424 elseif ($release['status'] == 'unpublished') { 425 $projects[$project]['status'] = UPDATE_REVOKED; 426 if (empty($projects[$project]['extra'])) { 427 $projects[$project]['extra'] = array(); 428 } 429 $projects[$project]['extra'][] = array( 430 'class' => 'release-revoked', 431 'label' => t('Release revoked'), 432 'data' => t('Your currently installed release has been revoked, and is no longer available for download. Disabling everything included in this release or upgrading is strongly recommended!'), 433 ); 434 } 435 elseif (isset($release['terms']['Release type']) && 436 in_array('Unsupported', $release['terms']['Release type'])) { 437 $projects[$project]['status'] = UPDATE_NOT_SUPPORTED; 438 if (empty($projects[$project]['extra'])) { 439 $projects[$project]['extra'] = array(); 440 } 441 $projects[$project]['extra'][] = array( 442 'class' => 'release-not-supported', 443 'label' => t('Release not supported'), 444 'data' => t('Your currently installed release is now unsupported, and is no longer available for download. Disabling everything included in this release or upgrading is strongly recommended!'), 445 ); 446 } 447 } 448 449 // Otherwise, ignore unpublished, insecure, or unsupported releases. 450 if ($release['status'] == 'unpublished' || 451 (isset($release['terms']['Release type']) && 452 (in_array('Insecure', $release['terms']['Release type']) || 453 in_array('Unsupported', $release['terms']['Release type'])))) { 454 continue; 455 } 456 457 // See if this is a higher major version than our target and yet still 458 // supported. If so, record it as an "Also available" release. 459 if ($release['version_major'] > $target_major) { 460 if (in_array($release['version_major'], $supported_majors)) { 461 if (!isset($available[$project]['also'])) { 462 $available[$project]['also'] = array(); 463 } 464 if (!isset($available[$project]['also'][$release['version_major']])) { 465 $available[$project]['also'][$release['version_major']] = $version; 466 } 467 } 468 // Otherwise, this release can't matter to us, since it's neither 469 // from the release series we're currently using nor the recommended 470 // release. We don't even care about security updates for this 471 // branch, since if a project maintainer puts out a security release 472 // at a higher major version and not at the lower major version, 473 // they must remove the lower version from the supported major 474 // versions at the same time, in which case we won't hit this code. 475 continue; 476 } 477 478 // Look for the 'latest version' if we haven't found it yet. Latest is 479 // defined as the most recent version for the target major version. 480 if (!isset($available[$project]['latest_version']) 481 && $release['version_major'] == $target_major) { 482 $available[$project]['latest_version'] = $version; 483 } 484 485 // Look for the development snapshot release for this branch. 486 if (!isset($available[$project]['dev_version']) 487 && $release['version_major'] == $target_major 488 && isset($release['version_extra']) 489 && $release['version_extra'] == 'dev') { 490 $available[$project]['dev_version'] = $version; 491 } 492 493 // Look for the 'recommended' version if we haven't found it yet (see 494 // phpdoc at the top of this function for the definition). 495 if (!isset($available[$project]['recommended']) 496 && $release['version_major'] == $target_major 497 && isset($release['version_patch'])) { 498 if ($patch != $release['version_patch']) { 499 $patch = $release['version_patch']; 500 $version_patch_changed = $release['version']; 501 } 502 if (empty($release['version_extra']) && $patch == $release['version_patch']) { 503 $available[$project]['recommended'] = $version_patch_changed; 504 } 505 } 506 507 // Stop searching once we hit the currently installed version. 508 if ($projects[$project]['existing_version'] === $version) { 509 break; 510 } 511 512 // If we're running a dev snapshot and have a timestamp, stop 513 // searching for security updates once we hit an official release 514 // older than what we've got. Allow 100 seconds of leeway to handle 515 // differences between the datestamp in the .info file and the 516 // timestamp of the tarball itself (which are usually off by 1 or 2 517 // seconds) so that we don't flag that as a new release. 518 if ($projects[$project]['install_type'] == 'dev') { 519 if (empty($projects[$project]['datestamp'])) { 520 // We don't have current timestamp info, so we can't know. 521 continue; 522 } 523 elseif (isset($release['date']) && ($projects[$project]['datestamp'] + 100 > $release['date'])) { 524 // We're newer than this, so we can skip it. 525 continue; 526 } 527 } 528 529 // See if this release is a security update. 530 if (isset($release['terms']['Release type']) 531 && in_array('Security update', $release['terms']['Release type'])) { 532 $projects[$project]['security updates'][] = $release; 533 } 534 } 535 536 // If we were unable to find a recommended version, then make the latest 537 // version the recommended version if possible. 538 if (!isset($available[$project]['recommended']) && isset($available[$project]['latest_version'])) { 539 $available[$project]['recommended'] = $available[$project]['latest_version']; 540 } 541 542 // Stash the info about available releases into our $projects array. 543 $projects[$project] += $available[$project]; 544 545 // 546 // Check to see if we need an update or not. 547 // 548 549 if (!empty($projects[$project]['security updates'])) { 550 // If we found security updates, that always trumps any other status. 551 $projects[$project]['status'] = UPDATE_NOT_SECURE; 552 } 553 554 if (isset($projects[$project]['status'])) { 555 // If we already know the status, we're done. 556 continue; 557 } 558 559 // If we don't know what to recommend, there's nothing we can report. 560 // Bail out early. 561 if (!isset($projects[$project]['recommended'])) { 562 $projects[$project]['status'] = UPDATE_UNKNOWN; 563 $projects[$project]['reason'] = t('No available releases found'); 564 continue; 565 } 566 567 // If we're running a dev snapshot, compare the date of the dev snapshot 568 // with the latest official version, and record the absolute latest in 569 // 'latest_dev' so we can correctly decide if there's a newer release 570 // than our current snapshot. 571 if ($projects[$project]['install_type'] == 'dev') { 572 if (isset($available[$project]['dev_version']) && $available[$project]['releases'][$available[$project]['dev_version']]['date'] > $available[$project]['releases'][$available[$project]['latest_version']]['date']) { 573 $projects[$project]['latest_dev'] = $available[$project]['dev_version']; 574 } 575 else { 576 $projects[$project]['latest_dev'] = $available[$project]['latest_version']; 577 } 578 } 579 580 // Figure out the status, based on what we've seen and the install type. 581 switch ($projects[$project]['install_type']) { 582 case 'official': 583 if ($projects[$project]['existing_version'] === $projects[$project]['recommended'] || $projects[$project]['existing_version'] === $projects[$project]['latest_version']) { 584 $projects[$project]['status'] = UPDATE_CURRENT; 585 } 586 else { 587 $projects[$project]['status'] = UPDATE_NOT_CURRENT; 588 } 589 break; 590 591 case 'dev': 592 $latest = $available[$project]['releases'][$projects[$project]['latest_dev']]; 593 if (empty($projects[$project]['datestamp'])) { 594 $projects[$project]['status'] = UPDATE_NOT_CHECKED; 595 $projects[$project]['reason'] = t('Unknown release date'); 596 } 597 elseif (($projects[$project]['datestamp'] + 100 > $latest['date'])) { 598 $projects[$project]['status'] = UPDATE_CURRENT; 599 } 600 else { 601 $projects[$project]['status'] = UPDATE_NOT_CURRENT; 602 } 603 break; 604 605 default: 606 $projects[$project]['status'] = UPDATE_UNKNOWN; 607 $projects[$project]['reason'] = t('Invalid info'); 608 } 609 } 610 else { 611 $projects[$project]['status'] = UPDATE_UNKNOWN; 612 $projects[$project]['reason'] = t('No available releases found'); 613 } 614 } 615 // Give other modules a chance to alter the status (for example, to allow a 616 // contrib module to provide fine-grained settings to ignore specific 617 // projects or releases). 618 drupal_alter('update_status', $projects); 619 620 // Cache the site's update status for at most 1 hour. 621 _update_cache_set('update_project_data', $projects, time() + 3600); 622 return $projects; 623 } 624 625 /** 626 * Retrieve data from {cache_update} or empty the cache when necessary. 627 * 628 * Two very expensive arrays computed by this module are the list of all 629 * installed modules and themes (and .info data, project associations, etc), 630 * and the current status of the site relative to the currently available 631 * releases. These two arrays are cached in the {cache_update} table and used 632 * whenever possible. The cache is cleared whenever the administrator visits 633 * the status report, available updates report, or the module or theme 634 * administration pages, since we should always recompute the most current 635 * values on any of those pages. 636 * 637 * Note: while both of these arrays are expensive to compute (in terms of disk 638 * I/O and some fairly heavy CPU processing), neither of these is the actual 639 * data about available updates that we have to fetch over the network from 640 * updates.drupal.org. That information is stored with the 641 * 'update_available_releases' cache ID -- it needs to persist longer than 1 642 * hour and never get invalidated just by visiting a page on the site. 643 * 644 * @param $cid 645 * The cache id of data to return from the cache. Valid options are 646 * 'update_project_data' and 'update_project_projects'. 647 * 648 * @return 649 * The cached value of the $projects array generated by 650 * update_calculate_project_data() or update_get_projects(), or an empty 651 * array when the cache is cleared. 652 */ 653 function update_project_cache($cid) { 654 $projects = array(); 655 656 // On certain paths, we should clear the cache and recompute the projects or 657 // update status of the site to avoid presenting stale information. 658 $q = $_GET['q']; 659 $paths = array('admin/build/modules', 'admin/build/themes', 'admin/reports', 'admin/reports/updates', 'admin/reports/status', 'admin/reports/updates/check'); 660 if (in_array($q, $paths)) { 661 _update_cache_clear($cid); 662 } 663 else { 664 $cache = _update_cache_get($cid); 665 if (!empty($cache->data) && $cache->expire > time()) { 666 $projects = $cache->data; 667 } 668 } 669 return $projects; 670 } 671 672 /** 673 * Filter the project .info data to only save attributes we need. 674 * 675 * @param array $info 676 * Array of .info file data as returned by drupal_parse_info_file(). 677 * 678 * @return 679 * Array of .info file data we need for the Update manager. 680 * 681 * @see _update_process_info_list() 682 */ 683 function update_filter_project_info($info) { 684 $whitelist = array( 685 '_info_file_ctime', 686 'datestamp', 687 'major', 688 'name', 689 'package', 690 'project', 691 'project status url', 692 'version', 693 ); 694 $whitelist = array_flip($whitelist); 695 foreach ($info as $key => $value) { 696 if (!isset($whitelist[$key])) { 697 unset($info[$key]); 698 } 699 } 700 return $info; 701 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |