slugs. Keys and slugs come from web/lib/help/keys.ts of smsportal.app * (scripts/validate-help.mjs checks that they match). */ const ARTICLES = array( 'wp-install' => array( 'pl' => 'wordpress-instalacja', 'en' => 'wordpress-install', ), 'wp-connect' => array( 'pl' => 'wordpress-polaczenie', 'en' => 'wordpress-connect', ), 'wp-rules' => array( 'pl' => 'wordpress-reguly', 'en' => 'wordpress-rules', ), 'wp-woocommerce' => array( 'pl' => 'wordpress-woocommerce', 'en' => 'wordpress-woocommerce', ), 'wp-forms' => array( 'pl' => 'wordpress-formularze', 'en' => 'wordpress-forms', ), 'wp-bookings' => array( 'pl' => 'wordpress-rezerwacje', 'en' => 'wordpress-bookings', ), 'wp-members' => array( 'pl' => 'wordpress-ultimate-member-automator', 'en' => 'wordpress-ultimate-member-automator', ), 'wp-replies-stop' => array( 'pl' => 'wordpress-odpowiedzi-i-stop', 'en' => 'wordpress-replies-and-stop', ), 'wp-log' => array( 'pl' => 'wordpress-wyslane-i-dziennik', 'en' => 'wordpress-sent-and-log', ), 'wp-settings' => array( 'pl' => 'wordpress-ustawienia', 'en' => 'wordpress-settings', ), 'wp-troubleshooting' => array( 'pl' => 'wordpress-problemy', 'en' => 'wordpress-troubleshooting', ), 'offline' => array( 'pl' => 'telefon-offline', 'en' => 'phone-offline', ), 'battery' => array( 'pl' => 'oszczedzanie-baterii', 'en' => 'battery-optimization', ), 'sms-length' => array( 'pl' => 'polskie-znaki-i-dlugosc-sms', 'en' => 'sms-length-and-special-characters', ), ); /** * Articles of each plugin tab; the first one is the main guide (also linked from the header). */ const TABS = array( 'overview' => array( 'wp-connect', 'offline' ), 'rules' => array( 'wp-rules', 'wp-woocommerce', 'wp-forms', 'wp-bookings', 'wp-members' ), 'sent' => array( 'wp-log' ), 'replies' => array( 'wp-replies-stop' ), 'log' => array( 'wp-log' ), 'blocked' => array( 'wp-replies-stop' ), 'settings' => array( 'wp-settings' ), ); /** * Articles linked in the help sidebar of every tab, after the help center itself. */ const SIDEBAR = array( 'wp-troubleshooting', 'battery' ); /** * Whether the admin works in Polish (pl, pl_PL…). Every other language gets the English help center. * * @return bool */ private static function polish(): bool { return 0 === strpos( determine_locale(), 'pl' ); } /** * Help center home in the admin's language. * * @return string */ public static function index_url(): string { return self::SITE . ( self::polish() ? '/pomoc' : '/en/help' ); } /** * Article in the admin's language. An unknown key gives the help center home. * * @param string $key Article key (self::ARTICLES). * @return string */ public static function url( string $key ): string { if ( ! isset( self::ARTICLES[ $key ] ) ) { return self::index_url(); } return self::index_url() . '/' . self::ARTICLES[ $key ][ self::polish() ? 'pl' : 'en' ]; } /** * Main guide of a plugin tab. An unknown tab gives the overview guide. * * @param string $tab Tab slug (Menu::tabs()). * @return string */ public static function tab_url( string $tab ): string { $keys = self::TABS[ $tab ] ?? self::TABS['overview']; return self::url( $keys[0] ); } /** * Add the help tab of the current plugin tab and the help sidebar to the screen. Runs on load-{hook}. * * @return void */ public static function register(): void { $screen = get_current_screen(); if ( null === $screen ) { return; } $tab = Menu::current_tab(); $screen->add_help_tab( array( 'id' => 'smsportal-help-' . $tab, 'title' => Menu::tabs()[ $tab ], 'content' => self::tab_content( $tab ), ) ); $screen->set_help_sidebar( self::sidebar() ); } /** * Body of a help tab: a short explanation and links to the guides. * * @param string $tab Tab slug. * @return string */ private static function tab_content( string $tab ): string { $html = ''; foreach ( self::texts()[ $tab ] as $paragraph ) { $html .= '

' . esc_html( $paragraph ) . '

'; } $html .= '

' . esc_html__( 'Step-by-step guides (they open in a new tab):', '85pl-android-sms-api' ) . '

'; return wp_kses_post( $html ); } /** * Help sidebar: the help center and the guides for the most common problems. * * @return string */ private static function sidebar(): string { $html = '

' . esc_html__( 'More help', '85pl-android-sms-api' ) . '

'; $html .= '

' . self::anchor( self::index_url(), __( 'Help center', '85pl-android-sms-api' ) ) . '

'; foreach ( self::SIDEBAR as $key ) { $html .= '

' . self::link( $key ) . '

'; } return wp_kses_post( $html ); } /** * Link to an article, labelled with its title. * * @param string $key Article key. * @return string */ private static function link( string $key ): string { return self::anchor( self::url( $key ), self::titles()[ $key ] ); } /** * Link that opens in a new tab. * * @param string $url Address. * @param string $label Link text. * @return string */ private static function anchor( string $url, string $label ): string { return '' . esc_html( $label ) . ''; } /** * Titles of the linked articles. * * @return array */ private static function titles(): array { return array( 'wp-connect' => __( 'Connecting WordPress, step by step', '85pl-android-sms-api' ), 'offline' => __( 'The phone shows "offline"', '85pl-android-sms-api' ), 'wp-rules' => __( 'Rules: automatic SMS', '85pl-android-sms-api' ), 'wp-woocommerce' => __( 'WooCommerce: order and shipping SMS', '85pl-android-sms-api' ), 'wp-forms' => __( 'Forms: Contact Form 7, WPForms, Fluent Forms and more', '85pl-android-sms-api' ), 'wp-bookings' => __( 'Bookings and reminders', '85pl-android-sms-api' ), 'wp-members' => __( 'Ultimate Member and Uncanny Automator', '85pl-android-sms-api' ), 'wp-replies-stop' => __( 'Customer replies and STOP', '85pl-android-sms-api' ), 'wp-log' => __( 'The "Sent" and "Log" tabs', '85pl-android-sms-api' ), 'wp-settings' => __( 'Plugin settings', '85pl-android-sms-api' ), 'wp-troubleshooting' => __( 'WordPress: troubleshooting', '85pl-android-sms-api' ), 'battery' => __( 'Battery saving: keep Android from putting the app to sleep', '85pl-android-sms-api' ), ); } /** * Short explanation of each tab (summaries of the help center guides). * * @return array */ private static function texts(): array { return array( 'overview' => array( sprintf( /* translators: %s: label of the button "Connect to smsportal.app". */ __( 'You connect the site once: click "%s", sign in, pick the phone and approve. You copy no keys, and you can end the connection here or in the smsportal.app dashboard.', '85pl-android-sms-api' ), __( 'Connect to smsportal.app', '85pl-android-sms-api' ) ), __( 'This tab shows whether the phone is online, its battery and how many SMS went out this month. While the phone is offline, SMS wait for it, at most as long as the rule allows (12 hours by default).', '85pl-android-sms-api' ), ), 'rules' => array( sprintf( /* translators: %s: label of the button "Add automatic SMS". */ __( 'A rule sends an SMS by itself each time something happens on the site, for example a new order, a sent form or a booking. Click "%s", pick the event and who gets the SMS, write the text and save.', '85pl-android-sms-api' ), __( 'Add automatic SMS', '85pl-android-sms-api' ) ), __( 'Words in curly brackets, such as {first_name} or {order_number}, are replaced with the data of the event. The editor counts the SMS parts and shows a preview.', '85pl-android-sms-api' ), ), 'sent' => array( __( 'Every SMS from this site is listed here with its status, from "Queued" and "Waiting for the phone" to "Delivered". When smsportal.app cannot be reached, the plugin tries again after 1, 5 and 15 minutes.', '85pl-android-sms-api' ), __( 'A failed SMS shows the reason. "Expired" means the SMS could not go out in the time the rule allows, for example because the phone was offline.', '85pl-android-sms-api' ), ), 'replies' => array( __( 'Customer replies to SMS from this site appear here, on the WooCommerce order as a private note and in an e-mail to you (you can turn the e-mail off in "Settings").', '85pl-android-sms-api' ), __( 'A customer who replies STOP is added to "Blocked" and gets no more SMS from this site.', '85pl-android-sms-api' ), ), 'log' => array( __( 'The log lists events of the connection with smsportal.app: connecting and disconnecting, connection and sending errors, and SMS stopped by the safety limit.', '85pl-android-sms-api' ), __( 'The status of each SMS is under "Sent"; look here when "Sent" does not explain why an SMS did not go out.', '85pl-android-sms-api' ), ), 'blocked' => array( __( 'This site sends no SMS to the numbers on this list. A customer who replies STOP (or NIE, REZYGNUJE, UNSUBSCRIBE) is added automatically.', '85pl-android-sms-api' ), sprintf( /* translators: 1: label of the field "Block a number", 2: label of the link "Unblock". */ __( 'To add a number by hand, type it in "%1$s". "%2$s" takes a number off the list.', '85pl-android-sms-api' ), __( 'Block a number', '85pl-android-sms-api' ), __( 'Unblock', '85pl-android-sms-api' ) ), ), 'settings' => array( __( 'Here you set your own number for test SMS, the e-mail about each customer reply and the countries that SMS to customers may go to.', '85pl-android-sms-api' ), __( 'How long an SMS may wait to go out (12 hours by default) is set in each rule. Sent SMS, replies and log entries are deleted after 90 days.', '85pl-android-sms-api' ), ), ); } }