Completed
Push — master ( 87f5e0...117349 )
by Benjamin
05:50
created

AbTesting::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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