Merge pull request #30900 from woocommerce/update/marketplace-featured-page

Revamp Featured page in WooCommerce Marketplace
This commit is contained in:
Néstor Soriano 2021-10-15 09:22:19 +02:00 committed by GitHub
commit d5b874a7fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 502 additions and 380 deletions

View File

@ -194,14 +194,6 @@
}
}
h1.search-form-title {
clear: left;
font-size: 20px;
line-height: 1.2;
margin: 48px 0 16px;
padding: 0;
}
.update-plugins .update-count {
background-color: #d54e21;
border-radius: 10px;
@ -215,6 +207,26 @@
vertical-align: text-top;
}
/**
* Marketplace related variables
*/
$font-sf-pro-text:
helveticaneue-light,
"Helvetica Neue Light",
"Helvetica Neue",
sans-serif;
$font-sf-pro-display: sans-serif;
h1.search-form-title {
clear: left;
font-size: 20px;
font-family: $font-sf-pro-display;
line-height: 1.2;
margin: 48px 0 16px;
padding: 0;
}
.addons-featured {
margin: 0;
}
@ -243,82 +255,15 @@
width: 124px;
}
.addons-banner-block-item-icon,
.addons-column-block-item-icon {
align-items: center;
display: flex;
justify-content: center;
}
.addons-banner-block,
.addons-wcs-banner-block {
align-items: center;
background: #fff;
border: 1px solid #ddd;
display: flex;
margin: 0 0 1em 0;
padding: 2em 2em 1em;
}
.addons-banner-block img {
height: 62px;
}
.addons-banner-block p {
margin: 0 0 20px;
}
.addons-banner-block-items {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
margin: 0 -10px 0 -10px;
}
.addons-banner-block-item {
border: 1px solid #e6e6e6;
border-radius: 3px;
flex: 1;
margin: 1em;
min-width: 200px;
width: 30%;
}
.addons-banner-block-item-icon {
background: #f7f7f7;
height: 143px;
}
.addons-banner-block-item-content {
display: flex;
flex-direction: column;
height: 184px;
justify-content: space-between;
padding: 24px;
}
.addons-banner-block-item-content h3 {
margin-top: 0;
}
.addons-banner-block-item-content p {
margin: 0 0 auto;
}
.addons-wcs-banner-block {
display: flex;
align-items: center;
}
.addons-promotion-block {
display: flex;
padding: 20px;
.addons-img {
height: auto;
width: 200px;
}
}
.addons-wcs-banner-block-image {
background: #f7f7f7;
border: 1px solid #e6e6e6;
@ -343,33 +288,6 @@
}
}
.addons-promotion-block-content {
display: flex;
flex-direction: column;
margin-left: 24px;
}
.addons-promotion-block-description {
margin-bottom: 20px;
}
.addons-promotion-block-title {
margin: 0 0 16px;
padding: 0;
}
.addons-promotion-block-buttons {
margin-top: auto;
.addons-button {
margin-right: 8px;
&:last-child {
margin-right: 0;
}
}
}
.addons-shipping-methods .addons-wcs-banner-block {
margin-left: 0;
margin-right: 0;
@ -415,13 +333,6 @@
}
}
.addons-column-section {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
}
.addons-column {
flex: 1;
width: 50%;
@ -432,90 +343,6 @@
margin-right: 0;
}
.addons-small-light-block,
.addons-small-dark-block,
.addons-column-block {
box-sizing: border-box;
border: 1px solid #ddd;
margin: 0 0 1em;
padding: 20px;
}
.addons-column-block img {
max-height: 50px;
max-width: 50px;
}
.addons-small-light-block,
.addons-column-block {
background: #fff;
}
.addons-column-block-left {
float: left;
}
.addons-column-block-right {
float: right;
}
.addons-column-block-item {
border-top: 2px solid #f9f9f9;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
margin: 0 -20px;
padding: 20px;
}
.addons-column-block-item-icon {
background: #f7f7f7;
border: 1px solid #e6e6e6;
height: 100px;
margin: 0 10px 10px 0;
width: 100px;
}
.addons-column-block-item-content {
display: flex;
flex: 1;
flex-wrap: wrap;
height: 20%;
justify-content: space-between;
min-width: 200px;
}
.addons-column-block-item-content h2 {
float: left;
margin-top: 8px;
}
.addons-column-block-item-content a {
float: right;
}
.addons-column-block-item-content p {
float: left;
}
.addons-banner-block-item,
.addons-column-block-item {
display: none;
}
.addons-banner-block-item:nth-child(-n + 3) {
display: block;
}
.addons-column-block-item:nth-of-type(-n + 3) {
display: flex;
}
.addons-small-dark-block {
background-color: #54687d;
text-align: center;
}
.addons-small-dark-items {
display: flex;
flex-wrap: wrap;
@ -526,14 +353,6 @@
margin: 0 0 20px;
}
.addons-small-dark-block h1 {
color: #fff;
}
.addons-small-dark-block p {
color: #fafafa;
}
.addons-small-dark-item-icon img {
height: 30px;
}
@ -542,40 +361,6 @@
margin: 28px auto 0;
}
.addons-small-light-block {
display: flex;
flex-wrap: wrap;
}
.addons-small-light-block h1 {
margin-top: -12px;
}
.addons-small-light-block p {
margin-top: 0;
}
.addons-small-light-block img {
height: 225px;
margin: 0 0 0 -20px;
}
.addons-small-light-block-content {
display: flex;
flex: 1 1 100px;
flex-direction: column;
justify-content: space-around;
}
.addons-small-light-block-buttons {
display: flex;
justify-content: space-between;
}
.addons-small-light-block-content a {
width: 48%;
}
.addons-button-solid {
background-color: #674399;
color: #fff;
@ -645,31 +430,64 @@
.addons-small-dark-item {
width: 100%;
}
.addons-column-block-item-icon {
background: none;
border: none;
height: 75px;
margin: 0 10px 10px 0;
width: 75px;
}
}
.marketplace-content-wrapper {
font-family: $font-sf-pro-text;
margin: 0 auto;
max-width: 1032px;
width: 100%;
}
.addon-product-group-title {
font-family: $font-sf-pro-display;
letter-spacing: 0.38px;
}
.addon-product-group-description-container {
align-items: center;
display: flex;
flex-direction: row;
font-size: 14px;
justify-content: space-between;
line-height: 20px;
.addon-product-group-see-more,
.addon-product-group-see-more:visited {
color: #007cba; /* Primary / Blue */
display: block;
font-size: 13px;
text-decoration: none;
}
}
.products {
display: flex;
flex-flow: row;
flex-wrap: wrap;
font-weight: normal;
justify-content: space-between;
margin: 0;
max-width: 1032px;
overflow: hidden;
.product.addons-product-banner,
.product.addons-buttons-banner {
max-width: calc(100% - 2px);
}
@media screen and (min-width: 960px) {
// Adjust heading titles font for three-column product groups
&.addons-products-three-column li.product {
max-width: calc(33.33% - 12px);
h2,
h3 {
font-size: 16px;
}
}
}
li {
background: #fff;
border: 1px solid #dcdcde;
@ -697,11 +515,15 @@
.product-details {
padding: 24px;
position: relative;
/* Display an image (product's icon) top right */
.product-img-wrap {
display: block;
float: right;
margin-left: 24px;
position: absolute;
right: 24px;
top: 24px;
img {
border-radius: 3px;
@ -712,24 +534,62 @@
}
}
/* Align aproduct-related banner image vertically centered */
&.addon-product-banner-details {
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
.product-img-wrap {
position: unset;
img {
max-width: 150px;
max-height: 150px;
}
}
}
h2,
h3 {
color: #007cba;
font-family:
HelveticaNeue-Light,
"Helvetica Neue Light",
"Helvetica Neue",
sans-serif;
font-size: 20px;
font-weight: 400;
letter-spacing: -0.32px;
line-height: 28px;
margin: 0 !important;
// Don't cover a product icon
max-width: calc(100% - 48px);
}
.addons-buttons-banner-details h2 {
color: #1d2327; // Gray / Gray 90
}
p {
color: #2c3338;
font-size: 14px;
line-height: 20px;
margin: 14px 64px 0 0;
max-width: 389px;
width: 100%;
}
.addons-buttons-banner-details p {
font-size: 14px;
margin-bottom: 14px;
max-width: none;
}
.product-developed-by {
color: #50575e; /* Gray 60 */
font-size: 12px;
line-height: 20px;
margin-top: 4px;
.product-vendor-link {
color: #50575e; /* Gray 60 */
}
}
.product-developed-by {
@ -802,7 +662,48 @@
border-color: #007cba;
color: #007cba;
float: right;
height: 22px;
font-size: 13px;
height: 36px;
line-height: 30px;
padding: 2px 14px;
}
}
}
.addons-buttons-banner {
display: flex;
flex-direction: row;
.addons-buttons-banner-image {
background-repeat: no-repeat;
background-size: cover;
height: 190px;
margin: 24px;
width: 200px;
}
.addons-buttons-banner-details-container {
padding-left: 0;
width: calc(100% - 198px - 24px - 24px);
}
.addons-buttons-banner-details-container {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.button.addons-buttons-banner-button,
.button.addons-buttons-banner-button:hover {
background: #fff;
border: 1.5px solid #624594;
color: #624594;
padding: 4px 12px;
margin-right: 16px;
&.addons-buttons-banner-button-primary {
background-color: #624594;
color: #fff;
}
}
}
@ -3016,30 +2917,6 @@ ul.wc_coupon_list_block {
float: right;
}
}
.wc-addons-wrap {
.addons-promotion-block {
flex-direction: column;
padding: 24px;
.addons-img {
height: auto;
width: 100%;
max-width: 240px;
margin: 0 auto 20px;
}
}
.addons-promotion-block-content {
display: block;
margin-left: 0;
}
.addons-promotion-block-title {
margin-top: 4px;
}
}
}
.column-customer_message .note-on {

2
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ed397d52c25da204154232b3dd4b529f",
"content-hash": "f694e88349087e677d5ae262107235de",
"packages": [
{
"name": "automattic/jetpack-autoloader",

View File

@ -21,6 +21,8 @@ class WC_Admin_Addons {
/**
* Get featured for the addons screen
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @return array of objects
*/
public static function get_featured() {
@ -55,6 +57,49 @@ class WC_Admin_Addons {
}
}
/**
* Render featured products and banners using WCCOM's the Featured 2.0 Endpoint
*
* @return void
*/
public static function render_featured() {
$featured = get_transient( 'wc_addons_featured' );
if ( false === $featured ) {
$headers = array();
$auth = WC_Helper_Options::get( 'auth' );
if ( ! empty( $auth['access_token'] ) ) {
$headers['Authorization'] = 'Bearer ' . $auth['access_token'];
}
$parameter_string = '';
$country = WC()->countries->get_base_country();
if ( ! empty( $country ) ) {
$parameter_string = '?' . http_build_query( array( 'country' => $country ) );
}
// Important: WCCOM Extensions API v2.0 is used.
$raw_featured = wp_safe_remote_get(
'https://woocommerce.com/wp-json/wccom-extensions/2.0/featured' . $parameter_string,
array(
'headers' => $headers,
'user-agent' => 'WooCommerce Addons Page',
)
);
if ( ! is_wp_error( $raw_featured ) ) {
$featured = json_decode( wp_remote_retrieve_body( $raw_featured ) );
if ( $featured ) {
set_transient( 'wc_addons_featured', $featured, DAY_IN_SECONDS );
}
}
}
if ( ! empty( $featured ) ) {
self::output_featured( $featured );
}
}
/**
* Build url parameter string
*
@ -141,9 +186,12 @@ class WC_Admin_Addons {
return false;
}
/**
* Get section content for the addons screen.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param string $section_id Required section ID.
*
* @return array
@ -172,6 +220,8 @@ class WC_Admin_Addons {
/**
* Handles the outputting of a contextually aware Storefront link (points to child themes if Storefront is already active).
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*/
public static function output_storefront_button() {
$template = get_option( 'template' );
@ -209,6 +259,8 @@ class WC_Admin_Addons {
/**
* Handles the outputting of a banner block.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param object $block Banner data.
*/
public static function output_banner_block( $block ) {
@ -246,6 +298,8 @@ class WC_Admin_Addons {
/**
* Handles the outputting of a column.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param object $block Column data.
*/
public static function output_column( $block ) {
@ -273,6 +327,8 @@ class WC_Admin_Addons {
/**
* Handles the outputting of a column block.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param object $block Column block data.
*/
public static function output_column_block( $block ) {
@ -309,6 +365,8 @@ class WC_Admin_Addons {
/**
* Handles the outputting of a small light block.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param object $block Block data.
*/
public static function output_small_light_block( $block ) {
@ -337,6 +395,8 @@ class WC_Admin_Addons {
/**
* Handles the outputting of a small dark block.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param object $block Block data.
*/
public static function output_small_dark_block( $block ) {
@ -369,6 +429,8 @@ class WC_Admin_Addons {
/**
* Handles the outputting of the WooCommerce Services banner block.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param object $block Block data.
*/
public static function output_wcs_banner_block( $block = array() ) {
@ -464,6 +526,8 @@ class WC_Admin_Addons {
/**
* Handles the outputting of the WooCommerce Pay banner block.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param object $block Block data.
*/
public static function output_wcpay_banner_block( $block = array() ) {
@ -523,6 +587,7 @@ class WC_Admin_Addons {
<?php
}
/**
* Output the HTML for the promotion block.
*
@ -554,9 +619,12 @@ class WC_Admin_Addons {
<?php
}
/**
* Handles the output of a full-width block.
*
* @deprecated 5.9.0 No longer used in In-App Marketplace
*
* @param array $section Section data.
*/
public static function output_promotion_block( $section ) {
@ -658,6 +726,115 @@ class WC_Admin_Addons {
}
}
/**
* Handles the outputting of featured page
*
* @param array $blocks Featured page's blocks.
*/
private static function output_featured( $blocks ) {
foreach ( $blocks as $block ) {
$block_type = $block->type ?? null;
switch ( $block_type ) {
case 'group':
self::output_group( $block );
break;
case 'banner':
self::output_banner( $block );
break;
}
}
}
/**
* Render a group block including products
*
* @param mixed $block Block of the page for rendering.
*
* @return void
*/
private static function output_group( $block ) {
$capacity = $block->capacity ?? 3;
$product_list_classes = 3 === $capacity ? 'three-column' : 'two-column';
$product_list_classes = 'products addons-products-' . $product_list_classes;
?>
<section class="addon-product-group">
<h1 class="addon-product-group-title"><?php echo esc_html( $block->title ); ?></h1>
<div class="addon-product-group-description-container">
<?php if ( ! empty( $block->description ) ) : ?>
<div class="addon-product-group-description">
<?php echo esc_html( $block->description ); ?>
</div>
<?php endif; ?>
<?php if ( null !== $block->url ) : ?>
<a class="addon-product-group-see-more" href="<?php echo esc_url( $block->url ); ?>">
<?php esc_html_e( 'See more', 'woocommerce' ); ?>
</a>
<?php endif; ?>
</div>
<div class="addon-product-group__items">
<ul class="<?php echo esc_attr( $product_list_classes ); ?>">
<?php
$products = array_slice( $block->items, 0, $capacity );
foreach ( $products as $item ) {
self::render_product_card( $item );
}
?>
</ul>
<div>
</section>
<?php
}
/**
* Render a banner contains a product
*
* @param mixed $block Block of the page for rendering.
*
* @return void
*/
private static function output_banner( $block ) {
if ( empty( $block->buttons ) ) {
// Render a product-like banner.
?>
<ul class="products">
<?php self::render_product_card( $block, $block->type ); ?>
</ul>
<?php
} else {
// Render a banner with buttons.
?>
<ul class="products">
<li class="product addons-buttons-banner">
<div class="addons-buttons-banner-image"
style="background-image:url(<?php echo esc_url( $block->image ); ?>)"
title="<?php echo esc_attr( $block->image_alt ); ?>"></div>
<div class="product-details addons-buttons-banner-details-container">
<div class="addons-buttons-banner-details">
<h2><?php echo esc_html( $block->title ); ?></h2>
<p><?php echo wp_kses( $block->description, array() ); ?></p>
</div>
<div class="addons-buttons-banner-button-container">
<?php
foreach ( $block->buttons as $button ) {
$button_classes = array( 'button', 'addons-buttons-banner-button' );
$type = $button->type ?? null;
if ( 'primary' === $type ) {
$button_classes[] = 'addons-buttons-banner-button-primary';
}
?>
<a class="<?php echo esc_attr( implode( ' ', $button_classes ) ); ?>"
href="<?php echo esc_url( $button->href ); ?>">
<?php echo esc_html( $button->title ); ?>
</a>
<?php } ?>
</div>
</div>
</li>
</ul>
<?php
}
}
/**
* Returns in-app-purchase URL params.
*/
@ -843,29 +1020,6 @@ class WC_Admin_Addons {
exit;
}
/**
* Should an extension be shown on the featured page.
*
* @param object $item Item data.
* @return boolean
*/
public static function show_extension( $item ) {
$location = WC()->countries->get_base_country();
if ( isset( $item->geowhitelist ) && ! in_array( $location, $item->geowhitelist, true ) ) {
return false;
}
if ( isset( $item->geoblacklist ) && in_array( $location, $item->geoblacklist, true ) ) {
return false;
}
if ( is_plugin_active( $item->plugin ) ) {
return false;
}
return true;
}
/**
* We're displaying page=wc-addons and page=wc-addons&section=helper as two separate pages.
* When we're on those pages, add body classes to distinguishe them.
@ -984,4 +1138,171 @@ class WC_Admin_Addons {
}
return $formatted_promotions;
}
/**
* Map data from different endpoints to a universal format
*
* Search and featured products has a slightly different products' field names.
* Mapping converts different data structures into a universal one for further processing.
*
* @param mixed $data Product Card Data.
*
* @return object Converted data.
*/
public static function map_product_card_data( $data ) {
$mapped = (object) null;
$type = $data->type ?? null;
// Icon.
$mapped->icon = $data->icon ?? null;
if ( null === $mapped->icon && 'banner' === $type ) {
// For product-related banners icon is a product's image.
$mapped->icon = $data->image ?? null;
}
// URL.
$mapped->url = $data->link ?? null;
if ( empty( $mapped->url ) ) {
$mapped->url = $data->url ?? null;
}
// Title.
$mapped->title = $data->title ?? null;
// Vendor Name.
$mapped->vendor_name = $data->vendor_name ?? null;
if ( empty( $mapped->vendor_name ) ) {
$mapped->vendor_name = $data->vendorName ?? null; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
// Vendor URL.
$mapped->vendor_url = $data->vendor_url ?? null;
if ( empty( $mapped->vendor_url ) ) {
$mapped->vendor_url = $data->vendorUrl ?? null; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
// Description.
$mapped->description = $data->excerpt ?? null;
if ( empty( $mapped->description ) ) {
$mapped->description = $data->description ?? null;
}
$has_currency = ! empty( $data->currency ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
// Is Free.
if ( $has_currency ) {
$mapped->is_free = 0 === (int) $data->price;
} else {
$mapped->is_free = '&#36;0.00' === $data->price;
}
// Price.
if ( $has_currency ) {
$mapped->price = wc_price( $data->price, array( 'currency' => $data->currency ) );
} else {
$mapped->price = $data->price;
}
// Rating.
$mapped->rating = $data->rating ?? null;
if ( null === $mapped->rating ) {
$mapped->rating = $data->averageRating ?? null; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
// Reviews Count.
$mapped->reviews_count = $data->reviews_count ?? null;
if ( null === $mapped->reviews_count ) {
$mapped->reviews_count = $data->reviewsCount ?? null; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
return $mapped;
}
/**
* Render a product card
*
* There's difference in data structure (e.g. field names) between endpoints such as search and
* featured. Inner mapping helps to use universal field names for further work.
*
* @param mixed $data Product data.
* @param string $block_type Block type that's different from the default product card, e.g. a banner.
*
* @return void
*/
public static function render_product_card( $data, $block_type = null ) {
$mapped = self::map_product_card_data( $data );
$product_url = self::add_in_app_purchase_url_params( $mapped->url );
$class_names = array( 'product' );
// Specify a class name according to $block_type (if it's specified).
if ( null !== $block_type ) {
$class_names[] = 'addons-product-' . $block_type;
}
$product_details_classes = 'product-details';
if ( 'banner' === $block_type ) {
$product_details_classes .= ' addon-product-banner-details';
}
?>
<li class="<?php echo esc_attr( implode( ' ', $class_names ) ); ?>">
<div class="<?php echo esc_attr( $product_details_classes ); ?>">
<div class="product-text-container">
<a href="<?php echo esc_url( $product_url ); ?>">
<h2><?php echo esc_html( $mapped->title ); ?></h2>
</a>
<?php if ( ! empty( $mapped->vendor_name ) && ! empty( $mapped->vendor_url ) ) : ?>
<div class="product-developed-by">
<?php
printf(
/* translators: %s vendor link */
esc_html__( 'Developed by %s', 'woocommerce' ),
sprintf(
'<a class="product-vendor-link" href="%1$s" target="_blank">%2$s</a>',
esc_url_raw( $mapped->vendor_url ),
esc_html( $mapped->vendor_name )
)
);
?>
</div>
<?php endif; ?>
<p><?php echo wp_kses_post( $mapped->description ); ?></p>
</div>
<?php if ( ! empty( $mapped->icon ) ) : ?>
<span class="product-img-wrap">
<?php /* Show an icon if it exists */ ?>
<img src="<?php echo esc_url( $mapped->icon ); ?>" />
</span>
<?php endif; ?>
</div>
<div class="product-footer">
<div class="product-price-and-reviews-container">
<div class="product-price-block">
<?php if ( $mapped->is_free ) : ?>
<span class="price"><?php esc_html_e( 'Free', 'woocommerce' ); ?></span>
<?php else : ?>
<span class="price">
<?php
echo wp_kses(
$mapped->price,
array(
'span' => array(
'class' => array(),
),
'bdi' => array(),
)
);
?>
</span>
<span class="price-suffix"><?php esc_html_e( 'per year', 'woocommerce' ); ?></span>
<?php endif; ?>
</div>
<?php if ( ! empty( $mapped->reviews_count ) && ! empty( $mapped->rating ) ) : ?>
<?php /* Show rating and the number of reviews */ ?>
<div class="product-reviews-block">
<?php for ( $index = 1; $index <= 5; ++$index ) : ?>
<?php $rating_star_class = 'product-rating-star product-rating-star__' . self::get_star_class( $mapped->rating, $index ); ?>
<div class="<?php echo esc_attr( $rating_star_class ); ?>"></div>
<?php endfor; ?>
<span class="product-reviews-count">(<?php echo (int) $mapped->reviews_count; ?>)</span>
</div>
<?php endif; ?>
</div>
<a class="button" href="<?php echo esc_url( $product_url ); ?>">
<?php esc_html_e( 'View details', 'woocommerce' ); ?>
</a>
</div>
</li>
<?php
}
}

View File

@ -64,7 +64,7 @@ $current_section_name = __( 'Browse Categories', 'woocommerce' );
<div class="wrap">
<div class="marketplace-content-wrapper">
<?php if ( count( $addons ) == 0 ) : ?>
<?php if ( ! empty( $search ) && 0 === count( $addons ) ) : ?>
<h1 class="search-form-title">
<?php esc_html_e( 'Sorry, could not find anything. Try searching again using a different term.', 'woocommerce' ); ?></p>
</h1>
@ -78,9 +78,7 @@ $current_section_name = __( 'Browse Categories', 'woocommerce' );
<?php if ( '_featured' === $current_section ) : ?>
<div class="addons-featured">
<?php
$featured = WC_Admin_Addons::get_featured();
?>
<?php WC_Admin_Addons::render_featured(); ?>
</div>
<?php endif; ?>
<?php if ( '_featured' !== $current_section && $addons ) : ?>
@ -115,81 +113,7 @@ $current_section_name = __( 'Browse Categories', 'woocommerce' );
}
}
?>
<li class="product">
<div class="product-details">
<?php if ( ! empty( $addon->icon ) ) : ?>
<span class="product-img-wrap">
<?php /* Show an icon if it exists */ ?>
<img src="<?php echo esc_url( $addon->icon ); ?>" />
</span>
<?php endif; ?>
<a href="<?php echo esc_url( WC_Admin_Addons::add_in_app_purchase_url_params( $addon->link ) ); ?>">
<h2><?php echo esc_html( $addon->title ); ?></h2>
</a>
<?php if ( ! empty( $addon->vendor_name ) && ! empty( $addon->vendor_url ) ) : ?>
<div class="product-developed-by">
<?php
$parsed_vendor_url = parse_url( $addon->vendor_url );
if ( null == $parsed_vendor_url['path'] ) {
$addon->vendor_url .= '/';
}
$separator = ( null == $parsed_vendor_url['query'] ) ? '?' : '&';
$query = http_build_query(
array(
'utm_source' => 'extensionsscreen',
'utm_medium' => 'product',
'utm_campaign' => 'wcaddons',
'utm_content' => 'devpartner',
)
);
$addon->vendor_url .= $separator . $query;
printf(
/* translators: %s vendor link */
esc_html__( 'Developed by %s', 'woocommerce' ),
sprintf(
'<a class="product-vendor-link" href="%1$s" target="_blank">%2$s</a>',
esc_url_raw( $addon->vendor_url ),
wp_kses_post( $addon->vendor_name )
)
);
?>
</div>
<?php endif; ?>
<p><?php echo wp_kses_post( $addon->excerpt ); ?></p>
</div>
<div class="product-footer">
<div class="product-price-and-reviews-container">
<div class="product-price-block">
<?php if ( '&#36;0.00' === $addon->price ) : ?>
<span class="price"><?php esc_html_e( 'Free', 'woocommerce' ); ?></span>
<?php else : ?>
<?php
$price_suffix = __( 'per year', 'woocommerce' );
if ( ! empty( $addon->price_suffix ) ) {
$price_suffix = $addon->price_suffix;
}
?>
<span class="price"><?php echo wp_kses_post( $addon->price ); ?></span>
<span class="price-suffix"><?php echo esc_html( $price_suffix ); ?></span>
<?php endif; ?>
</div>
<?php if ( ! empty( $addon->reviews_count ) && ! empty( $addon->rating ) ) : ?>
<?php /* Show rating and the number of reviews */ ?>
<div class="product-reviews-block">
<?php for ( $index = 1; $index <= 5; ++$index ) : ?>
<?php $rating_star_class = 'product-rating-star product-rating-star__' . WC_Admin_Addons::get_star_class( $addon->rating, $index ); ?>
<div class="<?php echo esc_attr( $rating_star_class ); ?>"></div>
<?php endfor; ?>
<span class="product-reviews-count">(<?php echo wp_kses_post( $addon->reviews_count ); ?>)</span>
</div>
<?php endif; ?>
</div>
<a class="button" href="<?php echo esc_url( WC_Admin_Addons::add_in_app_purchase_url_params( $addon->link ) ); ?>">
<?php esc_html_e( 'View details', 'woocommerce' ); ?>
</a>
</div>
</li>
<?php WC_Admin_Addons::render_product_card( $addon ); ?>
<?php endforeach; ?>
</ul>
<?php endif; ?>