group, label, position, render. * @return array */ public static function sections( $sections ) { $sections = (array) $sections; $sections['periods'] = array( 'tab' => 'timing', 'label' => __( 'When the periods start', 'careback' ), 'position' => 5, 'render' => array( __CLASS__, 'render_periods' ), ); $sections['deleting'] = array( 'tab' => 'safeguards', 'label' => __( 'Deleting the plugin', 'careback' ), 'position' => 90, 'render' => array( __CLASS__, 'render_deleting' ), ); return $sections; } /** * The fields of the last save that were refused (their stored value kept). * * @return string[] */ public static function invalid_fields() { return self::$invalid; } /** * The values of the two sections, from the returns form. A status that is * not one to choose and a buffer outside 0–30 are refused: the stored value * stays and the field says why. * * @param array $values Values the form stores. * @param string $screen Id of the screen saving (Admin::SCREEN). * @param Settings|null $settings The screen's settings. * @param array $posted The posted form (Admin::save(), after its capability and nonce checks). * @return array */ public static function save( $values, $screen = '', $settings = null, $posted = array() ) { $values = (array) $values; $posted = (array) $posted; if ( Admin::SCREEN !== $screen ) { return $values; } unset( $settings ); self::$invalid = array(); $values['delete_data_on_uninstall'] = empty( $posted['delete_data_on_uninstall'] ) ? 0 : 1; if ( isset( $posted['delivered_status'] ) && is_scalar( $posted['delivered_status'] ) ) { $status = sanitize_key( $posted['delivered_status'] ); if ( isset( Periods::choices()[ $status ] ) ) { $values['delivered_status'] = $status; } } if ( isset( $posted['delivery_buffer_days'] ) && is_scalar( $posted['delivery_buffer_days'] ) ) { $buffer = trim( sanitize_text_field( $posted['delivery_buffer_days'] ) ); if ( '' !== $buffer && ctype_digit( $buffer ) && (int) $buffer <= Periods::BUFFER_MAX ) { $values['delivery_buffer_days'] = (int) $buffer; } else { self::$invalid[] = 'delivery_buffer_days'; } } return $values; } /** * True when the save before this screen refused the field. * * @param string $field Field name. * @return bool */ private static function refused( $field ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display only: the result of the redirect after a save; nothing is changed. $raw = isset( $_GET[ self::INVALID_ARG ] ) && is_scalar( $_GET[ self::INVALID_ARG ] ) ? sanitize_text_field( wp_unslash( $_GET[ self::INVALID_ARG ] ) ) : ''; return in_array( $field, explode( ',', $raw ), true ); } /** * When the periods start: the explanation, the status, the buffer, the * example. * * @param array $s Stored settings. * @param string $screen Id of the screen printing it. * @param Settings|null $settings The settings that screen prints. */ public static function render_periods( array $s, $screen = '', $settings = null ) { unset( $screen ); $settings = $settings instanceof Settings ? $settings : new Settings(); $status = Periods::delivered_status( $settings ); $buffer = Periods::buffer_days( $settings ); $choices = Periods::choices(); $refused = self::refused( 'delivery_buffer_days' ); $example = self::example( $settings, $choices ); ?>

$choices Status slug => label. * @return array{text:string,template:string,dates:array} */ private static function example( Settings $settings, array $choices ) { $status = Periods::delivered_status( $settings ); $label = isset( $choices[ $status ] ) ? $choices[ $status ] : $status; $statutory = (int) $settings->get( 'statutory_window_days', 14 ); $return = (int) $settings->get( 'return_window_days', 30 ); $now = time(); $day = static function ( $offset ) use ( $now ) { /* translators: a PHP date() format for a day and month (29 October): keep the letters, set the order and separators of your language. */ return (string) wp_date( _x( 'j F', 'day and month format (PHP date())', 'careback' ), $now + (int) $offset * DAY_IN_SECONDS ); }; if ( Routes::withdrawal_offered( $settings ) ) { /* translators: 1: an order status, such as "Completed", 2: the day the periods start, 3: the last day of the withdrawal, 4: the last day of the return. */ $template = __( 'Example: an order marked %1$s today → the periods start on %2$s; withdrawal is possible until %3$s, return until %4$s.', 'careback' ); } else { /* translators: 1: an order status, such as "Completed", 2: the day the return period starts, 3: its last day. */ $template = __( 'Example: an order marked %1$s today → the return period starts on %2$s and ends on %3$s.', 'careback' ); } $dates = array(); for ( $buffer = 0; $buffer <= Periods::BUFFER_MAX; $buffer++ ) { $dates[] = Routes::withdrawal_offered( $settings ) ? array( $day( $buffer ), $day( $buffer + $statutory ), $day( $buffer + $return ) ) : array( $day( $buffer ), $day( $buffer + $return ) ); } $current = $dates[ Periods::buffer_days( $settings ) ]; return array( 'text' => vsprintf( $template, array_merge( array( $label ), $current ) ), 'template' => $template, 'dates' => $dates, ); } /** * Deleting the plugin: the box, what goes, what always stays, and when * nothing goes. * * @param array $s Stored settings. * @param string $screen Id of the screen printing it. * @param Settings|null $settings The settings that screen prints. */ public static function render_deleting( array $s, $screen = '', $settings = null ) { unset( $screen ); $settings = $settings instanceof Settings ? $settings : new Settings(); $ticked = ! empty( $settings->get( 'delete_data_on_uninstall', 0 ) ); $dependents = Data_Eraser::dependents(); $in_config = defined( 'CAREBACK_HASH_KEY' ) && CAREBACK_HASH_KEY; ?>