diff --git a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/block.js b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/block.js
index 2d0be6011d5..5d9d67dc614 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/block.js
+++ b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/block.js
@@ -29,7 +29,7 @@ import {
import classnames from 'classnames';
import { Component, Fragment } from '@wordpress/element';
import { compose } from '@wordpress/compose';
-import { debounce, isObject } from 'lodash';
+import { debounce, isObject, isEmpty } from 'lodash';
import PropTypes from 'prop-types';
/**
@@ -193,7 +193,7 @@ class FeaturedProduct extends Component {
className="wc-block-featured-product"
>
{ __(
- 'Visually highlight a product and encourage prompt action',
+ 'Visually highlight a product or variation and encourage prompt action',
'woo-gutenberg-products-block'
) }
@@ -305,11 +305,19 @@ class FeaturedProduct extends Component {
__html: product.name,
} }
/>
+ { ! isEmpty( product.variation ) && (
+
+ ) }
{ showDesc && (
) }
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.js b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.js
index 818616f6ad0..07da5413e2f 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.js
+++ b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.js
@@ -24,7 +24,7 @@ registerBlockType( 'woocommerce/featured-product', {
category: 'woocommerce',
keywords: [ __( 'WooCommerce', 'woo-gutenberg-products-block' ) ],
description: __(
- 'Visually highlight a product and encourage prompt action.',
+ 'Visually highlight a product or variation and encourage prompt action.',
'woo-gutenberg-products-block'
),
supports: {
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/style.scss b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/style.scss
index 8c383554c25..8a5aee85d73 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/style.scss
+++ b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/style.scss
@@ -25,6 +25,7 @@
justify-content: flex-start;
.wc-block-featured-product__title,
+ .wc-block-featured-product__variation,
.wc-block-featured-product__description,
.wc-block-featured-product__price {
margin-left: 0;
@@ -36,6 +37,7 @@
justify-content: flex-end;
.wc-block-featured-product__title,
+ .wc-block-featured-product__variation,
.wc-block-featured-product__description,
.wc-block-featured-product__price {
margin-right: 0;
@@ -44,6 +46,7 @@
}
.wc-block-featured-product__title,
+ .wc-block-featured-product__variation,
.wc-block-featured-product__description,
.wc-block-featured-product__price {
color: $white;
@@ -60,25 +63,34 @@
}
.wc-block-featured-product__title,
+ .wc-block-featured-product__variation,
.wc-block-featured-product__description,
.wc-block-featured-product__price,
.wc-block-featured-product__link {
width: 100%;
- padding: 0 48px 16px 48px;
+ padding: 16px 48px 0 48px;
z-index: 1;
}
- .wc-block-featured-product__title {
+ .wc-block-featured-product__title,
+ .wc-block-featured-product__variation {
margin-top: 0;
+ border: 0;
&:before {
display: none;
}
}
+ .wc-block-featured-product__variation {
+ font-style: italic;
+ padding-top: 0;
+ }
+
.wc-block-featured-product__description {
p {
margin: 0;
+ line-height: 1.5em;
}
}
diff --git a/plugins/woocommerce-blocks/assets/js/components/product-attribute-control/style.scss b/plugins/woocommerce-blocks/assets/js/components/product-attribute-control/style.scss
index fe2e31e4ad3..200a47374f9 100644
--- a/plugins/woocommerce-blocks/assets/js/components/product-attribute-control/style.scss
+++ b/plugins/woocommerce-blocks/assets/js/components/product-attribute-control/style.scss
@@ -42,14 +42,14 @@
content: '';
height: $gap-large;
width: $gap-large;
- background-image: url('data:image/svg+xml;utf8,
');
+ background-image: url('data:image/svg+xml;utf8,
');
background-repeat: no-repeat;
background-position: center right;
background-size: contain;
}
&.depth-0[aria-expanded="true"]::after {
- background-image: url('data:image/svg+xml;utf8,
');
+ background-image: url('data:image/svg+xml;utf8,
');
}
&[disabled].depth-0::after {
diff --git a/plugins/woocommerce-blocks/assets/js/components/product-control/index.js b/plugins/woocommerce-blocks/assets/js/components/product-control/index.js
index 9990f358038..c98087608a4 100644
--- a/plugins/woocommerce-blocks/assets/js/components/product-control/index.js
+++ b/plugins/woocommerce-blocks/assets/js/components/product-control/index.js
@@ -1,54 +1,245 @@
/**
* External dependencies
*/
-import { __ } from '@wordpress/i18n';
+import { __, _n, sprintf } from '@wordpress/i18n';
import { Component, Fragment } from '@wordpress/element';
-import { debounce, find } from 'lodash';
+import { addQueryArgs } from '@wordpress/url';
+import apiFetch from '@wordpress/api-fetch';
+import { debounce, find, escapeRegExp, isEmpty } from 'lodash';
import PropTypes from 'prop-types';
-import { SearchListControl } from '@woocommerce/components';
+import {
+ SearchListControl,
+ SearchListItem,
+} from '@woocommerce/components';
+import { Spinner, MenuItem } from '@wordpress/components';
+import classnames from 'classnames';
/**
* Internal dependencies
*/
import { isLargeCatalog, getProducts } from '../utils';
+import {
+ IconRadioSelected,
+ IconRadioUnselected,
+} from '../icons';
+import './style.scss';
+
+function getHighlightedName( name, search ) {
+ if ( ! search ) {
+ return name;
+ }
+ const re = new RegExp( escapeRegExp( search ), 'ig' );
+ return name.replace( re, '
$&' );
+}
+
+const getInteractionIcon = ( isSelected = false ) => {
+ return isSelected ?
:
;
+};
class ProductControl extends Component {
constructor() {
super( ...arguments );
this.state = {
- list: [],
+ products: [],
+ product: 0,
+ variationsList: {},
+ variationsLoading: false,
loading: true,
};
this.debouncedOnSearch = debounce( this.onSearch.bind( this ), 400 );
+ this.debouncedGetVariations = debounce( this.getVariations.bind( this ), 200 );
+ this.renderItem = this.renderItem.bind( this );
+ this.onProductSelect = this.onProductSelect.bind( this );
}
componentDidMount() {
const { selected } = this.props;
getProducts( { selected } )
- .then( ( list ) => {
- this.setState( { list, loading: false } );
+ .then( ( products ) => {
+ products = products.map( ( product ) => {
+ const count = product.variations ? product.variations.length : 0;
+ return {
+ ...product,
+ parent: 0,
+ count: count,
+ };
+ } );
+ this.setState( { products, loading: false } );
} )
.catch( () => {
- this.setState( { list: [], loading: false } );
+ this.setState( { products: [], loading: false } );
+ } );
+ }
+
+ componentDidUpdate( prevProps, prevState ) {
+ if ( prevState.product !== this.state.product ) {
+ this.debouncedGetVariations();
+ }
+ }
+
+ getVariations() {
+ const { product, variationsList } = this.state;
+
+ if ( ! product ) {
+ this.setState( {
+ variationsList: {},
+ variationsLoading: false,
+ } );
+ return;
+ }
+
+ const productDetails = this.state.products.find( ( findProduct ) => findProduct.id === product );
+
+ if ( ! productDetails.variations || productDetails.variations.length === 0 ) {
+ return;
+ }
+
+ if ( ! variationsList[ product ] ) {
+ this.setState( { variationsLoading: true } );
+ }
+
+ apiFetch( {
+ path: addQueryArgs( `/wc/blocks/products/${ product }/variations`, {
+ per_page: -1,
+ } ),
+ } )
+ .then( ( variations ) => {
+ variations = variations.map( ( variation ) => ( { ...variation, parent: product } ) );
+ this.setState( ( prevState ) => ( {
+ variationsList: { ...prevState.variationsList, [ product ]: variations },
+ variationsLoading: false,
+ } ) );
+ } )
+ .catch( () => {
+ this.setState( { termsLoading: false } );
} );
}
onSearch( search ) {
const { selected } = this.props;
getProducts( { selected, search } )
- .then( ( list ) => {
- this.setState( { list, loading: false } );
+ .then( ( products ) => {
+ this.setState( { products, loading: false } );
} )
.catch( () => {
- this.setState( { list: [], loading: false } );
+ this.setState( { products: [], loading: false } );
} );
}
+ onProductSelect( item, isSelected ) {
+ return () => {
+ this.setState( {
+ product: isSelected ? 0 : item.id,
+ } );
+ };
+ }
+
+ renderItem( args ) {
+ const { item, search, depth = 0, isSelected, onSelect } = args;
+ const { product, variationsLoading } = this.state;
+ const classes = classnames(
+ 'woocommerce-search-product__item',
+ 'woocommerce-search-list__item',
+ `depth-${ depth }`,
+ {
+ 'is-searching': search.length > 0,
+ 'is-skip-level': depth === 0 && item.parent !== 0,
+ 'is-variable': item.count > 0,
+ }
+ );
+
+ const itemArgs = Object.assign( {}, args );
+ delete itemArgs.isSingle;
+
+ const a11yProps = {
+ role: 'menuitemradio',
+ };
+
+ if ( item.breadcrumbs.length ) {
+ a11yProps[ 'aria-label' ] = `${ item.breadcrumbs[ 0 ] }: ${ item.name }`;
+ }
+
+ if ( item.count ) {
+ a11yProps[ 'aria-expanded' ] = item.id === product;
+ }
+
+ // Top level items custom rendering based on SearchListItem.
+ if ( ! item.breadcrumbs.length ) {
+ return [
+
,
+ product === item.id && item.count > 0 && variationsLoading && (
+
+
+
+ ),
+ ];
+ }
+
+ if ( ! isEmpty( item.variation ) ) {
+ item.name = item.variation;
+ }
+
+ return (
+
+ );
+ }
+
render() {
- const { list, loading } = this.state;
+ const { products, loading, product, variationsList } = this.state;
const { onChange, selected } = this.props;
+ const currentVariations = variationsList[ product ] || [];
+ const currentList = [ ...products, ...currentVariations ];
const messages = {
list: __( 'Products', 'woo-gutenberg-products-block' ),
noItems: __(
@@ -64,19 +255,21 @@ class ProductControl extends Component {
'woo-gutenberg-products-block'
),
};
+ const selectedListItems = selected ? [ find( currentList, { id: selected } ) ] : [];
- // Note: selected prop still needs to be array for SearchListControl.
return (
);
diff --git a/plugins/woocommerce-blocks/assets/js/components/product-control/style.scss b/plugins/woocommerce-blocks/assets/js/components/product-control/style.scss
new file mode 100644
index 00000000000..eb88c2e8271
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/components/product-control/style.scss
@@ -0,0 +1,43 @@
+.woocommerce-search-product__item {
+ .woocommerce-search-list__item-name {
+ .description {
+ display: block;
+ }
+ }
+
+ &.is-searching,
+ &.is-skip-level {
+ .woocommerce-search-list__item-prefix::after {
+ content: ":";
+ }
+ }
+
+ &.is-not-active {
+ @include hover-state {
+ background: $white;
+ }
+ }
+
+ &.is-loading {
+ justify-content: center;
+
+ .components-spinner {
+ margin-bottom: $gap-small;
+ }
+ }
+
+ &.depth-0.is-variable::after {
+ margin-left: $gap-smaller;
+ content: '';
+ height: $gap-large;
+ width: $gap-large;
+ background-image: url('data:image/svg+xml;utf8,
');
+ background-repeat: no-repeat;
+ background-position: center right;
+ background-size: contain;
+ }
+
+ &.depth-0.is-variable[aria-expanded="true"]::after {
+ background-image: url('data:image/svg+xml;utf8,
');
+ }
+}
diff --git a/plugins/woocommerce-blocks/composer.lock b/plugins/woocommerce-blocks/composer.lock
index 8296e543db2..3339347fb0f 100644
--- a/plugins/woocommerce-blocks/composer.lock
+++ b/plugins/woocommerce-blocks/composer.lock
@@ -438,16 +438,16 @@
},
{
"name": "phpcompatibility/php-compatibility",
- "version": "9.1.1",
+ "version": "9.2.0",
"source": {
"type": "git",
"url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
- "reference": "2b63c5d284ab8857f7b1d5c240ddb507a6b2293c"
+ "reference": "3db1bf1e28123fd574a4ae2e9a84072826d51b5e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/2b63c5d284ab8857f7b1d5c240ddb507a6b2293c",
- "reference": "2b63c5d284ab8857f7b1d5c240ddb507a6b2293c",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/3db1bf1e28123fd574a4ae2e9a84072826d51b5e",
+ "reference": "3db1bf1e28123fd574a4ae2e9a84072826d51b5e",
"shasum": ""
},
"require": {
@@ -461,7 +461,7 @@
"phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0"
},
"suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
"roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
},
"type": "phpcodesniffer-standard",
@@ -492,7 +492,7 @@
"phpcs",
"standards"
],
- "time": "2018-12-30T23:16:27+00:00"
+ "time": "2019-06-27T19:58:56+00:00"
},
{
"name": "phpcompatibility/phpcompatibility-paragonie",
diff --git a/plugins/woocommerce-blocks/src/BlockTypes/FeaturedProduct.php b/plugins/woocommerce-blocks/src/BlockTypes/FeaturedProduct.php
index 5b3de0a7f98..26dd0cc61d4 100644
--- a/plugins/woocommerce-blocks/src/BlockTypes/FeaturedProduct.php
+++ b/plugins/woocommerce-blocks/src/BlockTypes/FeaturedProduct.php
@@ -60,9 +60,16 @@ class FeaturedProduct extends AbstractDynamicBlock {
wp_kses_post( $product->get_title() )
);
+ if ( $product->is_type( 'variation' ) ) {
+ $title .= sprintf(
+ '
%s
',
+ wc_get_formatted_variation( $product, true, true, false )
+ );
+ }
+
$desc_str = sprintf(
'
%s
',
- apply_filters( 'woocommerce_short_description', $product->get_short_description() )
+ apply_filters( 'woocommerce_short_description', $product->get_short_description() ? $product->get_short_description() : wc_trim_string( $product->get_description(), 400 ) )
);
$price_str = sprintf(
diff --git a/plugins/woocommerce-blocks/src/RestApi.php b/plugins/woocommerce-blocks/src/RestApi.php
index 32174da30e5..ac658ac56a7 100644
--- a/plugins/woocommerce-blocks/src/RestApi.php
+++ b/plugins/woocommerce-blocks/src/RestApi.php
@@ -44,6 +44,7 @@ class RestApi {
'product-attribute-terms' => __NAMESPACE__ . '\RestApi\Controllers\ProductAttributeTerms',
'product-categories' => __NAMESPACE__ . '\RestApi\Controllers\ProductCategories',
'products' => __NAMESPACE__ . '\RestApi\Controllers\Products',
+ 'variations' => __NAMESPACE__ . '\RestApi\Controllers\Variations',
];
}
}
diff --git a/plugins/woocommerce-blocks/src/RestApi/Controllers/Products.php b/plugins/woocommerce-blocks/src/RestApi/Controllers/Products.php
index 562746389d7..645a35f342b 100644
--- a/plugins/woocommerce-blocks/src/RestApi/Controllers/Products.php
+++ b/plugins/woocommerce-blocks/src/RestApi/Controllers/Products.php
@@ -167,27 +167,23 @@ class Products extends WC_REST_Products_Controller {
/**
* Get product data.
*
- * @param WC_Product $product Product instance.
- * @param string $context Request context.
- * Options: 'view' and 'edit'.
+ * @param \WC_Product|\WC_Product_Variation $product Product instance.
+ * @param string $context Request context. Options: 'view' and 'edit'.
* @return array
*/
protected function get_product_data( $product, $context = 'view' ) {
- $raw_data = parent::get_product_data( $product, $context );
- $data = array();
-
- $data['id'] = $raw_data['id'];
- $data['name'] = $raw_data['name'];
- $data['permalink'] = $raw_data['permalink'];
- $data['sku'] = $raw_data['sku'];
- $data['description'] = $raw_data['description'];
- $data['short_description'] = $raw_data['short_description'];
- $data['price'] = $raw_data['price'];
- $data['price_html'] = $raw_data['price_html'];
- $data['images'] = $raw_data['images'];
- $data['average_rating'] = $raw_data['average_rating'];
-
- return $data;
+ return array(
+ 'id' => $product->get_id(),
+ 'name' => $product->get_title(),
+ 'variation' => $product->is_type( 'variation' ) ? wc_get_formatted_variation( $product, true, true, false ) : '',
+ 'permalink' => $product->get_permalink(),
+ 'sku' => $product->get_sku(),
+ 'description' => apply_filters( 'woocommerce_short_description', $product->get_short_description() ? $product->get_short_description() : wc_trim_string( $product->get_description(), 400 ) ),
+ 'price' => $product->get_price(),
+ 'price_html' => $product->get_price_html(),
+ 'images' => $this->get_images( $product ),
+ 'average_rating' => $product->get_average_rating(),
+ );
}
/**
@@ -201,7 +197,7 @@ class Products extends WC_REST_Products_Controller {
$attachment_ids = array();
// Add featured image.
- if ( has_post_thumbnail( $product->get_id() ) ) {
+ if ( $product->get_image_id() ) {
$attachment_ids[] = $product->get_image_id();
}
@@ -287,58 +283,58 @@ class Products extends WC_REST_Products_Controller {
'title' => 'product_block_product',
'type' => 'object',
'properties' => array(
- 'id' => array(
+ 'id' => array(
'description' => __( 'Unique identifier for the resource.', 'woo-gutenberg-products-block' ),
'type' => 'integer',
'context' => array( 'view', 'edit', 'embed' ),
'readonly' => true,
),
- 'name' => array(
+ 'name' => array(
'description' => __( 'Product name.', 'woo-gutenberg-products-block' ),
'type' => 'string',
'context' => array( 'view', 'edit', 'embed' ),
),
- 'permalink' => array(
+ 'variation' => array(
+ 'description' => __( 'Product variation attributes, if applicable.', 'woo-gutenberg-products-block' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ 'permalink' => array(
'description' => __( 'Product URL.', 'woo-gutenberg-products-block' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view', 'edit', 'embed' ),
'readonly' => true,
),
- 'description' => array(
- 'description' => __( 'Product description.', 'woo-gutenberg-products-block' ),
+ 'description' => array(
+ 'description' => __( 'Short description or excerpt from description.', 'woo-gutenberg-products-block' ),
'type' => 'string',
'context' => array( 'view', 'edit', 'embed' ),
),
- 'short_description' => array(
- 'description' => __( 'Product short description.', 'woo-gutenberg-products-block' ),
- 'type' => 'string',
- 'context' => array( 'view', 'edit', 'embed' ),
- ),
- 'sku' => array(
+ 'sku' => array(
'description' => __( 'Unique identifier.', 'woo-gutenberg-products-block' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
- 'price' => array(
+ 'price' => array(
'description' => __( 'Current product price.', 'woo-gutenberg-products-block' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'price_html' => array(
+ 'price_html' => array(
'description' => __( 'Price formatted in HTML.', 'woo-gutenberg-products-block' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'average_rating' => array(
+ 'average_rating' => array(
'description' => __( 'Reviews average rating.', 'woo-gutenberg-products-block' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
- 'images' => array(
+ 'images' => array(
'description' => __( 'List of images.', 'woo-gutenberg-products-block' ),
'type' => 'object',
'context' => array( 'view', 'edit', 'embed' ),
diff --git a/plugins/woocommerce-blocks/src/RestApi/Controllers/Variations.php b/plugins/woocommerce-blocks/src/RestApi/Controllers/Variations.php
new file mode 100644
index 00000000000..1a836d8f6c4
--- /dev/null
+++ b/plugins/woocommerce-blocks/src/RestApi/Controllers/Variations.php
@@ -0,0 +1,121 @@
+namespace,
+ '/' . $this->rest_base,
+ array(
+ 'args' => array(
+ 'product_id' => array(
+ 'description' => __( 'Unique identifier for the variable product.', 'woo-gutenberg-products-block' ),
+ 'type' => 'integer',
+ ),
+ ),
+ array(
+ 'methods' => 'GET',
+ 'callback' => array( $this, 'get_items' ),
+ 'permission_callback' => array( $this, 'get_items_permissions_check' ),
+ 'args' => $this->get_collection_params(),
+ ),
+ 'schema' => array( $this, 'get_public_item_schema' ),
+ )
+ );
+ }
+
+ /**
+ * Check if a given request has access to read items.
+ *
+ * @param \WP_REST_Request $request Full details about the request.
+ * @return \WP_Error|boolean
+ */
+ public function get_items_permissions_check( $request ) {
+ if ( ! \current_user_can( 'edit_posts' ) ) {
+ return new \WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woo-gutenberg-products-block' ), array( 'status' => \rest_authorization_required_code() ) );
+ }
+ return true;
+ }
+
+ /**
+ * Prepare a single variation output for response.
+ *
+ * @param \WC_Data $object Object data.
+ * @param \WP_REST_Request $request Request object.
+ * @return \WP_REST_Response
+ */
+ public function prepare_object_for_response( $object, $request ) {
+ $data = array(
+ 'id' => $object->get_id(),
+ 'name' => $object->get_title(),
+ 'variation' => wc_get_formatted_variation( $object, true, true, false ),
+ );
+
+ $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
+ $data = $this->add_additional_fields_to_object( $data, $request );
+ $data = $this->filter_response_by_context( $data, $context );
+ $response = rest_ensure_response( $data );
+ $response->add_links( $this->prepare_links( $object, $request ) );
+
+ return $response;
+ }
+
+ /**
+ * Get the Product's schema, conforming to JSON Schema.
+ *
+ * @return array
+ */
+ public function get_item_schema() {
+ $schema = array(
+ '$schema' => 'http://json-schema.org/draft-04/schema#',
+ 'title' => 'product_block_variation',
+ 'type' => 'object',
+ 'properties' => array(
+ 'id' => array(
+ 'description' => __( 'Unique identifier for the resource.', 'woo-gutenberg-products-block' ),
+ 'type' => 'integer',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ 'readonly' => true,
+ ),
+ 'name' => array(
+ 'description' => __( 'Product name.', 'woo-gutenberg-products-block' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ 'variation' => array(
+ 'description' => __( 'Product variation attributes, if applicable.', 'woo-gutenberg-products-block' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit', 'embed' ),
+ ),
+ ),
+ );
+ return $this->add_additional_fields_schema( $schema );
+ }
+}