*/ public static function default_status_messages() { return array( 'processing' => array( 'enabled' => true, /* translators: Keep the {placeholders} in English. */ 'text' => __( "Hi {first_name}, thanks for your order #{order_number} at {shop_name}! We've received it and we're getting it ready.\nTotal: {order_total}", 'orderchirp' ), ), 'on-hold' => array( 'enabled' => false, /* translators: Keep the {placeholders} in English. */ 'text' => __( 'Hi {first_name}, your order #{order_number} at {shop_name} is on hold until we confirm your payment.', 'orderchirp' ), ), 'completed' => array( 'enabled' => true, /* translators: Keep the {placeholders} in English. */ 'text' => __( "Good news, {first_name}! Your order #{order_number} from {shop_name} is on its way.\nTracking: {tracking_number} {tracking_provider}\n{tracking_url}", 'orderchirp' ), ), 'cancelled' => array( 'enabled' => true, /* translators: Keep the {placeholders} in English. */ 'text' => __( 'Hi {first_name}, your order #{order_number} at {shop_name} has been cancelled. If you have a question, just reply to this message.', 'orderchirp' ), ), 'refunded' => array( 'enabled' => true, /* translators: Keep the {placeholders} in English. */ 'text' => __( 'Hi {first_name}, your order #{order_number} at {shop_name} has been refunded.', 'orderchirp' ), ), 'failed' => array( 'enabled' => false, /* translators: Keep the {placeholders} in English. */ 'text' => __( 'Hi {first_name}, the payment for your order #{order_number} at {shop_name} did not go through. You can try again here: {order_url}', 'orderchirp' ), ), ); } /** * Defaults. * * @return array */ public static function defaults() { return array( 'bot_token' => '', 'bot_username' => '', 'delivery' => 'webhook', 'owner_new_order' => true, 'owner_low_stock' => true, 'owner_replies' => true, 'optin_thankyou' => true, 'optin_email' => true, 'optin_account' => true, 'status_messages' => self::default_status_messages(), 'owner_chats' => array(), ); } /** * All settings with defaults merged in. * * @return array */ public static function all() { $stored = get_option( self::OPTION, array() ); return self::merge( is_array( $stored ) ? $stored : array() ); } /** * Merge stored values over the defaults, one level deep for the status messages so a * status the owner never touched keeps its default text. * * @param array $stored Stored values. * @return array */ public static function merge( array $stored ) { $defaults = self::defaults(); $merged = array_merge( $defaults, array_intersect_key( $stored, $defaults ) ); $messages = $defaults['status_messages']; if ( isset( $stored['status_messages'] ) && is_array( $stored['status_messages'] ) ) { foreach ( $stored['status_messages'] as $status => $message ) { if ( ! is_array( $message ) ) { continue; } $base = isset( $messages[ $status ] ) ? $messages[ $status ] : array( 'enabled' => false, 'text' => '' ); $messages[ $status ] = array( 'enabled' => isset( $message['enabled'] ) ? (bool) $message['enabled'] : $base['enabled'], 'text' => isset( $message['text'] ) ? (string) $message['text'] : $base['text'], ); } } $merged['status_messages'] = $messages; if ( ! is_array( $merged['owner_chats'] ) ) { $merged['owner_chats'] = array(); } return $merged; } /** * One setting. * * @param string $key Key. * @return mixed */ public static function get( $key ) { $all = self::all(); return isset( $all[ $key ] ) ? $all[ $key ] : null; } /** * Save a partial update. * * @param array $values Values to change. */ public static function update( array $values ) { $all = self::all(); foreach ( $values as $key => $value ) { $all[ $key ] = $value; } update_option( self::OPTION, $all, false ); } /** * Whether a bot is connected. * * @return bool */ public static function connected() { return '' !== (string) self::get( 'bot_token' ) && '' !== (string) self::get( 'bot_username' ); } /** * The site secret: signs the Telegram links and is the webhook secret. Created once. * * @return string */ public static function secret() { $secret = (string) get_option( self::SECRET_OPTION, '' ); if ( strlen( $secret ) < 32 ) { $secret = wp_generate_password( 48, false, false ); update_option( self::SECRET_OPTION, $secret, false ); } return $secret; } /** * The value Telegram sends back in X-Telegram-Bot-Api-Secret-Token. Derived from the site * secret so the secret itself never leaves the site. Telegram allows 1-256 of A-Z a-z 0-9 _ -. * * @param string $secret Site secret. * @return string */ public static function webhook_token( $secret ) { return substr( hash_hmac( 'sha256', 'telegram-webhook', $secret ), 0, 48 ); } /** * A bot token as Telegram issues it: digits, a colon, then 30+ of A-Z a-z 0-9 _ -. * * @param string $token Candidate. * @return bool */ public static function valid_bot_token( $token ) { return 1 === preg_match( '/^\d{5,16}:[A-Za-z0-9_-]{30,64}$/D', (string) $token ); } }