Skip to content

Commit

Permalink
New blocks: Ratings (bars) and Ratings (stars). (#633)
Browse files Browse the repository at this point in the history
Move ratings-bars and ratings-stars from Theme Directory, and update to use filter for ratings data.

See WordPress/wporg-theme-directory@73b4c09, WordPress/wporg-theme-directory@8d5984c

---------

Co-authored-by: Kelly Dwan <[email protected]>
  • Loading branch information
StevenDufresne and ryelle authored Jul 24, 2024
1 parent 85cde2d commit bd22c7c
Show file tree
Hide file tree
Showing 11 changed files with 350 additions and 0 deletions.
20 changes: 20 additions & 0 deletions mu-plugins/blocks/ratings-bars/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
/**
* Block Name: Ratings (bars)
* Description: The breakdown of ratings displayed as bars for each rating value.
*
* @package wporg
*/

namespace WordPressdotorg\Theme\MU_Plugins\Ratings_Bars_Block;

defined( 'WPINC' ) || die();

add_action( 'init', __NAMESPACE__ . '\init' );

/**
* Register the block.
*/
function init() {
register_block_type( __DIR__ . '/build' );
}
72 changes: 72 additions & 0 deletions mu-plugins/blocks/ratings-bars/render.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

$current_post_id = $block->context['postId'];
if ( ! $current_post_id ) {
return;
}

/**
* Get the ratings data via filter, so that individual sites can provide
* this regardless of rating data format.
*
* @param array $data {
* Array of ratings data.
*
* The return value should use the following format.
*
* @type int $ratingsCount The total of ratings, must match sum of all
* values in ratings.
* @type int[] $ratings Rating count. The array must have 5 items, ex:
* [1 => count of 1-star, …, 5 => count of 5-star].
* @type int $rating The average rating on a scale of 0 - 100.
* @type string $supportUrl URL to support forum.
* }
* @param int $current_post_id The ID of the current post.
*/
$data = apply_filters( 'wporg_ratings_data', array(), $current_post_id );

$defaults = array(
'ratingsCount' => 0,
'ratings' => [],
'supportUrl' => '',
);

$data = wp_parse_args( $data, $defaults );

if ( empty( $data['ratings'] ) || empty( $data['ratingsCount'] ) ) {
return;
}

?>
<ul <?php echo get_block_wrapper_attributes(); // phpcs:ignore ?>>
<?php
foreach ( range( 5, 1 ) as $stars ) :
if ( ! isset( $data['ratings'][ $stars ] ) ) {
continue;
}
$count = $data['ratings'][ $stars ];
$rating_bar_width = 100 * $count / $data['ratingsCount'];
$support_url = add_query_arg( 'filter', $stars, $data['supportUrl'] );
?>
<li class="wporg-ratings-bars__bar">
<a href="<?php echo esc_url( $support_url ); ?>">
<span class="screen-reader-text">
<?php
// translators: %1$d: count of reviews. %2$d: level of star rating (ex, 5-star).
echo esc_html( sprintf( _n( '%1$d %2$d-star review', '%1$d %2$d-star reviews', $count, 'wporg' ), $count, $stars ) );
?>
</span>
<span aria-hidden="true" class="wporg-ratings-bars__bar-label">
<?php
// translators: %d: star review amount, 1-5; ex "5 stars".
echo esc_html( sprintf( _n( '%d star', '%d stars', $stars, 'wporg' ), $stars ) );
?>
</span>
<span aria-hidden="true" class="wporg-ratings-bars__bar-background">
<span class="wporg-ratings-bars__bar-foreground" style="width: <?php echo intval( $rating_bar_width ); ?>%;"></span>
</span>
<span aria-hidden="true" class="wporg-ratings-bars__bar-count"><?php echo intval( $count ); ?></span>
</a>
</li>
<?php endforeach; ?>
</ul>
18 changes: 18 additions & 0 deletions mu-plugins/blocks/ratings-bars/src/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "wporg/ratings-bars",
"version": "0.1.0",
"title": "Ratings (bars)",
"category": "design",
"icon": "",
"description": "The breakdown of ratings displayed as bars for each rating value.",
"textdomain": "wporg",
"supports": {
"html": false
},
"usesContext": [ "postId" ],
"editorScript": "file:./index.js",
"style": "file:./style-index.css",
"render": "file:../render.php"
}
25 changes: 25 additions & 0 deletions mu-plugins/blocks/ratings-bars/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* WordPress dependencies
*/
import { registerBlockType } from '@wordpress/blocks';
import ServerSideRender from '@wordpress/server-side-render';
import { useBlockProps } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import metadata from './block.json';
import './style.scss';

