first commit

This commit is contained in:
Roman Pyrih
2023-07-24 08:30:51 +02:00
commit c2e100a763
7128 changed files with 1622619 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
<?php if (!defined('FW')) die('Forbidden');
$cfg = array();
/**
* Do not show details about each extension update, but show it as one update
* (simplify users life)
*/
$cfg['extensions_as_one_update'] = true;

View File

@@ -0,0 +1,231 @@
<?php defined( 'FW' ) or die();
/**
* Bitbucket server Update
*
* Add {'remote' => 'your_url'} to your manifest and this extension will handle it
*/
class FW_Extension_Bitbucket_Update extends FW_Ext_Update_Service {
/**
* How long to cache server responses
* @var int seconds
*/
private $transient_expiration = DAY_IN_SECONDS;
private $download_timeout = 300;
/**
* Used when there is internet connection problems
* To prevent site being blocked on every refresh, this fake version will be cached in the transient
* @var string
*/
private $fake_latest_version = '0.0.0';
/**
* @internal
*/
protected function _init() {}
/**
* @param $user_repo
* @param $force_check
*
* @return mixed|string|WP_Error
*/
private function get_latest_version( $user_repo, $force_check ) {
$transient_name = 'fw_ext_upd_gh_fw';
if ( $force_check ) {
delete_site_transient( $transient_name );
$cache = array();
} else {
$cache = ( $c = get_site_transient( $transient_name ) ) && $c !== false ? $c : array();
if ( isset( $cache[ $user_repo ] ) ) {
return $cache[ $user_repo ];
}
}
$version = $this->fetch_latest_version( $user_repo );
if ( is_wp_error( $version ) ) {
// Cache fake version to prevent requests to bitbucket on every refresh.
$cache[ $user_repo ] = $this->fake_latest_version;
// Show the error to the user because it is not visible elsewhere.
FW_Flash_Messages::add( 'fw_ext_bitbucket_update_error', $version->get_error_message(), 'error' );
} else {
$cache[ $user_repo ] = $version;
}
set_site_transient( $transient_name, $cache, $this->transient_expiration );
return $version;
}
/**
* @param $user_repo
* @param $next_page
*
* @return array|string|WP_Error
*/
private function fetch_latest_version( $user_repo, $next_page = '' ) {
/**
* If at least one request failed, do not do any other requests, to prevent site being blocked on every refresh.
* This may happen on localhost when develop your theme and you have no internet connection.
* Then this method will return a fake '0.0.0' version, it will be cached by the transient
* and will not bother you until the transient will expire, then a new request will be made.
* @var bool
*/
static $no_internet_connection = false;
if ( $no_internet_connection ) {
return $this->fake_latest_version;
}
$url = $next_page ? $next_page : "https://api.bitbucket.org/2.0/repositories/{$user_repo}/refs/tags/";
$request = wp_remote_get( $url, array( 'timeout' => $this->download_timeout ) );
if ( is_wp_error( $request ) ) {
if ( $request->get_error_code() === 'http_request_failed' ) {
$no_internet_connection = true;
}
return $request;
}
if ( ! ( $versions = json_decode( wp_remote_retrieve_body( $request ), true ) ) || is_wp_error( $versions ) ) {
return ! $versions ? new WP_Error( sprintf( __( 'Empty version for item: %s', 'fw' ), $user_repo ) ) : $versions;
}
if ( isset( $versions['next'] ) ) {
return $this->fetch_latest_version( $user_repo, $versions['next'] );
}
$data_version = end( $versions['values'] );
return ! empty( $data_version['name'] ) ? $data_version['name'] : new WP_Error( sprintf( __( 'Wrong Bibucket version for item: %s', 'fw' ), $user_repo ) );
}
/**
* @param array $user_repo - user's repsository formtat username/repositoryName.
* @param string $version Requested version to download
* @param string $wp_filesystem_download_directory Allocated temporary empty directory
* @param string $title Used in messages
*
* @return string|WP_Error Path to the downloaded directory
*/
private function download( $user_repo, $version, $wp_filesystem_download_directory, $title ) {
/** @var WP_Filesystem_Base $wp_filesystem */
global $wp_filesystem;
$error_id = 'fw_ext_update_bitbucket_download_zip';
$request = wp_remote_get( "https://bitbucket.org/{$user_repo}/get/{$version}.zip", array( 'timeout' => $this->download_timeout ) );
if ( is_wp_error( $request ) ) {
return $request;
}
if ( ! ( $body = wp_remote_retrieve_body( $request ) ) || is_wp_error( $body ) ) {
return ! $body ? new WP_Error( $error_id, sprintf( esc_html__( 'Empty zip body for item: %s', 'fw' ), $title ) ) : $body;
}
// Try to extract error if server returned json with key error. If not then is an archive zip.
if ( ( $error = json_decode( $body, true ) ) && isset( $error['error'] ) ) {
return new WP_Error( $error_id, $error['error'] );
}
$zip_path = $wp_filesystem_download_directory . '/temp.zip';
// save zip to file
if ( ! $wp_filesystem->put_contents( $zip_path, $body ) ) {
return new WP_Error( $error_id, sprintf( esc_html__( 'Cannot save %s zip.', 'fw' ), $title ) );
}
$unzip_result = unzip_file( FW_WP_Filesystem::filesystem_path_to_real_path( $zip_path ), $wp_filesystem_download_directory );
if ( is_wp_error( $unzip_result ) ) {
return $unzip_result;
}
// remove zip file
if ( ! $wp_filesystem->delete( $zip_path, false, 'f' ) ) {
return new WP_Error( $error_id, sprintf( esc_html__( 'Cannot remove %s zip.', 'fw' ), $title ) );
}
$unzipped_dir_files = $wp_filesystem->dirlist( $wp_filesystem_download_directory );
if ( ! $unzipped_dir_files ) {
return new WP_Error( $error_id, esc_html__( 'Cannot access the unzipped directory files.', 'fw' ) );
}
/**
* get first found directory
* (if everything worked well, there should be only one directory)
*/
foreach ( $unzipped_dir_files as $file ) {
if ( $file['type'] == 'd' ) {
return $wp_filesystem_download_directory . '/' . $file['name'];
}
}
return new WP_Error( $error_id, sprintf( esc_html__( 'The unzipped %s directory not found.', 'fw' ), $title ) );
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_framework_latest_version( $force_check ) {
return false;
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_theme_latest_version( $force_check ) {
$user_repo = fw()->theme->manifest->get( 'bitbucket' );
if ( empty( $user_repo ) ) {
return false;
}
return $this->get_latest_version( $user_repo, $force_check );
}
/**
* {@inheritdoc}
* @internal
*/
public function _download_theme( $version, $wp_filesystem_download_directory ) {
return $this->download( fw()->theme->manifest->get( 'bitbucket' ), $version, $wp_filesystem_download_directory, esc_html__( 'Theme', 'fw' ) );
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_extension_latest_version( FW_Extension $extension, $force_check ) {
if ( ! $extension->manifest->get( 'bitbucket' ) ) {
return false;
}
return $this->get_latest_version( $extension->manifest->get( 'bitbucket' ), $force_check );
}
/**
* {@inheritdoc}
* @internal
*/
public function _download_extension( FW_Extension $extension, $version, $wp_filesystem_download_directory ) {
return $this->download( $extension->manifest->get( 'bitbucket' ), $version, $wp_filesystem_download_directory, sprintf( esc_html__( '%s extension', 'fw' ), $extension->manifest->get_name() )
);
}
}

View File

@@ -0,0 +1,5 @@
<?php defined( 'FW' ) or die();
$manifest = array();
$manifest['standalone'] = true;

View File

@@ -0,0 +1,259 @@
<?php defined( 'FW' ) or die();
/**
* Custom server Update
*
* Add {'remote' => 'your_url'} to your manifest and this extension will handle it
*/
class FW_Extension_Custom_Update extends FW_Ext_Update_Service {
/**
* How long to cache server responses
* @var int seconds
*/
private $transient_expiration = DAY_IN_SECONDS;
private $download_timeout = 300;
/**
* Used when there is internet connection problems
* To prevent site being blocked on every refresh, this fake version will be cached in the transient
* @var string
*/
private $fake_latest_version = '0.0.0';
/**
* @internal
*/
protected function _init() {}
/**
* @param $force_check
* @param $set - manifest settings.
*
* @return mixed|string|WP_Error
*/
private function get_latest_version( $force_check, $set ) {
$transient_name = 'fw_ext_upd_gh_fw';
if ( $force_check ) {
delete_site_transient( $transient_name );
$cache = array();
} else {
$cache = ( $c = get_site_transient( $transient_name ) ) && $c !== false ? $c : array();
if ( isset( $cache[ $set['item'] ] ) ) {
return $cache[ $set['item'] ];
}
}
$version = $this->fetch_latest_version( $set );
if ( is_wp_error( $version ) ) {
// Cache fake version to prevent requests to yourserver on every refresh.
$cache[ $set['item'] ] = $this->fake_latest_version;
// Show the error to the user because it is not visible elsewhere.
FW_Flash_Messages::add( 'fw_ext_custom_update_error', $version->get_error_message(), 'error' );
} else {
$cache[ $set['item'] ] = $version;
}
set_site_transient( $transient_name, $cache, $this->transient_expiration );
return $version;
}
/**
* @param $set
*
* @return array|string|WP_Error
*/
private function fetch_latest_version( $set ) {
/**
* If at least one request failed, do not do any other requests, to prevent site being blocked on every refresh.
* This may happen on localhost when develop your theme and you have no internet connection.
* Then this method will return a fake '0.0.0' version, it will be cached by the transient
* and will not bother you until the transient will expire, then a new request will be made.
* @var bool
*/
static $no_internet_connection = false;
if ( $no_internet_connection ) {
return $this->fake_latest_version;
}
$request = wp_remote_post(
apply_filters( 'fw_custom_url_version', $set['remote'], $set ),
array(
'timeout' => $this->download_timeout,
'body' => json_encode( array_merge( $set, array( 'pull' => 'version' ) ) )
)
);
if ( is_wp_error( $request ) ) {
if ( $request->get_error_code() === 'http_request_failed' ) {
$no_internet_connection = true;
}
return $request;
}
if ( ! ( $version = wp_remote_retrieve_body( $request ) ) || is_wp_error( $version ) ) {
return ! $version ? new WP_Error( sprintf( __( 'Empty version for item: %s', 'fw' ), $set['item'] ) ) : $version;
}
return $version;
}
/**
* @param array $set - manifest keys.
* @param string $version Requested version to download
* @param string $wp_filesystem_download_directory Allocated temporary empty directory
* @param string $title Used in messages
*
* @return string|WP_Error Path to the downloaded directory
*/
private function download( $set, $version, $wp_filesystem_download_directory, $title ) {
/** @var WP_Filesystem_Base $wp_filesystem */
global $wp_filesystem;
$error_id = 'fw_ext_update_custom_download_zip';
$request = wp_remote_post(
$set['remote'],
array(
'timeout' => $this->download_timeout,
'body' => json_encode( array_merge( $set, array( 'pull' => 'zip' ) ) )
)
);
if ( is_wp_error( $request ) ) {
return $request;
}
if ( ! ( $body = wp_remote_retrieve_body( $request ) ) || is_wp_error( $body ) ) {
return ! $body ? new WP_Error( $error_id, sprintf( esc_html__( 'Empty zip body for item: %s', 'fw' ), $title ) ) : $body;
}
// Try to extract error if server returned json with key error. If not then is an archive zip.
if ( ( $error = json_decode( $body, true ) ) && isset( $error['error'] ) ) {
return new WP_Error( $error_id, $error['error'] );
}
$zip_path = $wp_filesystem_download_directory . '/temp.zip';
// save zip to file
if ( ! $wp_filesystem->put_contents( $zip_path, $body ) ) {
return new WP_Error( $error_id, sprintf( esc_html__( 'Cannot save %s zip.', 'fw' ), $title ) );
}
$unzip_result = unzip_file( FW_WP_Filesystem::filesystem_path_to_real_path( $zip_path ), $wp_filesystem_download_directory );
if ( is_wp_error( $unzip_result ) ) {
return $unzip_result;
}
// remove zip file
if ( ! $wp_filesystem->delete( $zip_path, false, 'f' ) ) {
return new WP_Error( $error_id, sprintf( esc_html__( 'Cannot remove %s zip.', 'fw' ), $title ) );
}
$unzipped_dir_files = $wp_filesystem->dirlist( $wp_filesystem_download_directory );
if ( ! $unzipped_dir_files ) {
return new WP_Error( $error_id, esc_html__( 'Cannot access the unzipped directory files.', 'fw' ) );
}
/**
* get first found directory
* (if everything worked well, there should be only one directory)
*/
foreach ( $unzipped_dir_files as $file ) {
if ( $file['type'] == 'd' ) {
return $wp_filesystem_download_directory . '/' . $file['name'];
}
}
return new WP_Error( $error_id, sprintf( esc_html__( 'The unzipped %s directory not found.', 'fw' ), $title ) );
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_framework_latest_version( $force_check ) {
return false;
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_theme_latest_version( $force_check ) {
$manifest = $this->get_clean_theme_manifest();
if ( empty( $manifest['remote'] ) ) {
return false;
}
return $this->get_latest_version( $force_check, $manifest );
}
/**
* {@inheritdoc}
* @internal
*/
public function _download_theme( $version, $wp_filesystem_download_directory ) {
return $this->download( $this->get_clean_theme_manifest(), $version, $wp_filesystem_download_directory, esc_html__( 'Theme', 'fw' ) );
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_extension_latest_version( FW_Extension $extension, $force_check ) {
if ( ! $extension->manifest->get( 'remote' ) ) {
return false;
}
return $this->get_latest_version( $force_check, $this->data_manifest( $extension->manifest->get_manifest(), 'extension', $extension->get_name() ) );
}
/**
* {@inheritdoc}
* @internal
*/
public function _download_extension( FW_Extension $extension, $version, $wp_filesystem_download_directory ) {
return $this->download(
$this->data_manifest( $extension->manifest->get_manifest(), 'extension', $extension->get_name() ),
$version,
$wp_filesystem_download_directory,
sprintf( esc_html__( '%s extension', 'fw' ), $extension->manifest->get_name() )
);
}
public function data_manifest( $manifest, $type, $id ) {
return array_merge( $manifest, array( 'type' => $type, 'item' => $id ) );
}
public function get_clean_theme_manifest() {
if ( ! ( $manifest_file = fw_get_template_customizations_directory( '/theme/manifest.php' ) ) || ! is_file( $manifest_file ) ) {
return array();
}
include $manifest_file;
if ( isset( $manifest ) ) {
$theme_id = isset( $manifest['id'] ) ? $manifest['id'] : '';
return $this->data_manifest( $manifest, 'theme', $theme_id );
}
return array();
}
}

View File

@@ -0,0 +1,5 @@
<?php defined( 'FW' ) or die();
$manifest = array();
$manifest['standalone'] = true;

View File

@@ -0,0 +1,433 @@
<?php if ( ! defined( 'FW' ) ) {
die( 'Forbidden' );
}
/**
* Github Update
*
* Add {'github_update' => 'user/repo'} to your manifest and this extension will handle it
*/
class FW_Extension_Github_Update extends FW_Ext_Update_Service {
/**
* Handle framework, theme and extensions that has this key in manifest
* @var string
*/
private $manifest_key = 'github_update';
/**
* Check if manifest key format is correct 'user/repo'
* @var string
*/
private $manifest_key_regex = '/^([^\s\/]+)\/([^\s\/]+)$/';
/**
* How long to cache server responses - 12 hours
* @var int seconds
*/
private $transient_expiration = 43200;
private $download_timeout = 300;
/**
* Used when there is internet connection problems
* To prevent site being blocked on every refresh, this fake version will be cached in the transient
* @var string
*/
private $fake_latest_version = '0.0.0';
/**
* @internal
*/
protected function _init() {}
/**
* @param string $append '/foo/bar'
*
* @return string
*/
private function get_github_api_url( $append ) {
return apply_filters( 'fw_github_api_url', 'https://api.github.com' ) . $append;
}
private function fetch_latest_version( $user_slash_repo ) {
/**
* If at least one request failed, do not do any other requests, to prevent site being blocked on every refresh.
* This may happen on localhost when develop your theme and you have no internet connection.
* Then this method will return a fake '0.0.0' version, it will be cached by the transient
* and will not bother you until the transient will expire, then a new request will be made.
* @var bool
*/
static $no_internet_connection = false;
if ( $no_internet_connection ) {
return $this->fake_latest_version;
}
$http = new WP_Http();
$response = $http->get(
$this->get_github_api_url( '/repos/' . $user_slash_repo . '/releases/latest' )
);
unset( $http );
if ( is_wp_error( $response ) ) {
if ( $response->get_error_code() === 'http_request_failed' ) {
$no_internet_connection = true;
}
return $response;
}
if ( ( $response_code = intval( wp_remote_retrieve_response_code( $response ) ) ) !== 200 ) {
if ( $response_code === 403 ) {
$json_response = json_decode( $response['body'], true );
if ( $json_response ) {
return new WP_Error(
'fw_ext_update_github_fetch_releases_failed',
__( 'Github error:', 'fw' ) . ' ' . $json_response['message']
);
}
}
if ( $response_code ) {
return new WP_Error(
'fw_ext_update_github_fetch_releases_failed',
sprintf(
__( 'Failed to access Github repository "%s" releases. (Response code: %d)', 'fw' ),
$user_slash_repo, $response_code
)
);
} else {
return new WP_Error(
'fw_ext_update_github_fetch_releases_failed',
sprintf(
__( 'Failed to access Github repository "%s" releases.', 'fw' ),
$user_slash_repo
)
);
}
}
$release = json_decode( $response['body'], true );
unset( $response );
if ( empty( $release ) ) {
return new WP_Error(
'fw_ext_update_github_fetch_no_releases',
sprintf( __( 'No releases found in repository "%s".', 'fw' ), $user_slash_repo )
);
}
return $release['tag_name'];
}
/**
* Get repository latest release version
*
* @param string $user_slash_repo Github 'user/repo'
* @param bool $force_check Bypass cache
* @param string $title Used in messages
*
* @return string|WP_Error
*/
private function get_latest_version( $user_slash_repo, $force_check, $title ) {
if ( ! preg_match( $this->manifest_key_regex, $user_slash_repo ) ) {
return new WP_Error( 'fw_ext_update_github_manifest_invalid',
sprintf(
__( '%s manifest has invalid "github_update" parameter. Please use "user/repo" format.', 'fw' ),
$title
)
);
}
$transient_id = 'fw_ext_upd_gh_fw'; // the length must be 45 characters or less
if ( $force_check ) {
delete_site_transient( $transient_id );
$cache = array();
} else {
$cache = get_site_transient( $transient_id );
if ( $cache === false ) {
$cache = array();
} elseif ( isset( $cache[ $user_slash_repo ] ) ) {
return $cache[ $user_slash_repo ];
}
}
$latest_version = $this->fetch_latest_version( $user_slash_repo );
if ( empty( $latest_version ) ) {
return new WP_Error(
'fw_ext_update_github_failed_fetch_latest_version',
sprintf(
__( 'Failed to fetch %s latest version from github "%s".', 'fw' ),
$title, $user_slash_repo
)
);
}
if ( is_wp_error( $latest_version ) && is_admin() ) {
/**
* Internet connection problems or Github API requests limit reached.
* Cache fake version to prevent requests to Github API on every refresh.
*/
$cache = array_merge( $cache, array( $user_slash_repo => $this->fake_latest_version ) );
/**
* Show the error to the user because it is not visible elsewhere
*/
FW_Flash_Messages::add(
'fw_ext_github_update_error',
$latest_version->get_error_message(),
'error'
);
} else {
$cache = array_merge( $cache, array( $user_slash_repo => $latest_version ) );
}
set_site_transient(
$transient_id,
$cache,
$this->transient_expiration
);
return $latest_version;
}
/**
* @param string $user_slash_repo Github 'user/repo'
* @param string $version Requested version to download
* @param string $wp_filesystem_download_directory Allocated temporary empty directory
* @param string $title Used in messages
*
* @return string|WP_Error Path to the downloaded directory
*/
private function download( $user_slash_repo, $version, $wp_filesystem_download_directory, $title ) {
$http = new WP_Http();
$response = $http->get(
$this->get_github_api_url( '/repos/' . $user_slash_repo . '/releases/tags/' . $version )
);
unset( $http );
$response_code = intval( wp_remote_retrieve_response_code( $response ) );
if ( $response_code !== 200 ) {
if ( $response_code === 403 ) {
$json_response = json_decode( $response['body'], true );
if ( $json_response ) {
return new WP_Error(
'fw_ext_update_github_download_releases_failed',
__( 'Github error:', 'fw' ) . ' ' . $json_response['message']
);
}
}
if ( $response_code ) {
return new WP_Error(
'fw_ext_update_github_download_releases_failed',
sprintf(
__( 'Failed to access Github repository "%s" releases. (Response code: %d)', 'fw' ),
$user_slash_repo, $response_code
)
);
} else {
return new WP_Error(
'fw_ext_update_github_download_releases_failed',
sprintf(
__( 'Failed to access Github repository "%s" releases.', 'fw' ),
$user_slash_repo
)
);
}
}
$release = json_decode( $response['body'], true );
unset( $response );
if ( empty( $release ) ) {
return new WP_Error(
'fw_ext_update_github_download_no_release',
sprintf(
__( '%s github repository "%s" does not have the "%s" release.', 'fw' ),
$title, $user_slash_repo, $version
)
);
}
$http = new WP_Http();
$response = $http->request(
'https://github.com/' . $user_slash_repo . '/archive/' . $release['tag_name'] . '.zip',
array(
'timeout' => $this->download_timeout,
)
);
unset( $http );
if ( intval( wp_remote_retrieve_response_code( $response ) ) !== 200 ) {
return new WP_Error(
'fw_ext_update_github_download_failed',
sprintf( __( 'Cannot download %s zip.', 'fw' ), $title )
);
}
/** @var WP_Filesystem_Base $wp_filesystem */
global $wp_filesystem;
$zip_path = $wp_filesystem_download_directory . '/temp.zip';
// save zip to file
if ( ! $wp_filesystem->put_contents( $zip_path, $response['body'] ) ) {
return new WP_Error(
'fw_ext_update_github_save_download_failed',
sprintf( __( 'Cannot save %s zip.', 'fw' ), $title )
);
}
unset( $response );
$unzip_result = unzip_file(
FW_WP_Filesystem::filesystem_path_to_real_path( $zip_path ),
$wp_filesystem_download_directory
);
if ( is_wp_error( $unzip_result ) ) {
return $unzip_result;
}
// remove zip file
if ( ! $wp_filesystem->delete( $zip_path, false, 'f' ) ) {
return new WP_Error(
'fw_ext_update_github_remove_downloaded_zip_failed',
sprintf( __( 'Cannot remove %s zip.', 'fw' ), $title )
);
}
$unzipped_dir_files = $wp_filesystem->dirlist( $wp_filesystem_download_directory );
if ( ! $unzipped_dir_files ) {
return new WP_Error(
'fw_ext_update_github_unzipped_dir_fail',
__( 'Cannot access the unzipped directory files.', 'fw' )
);
}
/**
* get first found directory
* (if everything worked well, there should be only one directory)
*/
foreach ( $unzipped_dir_files as $file ) {
if ( $file['type'] == 'd' ) {
return $wp_filesystem_download_directory . '/' . $file['name'];
}
}
return new WP_Error(
'fw_ext_update_github_unzipped_dir_not_found',
sprintf( __( 'The unzipped %s directory not found.', 'fw' ), $title )
);
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_framework_latest_version( $force_check ) {
$user_slash_repo = fw()->manifest->get( $this->manifest_key );
if ( empty( $user_slash_repo ) ) {
return false;
}
return $this->get_latest_version(
$user_slash_repo,
$force_check,
__( 'Framework', 'fw' )
);
}
/**
* {@inheritdoc}
* @internal
*/
public function _download_framework( $version, $wp_filesystem_download_directory ) {
return $this->download(
fw()->manifest->get( $this->manifest_key ),
$version,
$wp_filesystem_download_directory,
__( 'Framework', 'fw' )
);
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_theme_latest_version( $force_check ) {
$user_slash_repo = fw()->theme->manifest->get( $this->manifest_key );
if ( empty( $user_slash_repo ) ) {
return false;
}
return $this->get_latest_version(
$user_slash_repo,
$force_check,
__( 'Theme', 'fw' )
);
}
/**
* {@inheritdoc}
* @internal
*/
public function _download_theme( $version, $wp_filesystem_download_directory ) {
return $this->download(
fw()->theme->manifest->get( $this->manifest_key ),
$version,
$wp_filesystem_download_directory,
__( 'Theme', 'fw' )
);
}
/**
* {@inheritdoc}
* @internal
*/
public function _get_extension_latest_version( FW_Extension $extension, $force_check ) {
$user_slash_repo = $extension->manifest->get( $this->manifest_key );
if ( empty( $user_slash_repo ) ) {
return false;
}
return $this->get_latest_version(
$user_slash_repo,
$force_check,
sprintf( __( '%s extension', 'fw' ), $extension->manifest->get_name() )
);
}
/**
* {@inheritdoc}
* @internal
*/
public function _download_extension( FW_Extension $extension, $version, $wp_filesystem_download_directory ) {
return $this->download(
$extension->manifest->get( $this->manifest_key ),
$version,
$wp_filesystem_download_directory,
sprintf( __( '%s extension', 'fw' ), $extension->manifest->get_name() )
);
}
}

View File

@@ -0,0 +1,5 @@
<?php if (!defined('FW')) die('Forbidden');
$manifest = array();
$manifest['standalone'] = true;

View File

@@ -0,0 +1,128 @@
<?php if (!defined('FW')) die('Forbidden');
/**
* Display extensions with updates on the Update Page
*/
class _FW_Ext_Update_Extensions_List_Table extends WP_List_Table
{
private $items_pre_page = 1000;
private $total_items = null;
private $_extensions = array();
private $_table_columns = array();
private $_table_columns_count = 0;
public function __construct($args)
{
parent::__construct(array(
'screen' => 'fw-ext-update-extensions-update'
));
$this->_extensions = $args['extensions'];
$this->_table_columns = array(
'cb' => '<input type="checkbox" />',
'details' => fw_html_tag(
'a',
array(
'href' => '#',
'onclick' => "jQuery(this).closest('tr').find('input[type=\"checkbox\"]:first').trigger('click'); return false;"
),
__('Select All', 'fw')
),
);
$this->_table_columns_count = count($this->_table_columns);
}
public function get_columns()
{
return $this->_table_columns;
}
public function prepare_items()
{
if ($this->total_items !== null) {
return;
}
$this->total_items = count($this->_extensions);
$this->set_pagination_args(array(
'total_items' => $this->total_items,
'per_page' => $this->items_pre_page,
));
$page_num = $this->get_pagenum();
$offset = ($page_num - 1) * $this->items_pre_page;
/**
* Prepare items for output
*/
foreach ($this->_extensions as $ext_name => $ext_update) {
$extension = fw()->extensions->get($ext_name);
if (is_wp_error($ext_update)) {
$this->items[] = array(
'cb' => '<input type="checkbox" disabled />',
'details' =>
'<p>'.
'<strong>'. fw_htmlspecialchars($extension->manifest->get_name()) .'</strong>'.
'<br/>'.
'<span class="wp-ui-text-notification">'. $ext_update->get_error_message() .'</span>'.
'</p>',
);
} else {
$this->items[] = array(
'cb' => '<input type="checkbox" name="extensions['. esc_attr($ext_name) .']" />',
'details' =>
'<p>'.
'<strong>'. fw_htmlspecialchars($extension->manifest->get_name()) .'</strong>'.
'<br/>'.
sprintf(
__('You have version %s installed. Update to %s.', 'fw'),
$extension->manifest->get_version(), fw_htmlspecialchars($ext_update['fixed_latest_version'])
).
'</p>',
);
}
}
}
public function has_items()
{
$this->prepare_items();
return $this->total_items;
}
/**
* (override parent)
*/
function single_row($item)
{
static $row_class = '';
$row_class = ( $row_class == '' ? ' class="alternate"' : '' );
echo '<tr' . $row_class . '>';
echo $this->single_row_columns( $item );
echo '</tr>';
}
protected function column_cb($item)
{
echo $item['cb'];
}
protected function column_default($item, $column_name)
{
echo $item[$column_name];
}
function no_items()
{
_e('No Extensions for update.', 'fw');
}
}

View File

@@ -0,0 +1,36 @@
<?php if (!defined('FW')) die('Forbidden');
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
class _FW_Ext_Update_Extensions_Upgrader_Skin extends WP_Upgrader_Skin
{
public function after()
{
$update_actions = array(
'updates_page' => fw_html_tag(
'a',
array(
'href' => self_admin_url('update-core.php'),
'title' => __('Go to updates page', 'fw'),
'target' => '_parent',
),
__('Return to Updates page', 'fw')
)
);
/**
* Filter the list of action links available following extensions update.
* @param array $update_actions Array of plugin action links.
*/
$update_actions = apply_filters('fw_ext_update_extensions_complete_actions', $update_actions);
if (!empty($update_actions)) {
$this->feedback(implode(' | ', (array)$update_actions));
}
}
public function decrement_extension_update_count($extension_name)
{
$this->decrement_update_count('fw:extension:'. $extension_name);
}
}

View File

@@ -0,0 +1,33 @@
<?php if (!defined('FW')) die('Forbidden');
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
class _FW_Ext_Update_Framework_Upgrader_Skin extends WP_Upgrader_Skin
{
public function after()
{
$this->decrement_update_count('fw');
$update_actions = array(
'updates_page' => fw_html_tag(
'a',
array(
'href' => self_admin_url('update-core.php'),
'title' => __('Go to updates page', 'fw'),
'target' => '_parent',
),
__('Return to Updates page', 'fw')
)
);
/**
* Filter the list of action links available following framework update.
* @param array $update_actions Array of plugin action links.
*/
$update_actions = apply_filters('fw_ext_update_framework_complete_actions', $update_actions);
if (!empty($update_actions)) {
$this->feedback(implode(' | ', (array)$update_actions));
}
}
}

View File

@@ -0,0 +1,33 @@
<?php if (!defined('FW')) die('Forbidden');
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
class _FW_Ext_Update_Theme_Upgrader_Skin extends WP_Upgrader_Skin
{
public function after()
{
$this->decrement_update_count('fw:theme');
$update_actions = array(
'updates_page' => fw_html_tag(
'a',
array(
'href' => self_admin_url('update-core.php'),
'title' => __('Go to updates page', 'fw'),
'target' => '_parent',
),
__('Return to Updates page', 'fw')
)
);
/**
* Filter the list of action links available following theme update.
* @param array $update_actions Array of plugin action links.
*/
$update_actions = apply_filters('fw_ext_update_theme_complete_actions', $update_actions);
if (!empty($update_actions)) {
$this->feedback(implode(' | ', (array)$update_actions));
}
}
}

View File

@@ -0,0 +1,105 @@
<?php if (!defined('FW')) die('Forbidden');
/**
* Extend this class if you want to create a new update service
*/
abstract class FW_Ext_Update_Service extends FW_Extension
{
/**
* Return latest version of the framework if this service supports framework update
*
* @param bool $force_check Check now, do not use cache
* @return string|false|WP_Error
* false Does not know how to work with extension.
* WP_Error Knows how to work with it, but there is an error
* string Everything is ok, here is latest version
*
* @internal
*/
public function _get_framework_latest_version($force_check)
{
return false;
}
/**
* Download (and extract) framework files
*
* ! Work with global $wp_filesystem; Do not use base php filesystem functions
*
* @param $version Version to download
* @param string $wp_filesystem_download_directory Empty directory offered for download files in it
* @return string|false|WP_Error Path to WP Filesystem directory with downloaded (and extracted) files
*
* @internal
*/
public function _download_framework($version, $wp_filesystem_download_directory)
{
return false;
}
/**
* Return latest version of the theme if this service supports theme update
*
* @param bool $force_check Check now, do not use cache
* @return string|false|WP_Error
* false Does not know how to work with extension.
* WP_Error Knows how to work with it, but there is an error
* string Everything is ok, here is latest version
*
* @internal
*/
public function _get_theme_latest_version($force_check)
{
return false;
}
/**
* Download (and extract) theme files
*
* ! Work with global $wp_filesystem; Do not use base php filesystem functions
*
* @param $version Version to download
* @param string $wp_filesystem_download_directory Empty directory offered for download files in it
* @return string|false|WP_Error Path to WP Filesystem directory with downloaded (and extracted) files
*
* @internal
*/
public function _download_theme($version, $wp_filesystem_download_directory)
{
return false;
}
/**
* Return latest version of the extension if this service supports extension update
*
* @param FW_Extension $extension
* @param bool $force_check Check now, do not use cache
* @return string|false|WP_Error
* false Does not know how to work with extension.
* WP_Error Knows how to work with it, but there is an error
* string Everything is ok, here is latest version
*
* @internal
*/
public function _get_extension_latest_version(FW_Extension $extension, $force_check)
{
return false;
}
/**
* Download (and extract) extension
*
* ! Work with global $wp_filesystem; Do not use base php filesystem functions
*
* @param FW_Extension $extension
* @param $version Version to download
* @param string $wp_filesystem_download_directory Empty directory offered for download files in it
* @return string|false|WP_Error Path to WP Filesystem directory with downloaded (and extracted) files
*
* @internal
*/
public function _download_extension(FW_Extension $extension, $version, $wp_filesystem_download_directory)
{
return false;
}
}

View File

@@ -0,0 +1,10 @@
<?php if (!defined('FW')) die('Forbidden');
$manifest = array();
$manifest['name'] = __('Update', 'fw');
$manifest['description'] = __('Keep you framework, extensions and theme up to date.', 'fw');
$manifest['standalone'] = true;
$manifest['version'] = '1.0.12';
$manifest['github_update'] = 'ThemeFuse/Unyson-Update-Extension';

View File

@@ -0,0 +1,14 @@
<?php if (!defined('FW')) die('Forbidden');
$extension = fw()->extensions->get('update');
if (fw_current_screen_match(array('only' => array(array('id' => 'update-core'))))) {
// Include only on update page
wp_enqueue_style(
'fw-ext-'. $extension->get_name() .'-update-page',
$extension->get_declared_URI('/static/css/admin-update-page.css'),
array(),
$extension->manifest->get_version()
);
}

View File

@@ -0,0 +1,3 @@
#fw-ext-update-extensions .tablenav {
display: none;
}

View File

@@ -0,0 +1,118 @@
<?php defined( 'FW' ) or die(); ?>
<?php if ( $updates['framework'] !== false ): ?>
<div id="fw-ext-update-framework">
<a name="fw-framework"></a>
<h3><?php _e( 'Framework', 'fw' ) ?></h3>
<?php if ( empty( $updates['framework'] ) ): ?>
<p><?php echo sprintf( __( 'You have the latest version of %s.', 'fw' ), fw()->manifest->get_name() ) ?></p>
<?php else: ?>
<?php if ( is_wp_error( $updates['framework'] ) ): ?>
<p class="wp-ui-text-notification"><?php echo $updates['framework']->get_error_message() ?></p>
<?php else: ?>
<form id="fw-ext-update-framework" method="post" action="update-core.php?action=fw-update-framework">
<p>
<?php
_e( sprintf( 'You have version %s installed. Update to %s.',
fw()->manifest->get_version(),
$updates['framework']['fixed_latest_version']
), 'fw' )
?>
</p>
<?php wp_nonce_field( - 1, '_nonce_fw_ext_update_framework' ); ?>
<p>
<input class="button" type="submit" value="<?php echo esc_attr( __( 'Update Framework', 'fw' ) ); ?>" name="update">
</p>
</form>
<?php endif; ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if ( $updates['theme'] !== false ): ?>
<div id="fw-ext-update-theme">
<a name="fw-theme"></a>
<h3><?php $theme = wp_get_theme();
_e( sprintf( '%s Theme', ( is_child_theme() ? $theme->parent()->get( 'Name' ) : $theme->get( 'Name' ) ) ), 'fw' ) ?></h3>
<?php if ( empty( $updates['theme'] ) ): ?>
<p><?php _e( 'Your theme is up to date.', 'fw' ) ?></p>
<?php else: ?>
<?php if ( is_wp_error( $updates['theme'] ) ): ?>
<p class="wp-ui-text-notification"><?php echo $updates['theme']->get_error_message() ?></p>
<?php else: ?>
<form id="fw-ext-update-theme" method="post" action="<?php echo esc_url( add_query_arg( 'action', 'fw-update-theme', $form_action ) ); ?>">
<p>
<?php
_e( sprintf( 'You have version %s installed. Update to %s.',
fw()->theme->manifest->get_version(),
$updates['theme']['fixed_latest_version']
), 'fw' )
?>
</p>
<?php wp_nonce_field( - 1, '_nonce_fw_ext_update_theme' ); ?>
<p>
<input class="button" type="submit" value="<?php echo esc_attr( __( 'Update Theme', 'fw' ) ) ?>" name="update">
</p>
</form>
<?php endif; ?>
<?php endif; ?>
</div>
<?php endif; ?>
<div id="fw-ext-update-extensions">
<a name="fw-extensions"></a>
<h3><?php echo sprintf( __( '%s Extensions', 'fw' ), fw()->manifest->get_name() ); ?></h3>
<?php if ( empty( $updates['extensions'] ) ): ?>
<p><?php echo sprintf( __( 'You have the latest version of %s Extensions.', 'fw' ), fw()->manifest->get_name() ); ?></p>
<?php else: ?>
<?php
$one_update_mode = fw()->extensions->get( 'update' )->ext_as_one_update();
foreach ( $updates['extensions'] as $extension ) {
if ( is_wp_error( $extension ) ) {
/**
* Cancel the "One update mode" and display all extensions list table with details
* if at least one extension has an error that needs to be visible
*/
$one_update_mode = false;
break;
}
}
?>
<form id="fw-ext-update-extensions" method="post" action="<?php echo esc_url( add_query_arg( 'action', 'fw-update-extensions', $form_action ) ); ?>">
<div class="fw-ext-update-extensions-form-detailed"<?php echo( $one_update_mode ? ' style="display: none;"' : '' ); ?>>
<p>
<input class="button" type="submit" value="<?php echo esc_attr( __( 'Update Extensions', 'fw' ) ) ?>" name="update">
</p>
<?php
if ( ! class_exists( '_FW_Ext_Update_Extensions_List_Table' ) ) {
fw_include_file_isolated(
fw()->extensions->get( 'update' )->get_declared_path( '/includes/classes/class--fw-ext-update-extensions-list-table.php' )
);
}
$list_table = new _FW_Ext_Update_Extensions_List_Table( array( 'extensions' => $updates['extensions'] ) );
$list_table->display();
?>
<?php wp_nonce_field( - 1, '_nonce_fw_ext_update_extensions' ); ?>
<p>
<input class="button" type="submit" value="<?php echo esc_attr( esc_html__( 'Update Extensions', 'fw' ) ); ?>" name="update">
</p>
</div>
<?php if ( $one_update_mode ) : ?>
<div class="fw-ext-update-extensions-form-simple">
<p style="color:#d54e21;"><?php _e( 'New extensions updates available.', 'fw' ); ?></p>
<p><input class="button" type="submit"
value="<?php echo esc_attr( __( 'Update Extensions', 'fw' ) ) ?>" name="update"></p>
<script type="text/javascript">
jQuery( function ( $ ) {
$( 'form#fw-ext-update-extensions' ).on( 'submit', function () {
$( this ).find( '.check-column input[type="checkbox"]' ).prop( 'checked', true );
} );
} );
</script>
</div>
<?php endif; ?>
</form>
<?php endif; ?>
</div>