Completed
Push — master ( 9eb681...ff1819 )
by Benjamin
06:13 queued 01:19
created

AbTesting::getExperiment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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