From 3f1e35d45e1ead0b347d2e65997efa7ff9dc9eb8 Mon Sep 17 00:00:00 2001 From: Dan Garner Date: Thu, 8 Feb 2024 18:11:18 +0000 Subject: [PATCH] Currencies and Stocks duration issue (#2360) * JavaScript: ignore [0] references as they cannot be library references. * Widget: calculatedDuration incorrect for currencies and stocks. * Widget: HTML should contain the duration according to whether use duration is set. relates to xibosignageltd/xibo-private#615 --- lib/Entity/ModulePropertyTrait.php | 6 +- lib/Widget/CurrenciesAndStocksProvider.php | 96 +++++++++++++++++++ lib/Widget/Provider/DataProviderInterface.php | 8 +- lib/Widget/Render/WidgetHtmlRenderer.php | 4 +- modules/currencies.xml | 4 +- modules/stocks.xml | 4 +- 6 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 lib/Widget/CurrenciesAndStocksProvider.php diff --git a/lib/Entity/ModulePropertyTrait.php b/lib/Entity/ModulePropertyTrait.php index f36b0db7a0..aff418adc2 100644 --- a/lib/Entity/ModulePropertyTrait.php +++ b/lib/Entity/ModulePropertyTrait.php @@ -1,6 +1,6 @@ allowLibraryRefs && !empty($value)) { // Parse them out and replace for our special syntax. + // TODO: Can we improve this regex to ignore things we suspect are JavaScript array access? $matches = []; preg_match_all('/\[(.*?)\]/', $value, $matches); foreach ($matches[1] as $match) { - if (is_numeric($match)) { + // We ignore non-numbers and zero/negative integers + if (is_numeric($match) && intval($match) <= 0) { $value = str_replace( '[' . $match . ']', '[[mediaId=' . $match . ']]', diff --git a/lib/Widget/CurrenciesAndStocksProvider.php b/lib/Widget/CurrenciesAndStocksProvider.php new file mode 100644 index 0000000000..b20e5f5257 --- /dev/null +++ b/lib/Widget/CurrenciesAndStocksProvider.php @@ -0,0 +1,96 @@ +. + */ + +namespace Xibo\Widget; + +use Carbon\Carbon; +use Xibo\Widget\Provider\DataProviderInterface; +use Xibo\Widget\Provider\DurationProviderInterface; +use Xibo\Widget\Provider\WidgetProviderInterface; +use Xibo\Widget\Provider\WidgetProviderTrait; + +/** + * A widget provider for stocks and currencies, only used to correctly set the numItems + */ +class CurrenciesAndStocksProvider implements WidgetProviderInterface +{ + use WidgetProviderTrait; + + /** + * We want to pass this out to the event mechanism for 3rd party sources. + * @param \Xibo\Widget\Provider\DataProviderInterface $dataProvider + * @return \Xibo\Widget\Provider\WidgetProviderInterface + */ + public function fetchData(DataProviderInterface $dataProvider): WidgetProviderInterface + { + $dataProvider->setIsUseEvent(); + return $this; + } + + /** + * Special handling for currencies and stocks where the number of data items is based on the quantity of + * items input in the `items` property. + * @param \Xibo\Widget\Provider\DurationProviderInterface $durationProvider + * @return \Xibo\Widget\Provider\WidgetProviderInterface + */ + public function fetchDuration(DurationProviderInterface $durationProvider): WidgetProviderInterface + { + $this->getLog()->debug('fetchDuration: CurrenciesAndStocksProvider'); + + // Currencies and stocks are based on the number of items set in the respective fields. + $items = $durationProvider->getWidget()->getOptionValue('items', null); + if ($items === null) { + $this->getLog()->debug('fetchDuration: CurrenciesAndStocksProvider: no items set'); + return $this; + } + + if ($durationProvider->getWidget()->getOptionValue('durationIsPerItem', 0) == 0) { + $this->getLog()->debug('fetchDuration: CurrenciesAndStocksProvider: duration per item not set'); + return $this; + } + + $numItems = count(explode(',', $items)); + + $this->getLog()->debug('fetchDuration: CurrenciesAndStocksProvider: number of items: ' . $numItems); + + if ($numItems > 1) { + // If we have paging involved then work out the page count. + $itemsPerPage = $durationProvider->getWidget()->getOptionValue('itemsPerPage', 0); + if ($itemsPerPage > 0) { + $numItems = ceil($numItems / $itemsPerPage); + } + + $durationProvider->setDuration($durationProvider->getWidget()->calculatedDuration * $numItems); + } + return $this; + } + + public function getDataCacheKey(DataProviderInterface $dataProvider): ?string + { + return null; + } + + public function getDataModifiedDt(DataProviderInterface $dataProvider): ?Carbon + { + return null; + } +} diff --git a/lib/Widget/Provider/DataProviderInterface.php b/lib/Widget/Provider/DataProviderInterface.php index 2ceb15678f..f0c93434d0 100644 --- a/lib/Widget/Provider/DataProviderInterface.php +++ b/lib/Widget/Provider/DataProviderInterface.php @@ -1,6 +1,6 @@ $module->getPropertyValues(), 'isValid' => $widget->isValid === 1, 'isRepeatData' => $widget->getOptionValue('isRepeatData', 1) === 1, - 'duration' => $widget->duration, + 'duration' => $widget->useDuration ? $widget->duration : $module->defaultDuration, 'calculatedDuration' => $widget->calculatedDuration, 'isDataExpected' => $module->isDataProviderExpected(), ]; diff --git a/modules/currencies.xml b/modules/currencies.xml index 02abe80b1a..5b4e650fca 100755 --- a/modules/currencies.xml +++ b/modules/currencies.xml @@ -1,5 +1,5 @@