' . esc_html( $label ) . '';
array_unshift( $links, $settings );
return $links;
}
public static function handle_notice_dismiss() {
if ( empty( $_GET['quicksync_dismiss'] ) || ! current_user_can( 'manage_woocommerce' ) ) {
return;
}
check_admin_referer( 'quicksync_dismiss' );
$which = sanitize_key( wp_unslash( $_GET['quicksync_dismiss'] ) );
if ( 'activation' === $which ) {
delete_option( 'quicksync_show_activation_notice' );
}
if ( 'review' === $which ) {
QuickSync_Plugin::update_options( array( 'review_dismissed' => 1 ) );
}
wp_safe_redirect( remove_query_arg( array( 'quicksync_dismiss', '_wpnonce' ) ) );
exit;
}
public static function handle_copy() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'You do not have permission to change this connection.', 'quicksync-pro-for-woocommerce' ) );
}
check_admin_referer( 'quicksync_copy' );
QuickSync_Identity::treat_as_copy();
wp_safe_redirect( QuickSync_Connect::settings_url() );
exit;
}
public static function handle_moved() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'You do not have permission to change this connection.', 'quicksync-pro-for-woocommerce' ) );
}
check_admin_referer( 'quicksync_moved' );
if ( ! QuickSync_Identity::treat_as_moved() ) {
wp_safe_redirect(
add_query_arg(
'quicksync_error',
rawurlencode( __( 'This site is a different address. Reconnect it as its own store.', 'quicksync-pro-for-woocommerce' ) ),
QuickSync_Connect::settings_url()
)
);
exit;
}
wp_safe_redirect( QuickSync_Connect::settings_url() );
exit;
}
public static function handle_review() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'You do not have permission to dismiss this notice.', 'quicksync-pro-for-woocommerce' ) );
}
check_admin_referer( 'quicksync_review' );
$choice = isset( $_POST['quicksync_review'] ) ? sanitize_key( wp_unslash( $_POST['quicksync_review'] ) ) : '';
if ( in_array( $choice, array( 'done', 'later', 'leave' ), true ) ) {
QuickSync_Plugin::update_options( array( 'review_dismissed' => 1 ) );
}
if ( 'leave' === $choice ) {
wp_safe_redirect( self::REVIEW_URL );
exit;
}
wp_safe_redirect( QuickSync_Connect::settings_url() );
exit;
}
public static function activation_notice() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return;
}
if ( ! get_option( 'quicksync_show_activation_notice' ) ) {
return;
}
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
if ( ! $screen || 'plugins' !== $screen->id ) {
return;
}
$dismiss = wp_nonce_url(
add_query_arg( 'quicksync_dismiss', 'activation' ),
'quicksync_dismiss'
);
echo '
';
}
public static function review_notice() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return;
}
if ( ! self::should_ask_review() ) {
return;
}
$dismiss = wp_nonce_url(
add_query_arg( 'quicksync_dismiss', 'review' ),
'quicksync_dismiss'
);
echo '';
}
public static function should_ask_review() {
$opts = QuickSync_Plugin::options();
if ( ! empty( $opts['review_dismissed'] ) ) {
return false;
}
if ( ! QuickSync_Plugin::is_connected() ) {
return false;
}
$connected = (int) $opts['connected_at'];
if ( $connected < 1 ) {
return false;
}
return ( time() - $connected ) >= ( 14 * DAY_IN_SECONDS );
}
public static function render_page() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'You do not have permission to access this page.', 'quicksync-pro-for-woocommerce' ) );
}
delete_option( 'quicksync_show_activation_notice' );
$opts = QuickSync_Plugin::options();
$connected = QuickSync_Plugin::is_connected();
$safe = QuickSync_Identity::in_safe_mode();
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- display-only query args after capability check
$error = isset( $_GET['quicksync_error'] ) ? sanitize_text_field( wp_unslash( $_GET['quicksync_error'] ) ) : '';
$just = ! empty( $_GET['quicksync_connected'] );
$tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'status';
// phpcs:enable WordPress.Security.NonceVerification.Recommended
if ( ! in_array( $tab, array( 'status', 'support' ), true ) ) {
$tab = 'status';
}
$status = $connected ? QuickSync_Status::remote_status() : array();
if ( $connected && ! empty( $status['account_email'] ) && $status['account_email'] !== $opts['account_email'] ) {
QuickSync_Plugin::update_options( array( 'account_email' => sanitize_email( $status['account_email'] ) ) );
$opts['account_email'] = sanitize_email( $status['account_email'] );
}
$waiting = (bool) get_transient( 'quicksync_handoff_id' );
$expired = ! $waiting && ! empty( $_GET['quicksync_waiting'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only
$rerun = ! empty( $_GET['quicksync_rerun'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only
$checks = array();
if ( 'support' !== $tab ) {
$cached = isset( $opts['diagnostics'] ) && is_array( $opts['diagnostics'] ) ? $opts['diagnostics'] : array();
if ( $rerun || ! $cached || ! (int) $opts['diagnostics_checked_at'] ) {
$checks = QuickSync_Status::self_test();
QuickSync_Plugin::update_options(
array(
'diagnostics' => $checks,
'diagnostics_checked_at' => time(),
)
);
$opts['diagnostics_checked_at'] = time();
if ( $rerun ) {
wp_safe_redirect( QuickSync_Connect::settings_url() );
exit;
}
} else {
$checks = $cached;
}
if ( $connected && array_key_exists( 'rest_reachable', $status ) ) {
$reachable = ! empty( $status['rest_reachable'] );
$checks[] = array(
'label' => __( 'Reachable from QuickSync', 'quicksync-pro-for-woocommerce' ),
'ok' => $reachable,
'level' => $reachable ? 'ok' : 'warn',
'detail' => $reachable ? '' : __( 'blocked (likely WAF)', 'quicksync-pro-for-woocommerce' ),
'docs' => $reachable ? '' : QuickSync_Status::DOCS_FAQ,
);
}
}
?>
=' ) || (int) $opts['last_event_at'] > 0 || ! empty( $status['last_event_at'] );
$last_error = (string) $opts['last_error'];
$dash_url = ! empty( $status['dashboard_url'] ) ? $status['dashboard_url'] : 'https://app.quicksync.pro/';
?>
·
·
' . esc_html__( 'Diagnostics', 'quicksync-pro-for-woocommerce' ) . '';
echo $body; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- built above with escaped values
return;
}
?>
admin_url( 'admin-ajax.php' ),
'pollNonce' => wp_create_nonce( 'quicksync_handoff' ),
'connectNonce' => wp_create_nonce( 'quicksync_connect' ),
'connectedUrl' => add_query_arg( 'quicksync_connected', '1', QuickSync_Connect::settings_url() ),
'expiredUrl' => add_query_arg( 'quicksync_waiting', '1', QuickSync_Connect::settings_url() ),
'errorUrl' => add_query_arg( 'quicksync_error', 'ERR', QuickSync_Connect::settings_url() ),
'remaining' => $remaining,
'waiting' => (bool) $waiting,
'opening' => __( 'Opening QuickSync…', 'quicksync-pro-for-woocommerce' ),
);
wp_add_inline_script( 'quicksync-admin', 'window.quicksyncConnect = ' . wp_json_encode( $config ) . ';', 'before' );
}
private static function diagnostics_plaintext( $checks, $checked_at ) {
$lines = array( 'QuickSync diagnostics' );
if ( $checked_at ) {
$lines[] = 'Last checked: ' . date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $checked_at );
}
foreach ( $checks as $check ) {
$level = isset( $check['level'] ) ? $check['level'] : ( $check['ok'] ? 'ok' : 'warn' );
$line = $check['label'] . ': ' . strtoupper( $level );
if ( ! empty( $check['detail'] ) && 'ok' !== $level ) {
$line .= ' — ' . $check['detail'];
}
$lines[] = $line;
}
return implode( "\n", $lines );
}
private static function format_time( $ts ) {
$ts = (int) $ts;
if ( $ts < 1 ) {
return __( 'None yet', 'quicksync-pro-for-woocommerce' );
}
return date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $ts );
}
private static function is_plugins_screen() {
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
return $screen && 'plugins' === $screen->id;
}
}