plugin = $plugin; } /** * Translated text for a builder message. * * @param array $message [code, text]. * @param string $channel_label Marketplace name. */ public static function message_text( array $message, string $channel_label ): string { $texts = array( 'no_category' => Text::channel( __( 'Not mapped: this product has no {channel} category. Set it in the category mapping.', 'tidelist' ), $channel_label ), 'category_not_leaf' => Text::channel( __( '{channel} only takes adverts in the last level of its categories. Choose a more specific category.', 'tidelist' ), $channel_label ), 'attribute_missing' => Text::channel( __( 'A required {channel} field has no value. See the attribute mapping.', 'tidelist' ), $channel_label ), 'attribute_unmapped' => Text::channel( __( 'A value is not in the list {channel} offers. Map it in the attribute mapping.', 'tidelist' ), $channel_label ), 'category_ambiguous' => Text::channel( __( 'The shop categories of this product lead to more than one {channel} category, so one was picked. Check that it is the right one.', 'tidelist' ), $channel_label ), 'attribute_many' => Text::channel( __( '{channel} takes only one value for a field. The first one was used.', 'tidelist' ), $channel_label ), 'no_attribute_data' => Text::channel( __( 'The attributes of this {channel} category could not be read, so none are sent.', 'tidelist' ), $channel_label ), 'out_of_stock' => __( 'This product is out of stock, so it cannot be advertised. Put it back in stock in the shop first.', 'tidelist' ), 'not_for_sale' => __( 'This product is not published in the shop, so it cannot be advertised.', 'tidelist' ), 'no_price' => __( 'The product has no price.', 'tidelist' ), 'no_photos' => __( 'The product has no photos.', 'tidelist' ), 'photos_from_parent' => __( 'This variation has no own photos. The product photos are used and may show other options.', 'tidelist' ), 'photo_convert_failed' => __( 'A JPG copy of a .webp photo could not be made. Untick that photo.', 'tidelist' ), 'photo_copy_not_public' => Text::channel( __( 'The JPG copies of .webp photos can only be downloaded by {channel} after the plugin is installed on the live site. Until then this advert cannot be published.', 'tidelist' ), $channel_label ), 'contacts_removed' => __( 'A web address, e-mail or phone number was removed from the product text.', 'tidelist' ), 'no_contact' => __( 'Contact name is not set (Settings).', 'tidelist' ), ); $text = $texts[ $message['code'] ] ?? $message['text']; // Say which field it is: the generic sentence alone leaves the owner guessing. $args = isset( $message['args'] ) && is_array( $message['args'] ) ? array_values( $message['args'] ) : array(); if ( 'category_ambiguous' === $message['code'] && isset( $args[0], $args[1] ) ) { /* translators: 1: the category that was picked, 2: the other possible categories */ $text .= ' ' . sprintf( __( 'Picked: %1$s. Also possible: %2$s.', 'tidelist' ), (string) $args[0], (string) $args[1] ); } elseif ( 'attribute_missing' === $message['code'] && isset( $args[0] ) ) { /* translators: %s: name of the marketplace field */ $text .= ' ' . sprintf( __( 'Field: "%s".', 'tidelist' ), (string) $args[0] ); } elseif ( 'attribute_unmapped' === $message['code'] && isset( $args[0], $args[1] ) ) { /* translators: 1: name of the marketplace field, 2: the shop value */ $text .= ' ' . sprintf( __( 'Field: "%1$s", value: "%2$s".', 'tidelist' ), (string) $args[0], (string) $args[1] ); } return $text; } /** * The preview as HTML. * * @param int $product_id Product ID. * @param int|null $variation_id Variation ID. */ public function html( int $product_id, ?int $variation_id ): string { $channel = $this->plugin->channel(); $channel_label = $channel->label(); $result = $this->plugin->build_listing( $product_id, $variation_id ); ob_start(); if ( null === $result ) { echo '

' . esc_html__( 'This product no longer exists.', 'tidelist' ) . '

'; return (string) ob_get_clean(); } $listing = $result->listing; $body = null === $listing ? array() : $channel->request_body( $listing ); ?>

title ); ?>

messages( $result, $channel_label ); ?>
info['shop_price'] ?? 0 ); $sent = null === $listing ? 0.0 : $listing->price; echo esc_html( number_format_i18n( $sent, 2 ) . ' ' . (string) ( $result->info['currency'] ?? '' ) ); if ( abs( $price_info - $sent ) > 0.001 ) { echo ' ' . esc_html( sprintf( /* translators: %s: converted shop price */ __( '(price rule applied; converted shop price %s)', 'tidelist' ), number_format_i18n( $price_info, 2 ) ) ) . ''; } ?>
info['category'] ?? '' ) ? (string) $result->info['category'] : '—' ); ?>
attributes_text( null === $listing ? array() : $listing->attributes ) ); ?>
contact, array( (string) ( $result->info['location'] ?? '' ) ) ) ) ) ); ?>
category_form( $product_id, $variation_id, $channel_label ); ?>

description ); ?>

photos( $result, null === $listing ? array() : $listing->images, $product_id, $variation_id ); ?>
plugin->category_override_of( $product_id ); $product = wc_get_product( $product_id ); $title = $product ? wp_strip_all_tags( $product->get_name() ) : ''; ?>

0 ? Text::channel( __( 'This category was chosen for this product. The category mapping is not used for it.', 'tidelist' ), $channel_label ) : Text::channel( __( 'The category comes from the category mapping. Search for another {channel} category to use for this product only.', 'tidelist' ), $channel_label ) ); ?>

0 ) : ?>

errors as $message ) { echo '

' . esc_html__( 'Fix before publishing:', 'tidelist' ) . ' ' . esc_html( self::message_text( $message, $channel_label ) ) . '

'; } foreach ( $result->warnings as $message ) { echo '

' . esc_html( self::message_text( $message, $channel_label ) ) . '

'; } if ( ! $result->errors && ! $result->warnings ) { echo '

' . esc_html__( 'Ready: no errors or warnings.', 'tidelist' ) . '

'; } } /** * Photo picker. * * @param BuildResult $result Result. * @param string[] $sent Photo addresses that are sent. * @param int $product_id Product ID. * @param int|null $variation_id Variation ID. */ private function photos( BuildResult $result, array $sent, int $product_id, ?int $variation_id ): void { $image_base = (string) $this->plugin->settings()->get( 'image_base_url' ); $base_url = rtrim( $image_base, '/' ) . '/wp-content/uploads/'; $all = array_values( array_filter( explode( "\n", (string) ( $result->info['all_photos'] ?? '' ) ) ) ); ?>
$path ) : ?>