diff --git a/src/ContentElement/ReviewsElement.php b/src/ContentElement/ReviewsElement.php index 9259c33..a03d223 100644 --- a/src/ContentElement/ReviewsElement.php +++ b/src/ContentElement/ReviewsElement.php @@ -3,8 +3,9 @@ /* * Regiondo Bundle for Contao Open Source CMS. * - * @copyright Copyright (c) 2018, derhaeuptling + * @copyright Copyright (c) 2019, derhaeuptling * @author Codefog + * @author Moritz V. * @license MIT */ @@ -17,6 +18,9 @@ class ReviewsElement extends ContentElement { + public const SHOW_REVIEWS = 1 << 0; + public const SHOW_AGGREGATED_REVIEWS = 1 << 1; + /** * Template. * @@ -56,14 +60,25 @@ public function generate() */ protected function compile(): void { - $reviews = $this->reviews; + $displayMode = $this->regiondo_reviewsDisplayMode; + $showReviews = $displayMode & self::SHOW_REVIEWS; + $showAggregatedReviews = $displayMode & self::SHOW_AGGREGATED_REVIEWS; - // Limit the number of reviews - if ($this->regiondo_reviewsLimit > 0) { - $reviews = \array_slice($reviews, 0, $this->regiondo_reviewsLimit); + if ($showAggregatedReviews) { + $this->Template->aggregatedReviews = $this->aggregateReviews($this->reviews); } + $this->Template->showAggregatedReviews = $showAggregatedReviews; + + if ($showReviews) { + // Limit the number of reviews + $reviews = $this->reviews; + if ($this->regiondo_reviewsLimit > 0) { + $reviews = \array_slice($reviews, 0, $this->regiondo_reviewsLimit); + } - $this->Template->reviews = $this->generateReviews($reviews); + $this->Template->reviews = $this->generateReviews($reviews); + } + $this->Template->showReviews = $showReviews; } /** @@ -93,4 +108,56 @@ protected function generateReviews(array $items) return $reviews; } + + /** + * Aggregate reviews. + * + * @param array $items + * + * @return array + */ + protected function aggregateReviews(array $items): array + { + $ratings = \array_filter( + \array_map(function ($item) { + if (!$item['vote_details']) { + return null; + } + + // Average vote details + return $this->calculateAverage( + \array_map(static function ($item) { + return $item['percent']; + }, $item['vote_details']) + ); + }, $items) + ); + + // Average votes + return [ + 'count' => \count($ratings), + 'percent' => $this->calculateAverage($ratings), + ]; + } + + /** + * Calculate average - used to aggregate review details and reviews. + * + * @param array $values + * + * @return float + */ + protected function calculateAverage(array $values): float + { + $sum = \array_reduce($values, + static function ($sum, $item) { + $sum += $item; + + return $sum; + } + ); + + // Simple arithmetic mean + return $sum / \count($values); + } } diff --git a/src/Resources/contao/dca/tl_content.php b/src/Resources/contao/dca/tl_content.php index d4842b2..9af88e2 100644 --- a/src/Resources/contao/dca/tl_content.php +++ b/src/Resources/contao/dca/tl_content.php @@ -9,6 +9,7 @@ * @license MIT */ +use Derhaeuptling\RegiondoBundle\ContentElement\ReviewsElement; use Derhaeuptling\RegiondoBundle\EventListener\ContentListener; /* @@ -21,7 +22,7 @@ */ $GLOBALS['TL_DCA']['tl_content']['palettes']['__selector__'][] = 'regiondo_filterProducts'; $GLOBALS['TL_DCA']['tl_content']['palettes']['regiondo_event_booking_iframe'] = '{type_legend},type;{include_legend},regiondo_calendar,regiondo_iframeWidth;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID;{invisible_legend:hide},invisible,start,stop'; -$GLOBALS['TL_DCA']['tl_content']['palettes']['regiondo_reviews'] = '{type_legend},type;{include_legend},regiondo_filterProducts,regiondo_reviewsLimit,regiondo_syncReviews;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID;{invisible_legend:hide},invisible,start,stop'; +$GLOBALS['TL_DCA']['tl_content']['palettes']['regiondo_reviews'] = '{type_legend},type;{include_legend},regiondo_filterProducts,regiondo_reviewsLimit,regiondo_syncReviews;regiondo_reviewsDisplayMode;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID;{invisible_legend:hide},invisible,start,stop'; $GLOBALS['TL_DCA']['tl_content']['palettes']['regiondo_voucher'] = '{type_legend},type;{include_legend},regiondo_voucher,regiondo_iframeWidth;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID;{invisible_legend:hide},invisible,start,stop'; $GLOBALS['TL_DCA']['tl_content']['subpalettes']['regiondo_filterProducts'] = 'regiondo_products'; @@ -96,3 +97,17 @@ 'eval' => ['submitOnChange' => true], 'sql' => ['type' => 'string', 'default' => '1', 'length' => 1, 'options' => ['fixed' => true]], ]; + +$GLOBALS['TL_DCA']['tl_content']['fields']['regiondo_reviewsDisplayMode'] = [ + 'label' => &$GLOBALS['TL_LANG']['tl_content']['regiondo_reviewsDisplayMode'], + 'reference' => &$GLOBALS['TL_LANG']['tl_content']['regiondo_reviewsDisplayMode_options'], + 'exclude' => true, + 'inputType' => 'select', + 'options' => [ + ReviewsElement::SHOW_REVIEWS, + ReviewsElement::SHOW_AGGREGATED_REVIEWS, + ReviewsElement::SHOW_REVIEWS | ReviewsElement::SHOW_AGGREGATED_REVIEWS, + ], + 'eval' => ['tl_class' => 'w50'], + 'sql' => ['type' => 'smallint', 'unsigned' => true, 'default' => ReviewsElement::SHOW_REVIEWS], +]; diff --git a/src/Resources/contao/languages/de/tl_content.php b/src/Resources/contao/languages/de/tl_content.php index 8b4d7ce..5455ee6 100644 --- a/src/Resources/contao/languages/de/tl_content.php +++ b/src/Resources/contao/languages/de/tl_content.php @@ -8,6 +8,8 @@ * @license MIT */ +use Derhaeuptling\RegiondoBundle\ContentElement\ReviewsElement; + $GLOBALS['TL_LANG']['tl_content']['regiondo_calendar'] = ['Regiondo calendar', 'Please choose the Regiondo calendar.']; $GLOBALS['TL_LANG']['tl_content']['regiondo_filterProducts'] = ['Filter Regiondo products', 'Enable to select a range of products. If disabled all available products will be used.']; $GLOBALS['TL_LANG']['tl_content']['regiondo_products'] = ['Regiondo products', 'Please choose one or more Regiondo products to get the reviews from.']; @@ -16,3 +18,9 @@ $GLOBALS['TL_LANG']['tl_content']['regiondo_iframeWidth'] = ['Regiondo iFrame width (px)', 'Here you can enter the Regiondo iFrame width in pixels.']; $GLOBALS['TL_LANG']['tl_content']['regiondo_reviewsLimit'] = ['Reviews limit', 'Here you can limit the number of displayed reviews. Set 0 to display all reviews.']; $GLOBALS['TL_LANG']['tl_content']['regiondo_syncReviews'] = ['Synchronize reviews', 'Synchronize the Regiondo reviews upon content element save.']; +$GLOBALS['TL_LANG']['tl_content']['regiondo_reviewsDisplayMode'] = ['Display mode']; +$GLOBALS['TL_LANG']['tl_content']['regiondo_reviewsDisplayMode_options'] = [ + ReviewsElement::SHOW_REVIEWS => 'Show reviews', + ReviewsElement::SHOW_AGGREGATED_REVIEWS => 'Show aggregated reviews', + ReviewsElement::SHOW_REVIEWS | ReviewsElement::SHOW_AGGREGATED_REVIEWS => 'Show both reviews and aggregated reviews', +]; diff --git a/src/Resources/contao/languages/en/tl_content.php b/src/Resources/contao/languages/en/tl_content.php index 8b4d7ce..5455ee6 100644 --- a/src/Resources/contao/languages/en/tl_content.php +++ b/src/Resources/contao/languages/en/tl_content.php @@ -8,6 +8,8 @@ * @license MIT */ +use Derhaeuptling\RegiondoBundle\ContentElement\ReviewsElement; + $GLOBALS['TL_LANG']['tl_content']['regiondo_calendar'] = ['Regiondo calendar', 'Please choose the Regiondo calendar.']; $GLOBALS['TL_LANG']['tl_content']['regiondo_filterProducts'] = ['Filter Regiondo products', 'Enable to select a range of products. If disabled all available products will be used.']; $GLOBALS['TL_LANG']['tl_content']['regiondo_products'] = ['Regiondo products', 'Please choose one or more Regiondo products to get the reviews from.']; @@ -16,3 +18,9 @@ $GLOBALS['TL_LANG']['tl_content']['regiondo_iframeWidth'] = ['Regiondo iFrame width (px)', 'Here you can enter the Regiondo iFrame width in pixels.']; $GLOBALS['TL_LANG']['tl_content']['regiondo_reviewsLimit'] = ['Reviews limit', 'Here you can limit the number of displayed reviews. Set 0 to display all reviews.']; $GLOBALS['TL_LANG']['tl_content']['regiondo_syncReviews'] = ['Synchronize reviews', 'Synchronize the Regiondo reviews upon content element save.']; +$GLOBALS['TL_LANG']['tl_content']['regiondo_reviewsDisplayMode'] = ['Display mode']; +$GLOBALS['TL_LANG']['tl_content']['regiondo_reviewsDisplayMode_options'] = [ + ReviewsElement::SHOW_REVIEWS => 'Show reviews', + ReviewsElement::SHOW_AGGREGATED_REVIEWS => 'Show aggregated reviews', + ReviewsElement::SHOW_REVIEWS | ReviewsElement::SHOW_AGGREGATED_REVIEWS => 'Show both reviews and aggregated reviews', +]; diff --git a/src/Resources/contao/templates/elements/ce_regiondo_reviews.html5 b/src/Resources/contao/templates/elements/ce_regiondo_reviews.html5 index 8c5b4e9..507f811 100644 --- a/src/Resources/contao/templates/elements/ce_regiondo_reviews.html5 +++ b/src/Resources/contao/templates/elements/ce_regiondo_reviews.html5 @@ -2,28 +2,37 @@ block('content'); ?> -
- reviews): ?> - reviews as $review): ?> -
-

|

+showReviews): ?> +
+ reviews): ?> + reviews as $review): ?> +
+

|

-

+

-

+

- -
    - -
  • : %
  • - -
- -
- - -

- -
+ +
    + +
  • : %
  • + +
+ +
+ + +

+ +
+ + +showAggregatedReviews): ?> +
+ aggregatedReviews['percent'], 2); ?>% + (aggregatedReviews['count']; ?>) +
+ endblock(); ?>