self::PAGE ), $args ), admin_url( 'options-general.php' ) );
}
public static function app_url( $path = '' ) {
return untrailingslashit( REPLYBASH_APP_URL ) . $path;
}
public static function menu() {
add_options_page( __( 'ReplyBash', 'replybash' ), __( 'ReplyBash', 'replybash' ), 'manage_options', self::PAGE, array( __CLASS__, 'render' ) );
}
public static function register() {
register_setting(
'replybash',
ReplyBash_Options::SETTINGS,
array(
'type' => 'array',
'sanitize_callback' => array( 'ReplyBash_Options', 'sanitize' ),
'default' => ReplyBash_Options::defaults(),
)
);
}
public static function assets( $hook ) {
if ( 'settings_page_' . self::PAGE === $hook ) {
wp_enqueue_style( 'replybash-admin', plugins_url( 'assets/admin.css', REPLYBASH_FILE ), array(), REPLYBASH_VERSION );
}
}
public static function action_links( $links ) {
array_unshift( $links, '' . esc_html__( 'Settings', 'replybash' ) . '' );
return $links;
}
// Right after activation (and until connected) the Plugins screen points to the settings page.
public static function setup_notice() {
$screen = get_current_screen();
if ( ! $screen || 'plugins' !== $screen->id || ! current_user_can( 'manage_options' ) || ReplyBash_Options::connection()['key'] ) {
return;
}
printf(
'
',
esc_html__( 'ReplyBash is almost ready: connect your agent to show the chat on your site.', 'replybash' ),
esc_url( self::page_url() ),
esc_html__( 'Connect now', 'replybash' )
);
}
private static function check( $nonce_action ) {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You are not allowed to change these settings.', 'replybash' ), 403 );
}
check_admin_referer( $nonce_action );
}
private static function back( $notice ) {
wp_safe_redirect( self::page_url( array( 'replybash_notice' => $notice ) ) );
exit;
}
public static function start_connect() {
self::check( 'replybash_connect' );
$state = wp_generate_password( 32, false, false );
set_transient( 'replybash_state_' . get_current_user_id(), $state, self::STATE_TTL );
$url = add_query_arg(
array(
'site' => rawurlencode( home_url() ),
'return' => rawurlencode( self::page_url() ),
'state' => $state,
),
self::app_url( '/connect/wordpress' )
);
// The app is on another host; allow just that one for this redirect.
$host = wp_parse_url( REPLYBASH_APP_URL, PHP_URL_HOST );
add_filter(
'allowed_redirect_hosts',
function ( $hosts ) use ( $host ) {
$hosts[] = $host;
return $hosts;
}
);
wp_safe_redirect( $url );
exit;
}
// The app's redirect back: ?page=replybash&replybash_key=…&replybash_state=…
public static function finish_connect() {
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- the state below is this flow's nonce.
if ( ! isset( $_GET['page'], $_GET['replybash_state'] ) || self::PAGE !== $_GET['page'] ) {
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$transient = 'replybash_state_' . get_current_user_id();
$expected = get_transient( $transient );
$state = sanitize_text_field( wp_unslash( $_GET['replybash_state'] ) );
$key = ReplyBash_Options::clean_key( isset( $_GET['replybash_key'] ) ? sanitize_text_field( wp_unslash( $_GET['replybash_key'] ) ) : '' );
$agent = isset( $_GET['replybash_agent'] ) ? sanitize_text_field( wp_unslash( $_GET['replybash_agent'] ) ) : '';
$workspace = isset( $_GET['replybash_workspace'] ) ? sanitize_text_field( wp_unslash( $_GET['replybash_workspace'] ) ) : '';
// phpcs:enable
if ( ! is_string( $expected ) || ! hash_equals( $expected, $state ) || '' === $key ) {
self::back( 'bad_state' );
}
delete_transient( $transient );
ReplyBash_Options::connect( $key, $agent, $workspace );
self::back( 'connected' );
}
public static function save_manual_key() {
self::check( 'replybash_manual_key' );
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- check() above verified the nonce.
$key = ReplyBash_Options::clean_key( isset( $_POST['replybash_key'] ) ? sanitize_text_field( wp_unslash( $_POST['replybash_key'] ) ) : '' );
if ( '' === $key ) {
self::back( 'bad_key' );
}
ReplyBash_Options::connect( $key );
self::back( 'key_saved' );
}
public static function disconnect() {
self::check( 'replybash_disconnect' );
ReplyBash_Options::disconnect();
self::back( 'disconnected' );
}
private static function notice() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only picks a message to show.
$code = isset( $_GET['replybash_notice'] ) ? sanitize_key( $_GET['replybash_notice'] ) : '';
$messages = array(
'connected' => array( 'success', __( 'Connected. The chat now shows on your site.', 'replybash' ) ),
'key_saved' => array( 'success', __( 'Key saved. If the chat doesn\'t show, add this site\'s domain under Embed › Allowed domains in ReplyBash.', 'replybash' ) ),
'disconnected' => array( 'info', __( 'Disconnected. The chat no longer shows on your site.', 'replybash' ) ),
'bad_key' => array( 'error', __( 'That doesn\'t look like an agent key. Copy it from Embed in ReplyBash (it looks like acme_7Hq2k).', 'replybash' ) ),
'bad_state' => array( 'error', __( 'That connection link has expired or was meant for another admin. Click Connect again.', 'replybash' ) ),
);
if ( isset( $messages[ $code ] ) ) {
printf( '', esc_attr( $messages[ $code ][0] ), esc_html( $messages[ $code ][1] ) );
}
}
private static function post_form( $action, $button, $class = 'button' ) {
?>
' . esc_html__( 'Create one free', 'replybash' ) . ''
);
?>