REDROOM
PHP 8.2.31
Path:
Logout
Edit File
Size: 9.64 KB
Close
/home/nshryvcy/radiantskinclinics.org/wp-content/plugins/woocommerce/src/Internal/OrderReviews/ItemEligibility.php
Text
Base64
<?php /** * ItemEligibility class file. */ declare( strict_types = 1 ); namespace Automattic\WooCommerce\Internal\OrderReviews; use WC_Order; use WC_Order_Item; use WC_Order_Item_Product; use WP_Comment; /** * Decides how each Review Order line item should be rendered and supplies * any pre-fill data for the row form. * * Two outcomes for a row: * * - `form` — render the editable form row (`customer-review-order-row.php`), * optionally pre-filled with the rating + text the customer has already * submitted for this product **on this order**. * - `skip` — render nothing (e.g. the product has reviews disabled). * * Reviews left for a *different* order are not surfaced here: a customer who * buys the same product again gets a fresh form row, because their experience * the second time around may be different from the first. * * @internal Just for internal use. * * @since 10.8.0 */ class ItemEligibility { /** * Render the editable form row. * * @since 10.8.0 */ public const STATUS_FORM = 'form'; /** * Render nothing (e.g. comments closed on the product). * * @since 10.8.0 */ public const STATUS_SKIP = 'skip'; /** * Commentmeta key storing the order this review was submitted for. * * @since 10.8.0 */ public const ORDER_META_KEY = '_review_order_id'; /** * Per-request cache for the "did this email review this product on this * order" lookup, keyed by `order_id|product_id|email`. Value is a * `WP_Comment` when one matches, or `null` when the slot has been checked * and nothing matches (so a second call doesn't re-query). * * @var array<string, ?WP_Comment> */ private static array $review_cache = array(); /** * Set of `order_id|email` pairs that have already been bulk-preloaded in * this request, so a repeated `preload_for_items()` call (e.g. once from * the Endpoint and once from the page template) doesn't re-run the query. * * @var array<string, true> */ private static array $preloaded = array(); /** * Register the default filter callbacks the OrderReviews feature ships with. * * Auto-called by the WC dependency container after instantiation. * * @internal */ final public function init(): void { add_filter( 'woocommerce_review_order_eligible_items', array( self::class, 'exclude_fully_refunded_items' ), 10, 2 ); } /** * Pre-fill the per-request review cache for a set of items in one query. * * Call this from the template before iterating items so each subsequent * `decide()` / `prefill_for_item()` call hits the cache instead of running * its own `get_comments()` query. * * @since 10.8.0 * * @param iterable<WC_Order_Item_Product|mixed> $items Order line items. * @param WC_Order $order Order being reviewed. */ public static function preload_for_items( iterable $items, WC_Order $order ): void { $email = $order->get_billing_email(); $order_id = $order->get_id(); if ( '' === $email || $order_id <= 0 ) { return; } $preload_key = $order_id . '|' . $email; if ( isset( self::$preloaded[ $preload_key ] ) ) { return; } $product_ids = array(); foreach ( $items as $item ) { if ( $item instanceof WC_Order_Item_Product ) { $pid = (int) $item->get_product_id(); if ( $pid > 0 ) { $product_ids[ $pid ] = $pid; } } } if ( empty( $product_ids ) ) { return; } self::$preloaded[ $preload_key ] = true; // Scope to this order's reviews only: a customer who buys the same // product on a later order shouldn't see their old review here. $comments = get_comments( array( 'post__in' => array_values( $product_ids ), 'author_email' => $email, 'type' => 'review', 'status' => 'approve', 'include_unapproved' => array( $email ), 'orderby' => 'comment_date_gmt', 'order' => 'DESC', 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- bounded by post__in + author_email. array( 'key' => self::ORDER_META_KEY, 'value' => (string) $order_id, ), ), ) ); // Default every product id to null so subsequent reads don't re-query. foreach ( $product_ids as $pid ) { self::$review_cache[ self::cache_key( $order_id, $pid, $email ) ] = null; } if ( is_array( $comments ) ) { foreach ( $comments as $comment ) { if ( ! $comment instanceof WP_Comment ) { continue; } $key = self::cache_key( $order_id, (int) $comment->comment_post_ID, $email ); if ( null === ( self::$review_cache[ $key ] ?? null ) ) { self::$review_cache[ $key ] = $comment; } } } } /** * Reset the per-request cache. Test helper. * * @since 10.8.0 * @internal */ public static function reset_cache(): void { self::$review_cache = array(); self::$preloaded = array(); } /** * Decide how an order line item should render on the Review Order page. * * Returns one of the STATUS_* constants plus the matched comment (when * one exists for this order) and the product id. * * @since 10.8.0 * * @param WC_Order_Item_Product $item Order line item. * @param WC_Order $order Order being reviewed. * @return array{status:string, comment:?WP_Comment, product_id:int} */ public static function decide( WC_Order_Item_Product $item, WC_Order $order ): array { $product_id = (int) $item->get_product_id(); $result = array( 'status' => self::STATUS_FORM, 'comment' => null, 'product_id' => $product_id, ); if ( $product_id <= 0 || ! comments_open( $product_id ) ) { $result['status'] = self::STATUS_SKIP; return $result; } $result['comment'] = self::find_existing_review( $product_id, $order ); return $result; } /** * Pre-fill payload for a line item: rating, text, and comment id. * * Returns zero/empty values when no review exists for this order's row, * so callers can use it unconditionally. * * @since 10.8.0 * * @param WC_Order_Item_Product $item Order line item. * @param WC_Order $order Order being reviewed. * @return array{rating:int, text:string, comment_id:int} */ public static function prefill_for_item( WC_Order_Item_Product $item, WC_Order $order ): array { $existing = self::find_existing_review( (int) $item->get_product_id(), $order ); if ( ! $existing instanceof WP_Comment ) { return array( 'rating' => 0, 'text' => '', 'comment_id' => 0, ); } $rating = (int) get_comment_meta( (int) $existing->comment_ID, 'rating', true ); if ( $rating < 0 || $rating > 5 ) { $rating = 0; } return array( 'rating' => $rating, 'text' => (string) $existing->comment_content, 'comment_id' => (int) $existing->comment_ID, ); } /** * Drop fully-refunded line items from the eligible-items list. * * Default callback wired onto `woocommerce_review_order_eligible_items` * so the page never shows a row for a product the customer no longer * owns. A line item is considered fully refunded when the absolute * refunded quantity is greater than or equal to the item's ordered * quantity. Fractional quantities are honoured. * * @since 10.8.0 * * @param WC_Order_Item[] $items Order line items. * @param WC_Order $order Order being reviewed. * @return WC_Order_Item[] */ public static function exclude_fully_refunded_items( array $items, WC_Order $order ): array { $filtered = array(); foreach ( $items as $key => $item ) { if ( ! $item instanceof WC_Order_Item_Product ) { $filtered[ $key ] = $item; continue; } $refunded_qty = (float) abs( (float) $order->get_qty_refunded_for_item( $item->get_id() ) ); $ordered_qty = (float) $item->get_quantity(); if ( $ordered_qty > 0 && $refunded_qty >= $ordered_qty ) { continue; } $filtered[ $key ] = $item; } return $filtered; } /** * Look up the customer's review for a product on this order. * * @since 10.8.0 * * @param int $product_id Product id. * @param WC_Order $order Order being reviewed. * @return WP_Comment|null */ private static function find_existing_review( int $product_id, WC_Order $order ): ?WP_Comment { $email = $order->get_billing_email(); $order_id = (int) $order->get_id(); if ( '' === $email || $order_id <= 0 || $product_id <= 0 ) { return null; } $key = self::cache_key( $order_id, $product_id, $email ); if ( array_key_exists( $key, self::$review_cache ) ) { return self::$review_cache[ $key ]; } $comments = get_comments( array( 'post_id' => $product_id, 'author_email' => $email, 'type' => 'review', 'status' => 'approve', 'include_unapproved' => array( $email ), 'number' => 1, 'orderby' => 'comment_date_gmt', 'order' => 'DESC', 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- bounded by post_id + author_email. array( 'key' => self::ORDER_META_KEY, 'value' => (string) $order_id, ), ), ) ); if ( ! is_array( $comments ) || empty( $comments ) ) { self::$review_cache[ $key ] = null; return null; } $first = reset( $comments ); $found = $first instanceof WP_Comment ? $first : null; self::$review_cache[ $key ] = $found; return $found; } /** * Build the per-request cache key. * * @param int $order_id Order id. * @param int $product_id Product id. * @param string $email Customer email. */ private static function cache_key( int $order_id, int $product_id, string $email ): string { return $order_id . '|' . $product_id . '|' . $email; } }
Save
Close
Exit & Reset
Text mode: syntax highlighting auto-detects file type.
Directory Contents
Dirs: 0 × Files: 6
Delete Selected
Select All
Select None
Sort:
Name
Size
Modified
Enable drag-to-move
Name
Size
Perms
Modified
Actions
Endpoint.php
27.62 KB
lrw-r--r--
2026-05-25 14:01:26
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
ItemEligibility.php
9.64 KB
lrw-r--r--
2026-05-25 14:01:26
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Meta.php
1.34 KB
lrw-r--r--
2026-05-25 14:01:26
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Scheduler.php
7.30 KB
lrw-r--r--
2026-05-25 14:01:26
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
StarRating.php
2.88 KB
lrw-r--r--
2026-05-11 17:17:08
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
SubmissionHandler.php
13.65 KB
lrw-r--r--
2026-05-25 14:01:26
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Zip Selected
If ZipArchive is unavailable, a
.tar
will be created (no compression).