ProductFilterActive.php
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
/**
* Product Filter: Active Block.
*/
final class ProductFilterActive extends AbstractBlock {
/**
* Block name.
*
* @var string
*/
protected $block_name = 'product-filter-active';
/**
* Render the block.
*
* @param array $attributes Block attributes.
* @param string $content Block content.
* @param WP_Block $block Block instance.
* @return string Rendered block type output.
*/
protected function render( $attributes, $content, $block ) {
$query_id = $block->context['queryId'] ?? 0;
/**
* Filters the active filter data provided by filter blocks.
*
* $data = array(
* <id> => array(
* 'type' => string,
* 'items' => array(
* array(
* 'title' => string,
* 'attributes' => array(
* <key> => string
* )
* )
* )
* ),
* );
*
* @since 11.7.0
*
* @param array $data The active filters data
* @param array $params The query param parsed from the URL.
* @return array Active filters data.
*/
$active_filters = apply_filters( 'collection_active_filters_data', array(), $this->get_filter_query_params( $query_id ) );
$context = array(
'queryId' => $query_id,
'params' => array_keys( $this->get_filter_query_params( $query_id ) ),
);
$wrapper_attributes = get_block_wrapper_attributes(
array(
'data-wc-interactive' => wp_json_encode( array( 'namespace' => $this->get_full_block_name() ) ),
'data-wc-context' => wp_json_encode( $context ),
'data-has-filter' => empty( $active_filters ) ? 'no' : 'yes',
)
);
$list_classes = 'filter-list';
if ( 'chips' === $attributes['displayStyle'] ) {
$list_classes .= ' list-chips';
}
ob_start();
?>
<div <?php echo $wrapper_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<?php if ( ! empty( $active_filters ) ) : ?>
<ul class="<?php echo esc_attr( $list_classes ); ?>">
<?php foreach ( $active_filters as $filter ) : ?>
<li>
<span class="list-item-type"><?php echo esc_html( $filter['type'] ); ?>: </span>
<ul>
<?php $this->render_items( $filter['items'], $attributes['displayStyle'] ); ?>
</ul>
</li>
<?php endforeach; ?>
</ul>
<button class="clear-all" data-wc-on--click="actions.clearAll">
<span aria-hidden="true"><?php echo esc_html__( 'Clear All', 'woocommerce' ); ?></span>
<span class="screen-reader-text"><?php echo esc_html__( 'Clear All Filters', 'woocommerce' ); ?></span>
</button>
<?php endif; ?>
</div>
<?php
return ob_get_clean();
}
/**
* Render the list items.
*
* @param array $items Items data.
* @param string $style Display style: list | chips.
*/
private function render_items( $items, $style ) {
foreach ( $items as $item ) {
if ( 'chips' === $style ) {
$this->render_chip_item( $item );
} else {
$this->render_list_item( $item );
}
}
}
/**
* Render the list item of an active filter.
*
* @param array $args Item data.
* @return string Item HTML.
*/
private function render_list_item( $args ) {
list ( 'title' => $title, 'attributes' => $attributes ) = wp_parse_args(
$args,
array(
'title' => '',
'attributes' => array(),
)
);
if ( ! $title || empty( $attributes ) ) {
return;
}
$remove_label = sprintf( 'Remove %s filter', wp_strip_all_tags( $title ) );
?>
<li class="list-item">
<span class="list-item-name">
<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<button class="list-item-remove" <?php echo $this->get_html_attributes( $attributes ); ?>>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" class="wc-block-components-chip__remove-icon" aria-hidden="true" focusable="false"><path d="M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"></path></svg>
<span class="screen-reader-text"><?php echo esc_html( $remove_label ); ?></span>
</button>
<?php echo wp_kses_post( $title ); ?>
</span>
</li>
<?php
}
/**
* Render the chip item of an active filter.
*
* @param array $args Item data.
* @return string Item HTML.
*/
private function render_chip_item( $args ) {
list ( 'title' => $title, 'attributes' => $attributes ) = wp_parse_args(
$args,
array(
'title' => '',
'attributes' => array(),
)
);
if ( ! $title || empty( $attributes ) ) {
return;
}
$remove_label = sprintf( 'Remove %s filter', wp_strip_all_tags( $title ) );
?>
<li class="list-item">
<span class="is-removable wc-block-components-chip wc-block-components-chip--radius-large">
<span aria-hidden="false" class="wc-block-components-chip__text"><?php echo wp_kses_post( $title ); ?></span>
<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<button class="wc-block-components-chip__remove" aria-label="<?php echo esc_attr( $remove_label ); ?>" <?php echo $this->get_html_attributes( $attributes ); ?>>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" role="img" class="wc-block-components-chip__remove-icon" aria-hidden="true" focusable="false"><path d="M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"></path></svg>
</button>
</span>
</li>
<?php
}
/**
* Build HTML attributes string from assoc array.
*
* @param array $attributes Attributes data as an assoc array.
* @return string Escaped HTML attributes string.
*/
private function get_html_attributes( $attributes ) {
return array_reduce(
array_keys( $attributes ),
function( $acc, $key ) use ( $attributes ) {
$acc .= sprintf( ' %1$s="%2$s"', esc_attr( $key ), esc_attr( $attributes[ $key ] ) );
return $acc;
},
''
);
}
/**
* Parse the filter parameters from the URL.
* For now we only get the global query params from the URL. In the future,
* we should get the query params based on $query_id.
*
* @param int $query_id Query ID.
* @return array Parsed filter params.
*/
private function get_filter_query_params( $query_id ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
$parsed_url = wp_parse_url( esc_url_raw( $request_uri ) );
if ( empty( $parsed_url['query'] ) ) {
return array();
}
parse_str( $parsed_url['query'], $url_query_params );
/**
* Filters the active filter data provided by filter blocks.
*
* @since 11.7.0
*
* @param array $filter_param_keys The active filters data
* @param array $url_param_keys The query param parsed from the URL.
*
* @return array Active filters params.
*/
$filter_param_keys = array_unique( apply_filters( 'collection_filter_query_param_keys', array(), array_keys( $url_query_params ) ) );
return array_filter(
$url_query_params,
function( $key ) use ( $filter_param_keys ) {
return in_array( $key, $filter_param_keys, true );
},
ARRAY_FILTER_USE_KEY
);
}
}