2007-07-11 15:15:40 +00:00
< ? php
/**
* @ file
* Code required only when comparing available updates to existing data .
*/
Issue #3041885 by tedbow, beautifulmind, dww, ayushmishra206, phenaproxima, webchick, xjm, AaronMcHale, larowlan, benjifisher, heddn, catch, jhodgdon, longwave, mglaman, alexpott, mxr576, effulgentsia: Display relevant Security Advisories data for Drupal
2021-05-12 06:40:17 +00:00
use Drupal\Core\Extension\ExtensionVersion ;
Issue #2932518 by kim.pepper, joachim, bradjones1, voleger, cliddell, gapple, Xano, andregp, andypost, neclimdul, rpayanm, Hardik_Patel_12, NWOM, smustgrave, dawehner, alexpott, daffie, larowlan, Berdir, mstrelan, xjm, dagmar: Deprecate watchdog_exception
2023-04-28 03:36:57 +00:00
use Drupal\Core\Utility\Error ;
2021-06-23 03:51:34 +00:00
use Drupal\update\ProjectRelease ;
2019-12-04 11:57:25 +00:00
use Drupal\update\UpdateFetcherInterface ;
use Drupal\update\UpdateManagerInterface ;
2019-12-12 20:20:47 +00:00
use Drupal\update\ProjectCoreCompatibility ;
2019-12-04 11:57:25 +00:00
2007-07-11 15:15:40 +00:00
/**
2012-06-06 15:33:53 +00:00
* Determines version and type information for currently installed projects .
*
* Processes the list of projects on the system to figure out the currently
2007-07-11 15:15:40 +00:00
* installed versions , and other information that is required before we can
* compare against the available releases to produce the status report .
*
* @ param $projects
2015-05-04 10:52:57 +00:00
* Array of project information from
2019-12-11 09:53:53 +00:00
* \Drupal\update\UpdateManager :: getProjects () .
2007-07-11 15:15:40 +00:00
*/
function update_process_project_info ( & $projects ) {
foreach ( $projects as $key => $project ) {
// Assume an official release until we see otherwise.
$install_type = 'official' ;
$info = $project [ 'info' ];
if ( isset ( $info [ 'version' ])) {
// Check for development snapshots
if ( preg_match ( '@(dev|HEAD)@' , $info [ 'version' ])) {
$install_type = 'dev' ;
}
// Figure out what the currently installed major version is. We need
// to handle both contribution (e.g. "5.x-1.3", major = 1) and core
// (e.g. "5.1", major = 5) version strings.
2017-03-04 01:20:24 +00:00
$matches = [];
2007-07-11 15:15:40 +00:00
if ( preg_match ( '/^(\d+\.x-)?(\d+)\..*$/' , $info [ 'version' ], $matches )) {
$info [ 'major' ] = $matches [ 2 ];
}
2020-12-23 10:46:13 +00:00
else {
2007-07-11 15:15:40 +00:00
// This would only happen for version strings that don't follow the
2020-12-23 10:46:13 +00:00
// drupal.org convention.
2007-07-11 15:15:40 +00:00
$info [ 'major' ] = - 1 ;
}
}
else {
// No version info available at all.
$install_type = 'unknown' ;
$info [ 'version' ] = t ( 'Unknown' );
$info [ 'major' ] = - 1 ;
}
// Finally, save the results we care about into the $projects array.
$projects [ $key ][ 'existing_version' ] = $info [ 'version' ];
$projects [ $key ][ 'existing_major' ] = $info [ 'major' ];
$projects [ $key ][ 'install_type' ] = $install_type ;
}
}
/**
2012-06-06 15:33:53 +00:00
* Calculates the current update status of all projects on the site .
2007-07-11 15:15:40 +00:00
*
2009-12-29 06:53:04 +00:00
* The results of this function are expensive to compute , especially on sites
* with lots of modules or themes , since it involves a lot of comparisons and
2013-03-20 11:51:03 +00:00
* other operations . Therefore , we store the results . However , since this is not
2009-12-29 06:53:04 +00:00
* the data about available updates fetched from the network , it is ok to
* invalidate it somewhat quickly . If we keep this data for very long , site
2012-06-06 15:33:53 +00:00
* administrators are more likely to see incorrect results if they upgrade to a
* newer version of a module or theme but do not visit certain pages that
2013-03-20 11:51:03 +00:00
* automatically clear this .
2009-12-29 06:53:04 +00:00
*
* @ param array $available
* Data about available project releases .
*
Issue #2941148 by quietone, bruno.bicudo, ravi.shankar, Sweetchuck, beatrizrodrigues, lucienchalom, VitaliyB98, WagnerMelo, sophiavs, ankitjain28may, daffie, longwave, Sutharsan, borisson_, cosmicdreams, heykarthikwithu, catch: Fix Drupal.Commenting.FunctionComment.MissingReturnType
2022-09-27 09:58:26 +00:00
* @ return array
2012-06-06 15:33:53 +00:00
* An array of installed projects with current update status information .
*
2009-12-29 06:53:04 +00:00
* @ see update_get_available ()
2019-12-11 09:53:53 +00:00
* @ see \Drupal\update\UpdateManager :: getProjects ()
2009-12-29 06:53:04 +00:00
* @ see update_process_project_info ()
2015-04-07 07:03:23 +00:00
* @ see \Drupal\update\UpdateManagerInterface :: projectStorage ()
2020-01-20 13:44:58 +00:00
* @ see \Drupal\update\ProjectCoreCompatibility :: setReleaseMessage ()
2009-12-29 06:53:04 +00:00
*/
function update_calculate_project_data ( $available ) {
2013-03-20 11:51:03 +00:00
// Retrieve the projects from storage, if present.
2015-04-07 07:03:23 +00:00
$projects = \Drupal :: service ( 'update.manager' ) -> projectStorage ( 'update_project_data' );
2013-03-20 11:51:03 +00:00
// If $projects is empty, then the data must be rebuilt.
// Otherwise, return the data and skip the rest of the function.
2009-12-29 06:53:04 +00:00
if ( ! empty ( $projects )) {
return $projects ;
}
2015-05-04 10:52:57 +00:00
$projects = \Drupal :: service ( 'update.manager' ) -> getProjects ();
2009-12-29 06:53:04 +00:00
update_process_project_info ( $projects );
2019-12-12 20:20:47 +00:00
if ( isset ( $projects [ 'drupal' ]) && ! empty ( $available [ 'drupal' ])) {
// Calculate core status first so that it is complete before
// \Drupal\update\ProjectCoreCompatibility::setReleaseMessage() is called
// for each module below.
update_calculate_project_update_status ( $projects [ 'drupal' ], $available [ 'drupal' ]);
2024-04-17 13:55:49 +00:00
if ( isset ( $available [ 'drupal' ][ 'releases' ]) && ! empty ( $available [ 'drupal' ][ 'supported_branches' ])) {
$supported_branches = explode ( ',' , $available [ 'drupal' ][ 'supported_branches' ]);
$project_core_compatibility = new ProjectCoreCompatibility ( $projects [ 'drupal' ], $available [ 'drupal' ][ 'releases' ], $supported_branches );
2019-12-12 20:20:47 +00:00
}
}
2009-12-29 06:53:04 +00:00
foreach ( $projects as $project => $project_info ) {
if ( isset ( $available [ $project ])) {
2019-12-12 20:20:47 +00:00
if ( $project === 'drupal' ) {
continue ;
}
2012-04-02 03:28:37 +00:00
update_calculate_project_update_status ( $projects [ $project ], $available [ $project ]);
2020-01-20 13:44:58 +00:00
// Inject the list of compatible core versions to show administrator(s)
// which versions of core a given available update can be installed with.
// Since individual releases of a project can be compatible with different
// versions of core, and even multiple major versions of core (for
// example, 8.9.x and 9.0.x), this list will hopefully help
// administrator(s) know which available updates they can upgrade a given
// project to.
2019-12-12 20:20:47 +00:00
if ( isset ( $project_core_compatibility )) {
$project_core_compatibility -> setReleaseMessage ( $projects [ $project ]);
}
2009-12-29 06:53:04 +00:00
}
else {
2019-12-04 11:57:25 +00:00
$projects [ $project ][ 'status' ] = UpdateFetcherInterface :: UNKNOWN ;
2009-12-29 06:53:04 +00:00
$projects [ $project ][ 'reason' ] = t ( 'No available releases found' );
}
}
// Give other modules a chance to alter the status (for example, to allow a
// contrib module to provide fine-grained settings to ignore specific
// projects or releases).
2014-02-24 10:10:52 +00:00
\Drupal :: moduleHandler () -> alter ( 'update_status' , $projects );
2009-12-29 06:53:04 +00:00
2013-03-20 11:51:03 +00:00
// Store the site's update status for at most 1 hour.
2013-09-16 03:58:06 +00:00
\Drupal :: keyValueExpirable ( 'update' ) -> setWithExpire ( 'update_project_data' , $projects , 3600 );
2009-12-29 06:53:04 +00:00
return $projects ;
}
/**
2012-06-06 15:33:53 +00:00
* Calculates the current update status of a specific project .
2009-12-29 06:53:04 +00:00
*
2012-06-06 15:33:53 +00:00
* This function is the heart of the update status feature . For each project it
* is invoked with , it first checks if the project has been flagged with a
2009-12-29 06:53:04 +00:00
* special status like " unsupported " or " insecure " , or if the project node
* itself has been unpublished . In any of those cases , the project is marked
* with an error and the next project is considered .
2008-01-10 14:14:54 +00:00
*
* If the project itself is valid , the function decides what major release
2020-01-23 21:28:49 +00:00
* series to consider . The project defines its currently supported branches in
* its Drupal . org for the project , so the first step is to make sure the
* development branch of the current version is still supported . If so , then the
* major version of the current version is used . If the current version is not
* in a supported branch , the next supported branch is used to determine the
* major version to use . There ' s also a check to make sure that this function
* never recommends an earlier release than the currently installed major
* version .
2012-06-06 15:33:53 +00:00
*
* Given a target major version , the available releases are scanned looking for
2007-07-11 15:15:40 +00:00
* the specific release to recommend ( avoiding beta releases and development
2012-06-06 15:33:53 +00:00
* snapshots if possible ) . For the target major version , the highest patch level
* is found . If there is a release at that patch level with no extra ( " beta " ,
* etc . ), then the release at that patch level with the most recent release date
* is recommended . If every release at that patch level has extra ( only betas ),
* then the latest release from the previous patch level is recommended . For
* example :
2007-07-11 15:15:40 +00:00
*
2012-06-06 15:33:53 +00:00
* - 1.6 - bugfix <-- recommended version because 1.6 already exists .
* - 1.6
2007-07-11 15:15:40 +00:00
*
* or
*
2012-06-06 15:33:53 +00:00
* - 1.6 - beta
* - 1.5 <-- recommended version because no 1.6 exists .
* - 1.4
2007-07-11 15:15:40 +00:00
*
2012-06-06 15:33:53 +00:00
* Also , the latest release from the same major version is looked for , even beta
* releases , to display to the user as the " Latest version " option .
* Additionally , the latest official release from any higher major versions that
* have been released is searched for to provide a set of " Also available "
2007-07-11 15:15:40 +00:00
* options .
*
2012-06-06 15:33:53 +00:00
* Finally , and most importantly , the release history continues to be scanned
* until the currently installed release is reached , searching for anything
* marked as a security update . If any security updates have been found between
* the recommended release and the installed version , all of the releases that
2007-07-11 15:15:40 +00:00
* included a security fix are recorded so that the site administrator can be
* warned their site is insecure , and links pointing to the release notes for
* each security update can be included ( which , in turn , will link to the
* official security announcements for each vulnerability ) .
*
* This function relies on the fact that the . xml release history data comes
* sorted based on major version and patch level , then finally by release date
* if there are multiple releases such as betas from the same major . patch
2012-06-06 15:33:53 +00:00
* version ( e . g . , 5. x - 1.5 - beta1 , 5. x - 1.5 - beta2 , and 5. x - 1.5 ) . Development
2007-07-11 15:15:40 +00:00
* snapshots for a given major version are always listed last .
*
Issue #3118087 by dww, JoshaHubbers, jungle, tedbow, RajabNatshah, Kingdutch, JonMcL, xjm, Nick Hope, wroehrig, wxman, broeker, mlozano7, kazajhodo, suit4, xmacinfo, BrightBold: If any extension has a missing or invalid version, Update manager throws errors and is confused about site update status
2020-03-19 21:34:25 +00:00
* NOTE : This function * must * set a value for $project_data [ 'status' ] before
* returning , or the rest of the Update Manager will break in unexpected ways .
*
2012-06-06 15:33:53 +00:00
* @ param $project_data
* An array containing information about a specific project .
* @ param $available
* Data about available project releases of a specific project .
2007-07-11 15:15:40 +00:00
*/
2012-04-02 03:28:37 +00:00
function update_calculate_project_update_status ( & $project_data , $available ) {
2017-03-04 01:20:24 +00:00
foreach ([ 'title' , 'link' ] as $attribute ) {
2009-12-29 06:53:04 +00:00
if ( ! isset ( $project_data [ $attribute ]) && isset ( $available [ $attribute ])) {
$project_data [ $attribute ] = $available [ $attribute ];
}
2008-01-27 17:50:10 +00:00
}
2008-01-10 14:14:54 +00:00
2009-12-29 06:53:04 +00:00
// If the project status is marked as something bad, there's nothing else
// to consider.
if ( isset ( $available [ 'project_status' ])) {
switch ( $available [ 'project_status' ]) {
case 'insecure' :
2019-12-12 08:24:15 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: NOT_SECURE ;
2009-12-29 06:53:04 +00:00
if ( empty ( $project_data [ 'extra' ])) {
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ] = [];
2008-01-10 14:14:54 +00:00
}
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ][] = [
2009-12-29 06:53:04 +00:00
'label' => t ( 'Project not secure' ),
2024-01-11 13:24:56 +00:00
'data' => t ( 'This project has been labeled insecure by the Drupal security team, and is no longer available for download. Immediately uninstalling everything included by this project is strongly recommended!' ),
2017-03-04 01:20:24 +00:00
];
2009-12-29 06:53:04 +00:00
break ;
2020-06-02 08:46:52 +00:00
2009-12-29 06:53:04 +00:00
case 'unpublished' :
case 'revoked' :
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: REVOKED ;
2009-12-29 06:53:04 +00:00
if ( empty ( $project_data [ 'extra' ])) {
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ] = [];
2009-12-29 06:53:04 +00:00
}
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ][] = [
2009-12-29 06:53:04 +00:00
'label' => t ( 'Project revoked' ),
2024-01-11 13:24:56 +00:00
'data' => t ( 'This project has been revoked, and is no longer available for download. Uninstalling everything included by this project is strongly recommended!' ),
2017-03-04 01:20:24 +00:00
];
2009-12-29 06:53:04 +00:00
break ;
2020-06-02 08:46:52 +00:00
2009-12-29 06:53:04 +00:00
case 'unsupported' :
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: NOT_SUPPORTED ;
2009-12-29 06:53:04 +00:00
if ( empty ( $project_data [ 'extra' ])) {
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ] = [];
2009-12-29 06:53:04 +00:00
}
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ][] = [
2009-12-29 06:53:04 +00:00
'label' => t ( 'Project not supported' ),
2024-01-11 13:24:56 +00:00
'data' => t ( 'This project is no longer supported, and is no longer available for download. Uninstalling everything included by this project is strongly recommended!' ),
2017-03-04 01:20:24 +00:00
];
2009-12-29 06:53:04 +00:00
break ;
2020-06-02 08:46:52 +00:00
2009-12-29 06:53:04 +00:00
case 'not-fetched' :
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateFetcherInterface :: NOT_FETCHED ;
2009-12-29 06:53:04 +00:00
$project_data [ 'reason' ] = t ( 'Failed to get available update data.' );
break ;
default :
// Assume anything else (e.g. 'published') is valid and we should
// perform the rest of the logic in this function.
break ;
}
}
2008-01-10 14:14:54 +00:00
2009-12-29 06:53:04 +00:00
if ( ! empty ( $project_data [ 'status' ])) {
// We already know the status for this project, so there's nothing else to
// compute. Record the project status into $project_data and we're done.
$project_data [ 'project_status' ] = $available [ 'project_status' ];
return ;
}
2008-01-10 14:14:54 +00:00
2009-12-29 06:53:04 +00:00
// Figure out the target major version.
Issue #3118087 by dww, JoshaHubbers, jungle, tedbow, RajabNatshah, Kingdutch, JonMcL, xjm, Nick Hope, wroehrig, wxman, broeker, mlozano7, kazajhodo, suit4, xmacinfo, BrightBold: If any extension has a missing or invalid version, Update manager throws errors and is confused about site update status
2020-03-19 21:34:25 +00:00
// Off Drupal.org, '0' could be a valid version string, so don't use empty().
if ( ! isset ( $project_data [ 'existing_version' ]) || $project_data [ 'existing_version' ] === '' ) {
$project_data [ 'status' ] = UpdateFetcherInterface :: UNKNOWN ;
$project_data [ 'reason' ] = t ( 'Empty version' );
return ;
}
2020-01-23 21:28:49 +00:00
try {
Issue #3041885 by tedbow, beautifulmind, dww, ayushmishra206, phenaproxima, webchick, xjm, AaronMcHale, larowlan, benjifisher, heddn, catch, jhodgdon, longwave, mglaman, alexpott, mxr576, effulgentsia: Display relevant Security Advisories data for Drupal
2021-05-12 06:40:17 +00:00
$existing_major = ExtensionVersion :: createFromVersionString ( $project_data [ 'existing_version' ]) -> getMajorVersion ();
2009-12-29 06:53:04 +00:00
}
2020-01-23 21:28:49 +00:00
catch ( UnexpectedValueException $exception ) {
// If the version has an unexpected value we can't determine updates.
Issue #3118087 by dww, JoshaHubbers, jungle, tedbow, RajabNatshah, Kingdutch, JonMcL, xjm, Nick Hope, wroehrig, wxman, broeker, mlozano7, kazajhodo, suit4, xmacinfo, BrightBold: If any extension has a missing or invalid version, Update manager throws errors and is confused about site update status
2020-03-19 21:34:25 +00:00
$project_data [ 'status' ] = UpdateFetcherInterface :: UNKNOWN ;
$project_data [ 'reason' ] = t ( 'Invalid version: @existing_version' , [ '@existing_version' => $project_data [ 'existing_version' ]]);
2020-01-23 21:28:49 +00:00
return ;
}
$supported_branches = [];
if ( isset ( $available [ 'supported_branches' ])) {
$supported_branches = explode ( ',' , $available [ 'supported_branches' ]);
2009-12-29 06:53:04 +00:00
}
2008-01-10 14:14:54 +00:00
2020-01-23 21:28:49 +00:00
$is_in_supported_branch = function ( $version ) use ( $supported_branches ) {
foreach ( $supported_branches as $supported_branch ) {
2023-01-27 12:37:01 +00:00
if ( str_starts_with ( $version , $supported_branch )) {
2020-01-23 21:28:49 +00:00
return TRUE ;
}
}
return FALSE ;
};
if ( $is_in_supported_branch ( $project_data [ 'existing_version' ])) {
2009-12-29 06:53:04 +00:00
// Still supported, stay at the current major version.
$target_major = $existing_major ;
}
2020-01-23 21:28:49 +00:00
elseif ( $supported_branches ) {
// We know the current release is unsupported since it is not in
// 'supported_branches' list. We should use the next valid supported
// branch for the target major version.
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: NOT_SUPPORTED ;
2020-01-23 21:28:49 +00:00
foreach ( $supported_branches as $supported_branch ) {
try {
Issue #3041885 by tedbow, beautifulmind, dww, ayushmishra206, phenaproxima, webchick, xjm, AaronMcHale, larowlan, benjifisher, heddn, catch, jhodgdon, longwave, mglaman, alexpott, mxr576, effulgentsia: Display relevant Security Advisories data for Drupal
2021-05-12 06:40:17 +00:00
$target_major = ExtensionVersion :: createFromSupportBranch ( $supported_branch ) -> getMajorVersion ();
2024-04-16 15:51:30 +00:00
break ;
2020-01-23 21:28:49 +00:00
}
catch ( UnexpectedValueException $exception ) {
continue ;
}
}
if ( ! isset ( $target_major )) {
// If there are no valid support branches, use the current major.
$target_major = $existing_major ;
}
2009-12-29 06:53:04 +00:00
}
else {
2020-01-23 21:28:49 +00:00
// Malformed XML file? Stick with the current branch.
2009-12-29 06:53:04 +00:00
$target_major = $existing_major ;
}
2007-07-11 15:15:40 +00:00
2009-12-29 06:53:04 +00:00
// Make sure we never tell the admin to downgrade. If we recommended an
// earlier version than the one they're running, they'd face an
// impossible data migration problem, since Drupal never supports a DB
// downgrade path. In the unfortunate case that what they're running is
// unsupported, and there's nothing newer for them to upgrade to, we
// can't print out a "Recommended version", but just have to tell them
// what they have is unsupported and let them figure it out.
$target_major = max ( $existing_major , $target_major );
2019-12-04 11:57:25 +00:00
// If the project is marked as UpdateFetcherInterface::FETCH_PENDING, it
// means that the data we currently have (if any) is stale, and we've got a
// task queued up to (re)fetch the data. In that case, we mark it as such,
// merge in whatever data we have (e.g. project title and link), and move on.
if ( ! empty ( $available [ 'fetch_status' ]) && $available [ 'fetch_status' ] == UpdateFetcherInterface :: FETCH_PENDING ) {
$project_data [ 'status' ] = UpdateFetcherInterface :: FETCH_PENDING ;
2009-12-29 06:53:04 +00:00
$project_data [ 'reason' ] = t ( 'No available update data' );
$project_data [ 'fetch_status' ] = $available [ 'fetch_status' ];
return ;
}
2009-10-13 02:14:05 +00:00
2009-12-29 06:53:04 +00:00
// Defend ourselves from XML history files that contain no releases.
if ( empty ( $available [ 'releases' ])) {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateFetcherInterface :: UNKNOWN ;
2009-12-29 06:53:04 +00:00
$project_data [ 'reason' ] = t ( 'No available releases found' );
return ;
}
2020-01-23 21:28:49 +00:00
$recommended_version_without_extra = '' ;
$recommended_release = NULL ;
2024-04-16 15:51:30 +00:00
$release_is_supported = FALSE ;
2021-06-23 03:51:34 +00:00
foreach ( $available [ 'releases' ] as $version => $release_info ) {
2020-01-23 21:28:49 +00:00
try {
2021-06-23 03:51:34 +00:00
$release = ProjectRelease :: createFromArray ( $release_info );
}
catch ( UnexpectedValueException $exception ) {
// Ignore releases that are in an invalid format. Although this is highly
// unlikely we should still process releases in the correct format.
Issue #2932518 by kim.pepper, joachim, bradjones1, voleger, cliddell, gapple, Xano, andregp, andypost, neclimdul, rpayanm, Hardik_Patel_12, NWOM, smustgrave, dawehner, alexpott, daffie, larowlan, Berdir, mstrelan, xjm, dagmar: Deprecate watchdog_exception
2023-04-28 03:36:57 +00:00
Error :: logException ( \Drupal :: logger ( 'update' ), $exception , 'Invalid project format: @release' , [ '@release' => print_r ( $release_info , TRUE )]);
2021-06-23 03:51:34 +00:00
continue ;
}
try {
$release_module_version = ExtensionVersion :: createFromVersionString ( $release -> getVersion ());
2020-01-23 21:28:49 +00:00
}
catch ( UnexpectedValueException $exception ) {
continue ;
}
2024-04-16 15:51:30 +00:00
// This release is supported only if it is in a supported branch and is
// not unsupported.
$release_is_supported = $is_in_supported_branch ( $release -> getVersion ()) && ! $release -> isUnsupported ();
2009-12-29 06:53:04 +00:00
// First, if this is the existing release, check a few conditions.
if ( $project_data [ 'existing_version' ] === $version ) {
2021-06-23 03:51:34 +00:00
if ( $release -> isInsecure ()) {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: NOT_SECURE ;
2008-01-10 14:14:54 +00:00
}
2021-06-23 03:51:34 +00:00
elseif ( ! $release -> isPublished ()) {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: REVOKED ;
2009-12-29 06:53:04 +00:00
if ( empty ( $project_data [ 'extra' ])) {
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ] = [];
2007-07-11 15:15:40 +00:00
}
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ][] = [
'class' => [ 'release-revoked' ],
2009-12-29 06:53:04 +00:00
'label' => t ( 'Release revoked' ),
2024-01-11 13:24:56 +00:00
'data' => t ( 'Your currently installed release has been revoked, and is no longer available for download. Uninstalling everything included in this release or upgrading is strongly recommended!' ),
2017-03-04 01:20:24 +00:00
];
2009-12-29 06:53:04 +00:00
}
2024-04-16 15:51:30 +00:00
elseif ( ! $release_is_supported ) {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: NOT_SUPPORTED ;
2009-12-29 06:53:04 +00:00
if ( empty ( $project_data [ 'extra' ])) {
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ] = [];
2007-07-11 15:15:40 +00:00
}
2024-04-16 15:51:30 +00:00
if ( empty ( $project_data [ 'recommended' ]) && empty ( $project_data [ 'also' ])) {
$unsupported_message = t ( 'Your currently installed release is now unsupported, is no longer available for download and no update is available. Uninstalling everything included in this release is strongly recommended!' );
}
else {
$unsupported_message = t ( 'Your currently installed release is now unsupported, and is no longer available for download. Uninstalling everything included in this release or upgrading is strongly recommended!' );
}
2017-03-04 01:20:24 +00:00
$project_data [ 'extra' ][] = [
'class' => [ 'release-not-supported' ],
2009-12-29 06:53:04 +00:00
'label' => t ( 'Release not supported' ),
2024-04-16 15:51:30 +00:00
'data' => $unsupported_message ,
2017-03-04 01:20:24 +00:00
];
2009-12-29 06:53:04 +00:00
}
}
2020-04-19 23:25:26 +00:00
// Other than the currently installed release, ignore unpublished, insecure,
// or unsupported updates.
2021-06-23 03:51:34 +00:00
elseif ( ! $release -> isPublished () ||
2024-04-16 15:51:30 +00:00
! $release_is_supported ||
2021-06-23 03:51:34 +00:00
$release -> isInsecure ()
2020-04-19 23:25:26 +00:00
) {
2009-12-29 06:53:04 +00:00
continue ;
}
2022-06-22 10:42:12 +00:00
// Ignore dev releases with no date. These are either broken releases or
// stub releases to allow them to be selected on drupal.org project issues.
elseif ( $release -> getDate () === NULL && $release_module_version -> getVersionExtra () === 'dev' ) {
continue ;
}
2007-07-11 15:15:40 +00:00
2020-01-23 21:28:49 +00:00
$release_major_version = $release_module_version -> getMajorVersion ();
2009-12-29 06:53:04 +00:00
// See if this is a higher major version than our target and yet still
// supported. If so, record it as an "Also available" release.
2020-01-23 21:28:49 +00:00
if ( $release_major_version > $target_major ) {
2020-02-28 12:26:45 +00:00
if ( ! isset ( $project_data [ 'also' ])) {
$project_data [ 'also' ] = [];
}
if ( ! isset ( $project_data [ 'also' ][ $release_major_version ])) {
$project_data [ 'also' ][ $release_major_version ] = $version ;
2021-06-23 03:51:34 +00:00
$project_data [ 'releases' ][ $version ] = $release_info ;
2009-12-29 06:53:04 +00:00
}
// Otherwise, this release can't matter to us, since it's neither
// from the release series we're currently using nor the recommended
// release. We don't even care about security updates for this
// branch, since if a project maintainer puts out a security release
// at a higher major version and not at the lower major version,
// they must remove the lower version from the supported major
// versions at the same time, in which case we won't hit this code.
continue ;
}
2007-07-11 15:15:40 +00:00
2009-12-29 06:53:04 +00:00
// Look for the 'latest version' if we haven't found it yet. Latest is
// defined as the most recent version for the target major version.
if ( ! isset ( $project_data [ 'latest_version' ])
2020-01-23 21:28:49 +00:00
&& $release_major_version == $target_major ) {
2009-12-29 06:53:04 +00:00
$project_data [ 'latest_version' ] = $version ;
2021-06-23 03:51:34 +00:00
$project_data [ 'releases' ][ $version ] = $release_info ;
2009-12-29 06:53:04 +00:00
}
2007-07-11 15:15:40 +00:00
2009-12-29 06:53:04 +00:00
// Look for the development snapshot release for this branch.
if ( ! isset ( $project_data [ 'dev_version' ])
2020-01-23 21:28:49 +00:00
&& $release_major_version == $target_major
&& $release_module_version -> getVersionExtra () === 'dev' ) {
2009-12-29 06:53:04 +00:00
$project_data [ 'dev_version' ] = $version ;
2021-06-23 03:51:34 +00:00
$project_data [ 'releases' ][ $version ] = $release_info ;
2009-12-29 06:53:04 +00:00
}
2007-07-11 15:15:40 +00:00
2020-01-23 21:28:49 +00:00
if ( $release_module_version -> getVersionExtra ()) {
2021-06-23 03:51:34 +00:00
$release_version_without_extra = str_replace ( '-' . $release_module_version -> getVersionExtra (), '' , $release -> getVersion ());
2020-01-23 21:28:49 +00:00
}
else {
2021-06-23 03:51:34 +00:00
$release_version_without_extra = $release -> getVersion ();
2020-01-23 21:28:49 +00:00
}
2009-12-29 06:53:04 +00:00
// Look for the 'recommended' version if we haven't found it yet (see
Issue #3219513 by quietone, smustgrave, Vidushi Mehta, sourabhjain, rpayanm, longwave, xjm, dww, catch: Fix spelling for words used once, beginning with 'n' -> 'p', inclusive
2023-08-01 10:07:26 +00:00
// PHPDoc at the top of this function for the definition).
2009-12-29 06:53:04 +00:00
if ( ! isset ( $project_data [ 'recommended' ])
2024-04-16 15:51:30 +00:00
&& $release_major_version == $target_major && $release_is_supported ) {
2020-01-23 21:28:49 +00:00
if ( $recommended_version_without_extra !== $release_version_without_extra ) {
$recommended_version_without_extra = $release_version_without_extra ;
2021-06-23 03:51:34 +00:00
$recommended_release = $release_info ;
2007-07-11 15:15:40 +00:00
}
2020-01-23 21:28:49 +00:00
if ( $release_module_version -> getVersionExtra () === NULL ) {
$project_data [ 'recommended' ] = $recommended_release [ 'version' ];
$project_data [ 'releases' ][ $recommended_release [ 'version' ]] = $recommended_release ;
2007-07-11 15:15:40 +00:00
}
2009-12-29 06:53:04 +00:00
}
2007-07-11 15:15:40 +00:00
2009-12-29 06:53:04 +00:00
// Stop searching once we hit the currently installed version.
if ( $project_data [ 'existing_version' ] === $version ) {
break ;
}
2008-01-10 14:14:54 +00:00
2009-12-29 06:53:04 +00:00
// If we're running a dev snapshot and have a timestamp, stop
// searching for security updates once we hit an official release
// older than what we've got. Allow 100 seconds of leeway to handle
2013-03-06 22:51:39 +00:00
// differences between the datestamp in the .info.yml file and the
2009-12-29 06:53:04 +00:00
// timestamp of the tarball itself (which are usually off by 1 or 2
// seconds) so that we don't flag that as a new release.
if ( $project_data [ 'install_type' ] == 'dev' ) {
if ( empty ( $project_data [ 'datestamp' ])) {
// We don't have current timestamp info, so we can't know.
2008-01-10 14:14:54 +00:00
continue ;
}
2021-06-23 03:51:34 +00:00
elseif ( $release -> getDate () && $project_data [ 'datestamp' ] + 100 > $release -> getDate ()) {
2009-12-29 06:53:04 +00:00
// We're newer than this, so we can skip it.
2007-07-11 15:15:40 +00:00
continue ;
}
2009-12-29 06:53:04 +00:00
}
2007-07-11 15:15:40 +00:00
2021-06-23 03:51:34 +00:00
if ( $release -> isSecurityRelease ()) {
$project_data [ 'security updates' ][] = $release_info ;
2009-12-29 06:53:04 +00:00
}
}
2007-07-11 15:15:40 +00:00
2009-12-29 06:53:04 +00:00
// If we were unable to find a recommended version, then make the latest
// version the recommended version if possible.
2024-04-16 15:51:30 +00:00
if ( ! isset ( $project_data [ 'recommended' ]) && isset ( $project_data [ 'latest_version' ]) && $release_is_supported ) {
2009-12-29 06:53:04 +00:00
$project_data [ 'recommended' ] = $project_data [ 'latest_version' ];
}
if ( isset ( $project_data [ 'status' ])) {
// If we already know the status, we're done.
return ;
}
// If we don't know what to recommend, there's nothing we can report.
// Bail out early.
if ( ! isset ( $project_data [ 'recommended' ])) {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateFetcherInterface :: UNKNOWN ;
2009-12-29 06:53:04 +00:00
$project_data [ 'reason' ] = t ( 'No available releases found' );
return ;
}
// If we're running a dev snapshot, compare the date of the dev snapshot
// with the latest official version, and record the absolute latest in
// 'latest_dev' so we can correctly decide if there's a newer release
// than our current snapshot.
if ( $project_data [ 'install_type' ] == 'dev' ) {
if ( isset ( $project_data [ 'dev_version' ]) && $available [ 'releases' ][ $project_data [ 'dev_version' ]][ 'date' ] > $available [ 'releases' ][ $project_data [ 'latest_version' ]][ 'date' ]) {
$project_data [ 'latest_dev' ] = $project_data [ 'dev_version' ];
2007-07-11 15:15:40 +00:00
}
else {
2009-12-29 06:53:04 +00:00
$project_data [ 'latest_dev' ] = $project_data [ 'latest_version' ];
2007-07-11 15:15:40 +00:00
}
}
2008-01-27 17:50:10 +00:00
2009-12-29 06:53:04 +00:00
// Figure out the status, based on what we've seen and the install type.
switch ( $project_data [ 'install_type' ]) {
case 'official' :
if ( $project_data [ 'existing_version' ] === $project_data [ 'recommended' ] || $project_data [ 'existing_version' ] === $project_data [ 'latest_version' ]) {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: CURRENT ;
2009-12-29 06:53:04 +00:00
}
else {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: NOT_CURRENT ;
2009-12-29 06:53:04 +00:00
}
break ;
case 'dev' :
$latest = $available [ 'releases' ][ $project_data [ 'latest_dev' ]];
if ( empty ( $project_data [ 'datestamp' ])) {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateFetcherInterface :: NOT_CHECKED ;
2009-12-29 06:53:04 +00:00
$project_data [ 'reason' ] = t ( 'Unknown release date' );
}
elseif (( $project_data [ 'datestamp' ] + 100 > $latest [ 'date' ])) {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: CURRENT ;
2009-12-29 06:53:04 +00:00
}
else {
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateManagerInterface :: NOT_CURRENT ;
2009-12-29 06:53:04 +00:00
}
break ;
default :
2019-12-04 11:57:25 +00:00
$project_data [ 'status' ] = UpdateFetcherInterface :: UNKNOWN ;
2009-12-29 06:53:04 +00:00
$project_data [ 'reason' ] = t ( 'Invalid info' );
}
2008-01-27 17:50:10 +00:00
}