Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement abstract Block facet feature class #3499

Merged
merged 18 commits into from
Aug 7, 2023
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
58 changes: 58 additions & 0 deletions includes/classes/Feature/Facets/Block.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php
/**
* Abstract Facet Block class.
*
* @since 4.7.0
* @package elasticpress
*/

namespace ElasticPress\Feature\Facets;

/**
* Abstract Facet Block class.
*/
abstract class Block {

/**
* Setup hooks and filters for facet block.
*/
abstract public function setup();

/**
* Register facet block.
*/
abstract public function register_block();

/**
* Setup REST endpoints for facet feature.
*/
abstract public function setup_endpoints();

/**
* Render the block.
*
* @param array $attributes Block attributes.
* @return string
*/
abstract public function render_block( $attributes );

/**
* Outputs the block preview
*
* @param \WP_REST_Request $request REST request
* @return string
*/
abstract public function render_block_preview( $request );

/**
* Check if the current user has permission to view the facets REST endpoint.
*
* @return true|\WP_Error
*/
public function check_facets_rest_permission() {
if ( ! current_user_can( 'edit_theme_options' ) ) {
return new \WP_Error( 'ep_rest_forbidden', esc_html__( 'Sorry, you cannot view this resource.', 'elasticpress' ), array( 'status' => 401 ) );
}
return true;
}
}
78 changes: 78 additions & 0 deletions includes/classes/Feature/Facets/Renderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php
/**
* Abstract Facet Renderer class.
*
* @since 4.7.0
* @package elasticpress
*/

namespace ElasticPress\Feature\Facets;

