Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.

Commit 5539dcc

Browse files
authored
Consistent HTML entities in Store API (2.5.x changes) (#1608)
* apply changes from PR #1597 to release/2.5 branch: - changes can't be cherry picked automatically due to significant other API changes on master * fix phpcs errors introduced in last commit
1 parent c08fa54 commit 5539dcc

File tree

10 files changed

+47
-20
lines changed

10 files changed

+47
-20
lines changed

assets/js/atomic/components/product/button/index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { find } from 'lodash';
1616
import { useCollection } from '@woocommerce/base-hooks';
1717
import { COLLECTIONS_STORE_KEY as storeKey } from '@woocommerce/block-data';
1818
import { useProductLayoutContext } from '@woocommerce/base-context/product-layout-context';
19+
import { decodeEntities } from '@wordpress/html-entities';
1920

2021
/**
2122
* A custom hook for exposing cart related data for a given product id and an
@@ -113,7 +114,7 @@ const ProductButton = ( { product, className } ) => {
113114
cartQuantity
114115
);
115116
}
116-
return productCartDetails.text;
117+
return decodeEntities( productCartDetails.text );
117118
};
118119

119120
// This is a hack to trigger cart updates till we migrate to block based card
@@ -166,7 +167,9 @@ const ProductButton = ( { product, className } ) => {
166167
{ allowAddToCart ? (
167168
<button
168169
onClick={ addToCart }
169-
aria-label={ productCartDetails.description }
170+
aria-label={ decodeEntities(
171+
productCartDetails.description
172+
) }
170173
className={ buttonClasses }
171174
disabled={ addingToCart }
172175
>
@@ -175,7 +178,9 @@ const ProductButton = ( { product, className } ) => {
175178
) : (
176179
<a
177180
href={ permalink }
178-
aria-label={ productCartDetails.description }
181+
aria-label={ decodeEntities(
182+
productCartDetails.description
183+
) }
179184
className={ buttonClasses }
180185
rel="nofollow"
181186
>

assets/js/atomic/components/product/title/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import PropTypes from 'prop-types';
55
import classnames from 'classnames';
66
import { useProductLayoutContext } from '@woocommerce/base-context/product-layout-context';
7+
import { decodeEntities } from '@wordpress/html-entities';
78

89
const ProductTitle = ( {
910
className,
@@ -16,7 +17,7 @@ const ProductTitle = ( {
1617
return null;
1718
}
1819

19-
const productName = product.name;
20+
const productName = decodeEntities( product.name );
2021
const TagName = `h${ headingLevel }`;
2122

2223
return (

assets/js/blocks/active-filters/active-attribute-filters.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* External dependencies
33
*/
44
import { useCollection, useQueryStateByKey } from '@woocommerce/base-hooks';
5+
import { decodeEntities } from '@wordpress/html-entities';
56

67
/**
78
* Internal dependencies
@@ -39,7 +40,7 @@ const ActiveAttributeFilters = ( { attributeObject = {}, slugs = [] } ) => {
3940
termObject &&
4041
renderRemovableListItem(
4142
attributeLabel,
42-
termObject.name || slug,
43+
decodeEntities( termObject.name || slug ),
4344
() => {
4445
removeAttributeFilterBySlug(
4546
productAttributes,

assets/js/blocks/attribute-filter/block.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
useMemo,
1616
} from '@wordpress/element';
1717
import CheckboxList from '@woocommerce/base-components/checkbox-list';
18+
import { decodeEntities } from '@wordpress/html-entities';
1819

1920
/**
2021
* Internal dependencies
@@ -37,7 +38,7 @@ const AttributeFilterBlock = ( {
3738
( name, count ) => {
3839
return (
3940
<Fragment>
40-
{ name }
41+
{ decodeEntities( name ) }
4142
{ blockAttributes.showCounts && count !== null && (
4243
<span className="wc-block-attribute-filter-list-count">
4344
{ count }

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"@wordpress/jest-preset-default": "4.3.0",
6060
"@wordpress/rich-text": "3.7.0",
6161
"@wordpress/scripts": "3.4.0",
62+
"@wordpress/html-entities": "2.5.0",
6263
"autoprefixer": "9.7.2",
6364
"babel-core": "7.0.0-bridge.0",
6465
"babel-eslint": "10.0.3",

src/RestApi/StoreApi/Schemas/AbstractSchema.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,20 @@ function( $property ) {
6363
$properties
6464
);
6565
}
66+
67+
/**
68+
* Prepares HTML based content, such as post titles and content, for the API response.
69+
*
70+
* The wptexturize, convert_chars, and trim functions are also used in the `the_title` filter.
71+
* The function wp_kses_post removes disallowed HTML tags.
72+
*
73+
* @param string|array $response Data to format.
74+
* @return string|array Formatted data.
75+
*/
76+
protected function prepare_html_response( $response ) {
77+
if ( is_array( $response ) ) {
78+
return array_map( [ $this, 'prepare_html_response' ], $response );
79+
}
80+
return is_scalar( $response ) ? wp_kses_post( trim( convert_chars( wptexturize( $response ) ) ) ) : $response;
81+
}
6682
}

