Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.40% covered (success)
97.40%
75 / 77
88.89% covered (warning)
88.89%
8 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
TsumegoButtonsQueryBuilder
97.37% covered (success)
97.37%
74 / 76
88.89% covered (warning)
88.89%
8 / 9
27
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
1 / 1
7
 filterRanks
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 filterSets
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 filterTags
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 queryRank
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 queryTag
83.33% covered (warning)
83.33%
10 / 12
0.00% covered (danger)
0.00%
0 / 1
4.07
 querySet
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 queryFavorites
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 queryPublished
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3App::uses('Query', 'Utility');
4
5class TsumegoButtonsQueryBuilder
6{
7    public Query $query;
8    public string $description = '';
9    private TsumegoFilters $tsumegoFilters;
10
11    public function __construct($tsumegoFilters, $id)
12    {
13        $this->query = new Query('FROM tsumego');
14        if ($tsumegoFilters->query != 'topics')
15        {
16            $this->query->selects[] = "ROW_NUMBER() OVER (PARTITION BY tsumego.id ORDER BY tsumego.id) AS rn";
17            $this->query->prefix = "SELECT tsumego_id, set_connection_id, num, rating";
18            if (Auth::isLoggedIn())
19                $this->query->prefix .= ", status";
20            $this->query->prefix .= " FROM (";
21            $this->query->suffix = ") x WHERE rn = 1 ORDER BY tsumego_id";
22            $this->query->orderBy[] = 'tsumego.id';
23        }
24        else
25            $this->query->orderBy[] = 'set_connection.num, set_connection.id';
26        $this->tsumegoFilters = $tsumegoFilters;
27
28        $this->query->selects[] = 'tsumego.id as tsumego_id';
29        $this->query->selects[] = 'tsumego.rating as rating';
30        $this->query->selects[] = 'set_connection.id as set_connection_id';
31        $this->query->selects[] = 'set_connection.num as num';
32        if (Auth::isLoggedIn())
33            $this->query->selects[] = 'tsumego_status.status as status';
34
35        $this->query->query .= " JOIN set_connection ON set_connection.tsumego_id = tsumego.id";
36        $this->query->conditions[] = 'tsumego.deleted is NULL';
37
38        // when I'm quering by topics (which means sets), and I'm viewing private set
39        // It means I explicitelly want to view that.
40        // In all other cases, private set is not included.
41        if ($tsumegoFilters->query != 'topics')
42            $this->query->conditions [] = '`set`.public = 1';
43
44        $this->query->query .= " JOIN `set` ON `set`.id=set_connection.set_id";
45        if (Auth::isLoggedIn())
46            $this->query->query .= ' LEFT JOIN tsumego_status ON tsumego_status.user_id = ' . Auth::getUserID() . ' AND tsumego_status.tsumego_id = tsumego.id';
47
48        if (!Auth::hasPremium())
49            $this->query->conditions[] = '`set`.premium = false';
50
51        $this->filterRanks();
52        $this->filterSets();
53        $this->filterTags();
54        $this->queryRank();
55        $this->queryTag();
56        $this->querySet($id);
57        $this->queryFavorites();
58        $this->queryPublished();
59    }
60
61    private function filterRanks(): void
62    {
63        if ($this->tsumegoFilters->query == 'difficulty') // we filter by ranks unless we query a specific difficulty
64            return;
65        $this->tsumegoFilters->filterRanks($this->query);
66    }
67
68    private function filterSets()
69    {
70        if ($this->tsumegoFilters->query == 'topics') // we filter by sets unless we query a specific set
71            return;
72        $this->tsumegoFilters->filterSets($this->query);
73    }
74
75    private function filterTags()
76    {
77        if ($this->tsumegoFilters->query == 'tags') // we filter by tags unless we query a specific tag
78            return;
79        $this->tsumegoFilters->filterTags($this->query);
80    }
81
82    private function queryRank()
83    {
84        if ($this->tsumegoFilters->query != 'difficulty')
85            return;
86        if (empty($_COOKIE['lastSet']))
87        {
88            // when we don't have lastSet, we fallback to showing by topics (the set of current tsumego)
89            $this->tsumegoFilters->query = 'topics';
90            return;
91        }
92        try
93        {
94            $ratingBounds = RatingBounds::coverRank($_COOKIE['lastSet'], '15k');
95            $ratingBounds->addQueryConditions($this->query);
96            $this->description = $_COOKIE['lastSet'] . ' are problems that have a rating ' . $ratingBounds->textualDescription() . '.';
97        }
98        catch (RatingParseException $e)
99        {
100            // when we get bad lastSet value, we fallback to showing by topics (the set of current tsumego)
101            $this->tsumegoFilters->query = 'topics';
102        }
103    }
104
105    private function queryTag()
106    {
107        if ($this->tsumegoFilters->query != 'tags')
108            return;
109
110        $currentTag = $_COOKIE['lastSet'] ?? '';
111        if (empty($currentTag))
112        {
113            $this->tsumegoFilters->query = 'topics';
114            return;
115        }
116
117        $tag = ClassRegistry::init('Tag')->find('first', ['conditions' => ['name' => $currentTag]]);
118        if (!$tag)
119        {
120            $this->tsumegoFilters->query = 'topics';
121            return;
122        }
123        $this->query->query .= ' LEFT JOIN tag_connection ON tag_connection.tsumego_id=tsumego.id';
124        $this->query->conditions[] = 'tag_connection.tag_id=' . $tag['Tag']['id'];
125    }
126
127    private function querySet($id)
128    {
129        if ($this->tsumegoFilters->query != 'topics')
130            return;
131        $this->query->conditions[] = '`set`.id=' . $id;
132    }
133
134    private function queryFavorites()
135    {
136        if ($this->tsumegoFilters->query != 'favorites')
137            return;
138        $this->query->query .= ' JOIN favorite ON `favorite`.user_id =' . Auth::getUserID() . ' AND favorite.tsumego_id = tsumego.id';
139        $this->query->orderBy = ['favorite.id ASC'];
140    }
141
142    private function queryPublished()
143    {
144        if ($this->tsumegoFilters->query != 'published')
145            return;
146        $this->query->query .= ' JOIN schedule ON `schedule`.tsumego_id = tsumego.id AND schedule.set_id = `set`.id';
147        $this->query->conditions[] = "`schedule`.date = '" . date('Y-m-d') . "'";
148    }
149}