Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 14 additions & 48 deletions inc/packages/admin/info.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace FAIR\Packages\Admin\Info;

use FAIR\Packages;
use FAIR\Packages\Admin;
use FAIR\Packages\MetadataDocument;
use FAIR\Packages\ReleaseDocument;
Expand Down Expand Up @@ -165,7 +166,7 @@ function render( MetadataDocument $doc, string $tab, string $section ) {

<div id="section-holder">
<?php
check_requirements( $latest );
add_requirement_notices( $latest );
foreach ( $sections as $section_id => $content ) {
$prepared = sanitize_html( $content );
$prepared = links_add_target( $prepared, '_blank' );
Expand Down Expand Up @@ -324,53 +325,19 @@ function render_fyi( MetadataDocument $doc, ReleaseDocument $release ) : void {
}

/**
* Get version requirements.
* Check requirements, and add notices if not met.
*
* @param ReleaseDocument $release Release document.
*
* @return array
* @return void
*/
function version_requirements( ReleaseDocument $release ) {
$required_versions = [];
foreach ( $release->requires as $pkg => $vers ) {
$vers = preg_replace( '/^[^0-9]+/', '', $vers );
if ( $pkg === 'env:php' ) {
$required_versions['requires_php'] = $vers;
}
if ( $pkg === 'env:wp' ) {
$required_versions['requires_wp'] = $vers;
}
}
foreach ( $release->suggests as $pkg => $vers ) {
$vers = preg_replace( '/^[^0-9]+/', '', $vers );
if ( $pkg === 'env:wp' ) {
$required_versions['tested_to'] = $vers;
}
function add_requirement_notices( ReleaseDocument $release ) : void {
$unmet_requires = Packages\get_unmet_requirements( (array) $release->requires );
$unmet_suggests = Packages\get_unmet_requirements( (array) $release->suggests );
if ( empty( $unmet_requires ) && empty( $unmet_suggests ) ) {
return;
}

return $required_versions;
}

/**
* Check requirements.
*
* @param ReleaseDocument $release Release document.
*
* @return bool
*/
function check_requirements( ReleaseDocument $release ) {
$required_versions = version_requirements( $release );
$requires_php = $required_versions['requires_php'] ?? null;
$requires_wp = $required_versions['requires_wp'] ?? null;
$tested_to = $required_versions['tested_to'] ?? null;

$compatible_php = is_php_version_compatible( $requires_php );
$compatible_wp = is_wp_version_compatible( $requires_wp );

// Set to true if using a development release.
$tested_wp = (bool) preg_match( '/alpha|beta|RC/', get_bloginfo( 'version' ) ) ?? ( empty( $tested_to ) || version_compare( get_bloginfo( 'version' ), $tested_to, '<=' ) );

if ( ! $compatible_php ) {
if ( isset( $unmet_requires['env:php'] ) ) {
$compatible_php_notice_message = '<p>';
$compatible_php_notice_message .= __( '<strong>Error:</strong> This plugin <strong>requires a newer version of PHP</strong>.', 'fair' );

Expand All @@ -394,15 +361,16 @@ function check_requirements( ReleaseDocument $release ) {
);
}

if ( ! $tested_wp ) {
$is_dev = (bool) preg_match( '/alpha|beta|RC/', get_bloginfo( 'version' ) );
if ( isset( $unmet_suggests['env:wp'] ) && ! $is_dev ) {
wp_admin_notice(
__( '<strong>Warning:</strong> This plugin <strong>has not been tested</strong> with your current version of WordPress.', 'fair' ),
[
'type' => 'warning',
'additional_classes' => [ 'notice-alt' ],
]
);
} elseif ( ! $compatible_wp ) {
} elseif ( isset( $unmet_requires['env:wp'] ) ) {
$compatible_wp_notice_message = __( '<strong>Error:</strong> This plugin <strong>requires a newer version of WordPress</strong>.', 'fair' );
if ( current_user_can( 'update_core' ) ) {
$compatible_wp_notice_message .= sprintf(
Expand All @@ -420,8 +388,6 @@ function check_requirements( ReleaseDocument $release ) {
]
);
}

return $compatible_php && $compatible_wp && $tested_to;
}

/**
Expand All @@ -439,7 +405,7 @@ function get_action_button( MetadataDocument $doc, ReleaseDocument $release ) {
}

// Do we actually meet the requirements?
$compatible = check_requirements( $release );
$compatible = Packages\check_requirements( $release );

$status = 'install'; // todo.
switch ( $status ) {
Expand Down
110 changes: 110 additions & 0 deletions inc/packages/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,114 @@ function pick_artifact_by_lang( array $artifacts, ?string $locale = null ) {
return apply_filters( 'fair.packages.pick_artifact_by_lang', $selected, $artifacts, $locale, $langs );
}

/**
* Get version requirements.
*
* @param ReleaseDocument $release Release document.
*
* @return array
*/
function version_requirements( ReleaseDocument $release ) {
$required_versions = [];
foreach ( $release->requires as $pkg => $vers ) {
$vers = preg_replace( '/^[^0-9]+/', '', $vers );
if ( $pkg === 'env:php' ) {
$required_versions['requires_php'] = $vers;
}
if ( $pkg === 'env:wp' ) {
$required_versions['requires_wp'] = $vers;
}
}
foreach ( $release->suggests as $pkg => $vers ) {
$vers = preg_replace( '/^[^0-9]+/', '', $vers );
if ( $pkg === 'env:wp' ) {
$required_versions['tested_to'] = $vers;
}
}

return $required_versions;
}

/**
* Get unmet requirements.
*
* @param array $requirements Requirements to check. Map of package names to requirement strings.
* @return array Map of package names to unmet requirements.
*/
function get_unmet_requirements( array $requirements ) : array {
$unmet = [];
foreach ( $requirements as $pkg => $req_list ) {
$req_parts = explode( ',', $req_list );
$req_unmet = [];
foreach ( $req_parts as $req ) {
$req = trim( $req );
$comp_spn = strspn( $req, '<>=!' );
if ( $comp_spn === 0 ) {
// Invalid requirement, for now.
continue;
}

$comp = trim( substr( $req, 0, $comp_spn ) );
$ver = trim( substr( $req, $comp_spn ) );

switch ( true ) {
case $pkg === 'env:wp':
// From is_wp_version_compatible()
// We use our own copy to allow passing $comp.
if (
defined( 'WP_RUN_CORE_TESTS' )
&& WP_RUN_CORE_TESTS
&& isset( $GLOBALS['_wp_tests_wp_version'] )
) {
$wp_version = $GLOBALS['_wp_tests_wp_version'];
} else {
$wp_version = wp_get_wp_version();
}

$valid = version_compare( $wp_version, $ver, $comp );
if ( ! $valid ) {
$req_unmet[] = $req;
}
break;

case $pkg === 'env:php':
$valid = version_compare( PHP_VERSION, $ver, $comp );
if ( ! $valid ) {
$req_unmet[] = $req;
}
break;

case str_starts_with( $pkg, 'env:php-' ):
// todo: check extensions.
break;

case str_starts_with( $pkg, 'env:' ):
// todo: check other env, or fail.
break;

default:
// todo: check packages.
break;
}
}
if ( ! empty( $req_unmet ) ) {
$unmet[ $pkg ] = implode( ', ', $req_unmet );
}
}

return $unmet;
}

/**
* Check if a release meets the requirements.
*
* @param ReleaseDocument $release Release document.
*
* @return bool True if the release meets the requirements, false otherwise.
*/
function check_requirements( ReleaseDocument $release ) {
$requires = get_unmet_requirements( (array) $release->requires );
return empty( $requires );
}

// phpcs:enable
4 changes: 2 additions & 2 deletions inc/updater/class-updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

use const FAIR\Packages\SERVICE_ID;

use function FAIR\Packages\Admin\Info\check_requirements;
use FAIR\Packages;
use function FAIR\Packages\fetch_metadata_doc;
use function FAIR\Packages\fetch_package_metadata;
use function FAIR\Packages\get_did_document;
Expand Down Expand Up @@ -314,7 +314,7 @@ public function update_site_transient( $transient ) {
$rel_path = plugin_basename( $this->filepath );
$response = $this->get_update_data();
$response = 'plugin' === $this->type ? (object) $response : $response;
$is_compatible = check_requirements( $this->release );
$is_compatible = Packages\check_requirements( $this->release );

if ( $is_compatible && version_compare( $this->release->version, $this->local_version, '>' ) ) {
$transient->response[ $rel_path ] = $response;
Expand Down