src/RestApi/StoreApi/Schemas/CartItemSchema.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ public function get_item_response( $cart_item ) {
171171
'key' => $cart_item['key'],
172172
'id' => $product->get_id(),
173173
'quantity' => wc_stock_amount( $cart_item['quantity'] ),
174-
'name' => $product->get_title(),
175-
'sku' => $product->get_sku(),
174+
'name' => $this->prepare_html_response( $product->get_title() ),
175+
'sku' => $this->prepare_html_response( $product->get_sku() ),
176176
'permalink' => $product->get_permalink(),
177177
'images' => ( new ProductImages() )->images_to_array( $product ),
178178
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
@@ -207,7 +207,7 @@ protected function format_variation_data( $variation_data, $product ) {
207207
$label = wc_attribute_label( str_replace( 'attribute_', '', $name ), $product );
208208
}
209209

210-
$return[ $label ] = $value;
210+
$return[ $this->prepare_html_response( $label ) ] = $this->prepare_html_response( $value );
211211
}
212212

213213
return $return;

src/RestApi/StoreApi/Schemas/ProductAttributeSchema.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ protected function get_properties() {
7777
public function get_item_response( $attribute ) {
7878
return [
7979
'id' => (int) $attribute->id,
80-
'name' => $attribute->name,
80+
'name' => $this->prepare_html_response( $attribute->name ),
8181
'slug' => $attribute->slug,
8282
'type' => $attribute->type,
8383
'order' => $attribute->order_by,

src/RestApi/StoreApi/Schemas/ProductSchema.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,11 @@ protected function get_properties() {
255255
public function get_item_response( $product ) {
256256
return [
257257
'id' => $product->get_id(),
258-
'name' => $product->get_title(),
259-
'variation' => $product->is_type( 'variation' ) ? wc_get_formatted_variation( $product, true, true, false ) : '',
258+
'name' => $this->prepare_html_response( $product->get_title() ),
259+
'variation' => $this->prepare_html_response( $product->is_type( 'variation' ) ? wc_get_formatted_variation( $product, true, true, false ) : '' ),
260260
'permalink' => $product->get_permalink(),
261-
'sku' => $product->get_sku(),
262-
'description' => apply_filters( 'woocommerce_short_description', $product->get_short_description() ? $product->get_short_description() : wc_trim_string( $product->get_description(), 400 ) ),
261+
'sku' => $this->prepare_html_response( $product->get_sku() ),
262+
'description' => $this->prepare_html_response( apply_filters( 'woocommerce_short_description', $product->get_short_description() ? $product->get_short_description() : wc_trim_string( $product->get_description(), 400 ) ) ),
263263
'on_sale' => $product->is_on_sale(),
264264
'prices' => $this->get_prices( $product ),
265265
'average_rating' => $product->get_average_rating(),
@@ -268,10 +268,12 @@ public function get_item_response( $product ) {
268268
'has_options' => $product->has_options(),
269269
'is_purchasable' => $product->is_purchasable(),
270270
'is_in_stock' => $product->is_in_stock(),
271-
'add_to_cart' => [
272-
'text' => $product->add_to_cart_text(),
273-
'description' => $product->add_to_cart_description(),
274-
],
271+
'add_to_cart' => $this->prepare_html_response(
272+
[
273+
'text' => $product->add_to_cart_text(),
274+
'description' => $product->add_to_cart_description(),
275+
]
276+
),
275277
];
276278
}
277279

src/RestApi/StoreApi/Schemas/TermSchema.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ protected function get_properties() {
7171
public function get_item_response( $term ) {
7272
return [
7373
'id' => (int) $term->term_id,
74-
'name' => $term->name,
75-
'description' => $term->description,
74+
'name' => $this->prepare_html_response( $term->name ),
75+
'description' => $this->prepare_html_response( $term->description ),
7676
'slug' => $term->slug,
7777
'count' => (int) $term->count,
7878
];

0 commit comments

Comments
 (0)