mirror of
https://github.com/Anyape/updatepulse-server.git
synced 2025-11-22 12:25:46 +08:00
Compare commits
15 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4847ed1ed7 | ||
|
|
84da98bc6a | ||
|
|
8356ac6ca2 | ||
|
|
8efebb1774 | ||
|
|
575c7c3cdb | ||
|
|
e1fc90780e | ||
|
|
deda3090c3 | ||
|
|
15ce059512 | ||
|
|
c6155be1fa | ||
|
|
ec8856175b | ||
|
|
d4a206ab1f | ||
|
|
49adf7f6b4 | ||
|
|
2589b5071b | ||
|
|
4bb83b4837 | ||
|
|
0c3c1ab306 |
19 changed files with 1073 additions and 140 deletions
|
|
@ -151,7 +151,7 @@ Name | Type | Description
|
||||||
Enable VCS | checkbox | Enables this server to download packages from a Version Control System before delivering updates.<br/>Supports Bitbucket, Github and Gitlab.<br/>If left unchecked, zip packages need to be manually uploaded to `wp-content/plugins/updatepulse-server/packages`.
|
Enable VCS | checkbox | Enables this server to download packages from a Version Control System before delivering updates.<br/>Supports Bitbucket, Github and Gitlab.<br/>If left unchecked, zip packages need to be manually uploaded to `wp-content/plugins/updatepulse-server/packages`.
|
||||||
VCS URL | text | The URL of the Version Control System where packages are hosted.<br/>Must follow the following pattern: `https://version-control-system.tld/username` where `https://version-control-system.tld` may be a self-hosted instance of Gitlab.<br/>Each package repository URL must follow the following pattern: `https://version-control-system.tld/username/package-slug/`; the package files must be located at the root of the repository, and in the case of WordPress plugins the main plugin file must follow the pattern `package-slug.php`.
|
VCS URL | text | The URL of the Version Control System where packages are hosted.<br/>Must follow the following pattern: `https://version-control-system.tld/username` where `https://version-control-system.tld` may be a self-hosted instance of Gitlab.<br/>Each package repository URL must follow the following pattern: `https://version-control-system.tld/username/package-slug/`; the package files must be located at the root of the repository, and in the case of WordPress plugins the main plugin file must follow the pattern `package-slug.php`.
|
||||||
Self-hosted VCS | checkbox | Check this only if the Version Control System is a self-hosted instance of Gitlab.
|
Self-hosted VCS | checkbox | Check this only if the Version Control System is a self-hosted instance of Gitlab.
|
||||||
Packages branch name | text | The branch to download when getting remote packages from the Version Control System.
|
Packages branch name | text | The branch to download when getting remote packages from the Version Control System.<br/>If the VCS supports releases or tags, they will be prioritised over the branch name (release first, then tag, then branch).<br/>To bypass this behaviour, set the `PUC_FORCE_BRANCH` constant to `true` in `wp-config.php`.
|
||||||
VCS credentials | text | Credentials for non-publicly accessible repositories.<br/>In the case of Github and Gitlab, a Personal Access Token; in the case of Bitckucket, an App Password.<br/>**WARNING: Keep these credentials secret, do not share them, and take care of renewing them before they expire!**
|
VCS credentials | text | Credentials for non-publicly accessible repositories.<br/>In the case of Github and Gitlab, a Personal Access Token; in the case of Bitckucket, an App Password.<br/>**WARNING: Keep these credentials secret, do not share them, and take care of renewing them before they expire!**
|
||||||
Use Webhooks | checkbox | Check so that each repository of the Version Control System calls a Webhook when updates are pushed.<br>When checked, UpdatePulse Server will not regularly poll repositories for package version changes, but relies on events sent by the repositories to schedule a package download.<br>Webhook URL: `https://domain.tld/updatepulse-server-webhook/package-type/package-slug` - where `package-type` is the package type (`plugin`, `theme`, or `generic`) and `package-slug` is the slug of the package that needs updates.<br>Note that UpdatePulse Server does not rely on the content of the payload to schedule a package download, so any type of event can be used to trigger the Webhook.
|
Use Webhooks | checkbox | Check so that each repository of the Version Control System calls a Webhook when updates are pushed.<br>When checked, UpdatePulse Server will not regularly poll repositories for package version changes, but relies on events sent by the repositories to schedule a package download.<br>Webhook URL: `https://domain.tld/updatepulse-server-webhook/package-type/package-slug` - where `package-type` is the package type (`plugin`, `theme`, or `generic`) and `package-slug` is the slug of the package that needs updates.<br>Note that UpdatePulse Server does not rely on the content of the payload to schedule a package download, so any type of event can be used to trigger the Webhook.
|
||||||
Remote Download Delay | number | Delay in minutes after which UpdatePulse Server will poll the Version Control System for package updates when the Webhook has been called.<br>Leave at `0` to schedule a package update during the cron run happening immediately after the Webhook notification was received.
|
Remote Download Delay | number | Delay in minutes after which UpdatePulse Server will poll the Version Control System for package updates when the Webhook has been called.<br>Leave at `0` to schedule a package update during the cron run happening immediately after the Webhook notification was received.
|
||||||
|
|
|
||||||
|
|
@ -424,7 +424,6 @@ class Webhook_API {
|
||||||
|
|
||||||
if ( 0 === strpos( $config['url'], trailingslashit( $url ) ) ) {
|
if ( 0 === strpos( $config['url'], trailingslashit( $url ) ) ) {
|
||||||
$vcs_candidates[] = $config;
|
$vcs_candidates[] = $config;
|
||||||
$vcs_candidates[] = $config;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,41 @@ use Anyape\UpdatePulse\Server\Manager\Data_Manager;
|
||||||
use Anyape\UpdatePulse\Server\Manager\Package_Manager;
|
use Anyape\UpdatePulse\Server\Manager\Package_Manager;
|
||||||
use Anyape\Utils\Utils;
|
use Anyape\Utils\Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main server class for UpdatePulse
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
class UPServ {
|
class UPServ {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class instance
|
||||||
|
*
|
||||||
|
* @var UPServ|null
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected static $instance;
|
protected static $instance;
|
||||||
|
/**
|
||||||
|
* Default plugin options
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected static $default_options;
|
protected static $default_options;
|
||||||
|
/**
|
||||||
|
* Current plugin options
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected static $options;
|
protected static $options;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param boolean $init_hooks Whether to initialize hooks
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function __construct( $init_hooks = false ) {
|
public function __construct( $init_hooks = false ) {
|
||||||
self::$default_options = array(
|
self::$default_options = array(
|
||||||
'use_vcs' => 0,
|
'use_vcs' => 0,
|
||||||
|
|
@ -79,6 +108,16 @@ class UPServ {
|
||||||
* Public methods
|
* Public methods
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle Action Scheduler failed execution
|
||||||
|
*
|
||||||
|
* Logs information about failed scheduled actions when debug mode is enabled.
|
||||||
|
*
|
||||||
|
* @param int $action_id The ID of the failed action
|
||||||
|
* @param Exception $exception The exception that was thrown
|
||||||
|
* @param string $context Additional context information
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function action_scheduler_failed_execution( $action_id, Exception $exception, $context = '' ) {
|
public function action_scheduler_failed_execution( $action_id, Exception $exception, $context = '' ) {
|
||||||
|
|
||||||
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
|
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
|
||||||
|
|
@ -96,6 +135,13 @@ class UPServ {
|
||||||
|
|
||||||
// WordPress hooks ---------------------------------------------
|
// WordPress hooks ---------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activate plugin
|
||||||
|
*
|
||||||
|
* Runs on plugin activation to verify requirements and initialize settings.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public static function activate() {
|
public static function activate() {
|
||||||
|
|
||||||
if ( ! version_compare( phpversion(), '8.0', '>=' ) ) {
|
if ( ! version_compare( phpversion(), '8.0', '>=' ) ) {
|
||||||
|
|
@ -127,25 +173,70 @@ class UPServ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deactivate plugin
|
||||||
|
*
|
||||||
|
* Runs on plugin deactivation.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public static function deactivate() {
|
public static function deactivate() {
|
||||||
flush_rewrite_rules();
|
flush_rewrite_rules();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstall plugin
|
||||||
|
*
|
||||||
|
* Runs on plugin uninstallation.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public static function uninstall() {
|
public static function uninstall() {
|
||||||
require_once UPSERV_PLUGIN_PATH . 'uninstall.php';
|
require_once UPSERV_PLUGIN_PATH . 'uninstall.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all plugin options
|
||||||
|
*
|
||||||
|
* Retrieves the plugin's options from the database.
|
||||||
|
*
|
||||||
|
* @return array Plugin options
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function get_options() {
|
public function get_options() {
|
||||||
$options = get_option( 'upserv_options' );
|
$options = get_option( 'upserv_options' );
|
||||||
$options = json_decode( $options, true );
|
$options = json_decode( $options, true );
|
||||||
$options = $options ? $options : array();
|
$options = $options ? $options : array();
|
||||||
$options = array_merge( self::$default_options, $options );
|
$options = array_merge( self::$default_options, $options );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the plugin options.
|
||||||
|
*
|
||||||
|
* @param array $options The plugin options
|
||||||
|
* @return array The filtered options
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
return apply_filters( 'upserv_get_options', $options );
|
return apply_filters( 'upserv_get_options', $options );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update plugin options
|
||||||
|
*
|
||||||
|
* Updates the plugin's options in the database.
|
||||||
|
*
|
||||||
|
* @param array $options New options to update
|
||||||
|
* @return bool Whether the update was successful
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function update_options( $options ) {
|
public function update_options( $options ) {
|
||||||
$options = array_merge( self::$options, $options );
|
$options = array_merge( self::$options, $options );
|
||||||
|
/**
|
||||||
|
* Filter the options before updating.
|
||||||
|
*
|
||||||
|
* @param array $options The options to update
|
||||||
|
* @return array The filtered options
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$options = apply_filters( 'upserv_update_options', $options );
|
$options = apply_filters( 'upserv_update_options', $options );
|
||||||
$options = wp_json_encode(
|
$options = wp_json_encode(
|
||||||
$options,
|
$options,
|
||||||
|
|
@ -160,6 +251,16 @@ class UPServ {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get single option value
|
||||||
|
*
|
||||||
|
* Retrieves a specific option by its path.
|
||||||
|
*
|
||||||
|
* @param string|array $path Option path
|
||||||
|
* @param mixed $_default Default value if option not found
|
||||||
|
* @return mixed Option value
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function get_option( $path, $_default ) {
|
public function get_option( $path, $_default ) {
|
||||||
$options = $this->get_options();
|
$options = $this->get_options();
|
||||||
$option = Utils::access_nested_array( $options, $path );
|
$option = Utils::access_nested_array( $options, $path );
|
||||||
|
|
@ -168,9 +269,27 @@ class UPServ {
|
||||||
$option = $_default;
|
$option = $_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter a specific option value.
|
||||||
|
*
|
||||||
|
* @param mixed $option The option value
|
||||||
|
* @param string|array $path The option path
|
||||||
|
* @return mixed The filtered option value
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
return apply_filters( 'upserv_get_option', $option, $path );
|
return apply_filters( 'upserv_get_option', $option, $path );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set option in memory
|
||||||
|
*
|
||||||
|
* Sets an option value in memory without saving to database.
|
||||||
|
*
|
||||||
|
* @param string|array $path Option path
|
||||||
|
* @param mixed $value Option value
|
||||||
|
* @return array Updated options
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function set_option( $path, $value ) {
|
public function set_option( $path, $value ) {
|
||||||
$options = self::$options;
|
$options = self::$options;
|
||||||
|
|
||||||
|
|
@ -181,6 +300,16 @@ class UPServ {
|
||||||
return self::$options;
|
return self::$options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update single option
|
||||||
|
*
|
||||||
|
* Updates a specific option by its path and saves to database.
|
||||||
|
*
|
||||||
|
* @param string|array $path Option path
|
||||||
|
* @param mixed $value Option value
|
||||||
|
* @return bool Whether the update was successful
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function update_option( $path, $value ) {
|
public function update_option( $path, $value ) {
|
||||||
$options = $this->get_options();
|
$options = $this->get_options();
|
||||||
|
|
||||||
|
|
@ -189,6 +318,13 @@ class UPServ {
|
||||||
return $this->update_options( $options );
|
return $this->update_options( $options );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize plugin
|
||||||
|
*
|
||||||
|
* Runs during WordPress init hook to set up the plugin.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function init() {
|
public function init() {
|
||||||
|
|
||||||
if ( get_transient( 'upserv_flush' ) ) {
|
if ( get_transient( 'upserv_flush' ) ) {
|
||||||
|
|
@ -207,10 +343,26 @@ class UPServ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load text domain
|
||||||
|
*
|
||||||
|
* Loads the plugin's translations.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function load_textdomain() {
|
public function load_textdomain() {
|
||||||
load_plugin_textdomain( 'updatepulse-server', false, '/languages' );
|
load_plugin_textdomain( 'updatepulse-server', false, '/languages' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register admin styles
|
||||||
|
*
|
||||||
|
* Adds stylesheets for the admin interface.
|
||||||
|
*
|
||||||
|
* @param array $styles Existing styles
|
||||||
|
* @return array Modified styles
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function upserv_admin_styles( $styles ) {
|
public function upserv_admin_styles( $styles ) {
|
||||||
$styles['main'] = array(
|
$styles['main'] = array(
|
||||||
'path' => UPSERV_PLUGIN_PATH . 'css/admin/main' . upserv_assets_suffix() . '.css',
|
'path' => UPSERV_PLUGIN_PATH . 'css/admin/main' . upserv_assets_suffix() . '.css',
|
||||||
|
|
@ -232,6 +384,15 @@ class UPServ {
|
||||||
return $styles;
|
return $styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register admin scripts
|
||||||
|
*
|
||||||
|
* Adds JavaScript files for the admin interface.
|
||||||
|
*
|
||||||
|
* @param array $scripts Existing scripts
|
||||||
|
* @return array Modified scripts
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function upserv_admin_scripts( $scripts ) {
|
public function upserv_admin_scripts( $scripts ) {
|
||||||
$scripts['main'] = array(
|
$scripts['main'] = array(
|
||||||
'path' => UPSERV_PLUGIN_PATH . 'js/admin/main' . upserv_assets_suffix() . '.js',
|
'path' => UPSERV_PLUGIN_PATH . 'js/admin/main' . upserv_assets_suffix() . '.js',
|
||||||
|
|
@ -246,6 +407,16 @@ class UPServ {
|
||||||
return $scripts;
|
return $scripts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process script localization
|
||||||
|
*
|
||||||
|
* Formats localization strings for JavaScript files.
|
||||||
|
*
|
||||||
|
* @param array $l10n Localization data
|
||||||
|
* @param string $script Script name
|
||||||
|
* @return array Modified localization data
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function upserv_scripts_l10n( $l10n, $script ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
public function upserv_scripts_l10n( $l10n, $script ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
||||||
|
|
||||||
foreach ( $l10n as $key => $values ) {
|
foreach ( $l10n as $key => $values ) {
|
||||||
|
|
@ -260,6 +431,14 @@ class UPServ {
|
||||||
return $l10n;
|
return $l10n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue admin scripts and styles
|
||||||
|
*
|
||||||
|
* Loads the necessary assets for admin pages.
|
||||||
|
*
|
||||||
|
* @param string $hook Current admin page hook
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function admin_enqueue_scripts( $hook ) {
|
public function admin_enqueue_scripts( $hook ) {
|
||||||
|
|
||||||
if ( false !== strpos( $hook, 'page_upserv' ) ) {
|
if ( false !== strpos( $hook, 'page_upserv' ) ) {
|
||||||
|
|
@ -268,6 +447,13 @@ class UPServ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register main admin menu
|
||||||
|
*
|
||||||
|
* Adds the main UpdatePulse menu item to the admin menu.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function admin_menu() {
|
public function admin_menu() {
|
||||||
$page_title = __( 'UpdatePulse', 'updatepulse-server' );
|
$page_title = __( 'UpdatePulse', 'updatepulse-server' );
|
||||||
$menu_title = $page_title;
|
$menu_title = $page_title;
|
||||||
|
|
@ -276,6 +462,13 @@ class UPServ {
|
||||||
add_menu_page( $page_title, $menu_title, 'manage_options', 'upserv-page', '', $icon );
|
add_menu_page( $page_title, $menu_title, 'manage_options', 'upserv-page', '', $icon );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register help page in admin menu
|
||||||
|
*
|
||||||
|
* Adds the help submenu to the UpdatePulse menu.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function admin_menu_help() {
|
public function admin_menu_help() {
|
||||||
$function = array( $this, 'help_page' );
|
$function = array( $this, 'help_page' );
|
||||||
$page_title = __( 'UpdatePulse Server - Help', 'updatepulse-server' );
|
$page_title = __( 'UpdatePulse Server - Help', 'updatepulse-server' );
|
||||||
|
|
@ -285,6 +478,15 @@ class UPServ {
|
||||||
add_submenu_page( 'upserv-page', $page_title, $menu_title, 'manage_options', $menu_slug, $function );
|
add_submenu_page( 'upserv-page', $page_title, $menu_title, 'manage_options', $menu_slug, $function );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add tab links for admin interface
|
||||||
|
*
|
||||||
|
* Registers navigation tabs for the admin interface.
|
||||||
|
*
|
||||||
|
* @param array $links Existing tab links
|
||||||
|
* @return array Modified tab links
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function upserv_admin_tab_links( $links ) {
|
public function upserv_admin_tab_links( $links ) {
|
||||||
$links['help'] = array(
|
$links['help'] = array(
|
||||||
admin_url( 'admin.php?page=upserv-page-help' ),
|
admin_url( 'admin.php?page=upserv-page-help' ),
|
||||||
|
|
@ -294,12 +496,31 @@ class UPServ {
|
||||||
return $links;
|
return $links;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add tab states for admin interface
|
||||||
|
*
|
||||||
|
* Sets active states for navigation tabs.
|
||||||
|
*
|
||||||
|
* @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 ) {
|
public function upserv_admin_tab_states( $states, $page ) {
|
||||||
$states['help'] = 'upserv-page-help' === $page;
|
$states['help'] = 'upserv-page-help' === $page;
|
||||||
|
|
||||||
return $states;
|
return $states;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add plugin action links
|
||||||
|
*
|
||||||
|
* Adds custom links to the plugin's entry in the plugins list.
|
||||||
|
*
|
||||||
|
* @param array $links Existing plugin action links
|
||||||
|
* @return array Modified plugin action links
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function add_action_links( $links ) {
|
public function add_action_links( $links ) {
|
||||||
$link = array(
|
$link = array(
|
||||||
'<a href="' . admin_url( 'admin.php?page=upserv-page-help' ) . '">' . __( 'Help', 'updatepulse-server' ) . '</a>',
|
'<a href="' . admin_url( 'admin.php?page=upserv-page-help' ) . '">' . __( 'Help', 'updatepulse-server' ) . '</a>',
|
||||||
|
|
@ -308,10 +529,28 @@ class UPServ {
|
||||||
return array_merge( $links, $link );
|
return array_merge( $links, $link );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set action scheduler retention period
|
||||||
|
*
|
||||||
|
* Controls how long scheduled actions are kept in the database.
|
||||||
|
*
|
||||||
|
* @return int Retention period in seconds
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function action_scheduler_retention_period() {
|
public function action_scheduler_retention_period() {
|
||||||
return DAY_IN_SECONDS;
|
return DAY_IN_SECONDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify admin template arguments
|
||||||
|
*
|
||||||
|
* Adds or modifies arguments passed to admin templates.
|
||||||
|
*
|
||||||
|
* @param array $args Existing template arguments
|
||||||
|
* @param string $template_name Name of the template
|
||||||
|
* @return array Modified template arguments
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function upserv_get_admin_template_args( $args, $template_name ) {
|
public function upserv_get_admin_template_args( $args, $template_name ) {
|
||||||
|
|
||||||
if ( preg_match( '/^plugin-.*-page\.php$/', $template_name ) ) {
|
if ( preg_match( '/^plugin-.*-page\.php$/', $template_name ) ) {
|
||||||
|
|
@ -323,6 +562,14 @@ class UPServ {
|
||||||
|
|
||||||
// Misc. -------------------------------------------------------
|
// Misc. -------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get class instance
|
||||||
|
*
|
||||||
|
* Retrieves or creates the singleton instance of this class.
|
||||||
|
*
|
||||||
|
* @return UPServ The class instance
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public static function get_instance() {
|
public static function get_instance() {
|
||||||
|
|
||||||
if ( ! isset( self::$instance ) ) {
|
if ( ! isset( self::$instance ) ) {
|
||||||
|
|
@ -332,6 +579,17 @@ class UPServ {
|
||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate template file
|
||||||
|
*
|
||||||
|
* Finds a template file in the theme or plugin directories.
|
||||||
|
*
|
||||||
|
* @param string $template_name Template name
|
||||||
|
* @param bool $load Whether to load the template
|
||||||
|
* @param bool $required_once Whether to use require_once or require
|
||||||
|
* @return string Template path
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public static function locate_template( $template_name, $load = false, $required_once = true ) {
|
public static function locate_template( $template_name, $load = false, $required_once = true ) {
|
||||||
$name = str_replace( 'templates/', '', $template_name );
|
$name = str_replace( 'templates/', '', $template_name );
|
||||||
$paths = array(
|
$paths = array(
|
||||||
|
|
@ -340,12 +598,28 @@ class UPServ {
|
||||||
'updatepulse-server/templates/' . $name,
|
'updatepulse-server/templates/' . $name,
|
||||||
'updatepulse-server/' . $name,
|
'updatepulse-server/' . $name,
|
||||||
);
|
);
|
||||||
|
/**
|
||||||
|
* Filter the paths where templates can be located.
|
||||||
|
*
|
||||||
|
* @param array $paths Array of template paths
|
||||||
|
* @return array The filtered paths
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$template = locate_template( apply_filters( 'upserv_locate_template_paths', $paths ) );
|
$template = locate_template( apply_filters( 'upserv_locate_template_paths', $paths ) );
|
||||||
|
|
||||||
if ( empty( $template ) ) {
|
if ( empty( $template ) ) {
|
||||||
$template = UPSERV_PLUGIN_PATH . 'inc/templates/' . $template_name;
|
$template = UPSERV_PLUGIN_PATH . 'inc/templates/' . $template_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the located template.
|
||||||
|
*
|
||||||
|
* @param string $template The path to the template
|
||||||
|
* @param string $template_name The template name
|
||||||
|
* @param string $template_path The template path
|
||||||
|
* @return string The filtered template path
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$template = apply_filters(
|
$template = apply_filters(
|
||||||
'upserv_locate_template',
|
'upserv_locate_template',
|
||||||
$template,
|
$template,
|
||||||
|
|
@ -360,7 +634,27 @@ class UPServ {
|
||||||
return $template;
|
return $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate admin template file
|
||||||
|
*
|
||||||
|
* Finds an admin template file in the plugin directory.
|
||||||
|
*
|
||||||
|
* @param string $template_name Template name
|
||||||
|
* @param bool $load Whether to load the template
|
||||||
|
* @param bool $required_once Whether to use require_once or require
|
||||||
|
* @return string Template path
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public static function locate_admin_template( $template_name, $load = false, $required_once = true ) {
|
public static function locate_admin_template( $template_name, $load = false, $required_once = true ) {
|
||||||
|
/**
|
||||||
|
* Filter the admin template location.
|
||||||
|
*
|
||||||
|
* @param string $template The path to the template
|
||||||
|
* @param string $template_name The template name
|
||||||
|
* @param string $template_path The template path
|
||||||
|
* @return string The filtered template path
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$template = apply_filters(
|
$template = apply_filters(
|
||||||
'upserv_locate_admin_template',
|
'upserv_locate_admin_template',
|
||||||
UPSERV_PLUGIN_PATH . 'inc/templates/admin/' . $template_name,
|
UPSERV_PLUGIN_PATH . 'inc/templates/admin/' . $template_name,
|
||||||
|
|
@ -375,6 +669,13 @@ class UPServ {
|
||||||
return $template;
|
return $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display MU plugin setup failure notice
|
||||||
|
*
|
||||||
|
* Shows admin notice when MU plugin couldn't be installed.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function setup_mu_plugin_failure_notice() {
|
public function setup_mu_plugin_failure_notice() {
|
||||||
$class = 'notice notice-error';
|
$class = 'notice notice-error';
|
||||||
$message = sprintf(
|
$message = sprintf(
|
||||||
|
|
@ -387,6 +688,13 @@ class UPServ {
|
||||||
printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display MU plugin setup success notice
|
||||||
|
*
|
||||||
|
* Shows admin notice when MU plugin was successfully installed.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function setup_mu_plugin_success_notice() {
|
public function setup_mu_plugin_success_notice() {
|
||||||
$class = 'notice notice-info is-dismissible';
|
$class = 'notice notice-info is-dismissible';
|
||||||
$message = sprintf(
|
$message = sprintf(
|
||||||
|
|
@ -398,6 +706,14 @@ class UPServ {
|
||||||
printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display settings header
|
||||||
|
*
|
||||||
|
* Renders the header for settings pages with notices.
|
||||||
|
*
|
||||||
|
* @param string|array $notice Optional notice to display
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function display_settings_header( $notice ) {
|
public function display_settings_header( $notice ) {
|
||||||
echo '<h1>' . esc_html__( 'UpdatePulse Server', 'updatepulse-server' ) . '</h1>';
|
echo '<h1>' . esc_html__( 'UpdatePulse Server', 'updatepulse-server' ) . '</h1>';
|
||||||
|
|
||||||
|
|
@ -429,6 +745,13 @@ class UPServ {
|
||||||
$this->display_tabs();
|
$this->display_tabs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render help page
|
||||||
|
*
|
||||||
|
* Displays the plugin's help documentation.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function help_page() {
|
public function help_page() {
|
||||||
|
|
||||||
if ( ! current_user_can( 'manage_options' ) ) {
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
|
@ -453,6 +776,13 @@ class UPServ {
|
||||||
* Protected methods
|
* Protected methods
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display navigation tabs
|
||||||
|
*
|
||||||
|
* Renders the tab navigation for admin pages.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function display_tabs() {
|
protected function display_tabs() {
|
||||||
$states = $this->get_tab_states();
|
$states = $this->get_tab_states();
|
||||||
$state = array_filter( $states );
|
$state = array_filter( $states );
|
||||||
|
|
@ -463,6 +793,13 @@ class UPServ {
|
||||||
|
|
||||||
$state = array_keys( $state );
|
$state = array_keys( $state );
|
||||||
$state = reset( $state );
|
$state = reset( $state );
|
||||||
|
/**
|
||||||
|
* Filter the admin tab links.
|
||||||
|
*
|
||||||
|
* @param array $links The existing tab links
|
||||||
|
* @return array The modified tab links
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$links = apply_filters( 'upserv_admin_tab_links', array() );
|
$links = apply_filters( 'upserv_admin_tab_links', array() );
|
||||||
|
|
||||||
upserv_get_admin_template(
|
upserv_get_admin_template(
|
||||||
|
|
@ -475,20 +812,51 @@ class UPServ {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tab states
|
||||||
|
*
|
||||||
|
* Determines which tab is currently active.
|
||||||
|
*
|
||||||
|
* @return array Tab states
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function get_tab_states() {
|
protected function get_tab_states() {
|
||||||
$page = sanitize_text_field( wp_unslash( filter_input( INPUT_GET, 'page' ) ) );
|
$page = sanitize_text_field( wp_unslash( filter_input( INPUT_GET, 'page' ) ) );
|
||||||
$states = array();
|
$states = array();
|
||||||
|
|
||||||
if ( 0 === strpos( $page, 'upserv-page' ) ) {
|
if ( 0 === strpos( $page, 'upserv-page' ) ) {
|
||||||
|
/**
|
||||||
|
* Filter the admin tab states.
|
||||||
|
*
|
||||||
|
* @param array $states The existing tab states
|
||||||
|
* @param string $page The current page
|
||||||
|
* @return array The modified tab states
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$states = apply_filters( 'upserv_admin_tab_states', $states, $page );
|
$states = apply_filters( 'upserv_admin_tab_states', $states, $page );
|
||||||
}
|
}
|
||||||
|
|
||||||
return $states;
|
return $states;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue styles
|
||||||
|
*
|
||||||
|
* Loads stylesheets for the admin interface.
|
||||||
|
*
|
||||||
|
* @param array $styles Styles to enqueue
|
||||||
|
* @return array Enqueued styles
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function enqueue_styles( $styles ) {
|
protected function enqueue_styles( $styles ) {
|
||||||
$filter = 'upserv_admin_styles';
|
/**
|
||||||
$styles = apply_filters( $filter, $styles );
|
* Filter the admin styles to be enqueued.
|
||||||
|
*
|
||||||
|
* @param array $styles Array of styles to be enqueued
|
||||||
|
* @return array Modified array of styles
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
$styles = apply_filters( 'upserv_admin_styles', $styles );
|
||||||
|
|
||||||
if ( ! empty( $styles ) ) {
|
if ( ! empty( $styles ) ) {
|
||||||
|
|
||||||
|
|
@ -516,9 +884,24 @@ class UPServ {
|
||||||
return $styles;
|
return $styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue scripts
|
||||||
|
*
|
||||||
|
* Loads JavaScript files for the admin interface.
|
||||||
|
*
|
||||||
|
* @param array $scripts Scripts to enqueue
|
||||||
|
* @return array Enqueued scripts
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function enqueue_scripts( $scripts ) {
|
protected function enqueue_scripts( $scripts ) {
|
||||||
$filter = 'upserv_admin_scripts';
|
/**
|
||||||
$scripts = apply_filters( $filter, $scripts );
|
* Filter the admin scripts to be enqueued.
|
||||||
|
*
|
||||||
|
* @param array $scripts Array of scripts to be enqueued
|
||||||
|
* @return array Modified array of scripts
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
$scripts = apply_filters( 'upserv_admin_scripts', $scripts );
|
||||||
|
|
||||||
if ( ! empty( $scripts ) ) {
|
if ( ! empty( $scripts ) ) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,26 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
* Class Utils
|
* Class Utils
|
||||||
*
|
*
|
||||||
* @package Anyape\Utils
|
* @package Anyape\Utils
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
class Utils {
|
class Utils {
|
||||||
|
|
||||||
// JSON options
|
/**
|
||||||
|
* JSON encoding options
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
const JSON_OPTIONS = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE;
|
const JSON_OPTIONS = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $message
|
* Log a message to PHP error log
|
||||||
* @param string $prefix
|
*
|
||||||
|
* Adds class/method context information to the log message.
|
||||||
|
*
|
||||||
|
* @param string $message Message to log
|
||||||
|
* @param string $prefix Optional prefix for the log message
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function php_log( $message = '', $prefix = '' ) {
|
public static function php_log( $message = '', $prefix = '' ) {
|
||||||
$prefix = $prefix ? ' ' . $prefix . ' => ' : ' => ';
|
$prefix = $prefix ? ' ' . $prefix . ' => ' : ' => ';
|
||||||
|
|
@ -33,10 +44,14 @@ class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $ip
|
* Check if IP address is within CIDR range
|
||||||
* @param string $range
|
|
||||||
*
|
*
|
||||||
* @return bool
|
* Validates whether a given IP address falls within the specified CIDR range.
|
||||||
|
*
|
||||||
|
* @param string $ip IP address to check
|
||||||
|
* @param string $range CIDR range notation (e.g., 192.168.1.0/24)
|
||||||
|
* @return bool True if IP is in range, false otherwise
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function cidr_match( $ip, $range ) {
|
public static function cidr_match( $ip, $range ) {
|
||||||
list ( $subnet, $bits ) = explode( '/', $range );
|
list ( $subnet, $bits ) = explode( '/', $range );
|
||||||
|
|
@ -54,12 +69,16 @@ class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $_array
|
* Access or update nested array using path notation
|
||||||
* @param string $path
|
|
||||||
* @param null $value
|
|
||||||
* @param bool $update
|
|
||||||
*
|
*
|
||||||
* @return mixed|null
|
* Gets or sets a value in a nested array using a path string with / as separator.
|
||||||
|
*
|
||||||
|
* @param array $_array Reference to the array to access
|
||||||
|
* @param string $path Path notation to the nested element (e.g., 'parent/child/item')
|
||||||
|
* @param mixed $value Optional value to set if updating
|
||||||
|
* @param bool $update Whether to update the array (true) or just read (false)
|
||||||
|
* @return mixed|null Retrieved value or null if path doesn't exist
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function access_nested_array( &$_array, $path, $value = null, $update = false ) {
|
public static function access_nested_array( &$_array, $path, $value = null, $update = false ) {
|
||||||
$keys = explode( '/', $path );
|
$keys = explode( '/', $path );
|
||||||
|
|
@ -87,10 +106,13 @@ class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* Check if URL subpath matches a regex pattern
|
||||||
* @param string $regex
|
|
||||||
*
|
*
|
||||||
* @return int|null
|
* Tests if the first segment of the current request URI matches the provided regex.
|
||||||
|
*
|
||||||
|
* @param string $regex Regular expression to match against the first path segment
|
||||||
|
* @return int|null 1 if match found, 0 if no match, null if host couldn't be determined
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function is_url_subpath_match( $regex ) {
|
public static function is_url_subpath_match( $regex ) {
|
||||||
$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : false;
|
$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : false;
|
||||||
|
|
@ -111,10 +133,12 @@ class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* Get time elapsed since request start
|
||||||
* @param string $regex
|
|
||||||
*
|
*
|
||||||
* @return int|null
|
* Calculates the time elapsed since the request started in seconds.
|
||||||
|
*
|
||||||
|
* @return string|null Time elapsed in seconds with 3 decimal precision, or null if request time not available
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function get_time_elapsed() {
|
public static function get_time_elapsed() {
|
||||||
|
|
||||||
|
|
@ -132,10 +156,12 @@ class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* Get remote IP address
|
||||||
* @param string $regex
|
|
||||||
*
|
*
|
||||||
* @return int|null
|
* Safely retrieves the remote IP address of the client.
|
||||||
|
*
|
||||||
|
* @return string IP address of the client or '0.0.0.0' if not available or invalid
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function get_remote_ip() {
|
public static function get_remote_ip() {
|
||||||
|
|
||||||
|
|
@ -152,6 +178,15 @@ class Utils {
|
||||||
return $ip;
|
return $ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get human-readable status string
|
||||||
|
*
|
||||||
|
* Converts a status code to a localized human-readable string.
|
||||||
|
*
|
||||||
|
* @param string $status Status code to convert
|
||||||
|
* @return string Localized human-readable status string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public static function get_status_string( $status ) {
|
public static function get_status_string( $status ) {
|
||||||
switch ( $status ) {
|
switch ( $status ) {
|
||||||
case 'pending':
|
case 'pending':
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,8 @@ class Data_Manager {
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function maybe_setup_mu_plugin() {
|
public static function maybe_setup_mu_plugin() {
|
||||||
|
WP_Filesystem();
|
||||||
|
|
||||||
global $wp_filesystem;
|
global $wp_filesystem;
|
||||||
|
|
||||||
$result = true;
|
$result = true;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ use Anyape\UpdatePulse\Server\Server\Update\Package;
|
||||||
use Anyape\UpdatePulse\Server\Manager\Data_Manager;
|
use Anyape\UpdatePulse\Server\Manager\Data_Manager;
|
||||||
use Anyape\UpdatePulse\Server\API\Package_API;
|
use Anyape\UpdatePulse\Server\API\Package_API;
|
||||||
use Anyape\UpdatePulse\Server\Table\Packages_Table;
|
use Anyape\UpdatePulse\Server\Table\Packages_Table;
|
||||||
|
use Anyape\UpdatePulse\Server\Scheduler\Scheduler;
|
||||||
use Anyape\Utils\Utils;
|
use Anyape\Utils\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -445,18 +446,6 @@ class Package_Manager {
|
||||||
upserv_set_package_metadata( $slug, $meta );
|
upserv_set_package_metadata( $slug, $meta );
|
||||||
|
|
||||||
$result = upserv_download_remote_package( $slug, null );
|
$result = upserv_download_remote_package( $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' )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( wp_cache_get( 'upserv_download_remote_package_aborted', 'updatepulse-server' ) ) {
|
if ( wp_cache_get( 'upserv_download_remote_package_aborted', 'updatepulse-server' ) ) {
|
||||||
$vcs_config = upserv_get_package_vcs_config( $slug );
|
$vcs_config = upserv_get_package_vcs_config( $slug );
|
||||||
|
|
@ -473,6 +462,22 @@ class Package_Manager {
|
||||||
wp_cache_delete( 'upserv_download_remote_package_aborted', '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.
|
* Fired after a package has been registered from a VCS.
|
||||||
*
|
*
|
||||||
|
|
@ -989,7 +994,20 @@ class Package_Manager {
|
||||||
do_action( 'upserv_package_manager_deleted_package', $slug, $result );
|
do_action( 'upserv_package_manager_deleted_package', $slug, $result );
|
||||||
|
|
||||||
if ( $result ) {
|
if ( $result ) {
|
||||||
|
$scheduled_hook = 'upserv_check_remote_' . $slug;
|
||||||
|
|
||||||
upserv_unwhitelist_package( $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;
|
$deleted_package_slugs[] = $slug;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -885,7 +885,7 @@ class Remote_Sources_Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( empty( $slugs ) ) {
|
if ( ! empty( $slugs ) ) {
|
||||||
|
|
||||||
foreach ( $slugs as $idx => $slug ) {
|
foreach ( $slugs as $idx => $slug ) {
|
||||||
$meta = upserv_get_package_metadata( $slug );
|
$meta = upserv_get_package_metadata( $slug );
|
||||||
|
|
|
||||||
|
|
@ -588,6 +588,8 @@ class Nonce {
|
||||||
$sql = "DELETE FROM {$wpdb->prefix}upserv_nonce
|
$sql = "DELETE FROM {$wpdb->prefix}upserv_nonce
|
||||||
WHERE expiry < %d
|
WHERE expiry < %d
|
||||||
AND (
|
AND (
|
||||||
|
JSON_VALID(`data`) = 0
|
||||||
|
OR (
|
||||||
JSON_VALID(`data`) = 1
|
JSON_VALID(`data`) = 1
|
||||||
AND (
|
AND (
|
||||||
JSON_EXTRACT(`data` , '$.permanent') IS NULL
|
JSON_EXTRACT(`data` , '$.permanent') IS NULL
|
||||||
|
|
@ -595,8 +597,8 @@ class Nonce {
|
||||||
OR JSON_EXTRACT(`data` , '$.permanent') = '0'
|
OR JSON_EXTRACT(`data` , '$.permanent') = '0'
|
||||||
OR JSON_EXTRACT(`data` , '$.permanent') = false
|
OR JSON_EXTRACT(`data` , '$.permanent') = false
|
||||||
)
|
)
|
||||||
) OR
|
)
|
||||||
JSON_VALID(`data`) = 0;";
|
);";
|
||||||
$sql_args = array( time() - self::DEFAULT_EXPIRY_LENGTH );
|
$sql_args = array( time() - self::DEFAULT_EXPIRY_LENGTH );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -288,6 +288,13 @@ class Update_Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires after pre-filtering package information
|
||||||
|
*
|
||||||
|
* Allows developers to perform actions after the package information has been initially filtered.
|
||||||
|
*
|
||||||
|
* @param array $info The package information array after pre-filtering
|
||||||
|
*/
|
||||||
do_action( 'upserv_pre_filter_package_info', $info );
|
do_action( 'upserv_pre_filter_package_info', $info );
|
||||||
|
|
||||||
return $info;
|
return $info;
|
||||||
|
|
@ -314,6 +321,13 @@ class Update_Server {
|
||||||
*/
|
*/
|
||||||
$info = apply_filters( 'upserv_filter_package_info', $info, $this->filter_packages_file_content );
|
$info = apply_filters( 'upserv_filter_package_info', $info, $this->filter_packages_file_content );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires after filtering package information
|
||||||
|
*
|
||||||
|
* Allows developers to perform actions after the package information has been filtered.
|
||||||
|
*
|
||||||
|
* @param array $info The package information array after filtering
|
||||||
|
*/
|
||||||
do_action( 'upserv_filter_package_info', $info );
|
do_action( 'upserv_filter_package_info', $info );
|
||||||
|
|
||||||
return $info;
|
return $info;
|
||||||
|
|
@ -365,6 +379,13 @@ class Update_Server {
|
||||||
) ) {
|
) ) {
|
||||||
$this->remove_package( $safe_slug, true );
|
$this->remove_package( $safe_slug, true );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires when a remote package download is aborted
|
||||||
|
*
|
||||||
|
* @param string $safe_slug The sanitized package slug
|
||||||
|
* @param string $type The package type
|
||||||
|
* @param array $info The package information
|
||||||
|
*/
|
||||||
do_action( 'upserv_download_remote_package_aborted', $safe_slug, $this->type, $info );
|
do_action( 'upserv_download_remote_package_aborted', $safe_slug, $this->type, $info );
|
||||||
|
|
||||||
return $info;
|
return $info;
|
||||||
|
|
@ -375,6 +396,13 @@ class Update_Server {
|
||||||
|
|
||||||
$package = $this->download_remote_package( $info['download_url'] );
|
$package = $this->download_remote_package( $info['download_url'] );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires after a remote package has been downloaded
|
||||||
|
*
|
||||||
|
* @param string $package Path to the downloaded package file
|
||||||
|
* @param string $type The package type
|
||||||
|
* @param string $safe_slug The sanitized package slug
|
||||||
|
*/
|
||||||
do_action( 'upserv_downloaded_remote_package', $package, $info['type'], $safe_slug );
|
do_action( 'upserv_downloaded_remote_package', $package, $info['type'], $safe_slug );
|
||||||
|
|
||||||
$package_manager = new Zip_Package_Manager(
|
$package_manager = new Zip_Package_Manager(
|
||||||
|
|
@ -385,6 +413,13 @@ class Update_Server {
|
||||||
);
|
);
|
||||||
$local_ready = $package_manager->clean_package();
|
$local_ready = $package_manager->clean_package();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires after a remote package has been saved to local storage
|
||||||
|
*
|
||||||
|
* @param bool $local_ready Whether the package was successfully saved locally
|
||||||
|
* @param string $type The package type
|
||||||
|
* @param string $safe_slug The sanitized package slug
|
||||||
|
*/
|
||||||
do_action(
|
do_action(
|
||||||
'upserv_saved_remote_package_to_local',
|
'upserv_saved_remote_package_to_local',
|
||||||
$local_ready,
|
$local_ready,
|
||||||
|
|
@ -429,6 +464,11 @@ class Update_Server {
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function check_remote_package_update( $slug ) {
|
public function check_remote_package_update( $slug ) {
|
||||||
|
/**
|
||||||
|
* Fires before checking if a remote package needs to be updated
|
||||||
|
*
|
||||||
|
* @param string $slug The package slug
|
||||||
|
*/
|
||||||
do_action( 'upserv_check_remote_update', $slug );
|
do_action( 'upserv_check_remote_update', $slug );
|
||||||
|
|
||||||
$needs_update = true;
|
$needs_update = true;
|
||||||
|
|
@ -477,7 +517,7 @@ class Update_Server {
|
||||||
|
|
||||||
$remote_info = $this->update_checker->request_info();
|
$remote_info = $this->update_checker->request_info();
|
||||||
|
|
||||||
if ( $remote_info && ! is_wp_error( $remote_info ) ) {
|
if ( ! is_wp_error( $remote_info ) && isset( $remote_info['version'] ) ) {
|
||||||
$needs_update = version_compare( $remote_info['version'], $meta['header']['Version'], '>' );
|
$needs_update = version_compare( $remote_info['version'], $meta['header']['Version'], '>' );
|
||||||
} else {
|
} else {
|
||||||
Utils::php_log(
|
Utils::php_log(
|
||||||
|
|
@ -491,6 +531,13 @@ class Update_Server {
|
||||||
$needs_update = null;
|
$needs_update = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires after checking if a remote package needs to be updated
|
||||||
|
*
|
||||||
|
* @param bool|null $needs_update Whether the package needs to be updated
|
||||||
|
* @param string $type The package type
|
||||||
|
* @param string $slug The package slug
|
||||||
|
*/
|
||||||
do_action( 'upserv_checked_remote_package_update', $needs_update, $this->type, $slug );
|
do_action( 'upserv_checked_remote_package_update', $needs_update, $this->type, $slug );
|
||||||
|
|
||||||
return $needs_update;
|
return $needs_update;
|
||||||
|
|
@ -552,6 +599,13 @@ class Update_Server {
|
||||||
$this->cache->clear( $cache_key );
|
$this->cache->clear( $cache_key );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires after a package has been removed
|
||||||
|
*
|
||||||
|
* @param bool $result Whether the package was successfully removed
|
||||||
|
* @param string $type The package type
|
||||||
|
* @param string $slug The package slug
|
||||||
|
*/
|
||||||
do_action( 'upserv_removed_package', $result, $type, $slug );
|
do_action( 'upserv_removed_package', $result, $type, $slug );
|
||||||
self::unlock_update_from_remote( $slug );
|
self::unlock_update_from_remote( $slug );
|
||||||
|
|
||||||
|
|
@ -709,6 +763,11 @@ class Update_Server {
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function action_download( Request $request ) {
|
protected function action_download( Request $request ) {
|
||||||
|
/**
|
||||||
|
* Fires when processing a download action
|
||||||
|
*
|
||||||
|
* @param Request $request The current request object
|
||||||
|
*/
|
||||||
do_action( 'upserv_update_server_action_download', $request );
|
do_action( 'upserv_update_server_action_download', $request );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -846,6 +905,13 @@ class Update_Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( null === $cached_value ) {
|
if ( null === $cached_value ) {
|
||||||
|
/**
|
||||||
|
* Fires when no cached package metadata is available
|
||||||
|
*
|
||||||
|
* @param string $safe_slug The sanitized package slug
|
||||||
|
* @param string $filename The local filename path
|
||||||
|
* @param Cache $cache The cache instance
|
||||||
|
*/
|
||||||
do_action( 'upserv_find_package_no_cache', $safe_slug, $filename, $this->cache );
|
do_action( 'upserv_find_package_no_cache', $safe_slug, $filename, $this->cache );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1249,7 +1315,7 @@ class Update_Server {
|
||||||
$this->self_hosted
|
$this->self_hosted
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $this->update_checker ) {
|
if ( $this->update_checker && $this->update_checker->slug === $slug ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,23 @@ use Anyape\UpdatePulse\Package_Parser\Parser;
|
||||||
class Zip_Metadata_Parser {
|
class Zip_Metadata_Parser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int $cache_time How long the package metadata should be cached in seconds.
|
* Cache time
|
||||||
|
*
|
||||||
|
* How long the package metadata should be cached in seconds.
|
||||||
* Defaults to 1 week ( 7 * 24 * 60 * 60 ).
|
* Defaults to 1 week ( 7 * 24 * 60 * 60 ).
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static $cache_time = 604800;
|
public static $cache_time = 604800;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array Package PHP header mapping, i.e. which tags to add to the metadata under which array key
|
* Header map
|
||||||
|
*
|
||||||
|
* Package PHP header mapping, i.e. which tags to add to the metadata under which array key.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected $header_map = array(
|
protected $header_map = array(
|
||||||
'Name' => 'name',
|
'Name' => 'name',
|
||||||
|
|
@ -36,48 +46,75 @@ class Zip_Metadata_Parser {
|
||||||
'Depends' => 'depends',
|
'Depends' => 'depends',
|
||||||
'Provides' => 'provides',
|
'Provides' => 'provides',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array Plugin readme file mapping, i.e. which tags to add to the metadata
|
* Readme map
|
||||||
|
*
|
||||||
|
* Plugin readme file mapping, i.e. which tags to add to the metadata.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected $readme_map = array(
|
protected $readme_map = array(
|
||||||
'requires',
|
'requires',
|
||||||
'tested',
|
'tested',
|
||||||
'requires_php',
|
'requires_php',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array Package info as retrieved by the parser
|
* Package info
|
||||||
|
*
|
||||||
|
* Package info as retrieved by the parser.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected $package_info;
|
protected $package_info;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Path to the Zip archive that contains the package.
|
* Filename
|
||||||
|
*
|
||||||
|
* Path to the Zip archive that contains the package.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected $filename;
|
protected $filename;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Package slug.
|
* Slug
|
||||||
|
*
|
||||||
|
* Package slug.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected $slug;
|
protected $slug;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Cache object.
|
* Cache
|
||||||
|
*
|
||||||
|
* Cache object.
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected $cache;
|
protected $cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array Package metadata in a format suitable for the update checker.
|
* Metadata
|
||||||
|
*
|
||||||
|
* Package metadata in a format suitable for the update checker.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected $metadata;
|
protected $metadata;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
* Get the metadata from a zip file.
|
* Get the metadata from a zip file.
|
||||||
*
|
*
|
||||||
* @param string $slug
|
* @param string $slug Package slug.
|
||||||
* @param string $filename
|
* @param string $filename Path to the Zip archive.
|
||||||
* @param $cache
|
* @param object $cache Cache object.
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function __construct( $slug, $filename, $cache = null ) {
|
public function __construct( $slug, $filename, $cache = null ) {
|
||||||
$this->slug = $slug;
|
$this->slug = $slug;
|
||||||
|
|
@ -88,7 +125,14 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the cache key (cache filename) for a file
|
* Build cache key
|
||||||
|
*
|
||||||
|
* Build the cache key (cache filename) for a file.
|
||||||
|
*
|
||||||
|
* @param string $slug Package slug.
|
||||||
|
* @param string $filename Path to the Zip archive.
|
||||||
|
* @return string The cache key.
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function build_cache_key( $slug, $filename ) {
|
public static function build_cache_key( $slug, $filename ) {
|
||||||
$cache_key = $slug . '-b64-';
|
$cache_key = $slug . '-b64-';
|
||||||
|
|
@ -97,6 +141,15 @@ class Zip_Metadata_Parser {
|
||||||
$cache_key .= md5( $filename . '|' . filesize( $filename ) . '|' . filemtime( $filename ) );
|
$cache_key .= md5( $filename . '|' . filesize( $filename ) . '|' . filemtime( $filename ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the cache key used for storing package metadata.
|
||||||
|
*
|
||||||
|
* @param string $cache_key The generated cache key for the package.
|
||||||
|
* @param string $slug The package slug.
|
||||||
|
* @param string $filename The path to the Zip archive.
|
||||||
|
* @return string The filtered cache key.
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
return apply_filters(
|
return apply_filters(
|
||||||
'upserv_zip_metadata_parser_cache_key',
|
'upserv_zip_metadata_parser_cache_key',
|
||||||
$cache_key,
|
$cache_key,
|
||||||
|
|
@ -106,19 +159,26 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get metadata.
|
* Get metadata
|
||||||
*
|
*
|
||||||
* @return array
|
* Get the package metadata.
|
||||||
|
*
|
||||||
|
* @return array Package metadata.
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function get() {
|
public function get() {
|
||||||
return $this->metadata;
|
return $this->metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Set metadata
|
||||||
|
*
|
||||||
* Load metadata information from a cache or create it.
|
* Load metadata information from a cache or create it.
|
||||||
*
|
*
|
||||||
* We'll try to load processed metadata from the cache first (if available), and if that
|
* We'll try to load processed metadata from the cache first (if available), and if that
|
||||||
* fails we'll extract package details from the specified Zip file.
|
* fails we'll extract package details from the specified Zip file.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_metadata() {
|
protected function set_metadata() {
|
||||||
$cache_key = self::build_cache_key( $this->slug, $this->filename );
|
$cache_key = self::build_cache_key( $this->slug, $this->filename );
|
||||||
|
|
@ -151,10 +211,13 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Extract metadata
|
||||||
|
*
|
||||||
* Extract package headers and readme contents from a ZIP file and convert them
|
* Extract package headers and readme contents from a ZIP file and convert them
|
||||||
* into a structure compatible with the custom update checker.
|
* into a structure compatible with the custom update checker.
|
||||||
*
|
*
|
||||||
* @throws Invalid_Package_Exception if the input file can't be parsed as a package.
|
* @throws Invalid_Package_Exception if the input file can't be parsed as a package.
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function extract_metadata() {
|
protected function extract_metadata() {
|
||||||
$this->package_info = Parser::parse_package( $this->filename, true );
|
$this->package_info = Parser::parse_package( $this->filename, true );
|
||||||
|
|
@ -177,7 +240,11 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract relevant metadata from the package header information
|
* Set info from header
|
||||||
|
*
|
||||||
|
* Extract relevant metadata from the package header information.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_info_from_header() {
|
protected function set_info_from_header() {
|
||||||
|
|
||||||
|
|
@ -188,7 +255,11 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract relevant metadata from the plugin readme
|
* Set info from readme
|
||||||
|
*
|
||||||
|
* Extract relevant metadata from the plugin readme.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_info_from_readme() {
|
protected function set_info_from_readme() {
|
||||||
|
|
||||||
|
|
@ -202,14 +273,17 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract selected metadata from the retrieved package info
|
* Set mapped fields
|
||||||
|
*
|
||||||
|
* Extract selected metadata from the retrieved package info.
|
||||||
*
|
*
|
||||||
* @see http://codex.wordpress.org/File_Header
|
* @see http://codex.wordpress.org/File_Header
|
||||||
* @see https://wordpress.org/plugins/about/readme.txt
|
* @see https://wordpress.org/plugins/about/readme.txt
|
||||||
*
|
*
|
||||||
* @param array $input The package info sub-array to use to retrieve the info from
|
* @param array $input The package info sub-array to use to retrieve the info from.
|
||||||
* @param array $map The key mapping for that sub-array where the key is the key as used in the
|
* @param array $map The key mapping for that sub-array where the key is the key as used in the
|
||||||
* input array and the value is the key to use for the output array
|
* input array and the value is the key to use for the output array.
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_mapped_fields( $input, $map ) {
|
protected function set_mapped_fields( $input, $map ) {
|
||||||
|
|
||||||
|
|
@ -222,11 +296,15 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the details url for themes
|
* Set theme details URL
|
||||||
|
*
|
||||||
|
* Determine the details url for themes.
|
||||||
*
|
*
|
||||||
* Theme metadata should include a "details_url" that specifies the page to display
|
* Theme metadata should include a "details_url" that specifies the page to display
|
||||||
* when the user clicks "View version x.y.z details". If the developer didn't provide
|
* when the user clicks "View version x.y.z details". If the developer didn't provide
|
||||||
* it by setting the "Details URI" header, we'll default to the theme homepage ( "Theme URI" ).
|
* it by setting the "Details URI" header, we'll default to the theme homepage ( "Theme URI" ).
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_theme_details_url() {
|
protected function set_theme_details_url() {
|
||||||
|
|
||||||
|
|
@ -239,9 +317,12 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the texual information sections from a readme file
|
* Set readme sections
|
||||||
|
*
|
||||||
|
* Extract the texual information sections from a readme file.
|
||||||
*
|
*
|
||||||
* @see https://wordpress.org/plugins/about/readme.txt
|
* @see https://wordpress.org/plugins/about/readme.txt
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_readme_sections() {
|
protected function set_readme_sections() {
|
||||||
|
|
||||||
|
|
@ -263,9 +344,12 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the upgrade notice for the current version from a readme file
|
* Set readme upgrade notice
|
||||||
|
*
|
||||||
|
* Extract the upgrade notice for the current version from a readme file.
|
||||||
*
|
*
|
||||||
* @see https://wordpress.org/plugins/about/readme.txt
|
* @see https://wordpress.org/plugins/about/readme.txt
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_readme_upgrade_notice() {
|
protected function set_readme_upgrade_notice() {
|
||||||
|
|
||||||
|
|
@ -282,7 +366,11 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add last update date to the metadata ; this is tied to the version
|
* Set last update date
|
||||||
|
*
|
||||||
|
* Add last update date to the metadata; this is tied to the version.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_last_update_date() {
|
protected function set_last_update_date() {
|
||||||
|
|
||||||
|
|
@ -309,10 +397,24 @@ class Zip_Metadata_Parser {
|
||||||
$this->metadata['last_updated'] = $meta['version_time'];
|
$this->metadata['last_updated'] = $meta['version_time'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set type
|
||||||
|
*
|
||||||
|
* Set the package type in the metadata.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function set_type() {
|
protected function set_type() {
|
||||||
$this->metadata['type'] = $this->package_info['type'];
|
$this->metadata['type'] = $this->package_info['type'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set slug
|
||||||
|
*
|
||||||
|
* Set the package slug in the metadata.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function set_slug() {
|
protected function set_slug() {
|
||||||
|
|
||||||
if ( 'plugin' === $this->package_info['type'] ) {
|
if ( 'plugin' === $this->package_info['type'] ) {
|
||||||
|
|
@ -327,7 +429,11 @@ class Zip_Metadata_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract icons and banners info for plugins
|
* Set info from assets
|
||||||
|
*
|
||||||
|
* Extract icons and banners info for plugins.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected function set_info_from_assets() {
|
protected function set_info_from_assets() {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,43 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
use WP_List_Table;
|
use WP_List_Table;
|
||||||
use Anyape\Utils\Utils;
|
use Anyape\Utils\Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Licenses table class
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
class Licenses_Table extends WP_List_Table {
|
class Licenses_Table extends WP_List_Table {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk action error
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public $bulk_action_error;
|
public $bulk_action_error;
|
||||||
|
/**
|
||||||
|
* Nonce action name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public $nonce_action;
|
public $nonce_action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table rows data
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected $rows;
|
protected $rows;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* Sets up the table properties and hooks
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
parent::__construct(
|
parent::__construct(
|
||||||
array(
|
array(
|
||||||
|
|
@ -34,6 +64,14 @@ class Licenses_Table extends WP_List_Table {
|
||||||
|
|
||||||
// Overrides ---------------------------------------------------
|
// Overrides ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get table columns
|
||||||
|
*
|
||||||
|
* Define the columns for the licenses table
|
||||||
|
*
|
||||||
|
* @return array The table columns
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function get_columns() {
|
public function get_columns() {
|
||||||
return array(
|
return array(
|
||||||
'cb' => '<input type="checkbox" />',
|
'cb' => '<input type="checkbox" />',
|
||||||
|
|
@ -48,10 +86,28 @@ class Licenses_Table extends WP_List_Table {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default column rendering
|
||||||
|
*
|
||||||
|
* Default handler for displaying column data
|
||||||
|
*
|
||||||
|
* @param array $item The row item
|
||||||
|
* @param string $column_name The column name
|
||||||
|
* @return mixed The column value
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function column_default( $item, $column_name ) {
|
public function column_default( $item, $column_name ) {
|
||||||
return $item[ $column_name ];
|
return $item[ $column_name ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sortable columns
|
||||||
|
*
|
||||||
|
* Define which columns can be sorted
|
||||||
|
*
|
||||||
|
* @return array The sortable columns
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function get_sortable_columns() {
|
public function get_sortable_columns() {
|
||||||
return array(
|
return array(
|
||||||
'col_status' => array( 'status', false ),
|
'col_status' => array( 'status', false ),
|
||||||
|
|
@ -64,6 +120,13 @@ class Licenses_Table extends WP_List_Table {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare table items
|
||||||
|
*
|
||||||
|
* Query the database and set up the items for display
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function prepare_items() {
|
public function prepare_items() {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
|
|
@ -174,6 +237,13 @@ class Licenses_Table extends WP_List_Table {
|
||||||
$this->items = $items;
|
$this->items = $items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display table rows
|
||||||
|
*
|
||||||
|
* Output the HTML for each row in the table
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function display_rows() {
|
public function display_rows() {
|
||||||
$records = $this->items;
|
$records = $this->items;
|
||||||
$table = $this;
|
$table = $this;
|
||||||
|
|
@ -214,6 +284,14 @@ class Licenses_Table extends WP_List_Table {
|
||||||
|
|
||||||
// Misc. -------------------------------------------------------
|
// Misc. -------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set table rows
|
||||||
|
*
|
||||||
|
* Set the row data for the table
|
||||||
|
*
|
||||||
|
* @param array $rows The rows data
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function set_rows( $rows ) {
|
public function set_rows( $rows ) {
|
||||||
$this->rows = $rows;
|
$this->rows = $rows;
|
||||||
}
|
}
|
||||||
|
|
@ -224,6 +302,16 @@ class Licenses_Table extends WP_List_Table {
|
||||||
|
|
||||||
// Overrides ---------------------------------------------------
|
// Overrides ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate row actions
|
||||||
|
*
|
||||||
|
* Create action links for each row
|
||||||
|
*
|
||||||
|
* @param array $actions The actions array
|
||||||
|
* @param bool $always_visible Whether actions should be always visible
|
||||||
|
* @return string HTML for the row actions
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function row_actions( $actions, $always_visible = false ) {
|
protected function row_actions( $actions, $always_visible = false ) {
|
||||||
$action_count = count( $actions );
|
$action_count = count( $actions );
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
|
@ -248,6 +336,14 @@ class Licenses_Table extends WP_List_Table {
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display extra tablenav
|
||||||
|
*
|
||||||
|
* Add additional controls above or below the table
|
||||||
|
*
|
||||||
|
* @param string $which The location ('top' or 'bottom')
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function extra_tablenav( $which ) {
|
protected function extra_tablenav( $which ) {
|
||||||
|
|
||||||
if ( 'bottom' === $which ) {
|
if ( 'bottom' === $which ) {
|
||||||
|
|
@ -255,6 +351,14 @@ class Licenses_Table extends WP_List_Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get bulk actions
|
||||||
|
*
|
||||||
|
* Define available bulk actions for the table
|
||||||
|
*
|
||||||
|
* @return array The available bulk actions
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function get_bulk_actions() {
|
protected function get_bulk_actions() {
|
||||||
$actions = array(
|
$actions = array(
|
||||||
'pending' => __( 'Set to Pending', 'updatepulse-server' ),
|
'pending' => __( 'Set to Pending', 'updatepulse-server' ),
|
||||||
|
|
@ -268,6 +372,14 @@ class Licenses_Table extends WP_List_Table {
|
||||||
return $actions;
|
return $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get table classes
|
||||||
|
*
|
||||||
|
* Define CSS classes for the table
|
||||||
|
*
|
||||||
|
* @return array The table CSS classes
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function get_table_classes() {
|
protected function get_table_classes() {
|
||||||
$mode = get_user_setting( 'posts_list_mode', 'list' );
|
$mode = get_user_setting( 'posts_list_mode', 'list' );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,51 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
use WP_List_Table;
|
use WP_List_Table;
|
||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packages Table class
|
||||||
|
*
|
||||||
|
* Manages the display of packages in the admin area
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
class Packages_Table extends WP_List_Table {
|
class Packages_Table extends WP_List_Table {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk action error message
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public $bulk_action_error;
|
public $bulk_action_error;
|
||||||
|
/**
|
||||||
|
* Nonce action name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public $nonce_action;
|
public $nonce_action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table rows data
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected $rows;
|
protected $rows;
|
||||||
|
/**
|
||||||
|
* Package manager instance
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected $package_manager;
|
protected $package_manager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param object $package_manager The package manager instance
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function __construct( $package_manager ) {
|
public function __construct( $package_manager ) {
|
||||||
parent::__construct(
|
parent::__construct(
|
||||||
array(
|
array(
|
||||||
|
|
@ -36,7 +73,22 @@ class Packages_Table extends WP_List_Table {
|
||||||
|
|
||||||
// Overrides ---------------------------------------------------
|
// Overrides ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get table columns
|
||||||
|
*
|
||||||
|
* Define the columns shown in the packages table.
|
||||||
|
*
|
||||||
|
* @return array Table columns
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function get_columns() {
|
public function get_columns() {
|
||||||
|
/**
|
||||||
|
* Filter the columns shown in the packages table.
|
||||||
|
*
|
||||||
|
* @param array $columns The default columns for the packages table
|
||||||
|
* @return array The filtered columns
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$columns = apply_filters(
|
$columns = apply_filters(
|
||||||
'upserv_packages_table_columns',
|
'upserv_packages_table_columns',
|
||||||
array(
|
array(
|
||||||
|
|
@ -54,11 +106,36 @@ class Packages_Table extends WP_List_Table {
|
||||||
return $columns;
|
return $columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default column renderer
|
||||||
|
*
|
||||||
|
* Default handler for columns without specific renderers.
|
||||||
|
*
|
||||||
|
* @param array $item The current row item
|
||||||
|
* @param string $column_name The current column name
|
||||||
|
* @return mixed Column content
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function column_default( $item, $column_name ) {
|
public function column_default( $item, $column_name ) {
|
||||||
return $item[ $column_name ];
|
return $item[ $column_name ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sortable columns
|
||||||
|
*
|
||||||
|
* Define which columns can be sorted in the table.
|
||||||
|
*
|
||||||
|
* @return array Sortable columns configuration
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function get_sortable_columns() {
|
public function get_sortable_columns() {
|
||||||
|
/**
|
||||||
|
* Filter the sortable columns in the packages table.
|
||||||
|
*
|
||||||
|
* @param array $columns The default sortable columns
|
||||||
|
* @return array The filtered sortable columns
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$columns = apply_filters(
|
$columns = apply_filters(
|
||||||
'upserv_packages_table_sortable_columns',
|
'upserv_packages_table_sortable_columns',
|
||||||
array(
|
array(
|
||||||
|
|
@ -75,6 +152,13 @@ class Packages_Table extends WP_List_Table {
|
||||||
return $columns;
|
return $columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare table items
|
||||||
|
*
|
||||||
|
* Process data for table display including pagination.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function prepare_items() {
|
public function prepare_items() {
|
||||||
$total_items = count( $this->rows );
|
$total_items = count( $this->rows );
|
||||||
$offset = 0;
|
$offset = 0;
|
||||||
|
|
@ -111,7 +195,13 @@ class Packages_Table extends WP_List_Table {
|
||||||
uasort( $this->items, array( &$this, 'uasort_reorder' ) );
|
uasort( $this->items, array( &$this, 'uasort_reorder' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display table rows
|
||||||
|
*
|
||||||
|
* Render the rows of the packages table.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function display_rows() {
|
public function display_rows() {
|
||||||
$records = $this->items;
|
$records = $this->items;
|
||||||
$table = $this;
|
$table = $this;
|
||||||
|
|
@ -206,10 +296,28 @@ class Packages_Table extends WP_List_Table {
|
||||||
|
|
||||||
// Misc. -------------------------------------------------------
|
// Misc. -------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set table rows
|
||||||
|
*
|
||||||
|
* Set the rows data for the table.
|
||||||
|
*
|
||||||
|
* @param array $rows Table rows data
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function set_rows( $rows ) {
|
public function set_rows( $rows ) {
|
||||||
$this->rows = $rows;
|
$this->rows = $rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom sorting function
|
||||||
|
*
|
||||||
|
* Sort table items based on request parameters.
|
||||||
|
*
|
||||||
|
* @param array $a First item to compare
|
||||||
|
* @param array $b Second item to compare
|
||||||
|
* @return int Comparison result
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function uasort_reorder( $a, $b ) {
|
public function uasort_reorder( $a, $b ) {
|
||||||
$order_by = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) : 'name'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
$order_by = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) : 'name'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||||
$order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) : 'asc'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
$order = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) : 'asc'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||||
|
|
@ -242,6 +350,14 @@ class Packages_Table extends WP_List_Table {
|
||||||
|
|
||||||
// Overrides ---------------------------------------------------
|
// Overrides ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display extra table navigation
|
||||||
|
*
|
||||||
|
* Add additional controls above or below the table.
|
||||||
|
*
|
||||||
|
* @param string $which Position ('top' or 'bottom')
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function extra_tablenav( $which ) {
|
protected function extra_tablenav( $which ) {
|
||||||
|
|
||||||
if ( 'top' === $which ) {
|
if ( 'top' === $which ) {
|
||||||
|
|
@ -258,6 +374,14 @@ class Packages_Table extends WP_List_Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get table CSS classes
|
||||||
|
*
|
||||||
|
* Define the CSS classes for the table.
|
||||||
|
*
|
||||||
|
* @return array Table CSS classes
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function get_table_classes() {
|
protected function get_table_classes() {
|
||||||
$mode = get_user_setting( 'posts_list_mode', 'list' );
|
$mode = get_user_setting( 'posts_list_mode', 'list' );
|
||||||
$mode_class = esc_attr( 'table-view-' . $mode );
|
$mode_class = esc_attr( 'table-view-' . $mode );
|
||||||
|
|
@ -265,7 +389,22 @@ class Packages_Table extends WP_List_Table {
|
||||||
return array( 'widefat', 'striped', $mode_class, $this->_args['plural'] );
|
return array( 'widefat', 'striped', $mode_class, $this->_args['plural'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get bulk actions
|
||||||
|
*
|
||||||
|
* Define available bulk actions for the table.
|
||||||
|
*
|
||||||
|
* @return array Bulk actions
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function get_bulk_actions() {
|
protected function get_bulk_actions() {
|
||||||
|
/**
|
||||||
|
* Filter the bulk actions available in the packages table.
|
||||||
|
*
|
||||||
|
* @param array $actions The default bulk actions
|
||||||
|
* @return array The filtered bulk actions
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
$actions = apply_filters(
|
$actions = apply_filters(
|
||||||
'upserv_packages_table_bulk_actions',
|
'upserv_packages_table_bulk_actions',
|
||||||
array(
|
array(
|
||||||
|
|
@ -277,6 +416,15 @@ class Packages_Table extends WP_List_Table {
|
||||||
return $actions;
|
return $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get VCS icon class
|
||||||
|
*
|
||||||
|
* Get the appropriate icon class for a VCS provider.
|
||||||
|
*
|
||||||
|
* @param array $vcs_config VCS configuration
|
||||||
|
* @return string CSS class for the VCS icon
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
protected function get_vcs_class( $vcs_config ) {
|
protected function get_vcs_class( $vcs_config ) {
|
||||||
|
|
||||||
switch ( $vcs_config['type'] ) {
|
switch ( $vcs_config['type'] ) {
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
printf(
|
printf(
|
||||||
// translators: %s is <code>upserv_download_remote_package( string $package_slug, string $type );</code>
|
// translators: %s is <code>upserv_download_remote_package( string $package_slug, string $type );</code>
|
||||||
esc_html__( '[expert] calling the %s method in your own code, with the VCS-related parameters corresponding to a VCS configuration saved in UpdatePulse Server', 'updatepulse-server' ),
|
esc_html__( '[expert] calling the %s method in your own code, with the VCS-related parameters corresponding to a VCS configuration saved in UpdatePulse Server', 'updatepulse-server' ),
|
||||||
'<code>upserv_download_remote_package( string $package_slug, string $type, string $vcs_url = false, string branch = \'main\');</code>'
|
'<code>upserv_download_remote_package( string $package_slug, string $type, string $vcs_url = false, string branch = \'main\' );</code>'
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -285,7 +285,7 @@ Licensed With: another-plugin-or-theme-slug</pre><br>
|
||||||
// translators: %1$s is a link to opening an issue, %2$s is a contact email
|
// translators: %1$s is a link to opening an issue, %2$s is a contact email
|
||||||
esc_html__( 'After reading the documentation, for more help on how to use UpdatePulse Server, please %1$s - bugfixes are welcome via pull requests, detailed bug reports with accurate pointers as to where and how they occur in the code will be addressed in a timely manner, and a fee will apply for any other request (if they are addressed). If and only if you found a security issue, please contact %2$s with full details for responsible disclosure.', 'updatepulse-server' ),
|
esc_html__( 'After reading the documentation, for more help on how to use UpdatePulse Server, please %1$s - bugfixes are welcome via pull requests, detailed bug reports with accurate pointers as to where and how they occur in the code will be addressed in a timely manner, and a fee will apply for any other request (if they are addressed). If and only if you found a security issue, please contact %2$s with full details for responsible disclosure.', 'updatepulse-server' ),
|
||||||
'<a target="_blank" href="https://github.com/anyape/updatepulse-server/issues">' . esc_html__( 'open an issue on Github', 'updatepulse-server' ) . '</a>',
|
'<a target="_blank" href="https://github.com/anyape/updatepulse-server/issues">' . esc_html__( 'open an issue on Github', 'updatepulse-server' ) . '</a>',
|
||||||
'<a href="mailto:updatepulse@anyape.come">updatepulse@anyape.com</a>',
|
'<a href="mailto:updatepulse@anyape.com">updatepulse@anyape.com</a>',
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,16 @@
|
||||||
<td>
|
<td>
|
||||||
<input class="vcs-setting regular-text" type="text" id="upserv_vcs_branch" data-prop="branch" value="">
|
<input class="vcs-setting regular-text" type="text" id="upserv_vcs_branch" data-prop="branch" value="">
|
||||||
<p class="description">
|
<p class="description">
|
||||||
<?php esc_html_e( 'The branch to download when getting remote packages from the Version Control System.', 'updatepulse-server' ); ?>
|
<?php
|
||||||
|
printf(
|
||||||
|
// translators: %1$s line break, %2$s is <code>PUC_FORCE_BRANCH</code>, %3$s is <code>true</code>, %4$s is <code>wp-config.php</code>
|
||||||
|
esc_html__( 'The branch to download when getting remote packages from the Version Control System.%1$sIf the VCS supports releases or tags, they will be prioritised over the branch name (release first, then tag, then branch).%1$sTo bypass this behaviour and exclusively rely on the branch, set the %2$s constant to %3$s in %4$s.', 'updatepulse-server' ),
|
||||||
|
'<br/>',
|
||||||
|
'<code>PUC_FORCE_BRANCH</code>',
|
||||||
|
'<code>true</code>',
|
||||||
|
'<code>wp-config.php</code>'
|
||||||
|
);
|
||||||
|
?>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -295,7 +304,16 @@
|
||||||
<td>
|
<td>
|
||||||
<input class="regular-text" type="text" id="upserv_add_vcs_branch" data-prop="branch" value="">
|
<input class="regular-text" type="text" id="upserv_add_vcs_branch" data-prop="branch" value="">
|
||||||
<p class="description">
|
<p class="description">
|
||||||
<?php esc_html_e( 'The branch to download when getting remote packages from the Version Control System.', 'updatepulse-server' ); ?>
|
<?php
|
||||||
|
printf(
|
||||||
|
// translators: %1$s line break, %2$s is <code>PUC_FORCE_BRANCH</code>, %3$s is <code>true</code>, %4$s is <code>wp-config.php</code>
|
||||||
|
esc_html__( 'The branch to download when getting remote packages from the Version Control System.%1$sIf the VCS supports releases or tags, they will be prioritised over the branch name (release first, then tag, then branch).%1$sTo bypass this behaviour and exclusively rely on the branch, set the %2$s constant to %3$s in %4$s.', 'updatepulse-server' ),
|
||||||
|
'<br/>',
|
||||||
|
'<code>PUC_FORCE_BRANCH</code>',
|
||||||
|
'<code>true</code>',
|
||||||
|
'<code>wp-config.php</code>'
|
||||||
|
);
|
||||||
|
?>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,10 @@ if ( ! class_exists( BitbucketApi::class, false ) ) :
|
||||||
return $this->get_branch( $config_branch );
|
return $this->get_branch( $config_branch );
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( ( 'main' === $config_branch || 'master' === $config_branch ) ) {
|
if (
|
||||||
|
( 'main' === $config_branch || 'master' === $config_branch ) &&
|
||||||
|
( ! defined( 'PUC_FORCE_BRANCH' ) || ! (bool) ( constant( 'PUC_FORCE_BRANCH' ) ) )
|
||||||
|
) {
|
||||||
$strategies[ self::STRATEGY_LATEST_TAG ] = array( $this, 'get_latest_tag' );
|
$strategies[ self::STRATEGY_LATEST_TAG ] = array( $this, 'get_latest_tag' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -458,7 +458,10 @@ if ( ! class_exists( GitHubApi::class, false ) ) :
|
||||||
protected function get_update_detection_strategies( $config_branch ) {
|
protected function get_update_detection_strategies( $config_branch ) {
|
||||||
$strategies = array();
|
$strategies = array();
|
||||||
|
|
||||||
if ( 'main' === $config_branch || 'master' === $config_branch ) {
|
if (
|
||||||
|
( 'main' === $config_branch || 'master' === $config_branch ) &&
|
||||||
|
( ! defined( 'PUC_FORCE_BRANCH' ) || ! (bool) ( constant( 'PUC_FORCE_BRANCH' ) ) )
|
||||||
|
) {
|
||||||
// Use the latest release.
|
// Use the latest release.
|
||||||
$strategies[ self::STRATEGY_LATEST_RELEASE ] = array( $this, 'get_latest_release' );
|
$strategies[ self::STRATEGY_LATEST_RELEASE ] = array( $this, 'get_latest_release' );
|
||||||
// Failing that, use the tag with the highest version number.
|
// Failing that, use the tag with the highest version number.
|
||||||
|
|
|
||||||
|
|
@ -440,7 +440,10 @@ if ( ! class_exists( GitLabApi::class, false ) ) :
|
||||||
protected function get_update_detection_strategies( $config_branch ) {
|
protected function get_update_detection_strategies( $config_branch ) {
|
||||||
$strategies = array();
|
$strategies = array();
|
||||||
|
|
||||||
if ( ( 'main' === $config_branch ) || ( 'master' === $config_branch ) ) {
|
if (
|
||||||
|
( 'main' === $config_branch ) || ( 'master' === $config_branch ) &&
|
||||||
|
( ! defined( 'PUC_FORCE_BRANCH' ) || ! (bool) ( constant( 'PUC_FORCE_BRANCH' ) ) )
|
||||||
|
) {
|
||||||
$strategies[ self::STRATEGY_LATEST_RELEASE ] = array( $this, 'get_latest_release' );
|
$strategies[ self::STRATEGY_LATEST_RELEASE ] = array( $this, 'get_latest_release' );
|
||||||
$strategies[ self::STRATEGY_LATEST_TAG ] = array( $this, 'get_latest_tag' );
|
$strategies[ self::STRATEGY_LATEST_TAG ] = array( $this, 'get_latest_tag' );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
37
readme.txt
37
readme.txt
|
|
@ -1,9 +1,10 @@
|
||||||
=== UpdatePulse Server ===
|
=== UpdatePulse Server ===
|
||||||
Contributors: frogerme
|
Contributors: frogerme
|
||||||
|
Donate link: https://paypal.me/frogerme
|
||||||
Tags: Plugin updates, Theme updates, WordPress updates, License
|
Tags: Plugin updates, Theme updates, WordPress updates, License
|
||||||
Requires at least: 6.7
|
Requires at least: 6.7
|
||||||
Tested up to: 6.7
|
Tested up to: 6.7
|
||||||
Stable tag: 1.0.6
|
Stable tag: 1.0.10
|
||||||
Requires PHP: 8.0
|
Requires PHP: 8.0
|
||||||
License: GPLv2 or later
|
License: GPLv2 or later
|
||||||
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
@ -46,6 +47,15 @@ This plugin adds the following major features to WordPress:
|
||||||
* **API:** UpdatePulse Server provides APIs to manage packages and licenses. The APIs keys are secured with a system of tokens: the API keys are never shared over the network, acquiring a token requires signed payloads, and the tokens have a limited lifetime. For more details about tokens and security, see [the Nonce API documentation](https://github.com/anyape/updatepulse-server/blob/main/docs/misc.md#nonce-api).
|
* **API:** UpdatePulse Server provides APIs to manage packages and licenses. The APIs keys are secured with a system of tokens: the API keys are never shared over the network, acquiring a token requires signed payloads, and the tokens have a limited lifetime. For more details about tokens and security, see [the Nonce API documentation](https://github.com/anyape/updatepulse-server/blob/main/docs/misc.md#nonce-api).
|
||||||
|
|
||||||
To connect their plugins or themes and UpdatePulse Server, developers can find integration examples in the [UpdatePulse Server Integration Examples](https://github.com/Anyape/updatepulse-server-integration) repository - theme and plugin examples rely heavily on the popular [Plugin Update Checker](https://github.com/YahnisElsts/plugin-update-checker) by [Yahnis Elsts](https://github.com/YahnisElsts).
|
To connect their plugins or themes and UpdatePulse Server, developers can find integration examples in the [UpdatePulse Server Integration Examples](https://github.com/Anyape/updatepulse-server-integration) repository - theme and plugin examples rely heavily on the popular [Plugin Update Checker](https://github.com/YahnisElsts/plugin-update-checker) by [Yahnis Elsts](https://github.com/YahnisElsts).
|
||||||
|
== Companion Plugins ==
|
||||||
|
|
||||||
|
The following plugins are compatible with UpdatePulse Server and can be used to extend its functionality:
|
||||||
|
* [Updatepulse Blocks](https://store.anyape.com/product/updatepulse-blocks/?wl=1): a seamless way to display packages from UpdatePulse Server directly within your site using the WordPress Block Editor or shortcodes.
|
||||||
|
* [UpdatePulse for WooCommerce](https://store.anyape.com/product/updatepulse-for-woocommerce/?wl=1): a WooCommerce connector for UpdatePulse Server, allowing you to sell licensed packages through your WooCommerce store, either on the same WordPress installation or a separate store site.
|
||||||
|
|
||||||
|
Developers are encouraged to build plugins and themes [integrated](https://github.com/anyape/updatepulse-server/blob/main/README.md) with UpdatePulse Server, leveraging its publicly available functions, actions and filters, or by making use of the provided APIs.
|
||||||
|
|
||||||
|
If you wish to see your plugin added to this list, please [contact the author](mailto:updatepulse@anyape.com).
|
||||||
|
|
||||||
== Troubleshooting ==
|
== Troubleshooting ==
|
||||||
|
|
||||||
|
|
@ -61,6 +71,15 @@ Each **bug** report will be addressed in a timely manner if properly documented
|
||||||
|
|
||||||
**Troubleshooting involving 3rd-party plugins or themes will not be addressed on the WordPress support forum.**
|
**Troubleshooting involving 3rd-party plugins or themes will not be addressed on the WordPress support forum.**
|
||||||
|
|
||||||
|
== Upgrade Notice ==
|
||||||
|
|
||||||
|
= 1.0.9 =
|
||||||
|
|
||||||
|
For installations using VCS in schedule mode (as opposed to webhook mode):
|
||||||
|
- delete all packages and re-register them
|
||||||
|
- remove any remaining `json` files from `wp-content/uploads/updatepulse-server/metadata` folder
|
||||||
|
- use the "Force Clear & Reschedule" button in the VCS settings
|
||||||
|
|
||||||
== FAQ ==
|
== FAQ ==
|
||||||
|
|
||||||
= How do I use UpdatePulse Server? =
|
= How do I use UpdatePulse Server? =
|
||||||
|
|
@ -119,6 +138,22 @@ This section describes how to install the plugin and get it working.
|
||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 1.0.10 =
|
||||||
|
* Introduce constant `PUC_FORCE_BRANCH` to bypass tags & releases in VCS detection strategies
|
||||||
|
* Minor fix
|
||||||
|
* Fix activation issue - `WP_Filesystem` call
|
||||||
|
|
||||||
|
= 1.0.9 =
|
||||||
|
* Schedule mode: remove package metadata files when deleting packages
|
||||||
|
* Schedule mode: make sure to reinitialise the update checker to avoid slug conflicts
|
||||||
|
|
||||||
|
= 1.0.8 =
|
||||||
|
* Fix scheduled mode package overrides. After update, if using this mode: delete all packages and re-register them ; remove any remaining `json` files from `wp-content/uploads/updatepulse-server/metadata` folder ; use the "Force Clear & Reschedule" button in the VCS settings
|
||||||
|
* Fix VCS candidates with webhook mode
|
||||||
|
|
||||||
|
= 1.0.7 =
|
||||||
|
* Full documentation of all classes and functions
|
||||||
|
|
||||||
= 1.0.6 =
|
= 1.0.6 =
|
||||||
* Fix webhook payload handling (thanks @eHtmlu on github)
|
* Fix webhook payload handling (thanks @eHtmlu on github)
|
||||||
* Fix webhook payload scheduling (thanks @BabaYaga0179 on github)
|
* Fix webhook payload scheduling (thanks @BabaYaga0179 on github)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Plugin Name: UpdatePulse Server
|
* Plugin Name: UpdatePulse Server
|
||||||
* Plugin URI: https://github.com/anyape/updatepulse-server/
|
* Plugin URI: https://github.com/anyape/updatepulse-server/
|
||||||
* Description: Run your own update server.
|
* Description: Run your own update server.
|
||||||
* Version: 1.0.6
|
* Version: 1.0.10
|
||||||
* Author: Alexandre Froger
|
* Author: Alexandre Froger
|
||||||
* Author URI: https://froger.me/
|
* Author URI: https://froger.me/
|
||||||
* License: GPLv2 or later
|
* License: GPLv2 or later
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue