Completed
Pull Request — master (#148)
by Anton
03:36
created

RebuildAggregatesJob::resetCountersValues()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 13
rs 10
cc 3
nc 3
nop 0
1
<?php
2
3
/*
4
 * This file is part of Laravel Love.
5
 *
6
 * (c) Anton Komarev <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cog\Laravel\Love\Reactant\Jobs;
15
16
use Cog\Contracts\Love\Reactant\Models\Reactant as ReactantContract;
17
use Cog\Contracts\Love\Reactant\ReactionCounter\Models\ReactionCounter as ReactionCounterContract;
18
use Cog\Contracts\Love\Reactant\ReactionTotal\Models\ReactionTotal as ReactionTotalContract;
19
use Cog\Contracts\Love\ReactionType\Models\ReactionType as ReactionTypeContract;
20
use Cog\Laravel\Love\Reactant\ReactionCounter\Models\ReactionCounter;
21
use Cog\Laravel\Love\Reactant\ReactionCounter\Services\ReactionCounterService;
22
use Cog\Laravel\Love\Reactant\ReactionTotal\Models\NullReactionTotal;
23
use Cog\Laravel\Love\Reactant\ReactionTotal\Models\ReactionTotal;
24
use Illuminate\Bus\Queueable;
25
use Illuminate\Contracts\Queue\ShouldQueue;
26
use Illuminate\Foundation\Bus\Dispatchable;
27
28
final class RebuildAggregatesJob implements
29
    ShouldQueue
30
{
31
    use Dispatchable;
32
    use Queueable;
33
34
    /**
35
     * @var \Cog\Contracts\Love\Reactant\Models\Reactant
36
     */
37
    private $reactant;
38
39
    /**
40
     * @var \Cog\Contracts\Love\ReactionType\Models\ReactionType|null
41
     */
42
    private $reactionType;
43
44
    /**
45
     * @param \Cog\Contracts\Love\Reactant\Models\Reactant $reactant
46
     * @param \Cog\Contracts\Love\ReactionType\Models\ReactionType|null $reactionType
47
     */
48
    public function __construct(
49
        ReactantContract $reactant,
50
        ?ReactionTypeContract $reactionType = null
51
    ) {
52
        $this->reactant = $reactant;
53
        $this->reactionType = $reactionType;
54
    }
55
56
    public function handle(
57
    ): void {
58
        $this->recountCounters($this->reactant);
59
        $this->recountTotal($this->reactant);
60
    }
61
62
    private function recountTotal(
63
        ReactantContract $reactant
64
    ): void {
65
        $counters = $reactant->getReactionCounters();
66
67
        if (count($counters) === 0) {
68
            return;
69
        }
70
71
        $totalCount = ReactionTotal::COUNT_DEFAULT;
72
        $totalWeight = ReactionTotal::WEIGHT_DEFAULT;
73
74
        foreach ($counters as $counter) {
75
            $totalCount += $counter->getCount();
76
            $totalWeight += $counter->getWeight();
77
        }
78
79
        $reactionTotal = $this->findOrCreateReactionTotal($reactant);
80
81
        /** @var \Cog\Laravel\Love\Reactant\ReactionTotal\Models\ReactionTotal $reactionTotal */
82
        $reactionTotal->update([
83
            'count' => $totalCount,
84
            'weight' => $totalWeight,
85
        ]);
86
    }
87
88
    private function recountCounters(
89
        ReactantContract $reactant
90
    ): void {
91
        $this->resetCountersValues();
92
93
        $service = new ReactionCounterService($reactant);
94
95
        $reactions = $this->collectReactions();
96
        foreach ($reactions as $reaction) {
97
            $service->addReaction($reaction);
98
        }
99
    }
100
101
    /**
102
     * @param \Cog\Contracts\Love\Reactant\Models\Reactant $reactant
103
     * @return \Cog\Contracts\Love\Reactant\ReactionTotal\Models\ReactionTotal
104
     */
105
    private function findOrCreateReactionTotal(
106
        ReactantContract $reactant
107
    ): ReactionTotalContract {
108
        $reactionTotal = $reactant->getReactionTotal();
109
110
        if ($reactionTotal instanceof NullReactionTotal) {
111
            $reactant->createReactionTotal();
112
            $reactionTotal = $reactant->getReactionTotal();
113
        }
114
115
        return $reactionTotal;
116
    }
117
118
    /**
119
     * @return void
120
     */
121
    private function resetCountersValues(
122
    ): void {
123
        $counters = $this->reactant->getReactionCounters();
124
125
        foreach ($counters as $counter) {
126
            if ($this->shouldNotAffectCounter($counter)) {
127
                continue;
128
            }
129
130
            /** @var \Cog\Laravel\Love\Reactant\ReactionCounter\Models\ReactionCounter $counter */
131
            $counter->update([
132
                'count' => ReactionCounter::COUNT_DEFAULT,
133
                'weight' => ReactionCounter::WEIGHT_DEFAULT,
134
            ]);
135
        }
136
    }
137
138
    /**
139
     * Determine if counter should not be rebuilt.
140
     *
141
     * @param ReactionCounterContract $counter
142
     * @return bool
143
     */
144
    private function shouldNotAffectCounter(
145
        ReactionCounterContract $counter
146
    ): bool
147
    {
148
        return $this->reactionType !== null
149
            && $counter->isNotReactionOfType($this->reactionType);
150
    }
151
152
    /**
153
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
154
     */
155
    private function collectReactions(
156
    ): iterable {
157
        /** @var \Illuminate\Database\Eloquent\Builder $query */
158
        $query = $this->reactant->reactions();
0 ignored issues
show
Bug introduced by
The method reactions() does not exist on Cog\Contracts\Love\Reactant\Models\Reactant. It seems like you code against a sub-type of Cog\Contracts\Love\Reactant\Models\Reactant such as Cog\Laravel\Love\Reactant\Models\Reactant. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
        /** @scrutinizer ignore-call */ 
159
        $query = $this->reactant->reactions();
Loading history...
159
160
        if ($this->reactionType !== null) {
161
            $query->where('reaction_type_id', $this->reactionType->getId());
162
        }
163
164
        return $query->get();
165
    }
166
}
167