1 | <?php |
||
29 | class Engine implements EngineInterface |
||
30 | { |
||
31 | /** |
||
32 | * A list with test bags. |
||
33 | * |
||
34 | * @var Bag[] |
||
35 | */ |
||
36 | public $tests = []; |
||
37 | |||
38 | /** |
||
39 | * The participation manager used to check if a user particiaptes. |
||
40 | * |
||
41 | * @var ManagerInterface |
||
42 | */ |
||
43 | private $participationManager; |
||
44 | |||
45 | /** |
||
46 | * The event dispatcher that dispatches events related to tests. |
||
47 | * |
||
48 | * @var DispatcherInterface |
||
49 | */ |
||
50 | private $dispatcher; |
||
51 | |||
52 | /** |
||
53 | * The default filter that is used when a test bag has no filter set. |
||
54 | * |
||
55 | * @var FilterInterface |
||
56 | */ |
||
57 | private $filter; |
||
58 | |||
59 | /** |
||
60 | * The default variant chooser that is used when a test bag has no variant chooser set. |
||
61 | * |
||
62 | * @var ChooserInterface |
||
63 | */ |
||
64 | private $chooser; |
||
65 | |||
66 | /** |
||
67 | * Locks the engine for further manipulaton |
||
68 | * |
||
69 | * @var boolean |
||
70 | */ |
||
71 | private $locked = false; |
||
72 | |||
73 | /** |
||
74 | * Initializes a new instance of this class. |
||
75 | * |
||
76 | * @param ManagerInterface $participationManager Handles the Participation state |
||
77 | * @param DispatcherInterface $dispatcher Dispatches events |
||
78 | * @param FilterInterface|null $filter The default filter to use if no filter is provided for the test. |
||
79 | * @param ChooserInterface|null $chooser The default chooser to use if no chooser is provided for the test. |
||
80 | */ |
||
81 | 17 | public function __construct( |
|
93 | |||
94 | /** |
||
95 | * {@inheritDoc} |
||
96 | */ |
||
97 | 1 | public function getTests() |
|
106 | |||
107 | /** |
||
108 | * {@inheritDoc} |
||
109 | * |
||
110 | * @param string $test The identifier of the test |
||
111 | */ |
||
112 | 2 | public function getTest($test) |
|
120 | |||
121 | /** |
||
122 | * {@inheritDoc} |
||
123 | * |
||
124 | * @param TestInterface $test |
||
125 | * @param array $options |
||
126 | * @param FilterInterface $filter |
||
127 | * @param ChooserInterface $chooser |
||
128 | */ |
||
129 | 14 | public function addTest( |
|
154 | |||
155 | /** |
||
156 | * {@inheritDoc} |
||
157 | */ |
||
158 | 12 | public function start() |
|
172 | |||
173 | /** |
||
174 | * Process the test bag |
||
175 | * |
||
176 | * @param Bag $bag |
||
177 | * |
||
178 | * @return bool true if the variant got executed, false otherwise |
||
179 | */ |
||
180 | 9 | private function handleTestBag(Bag $bag) |
|
181 | { |
||
182 | 9 | $test = $bag->getTest(); |
|
183 | |||
184 | 9 | $isParticipating = $this->participationManager->participates($test->getIdentifier()); |
|
185 | 9 | $testParticipation = $this->participationManager->getParticipatingVariant($test->getIdentifier()); |
|
186 | |||
187 | // Check if the user is marked as "do not participate". |
||
188 | 9 | if ($isParticipating && null === $testParticipation) { |
|
189 | 1 | $this->dispatcher->dispatch('phpab.participation.blocked', [$this, $bag]); |
|
190 | 1 | return; |
|
191 | } |
||
192 | |||
193 | // When the user does not participate at the test, let him participate. |
||
194 | 8 | if (!$isParticipating && !$bag->getParticipationFilter()->shouldParticipate()) { |
|
195 | // The user should not participate so let's set participation |
||
196 | // to null so he will not participate in the future, too. |
||
197 | 2 | $this->dispatcher->dispatch('phpab.participation.block', [$this, $bag]); |
|
198 | |||
199 | 2 | $this->participationManager->participate($test->getIdentifier(), null); |
|
200 | 2 | return; |
|
201 | } |
||
202 | |||
203 | // Let's try to recover a previously stored Variant |
||
204 | 6 | if ($isParticipating && $testParticipation !== null) { |
|
205 | 3 | $variant = $bag->getTest()->getVariant($testParticipation); |
|
206 | |||
207 | // If we managed to identify a Variant by a previously stored participation, do its magic again. |
||
208 | 3 | if ($variant instanceof VariantInterface) { |
|
209 | 2 | $this->activateVariant($bag, $variant); |
|
210 | 2 | return; |
|
211 | } |
||
212 | 1 | } |
|
213 | |||
214 | // Choose a variant for later usage. If the user should participate this one will be used |
||
215 | 4 | $chosen = $bag->getVariantChooser()->chooseVariant($test->getVariants()); |
|
216 | |||
217 | // Check if user participation should be blocked. Or maybe the variant does not exists anymore? |
||
218 | 4 | if (null === $chosen || !$test->getVariant($chosen->getIdentifier())) { |
|
219 | 3 | $this->dispatcher->dispatch('phpab.participation.variant_missing', [$this, $bag]); |
|
220 | |||
221 | 3 | $this->participationManager->participate($test->getIdentifier(), null); |
|
222 | 3 | return; |
|
223 | } |
||
224 | |||
225 | // Store the chosen variant so he will not switch between different states |
||
226 | 1 | $this->participationManager->participate($test->getIdentifier(), $chosen->getIdentifier()); |
|
227 | |||
228 | 1 | $this->activateVariant($bag, $chosen); |
|
229 | 1 | } |
|
230 | |||
231 | /** |
||
232 | * Runs the Variant and dispatches subscriptions |
||
233 | * |
||
234 | * @param Bag $bag |
||
235 | * @param VariantInterface $variant |
||
236 | */ |
||
237 | 3 | private function activateVariant(Bag $bag, VariantInterface $variant) |
|
243 | } |
||
244 |