&page= (aoo lib/storefront-embed/admin-data.ts) * → {items:[{name, code, sku, variation_count, image, price, price_max, compare_at, in_stock(bool|null), shown, active, * category, collections[], edit_url, view_url}], total, page, per_page, counts{all,shown,hidden}, categories[{slug,name}], * stock_enabled, links{products,new_product}} * Products are not personal data → works without the "share" switch · no cost price, no stock quantities (in stock yes/no). * Fetched live on each view (no transient). Capability: AooShop_Roles::products_cap(). * * @package AooShop */ defined( 'ABSPATH' ) || exit; class AooShop_Admin_Products { const SLUG = 'aooshop-products'; /** @var AooShop_Settings */ private $settings; /** @var AooShop_Api_Client */ private $api; public function __construct( AooShop_Settings $settings, AooShop_Api_Client $api ) { $this->settings = $settings; $this->api = $api; } private static function price_html( array $p ) { if ( ! isset( $p['price'] ) || null === $p['price'] ) { return '–'; } $min = (float) $p['price']; $max = isset( $p['price_max'] ) && null !== $p['price_max'] ? (float) $p['price_max'] : $min; if ( $max > $min ) { return esc_html( AooShop_Admin::money( $min ) . ' – ' . AooShop_Admin::money( $max ) ); } $out = ''; if ( isset( $p['compare_at'] ) && null !== $p['compare_at'] && (float) $p['compare_at'] > $min ) { $out .= '' . esc_html( AooShop_Admin::money( $p['compare_at'] ) ) . ' '; } return $out . '' . esc_html( AooShop_Admin::money( $min ) ) . ''; } public function render() { if ( ! current_user_can( AooShop_Roles::products_cap() ) ) { return; } // phpcs:disable WordPress.Security.NonceVerification.Recommended -- read-only screen; filters only. $q = isset( $_GET['s'] ) ? substr( sanitize_text_field( wp_unslash( $_GET['s'] ) ), 0, 80 ) : ''; $visible = isset( $_GET['visible'] ) && in_array( $_GET['visible'], array( '0', '1' ), true ) ? sanitize_key( wp_unslash( $_GET['visible'] ) ) : ''; $category = isset( $_GET['category'] ) ? sanitize_text_field( wp_unslash( $_GET['category'] ) ) : ''; $page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:enable echo '
'; AooShop_Admin::header( __( 'Products', 'aoo-shop' ) ); if ( ! $this->settings->is_configured() ) { echo '

' . esc_html__( 'Add your AOO API key first. Your shop products will then appear here.', 'aoo-shop' ) . '

' . '

' . esc_html__( 'Go to connection settings', 'aoo-shop' ) . '

'; return; } $res = $this->api->get( 'admin/products', array( 'q' => $q, 'visible' => $visible, 'category' => $category, 'page' => $page > 1 ? $page : null, ) ); if ( is_wp_error( $res ) ) { echo '

' . esc_html( sprintf( /* translators: %s: error message */ __( 'Could not load products from AOO: %s', 'aoo-shop' ), $res->get_error_message() ) ) . '

' . '

' . esc_html__( 'Try again', 'aoo-shop' ) . '

'; return; } $d = is_array( $res['data'] ) ? $res['data'] : array(); $items = isset( $d['items'] ) && is_array( $d['items'] ) ? $d['items'] : array(); $counts = isset( $d['counts'] ) && is_array( $d['counts'] ) ? $d['counts'] : array(); $cats = isset( $d['categories'] ) && is_array( $d['categories'] ) ? $d['categories'] : array(); $total = isset( $d['total'] ) ? (int) $d['total'] : 0; $per = isset( $d['per_page'] ) ? max( 1, (int) $d['per_page'] ) : 20; $stock = ! empty( $d['stock_enabled'] ); $links = isset( $d['links'] ) && is_array( $d['links'] ) ? $d['links'] : array(); $base = AooShop_Admin::url( self::SLUG ); $new = AooShop_Admin::http_url( isset( $links['new_product'] ) ? $links['new_product'] : '' ); if ( $new ) { echo '

' . esc_html__( 'Add product in AOO', 'aoo-shop' ) . '

'; } // Visibility tabs. $tabs = array( '' => array( __( 'All', 'aoo-shop' ), 'all' ), '1' => array( __( 'Shown on web', 'aoo-shop' ), 'shown' ), '0' => array( __( 'Hidden from web', 'aoo-shop' ), 'hidden' ), ); echo ''; // Search + category filter (one GET form). echo '
'; if ( '' !== $visible ) { echo ''; } echo ''; echo '
' . '
'; $this->pages( $total, $per, $page ); echo '
'; echo '' . '' . '' . '' . '' . ( $stock ? '' : '' ) . '' . '' . ''; if ( ! $items ) { echo ''; } foreach ( $items as $p ) { if ( ! is_array( $p ) ) { continue; } $img = AooShop_Admin::http_url( isset( $p['image'] ) ? $p['image'] : '' ); $edit = AooShop_Admin::http_url( isset( $p['edit_url'] ) ? $p['edit_url'] : '' ); $view = AooShop_Admin::http_url( isset( $p['view_url'] ) ? $p['view_url'] : '' ); $name = isset( $p['name'] ) ? (string) $p['name'] : ''; $vars = isset( $p['variation_count'] ) ? (int) $p['variation_count'] : 0; echo ''; echo ''; echo ''; $code = isset( $p['code'] ) ? (string) $p['code'] : ''; $sku = isset( $p['sku'] ) ? (string) $p['sku'] : ''; echo ''; echo ''; if ( $stock ) { $in = array_key_exists( 'in_stock', $p ) ? $p['in_stock'] : null; echo ''; } if ( ! empty( $p['shown'] ) ) { $web = AooShop_Admin::status_pill( array( 'label' => __( 'Shown', 'aoo-shop' ), 'color' => 'done' ) ); } elseif ( isset( $p['active'] ) && ! $p['active'] ) { $web = AooShop_Admin::status_pill( array( 'label' => __( 'Disabled', 'aoo-shop' ), 'color' => 'off' ) ); } else { $web = AooShop_Admin::status_pill( array( 'label' => __( 'Hidden', 'aoo-shop' ), 'color' => 'off' ) ); } echo ''; $cat = isset( $p['category'] ) ? (string) $p['category'] : ''; $cols = isset( $p['collections'] ) && is_array( $p['collections'] ) ? array_filter( array_map( 'strval', $p['collections'] ), 'strlen' ) : array(); echo ''; echo ''; } echo '
' . esc_html__( 'Image', 'aoo-shop' ) . '' . esc_html__( 'Product name', 'aoo-shop' ) . '' . esc_html__( 'Code / SKU', 'aoo-shop' ) . '' . esc_html__( 'Price', 'aoo-shop' ) . '' . esc_html__( 'Stock', 'aoo-shop' ) . '' . esc_html__( 'On web', 'aoo-shop' ) . '' . esc_html__( 'Category / collections', 'aoo-shop' ) . '
' . esc_html__( 'No products found.', 'aoo-shop' ) . '
' . ( $img ? '' : '' ) . '' . ( $edit ? '' . esc_html( $name ) . '' : esc_html( $name ) ) . ''; if ( $vars > 1 ) { echo '
' . esc_html( sprintf( /* translators: %d: number of variations */ __( '%d variations', 'aoo-shop' ), $vars ) ) . '
'; } $acts = array(); if ( $edit ) { $acts[] = '' . esc_html__( 'Edit in AOO', 'aoo-shop' ) . ''; } if ( $view ) { $acts[] = '' . esc_html__( 'View on web', 'aoo-shop' ) . ''; } if ( $acts ) { echo '
' . wp_kses_post( implode( ' | ', $acts ) ) . '
'; } echo '
' . ( '' !== $code ? esc_html( $code ) : '–' ) . ( '' !== $sku && $sku !== $code ? '
' . esc_html( $sku ) . '
' : '' ) . '
' . wp_kses_post( self::price_html( $p ) ) . '' . ( null === $in ? '–' : ( $in ? '' . esc_html__( 'In stock', 'aoo-shop' ) . '' : '' . esc_html__( 'Out of stock', 'aoo-shop' ) . '' ) ) . '' . wp_kses_post( $web ) . '' . ( '' !== $cat ? esc_html( $cat ) : '–' ) . ( $cols ? '
' . esc_html( implode( ' · ', $cols ) ) . '
' : '' ) . '
'; echo '
'; $this->pages( $total, $per, $page ); echo '
'; $all = AooShop_Admin::http_url( isset( $links['products'] ) ? $links['products'] : '' ); echo '

' . esc_html__( 'Read-only — add or edit products, prices, images and web visibility in AOO, and the site updates automatically.', 'aoo-shop' ) . '

'; if ( $all ) { echo '

' . esc_html__( 'Open all products in AOO', 'aoo-shop' ) . '

'; } echo ''; } private function pages( $total, $per, $page ) { $pages = (int) ceil( $total / $per ); echo '
' . esc_html( sprintf( /* translators: %s: number of products */ _n( '%s item', '%s items', $total, 'aoo-shop' ), number_format_i18n( $total ) ) ) . ''; if ( $pages > 1 ) { echo '' . wp_kses_post( (string) paginate_links( array( 'base' => add_query_arg( 'paged', '%#%' ), 'format' => '', 'current' => min( $page, $pages ), 'total' => $pages, 'prev_text' => '‹', 'next_text' => '›', ) ) ) . ''; } echo '
'; } }