PointsService::getPointsModel()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Pbmedia\Gamification\Services;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Facades\Event;
9
use Pbmedia\Gamification\Events;
10
use Pbmedia\Gamification\Exceptions;
11
use Pbmedia\Gamification\Interfaces;
12
use Pbmedia\Gamification\Models\PointsModel;
13
14
class PointsService
15
{
16
    protected $earner;
17
18
    protected $rewarder;
19
20
    protected $item;
21
22
    protected $points;
23
24
    protected $pointsModel;
25
26
    public function __construct(PointsModel $pointsModel = null)
27
    {
28
        if ($pointsModel) {
29
            $this->pointsModel = $pointsModel;
30
31
            $this->setEarner($pointsModel->earner);
32
            $this->setRewarder($pointsModel->rewarder);
33
            $this->setItem($pointsModel->item);
34
            $this->setPoints($pointsModel->points);
35
        }
36
    }
37
38
    public function setEarner(Interfaces\CanEarnPointsInterface $earner)
39
    {
40
        $this->earner = $earner;
41
42
        return $this;
43
    }
44
45
    public function setRewarder(Interfaces\CanRewardPointsInterface $rewarder)
46
    {
47
        $this->rewarder = $rewarder;
48
49
        return $this;
50
    }
51
52
    public function setItem(Model $item)
53
    {
54
        $this->item = $item;
55
56
        return $this;
57
    }
58
59
    public function setPoints(int $points)
60
    {
61
        $this->points = $points;
62
63
        return $this;
64
    }
65
66
    public function getPointsModel()
67
    {
68
        return $this->pointsModel;
69
    }
70
71
    public function checkIfModelAttributesAreFilled()
72
    {
73
        if (!$this->earner) {
74
            throw new Exceptions\EarnerIsNotFilledException;
75
        }
76
77
        if (!$this->rewarder) {
78
            throw new Exceptions\RewarderIsNotFilledException;
79
        }
80
81
        if (!$this->item) {
82
            throw new Exceptions\ItemIsNotFilledException;
83
        }
84
85
        if (!$this->points) {
86
            throw new Exceptions\PointsAreNotFilledException;
87
        }
88
    }
89
90
    public function save()
91
    {
92
        $this->checkIfModelAttributesAreFilled();
93
94
        if (!$this->rewarderHasEnoughPoints()) {
95
            throw new Exceptions\RewarderHasNotEnoughPointsException;
96
        }
97
98
        $pointsToSubtractFromRewarder = $this->points;
99
100
        if (!$this->pointsModel) {
101
            $this->pointsModel = new PointsModel;
102
        } else {
103
            $pointsToSubtractFromRewarder += $this->pointsModel->points * -1;
104
        }
105
106
        $this->pointsModel->fill([
107
            'earner_id'     => $this->earner->getKey(),
0 ignored issues
show
Bug introduced by
The method getKey() does not seem to exist on object<Pbmedia\Gamificat...CanEarnPointsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
108
            'earner_type'   => $this->earner->getMorphClass(),
0 ignored issues
show
Bug introduced by
The method getMorphClass() does not seem to exist on object<Pbmedia\Gamificat...CanEarnPointsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
109
            'rewarder_id'   => $this->rewarder->getKey(),
0 ignored issues
show
Bug introduced by
The method getKey() does not seem to exist on object<Pbmedia\Gamificat...nRewardPointsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
110
            'rewarder_type' => $this->rewarder->getMorphClass(),
0 ignored issues
show
Bug introduced by
The method getMorphClass() does not seem to exist on object<Pbmedia\Gamificat...nRewardPointsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
111
            'item_id'       => $this->item->getKey(),
112
            'item_type'     => $this->item->getMorphClass(),
113
            'points'        => $this->points,
114
        ]);
115
116
        $this->pointsModel->save();
117
        $this->subtractPointsFromRewarder($pointsToSubtractFromRewarder);
118
119
        if ($this->pointsModel->wasRecentlyCreated) {
120
            Event::fire(new Events\PointsHasBeenRewarderdEvent($this->pointsModel));
121
        }
122
123
        $this->pointsModel = $this->pointsModel->fresh();
124
125
        return $this;
126
    }
127
128
    public function find(): Collection
129
    {
130
        return $this->getBuilder()->get();
131
    }
132
133
    public function getTotalPoints(): int
134
    {
135
        return $this->getBuilder()->sum('points');
136
    }
137
138
    protected function getBuilder(): Builder
139
    {
140
        $builder = PointsModel::query();
141
142
        if ($this->earner) {
143
            $builder->where('earner_id', $this->earner->getKey())
0 ignored issues
show
Bug introduced by
The method getKey() does not seem to exist on object<Pbmedia\Gamificat...CanEarnPointsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
144
                ->where('earner_type', $this->earner->getMorphClass());
0 ignored issues
show
Bug introduced by
The method getMorphClass() does not seem to exist on object<Pbmedia\Gamificat...CanEarnPointsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
145
        }
146
147
        if ($this->rewarder) {
148
            $builder->where('rewarder_id', $this->rewarder->getKey())
0 ignored issues
show
Bug introduced by
The method getKey() does not seem to exist on object<Pbmedia\Gamificat...nRewardPointsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
149
                ->where('rewarder_type', $this->rewarder->getMorphClass());
0 ignored issues
show
Bug introduced by
The method getMorphClass() does not seem to exist on object<Pbmedia\Gamificat...nRewardPointsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
150
        }
151
152
        if ($this->item) {
153
            $builder->where('item_id', $this->item->getKey())
154
                ->where('item_type', $this->item->getMorphClass());
155
        }
156
157
        if ($this->points) {
158
            $builder->where('points', $this->points);
159
        }
160
161
        return $builder;
162
    }
163
164
    public function delete(): Collection
165
    {
166
        return $this->find()->each(function ($pointsModel) {
167
            $rewarder = $pointsModel->rewarder;
168
169
            $pointsModel->delete();
170
171
            if ($rewarder instanceof Interfaces\HasLimitedPointsToRewardInterface) {
172
                $rewarder->addPointsToReward($pointsModel->points);
173
            }
174
175
            Event::fire(new Events\PointsHasBeenDeletedEvent($pointsModel));
176
        });
177
    }
178
179
    protected function rewarderHasEnoughPoints(): bool
180
    {
181
        if (!$this->rewarder instanceof Interfaces\HasLimitedPointsToRewardInterface) {
182
            return true;
183
        }
184
185
        return $this->rewarder->getTotalPointsToRewardLeft() >= $this->points;
186
    }
187
188
    protected function subtractPointsFromRewarder(int $pointsToSubtract): bool
189
    {
190
        if (!$this->rewarder instanceof Interfaces\HasLimitedPointsToRewardInterface) {
191
            return true;
192
        }
193
194
        return $this->rewarder->addPointsToReward($pointsToSubtract * -1);
195
    }
196
197
    public static function getTotalEarnedPointsByEarner(Interfaces\CanEarnPointsInterface $earned): int
198
    {
199
        return (new static )->setEarner($earned)->getTotalPoints();
200
    }
201
202
    public static function getTotalEarnedPointsByItem(Model $item): int
203
    {
204
        return (new static )->setItem($item)->getTotalPoints();
205
    }
206
207
    public static function getTotalRewardedPointsByRewarder(Interfaces\CanRewardPointsInterface $rewarder): int
208
    {
209
        return (new static )->setRewarder($rewarder)->getTotalPoints();
210
    }
211
}
212