2022-06-16 14:01:47 +02:00
< ? php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2019-11-15 23:26:29 +01:00
2022-06-16 14:01:47 +02:00
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ;
require_once ABSPATH . 'wp-admin/includes/file.php' ;
2019-11-15 23:26:29 +01:00
2022-04-02 10:26:41 +02:00
use Automattic\Jetpack\Automatic_Install_Skin ;
2019-11-15 23:26:29 +01:00
use Automattic\Jetpack\Connection\Client ;
2022-06-16 14:01:47 +02:00
/**
* Themes install endpoint class .
*
* POST / sites /% s / themes /% s / install
*/
2019-11-15 23:26:29 +01:00
class Jetpack_JSON_API_Themes_Install_Endpoint extends Jetpack_JSON_API_Themes_Endpoint {
2022-06-16 14:01:47 +02:00
/**
* Needed capabilities .
*
* @ var string
*/
2019-11-15 23:26:29 +01:00
protected $needed_capabilities = 'install_themes' ;
2022-06-16 14:01:47 +02:00
/**
* The action .
*
* @ var string
*/
protected $action = 'install' ;
/**
* Download links .
*
* @ var array
*/
protected $download_links = array ();
/**
* Install the theme .
*
* @ return bool | WP_Error
*/
2019-11-15 23:26:29 +01:00
protected function install () {
foreach ( $this -> themes as $theme ) {
/**
* Filters whether to use an alternative process for installing a WordPress . com theme .
* The alternative process can be executed during the filter .
*
* The filter can also return an instance of WP_Error ; in which case the endpoint response will
* contain this error .
*
* @ module json - api
*
* @ since 4.4 . 2
*
* @ param bool $use_alternative_install_method Whether to use the alternative method of installing
* a WPCom theme .
* @ param string $theme_slug Theme name ( slug ) . If it is a WPCom theme ,
* it should be suffixed with `-wpcom` .
*/
$result = apply_filters ( 'jetpack_wpcom_theme_install' , false , $theme );
2022-06-16 14:01:47 +02:00
$skin = null ;
2019-11-15 23:26:29 +01:00
$upgrader = null ;
2022-06-16 14:01:47 +02:00
$link = null ;
2019-11-15 23:26:29 +01:00
// If the alternative install method was not used, use the standard method.
if ( ! $result ) {
2022-04-02 10:26:41 +02:00
$skin = new Automatic_Install_Skin ();
2019-11-15 23:26:29 +01:00
$upgrader = new Theme_Upgrader ( $skin );
$link = $this -> download_links [ $theme ];
$result = $upgrader -> install ( $link );
}
if ( file_exists ( $link ) ) {
// Delete if link was tmp local file
2023-04-26 17:39:43 +02:00
wp_delete_file ( $link );
2019-11-15 23:26:29 +01:00
}
if ( ! $this -> bulk && is_wp_error ( $result ) ) {
return $result ;
}
if ( ! $result ) {
2022-06-16 14:01:47 +02:00
$error = __ ( 'An unknown error occurred during installation' , 'jetpack' );
$this -> log [ $theme ][ 'error' ] = $error ;
} elseif ( ! self :: is_installed_theme ( $theme ) ) {
$error = __ ( 'There was an error installing your theme' , 'jetpack' );
$this -> log [ $theme ][ 'error' ] = $error ;
} elseif ( $upgrader ) {
2019-11-15 23:26:29 +01:00
$this -> log [ $theme ][] = $upgrader -> skin -> get_upgrade_messages ();
}
}
if ( ! $this -> bulk && isset ( $error ) ) {
2022-06-16 14:01:47 +02:00
return new WP_Error ( 'install_error' , $error , 400 );
2019-11-15 23:26:29 +01:00
}
return true ;
}
2022-06-16 14:01:47 +02:00
/**
* Validate the themes .
*
* @ return bool | WP_Error
*/
2019-11-15 23:26:29 +01:00
protected function validate_themes () {
if ( empty ( $this -> themes ) || ! is_array ( $this -> themes ) ) {
return new WP_Error ( 'missing_themes' , __ ( 'No themes found.' , 'jetpack' ) );
}
2022-06-16 14:01:47 +02:00
foreach ( $this -> themes as $theme ) {
2019-11-15 23:26:29 +01:00
if ( self :: is_installed_theme ( $theme ) ) {
return new WP_Error ( 'theme_already_installed' , __ ( 'The theme is already installed' , 'jetpack' ) );
}
/**
* Filters whether to skip the standard method of downloading and validating a WordPress . com
* theme . An alternative method of WPCom theme download and validation can be
* executed during the filter .
*
* The filter can also return an instance of WP_Error ; in which case the endpoint response will
* contain this error .
*
* @ module json - api
*
* @ since 4.4 . 2
*
* @ param bool $skip_download_filter_result Whether to skip the standard method of downloading
* and validating a WPCom theme .
* @ param string $theme_slug Theme name ( slug ) . If it is a WPCom theme ,
* it should be suffixed with `-wpcom` .
*/
$skip_download_filter_result = apply_filters ( 'jetpack_wpcom_theme_skip_download' , false , $theme );
if ( is_wp_error ( $skip_download_filter_result ) ) {
return $skip_download_filter_result ;
} elseif ( $skip_download_filter_result ) {
continue ;
}
if ( wp_endswith ( $theme , '-wpcom' ) ) {
$file = self :: download_wpcom_theme_to_file ( $theme );
if ( is_wp_error ( $file ) ) {
return $file ;
}
$this -> download_links [ $theme ] = $file ;
continue ;
}
2022-06-16 14:01:47 +02:00
$params = ( object ) array ( 'slug' => $theme );
$url = 'https://api.wordpress.org/themes/info/1.0/' ; // @todo Switch to https://api.wordpress.org/themes/info/1.1/, which uses JSON rather than PHP serialization.
$args = array (
2019-11-15 23:26:29 +01:00
'body' => array (
2022-06-16 14:01:47 +02:00
'action' => 'theme_information' ,
'request' => serialize ( $params ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
),
2019-11-15 23:26:29 +01:00
);
2022-06-16 14:01:47 +02:00
$response = wp_remote_post ( $url , $args );
$theme_data = unserialize ( $response [ 'body' ] ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
2019-11-15 23:26:29 +01:00
if ( is_wp_error ( $theme_data ) ) {
return $theme_data ;
}
2022-06-16 14:01:47 +02:00
if ( ! is_object ( $theme_data ) && ! isset ( $theme_data -> download_link ) ) {
return new WP_Error ( 'theme_not_found' , __ ( 'This theme does not exist' , 'jetpack' ), 404 );
2019-11-15 23:26:29 +01:00
}
$this -> download_links [ $theme ] = $theme_data -> download_link ;
}
return true ;
}
2022-06-16 14:01:47 +02:00
/**
* Check if the theme is installed .
*
* @ param string $theme - the theme we ' re checking .
*
* @ return bool
*/
2019-11-15 23:26:29 +01:00
protected static function is_installed_theme ( $theme ) {
$wp_theme = wp_get_theme ( $theme );
return $wp_theme -> exists ();
}
2022-06-16 14:01:47 +02:00
/**
* Download the wpcom theme .
*
* @ param string $theme - the theme to download .
*
* @ return string | WP_Error
*/
2019-11-15 23:26:29 +01:00
protected static function download_wpcom_theme_to_file ( $theme ) {
$file = wp_tempnam ( 'theme' );
if ( ! $file ) {
return new WP_Error ( 'problem_creating_theme_file' , __ ( 'Problem creating file for theme download' , 'jetpack' ) );
}
2022-06-16 14:01:47 +02:00
$url = " themes/download/ $theme .zip " ;
$args = array (
'stream' => true ,
'filename' => $file ,
);
2019-11-15 23:26:29 +01:00
$result = Client :: wpcom_json_api_request_as_blog ( $url , '1.1' , $args );
2022-06-16 14:01:47 +02:00
$response = $result [ 'response' ];
if ( $response [ 'code' ] !== 200 ) {
2023-04-26 17:39:43 +02:00
wp_delete_file ( $file );
2019-11-15 23:26:29 +01:00
return new WP_Error ( 'problem_fetching_theme' , __ ( 'Problem downloading theme' , 'jetpack' ) );
}
return $file ;
}
}