function Edit( { attributes, name } ) {
return (
<div { ...useBlockProps() }>
<ServerSideRender block={ name } attributes={ attributes } skipBlockSupportAttributes />
</div>
);
}

registerBlockType( metadata.name, {
edit: Edit,
save: () => null,
} );
65 changes: 65 additions & 0 deletions mu-plugins/blocks/ratings-bars/src/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.wp-block-wporg-ratings-bars {
list-style: none;
padding-inline-start: unset;
}

.wporg-ratings-bars__bar {
a {
margin-bottom: 4px;
display: flex;
align-items: center;
gap: var(--wp--preset--spacing--10);
text-decoration: none;

&:hover {
text-decoration: underline;
}
}

&:last-child a {
margin-bottom: 0;
}
}

.wporg-ratings-bars__bar-label {
flex-basis: 4em;
flex-shrink: 0;
}

.wporg-ratings-bars__bar-count {
flex-basis: 2em;
flex-shrink: 0;
text-align: right;
}

.wporg-ratings-bars__bar-background {
display: inline-block;
background-color: var(--wp--preset--color--light-grey-2);
position: relative;
width: 100%;
height: var(--wp--preset--spacing--20);
}

.wporg-ratings-bars__bar-foreground {
position: absolute;
inset: 0;
right: auto;
background-color: var(--wp--custom--wporg-ratings-stars--color--fill, #e26f56);
}

@supports (grid-template-columns: subgrid) {
.wp-block-wporg-ratings-bars {
display: grid;
gap: 4px var(--wp--preset--spacing--10);
grid-template-columns: auto 1fr auto;

.wporg-ratings-bars__bar,
.wporg-ratings-bars__bar a {
display: grid;
grid-column: span 3;
grid-template-columns: subgrid;
margin-bottom: unset;
gap: unset;
}
}
}
20 changes: 20 additions & 0 deletions mu-plugins/blocks/ratings-stars/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
/**
* Block Name: Ratings (stars)
* Description: The average rating of this theme displayed as stars.
*
* @package wporg
*/

namespace WordPressdotorg\Theme\MU_Plugins\Ratings_Stars_Block;

defined( 'WPINC' ) || die();

add_action( 'init', __NAMESPACE__ . '\init' );

/**
* Register the block.
*/
function init() {
register_block_type( __DIR__ . '/build' );
}
56 changes: 56 additions & 0 deletions mu-plugins/blocks/ratings-stars/render.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

$current_post_id = $block->context['postId'];
if ( ! $current_post_id ) {
return;
}

/** This filter is documented in mu-plugins/blocks/ratings-bars/render.php */
$data = apply_filters( 'wporg_ratings_data', array(), $current_post_id );

$defaults = array(
'rating' => 0,
);

$data = wp_parse_args( $data, $defaults );

if ( empty( $data['rating'] ) ) {
return;
}

?>
<div <?php echo get_block_wrapper_attributes(); // phpcs:ignore ?>>
<?php if ( ! $data['rating'] ) : ?>
<!-- Hide the "See all…" link if there are no ratings. -->
<style>.wporg-ratings-link{display:none}</style>
<div class="wporg-ratings-stars__label-empty">
<?php esc_html_e( 'This has not been rated yet.', 'wporg' ); ?>
</div>
<?php else : ?>
<div class="wporg-ratings-stars__icons">
<?php

$display_rating = round( $data['rating'] / 10 ) * 0.5;
for ( $i = 0; $i < 5; $i++ ) {
if ( $i + 1 <= $display_rating ) {
echo '<svg class="is-star-filled" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M11.776 4.454a.25.25 0 01.448 0l2.069 4.192a.25.25 0 00.188.137l4.626.672a.25.25 0 01.139.426l-3.348 3.263a.25.25 0 00-.072.222l.79 4.607a.25.25 0 01-.362.263l-4.138-2.175a.25.25 0 00-.232 0l-4.138 2.175a.25.25 0 01-.363-.263l.79-4.607a.25.25 0 00-.071-.222L4.754 9.881a.25.25 0 01.139-.426l4.626-.672a.25.25 0 00.188-.137l2.069-4.192z"></path></svg>';
} else if ( $i + 0.5 === $display_rating ) {
echo '<svg class="is-star-half" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M9.518 8.783a.25.25 0 00.188-.137l2.069-4.192a.25.25 0 01.448 0l2.07 4.192a.25.25 0 00.187.137l4.626.672a.25.25 0 01.139.427l-3.347 3.262a.25.25 0 00-.072.222l.79 4.607a.25.25 0 01-.363.264l-4.137-2.176a.25.25 0 00-.233 0l-4.138 2.175a.25.25 0 01-.362-.263l.79-4.607a.25.25 0 00-.072-.222L4.753 9.882a.25.25 0 01.14-.427l4.625-.672zM12 14.533c.28 0 .559.067.814.2l1.895.997-.362-2.11a1.75 1.75 0 01.504-1.55l1.533-1.495-2.12-.308a1.75 1.75 0 01-1.317-.957L12 7.39v7.143z"></path></svg>';
} else {
echo '<svg class="is-star-empty" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path fill-rule="evenodd" d="M9.706 8.646a.25.25 0 01-.188.137l-4.626.672a.25.25 0 00-.139.427l3.348 3.262a.25.25 0 01.072.222l-.79 4.607a.25.25 0 00.362.264l4.138-2.176a.25.25 0 01.233 0l4.137 2.175a.25.25 0 00.363-.263l-.79-4.607a.25.25 0 01.072-.222l3.347-3.262a.25.25 0 00-.139-.427l-4.626-.672a.25.25 0 01-.188-.137l-2.069-4.192a.25.25 0 00-.448 0L9.706 8.646zM12 7.39l-.948 1.921a1.75 1.75 0 01-1.317.957l-2.12.308 1.534 1.495c.412.402.6.982.503 1.55l-.362 2.11 1.896-.997a1.75 1.75 0 011.629 0l1.895.997-.362-2.11a1.75 1.75 0 01.504-1.55l1.533-1.495-2.12-.308a1.75 1.75 0 01-1.317-.957L12 7.39z" clip-rule="evenodd"></path></svg>';
}
}
?>
</div>

<div class="wporg-ratings-stars__label">
<?php
printf(
// translators: %s is the current rating value.
esc_html__( '%s out of 5 stars.', 'wporg' ),
'<span>' . $display_rating . '</span>' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
);
?>
</div>
<?php endif; ?>
</div>
18 changes: 18 additions & 0 deletions mu-plugins/blocks/ratings-stars/src/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "wporg/ratings-stars",
"version": "0.1.0",
"title": "Ratings (stars)",
"category": "design",
"icon": "",
"description": "The average rating displayed as stars.",
"textdomain": "wporg",
"supports": {
"html": false
},
"usesContext": [ "postId" ],
"editorScript": "file:./index.js",
"style": "file:./style-index.css",
"render": "file:../render.php"
}
25 changes: 25 additions & 0 deletions mu-plugins/blocks/ratings-stars/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* WordPress dependencies
*/
import { registerBlockType } from '@wordpress/blocks';
import ServerSideRender from '@wordpress/server-side-render';
import { useBlockProps } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import metadata from './block.json';
import './style.scss';

