Completed
Push — master ( b0b22f...359b9b )
by Benjamin
06:27
created

AbTesting::completeGoal()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 12
cts 12
cp 1
rs 9.552
c 0
b 0
f 0
cc 4
nc 6
nop 1
crap 4
1
<?php
2
3
namespace Ben182\AbTesting;
4
5
use Ben182\AbTesting\Models\Goal;
6
use Illuminate\Support\Collection;
7
use Ben182\AbTesting\Models\Experiment;
8
use Ben182\AbTesting\Exceptions\InvalidConfiguration;
9
use Ben182\AbTesting\Events\ExperimentNewVisitor;
10
use Ben182\AbTesting\Events\GoalCompleted;
11
12
class AbTesting
13
{
14
    protected $experiments;
15
16
    const SESSION_KEY_EXPERIMENTS = 'ab_testing_experiment';
17
    const SESSION_KEY_GOALS = 'ab_testing_goals';
18
19 48
    public function __construct()
20
    {
21 48
        $this->experiments = new Collection;
22 48
    }
23
24 48
    protected function start()
25
    {
26 48
        $configExperiments = config('ab-testing.experiments');
27 48
        $configGoals = config('ab-testing.goals');
28
29 48
        if (count($configExperiments) !== count(array_unique($configExperiments))) {
30 3
            throw InvalidConfiguration::experiment();
31
        }
32
33 45
        if (count($configGoals) !== count(array_unique($configGoals))) {
34 3
            throw InvalidConfiguration::goal();
35
        }
36
37 42
        foreach ($configExperiments as $configExperiment) {
38 42
            $this->experiments[] = $experiment = Experiment::firstOrCreate([
39 42
                'name' => $configExperiment,
40
            ], [
41 42
                'visitors' => 0,
42
            ]);
43
44 42
            foreach ($configGoals as $configGoal) {
45 42
                $experiment->goals()->firstOrCreate([
46 42
                    'name' => $configGoal,
47
                ], [
48 42
                    'hit' => 0,
49
                ]);
50
            }
51
        }
52
53 42
        session([
54 42
            self::SESSION_KEY_GOALS => new Collection,
55
        ]);
56 42
    }
57
58 48
    public function pageview()
59
    {
60 48
        if (! session(self::SESSION_KEY_EXPERIMENTS)) {
61 48
            $this->start();
62 42
            $this->setNextExperiment();
63
64 42
            event(new ExperimentNewVisitor($this->getExperiment()));
65
        }
66 42
    }
67
68 42
    protected function setNextExperiment()
69
    {
70 42
        $next = $this->getNextExperiment();
71 42
        $next->incrementVisitor();
72
73 42
        session([
74 42
            self::SESSION_KEY_EXPERIMENTS => $next,
75
        ]);
76 42
    }
77
78 42
    protected function getNextExperiment()
79
    {
80 42
        $sorted = $this->experiments->sortBy('visitors');
81
82 42
        return $sorted->first();
83
    }
84
85 9
    public function isExperiment($name)
86
    {
87 9
        $this->pageview();
88
89 9
        return $this->getExperiment()->name === $name;
90
    }
91
92 15
    public function completeGoal($goal)
93
    {
94 15
        if (! $this->getExperiment()) {
95 12
            $this->pageview();
96
        }
97
98 15
        $goal = $this->getExperiment()->goals->where('name', $goal)->first();
99
100 15
        if (! $goal) {
101 3
            return false;
102
        }
103
104 12
        if (session(self::SESSION_KEY_GOALS)->contains($goal->id)) {
105 3
            return false;
106
        }
107
108 12
        session(self::SESSION_KEY_GOALS)->push($goal->id);
109
110 12
        $goal->incrementHit();
111 12
        event(new GoalCompleted($goal));
112
113 12
        return $goal;
114
    }
115
116 42
    public function getExperiment()
117
    {
118 42
        return session(self::SESSION_KEY_EXPERIMENTS);
119
    }
120
121 3
    public function getCompletedGoals()
122
    {
123 3
        if (! session(self::SESSION_KEY_GOALS)) {
124
            return false;
125
        }
126
127
        return session(self::SESSION_KEY_GOALS)->map(function ($goalId) {
128 3
            return Goal::find($goalId);
129 3
        });
130
    }
131
}
132