digital_signage_framework-2.3.x-dev/src/Plugin/DigitalSignageScheduleGenerator/Base.php
src/Plugin/DigitalSignageScheduleGenerator/Base.php
<?php
namespace Drupal\digital_signage_framework\Plugin\DigitalSignageScheduleGenerator;
use Drupal\digital_signage_framework\ContentSettingInterface;
use Drupal\digital_signage_framework\DefaultDuration;
use Drupal\digital_signage_framework\DefaultWeight;
use Drupal\digital_signage_framework\ScheduleGeneratorPluginBase;
use Drupal\digital_signage_framework\SequenceItem;
use Drupal\digital_signage_framework\WeightInterface;
/**
* Plugin implementation of the digital_signage_schedule_generator.
*
* @DigitalSignageScheduleGenerator(
* id = "default",
* label = @Translation("Default Schedule Generator"),
* description = @Translation("Default Schedule Generator provided by the core digital signage framework.")
* )
*/
class Base extends ScheduleGeneratorPluginBase {
/**
* {@inheritdoc}
*/
public function generate($device, $contentSettings): array {
$sequenceItems = [];
$criticalSequenceItems = [];
/** @var \Drupal\digital_signage_framework\ContentSettingInterface[] $nonCriticalEntities */
$nonCriticalEntities = [];
$nonChosenEntities = [];
// @todo use dependency injection
$duration = new DefaultDuration($this->settings);
$weight = new DefaultWeight($this->settings);
$weightSum = 0;
foreach ($contentSettings as $contentSetting) {
if ($contentSetting->isEnabled()) {
if ($contentSetting->isCritical()) {
$criticalSequenceItems[] = SequenceItem::create($contentSetting, $duration->getDurationByComplexity($contentSetting->getType()));
}
else {
$nonCriticalEntities[] = $contentSetting;
$nonChosenEntities[] = $contentSetting;
$weightSum += $weight->getWeightByPriority($contentSetting->getPriority());
}
}
}
$weightMap = $this->getWeightMap($nonCriticalEntities, $weight);
/** @var \Drupal\digital_signage_framework\ContentSettingInterface|null $contentEntityTmp */
$contentEntityTmp = NULL;
for ($i = 0; $i < $weightSum; $i++) {
$contentEntity = $this->getNonCriticalEntity($weightMap, $weightSum);
if ($contentEntityTmp !== NULL && $contentEntityTmp->getReverseEntityId() === $contentEntity->getReverseEntityId()) {
continue;
}
/* @noinspection SlowArrayOperationsInLoopInspection */
$sequenceItems = array_merge($sequenceItems, $criticalSequenceItems);
$contentEntityTmp = $contentEntity;
$sequenceItems[] = SequenceItem::create($contentEntity, $duration->getDurationByComplexity($contentEntity->getType()));
// Remove from non chosen entity array.
$key = array_search($contentEntity, $nonChosenEntities, TRUE);
unset($nonChosenEntities[$key]);
}
usort($nonChosenEntities, [$this, 'sortItemsByPriority']);
foreach ($nonChosenEntities as $nonChosenEntity) {
/* @noinspection SlowArrayOperationsInLoopInspection */
$sequenceItems = array_merge($sequenceItems, $criticalSequenceItems);
$sequenceItems[] = SequenceItem::create($nonChosenEntity, $duration->getDurationByComplexity($nonChosenEntity->getType()));
}
return $sequenceItems;
}
/**
* Sort by priority function for entities.
*
* @param \Drupal\digital_signage_framework\ContentSettingInterface $contentSetting
* The settings.
* @param \Drupal\digital_signage_framework\ContentSettingInterface $otherContentSetting
* The other settings.
*
* @return int
* 0, if both settings are equal, 1 if settings come after other settings,
* -1 otherwise.
*/
private function sortItemsByPriority(ContentSettingInterface $contentSetting, ContentSettingInterface $otherContentSetting): int {
if ($contentSetting->getPriority() === $otherContentSetting->getPriority()) {
return 0;
}
return ($contentSetting->getPriority() < $otherContentSetting->getPriority()) ? -1 : 1;
}
/**
* Returns a sequence item based on the given weight.
*
* @param \Drupal\digital_signage_framework\ContentSettingInterface[] $weightMap
* List of entities order by weight.
* @param int $weightSum
* Max weight.
*
* @return \Drupal\digital_signage_framework\ContentSettingInterface
* One of the entities.
*/
private function getNonCriticalEntity(array $weightMap, int $weightSum): ContentSettingInterface {
$randomNumber = rand(1, $weightSum);
foreach ($weightMap as $key => $value) {
if ($randomNumber <= $key) {
return $value;
}
}
return end($weightMap);
}
/**
* Returns a weighted array for entities.
*
* @param \Drupal\digital_signage_framework\ContentSettingInterface[] $nonCriticalEntities
* List of entities.
* @param \Drupal\digital_signage_framework\WeightInterface $weight
* The weight service.
*
* @return \Drupal\digital_signage_framework\ContentSettingInterface[]
* Ordered list of entities.
*/
private function getWeightMap(array $nonCriticalEntities, WeightInterface $weight): array {
$weightMap = [];
$calculatedSum = 0;
foreach ($nonCriticalEntities as $contentEntity) {
$relativeWeight = $weight->getWeightByPriority($contentEntity->getPriority());
$calculatedSum += $relativeWeight;
$weightMap[$calculatedSum] = $contentEntity;
}
return $weightMap;
}
}
