0`) и быть одним из известных вложений — * товар без изображения показывал бы заглушку WooCommerce, и окошко этого не позволяет; * - галерея — известные вложения, без повторов и без изображения товара: одно фото * в одном месте; не длиннее предела; * - изображения вариаций — вариация обязана быть вариацией этого товара, значение — * известное вложение или 0 («снять изображение»). * * «Известные вложения» — те, что в момент открытия окошка стояли изображением товара, * в галерее или у вариаций (их собирает Product_Images::known_ids). Отказ возвращается кодом: * текст для человека подбирает адрес REST, здесь WordPress нет. * * Чистая логика без WordPress — проверяется тестами. */ final class Images_Layout { /** * Сколько фото принимает галерея из окошка — предел на один запрос, тот же, что у списка * фото товара для окна генерации. Он же — сколько фото галереи окошко показывает: предел * обязан быть не меньше показа, иначе фото за пределом молча выпали бы из карточки * при записи. */ public const MAX_GALLERY = 200; /** Изображения товара нет или оно не из известных вложений. */ public const ERROR_MAIN_MISSING = 'main_missing'; /** Вложение не принадлежит товару. */ public const ERROR_UNKNOWN_ATTACHMENT = 'unknown_attachment'; /** Одно фото в галерее дважды. */ public const ERROR_DUPLICATE_GALLERY = 'duplicate_gallery'; /** Изображение товара заодно и в галерее. */ public const ERROR_MAIN_IN_GALLERY = 'main_in_gallery'; /** Галерея длиннее предела. */ public const ERROR_TOO_MANY = 'too_many'; /** Вариация не этого товара. */ public const ERROR_UNKNOWN_VARIATION = 'unknown_variation'; /** * Проверяет тело запроса и приводит его к числам. * * @param array $body Тело запроса: mainId, galleryIds, variationImages. * @param array $known_ids Вложения, которые сейчас у товара. * @param array $variation_ids Вариации этого товара. * @param int $max_gallery Предел длины галереи. * @return array{ok: bool, error?: string, mainId?: int, galleryIds?: int[], variationImages?: array} * ok — всё сходится, и дальше идут приведённые значения; иначе error — один из кодов ERROR_*. */ public static function check( array $body, array $known_ids, array $variation_ids, int $max_gallery = self::MAX_GALLERY ): array { $known = array_map( 'intval', $known_ids ); $variations = array_map( 'intval', $variation_ids ); $main_id = (int) ( $body['mainId'] ?? 0 ); if ( $main_id <= 0 ) { return self::refuse( self::ERROR_MAIN_MISSING ); } if ( ! in_array( $main_id, $known, true ) ) { return self::refuse( self::ERROR_UNKNOWN_ATTACHMENT ); } $gallery_raw = $body['galleryIds'] ?? array(); $gallery = array(); if ( ! is_array( $gallery_raw ) ) { return self::refuse( self::ERROR_UNKNOWN_ATTACHMENT ); } if ( count( $gallery_raw ) > $max_gallery ) { return self::refuse( self::ERROR_TOO_MANY ); } foreach ( $gallery_raw as $raw_id ) { $id = (int) $raw_id; if ( $id <= 0 || ! in_array( $id, $known, true ) ) { return self::refuse( self::ERROR_UNKNOWN_ATTACHMENT ); } if ( $id === $main_id ) { return self::refuse( self::ERROR_MAIN_IN_GALLERY ); } if ( in_array( $id, $gallery, true ) ) { return self::refuse( self::ERROR_DUPLICATE_GALLERY ); } $gallery[] = $id; } $variation_raw = $body['variationImages'] ?? array(); $variation_images = array(); if ( ! is_array( $variation_raw ) ) { return self::refuse( self::ERROR_UNKNOWN_VARIATION ); } foreach ( $variation_raw as $raw_variation_id => $raw_attachment_id ) { $variation_id = (int) $raw_variation_id; $attachment_id = (int) $raw_attachment_id; if ( $variation_id <= 0 || ! in_array( $variation_id, $variations, true ) ) { return self::refuse( self::ERROR_UNKNOWN_VARIATION ); } // 0 — снять изображение вариации; иначе только известное вложение. if ( $attachment_id < 0 || ( $attachment_id > 0 && ! in_array( $attachment_id, $known, true ) ) ) { return self::refuse( self::ERROR_UNKNOWN_ATTACHMENT ); } $variation_images[ $variation_id ] = $attachment_id; } return array( 'ok' => true, 'mainId' => $main_id, 'galleryIds' => $gallery, 'variationImages' => $variation_images, ); } /** * Отказ с кодом. * * @param string $error Код — одна из констант ERROR_*. * @return array{ok: bool, error: string} */ private static function refuse( string $error ): array { return array( 'ok' => false, 'error' => $error, ); } }