Index: src/wp-admin/includes/plugin.php
===================================================================
--- src/wp-admin/includes/plugin.php	(revision 44975)
+++ src/wp-admin/includes/plugin.php	(working copy)
@@ -597,6 +597,7 @@
  * ensure that the success redirection will update the error redirection.
  *
  * @since 2.5.0
+ * @since 5.2.0 Test for WordPress version and PHP version compatibility.
  *
  * @param string $plugin       Path to the plugin file relative to the plugins directory.
  * @param string $redirect     Optional. URL to redirect to.
@@ -621,6 +622,11 @@
 		return $valid;
 	}
 
+	$requirements = validate_plugin_requirements( $plugin );
+	if ( is_wp_error( $requirements ) ) {
+		return $requirements;
+	}
+
 	if ( ( $network_wide && ! isset( $current[ $plugin ] ) ) || ( ! $network_wide && ! in_array( $plugin, $current ) ) ) {
 		if ( ! empty( $redirect ) ) {
 			wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) ); // we'll override this later if the plugin can be included without fatal error
@@ -1061,6 +1067,55 @@
 }
 
 /**
+ * Validate the plugin requirements for WP version and PHP version.
+ *
+ * @since 5.2.0
+ *
+ * @param string $plugin Path to the plugin file relative to the plugins directory.
+ * @return true|WP_Error True if requirements are met, WP_Error on failure.
+ */
+function validate_plugin_requirements( $plugin ) {
+	$readme_file = WP_PLUGIN_DIR . '/' . dirname( $plugin ) . '/readme.txt';
+
+	if ( file_exists( $readme_file ) ) {
+		$plugin_data = get_file_data(
+			$readme_file,
+			array(
+				'requires'     => 'Requires at least',
+				'requires_php' => 'Requires PHP',
+			),
+			'plugin'
+		);
+	} else {
+		return true;
+	}
+
+	$plugin_data['wp_compatible']  = wp_is_wp_compatible( $plugin_data['requires'] );
+	$plugin_data['php_compatible'] = wp_is_php_compatible( $plugin_data['requires_php'] );
+
+	$plugin_data = array_merge( $plugin_data, get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ) );
+
+	if ( ! $plugin_data['wp_compatible'] && ! $plugin_data['php_compatible'] ) {
+		return new WP_Error( 'plugin_wp_php_incompatible', sprintf(
+			/* translators: %s: plugin name */
+			__( '<strong>Error:</strong> Current WordPress and PHP versions do not meet minimum requirements for %s.' ), $plugin_data['Name'] )
+		);
+	} elseif ( ! $plugin_data['php_compatible'] ) {
+		return new WP_Error( 'plugin_php_incompatible', sprintf(
+			/* translators: %s: plugin name */
+			__( '<strong>Error:</strong> Current PHP version does not meet minimum requirements for %s.' ), $plugin_data['Name'] )
+		);
+	} elseif ( ! $plugin_data['wp_compatible'] ) {
+		return new WP_Error( 'plugin_wp_incompatible', sprintf(
+			/* translators: %s: plugin name */
+			__( '<strong>Error:</strong> Current WordPress version does not meet minimum requirements for %s.' ), $plugin_data['Name'] )
+		);
+	}
+
+	return true;
+}
+
+/**
  * Whether the plugin can be uninstalled.
  *
  * @since 2.7.0
Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 44975)
+++ src/wp-includes/functions.php	(working copy)
@@ -6897,3 +6897,29 @@
 	);
 	echo '</p>';
 }
+
+/**
+ * Checks compatibility with the current WordPress version.
+ *
+ * @since 5.2.0
+ *
+ * @param string $required Minimum required WordPress version.
+ * @return bool True if required version is compatible or empty, false if not.
+ */
+function wp_is_wp_compatible( $required ) {
+	$wp_version = get_bloginfo( 'version' );
+
+	return empty( $required ) || version_compare( $wp_version, $required, '>=' );
+}
+
+/**
+ * Checks compatibility with the current PHP version.
+ *
+ * @since 5.2.0
+ *
+ * @param string $required Minimum required PHP version.
+ * @return bool True if required version is compatible or empty, false if not.
+ */
+function wp_is_php_compatible( $required ) {
+	return empty( $required ) || version_compare( phpversion(), $required, '>=' );
+}
