0, 'right' => 0, 'bottom' => 0, 'left' => 0 ]; $margins = $layout_settings['margin'] ?? $default_margins; $spacing_options = [ 'top' => [ 'label' => _x( 'Top', 'Ad positioning spacing label', 'adpresso' ), 'value' => absint( $margins['top'] ?? 0 ) ], 'right' => [ 'label' => _x( 'Right', 'Ad positioning spacing label', 'adpresso' ), 'value' => absint( $margins['right'] ?? 0 ) ], 'bottom' => [ 'label' => _x( 'Bottom', 'Ad positioning spacing label', 'adpresso' ), 'value' => absint( $margins['bottom'] ?? 0 ) ], 'left' => [ 'label' => _x( 'Left', 'Ad positioning spacing label', 'adpresso' ), 'value' => absint( $margins['left'] ?? 0 ) ], ]; return [ 'options' => $spacing_options, 'is_centered' => $is_centered ]; } /** * Defines the positioning options for placements. * * @return array */ private function get_positioning_options_config(): array { return [ 'default' => [ 'title' => __( 'Theme’s Default', 'adpresso' ), 'description' => __( 'The ad will behave as predefined by the theme.', 'adpresso' ), 'options' => [ 'none' => [] ], ], 'float' => [ 'title' => _x( 'Float', 'Layout options "Text Flow" heading', 'adpresso' ), 'description' => __( 'Text will wrap around the ad and its margin.', 'adpresso' ), 'options' => [ 'left_float' => [], 'right_float' => [] ], ], 'block' => [ 'title' => _x( 'Block', 'Layout options "Text Flow" heading', 'adpresso' ), 'description' => __( 'Text will continue after the ad and its margin.', 'adpresso' ), 'options' => [ 'left_nofloat' => [ 'img' => 'block-lr' ], 'center_nofloat' => [ 'img' => 'block-cntr' ], 'right_nofloat' => [ 'img' => 'block-lr' ], ], ], ]; } /** * Displays the layout box content. * * @param WP_Post $post The post object. * @param array $box The metabox array. * * @return void */ public function display( WP_Post $post, array $box ): void { parent::display( $post, $box ); wp_enqueue_style( 'adpresso-alignment' ); $layout_settings = get_post_meta( $post->ID, self::META_KEY_LAYOUT, true ); if ( ! is_array( $layout_settings ) ) { $layout_settings = []; } // Spacing for ads and placements. if ( in_array( $post->post_type, [ Constants::POST_TYPE_AD, Constants::POST_TYPE_PLACEMENT ] ) ) { $spacing_data = $this->get_spacing_view_data( $layout_settings ); $options = $spacing_data['options']; $is_centered = $spacing_data['is_centered']; include ADPRESSO_ABSPATH . 'views/admin/fields/spacing.php'; } // Positioning only for placements. if ( $post->post_type === Constants::POST_TYPE_PLACEMENT ) { $positioning_options = $this->get_positioning_options_config(); $positioning = $layout_settings['position'] ?? 'none'; include ADPRESSO_ABSPATH . 'views/admin/fields/positioning.php'; } } /** * Saves the meta fields for this box. * * @param int $post_id The ID of the post being saved. * * @internal This method should not be called directly. Security checks (nonce verification, * capability checks) are handled by the calling orchestrator class (e.g., Metabox_Ad). * */ public function save( int $post_id, ParamsHandler $params_handler ): void { static $is_saving = false; if ( $is_saving ) { return; } $is_saving = true; // Release the guard even if saving throws. try { $current_post_type = get_post_type( $post_id ); $layout_settings = get_post_meta( $post_id, self::META_KEY_LAYOUT, true ); if ( ! is_array( $layout_settings ) ) { $layout_settings = []; } // Fetch the layout data array unsanitized from the Param class, so we can validate the known structure below. $data = $params_handler->getUnsanitized( 'layout_settings', [] ); $data = is_array( $data ) ? $data : []; // Save spacings for ads and placements. if ( in_array( $current_post_type, [ Constants::POST_TYPE_AD, Constants::POST_TYPE_PLACEMENT ] ) ) { $margins = is_array( $data['margin'] ?? null ) ? $data['margin'] : []; $margin_handler = new ParamsHandler( $margins ); $layout_settings['margin'] = [ 'top' => $margin_handler->getId( 'top' ), 'right' => $margin_handler->getId( 'right' ), 'bottom' => $margin_handler->getId( 'bottom' ), 'left' => $margin_handler->getId( 'left' ), ]; } // Save positioning for placements only. if ( $current_post_type === Constants::POST_TYPE_PLACEMENT ) { $data_handler = new ParamsHandler( $data ); $position = $data_handler->getKey( 'position', 'none' ); $allowed_positions = array_keys( $this->get_positioning_options_config()['default']['options'] ?? [] ); $allowed_positions = array_merge( $allowed_positions, array_keys( $this->get_positioning_options_config()['float']['options'] ?? [] ) ); $allowed_positions = array_merge( $allowed_positions, array_keys( $this->get_positioning_options_config()['block']['options'] ?? [] ) ); if ( in_array( $position, array_unique( $allowed_positions ), true ) ) { $layout_settings['position'] = $position; } else { $layout_settings['position'] = 'none'; } } if ( ! empty( $layout_settings ) ) { update_post_meta( $post_id, self::META_KEY_LAYOUT, $layout_settings ); } else { delete_post_meta( $post_id, self::META_KEY_LAYOUT ); } parent::save( $post_id, $params_handler ); } finally { $is_saving = false; } } }