function Edit( { attributes, name } ) {
return (
<div { ...useBlockProps() }>
<ServerSideRender block={ name } attributes={ attributes } skipBlockSupportAttributes />
</div>
);
}

registerBlockType( metadata.name, {
edit: Edit,
save: () => null,
} );
29 changes: 29 additions & 0 deletions mu-plugins/blocks/ratings-stars/src/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.wp-block-wporg-ratings-stars {
display: flex;
align-items: center;
}

.wporg-ratings-stars__icons {
display: inline-flex;

svg {
height: 32px;
width: 32px;
margin-inline-start: -6px;
fill: var(--wp--custom--wporg-ratings-stars--color--fill, #e26f56);
}

// Flip the half-star for RTL views.
.rtl & .is-star-half {
transform: rotateY(-180deg);
}
}

.wporg-ratings-stars__label {
font-size: var(--wp--preset--font-size--small);
color: var(--wp--preset--color--charcoal-4);

.wporg-ratings-stars__icons + & {
margin-inline-start: 0.5em;
}
}
2 changes: 2 additions & 0 deletions mu-plugins/loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
require_once __DIR__ . '/blocks/query-filter/index.php';
require_once __DIR__ . '/blocks/query-has-results/index.php';
require_once __DIR__ . '/blocks/query-total/index.php';
require_once __DIR__ . '/blocks/ratings-bars/index.php';
require_once __DIR__ . '/blocks/ratings-stars/index.php';
require_once __DIR__ . '/blocks/sidebar-container/index.php';
require_once __DIR__ . '/blocks/screenshot-preview/block.php';
require_once __DIR__ . '/blocks/screenshot-preview-block/block.php';
Expand Down

0 comments on commit bd22c7c

Please sign in to comment.