Issues (28)

src/Reactant/Jobs/RebuildReactionAggregatesJob.php (1 issue)

Labels
Severity
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 ReactantInterface;
17
use Cog\Contracts\Love\Reactant\ReactionCounter\Models\ReactionCounter as ReactionCounterInterface;
18
use Cog\Contracts\Love\Reactant\ReactionTotal\Models\ReactionTotal as ReactionTotalInterface;
19
use Cog\Contracts\Love\ReactionType\Models\ReactionType as ReactionTypeInterface;
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 as ShouldQueueInterface;
26
use Illuminate\Foundation\Bus\Dispatchable;
27
28
final class RebuildReactionAggregatesJob implements
29
    ShouldQueueInterface
30
{
31
    use Dispatchable;
32
    use Queueable;
33
34
    private ReactantInterface $reactant;
35
36
    private ReactionTypeInterface | null $reactionType;
37
38
    public function __construct(
39
        ReactantInterface $reactant,
40
        ReactionTypeInterface | null $reactionType = null,
41
    ) {
42
        $this->reactant = $reactant;
43
        $this->reactionType = $reactionType;
44
    }
45
46
    public function handle(): void
47
    {
48
        $this->recountReactionCounters();
49
        $this->recountReactionTotal();
50
    }
51
52
    private function recountReactionCounters(): void
53
    {
54
        $this->resetCountersValues();
55
56
        $service = new ReactionCounterService($this->reactant);
57
58
        $reactions = $this->collectReactions();
59
        foreach ($reactions as $reaction) {
60
            $service->addReaction($reaction);
61
        }
62
    }
63
64
    private function recountReactionTotal(): void
65
    {
66
        $counters = $this->reactant->getReactionCounters();
67
68
        if (count($counters) === 0) {
69
            return;
70
        }
71
72
        $totalCount = ReactionTotal::COUNT_DEFAULT;
73
        $totalWeight = ReactionTotal::WEIGHT_DEFAULT;
74
75
        foreach ($counters as $counter) {
76
            $totalCount += $counter->getCount();
77
            $totalWeight += $counter->getWeight();
78
        }
79
80
        $reactionTotal = $this->findOrCreateReactionTotal();
81
82
        /** @var \Cog\Laravel\Love\Reactant\ReactionTotal\Models\ReactionTotal $reactionTotal */
83
        $reactionTotal->update([
84
            'count' => $totalCount,
85
            'weight' => $totalWeight,
86
        ]);
87
    }
88
89
    private function findOrCreateReactionTotal(): ReactionTotalInterface
90
    {
91
        $reactionTotal = $this->reactant->getReactionTotal();
92
93
        if ($reactionTotal instanceof NullReactionTotal) {
94
            $this->reactant->createReactionTotal();
95
            $reactionTotal = $this->reactant->getReactionTotal();
96
        }
97
98
        return $reactionTotal;
99
    }
100
101
    private function resetCountersValues(): void
102
    {
103
        $counters = $this->reactant->getReactionCounters();
104
105
        foreach ($counters as $counter) {
106
            if ($this->shouldNotAffectCounter($counter)) {
107
                continue;
108
            }
109
110
            /** @var \Cog\Laravel\Love\Reactant\ReactionCounter\Models\ReactionCounter $counter */
111
            $counter->update([
112
                'count' => ReactionCounter::COUNT_DEFAULT,
113
                'weight' => ReactionCounter::WEIGHT_DEFAULT,
114
            ]);
115
        }
116
    }
117
118
    /**
119
     * @return \Cog\Laravel\Love\Reaction\Models\Reaction[]|\Illuminate\Database\Eloquent\Collection
120
     */
121
    private function collectReactions(): iterable
122
    {
123
        /** @var \Illuminate\Database\Eloquent\Builder $query */
124
        $query = $this->reactant->reactions();
0 ignored issues
show
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

124
        /** @scrutinizer ignore-call */ 
125
        $query = $this->reactant->reactions();
Loading history...
125
126
        if ($this->reactionType !== null) {
127
            $query->where('reaction_type_id', $this->reactionType->getId());
128
        }
129
130
        return $query->get();
131
    }
132
133
    /**
134
     * Determine if counter should not be rebuilt.
135
     */
136
    private function shouldNotAffectCounter(
137
        ReactionCounterInterface $counter,
138
    ): bool {
139
        return $this->reactionType !== null
140
            && $counter->isNotReactionOfType($this->reactionType);
141
    }
142
}
143