/**
* Abstract Facet Renderer class.
*/
abstract class Renderer {
/**
* Whether the term count should be displayed or not.
*
* @var bool
*/
protected $display_count;

/**
* Method to render the facet.
*
* @param array $args Widget args
* @param array $instance Instance settings
*/
abstract public function render( $args, $instance );

/**
* Whether the facet should be rendered or not.
*
* @return bool
*/
protected function should_render() : bool {
return true;
}

/**
* Given an array of values, reorder them.
*
* @param array $values Multidimensional array of values. Each value should have (string) `name`, (int) `count`, and (bool) `is_selected`.
* @param string $orderby Key to be used to order.
* @param string $order ASC or DESC.
* @return array
*/
protected function order_values( array $values, string $orderby = 'count', $order = 'desc' ) : array {
$orderby = strtolower( $orderby );
$orderby = in_array( $orderby, [ 'name', 'count' ], true ) ? $orderby : 'count';

$order = strtoupper( $order );
$order = in_array( $order, [ 'ASC', 'DESC' ], true ) ? $order : 'DESC';

$values = wp_list_sort( $values, $orderby, $order, true );

$selected = [];
foreach ( $values as $key => $value ) {
if ( $value['is_selected'] ) {
$selected[ $key ] = $value;
unset( $values[ $key ] );
}
}
$values = $selected + $values;

return $values;
}

/**
* Get the markup for an individual facet item.
*
* @param array|object $item Facet item.
* @param string $url URL for the facet item.
* @return string|null
*/
public function get_facet_item_value_html( $item, string $url ) {
return null;
}
}
30 changes: 14 additions & 16 deletions includes/classes/Feature/Facets/Types/Meta/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
/**
* Facets block class
*/
class Block {
class Block extends \ElasticPress\Feature\Facets\Block {
/**
* Hook block funcionality.
*/
Expand All @@ -36,7 +36,7 @@ public function setup_endpoints() {
'facets/meta/keys',
[
'methods' => 'GET',
'permission_callback' => [ $this, 'check_facets_meta_rest_permission' ],
'permission_callback' => [ $this, 'check_facets_rest_permission' ],
'callback' => [ $this, 'get_rest_registered_metakeys' ],
]
);
Expand All @@ -45,7 +45,7 @@ public function setup_endpoints() {
'facets/meta/block-preview',
[
'methods' => 'GET',
'permission_callback' => [ $this, 'check_facets_meta_rest_permission' ],
'permission_callback' => [ $this, 'check_facets_rest_permission' ],
'callback' => [ $this, 'render_block_preview' ],
'args' => [
'searchPlaceholder' => [
Expand All @@ -69,19 +69,6 @@ public function setup_endpoints() {
);
}

/**
* Check permissions of the /facets/meta/* REST endpoints.
*
* @return WP_Error|true
*/
public function check_facets_meta_rest_permission() {
if ( ! current_user_can( 'edit_theme_options' ) ) {
return new \WP_Error( 'ep_rest_forbidden', esc_html__( 'Sorry, you cannot view this resource.', 'elasticpress' ), array( 'status' => 401 ) );
}

return true;
}

/**
* Return an array of registered meta keys.
*
Expand Down Expand Up @@ -243,4 +230,15 @@ protected function parse_attributes( $attributes ) {
}
return $attributes;
}

/**
* DEPRECATED. Check permissions of the /facets/meta/* REST endpoints.
*
* @return WP_Error|true
*/
public function check_facets_meta_rest_permission() {
_deprecated_function( __METHOD__, '4.7.0', '\ElasticPress\Feature\Facets\Types\Meta\Block::check_facets_rest_permission()' );

return $this->check_facets_rest_permission();
}
}
76 changes: 30 additions & 46 deletions includes/classes/Feature/Facets/Types/Meta/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/**
* Facets render class
*/
class Renderer {
class Renderer extends \ElasticPress\Feature\Facets\Renderer {
/**
* Holds the meta field selected.
*
Expand Down Expand Up @@ -149,21 +149,21 @@ public function render( $args, $instance ) {
$order = $instance['order'] ?? 'desc';

$values = $this->order_values( $values, $orderby, $order );
foreach ( $values as $raw_value => $value ) {
foreach ( $values as $raw_value => $item ) {

$field_filters = $selected_filters;
if ( $value['is_selected'] ) {
if ( $item['is_selected'] ) {
unset( $field_filters[ $facet_type->get_filter_type() ][ $this->meta_field ]['terms'][ $raw_value ] );
} else {
$field_filters[ $facet_type->get_filter_type() ][ $this->meta_field ]['terms'][ $raw_value ] = 1;
}

// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
echo $this->get_meta_value_html(
$value,
echo $this->get_facet_item_value_html(
$item,
$feature->build_query_url( $field_filters )
);
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
</div>
Expand All @@ -180,19 +180,19 @@ public function render( $args, $instance ) {
/**
* Get the markup for an individual facet item.
*
* @param array $value Value.
* @param array $item Facet item.
* @param string $url Filter URL.
* @return string HTML for an individual facet term.
*/
public function get_meta_value_html( array $value, string $url ) : string {
public function get_facet_item_value_html( $item, string $url ) : string {
$href = sprintf(
'href="%s"',
esc_url( $url )
);

$label = $value['name'];
$label = $item['name'];
if ( $this->display_count ) {
$label .= ' <span>(' . $value['count'] . ')</span>';
$label .= ' <span>(' . $item['count'] . ')</span>';
}

/**
Expand All @@ -201,10 +201,10 @@ public function get_meta_value_html( array $value, string $url ) : string {
* @since 4.3.0
* @hook ep_facet_meta_value_label
* @param {string} $label Facet meta value label.
* @param {array} $value Value array. It contains `value`, `name`, `count`, and `is_selected`.
* @param {array} $item Value array. It contains `value`, `name`, `count`, and `is_selected`.
* @return {string} Individual facet meta value label.
*/
$label = apply_filters( 'ep_facet_meta_value_label', $label, $value );
$label = apply_filters( 'ep_facet_meta_value_label', $label, $item );

/**
* Filter the accessible label for an individual facet meta value link.
Expand All @@ -217,34 +217,34 @@ public function get_meta_value_html( array $value, string $url ) : string {
* @since 4.3.0
* @hook ep_facet_meta_value_accessible_label
* @param {string} $label Facet meta value accessible label.
* @param {array} $value Value array. It contains `value`, `name`, `count`, and `is_selected`.
* @param {array} $item Value array. It contains `value`, `name`, `count`, and `is_selected`.
* @return {string} Individual facet term accessible label.
*/
$accessible_label = apply_filters(
'ep_facet_meta_value_accessible_label',
$value['is_selected']
$item['is_selected']
/* translators: %s: Filter term name. */
? sprintf( __( 'Remove filter: %s', 'elasticpress' ), $label )
/* translators: %s: Filter term name. */
: sprintf( __( 'Apply filter: %s', 'elasticpress' ), $label ),
$value
$item
);

$link = sprintf(
'<a aria-label="%1$s" %2$s rel="nofollow"><div class="ep-checkbox %3$s" role="presentation"></div>%4$s</a>',
esc_attr( $accessible_label ),
$value['count'] ? $href : 'aria-role="link" aria-disabled="true"',
$value['is_selected'] ? 'checked' : '',
$item['count'] ? $href : 'aria-role="link" aria-disabled="true"',
$item['is_selected'] ? 'checked' : '',
wp_kses_post( $label )
);

$html = sprintf(
'<div class="term level-%1$d %2$s %3$s" data-term-name="%4$s" data-term-slug="%5$s">%6$s</div>',
0,
$value['is_selected'] ? 'selected' : '',
! $value['count'] ? 'empty-term' : '',
esc_attr( strtolower( $value['value'] ) ),
esc_attr( strtolower( $value['value'] ) ),
$item['is_selected'] ? 'selected' : '',
! $item['count'] ? 'empty-term' : '',
esc_attr( strtolower( $item['value'] ) ),
esc_attr( strtolower( $item['value'] ) ),
$link
);

Expand All @@ -258,11 +258,11 @@ public function get_meta_value_html( array $value, string $url ) : string {
* @since 4.3.0
* @hook ep_facet_meta_value_html
* @param {string} $html Facet meta value HTML.
* @param {array} $value Value array. It contains `value`, `name`, `count`, and `is_selected`.
* @param {array} $item Value array. It contains `value`, `name`, `count`, and `is_selected`.
* @param {string} $url Filter URL.
* @return {string} Individual facet meta value HTML.
*/
return apply_filters( 'ep_facet_meta_value_html', $html, $value, $url );
return apply_filters( 'ep_facet_meta_value_html', $html, $item, $url );
}

/**
Expand Down Expand Up @@ -309,31 +309,15 @@ protected function get_selected_meta() : array {
}

/**
* Given an array of values, reorder them.
* DEPRECATED. Get the markup for an individual facet item.
*
* @param array $values Multidimensional array of values. Each value should have (string) `name`, (int) `count`, and (bool) `is_selected`.
* @param string $orderby Key to be used to order.
* @param string $order ASC or DESC.
* @return array
* @param array $value Value.
* @param string $url Filter URL.
* @return string HTML for an individual facet term.
*/
protected function order_values( array $values, string $orderby = 'count', $order = 'desc' ) : array {
$orderby = strtolower( $orderby );
$orderby = in_array( $orderby, [ 'name', 'count' ], true ) ? $orderby : 'count';

$order = strtoupper( $order );
$order = in_array( $order, [ 'ASC', 'DESC' ], true ) ? $order : 'DESC';

$values = wp_list_sort( $values, $orderby, $order, true );

$selected = [];
foreach ( $values as $key => $value ) {
if ( $value['is_selected'] ) {
$selected[ $key ] = $value;
unset( $values[ $key ] );
}
}
$values = $selected + $values;
public function get_meta_value_html( array $value, string $url ) : string {
_deprecated_function( __METHOD__, '4.7.0', '\ElasticPress\Feature\Facets\Types\Meta\Renderer::get_facet_item_value_html()' );

return $values;
return $this->get_facet_item_value_html( $value, $url );
}
}
Loading