updatepulse-server/inc/manager/class-remote-sources-manager.php
2025-04-10 13:14:29 +08:00

911 lines
26 KiB
PHP

<?php
namespace Anyape\UpdatePulse\Server\Manager;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
use WP_Error;
use Anyape\UpdatePulse\Server\Manager\Data_Manager;
use Anyape\UpdatePulse\Server\API\Update_API;
use Anyape\UpdatePulse\Server\Scheduler\Scheduler;
/**
* Remote Sources Manager class
*
* @since 1.0.0
*/
class Remote_Sources_Manager {
/**
* Constructor
*
* @param boolean $init_hooks Whether to initialize WordPress hooks.
* @since 1.0.0
*/
public function __construct( $init_hooks = false ) {
if ( $init_hooks ) {
if ( upserv_get_option( 'use_vcs' ) ) {
add_action( 'upserv_scheduler_init', array( $this, 'register_remote_check_scheduled_hooks' ), 10, 0 );
} else {
add_action( 'init', array( $this, 'clear_remote_check_scheduled_hooks' ), 10, 0 );
}
add_action( 'wp_ajax_upserv_force_clean', array( $this, 'force_clean' ), 10, 0 );
add_action( 'wp_ajax_upserv_vcs_test', array( $this, 'vcs_test' ), 10, 0 );
add_action( 'admin_menu', array( $this, 'admin_menu' ), 15, 0 );
add_filter( 'upserv_admin_scripts', array( $this, 'upserv_admin_scripts' ), 10, 1 );
add_filter( 'upserv_admin_styles', array( $this, 'upserv_admin_styles' ), 10, 1 );
add_filter( 'upserv_admin_tab_links', array( $this, 'upserv_admin_tab_links' ), 15, 1 );
add_filter( 'upserv_admin_tab_states', array( $this, 'upserv_admin_tab_states' ), 15, 2 );
}
}
/*******************************************************************
* Public methods
*******************************************************************/
// WordPress hooks ---------------------------------------------
/**
* Activate
*
* Register schedules when the plugin is activated.
*
* @since 1.0.0
*/
public static function activate() {
self::register_schedules();
}
/**
* Deactivate
*
* Clear schedules when the plugin is deactivated.
*
* @since 1.0.0
*/
public static function deactivate() {
self::clear_schedules();
}
/**
* Enqueue admin scripts
*
* @param array $scripts List of scripts to enqueue.
* @return array Modified list of scripts.
* @since 1.0.0
*/
public function upserv_admin_scripts( $scripts ) {
$page = ! empty( $_REQUEST['page'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( 'upserv-page-remote-sources' !== $page ) {
return $scripts;
}
$scripts['remote_sources'] = array(
'path' => UPSERV_PLUGIN_PATH . 'js/admin/remote-sources' . upserv_assets_suffix() . '.js',
'uri' => UPSERV_PLUGIN_URL . 'js/admin/remote-sources' . upserv_assets_suffix() . '.js',
'deps' => array( 'jquery' ),
);
return $scripts;
}
/**
* Enqueue admin styles
*
* @param array $styles List of styles to enqueue.
* @return array Modified list of styles.
* @since 1.0.0
*/
public function upserv_admin_styles( $styles ) {
$styles['remote_sources'] = array(
'path' => UPSERV_PLUGIN_PATH . 'css/admin/remote-sources' . upserv_assets_suffix() . '.css',
'uri' => UPSERV_PLUGIN_URL . 'css/admin/remote-sources' . upserv_assets_suffix() . '.css',
);
return $styles;
}
/**
* Register remote check scheduled hooks
*
* @since 1.0.0
*/
public function register_remote_check_scheduled_hooks() {
if ( upserv_is_doing_update_api_request() ) {
return;
}
$vcs_configs = upserv_get_option( 'vcs', array() );
if ( empty( $vcs_configs ) ) {
return;
}
$slugs = array();
foreach ( $vcs_configs as $vcs_c ) {
if ( ! isset( $vcs_c['url'] ) ) {
continue;
}
$slugs = $this->get_package_slugs( $vcs_c['url'] );
if ( empty( $slugs ) ) {
continue;
}
$api = Update_API::get_instance();
$action_hook = array( $api, 'download_remote_package' );
foreach ( $slugs as $slug ) {
add_action( 'upserv_check_remote_' . $slug, $action_hook, 10, 3 );
/**
* Fired after a remote check action has been registered for a package.
* Fired during client update API request.
*
* @param string $package_slug The slug of the package for which an action has been registered
* @param string $scheduled_hook The event hook the action has been registered to
* @param string $action_hook The action that has been registered
*/
do_action(
'upserv_registered_check_remote_schedule',
$slug,
'upserv_check_remote_' . $slug,
$action_hook
);
}
}
}
/**
* Clear remote check scheduled hooks
*
* @param array|null $vcs_configs VCS configurations.
* @return bool True on success, false on failure.
* @since 1.0.0
*/
public function clear_remote_check_scheduled_hooks( $vcs_configs = null ) {
if ( upserv_is_doing_update_api_request() ) {
return false;
}
if ( null === $vcs_configs ) {
$vcs_configs = upserv_get_option( 'vcs', array() );
}
if ( empty( $vcs_configs ) ) {
return true;
}
foreach ( $vcs_configs as $vcs_c ) {
if ( ! isset( $vcs_c['url'] ) ) {
continue;
}
$slugs = $this->get_package_slugs( $vcs_c['url'] );
if ( empty( $slugs ) ) {
continue;
}
foreach ( $slugs as $slug ) {
$scheduled_hook = 'upserv_check_remote_' . $slug;
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 );
}
}
return true;
}
/**
* Add admin menu
*
* @since 1.0.0
*/
public function admin_menu() {
$function = array( $this, 'plugin_page' );
$page_title = __( 'UpdatePulse Server - Version Control Systems ', 'updatepulse-server' );
$menu_title = __( 'Version Control Systems ', 'updatepulse-server' );
$menu_slug = 'upserv-page-remote-sources';
add_submenu_page( 'upserv-page', $page_title, $menu_title, 'manage_options', $menu_slug, $function );
}
/**
* Add admin tab links
*
* @param array $links List of admin tab links.
* @return array Modified list of admin tab links.
* @since 1.0.0
*/
public function upserv_admin_tab_links( $links ) {
$links['remote-sources'] = array(
admin_url( 'admin.php?page=upserv-page-remote-sources' ),
'<i class="fa-solid fa-code-commit"></i>' . __( 'Version Control Systems ', 'updatepulse-server' ),
);
return $links;
}
/**
* Add admin tab states
*
* @param array $states List of admin tab states.
* @param string $page Current admin page.
* @return array Modified list of admin tab states.
* @since 1.0.0
*/
public function upserv_admin_tab_states( $states, $page ) {
$states['remote-sources'] = 'upserv-page-remote-sources' === $page;
return $states;
}
/**
* Force clean
*
* @since 1.0.0
*/
public function force_clean() {
$result = false;
$type = false;
if (
! isset( $_REQUEST['nonce'] ) ||
! wp_verify_nonce(
sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ),
'upserv_plugin_options'
)
) {
return;
}
$type = sanitize_text_field( wp_unslash( filter_input( INPUT_POST, 'type' ) ) );
if ( 'schedules' !== $type ) {
return;
}
$data = filter_input( INPUT_POST, 'data', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$data = $data ? array_map( 'sanitize_text_field', wp_unslash( $data ) ) : false;
if ( ! $data || ! isset( $data['upserv_vcs_list'] ) ) {
return;
}
$vcs_configs = upserv_get_option( 'vcs', array() );
$key = $data['upserv_vcs_list'];
if ( isset( $vcs_configs[ $key ] ) ) {
$result = $this->clear_remote_check_scheduled_hooks( array( $vcs_configs[ $key ] ) );
}
if ( $result && ! $vcs_configs[ $key ]['use_webhooks'] ) {
$this->reschedule_remote_check_recurring_events( $vcs_configs[ $key ] );
}
if ( $result ) {
wp_send_json_success();
} else {
wp_send_json_error(
new WP_Error(
__METHOD__,
__( 'Error - check the packages directory is readable and not empty', 'updatepulse-server' )
)
);
}
}
/**
* VCS test
*
* @since 1.0.0
*/
public function vcs_test() {
$result = false;
if (
! isset( $_REQUEST['nonce'] ) ||
! wp_verify_nonce(
sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ),
'upserv_plugin_options'
)
) {
wp_send_json_error(
new WP_Error(
__METHOD__,
__( 'Error - Received invalid data; please reload the page and try again.', 'updatepulse-server' )
)
);
}
$data = filter_input( INPUT_POST, 'data', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$data = $data ? array_map( 'sanitize_text_field', wp_unslash( $data ) ) : false;
if ( ! $data ) {
wp_send_json_error(
new WP_Error(
__METHOD__,
__( 'Error - Received invalid data; please reload the page and try again.', 'updatepulse-server' )
)
);
}
require_once UPSERV_PLUGIN_PATH . 'lib/package-update-checker/package-update-checker.php';
$url = $data['upserv_vcs_url'];
$credentials = $data['upserv_vcs_credentials'];
$vcs_type = $data['upserv_vcs_type'];
$service = upserv_get_vcs_name( $vcs_type, 'edit' );
$api_class = $service ? 'Anyape\PackageUpdateChecker\Vcs\\' . $service . 'Api' : false;
$test_result = $api_class::test( $url, $credentials );
if ( true === $test_result ) {
$result = array( __( 'Version Control System was reached sucessfully.', 'updatepulse-server' ) );
} elseif ( false === $test_result ) {
$result = new WP_Error(
__METHOD__,
__( 'Error - Please check the provided Version Control System Credentials.', 'updatepulse-server' )
);
} elseif ( 'failed_org_check' === $test_result ) {
$result = new WP_Error(
__METHOD__,
__( 'Error - Please check the provided Version Control System URL.', 'updatepulse-server' )
. "\n"
. __( 'If you are using a fine-grained access token for an organisation, please check the provided token has the permissions to access members information.', 'updatepulse-server' )
);
} elseif ( 'missing_privileges' === $test_result ) {
$result = new WP_Error(
__METHOD__,
__( 'Error - Please check the provided Version Control System URL.', 'updatepulse-server' )
. "\n"
. __( 'Please also check the provided credentials have access to account information and repositories.', 'updatepulse-server' )
);
} else {
$result = new WP_Error(
__METHOD__,
__( 'Error - Please check the provided Version Control System URL.', 'updatepulse-server' )
);
}
if ( ! is_wp_error( $result ) ) {
wp_send_json_success( $result );
} else {
wp_send_json_error( $result );
}
}
// Misc. -------------------------------------------------------
/**
* Clear schedules
*
* @return bool True on success, false on failure.
* @since 1.0.0
*/
public static function clear_schedules() {
$manager = new self();
return $manager->clear_remote_check_scheduled_hooks();
}
/**
* Register schedules
*
* @since 1.0.0
*/
public static function register_schedules() {
$options = get_option( 'upserv_options' );
$options = json_decode( $options, true );
$options = $options ? $options : array();
$vcs_configs = isset( $options['vcs'] ) && ! empty( $options['vcs'] ) ? $options['vcs'] : array();
if ( empty( $vcs_configs ) ) {
return;
}
$manager = new self();
foreach ( $vcs_configs as $vcs_c ) {
if ( ! isset( $vcs_c['url'], $vcs_c['use_webhooks'] ) || $vcs_c['use_webhooks'] ) {
continue;
}
$manager->reschedule_remote_check_recurring_events( $vcs_c );
}
}
/**
* Reschedule remote check recurring events
*
* @param array $vcs_c VCS configuration.
* @return bool True on success, false on failure.
* @since 1.0.0
*/
public function reschedule_remote_check_recurring_events( $vcs_c ) {
if (
upserv_is_doing_update_api_request() ||
! isset( $vcs_c['url'], $vcs_c['use_webhooks'] ) ||
$vcs_c['use_webhooks']
) {
return false;
}
$slugs = $this->get_package_slugs( $vcs_c['url'] );
if ( empty( $slugs ) ) {
return false;
}
foreach ( $slugs as $slug ) {
$meta = upserv_get_package_metadata( $slug );
$type = isset( $meta['type'] ) ? $meta['type'] : null;
$hook = 'upserv_check_remote_' . $slug;
$params = array( $slug, $type, false );
/**
* Filter the frequency at which remote checks for updates are performed for a package.
*
* @param string $frequency The frequency at which remote checks are performed
* @param string $package_slug The slug of the package
*/
$frequency = apply_filters(
'upserv_check_remote_frequency',
isset( $vcs_c['check_frequency'] ) ? $vcs_c['check_frequency'] : 'daily',
$slug
);
$timestamp = time();
$schedules = wp_get_schedules();
Scheduler::get_instance()->unschedule_all_actions( $hook, $params );
/**
* 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, $hook );
$result = Scheduler::get_instance()->schedule_recurring_action(
$timestamp,
$schedules[ $frequency ]['interval'],
$hook,
$params
);
/**
* Fired after a remote check event has been scheduled for a package.
* Fired during client update API request.
*
* @param bool $result Whether the event was scheduled
* @param string $package_slug The slug of the package for which the event was scheduled
* @param int $timestamp Timestamp for when to run the event the first time after it's been scheduled
* @param string $frequency Frequency at which the event would be ran
* @param string $hook Event hook to fire when the event is ran
* @param array $params Parameters passed to the actions registered to $hook when the event is ran
*/
do_action(
'upserv_scheduled_check_remote_event',
$result,
$slug,
$timestamp,
$frequency,
$hook,
$params
);
}
return true;
}
/**
* Plugin page
*
* @since 1.0.0
*/
public function plugin_page() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'Sorry, you are not allowed to access this page.' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
wp_cache_set( 'settings_notice', $this->plugin_options_handler(), 'updatepulse-server' );
$registered_schedules = wp_get_schedules();
$schedules = array();
$vcs_configs = upserv_get_option( 'vcs', array() );
$options = array(
'use_vcs' => upserv_get_option( 'use_vcs', 0 ),
'vcs' => empty( $vcs_configs ) ? '{}' : wp_json_encode( $vcs_configs ),
);
foreach ( $registered_schedules as $key => $schedule ) {
$schedules[ $schedule['display'] ] = array(
'slug' => $key,
);
}
upserv_get_admin_template(
'plugin-remote-sources-page.php',
array(
'options' => $options,
'packages_dir' => Data_Manager::get_data_dir( 'packages' ),
'registered_schedules' => $registered_schedules,
'schedules' => $schedules,
)
);
}
/*******************************************************************
* Protected methods
*******************************************************************/
/**
* Plugin options handler
*
* @return array|string Result of the options update.
* @since 1.0.0
*/
protected function plugin_options_handler() {
$errors = array();
$result = '';
$to_save = array();
$old_vcs_configs = upserv_get_option( 'vcs', array() );
$old_use_vcs = upserv_get_option( 'use_vcs' );
$nonce = sanitize_text_field( wp_unslash( filter_input( INPUT_POST, 'upserv_plugin_options_handler_nonce' ) ) );
if ( $nonce && ! wp_verify_nonce( $nonce, 'upserv_plugin_options' ) ) {
$errors['general'] = __( 'There was an error validating the form. It may be outdated. Please reload the page.', 'updatepulse-server' );
return $errors;
} elseif ( ! $nonce ) {
return $result;
}
$result = __( 'UpdatePulse Server options successfully updated', 'updatepulse-server' );
$options = $this->get_submitted_options();
foreach ( $options as $option_name => $option_info ) {
$condition = $option_info['value'];
if ( isset( $option_info['condition'] ) && 'vcs' === $option_info['condition'] ) {
$inputs = json_decode( $option_info['value'], true );
if ( ! is_array( $inputs ) ) {
$inputs = upserv_get_option( 'vcs', array() );
} else {
$option_info['value'] = $this->filter_json_input( $inputs, $option_name, $errors );
}
} elseif ( isset( $option_info['condition'] ) && 'boolean' === $option_info['condition'] ) {
$condition = true;
$option_info['value'] = (bool) $option_info['value'];
}
/**
* Filter whether to update the remote source option.
*
* @param bool $condition Whether to update the option
* @param string $option_name The name of the option
* @param array $option_info Information about the option
* @param array $options All submitted options
*/
$condition = apply_filters(
'upserv_remote_source_option_update',
$condition,
$option_name,
$option_info,
$options
);
if ( $condition ) {
/**
* Filter the value of the remote source option before saving it.
*
* @param mixed $value The value of the option
* @param string $option_name The name of the option
* @param array $option_info Information about the option
* @param array $options All submitted options
*/
$to_save[ $option_info['path'] ] = apply_filters(
'upserv_remote_sources_option_save_value',
$option_info['value'],
$option_name,
$option_info,
$options
);
$to_save[ $option_info['path'] ] = $option_info['value'];
} else {
$errors[ $option_name ] = sprintf(
// translators: %1$s is the option display name, %2$s is the condition for update
__( 'Option %1$s was not updated. Reason: %2$s', 'updatepulse-server' ),
$option_info['display_name'],
$option_info['failure_display_message']
);
}
}
if ( ! empty( $to_save ) ) {
foreach ( $to_save as $key => $value ) {
$to_update = upserv_set_option( $key, $value );
}
upserv_update_options( $to_update );
}
if ( ! empty( $errors ) ) {
$result = $errors;
}
$new_use_vcs = upserv_get_option( 'use_vcs' );
$new_vcs_configs = upserv_get_option( 'vcs', array() );
$keys = array_merge( array_keys( $old_vcs_configs ), array_keys( $new_vcs_configs ) );
foreach ( $keys as $key ) {
$old_use_webhooks = false;
$new_use_webhooks = false;
$clear = false;
$reschedule = false;
$old_check_frequency = 'daliy';
$new_check_frequency = 'daily';
if ( isset( $old_vcs_configs[ $key ], $old_vcs_configs[ $key ]['use_webhooks'] ) ) {
$old_use_webhooks = (bool) $old_vcs_configs[ $key ]['use_webhooks'];
}
if ( isset( $new_vcs_configs[ $key ], $new_vcs_configs[ $key ]['use_webhooks'] ) ) {
$new_use_webhooks = (bool) $new_vcs_configs[ $key ]['use_webhooks'];
}
if ( isset( $old_vcs_configs[ $key ], $old_vcs_configs[ $key ]['check_frequency'] ) ) {
$old_check_frequency = $old_vcs_configs[ $key ]['check_frequency'];
}
if ( isset( $new_vcs_configs[ $key ], $new_vcs_configs[ $key ]['check_frequency'] ) ) {
$new_check_frequency = $new_vcs_configs[ $key ]['check_frequency'];
}
if ( $old_check_frequency !== $new_check_frequency ) {
$reschedule = true;
}
if ( ! $old_use_vcs && $new_use_vcs ) {
$reschedule = true;
}
if ( $old_use_webhooks && ! $new_use_webhooks ) {
$reschedule = true;
}
if ( ! $old_use_webhooks && $new_use_webhooks ) {
$clear = true;
}
if ( $old_use_vcs && ! $new_use_vcs ) {
$clear = true;
$reschedule = false;
}
if ( $reschedule && ! isset( $new_vcs_configs[ $key ] ) ) {
$clear = true;
} elseif ( ! $clear && $reschedule ) {
$this->reschedule_remote_check_recurring_events(
$new_vcs_configs[ $key ]
);
}
if ( $clear ) {
$vcs_configs = false;
if ( isset( $new_vcs_configs[ $key ] ) ) {
$vcs_configs = array( $new_vcs_configs[ $key ] );
} elseif ( isset( $old_vcs_configs[ $key ] ) ) {
$vcs_configs = array( $old_vcs_configs[ $key ] );
}
if ( $vcs_configs ) {
$this->clear_remote_check_scheduled_hooks( $vcs_configs );
}
}
}
set_transient( 'upserv_flush', 1, 60 );
/**
* Fired after the options in "Remote Sources" have been updated.
*
* @param array|string $result The result of the options update, an array of errors or a success message
*/
do_action( 'upserv_remote_sources_options_updated', $result );
return $result;
}
/**
* Filter JSON input
*
* @param array $inputs JSON input data.
* @param string $option_name Option name.
* @param array $errors List of errors.
* @return array Filtered JSON input data.
* @since 1.0.0
*/
protected function filter_json_input( $inputs, $option_name, &$errors ) {
$filtered = array();
$index = 0;
$error_array = array();
foreach ( $inputs as $id => $values ) {
$url = filter_var( $values['url'], FILTER_VALIDATE_URL );
$url = trailingslashit( $url );
$branch = filter_var( $values['branch'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
$id = hash( 'sha256', $url . '|' . $branch );
if ( ! preg_match( '@^https?://[^/]+/[^/]+/$@', $url ) || ! $branch ) {
$error_array[] = sprintf(
// translators: %d is the index of the item in the list
__( 'Invalid URL or Branch for item at index %d', 'updatepulse-server' ),
$index
);
continue;
}
$type = filter_var( $values['type'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
if ( ! $type || 'undefined' === $type ) {
$error_array[] = sprintf(
// translators: %d is the index of the item in the list
__( 'Undefined VCS Type for item at index %d', 'updatepulse-server' ),
$index
);
continue;
}
$self_hosted = intval( filter_var( $values['self_hosted'], FILTER_VALIDATE_BOOLEAN ) );
$credentials = filter_var( $values['credentials'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
$filter_packages = intval( filter_var( $values['filter_packages'], FILTER_VALIDATE_BOOLEAN ) );
$check_frequency = filter_var( $values['check_frequency'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
$use_webhooks = intval( filter_var( $values['use_webhooks'], FILTER_VALIDATE_BOOLEAN ) );
$check_delay = intval( filter_var( $values['check_delay'], FILTER_VALIDATE_INT ) );
$webhook_secret = filter_var( $values['webhook_secret'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
$known_frequencies = wp_get_schedules();
$known_frequencies = array_keys( $known_frequencies );
if ( ! in_array( $check_frequency, $known_frequencies, true ) ) {
$check_frequency = 'daily';
}
$filtered[ $id ] = array(
'url' => $url,
'branch' => $branch,
'type' => $type,
'self_hosted' => $self_hosted,
'credentials' => $credentials,
'filter_packages' => $filter_packages,
'check_frequency' => $check_frequency,
'use_webhooks' => $use_webhooks,
'check_delay' => $check_delay,
'webhook_secret' => $webhook_secret,
);
++$index;
}
if ( ! empty( $error_array ) ) {
$errors[ $option_name ] = implode( '<br>', $error_array );
}
return $filtered;
}
/**
* Get submitted options
*
* @return array List of submitted options.
* @since 1.0.0
*/
protected function get_submitted_options() {
/**
* Filter the submitted remote sources configuration values before using them.
*
* @param array $config The submitted remote sources configuration values
* @return array The filtered configuration
*/
return apply_filters(
'upserv_submitted_remote_sources_config',
array(
'upserv_use_vcs' => array(
'value' => filter_input( INPUT_POST, 'upserv_use_vcs', FILTER_VALIDATE_BOOLEAN ),
'display_name' => __( 'Enable VCS', 'updatepulse-server' ),
'condition' => 'boolean',
'path' => 'use_vcs',
),
'upserv_vcs' => array(
'value' => wp_kses_post( filter_input( INPUT_POST, 'upserv_vcs' ) ),
'display_name' => __( 'Version Control Systems', 'updatepulse-server' ),
'failure_display_message' => __( 'Not a valid payload', 'updatepulse-server' ),
'condition' => 'vcs',
'path' => 'vcs',
),
)
);
}
/**
* Get package slugs
*
* @param string $vcs_url VCS URL.
* @return array List of package slugs.
* @since 1.0.0
*/
protected function get_package_slugs( $vcs_url ) {
$slugs = wp_cache_get( 'package_slugs', 'updatepulse-server' );
if ( false === $slugs ) {
$slugs = array();
$meta_dir = Data_Manager::get_data_dir( 'metadata' );
if ( is_dir( $meta_dir ) ) {
$meta_paths = glob( trailingslashit( $meta_dir ) . '*.json' );
if ( ! empty( $meta_paths ) ) {
foreach ( $meta_paths as $meta_path ) {
$meta_path_parts = explode( '/', $meta_path );
$slugs[] = str_replace( '.json', '', end( $meta_path_parts ) );
}
}
}
if ( ! empty( $slugs ) ) {
foreach ( $slugs as $idx => $slug ) {
$meta = upserv_get_package_metadata( $slug );
$mode = upserv_get_option( 'use_cloud_storage' ) ? 'cloud' : 'local';
if (
! isset( $meta['vcs'] ) ||
trailingslashit( $meta['vcs'] ) !== trailingslashit( $vcs_url ) ||
! isset( $meta['whitelisted'] ) ||
! isset( $meta['whitelisted'][ $mode ] ) ||
! $meta['whitelisted'][ $mode ]
) {
unset( $slugs[ $idx ] );
}
}
}
wp_cache_set( 'package_slugs', $slugs, 'updatepulse-server' );
}
return $slugs;
}
}