/
Planner.php
148 lines (130 loc) · 4.98 KB
/
Planner.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php
namespace Concrete\Core\Board\Instance\Slot\Planner;
use Concrete\Core\Board\Instance\Slot\Content\ObjectCollection;
use Concrete\Core\Board\Instance\Slot\Template\AvailableTemplateCollectionFactory;
use Concrete\Core\Entity\Board\Instance;
use Concrete\Core\Entity\Board\SlotTemplate;
use Concrete\Core\Logging\Channels;
use Concrete\Core\Logging\LoggerAwareInterface;
use Concrete\Core\Logging\LoggerAwareTrait;
class Planner implements LoggerAwareInterface
{
const MAX_VERIFICATION_CHECKS = 15;
const VERIFICATION_FAILURE_LOGGING_THRESHOLD = 5; // At what point do we start logging high numbers of failures.
use LoggerAwareTrait;
public function getLoggerChannel()
{
return Channels::CHANNEL_CONTENT;
}
/**
* @var SlotFilterer
*/
protected $slotFilterer;
public function __construct(SlotFilterer $slotFilterer)
{
$this->slotFilterer = $slotFilterer;
}
protected function planSlot(
PlannedInstance $plannedInstance,
int $slot
): ?PlannedSlot {
$templateChoices = $this->slotFilterer->getPotentialSlotTemplates($plannedInstance, $slot);
if (count($templateChoices)) {
$selectedTemplate = $this->slotFilterer->findValidTemplateForSlot(
$plannedInstance,
$templateChoices,
$slot
);
if ($selectedTemplate) {
$plannedSlot = new PlannedSlot();
$plannedSlot->setSlot($slot);
$plannedSlot->setTemplate($selectedTemplate);
return $plannedSlot;
} else {
$this->logger->notice(
t(
'No template was able to be selected for slot {slot} on board instance {instance}. Total content objects remaining: {remaining}'
),
[
'slot' => $slot,
'instance' => $plannedInstance->getInstance()->getBoardInstanceID(),
'remaining' => count($plannedInstance->getContentObjectGroups())
]
);
}
} else {
$this->logger->notice(
t('While planning slot {slot} on board instance {instance}, no valid template choices were returned.'),
['slot' => $slot, 'instance' => $plannedInstance->getInstance()->getBoardInstanceID()]
);
}
return null;
}
protected function createPlannedInstance(
Instance $instance,
array $contentObjectGroups,
int $startingSlot,
int $totalSlots
): PlannedInstance {
$plannedInstance = new PlannedInstance($instance, $contentObjectGroups);
for ($slot = $startingSlot; $slot <= $totalSlots; $slot++) {
$plannedSlot = $this->planSlot($plannedInstance, $slot);
if ($plannedSlot) {
$plannedInstance->addPlannedSlot($plannedSlot);
}
}
return $plannedInstance;
}
protected function isValidInstance(PlannedInstance $plannedInstance): bool
{
$planner = $plannedInstance->getInstance()->getBoard()->getTemplate()->getDriver()->getLayoutPlanner();
if ($planner) {
return $planner->isValidInstance($plannedInstance);
}
return true;
}
/**
* @param Instance $instance
* @param array $contentObjectGroups
* @param int $startingSlot
* @param int $totalSlots
* @return PlannedInstance
*/
public function plan(
Instance $instance,
array $contentObjectGroups,
int $startingSlot,
int $totalSlots
): PlannedInstance {
$isValidInstance = null;
$verificationChecks = 0;
while ($isValidInstance !== true && $verificationChecks <= self::MAX_VERIFICATION_CHECKS) {
if ($verificationChecks > self::VERIFICATION_FAILURE_LOGGING_THRESHOLD) {
$this->logger->notice(
t(
'High number of board planner verification checks on board instance generation for instance {instance}. Current check: {checkNumber}'
),
['instance' => $instance->getBoardInstanceID(), 'checkNumber' => $verificationChecks]
);
}
$verificationChecks++;
$plannedInstance = $this->createPlannedInstance(
$instance,
$contentObjectGroups,
$startingSlot,
$totalSlots
);
$isValidInstance = $this->isValidInstance($plannedInstance);
}
if ($verificationChecks >= self::MAX_VERIFICATION_CHECKS) {
throw new \Exception(
t(
'Max verification checks limit of %s reached while generating board instance %s',
self::MAX_VERIFICATION_CHECKS,
$instance->getBoardInstanceID()
)
);
}
return $plannedInstance;
}
}