mirror of
https://gh.wpcy.net/https://github.com/Anyape/updatepulse-server.git
synced 2026-07-14 20:46:49 +08:00
1956 lines
58 KiB
PHP
1956 lines
58 KiB
PHP
<?php
|
|
|
|
namespace Anyape\UpdatePulse\Server\Manager;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Exit if accessed directly
|
|
}
|
|
|
|
use WP_Error;
|
|
use ZipArchive;
|
|
use RecursiveIteratorIterator;
|
|
use RecursiveDirectoryIterator;
|
|
use Exception;
|
|
use Anyape\UpdatePulse\Package_Parser\Parser as Package_Parser;
|
|
use Anyape\UpdatePulse\Server\Server\Update\Zip_Metadata_Parser;
|
|
use Anyape\UpdatePulse\Server\Server\Update\Cache;
|
|
use Anyape\UpdatePulse\Server\Server\Update\Package;
|
|
use Anyape\UpdatePulse\Server\Manager\Data_Manager;
|
|
use Anyape\UpdatePulse\Server\API\Package_API;
|
|
use Anyape\UpdatePulse\Server\Table\Packages_Table;
|
|
use Anyape\UpdatePulse\Server\Scheduler\Scheduler;
|
|
use Anyape\Utils\Utils;
|
|
|
|
/**
|
|
* Package Manager class
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
class Package_Manager {
|
|
|
|
/**
|
|
* Default logs maximum size in MB
|
|
*
|
|
* @var int
|
|
* @since 1.0.0
|
|
*/
|
|
const DEFAULT_LOGS_MAX_SIZE = 10;
|
|
/**
|
|
* Default cache maximum size in MB
|
|
*
|
|
* @var int
|
|
* @since 1.0.0
|
|
*/
|
|
const DEFAULT_CACHE_MAX_SIZE = 100;
|
|
/**
|
|
* Default archive maximum size in MB
|
|
*
|
|
* @var int
|
|
* @since 1.0.0
|
|
*/
|
|
const DEFAULT_ARCHIVE_MAX_SIZE = 20;
|
|
|
|
/**
|
|
* Filesystem clean types
|
|
*
|
|
* Types of filesystem data that can be cleaned.
|
|
*
|
|
* @var array
|
|
* @since 1.0.0
|
|
*/
|
|
public static $filesystem_clean_types = array(
|
|
'cache',
|
|
'logs',
|
|
);
|
|
|
|
/**
|
|
* Instance
|
|
*
|
|
* @var Package_Manager|null
|
|
* @since 1.0.0
|
|
*/
|
|
protected static $instance;
|
|
|
|
/**
|
|
* Packages table
|
|
*
|
|
* @var Packages_Table|null
|
|
* @since 1.0.0
|
|
*/
|
|
protected $packages_table;
|
|
/**
|
|
* Package rows
|
|
*
|
|
* @var array
|
|
* @since 1.0.0
|
|
*/
|
|
protected $rows = array();
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param boolean $init_hooks Whether to initialize WordPress hooks.
|
|
* @since 1.0.0
|
|
*/
|
|
public function __construct( $init_hooks = false ) {
|
|
|
|
if ( $init_hooks ) {
|
|
add_action( 'admin_init', array( $this, 'admin_init' ), 10, 0 );
|
|
add_action( 'admin_menu', array( $this, 'admin_menu' ), 10, 0 );
|
|
add_action( 'wp_ajax_upserv_force_clean', array( $this, 'force_clean' ), 10, 0 );
|
|
add_action( 'wp_ajax_upserv_register_package_from_vcs', array( $this, 'register_package_from_vcs' ), 10, 0 );
|
|
add_action( 'wp_ajax_upserv_manual_package_upload', array( $this, 'manual_package_upload' ), 10, 0 );
|
|
add_action( 'load-toplevel_page_upserv-page', array( $this, 'add_page_options' ), 10, 0 );
|
|
add_action( 'upserv_package_manager_pre_delete_package', array( $this, 'upserv_package_manager_pre_delete_package' ), 10, 1 );
|
|
add_action( 'upserv_package_manager_deleted_package', array( $this, 'upserv_package_manager_deleted_package' ), 20, 1 );
|
|
add_action( 'upserv_download_remote_package_aborted', array( $this, 'upserv_download_remote_package_aborted' ), 10, 3 );
|
|
|
|
add_filter( 'upserv_admin_scripts', array( $this, 'upserv_admin_scripts' ), 10, 1 );
|
|
add_filter( 'upserv_admin_styles', array( $this, 'upserv_admin_styles' ), 10, 1 );
|
|
add_filter( 'upserv_admin_tab_links', array( $this, 'upserv_admin_tab_links' ), 10, 1 );
|
|
add_filter( 'upserv_admin_tab_states', array( $this, 'upserv_admin_tab_states' ), 10, 2 );
|
|
add_filter( 'set-screen-option', array( $this, 'set_page_options' ), 10, 3 );
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
* Public methods
|
|
*******************************************************************/
|
|
|
|
// WordPress hooks ---------------------------------------------
|
|
|
|
/**
|
|
* Admin init hook
|
|
*
|
|
* Handles admin initialization tasks.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function admin_init() {
|
|
|
|
if ( ! is_admin() || wp_doing_ajax() || wp_doing_cron() ) {
|
|
return;
|
|
}
|
|
|
|
$this->packages_table = new Packages_Table( $this );
|
|
|
|
if (
|
|
! (
|
|
isset( $_REQUEST['_wpnonce'] ) &&
|
|
wp_verify_nonce(
|
|
sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ),
|
|
$this->packages_table->nonce_action
|
|
)
|
|
) &&
|
|
! (
|
|
isset( $_REQUEST['linknonce'] ) &&
|
|
wp_verify_nonce(
|
|
sanitize_text_field( wp_unslash( $_REQUEST['linknonce'] ), ),
|
|
'linknonce'
|
|
)
|
|
)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
$page = ! empty( $_REQUEST['page'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ) : false;
|
|
|
|
if ( 'upserv-page' !== $page ) {
|
|
return;
|
|
}
|
|
|
|
$packages = false;
|
|
$action = false;
|
|
$delete_all_packages = ! empty( $_REQUEST['upserv_delete_all_packages'] ) ? true : false;
|
|
|
|
if ( ! empty( $_REQUEST['packages'] ) ) {
|
|
|
|
if ( is_array( $_REQUEST['packages'] ) ) {
|
|
$packages = array_map( 'sanitize_text_field', wp_unslash( $_REQUEST['packages'] ) );
|
|
} else {
|
|
$packages = sanitize_text_field( wp_unslash( $_REQUEST['packages'] ) );
|
|
}
|
|
}
|
|
|
|
if ( ! empty( $_REQUEST['action'] ) && -1 !== intval( $_REQUEST['action'] ) ) {
|
|
$action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) );
|
|
} elseif ( ! empty( $_REQUEST['action2'] ) && -1 !== intval( $_REQUEST['action2'] ) ) {
|
|
$action = sanitize_text_field( wp_unslash( $_REQUEST['action2'] ) );
|
|
}
|
|
|
|
if ( $packages && 'download' === $action ) {
|
|
$error = $this->download_packages_bulk( is_array( $packages ) ? $packages : array( $packages ) );
|
|
|
|
if ( $error ) {
|
|
$this->packages_table->bulk_action_error = $error;
|
|
}
|
|
} elseif ( $packages && 'delete' === $action ) {
|
|
$this->delete_packages_bulk( is_array( $packages ) ? $packages : array( $packages ) );
|
|
} elseif ( $delete_all_packages ) {
|
|
$this->delete_packages_bulk();
|
|
} else {
|
|
/**
|
|
* Fired when a request action that is not handled by default is received.
|
|
*
|
|
* @param string $action The action received in the request.
|
|
* @param array|string|false $packages The packages involved in the action.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_udpdate_manager_request_action', $action, $packages );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Admin menu hook
|
|
*
|
|
* Adds the plugin page to the admin menu.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function admin_menu() {
|
|
$page_title = __( 'UpdatePulse Server', 'updatepulse-server' );
|
|
$capability = 'manage_options';
|
|
$function = array( $this, 'plugin_page' );
|
|
$menu_title = __( 'Packages Overview', 'updatepulse-server' );
|
|
|
|
add_submenu_page( 'upserv-page', $page_title, $menu_title, $capability, 'upserv-page', $function );
|
|
}
|
|
|
|
/**
|
|
* Add page options
|
|
*
|
|
* Adds screen options for the plugin page.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function add_page_options() {
|
|
$option = 'per_page';
|
|
$args = array(
|
|
'label' => __( 'Packages per page', 'updatepulse-server' ),
|
|
'default' => 10,
|
|
'option' => 'packages_per_page',
|
|
);
|
|
|
|
add_screen_option( $option, $args );
|
|
}
|
|
|
|
/**
|
|
* Enqueue admin scripts
|
|
*
|
|
* Enqueues admin scripts for the plugin page.
|
|
*
|
|
* @param array $scripts Existing scripts.
|
|
* @return array Modified scripts.
|
|
* @since 1.0.0
|
|
*/
|
|
public function upserv_admin_scripts( $scripts ) {
|
|
$page = ! empty( $_REQUEST['page'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
|
|
if ( 'upserv-page' !== $page ) {
|
|
return $scripts;
|
|
}
|
|
|
|
$l10n = array(
|
|
'invalidFileFormat' => __( 'Error: invalid file format.', 'updatepulse-server' ),
|
|
'invalidFileSize' => __( 'Error: invalid file size.', 'updatepulse-server' ),
|
|
'invalidFileName' => __( 'Error: invalid file name.', 'updatepulse-server' ),
|
|
'invalidFile' => __( 'Error: invalid file', 'updatepulse-server' ),
|
|
'deletePackageConfirm' => __( 'Are you sure you want to delete this package?', 'updatepulse-server' ),
|
|
);
|
|
|
|
if ( upserv_get_option( 'use_vcs' ) ) {
|
|
$l10n['deletePackagesConfirm'] = array(
|
|
__( 'You are about to delete all the packages from this server.', 'updatepulse-server' ),
|
|
__( 'If a Webhook is configured, the packages will be re-downloaded from the VCS when it is triggered.', 'updatepulse-server' ),
|
|
__( 'Other packages provided by the VCS will need to be registered again.', 'updatepulse-server' ),
|
|
__( 'All packages manually uploaded will be permanently deleted.', 'updatepulse-server' ),
|
|
"\n",
|
|
__( 'Are you sure you want to do this?', 'updatepulse-server' ),
|
|
);
|
|
} else {
|
|
$l10n['deletePackagesConfirm'] = array(
|
|
__( 'You are about to delete all the packages from this server.', 'updatepulse-server' ),
|
|
__( 'All packages will be permanently deleted.', 'updatepulse-server' ),
|
|
"\n",
|
|
__( 'Are you sure you want to do this?', 'updatepulse-server' ),
|
|
);
|
|
}
|
|
|
|
$scripts['package'] = array(
|
|
'path' => UPSERV_PLUGIN_PATH . 'js/admin/package' . upserv_assets_suffix() . '.js',
|
|
'uri' => UPSERV_PLUGIN_URL . 'js/admin/package' . upserv_assets_suffix() . '.js',
|
|
'deps' => array( 'jquery' ),
|
|
'params' => array(
|
|
'debug' => (bool) ( constant( 'WP_DEBUG' ) ),
|
|
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
|
),
|
|
/**
|
|
* Filter the internationalization strings passed to the frontend scripts.
|
|
*
|
|
* @param array $l10n The internationalization strings passed to the frontend scripts.
|
|
* @param string $handle The handle of the script.
|
|
* @return array The filtered internationalization strings.
|
|
* @since 1.0.0
|
|
*/
|
|
'l10n' => apply_filters( 'upserv_scripts_l10n', $l10n, 'package' ),
|
|
);
|
|
|
|
return $scripts;
|
|
}
|
|
|
|
/**
|
|
* Enqueue admin styles
|
|
*
|
|
* Enqueues admin styles for the plugin page.
|
|
*
|
|
* @param array $styles Existing styles.
|
|
* @return array Modified styles.
|
|
* @since 1.0.0
|
|
*/
|
|
public function upserv_admin_styles( $styles ) {
|
|
$styles['package'] = array(
|
|
'path' => UPSERV_PLUGIN_PATH . 'css/admin/package' . upserv_assets_suffix() . '.css',
|
|
'uri' => UPSERV_PLUGIN_URL . 'css/admin/package' . upserv_assets_suffix() . '.css',
|
|
);
|
|
|
|
return $styles;
|
|
}
|
|
|
|
/**
|
|
* Set page options
|
|
*
|
|
* Sets screen options for the plugin page.
|
|
*
|
|
* @param mixed $status Screen option status.
|
|
* @param string $option Screen option name.
|
|
* @param mixed $value Screen option value.
|
|
* @return mixed Screen option value.
|
|
* @since 1.0.0
|
|
*/
|
|
public function set_page_options( $status, $option, $value ) {
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Admin tab links
|
|
*
|
|
* Adds tab links for the plugin page.
|
|
*
|
|
* @param array $links Existing tab links.
|
|
* @return array Modified tab links.
|
|
* @since 1.0.0
|
|
*/
|
|
public function upserv_admin_tab_links( $links ) {
|
|
$links['main'] = array(
|
|
admin_url( 'admin.php?page=upserv-page' ),
|
|
'<i class="fa-solid fa-cubes"></i>' . __( 'Packages Overview', 'updatepulse-server' ),
|
|
);
|
|
|
|
return $links;
|
|
}
|
|
|
|
/**
|
|
* Admin tab states
|
|
*
|
|
* Sets tab states for the plugin page.
|
|
*
|
|
* @param array $states Existing tab states.
|
|
* @param string $page Current page.
|
|
* @return array Modified tab states.
|
|
* @since 1.0.0
|
|
*/
|
|
public function upserv_admin_tab_states( $states, $page ) {
|
|
$states['main'] = 'upserv-page' === $page;
|
|
|
|
return $states;
|
|
}
|
|
|
|
/**
|
|
* Force clean
|
|
*
|
|
* Forces a cleanup of the specified filesystem data type.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function force_clean() {
|
|
$result = false;
|
|
$type = false;
|
|
|
|
if (
|
|
isset( $_REQUEST['nonce'] ) &&
|
|
wp_verify_nonce(
|
|
sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ),
|
|
'upserv_plugin_options'
|
|
)
|
|
) {
|
|
$type = sanitize_text_field( wp_unslash( filter_input( INPUT_POST, 'type' ) ) );
|
|
|
|
if ( in_array( $type, self::$filesystem_clean_types, true ) ) {
|
|
$result = Data_Manager::maybe_cleanup( $type, true );
|
|
}
|
|
}
|
|
|
|
if ( $result && $type ) {
|
|
wp_send_json_success( array( 'btnVal' => __( 'Force Clean', 'updatepulse-server' ) . ' (' . self::get_dir_size_mb( $type ) . ')' ) );
|
|
} elseif ( in_array( $type, self::$filesystem_clean_types, true ) ) {
|
|
$error = new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - check the directory is writable', 'updatepulse-server' )
|
|
);
|
|
|
|
wp_send_json_error( $error );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Download remote package aborted
|
|
*
|
|
* Handles the event when a remote package download is aborted.
|
|
*
|
|
* @param string $safe_slug Safe slug of the package.
|
|
* @param string $type Type of the package.
|
|
* @param array $info Additional information.
|
|
* @since 1.0.0
|
|
*/
|
|
public function upserv_download_remote_package_aborted( $safe_slug, $type, $info ) {
|
|
wp_cache_set( 'upserv_download_remote_package_aborted', $info, 'updatepulse-server' );
|
|
}
|
|
|
|
/**
|
|
* Register package from VCS
|
|
*
|
|
* Registers a package from a Version Control System (VCS).
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function register_package_from_vcs() {
|
|
$result = false;
|
|
$error = false;
|
|
$slug = 'N/A';
|
|
|
|
if (
|
|
isset( $_REQUEST['nonce'] ) &&
|
|
wp_verify_nonce(
|
|
sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ),
|
|
'upserv_plugin_options'
|
|
)
|
|
) {
|
|
$slug = sanitize_text_field( wp_unslash( filter_input( INPUT_POST, 'slug' ) ) );
|
|
$vcs_key = sanitize_text_field( wp_unslash( filter_input( INPUT_POST, 'vcs_key' ) ) );
|
|
|
|
if ( $slug && $vcs_key ) {
|
|
$vcs_config = upserv_get_option( 'vcs/' . $vcs_key, false );
|
|
$meta = upserv_get_package_metadata( $slug );
|
|
$meta['vcs_key'] = hash( 'sha256', trailingslashit( $vcs_config['url'] ) . '|' . $vcs_config['branch'] );
|
|
|
|
upserv_set_package_metadata( $slug, $meta );
|
|
|
|
$result = upserv_download_remote_package( $slug, null );
|
|
|
|
if ( wp_cache_get( 'upserv_download_remote_package_aborted', 'updatepulse-server' ) ) {
|
|
$vcs_config = upserv_get_package_vcs_config( $slug );
|
|
$error = isset( $vcs_config['filter_packages'] ) && $vcs_config['filter_packages'] ?
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not get remote package. The package was filtered out because it is not linked to this server.', 'updatepulse-server' )
|
|
) :
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not get remote package. The package was found and is valid, but the download was aborted. Please check the package is satisfying the requirements for this server.', 'updatepulse-server' )
|
|
);
|
|
|
|
wp_cache_delete( 'upserv_download_remote_package_aborted', 'updatepulse-server' );
|
|
}
|
|
|
|
if ( ! $result || isset( $result['abort_request'] ) ) {
|
|
upserv_set_package_metadata( $slug, null );
|
|
}
|
|
} else {
|
|
$error = new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not get remote package. Missing data - please reload the page and try again.', 'updatepulse-server' )
|
|
);
|
|
}
|
|
} else {
|
|
$error = new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not get remote package. The page has expired - please reload the page and try again.', 'updatepulse-server' )
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Fired after a package has been registered from a VCS.
|
|
*
|
|
* @param bool $result Whether the package was successfully registered.
|
|
* @param string $slug The slug of the registered package.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_registered_package_from_vcs', $result, $slug );
|
|
|
|
if ( ! $error && $result ) {
|
|
wp_send_json_success();
|
|
} else {
|
|
|
|
if ( ! $error ) {
|
|
$error = new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not get remote package. Check if a repository with this slug exists and has a valid file structure.', 'updatepulse-server' )
|
|
);
|
|
}
|
|
|
|
wp_send_json_error( $error );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Manual package upload
|
|
*
|
|
* Handles manual package uploads.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function manual_package_upload() {
|
|
$result = false;
|
|
$slug = 'N/A';
|
|
$type = 'N/A';
|
|
$parsed_info = false;
|
|
$error_text = __( 'Reload the page and try again.', 'updatepulse-server' );
|
|
|
|
if (
|
|
! isset( $_REQUEST['nonce'] ) ||
|
|
! wp_verify_nonce(
|
|
sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ),
|
|
'upserv_plugin_options'
|
|
)
|
|
) {
|
|
wp_send_json_error(
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not upload the package. The page has expired - please reload the page and try again.', 'updatepulse-server' )
|
|
)
|
|
);
|
|
}
|
|
|
|
WP_Filesystem();
|
|
|
|
global $wp_filesystem;
|
|
|
|
if ( ! $wp_filesystem ) {
|
|
return;
|
|
}
|
|
|
|
$files = $_FILES; // phpcs:ignore WordPress.Security.NonceVerification.Missing
|
|
|
|
$sanitized_part = function ( $part ) {
|
|
|
|
if ( 'application/zip' === $part ) {
|
|
return $part;
|
|
}
|
|
|
|
$part = realpath( $part );
|
|
$part_array = $part ? explode( DIRECTORY_SEPARATOR, $part ) : false;
|
|
|
|
if ( ! empty( $part_array ) ) {
|
|
|
|
foreach ( $part_array as $key => $_part ) {
|
|
|
|
if ( empty( $_part ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( 0 === $key && strlen( $_part ) === 2 && ':' === substr( $_part, 1, 1 ) ) {
|
|
continue;
|
|
}
|
|
|
|
$part_array[ $key ] = sanitize_file_name( $_part );
|
|
}
|
|
|
|
$part = implode( DIRECTORY_SEPARATOR, $part_array );
|
|
}
|
|
|
|
return $part;
|
|
};
|
|
|
|
if (
|
|
! is_array( $files ) ||
|
|
! isset(
|
|
$files['package'],
|
|
$files['package']['tmp_name'],
|
|
$files['package']['name'],
|
|
$files['package']['type']
|
|
) ||
|
|
$sanitized_part( $files['package']['type'] ) !== $files['package']['type'] ||
|
|
$sanitized_part( $files['package']['tmp_name'] ) !== $files['package']['tmp_name'] ||
|
|
sanitize_file_name( $files['package']['name'] ) !== $files['package']['name']
|
|
) {
|
|
/**
|
|
* Fired after an attempt to manually upload a package.
|
|
*
|
|
* @param bool $result Whether the upload was successful.
|
|
* @param string $type The package type.
|
|
* @param string $slug The package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_did_manual_upload_package', $result, $type, $slug );
|
|
wp_send_json_error(
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not upload the package. ', 'updatepulse-server' )
|
|
. "\n\n" .
|
|
__( 'Invalid file data.', 'updatepulse-server' )
|
|
)
|
|
);
|
|
}
|
|
|
|
$valid_archive_formats = array(
|
|
'multipart/x-zip',
|
|
'application/zip',
|
|
'application/zip-compressed',
|
|
'application/x-zip-compressed',
|
|
);
|
|
|
|
if ( ! in_array( $files['package']['type'], $valid_archive_formats, true ) ) {
|
|
$wp_filesystem->delete( $files['package']['tmp_name'] );
|
|
/**
|
|
* Fired after an attempt to manually upload a package.
|
|
*
|
|
* @param bool $result Whether the upload was successful.
|
|
* @param string $type The package type.
|
|
* @param string $slug The package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_did_manual_upload_package', $result, $type, $slug );
|
|
wp_send_json_error(
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not upload the package. ', 'updatepulse-server' )
|
|
. "\n\n" .
|
|
__( 'Make sure the uploaded file is a zip archive.', 'updatepulse-server' )
|
|
)
|
|
);
|
|
}
|
|
|
|
if ( isset( $files['package']['error'] ) && 0 !== abs( intval( $files['package']['error'] ) ) ) {
|
|
|
|
switch ( $files['package']['error'] ) {
|
|
case UPLOAD_ERR_INI_SIZE:
|
|
$error_text = __( 'The uploaded file exceeds the upload_max_filesize directive in php.ini.', 'updatepulse-server' );
|
|
|
|
break;
|
|
case UPLOAD_ERR_FORM_SIZE:
|
|
$error_text = __( 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', 'updatepulse-server' );
|
|
|
|
break;
|
|
case UPLOAD_ERR_PARTIAL:
|
|
$error_text = __( 'The uploaded file was only partially uploaded.', 'updatepulse-server' );
|
|
|
|
break;
|
|
case UPLOAD_ERR_NO_FILE:
|
|
$error_text = __( 'No file was uploaded.', 'updatepulse-server' );
|
|
|
|
break;
|
|
case UPLOAD_ERR_NO_TMP_DIR:
|
|
$error_text = __( 'Missing a temporary folder.', 'updatepulse-server' );
|
|
|
|
break;
|
|
case UPLOAD_ERR_CANT_WRITE:
|
|
$error_text = __( 'Failed to write file to disk.', 'updatepulse-server' );
|
|
|
|
break;
|
|
case UPLOAD_ERR_EXTENSION:
|
|
$error_text = __( 'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.', 'updatepulse-server' );
|
|
|
|
break;
|
|
default:
|
|
$error_text = __( 'An unknown file upload error occurred.', 'updatepulse-server' );
|
|
|
|
break;
|
|
}
|
|
|
|
$wp_filesystem->delete( $files['package']['tmp_name'] );
|
|
/**
|
|
* Fired after an attempt to manually upload a package.
|
|
*
|
|
* @param bool $result Whether the upload was successful.
|
|
* @param string $type The package type.
|
|
* @param string $slug The package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_did_manual_upload_package', $result, $type, $slug );
|
|
wp_send_json_error(
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not upload the package. ', 'updatepulse-server' ) . "\n\n" . $error_text
|
|
)
|
|
);
|
|
}
|
|
|
|
if ( 0 >= $files['package']['size'] ) {
|
|
$wp_filesystem->delete( $files['package']['tmp_name'] );
|
|
/**
|
|
* Fired after an attempt to manually upload a package.
|
|
*
|
|
* @param bool $result Whether the upload was successful.
|
|
* @param string $type The package type.
|
|
* @param string $slug The package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_did_manual_upload_package', $result, $type, $slug );
|
|
wp_send_json_error(
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not upload the package. ', 'updatepulse-server' )
|
|
. "\n\n" .
|
|
__( 'Make sure the uploaded file is not empty.', 'updatepulse-server' )
|
|
)
|
|
);
|
|
}
|
|
|
|
$parsed_info = Package_Parser::parse_package( $files['package']['tmp_name'], true );
|
|
|
|
if ( ! $parsed_info ) {
|
|
$wp_filesystem->delete( $files['package']['tmp_name'] );
|
|
/**
|
|
* Fired after an attempt to manually upload a package.
|
|
*
|
|
* @param bool $result Whether the upload was successful.
|
|
* @param string $type The package type.
|
|
* @param string $slug The package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_did_manual_upload_package', $result, $type, $slug );
|
|
wp_send_json_error(
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not upload the package. ', 'updatepulse-server' )
|
|
. "\n\n" .
|
|
__( 'The uploaded package is not a valid Generic, Theme or Plugin package.', 'updatepulse-server' )
|
|
)
|
|
);
|
|
}
|
|
|
|
$filename = $files['package']['name'];
|
|
$slug = str_replace( '.zip', '', $filename );
|
|
$type = ucfirst( $parsed_info['type'] );
|
|
$dest = Data_Manager::get_data_dir( 'packages' ) . $filename;
|
|
$result = $wp_filesystem->move( $files['package']['tmp_name'], $dest, true );
|
|
|
|
/**
|
|
* Fired after an attempt to manually upload a package.
|
|
*
|
|
* @param bool $result Whether the upload was successful.
|
|
* @param string $type The package type.
|
|
* @param string $slug The package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_did_manual_upload_package', $result, $type, $slug );
|
|
|
|
if ( $result ) {
|
|
upserv_whitelist_package( $slug );
|
|
|
|
$meta = $this->get_package_metadata( $slug );
|
|
$meta['origin'] = 'manual';
|
|
|
|
$this->set_package_metadata( $slug, $meta );
|
|
wp_send_json_success();
|
|
} else {
|
|
$wp_filesystem->delete( $files['package']['tmp_name'] );
|
|
wp_send_json_error(
|
|
new WP_Error(
|
|
__METHOD__,
|
|
__( 'Error - could not upload the package. ', 'updatepulse-server' )
|
|
. "\n\n" .
|
|
__( 'The uploaded package could not be moved to the packages directory.', 'updatepulse-server' )
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pre delete package hook
|
|
*
|
|
* Handles tasks before a package is deleted.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
public function upserv_package_manager_pre_delete_package( $package_slug ) {
|
|
$info = upserv_get_package_info( $package_slug, false );
|
|
|
|
wp_cache_set( 'upserv_package_manager_pre_delete_package_info', $info, 'updatepulse-server' );
|
|
}
|
|
|
|
/**
|
|
* Package deleted hook
|
|
*
|
|
* Handles tasks after a package is deleted.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
public function upserv_package_manager_deleted_package( $package_slug ) {
|
|
$package_info = wp_cache_get( 'upserv_package_manager_pre_delete_package_info', 'updatepulse-server' );
|
|
|
|
if ( $package_info ) {
|
|
$payload = array(
|
|
'event' => 'package_deleted',
|
|
// translators: %1$s is the package type, %2$s is the package slug
|
|
'description' => sprintf( esc_html__( 'The package of type `%1$s` and slug `%2$s` has been deleted on UpdatePulse Server', 'updatepulse-server' ), $package_info['type'], $package_slug ),
|
|
'content' => $package_info,
|
|
);
|
|
|
|
upserv_schedule_webhook( $payload, 'package' );
|
|
}
|
|
}
|
|
|
|
// Misc. -------------------------------------------------------
|
|
|
|
/**
|
|
* Get instance
|
|
*
|
|
* Returns the singleton instance of the class.
|
|
*
|
|
* @return Package_Manager
|
|
* @since 1.0.0
|
|
*/
|
|
public static function get_instance() {
|
|
|
|
if ( ! self::$instance ) {
|
|
self::$instance = new self();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Plugin page
|
|
*
|
|
* Renders the plugin page.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function plugin_page() {
|
|
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_die( __( 'Sorry, you are not allowed to access this page.' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
wp_cache_set( 'settings_notice', $this->plugin_options_handler(), 'updatepulse-server' );
|
|
|
|
$use_vcs = upserv_get_option( 'use_vcs', 0 );
|
|
$vcs_configs = upserv_get_option( 'vcs', array() );
|
|
$vcs_options = array();
|
|
|
|
if ( ! empty( $vcs_configs ) ) {
|
|
|
|
foreach ( $vcs_configs as $key => $vcs_c ) {
|
|
$url = untrailingslashit( $vcs_c['url'] );
|
|
$branch = $vcs_c['branch'];
|
|
$name = $vcs_c['self_hosted'] ?
|
|
__( 'Self-hosted', 'updatepulse-server' ) :
|
|
upserv_get_vcs_name( $vcs_c['type'] );
|
|
$identifier = substr( $url, strrpos( $url, '/' ) + 1 );
|
|
$name = $name . ' - ' . $identifier . ' - ' . $branch;
|
|
$vcs_options[ $key ] = $name;
|
|
}
|
|
}
|
|
|
|
$package_rows = $this->get_batch_package_info();
|
|
$options = array(
|
|
'use_vcs' => $use_vcs,
|
|
'archive_max_size' => upserv_get_option( 'limits/archive_max_size', self::DEFAULT_ARCHIVE_MAX_SIZE ),
|
|
'cache_max_size' => upserv_get_option( 'limits/cache_max_size', self::DEFAULT_CACHE_MAX_SIZE ),
|
|
'logs_max_size' => upserv_get_option( 'limits/logs_max_size', self::DEFAULT_LOGS_MAX_SIZE ),
|
|
);
|
|
|
|
$this->packages_table->set_rows( $package_rows );
|
|
$this->packages_table->prepare_items();
|
|
|
|
upserv_get_admin_template(
|
|
'plugin-packages-page.php',
|
|
array(
|
|
'packages_table' => $this->packages_table,
|
|
'cache_size' => self::get_dir_size_mb( 'cache' ),
|
|
'logs_size' => self::get_dir_size_mb( 'logs' ),
|
|
'package_rows' => $package_rows,
|
|
'packages_dir' => Data_Manager::get_data_dir( 'packages' ),
|
|
'vcs_options' => $vcs_options,
|
|
'options' => $options,
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Delete packages in bulk
|
|
*
|
|
* Deletes multiple packages in bulk.
|
|
*
|
|
* @param array $package_slugs Package slugs to delete.
|
|
* @return array|false Deleted package slugs or false if no packages were deleted.
|
|
* @since 1.0.0
|
|
*/
|
|
public function delete_packages_bulk( $package_slugs = array() ) {
|
|
$package_directory = Data_Manager::get_data_dir( 'packages' );
|
|
$package_paths = glob( trailingslashit( $package_directory ) . '*.zip' );
|
|
$package_names = array();
|
|
$deleted_package_slugs = array();
|
|
$delete_all = false;
|
|
|
|
/**
|
|
* Filter the package paths to be deleted in bulk.
|
|
*
|
|
* @param array $package_paths Paths to package files.
|
|
* @param array $package_slugs Package slugs to delete.
|
|
* @return array The filtered package paths.
|
|
* @since 1.0.0
|
|
*/
|
|
$package_paths = apply_filters(
|
|
'upserv_delete_packages_bulk_paths',
|
|
$package_paths,
|
|
$package_slugs
|
|
);
|
|
|
|
if ( ! empty( $package_paths ) ) {
|
|
|
|
if ( empty( $package_slugs ) ) {
|
|
$delete_all = true;
|
|
}
|
|
|
|
foreach ( $package_paths as $package_path ) {
|
|
$package_name = basename( $package_path );
|
|
$package_names[] = $package_name;
|
|
|
|
if ( $delete_all ) {
|
|
$package_slugs[] = str_replace( '.zip', '', $package_name );
|
|
}
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
$url = home_url( '/updatepulse-server-update-api/' );
|
|
$filter_args = array( 'url' => $url );
|
|
/**
|
|
* Filter the class name used for the update server.
|
|
*
|
|
* @param string $class_name The default class name.
|
|
* @param mixed $null Null value.
|
|
* @param array $filter_args Arguments for the filter.
|
|
* @return string The filtered class name.
|
|
* @since 1.0.0
|
|
*/
|
|
$_class_name = apply_filters(
|
|
'upserv_server_class_name',
|
|
str_replace( 'Manager', 'Server\\Update', __NAMESPACE__ ) . '\\Update_Server',
|
|
null,
|
|
$filter_args
|
|
);
|
|
/**
|
|
* Filter the constructor arguments for the update server.
|
|
*
|
|
* @param array $args Constructor arguments.
|
|
* @param mixed $null Null value.
|
|
* @param array $filter_args Arguments for the filter.
|
|
* @return array The filtered constructor arguments.
|
|
* @since 1.0.0
|
|
*/
|
|
$args = apply_filters(
|
|
'upserv_server_constructor_args',
|
|
array( $url, Data_Manager::get_data_dir(), '', '', '', '', false ),
|
|
null,
|
|
$filter_args
|
|
);
|
|
$update_server = new $_class_name( ...$args );
|
|
|
|
/**
|
|
* Fired before deleting multiple packages in bulk.
|
|
*
|
|
* @param array $package_slugs Slugs of packages about to be deleted.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_package_manager_pre_delete_packages_bulk', $package_slugs );
|
|
|
|
foreach ( $package_slugs as $slug ) {
|
|
$package_name = $slug . '.zip';
|
|
|
|
if ( in_array( $package_name, $package_names, true ) ) {
|
|
/**
|
|
* Fired before a package is deleted.
|
|
*
|
|
* @param string $slug The slug of the package to be deleted.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_package_manager_pre_delete_package', $slug );
|
|
|
|
$result = $update_server->remove_package( $slug );
|
|
|
|
/**
|
|
* Fired after a package has been deleted.
|
|
*
|
|
* @param string $slug The slug of the deleted package.
|
|
* @param bool $result Whether the package was successfully deleted.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_package_manager_deleted_package', $slug, $result );
|
|
|
|
if ( $result ) {
|
|
$scheduled_hook = 'upserv_check_remote_' . $slug;
|
|
|
|
upserv_unwhitelist_package( $slug );
|
|
upserv_set_package_metadata( $slug, null );
|
|
Scheduler::get_instance()->unschedule_all_actions( $scheduled_hook );
|
|
|
|
/**
|
|
* Fired after a remote check schedule event has been unscheduled for a package.
|
|
* Fired during client update API request.
|
|
*
|
|
* @param string $package_slug The slug of the package for which a remote check event has been unscheduled
|
|
* @param string $scheduled_hook The remote check event hook that has been unscheduled
|
|
*/
|
|
do_action( 'upserv_cleared_check_remote_schedule', $slug, $scheduled_hook );
|
|
|
|
$deleted_package_slugs[] = $slug;
|
|
|
|
unset( $this->rows[ $slug ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! empty( $deleted_package_slugs ) ) {
|
|
/**
|
|
* Fired after multiple packages have been deleted in bulk.
|
|
*
|
|
* @param array $deleted_package_slugs Slugs of packages that were deleted.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_package_manager_deleted_packages_bulk', $deleted_package_slugs );
|
|
}
|
|
|
|
return empty( $deleted_package_slugs ) ? false : $deleted_package_slugs;
|
|
}
|
|
|
|
/**
|
|
* Download packages in bulk
|
|
*
|
|
* Downloads multiple packages in bulk.
|
|
*
|
|
* @param array $package_slugs Package slugs to download.
|
|
* @return void
|
|
* @since 1.0.0
|
|
*/
|
|
public function download_packages_bulk( $package_slugs ) {
|
|
WP_Filesystem();
|
|
|
|
global $wp_filesystem;
|
|
|
|
if ( ! $wp_filesystem ) {
|
|
return null;
|
|
}
|
|
|
|
$package_directory = Data_Manager::get_data_dir( 'packages' );
|
|
$total_size = 0;
|
|
$max_archive_size = upserv_get_option( 'limits/archive_max_size', self::DEFAULT_ARCHIVE_MAX_SIZE );
|
|
|
|
if ( 1 === count( $package_slugs ) ) {
|
|
$archive_name = reset( $package_slugs );
|
|
$archive_path = trailingslashit( $package_directory ) . $archive_name . '.zip';
|
|
|
|
/**
|
|
* Fired before packages are downloaded.
|
|
*
|
|
* @param string $archive_name The name of the archive.
|
|
* @param string $archive_path The path to the archive.
|
|
* @param array $package_slugs The slugs of the packages to download.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_before_packages_download', $archive_name, $archive_path, $package_slugs );
|
|
|
|
foreach ( $package_slugs as $package_slug ) {
|
|
$total_size += filesize( trailingslashit( $package_directory ) . $package_slug . '.zip' );
|
|
}
|
|
|
|
if ( $max_archive_size < ( (float) ( $total_size / UPSERV_MB_TO_B ) ) ) {
|
|
$this->packages_table->bulk_action_error = 'max_file_size_exceeded';
|
|
|
|
return;
|
|
}
|
|
|
|
$this->trigger_packages_download( $archive_name, $archive_path );
|
|
|
|
return;
|
|
}
|
|
|
|
$temp_directory = Data_Manager::get_data_dir( 'tmp' );
|
|
$archive_name = 'archive-' . time();
|
|
$archive_path = trailingslashit( $temp_directory ) . $archive_name . '.zip';
|
|
|
|
/**
|
|
* Fired before packages are repackaged for download.
|
|
*
|
|
* @param string $archive_name The name of the archive.
|
|
* @param string $archive_path The path to the archive.
|
|
* @param array $package_slugs The slugs of the packages to repackage.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_before_packages_download_repack', $archive_name, $archive_path, $package_slugs );
|
|
|
|
foreach ( $package_slugs as $package_slug ) {
|
|
$total_size += filesize( trailingslashit( $package_directory ) . $package_slug . '.zip' );
|
|
}
|
|
|
|
if ( $max_archive_size < ( (float) ( $total_size / UPSERV_MB_TO_B ) ) ) {
|
|
$this->packages_table->bulk_action_error = 'max_file_size_exceeded';
|
|
|
|
return;
|
|
}
|
|
|
|
$zip = new ZipArchive();
|
|
|
|
if ( ! $zip->open( $archive_path, ZIPARCHIVE::CREATE ) ) {
|
|
return false;
|
|
}
|
|
|
|
foreach ( $package_slugs as $package_slug ) {
|
|
$file = trailingslashit( $package_directory ) . $package_slug . '.zip';
|
|
|
|
if ( is_file( $file ) ) {
|
|
$zip->addFromString( $package_slug . '.zip', @file_get_contents( $file ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.PHP.NoSilencedErrors.Discouraged
|
|
}
|
|
}
|
|
|
|
$zip->close();
|
|
|
|
/**
|
|
* Fired before packages are downloaded.
|
|
*
|
|
* @param string $archive_name The name of the archive.
|
|
* @param string $archive_path The path to the archive.
|
|
* @param array $package_slugs The slugs of the packages to download.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_before_packages_download', $archive_name, $archive_path, $package_slugs );
|
|
$this->trigger_packages_download( $archive_name, $archive_path );
|
|
}
|
|
|
|
/**
|
|
* Trigger packages download
|
|
*
|
|
* Triggers the download of the specified archive.
|
|
*
|
|
* @param string $archive_name Archive name.
|
|
* @param string $archive_path Archive path.
|
|
* @param boolean $exit_or_die Whether to exit or die after download.
|
|
* @since 1.0.0
|
|
*/
|
|
public function trigger_packages_download( $archive_name, $archive_path, $exit_or_die = true ) {
|
|
|
|
if ( ! empty( $archive_path ) && is_file( $archive_path ) && ! empty( $archive_name ) ) {
|
|
|
|
if ( ini_get( 'zlib.output_compression' ) ) {
|
|
@ini_set( 'zlib.output_compression', 'Off' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.PHP.IniSet.Risky
|
|
}
|
|
|
|
$md5 = md5_file( $archive_path );
|
|
|
|
if ( $md5 ) {
|
|
header( 'Content-MD5: ' . $md5 );
|
|
}
|
|
|
|
// Add Content-Digest or Repr-Digest header based on requested priority
|
|
$digest_requested = ! empty( $_SERVER['HTTP_WANT_DIGEST'] ) && is_string( $_SERVER['HTTP_WANT_DIGEST'] ) ?
|
|
sanitize_text_field( wp_unslash( $_SERVER['HTTP_WANT_DIGEST'] ) ) :
|
|
( ! empty( $_SERVER['HTTP_WANT_REPR_DIGEST'] ) && is_string( $_SERVER['HTTP_WANT_REPR_DIGEST'] ) ?
|
|
sanitize_text_field( wp_unslash( $_SERVER['HTTP_WANT_REPR_DIGEST'] ) ) :
|
|
'sha-256=1'
|
|
);
|
|
$digest_field = ! empty( $_SERVER['HTTP_WANT_DIGEST'] ) ?
|
|
'Content-Digest' :
|
|
( ! empty( $_SERVER['HTTP_WANT_REPR_DIGEST'] ) ? 'Repr-Digest' : 'Content-Digest' );
|
|
|
|
if ( $digest_requested && $digest_field ) {
|
|
$digests = array_map(
|
|
function ( $digest ) {
|
|
|
|
if ( strpos( $digest, '=' ) === false ) {
|
|
return array( '', 0 ); // Return default value if '=' delimiter is missing
|
|
}
|
|
|
|
$parts = explode( '=', strtolower( trim( $digest ) ) );
|
|
|
|
return array(
|
|
$parts[0], // Algorithm
|
|
isset( $parts[1] ) ? (int) $parts[1] : 0, // Priority
|
|
);
|
|
},
|
|
explode( ',', $digest_requested )
|
|
);
|
|
|
|
$sha_digests = array_filter(
|
|
$digests,
|
|
function ( $digest ) {
|
|
return ! empty( $digest[0] ) && str_starts_with( $digest[0], 'sha-' );
|
|
}
|
|
);
|
|
|
|
// Find the digest with the highest priority
|
|
$selected_digest = array_reduce(
|
|
$sha_digests,
|
|
function ( $carry, $item ) {
|
|
return $carry[1] > $item[1] ? $carry : $item;
|
|
},
|
|
array( '', 0 )
|
|
);
|
|
|
|
if ( ! empty( $selected_digest[0] ) ) {
|
|
$digest = str_replace( '-', '', $selected_digest[0] );
|
|
|
|
if ( ! in_array( $digest, hash_algos(), true ) ) {
|
|
$digest = '';
|
|
}
|
|
|
|
$hash = hash_file( $digest, $archive_path );
|
|
|
|
if ( $hash ) {
|
|
$safe_digest = htmlspecialchars( $digest, ENT_QUOTES, 'UTF-8' );
|
|
$safe_hash = htmlspecialchars( $hash, ENT_QUOTES, 'UTF-8' );
|
|
|
|
header( "$digest_field: $safe_digest=$safe_hash" );
|
|
}
|
|
}
|
|
}
|
|
|
|
header( 'Content-Type: application/zip' );
|
|
header( 'Content-Disposition: attachment; filename="' . $archive_name . '.zip"' );
|
|
header( 'Content-Transfer-Encoding: binary' );
|
|
header( 'Content-Length: ' . filesize( $archive_path ) );
|
|
|
|
/**
|
|
* Fired when a packages download is triggered.
|
|
*
|
|
* @param string $archive_name The name of the archive.
|
|
* @param string $archive_path The path to the archive.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_triggered_packages_download', $archive_name, $archive_path );
|
|
|
|
echo @file_get_contents( $archive_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
/**
|
|
* Fired after packages have been downloaded.
|
|
*
|
|
* @param string $archive_name The name of the archive.
|
|
* @param string $archive_path The path to the archive.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_after_packages_download', $archive_name, $archive_path );
|
|
|
|
if ( $exit_or_die ) {
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get package info
|
|
*
|
|
* Retrieves information about a package.
|
|
*
|
|
* @param string $slug Package slug.
|
|
* @return array|false Package information or false if not found.
|
|
* @since 1.0.0
|
|
*/
|
|
public function get_package_info( $slug ) {
|
|
$package_info = wp_cache_get( 'package_info_' . $slug, 'updatepulse-server' );
|
|
|
|
if ( false !== $package_info ) {
|
|
return $package_info;
|
|
}
|
|
|
|
/**
|
|
* Fired when retrieving package information.
|
|
*
|
|
* @param mixed $package_info Package information or false.
|
|
* @param string $slug Package slug.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_get_package_info', $package_info, $slug );
|
|
|
|
if ( has_filter( 'upserv_package_manager_get_package_info' ) ) {
|
|
/**
|
|
* Filter the package information for a specific package.
|
|
*
|
|
* @param mixed $package_info Package information or false.
|
|
* @param string $slug Package slug.
|
|
* @return array The filtered package information.
|
|
* @since 1.0.0
|
|
*/
|
|
$package_info = apply_filters( 'upserv_package_manager_get_package_info', $package_info, $slug );
|
|
} else {
|
|
$package_directory = Data_Manager::get_data_dir( 'packages' );
|
|
|
|
if ( file_exists( $package_directory . $slug . '.zip' ) ) {
|
|
$package = $this->get_package(
|
|
$package_directory . $slug . '.zip',
|
|
$slug
|
|
);
|
|
|
|
if ( $package ) {
|
|
$package_info = $package->get_metadata();
|
|
|
|
if ( ! isset( $package_info['type'] ) ) {
|
|
$package_info['type'] = 'unknown';
|
|
}
|
|
|
|
$file_path = $package_directory . $slug . '.zip';
|
|
$package_info['file_name'] = $slug . '.zip';
|
|
$package_info['file_path'] = $file_path;
|
|
$package_info['file_size'] = $package->get_file_size();
|
|
$package_info['file_last_modified'] = $package->get_last_modified();
|
|
$package_info['etag'] = hash_file( 'md5', $file_path );
|
|
$package_info['digests'] = array(
|
|
'sha1' => hash_file( 'sha1', $file_path ),
|
|
'sha256' => hash_file( 'sha256', $file_path ),
|
|
'sha512' => hash_file( 'sha512', $file_path ),
|
|
'crc32' => hash_file( 'crc32', $file_path ),
|
|
'crc32c' => hash_file( 'crc32c', $file_path ),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
wp_cache_set( 'package_info_' . $slug, $package_info, 'updatepulse-server' );
|
|
|
|
if ( is_array( $package_info ) && ! isset( $package_info['metadata'] ) ) {
|
|
$package_info['metadata'] = $this->get_package_metadata( $slug );
|
|
}
|
|
|
|
/**
|
|
* Filter the package information before returning it.
|
|
*
|
|
* @param array $package_info Package information.
|
|
* @param string $slug Package slug.
|
|
* @return array The filtered package information.
|
|
* @since 1.0.0
|
|
*/
|
|
$package_info = apply_filters( 'upserv_package_manager_package_info', $package_info, $slug );
|
|
|
|
return $package_info;
|
|
}
|
|
|
|
/**
|
|
* Get batch package info
|
|
*
|
|
* Retrieves information about multiple packages.
|
|
*
|
|
* @param string|false $search Search term.
|
|
* @return array Package information.
|
|
* @since 1.0.0
|
|
*/
|
|
public function get_batch_package_info( $search = false ) {
|
|
$packages = wp_cache_get( 'packages', 'updatepulse-server' );
|
|
|
|
if ( false !== $packages ) {
|
|
return empty( $packages ) ? array() : $packages;
|
|
}
|
|
|
|
if ( has_filter( 'upserv_package_manager_get_batch_package_info' ) ) {
|
|
/**
|
|
* Filter the batch package information.
|
|
*
|
|
* @param mixed $packages Package information or false.
|
|
* @param string|false $search Search term.
|
|
* @return array The filtered batch package information.
|
|
* @since 1.0.0
|
|
*/
|
|
$packages = apply_filters( 'upserv_package_manager_get_batch_package_info', $packages, $search );
|
|
wp_cache_set( 'packages', $packages, 'updatepulse-server' );
|
|
|
|
return empty( $packages ) ? array() : $packages;
|
|
}
|
|
|
|
$package_directory = Data_Manager::get_data_dir( 'packages' );
|
|
$packages = array();
|
|
|
|
if ( is_dir( $package_directory ) && ! Package_API::is_doing_api_request() ) {
|
|
$search = isset( $_REQUEST['s'] ) ? // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
trim( sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) ) : // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
$search;
|
|
}
|
|
|
|
$package_paths = is_dir( $package_directory ) ?
|
|
glob( trailingslashit( $package_directory ) . '*.zip' ) :
|
|
array();
|
|
|
|
if ( is_dir( $package_directory ) && ! empty( $package_paths ) ) {
|
|
|
|
foreach ( $package_paths as $package_path ) {
|
|
$package = $this->get_package(
|
|
$package_path,
|
|
str_replace(
|
|
array( trailingslashit( $package_directory ), '.zip' ),
|
|
array( '', '' ),
|
|
$package_path
|
|
)
|
|
);
|
|
|
|
if ( ! $package ) {
|
|
continue;
|
|
}
|
|
|
|
$meta = $package->get_metadata();
|
|
$include = ! $search ? true : (
|
|
$search &&
|
|
(
|
|
false === strpos( strtolower( $meta['name'] ), strtolower( $search ) ) ||
|
|
false === strpos( strtolower( $meta['slug'] ) . '.zip', strtolower( $search ) )
|
|
)
|
|
);
|
|
|
|
/**
|
|
* Filter whether to include a package in the batch info results.
|
|
*
|
|
* @param bool $include Whether to include the package.
|
|
* @param array $meta Package metadata.
|
|
* @return bool The filtered inclusion decision.
|
|
* @since 1.0.0
|
|
*/
|
|
$include = apply_filters( 'upserv_package_info_include', $include, $meta );
|
|
|
|
if ( ! $include ) {
|
|
continue;
|
|
}
|
|
|
|
$slug = $meta['slug'];
|
|
$file_path = $package_directory . $slug . '.zip';
|
|
$packages[ $slug ] = $meta;
|
|
$packages[ $slug ]['metadata'] = $this->get_package_metadata( $slug );
|
|
$packages[ $slug ]['file_name'] = $slug . '.zip';
|
|
$packages[ $slug ]['file_path'] = $package_directory . $slug . '.zip';
|
|
$packages[ $slug ]['file_size'] = $package->get_file_size();
|
|
$packages[ $slug ]['file_last_modified'] = $package->get_last_modified();
|
|
$packages[ $slug ]['etag'] = hash_file( 'md5', $file_path );
|
|
$packages[ $slug ]['digests'] = array(
|
|
'sha1' => hash_file( 'sha1', $file_path ),
|
|
'sha256' => hash_file( 'sha256', $file_path ),
|
|
'sha512' => hash_file( 'sha512', $file_path ),
|
|
'crc32' => hash_file( 'crc32', $file_path ),
|
|
'crc32c' => hash_file( 'crc32c', $file_path ),
|
|
);
|
|
|
|
wp_cache_set( 'package_info_' . $slug, $packages[ $slug ], 'updatepulse-server' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filter the batch package information before returning it.
|
|
*
|
|
* @param array $packages Package information.
|
|
* @param string|false $search Search term.
|
|
* @return array The filtered batch package information.
|
|
* @since 1.0.0
|
|
*/
|
|
$packages = apply_filters( 'upserv_package_manager_batch_package_info', $packages, $search );
|
|
|
|
wp_cache_set( 'packages', $packages, 'updatepulse-server' );
|
|
|
|
if ( empty( $packages ) ) {
|
|
$packages = array();
|
|
}
|
|
|
|
return $packages;
|
|
}
|
|
|
|
/**
|
|
* Check if package is whitelisted
|
|
*
|
|
* Checks if a package is whitelisted.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @return boolean True if whitelisted, false otherwise.
|
|
* @since 1.0.0
|
|
*/
|
|
public function is_package_whitelisted( $package_slug ) {
|
|
|
|
if ( has_filter( 'upserv_is_package_whitelisted' ) ) {
|
|
/**
|
|
* Filter whether a package is whitelisted.
|
|
*
|
|
* @param bool $is_whitelisted Whether the package is whitelisted.
|
|
* @param string $package_slug Package slug.
|
|
* @return bool The filtered whitelisted status.
|
|
* @since 1.0.0
|
|
*/
|
|
return apply_filters( 'upserv_is_package_whitelisted', false, $package_slug );
|
|
}
|
|
|
|
$data = $this->get_package_metadata( $package_slug, false );
|
|
|
|
if (
|
|
isset(
|
|
$data['whitelisted'],
|
|
$data['whitelisted']['local'],
|
|
$data['whitelisted']['local'][0]
|
|
)
|
|
) {
|
|
return (bool) $data['whitelisted']['local'][0];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Whitelist package
|
|
*
|
|
* Whitelists a package.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @return boolean True if successful, false otherwise.
|
|
* @since 1.0.0
|
|
*/
|
|
public function whitelist_package( $package_slug ) {
|
|
$data = $this->get_package_metadata( $package_slug, false );
|
|
|
|
if ( ! isset( $data['whitelisted'] ) ) {
|
|
$data['whitelisted'] = array();
|
|
}
|
|
|
|
if ( has_filter( 'upserv_whitelist_package_data' ) ) {
|
|
/**
|
|
* Filter the data used to whitelist a package.
|
|
*
|
|
* @param array $data Package metadata.
|
|
* @param string $package_slug Package slug.
|
|
* @return array The filtered package metadata.
|
|
* @since 1.0.0
|
|
*/
|
|
$data = apply_filters( 'upserv_whitelist_package_data', $data, $package_slug );
|
|
} else {
|
|
$data['whitelisted']['local'] = array( true, time() );
|
|
}
|
|
|
|
$result = $this->set_package_metadata( $package_slug, $data );
|
|
|
|
/**
|
|
* Fired after a package has been whitelisted.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @param array $data Package metadata.
|
|
* @param bool $result Whether the metadata was successfully updated.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_whitelist_package', $package_slug, $data, $result );
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Unwhitelist package
|
|
*
|
|
* Unwhitelists a package.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @return boolean True if successful, false otherwise.
|
|
* @since 1.0.0
|
|
*/
|
|
public function unwhitelist_package( $package_slug ) {
|
|
$data = $this->get_package_metadata( $package_slug, false );
|
|
|
|
if ( ! isset( $data['whitelisted'] ) ) {
|
|
$data['whitelisted'] = array();
|
|
}
|
|
|
|
if ( has_filter( 'upserv_unwhitelist_package_data' ) ) {
|
|
/**
|
|
* Filter the data used to unwhitelist a package.
|
|
*
|
|
* @param array $data Package metadata.
|
|
* @param string $package_slug Package slug.
|
|
* @return array The filtered package metadata.
|
|
* @since 1.0.0
|
|
*/
|
|
$data = apply_filters( 'upserv_unwhitelist_package_data', $data, $package_slug );
|
|
} else {
|
|
$data['whitelisted']['local'] = array( false, time() );
|
|
}
|
|
|
|
$result = $this->set_package_metadata( $package_slug, $data );
|
|
|
|
/**
|
|
* Fired after a package has been unwhitelisted.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @param bool $result Whether the metadata was successfully updated.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_unwhitelist_package', $package_slug, $result );
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Get package metadata
|
|
*
|
|
* Retrieves metadata for a package.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @param boolean $json_encode Whether to return JSON encoded data.
|
|
* @return array|string Package metadata.
|
|
* @since 1.0.0
|
|
*/
|
|
public function get_package_metadata( $package_slug, $json_encode = false ) {
|
|
$data = wp_cache_get( 'package_metadata_' . $package_slug, 'updatepulse-server' );
|
|
|
|
if ( $data ) {
|
|
return ! $json_encode ? json_decode( $data, true ) : $data;
|
|
}
|
|
|
|
$dir = upserv_get_data_dir( 'metadata' );
|
|
$filename = sanitize_file_name( $package_slug . '.json' );
|
|
$file_path = trailingslashit( $dir ) . $filename;
|
|
$data = '{}';
|
|
|
|
if ( ! has_filter( 'upserv_get_package_metadata' ) && is_file( $file_path ) ) {
|
|
$data = @file_get_contents( $file_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.PHP.NoSilencedErrors.Discouraged
|
|
} elseif ( has_filter( 'upserv_get_package_metadata' ) ) {
|
|
/**
|
|
* Filter the package metadata for a specific package.
|
|
*
|
|
* @param string $data JSON encoded package metadata.
|
|
* @param string $package_slug Package slug.
|
|
* @param bool $json_encode Whether to return JSON encoded data.
|
|
* @return string The filtered package metadata.
|
|
* @since 1.0.0
|
|
*/
|
|
$data = apply_filters( 'upserv_get_package_metadata', $data, $package_slug, $json_encode );
|
|
}
|
|
|
|
wp_cache_set( 'package_metadata_' . $package_slug, $data, 'updatepulse-server' );
|
|
|
|
if ( ! $json_encode ) {
|
|
$data = json_decode( $data, true );
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Set package metadata
|
|
*
|
|
* Sets metadata for a package.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @param array $metadata Package metadata.
|
|
* @return boolean True if successful, false otherwise.
|
|
* @since 1.0.0
|
|
*/
|
|
public function set_package_metadata( $package_slug, $metadata ) {
|
|
WP_Filesystem();
|
|
|
|
global $wp_filesystem;
|
|
|
|
$dir = upserv_get_data_dir( 'metadata' );
|
|
$filename = sanitize_file_name( $package_slug . '.json' );
|
|
$file_path = trailingslashit( $dir ) . $filename;
|
|
$result = false;
|
|
|
|
/**
|
|
* Filter the metadata to be set for a package.
|
|
*
|
|
* @param array $metadata Package metadata.
|
|
* @param string $package_slug Package slug.
|
|
* @return array The filtered package metadata.
|
|
* @since 1.0.0
|
|
*/
|
|
$data = apply_filters( 'upserv_set_package_metadata_data', $metadata, $package_slug );
|
|
|
|
wp_cache_delete( 'package_metadata_' . $package_slug, 'updatepulse-server' );
|
|
|
|
if ( empty( $data ) ) {
|
|
|
|
if ( ! has_filter( 'upserv_did_delete_package_metadata' ) && is_file( $file_path ) ) {
|
|
$result = (bool) $wp_filesystem->delete( $file_path );
|
|
} else {
|
|
/**
|
|
* Filter the result of deleting package metadata.
|
|
*
|
|
* @param bool $result Whether deletion was successful.
|
|
* @param string $package_slug Package slug.
|
|
* @return bool The filtered result.
|
|
* @since 1.0.0
|
|
*/
|
|
$result = apply_filters( 'upserv_did_delete_package_metadata', false, $package_slug );
|
|
}
|
|
|
|
/**
|
|
* Fired after package metadata has been deleted.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @param bool $result Whether the metadata was successfully deleted.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_delete_package_metadata', $package_slug, $result );
|
|
|
|
return $result;
|
|
}
|
|
|
|
$previous = $this->get_package_metadata( $package_slug );
|
|
|
|
wp_cache_delete( 'package_metadata_' . $package_slug, 'updatepulse-server' );
|
|
unset( $previous['previous'] );
|
|
|
|
$data['timestamp'] = time();
|
|
$data['previous'] = $previous;
|
|
|
|
if ( ! has_filter( 'upserv_did_set_package_metadata' ) ) {
|
|
$result = (bool) file_put_contents( // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
|
|
$file_path,
|
|
wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ),
|
|
FS_CHMOD_FILE
|
|
);
|
|
} else {
|
|
/**
|
|
* Filter the result of setting package metadata.
|
|
*
|
|
* @param bool $result Whether the operation was successful.
|
|
* @param string $package_slug Package slug.
|
|
* @param array $data Package metadata.
|
|
* @return bool The filtered result.
|
|
* @since 1.0.0
|
|
*/
|
|
$result = apply_filters( 'upserv_did_set_package_metadata', false, $package_slug, $data );
|
|
}
|
|
|
|
/**
|
|
* Fired after package metadata has been set.
|
|
*
|
|
* @param string $package_slug Package slug.
|
|
* @param array $data Package metadata.
|
|
* @param bool $result Whether the metadata was successfully updated.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_set_package_metadata', $package_slug, $data, $result );
|
|
|
|
return $result;
|
|
}
|
|
|
|
/*******************************************************************
|
|
* Protected methods
|
|
*******************************************************************/
|
|
|
|
/**
|
|
* Get directory size in MB
|
|
*
|
|
* Retrieves the size of the specified directory in MB.
|
|
*
|
|
* @param string $type Directory type.
|
|
* @return string Directory size in MB.
|
|
* @since 1.0.0
|
|
*/
|
|
protected static function get_dir_size_mb( $type ) {
|
|
$result = 'N/A';
|
|
|
|
if ( ! Data_Manager::is_valid_data_dir( $type ) ) {
|
|
return $result;
|
|
}
|
|
|
|
$directory = Data_Manager::get_data_dir( $type );
|
|
$total_size = 0;
|
|
|
|
if ( ! is_dir( $directory ) ) {
|
|
return $result;
|
|
}
|
|
|
|
foreach ( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $directory ) ) as $file ) {
|
|
$total_size += $file->getSize();
|
|
}
|
|
|
|
$size = (float) ( $total_size / UPSERV_MB_TO_B );
|
|
|
|
if ( $size < 0.01 ) {
|
|
$result = '< 0.01 MB';
|
|
} else {
|
|
$result = number_format( $size, 2, '.', '' ) . 'MB';
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Plugin options handler
|
|
*
|
|
* Handles the submission of plugin options.
|
|
*
|
|
* @return array|string Result of the options update.
|
|
* @since 1.0.0
|
|
*/
|
|
protected function plugin_options_handler() {
|
|
$errors = array();
|
|
$result = '';
|
|
$nonce = sanitize_text_field( wp_unslash( filter_input( INPUT_POST, 'upserv_plugin_options_handler_nonce' ) ) );
|
|
|
|
if ( $nonce && ! wp_verify_nonce( $nonce, 'upserv_plugin_options' ) ) {
|
|
$errors['general'] = __( 'There was an error validating the form. It may be outdated. Please reload the page.', 'updatepulse-server' );
|
|
|
|
return $errors;
|
|
} elseif ( ! $nonce ) {
|
|
return $result;
|
|
}
|
|
|
|
$result = __( 'UpdatePulse Server options successfully updated', 'updatepulse-server' );
|
|
$options = $this->get_submitted_options();
|
|
$to_save = array();
|
|
|
|
foreach ( $options as $option_name => $option_info ) {
|
|
$condition = $option_info['value'];
|
|
|
|
if ( isset( $option_info['condition'] ) && 'number' === $option_info['condition'] ) {
|
|
$condition = is_numeric( $option_info['value'] );
|
|
}
|
|
|
|
/**
|
|
* Filter whether to update a package option.
|
|
*
|
|
* @param bool $condition Whether the option should be updated.
|
|
* @param string $option_name Option name.
|
|
* @param array $option_info Option information.
|
|
* @param array $options All submitted options.
|
|
* @return bool The filtered update condition.
|
|
* @since 1.0.0
|
|
*/
|
|
$condition = apply_filters(
|
|
'upserv_package_option_update',
|
|
$condition,
|
|
$option_name,
|
|
$option_info,
|
|
$options
|
|
);
|
|
|
|
if ( $condition && isset( $option_info['path'] ) ) {
|
|
$to_save[ $option_info['path'] ] = $option_info['value'];
|
|
} else {
|
|
$errors[ $option_name ] = sprintf(
|
|
// translators: %1$s is the option display name, %2$s is the condition for update
|
|
__( 'Option %1$s was not updated. Reason: %2$s', 'updatepulse-server' ),
|
|
$option_info['display_name'],
|
|
$option_info['failure_display_message']
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( ! empty( $to_save ) ) {
|
|
$to_update = array();
|
|
|
|
foreach ( $to_save as $path => $value ) {
|
|
$to_update = upserv_set_option( $path, $value );
|
|
}
|
|
|
|
upserv_update_options( $to_update );
|
|
}
|
|
|
|
if ( ! empty( $errors ) ) {
|
|
$result = $errors;
|
|
}
|
|
|
|
/**
|
|
* Fired after package options have been updated.
|
|
*
|
|
* @param array|string $result The result of the update operation.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_package_options_updated', $result );
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Get submitted options
|
|
*
|
|
* Retrieves the submitted options from the form.
|
|
*
|
|
* @return array Submitted options.
|
|
* @since 1.0.0
|
|
*/
|
|
protected function get_submitted_options() {
|
|
|
|
/**
|
|
* Filter the submitted package configuration options.
|
|
*
|
|
* @param array $config Default package configuration.
|
|
* @return array The filtered package configuration.
|
|
* @since 1.0.0
|
|
*/
|
|
return apply_filters(
|
|
'upserv_submitted_package_config',
|
|
array(
|
|
'upserv_cache_max_size' => array(
|
|
'value' => filter_input( INPUT_POST, 'upserv_cache_max_size', FILTER_VALIDATE_INT ),
|
|
'display_name' => __( 'Cache max size (in MB)', 'updatepulse-server' ),
|
|
'failure_display_message' => __( 'Not a valid number', 'updatepulse-server' ),
|
|
'condition' => 'number',
|
|
'path' => 'limits/cache_max_size',
|
|
),
|
|
'upserv_logs_max_size' => array(
|
|
'value' => filter_input( INPUT_POST, 'upserv_logs_max_size', FILTER_VALIDATE_INT ),
|
|
'display_name' => __( 'Logs max size (in MB)', 'updatepulse-server' ),
|
|
'failure_display_message' => __( 'Not a valid number', 'updatepulse-server' ),
|
|
'condition' => 'number',
|
|
'path' => 'limits/logs_max_size',
|
|
),
|
|
'upserv_archive_max_size' => array(
|
|
'value' => filter_input( INPUT_POST, 'upserv_archive_max_size', FILTER_VALIDATE_INT ),
|
|
'display_name' => __( 'Archive max size (in MB)', 'updatepulse-server' ),
|
|
'failure_display_message' => __( 'Not a valid number', 'updatepulse-server' ),
|
|
'condition' => 'number',
|
|
'path' => 'limits/archive_max_size',
|
|
),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get package
|
|
*
|
|
* Retrieves a package object from the specified file.
|
|
*
|
|
* @param string $filename Package file name.
|
|
* @param string $slug Package slug.
|
|
* @return Package|false Package object or false if not found.
|
|
* @since 1.0.0
|
|
*/
|
|
protected function get_package( $filename, $slug ) {
|
|
$package = false;
|
|
$cache = new Cache( Data_Manager::get_data_dir( 'cache' ) );
|
|
$cached_value = null;
|
|
|
|
try {
|
|
|
|
if ( is_file( $filename ) && is_readable( $filename ) ) {
|
|
$cache_key = Zip_Metadata_Parser::build_cache_key( $slug, $filename );
|
|
$cached_value = $cache->get( $cache_key );
|
|
}
|
|
|
|
if ( null === $cached_value ) {
|
|
/**
|
|
* Fired when a package is not found in the cache.
|
|
*
|
|
* @param string $slug Package slug.
|
|
* @param string $filename Path to the package file.
|
|
* @param Cache $cache Cache object.
|
|
* @since 1.0.0
|
|
*/
|
|
do_action( 'upserv_find_package_no_cache', $slug, $filename, $cache );
|
|
}
|
|
|
|
$package = Package::from_archive( $filename, $slug, $cache );
|
|
} catch ( Exception $e ) {
|
|
Utils::php_log( 'Corrupt archive ' . $filename . '; package will not be displayed or delivered' );
|
|
|
|
$log = 'Exception caught: ' . $e->getMessage() . "\n";
|
|
$log .= 'File: ' . $e->getFile() . ':' . $e->getLine() . "\n";
|
|
|
|
Utils::php_log( $log );
|
|
}
|
|
|
|
return $package;
|
|
}
|
|
}
|