📁 File Manager Pro
v10.0.3 | PHP: 8.2.31
Server: LiteSpeed
2026-07-03 12:50:05
📂
/ (Root)
/
home
/
orkouolp
/
web
/
orkofarms.com
/
wp-content
/
plugins
/
woocommerce
/
src
/
StoreApi
/
Schemas
/
V1
📍 /home/orkouolp/web/orkofarms.com/wp-content/plugins/woocommerce/src/StoreApi/Schemas/V1
🔄 Refresh
✏️
Editing: ShopperListItemSchema.php
Writable
<?php declare( strict_types = 1 ); namespace Automattic\WooCommerce\StoreApi\Schemas\V1; use Automattic\WooCommerce\Internal\ShopperLists\ShopperListItem; use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema; use Automattic\WooCommerce\StoreApi\SchemaController; use Automattic\WooCommerce\StoreApi\Utilities\ProductItemTrait; /** * ShopperListItemSchema class. * * Serializes a {@see ShopperListItem}. Renders live product fields when the * item reports `is_live`, and falls back to at-save snapshot data otherwise. */ class ShopperListItemSchema extends AbstractSchema { // We only call format_variation_data(); see phpstan.neon for the related suppressions. use ProductItemTrait; /** * The schema item name. * * @var string */ protected $title = 'shopper_list_item'; /** * The schema item identifier. * * @var string */ const IDENTIFIER = 'shopper-list-item'; /** * Image attachment schema instance. * * @var ImageAttachmentSchema */ protected $image_attachment_schema; /** * Constructor. * * @throws \RuntimeException When the ImageAttachmentSchema is not registered. * * @param ExtendSchema $extend Rest Extending instance. * @param SchemaController $controller Schema Controller instance. */ public function __construct( ExtendSchema $extend, SchemaController $controller ) { parent::__construct( $extend, $controller ); $schema = $this->controller->get( ImageAttachmentSchema::IDENTIFIER ); if ( ! $schema instanceof ImageAttachmentSchema ) { throw new \RuntimeException( 'ImageAttachmentSchema is not registered in SchemaController.' ); } $this->image_attachment_schema = $schema; } /** * Item schema properties. * * @return array */ public function get_properties() { return array( 'key' => array( 'description' => __( 'Stable identifier for the saved item within its list.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'id' => array( 'description' => __( 'Variation ID if applicable, otherwise product ID.', 'woocommerce' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'product_id' => array( 'description' => __( 'Product ID at the time the item was saved.', 'woocommerce' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'variation_id' => array( 'description' => __( 'Variation ID at the time the item was saved, or 0 for non-variable products.', 'woocommerce' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'quantity' => array( 'description' => __( 'Quantity of this saved item.', 'woocommerce' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'is_live' => array( 'description' => __( 'True when the row serves live product data; false rows are at-save tombstones.', 'woocommerce' ), 'type' => 'boolean', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'is_purchasable' => array( 'description' => __( 'True when the product can be added to the cart.', 'woocommerce' ), 'type' => 'boolean', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'name' => array( 'description' => __( 'Product name. Live when is_live is true; falls back to the at-save title snapshot otherwise.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'permalink' => array( 'description' => __( 'Product URL. Null when the row is a tombstone (so iAPI strips the anchor href).', 'woocommerce' ), 'type' => array( 'string', 'null' ), 'format' => 'uri', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'images' => array( 'description' => __( 'List of images for the live product. Empty when the product no longer exists.', 'woocommerce' ), 'type' => 'array', 'context' => array( 'view', 'edit' ), 'readonly' => true, 'items' => array( 'type' => 'object', 'properties' => $this->image_attachment_schema->get_properties(), ), ), 'variation' => array( 'description' => __( 'Chosen variation attributes, if applicable.', 'woocommerce' ), 'type' => 'array', 'context' => array( 'view', 'edit' ), 'readonly' => true, 'items' => array( 'type' => 'object', 'properties' => array( 'raw_attribute' => array( 'description' => __( 'Variation system generated attribute name.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'attribute' => array( 'description' => __( 'Variation attribute name.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'value' => array( 'description' => __( 'Variation attribute value.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ), ), ), 'prices' => array( 'description' => __( 'Live product prices. Omitted when the product no longer exists.', 'woocommerce' ), 'type' => array( 'object', 'null' ), 'context' => array( 'view', 'edit' ), 'readonly' => true, 'properties' => array_merge( $this->get_store_currency_properties(), array( 'price' => array( 'description' => __( 'Current product price.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'regular_price' => array( 'description' => __( 'Regular product price.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'sale_price' => array( 'description' => __( 'Sale product price, if applicable.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ) ), ), 'price_html' => array( 'description' => __( 'Live product price as HTML, formatted via wc_price including sale/discount markup. Empty when the product no longer exists.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'image_html' => array( 'description' => __( 'Product thumbnail as a fully-formed <img> element with srcset, sizes, alt, and lazy-loading attributes. Falls back to the configured placeholder image when the product has no image or no longer exists.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'date_added_gmt' => array( 'description' => __( 'The date the item was saved, as GMT.', 'woocommerce' ), 'type' => 'string', 'format' => 'date-time', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ); } /** * Serialize the saved item. * * @param ShopperListItem $item Saved item. * @return array */ public function get_item_response( $item ) { $variation_id = $item->get_variation_id(); $product_id = $variation_id > 0 ? $variation_id : $item->get_product_id(); $product = $item->get_product(); $is_live = $item->is_live(); $response = array( 'key' => $item->get_key(), 'id' => $product_id, 'product_id' => $item->get_product_id(), 'variation_id' => $variation_id, 'quantity' => $item->get_quantity(), 'is_live' => $is_live, 'is_purchasable' => $item->is_purchasable(), 'date_added_gmt' => wc_rest_prepare_date_response( $item->get_date_added_gmt() ), ); if ( $is_live && $product instanceof \WC_Product ) { $response['name'] = $this->get_name( $product ); $response['permalink'] = $product->get_permalink(); $response['images'] = $this->get_images( $product ); $response['variation'] = $this->format_variation_data( $item->get_variation_attributes(), $product ); $response['prices'] = (object) $this->get_prices( $product ); $response['price_html'] = (string) $product->get_price_html(); $response['image_html'] = $this->get_image_html( $product ); } else { $response['name'] = $this->prepare_html_response( $item->get_product_title_at_save() ); $response['permalink'] = null; $response['images'] = array(); $response['variation'] = array(); $response['prices'] = null; $response['price_html'] = ''; $response['image_html'] = $this->get_image_html( null ); } return $response; } /** * Get the displayable name for the live product. * * @param \WC_Product $product Live product instance. * @return string */ private function get_name( \WC_Product $product ): string { $prepared = $this->prepare_html_response( $product->get_title() ); return is_string( $prepared ) ? $prepared : (string) $product->get_title(); } /** * Get the main image for a shopper list item. * * Returns the product's main image only — shopper list rows are compact and * the gallery isn't needed at the row level. * * @param \WC_Product $product Live product instance. * @return array */ private function get_images( \WC_Product $product ): array { $image_id = (int) $product->get_image_id(); if ( $image_id <= 0 ) { return array(); } $image = $this->image_attachment_schema->get_item_response( $image_id ); return $image ? array( $image ) : array(); } /** * Get the thumbnail image HTML for a shopper list item, falling back to the * WooCommerce placeholder when the product has no image or has been deleted. * * Pre-formatting on the server lets renderers (PHP SSR + JS hydration) * consume one canonical string instead of each side composing the markup * from the structured `images` array. Mirrors the pattern WC uses in * `ProductSchema::price_html` / `ProductImage::render`. * * @param \WC_Product|null $product Live product instance, or null for tombstones. * @return string */ private function get_image_html( ?\WC_Product $product ): string { $image_id = $product instanceof \WC_Product ? (int) $product->get_image_id() : 0; if ( $image_id > 0 ) { return (string) wp_get_attachment_image( $image_id, 'woocommerce_thumbnail' ); } return (string) wc_placeholder_img( 'woocommerce_thumbnail' ); } /** * Compute live prices for the saved item. * * We don't extend ProductSchema because saved items aren't products. The shape * here is a thin subset of cart-item prices. * * @param \WC_Product $product Live product instance. * @return array */ private function get_prices( \WC_Product $product ): array { $decimals = wc_get_price_decimals(); $regular_price = $product->get_regular_price(); $sale_price = $product->get_sale_price(); $current_price = $product->get_price(); return $this->prepare_currency_response( array( 'price' => $this->prepare_money_response( $current_price, $decimals ), 'regular_price' => $this->prepare_money_response( '' === $regular_price ? $current_price : $regular_price, $decimals ), 'sale_price' => '' === $sale_price ? '' : $this->prepare_money_response( $sale_price, $decimals ), ) ); } }
💾 Save Changes
❌ Cancel