TagRepository::getOrCreate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Blog\Tag;
6
7
use App\Blog\Entity\Post;
8
use App\Blog\Entity\PostTag;
9
use App\Blog\Entity\Tag;
10
use App\Blog\Post\PostRepository;
11
use Cycle\ORM\ORMInterface;
12
use Cycle\ORM\Select;
13
use Cycle\ORM\Select\Repository;
14
use Yiisoft\Data\Reader\DataReaderInterface;
15
use Yiisoft\Data\Reader\Sort;
16
use Yiisoft\Yii\Cycle\Data\Reader\EntityReader;
17
18
final class TagRepository extends Repository
19
{
20
    private ORMInterface $orm;
21
22 1
    public function __construct(Select $select, ORMInterface $orm)
23
    {
24 1
        $this->orm = $orm;
25 1
        parent::__construct($select);
26 1
    }
27
28
    public function getOrCreate(string $label): Tag
29
    {
30
        $tag = $this->findByLabel($label);
31
        return $tag ?? new Tag($label);
32
    }
33
34
    public function findByLabel(string $label): ?Tag
35
    {
36
        return $this->select()
37
                    ->where(['label' => $label])
38
                    ->fetchOne();
39
    }
40
41
    /**
42
     * @param int $limit
43
     *
44
     * @return DataReaderInterface Collection of Array('label' => 'Tag Label', 'count' => '8')
45
     */
46 1
    public function getTagMentions(int $limit = 0): DataReaderInterface
47
    {
48
        /** @var Repository $postTagRepo */
49 1
        $postTagRepo = $this->orm->getRepository(PostTag::class);
50
        /** @var PostRepository $postRepo */
51 1
        $postRepo = $this->orm->getRepository(Post::class);
52
53
        // For example, below are several ways to make queries
54
        // As a result, we should get a list of most used tags
55
        // All SQL-queries received on mysql database. SQL-queries may vary by driver
56
57
        /**
58
         * Case 1 would look like:
59
         *
60
         * SELECT `t`.`label`, count(*) `count`
61
         * FROM `post_tag` AS `postTag`
62
         * INNER JOIN `post` AS `p`
63
         * ON `p`.`id` = `postTag`.`post_id` AND `p`.`public` = TRUE
64
         * INNER JOIN `tag` AS `t`
65
         * ON `t`.`id` = `postTag`.`tag_id`
66
         * GROUP BY `t`.`label`, `tag_id`
67
         * ORDER BY `count` DESC
68
         */
69
        $case1 = $postTagRepo
0 ignored issues
show
Unused Code introduced by
The assignment to $case1 is dead and can be removed.
Loading history...
70 1
            ->select()
71 1
            ->buildQuery()
72 1
            ->columns(['t.label', 'count(*) count'])
73 1
            ->innerJoin('post', 'p')->on('p.id', 'postTag.post_id')->onWhere(['p.public' => true])
74 1
            ->innerJoin('tag', 't')->on('t.id', 'postTag.tag_id')
75 1
            ->groupBy('t.label, tag_id');
76
77
        /**
78
         * Case 2 would look like:
79
         *
80
         * SELECT `label`, count(*) `count`
81
         * FROM `tag` AS `tag`
82
         * INNER JOIN `post_tag` AS `tag_posts_pivot`
83
         * ON `tag_posts_pivot`.`tag_id` = `tag`.`id`
84
         * INNER JOIN `post` AS `tag_posts`
85
         * ON `tag_posts`.`id` = `tag_posts_pivot`.`post_id` AND `tag_posts`.`public` = TRUE
86
         * GROUP BY `tag`.`label`, `tag_id`
87
         * ORDER BY `count` DESC
88
         */
89
        $case2 = $this
0 ignored issues
show
Unused Code introduced by
The assignment to $case2 is dead and can be removed.
Loading history...
90 1
            ->select()
91 1
            ->with('posts')
92 1
            ->buildQuery()
93 1
            ->columns(['label', 'count(*) count'])
94 1
            ->groupBy('tag.label, tag_id');
95
96
        /**
97
         * Case 3 would look like:
98
         *
99
         * SELECT `label`, count(*) `count`
100
         * FROM `tag` AS `tag`
101
         * INNER JOIN `post_tag` AS `tag_posts_pivot`
102
         * ON `tag_posts_pivot`.`tag_id` = `tag`.`id`
103
         * INNER JOIN `post` AS `tag_posts`
104
         * ON `tag_posts`.`id` = `tag_posts_pivot`.`post_id` AND `tag_posts`.`public` = TRUE
105
         * GROUP BY `tag_posts_pivot`.`tag_id`, `tag`.`label`
106
         * ORDER BY `count` DESC
107
         */
108
        $case3 = $this
109 1
            ->select()
110 1
            ->groupBy('[email protected]_id') // relation posts -> pivot (@) -> column
111 1
            ->groupBy('label')
112 1
            ->buildQuery()
113 1
            ->columns(['label', 'count(*) count']);
114
115
        /**
116
         * Case 4 would look like:
117
         *
118
         * SELECT `label`, count(*) `count`
119
         * FROM `post` AS `post`
120
         * INNER JOIN `post_tag` AS `post_tags_pivot`
121
         * ON `post_tags_pivot`.`post_id` = `post`.`id`
122
         * INNER JOIN `tag` AS `post_tags`
123
         * ON `post_tags`.`id` = `post_tags_pivot`.`tag_id`
124
         * WHERE `post`.`public` = TRUE
125
         * GROUP BY `post_tags_pivot`.`tag_id`, `tag`.`label`
126
         */
127
        $case4 = $postRepo
0 ignored issues
show
Unused Code introduced by
The assignment to $case4 is dead and can be removed.
Loading history...
128 1
            ->select()
129 1
            ->groupBy('[email protected]_id') // relation tags -> pivot (@) -> column
130 1
            ->groupBy('tags.label')
131 1
            ->buildQuery()
132 1
            ->columns(['label', 'count(*) count']);
133
134 1
        $sort = Sort::only(['count', 'label'])->withOrder(['count' => 'desc']);
135 1
        return (new EntityReader($case3))->withSort($sort)->withLimit($limit);
136
    }
137
}
138