Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions assets/js/blocks/product-categories/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { InspectorControls } from '@wordpress/block-editor';
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import ServerSideRender from '@wordpress/server-side-render';
import PropTypes from 'prop-types';
import {
Expand Down Expand Up @@ -183,8 +183,12 @@ const ProductCategoriesBlock = ( { attributes, setAttributes, name } ) => {
);
};

const blockProps = useBlockProps( {
className: 'wc-block-product-categories',
} );

return (
<>
<div { ...blockProps }>
{ getInspectorControls() }
<Disabled>
<ServerSideRender
Expand All @@ -193,7 +197,7 @@ const ProductCategoriesBlock = ( { attributes, setAttributes, name } ) => {
EmptyResponsePlaceholder={ EmptyPlaceholder }
/>
</Disabled>
</>
</div>
);
};

Expand Down
12 changes: 12 additions & 0 deletions assets/js/blocks/product-categories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n';
import { createBlock, registerBlockType } from '@wordpress/blocks';
import { Icon, list } from '@woocommerce/icons';

import { isFeaturePluginBuild } from '@woocommerce/block-settings';
/**
* Internal dependencies
*/
Expand All @@ -13,6 +14,7 @@ import './style.scss';
import Block from './block.js';

registerBlockType( 'woocommerce/product-categories', {
apiVersion: 2,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With apiVersion: 2, you will need to pass useBlockProps() to the edit component. Similarly to how it's done here:

https://github.com/woocommerce/woocommerce-gutenberg-products-block/blob/trunk/assets/js/blocks/reviews/editor-container-block.js#L58

(I think you will need to replace the fragment <> with a wrapping div)

title: __( 'Product Categories List', 'woo-gutenberg-products-block' ),
icon: {
src: <Icon srcElement={ list } />,
Expand All @@ -27,6 +29,16 @@ registerBlockType( 'woocommerce/product-categories', {
supports: {
align: [ 'wide', 'full' ],
html: false,
...( isFeaturePluginBuild() && {
color: {
background: false,
link: true,
},
typography: {
fontSize: true,
lineHeight: true,
},
} ),
},
example: {
attributes: {
Expand Down
26 changes: 22 additions & 4 deletions src/BlockTypes/ProductCategories.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;

use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;

/**
* ProductCategories class.
*/
class ProductCategories extends AbstractDynamicBlock {


/**
* Block name.
*
Expand Down Expand Up @@ -42,6 +45,10 @@ protected function get_block_type_attributes() {
'hasEmpty' => $this->get_schema_boolean( false ),
'isDropdown' => $this->get_schema_boolean( false ),
'isHierarchical' => $this->get_schema_boolean( true ),
'textColor' => $this->get_schema_string(),
'fontSize' => $this->get_schema_string(),
'lineHeight' => $this->get_schema_string(),
'style' => array( 'type' => 'object' ),
)
);
}
Expand Down Expand Up @@ -77,9 +84,15 @@ protected function render( $attributes, $content ) {
}
}

$classes = $this->get_container_classes( $attributes );
$classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes(
$attributes,
array( 'line_height', 'text_color', 'font_size' )
);

$classes = $this->get_container_classes( $attributes ) . ' ' . $classes_and_styles['classes'];
$styles = $classes_and_styles['styles'];

$output = '<div class="' . esc_attr( $classes ) . '">';
$output = '<div class="wp-block-woocommerce-product-categories ' . esc_attr( $classes ) . '" style="' . esc_attr( $styles ) . '">';
Copy link
Contributor Author

@gigitux gigitux Nov 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a possibility that the style property will be empty. Do you think that is it necessary to exclude style property when the variable $styles is empty?
The same concept for class property and variable $classes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gigitux Empty style or class attribute is fine to me. But if you prefer a cleaner HTML output, go for it. I prefer empty attributes because of the readability. We will need some if condition checks to exclude the empty attributes, which makes the code harder to read IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need some if condition checks to exclude the empty attributes, which makes the code harder to read IMO.

I agree with you! In any case, I preferred to point it out to you

$output .= ! empty( $attributes['isDropdown'] ) ? $this->renderDropdown( $categories, $attributes, $uid ) : $this->renderList( $categories, $attributes, $uid );
$output .= '</div>';

Expand All @@ -93,6 +106,7 @@ protected function render( $attributes, $content ) {
* @return string space-separated list of classes.
*/
protected function get_container_classes( $attributes = array() ) {

$classes = array( 'wc-block-product-categories' );

if ( isset( $attributes['align'] ) ) {
Expand Down Expand Up @@ -301,11 +315,15 @@ protected function renderList( $categories, $attributes, $uid, $depth = 0 ) {
protected function renderListItems( $categories, $attributes, $uid, $depth = 0 ) {
$output = '';

$link_color_class_and_style = StyleAttributesUtils::get_link_color_class_and_style( $attributes );

$link_color_style = isset( $link_color_class_and_style['style'] ) ? $link_color_class_and_style['style'] : '';

foreach ( $categories as $category ) {
$output .= '
<li class="wc-block-product-categories-list-item">
<a href="' . esc_attr( get_term_link( $category->term_id, 'product_cat' ) ) . '">' . $this->get_image_html( $category, $attributes ) . esc_html( $category->name ) . '</a>
' . $this->getCount( $category, $attributes ) . '
<a style="' . esc_attr( $link_color_style ) . '" href="' . esc_attr( get_term_link( $category->term_id, 'product_cat' ) ) . '">' . $this->get_image_html( $category, $attributes ) . esc_html( $category->name ) . '</a>
' . $this->getCount( $category, $attributes ) . '
' . ( ! empty( $category->children ) ? $this->renderList( $category->children, $attributes, $uid, $depth + 1 ) : '' ) . '
</li>
';
Expand Down
210 changes: 210 additions & 0 deletions src/Utils/StyleAttributesUtils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
<?php
namespace Automattic\WooCommerce\Blocks\Utils;

/**
* StyleAttributesUtils class used for getting class and style from attributes.
*/
class StyleAttributesUtils {

/**
* Get class and style for font-size from attributes.
*
* @param array $attributes Block attributes.
*
* @return (array | null)
*/
public static function get_font_size_class_and_style( $attributes ) {

$font_size = $attributes['fontSize'];

$custom_font_size = isset( $attributes['style']['typography']['fontSize'] ) ? $attributes['style']['typography']['fontSize'] : null;

if ( ! isset( $font_size ) && ! isset( $custom_font_size ) ) {
return null;
};

$has_named_font_size = ! empty( $font_size );
$has_custom_font_size = isset( $custom_font_size );

if ( $has_named_font_size ) {
return array(
'class' => sprintf( 'has-font-size has-%s-font-size', $font_size ),
'style' => null,
);
} elseif ( $has_custom_font_size ) {
return array(
'class' => null,
'style' => sprintf( 'font-size: %s;', $custom_font_size ),
);
}
return null;
}

/**
* Get class and style for text-color from attributes.
*
* @param array $attributes Block attributes.
*
* @return (array | null)
*/
public static function get_text_color_class_and_style( $attributes ) {

$text_color = $attributes['textColor'];

$custom_text_color = isset( $attributes['style']['color']['text'] ) ? $attributes['style']['color']['text'] : null;

if ( ! isset( $text_color ) && ! isset( $custom_text_color ) ) {
return null;
};

$has_named_text_color = ! empty( $text_color );
$has_custom_text_color = isset( $custom_text_color );

if ( $has_named_text_color ) {
return array(
'class' => sprintf( 'has-text-color has-%s-color', $text_color ),
'style' => null,
);
} elseif ( $has_custom_text_color ) {
return array(
'class' => null,
'style' => sprintf( 'color: %s;', $custom_text_color ),
);
}
return null;
}

/**
* Get class and style for link-color from attributes.
*
* @param array $attributes Block attributes.
*
* @return (array | null)
*/
public static function get_link_color_class_and_style( $attributes ) {

if ( ! isset( $attributes['style']['elements']['link']['color']['text'] ) ) {
return null;
};

$link_color = $attributes['style']['elements']['link']['color']['text'];

// If the link color is selected from the theme color picker, the value of $link_color is var:preset|color|slug.
// If the link color is selected from the core color picker, the value of $link_color is an hex value.
// When the link color is a string var:preset|color|slug we parsed it for get the slug, otherwise we use the hex value.
$index_named_link_color = strrpos( $link_color, '|' );

if ( ! empty( $index_named_link_color ) ) {
$parsed_named_link_color = substr( $link_color, $index_named_link_color + 1 );
return array(
'class' => null,
'style' => sprintf( 'color: %s;', $parsed_named_link_color ),
);
} else {
return array(
'class' => null,
'style' => sprintf( 'color: %s;', $link_color ),
);
}
}

/**
* Get class and style for line height from attributes.
*
* @param array $attributes Block attributes.
*
* @return (array | null)
*/
public static function get_line_height_class_and_style( $attributes ) {

$line_height = isset( $attributes['style']['typography']['lineHeight'] ) ? $attributes['style']['typography']['lineHeight'] : null;

if ( ! isset( $line_height ) ) {
return null;
};

$line_height_style = sprintf( 'line-height: %s;', $line_height );

return array(
'class' => null,
'style' => $line_height_style,
);
}

/**
* Get classes and styles from attributes.
*
* @param array $attributes Block attributes.
* @param array $properties Properties to get classes/styles from.
*
* @return array
*/
public static function get_classes_and_styles_by_attributes( $attributes, $properties = array() ) {
$classes_and_styles = array(
'line_height' => self::get_line_height_class_and_style( $attributes ),
'text_color' => self::get_text_color_class_and_style( $attributes ),
'font_size' => self::get_font_size_class_and_style( $attributes ),
'link_color' => self::get_link_color_class_and_style( $attributes ),
);

if ( ! empty( $properties ) ) {
foreach ( $classes_and_styles as $key => $value ) {
if ( ! in_array( $key, $properties, true ) ) {
unset( $classes_and_styles[ $key ] );
}
}
}

$classes_and_styles = array_filter( $classes_and_styles );

$classes = array_map(
function( $item ) {
return $item['class'];
},
$classes_and_styles
);

$styles = array_map(
function( $item ) {
return $item['style'];
},
$classes_and_styles
);

$classes = array_filter( $classes );
$styles = array_filter( $styles );

return array(
'classes' => implode( ' ', $classes ),
'styles' => implode( ' ', $styles ),
);
}

/**
* Get space-separated classes from block attributes.
*
* @param array $attributes Block attributes.
* @param array $properties Properties to get classes from.
*
* @return string Space-separated classes.
*/
public static function get_classes_by_attributes( $attributes, $properties = array() ) {
$classes_and_styles = self::get_classes_and_styles_by_attributes( $attributes, $properties );

return $classes_and_styles['classes'];
}

/**
* Get space-separated style rules from block attributes.
*
* @param array $attributes Block attributes.
* @param array $properties Properties to get styles from.
*
* @return string Space-separated style rules.
*/
public static function get_styles_by_attributes( $attributes, $properties = array() ) {
$classes_and_styles = self::get_classes_and_styles_by_attributes( $attributes, $properties );

return $classes_and_styles['styles'];
}
}