Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.33% covered (success)
97.33%
73 / 75
88.89% covered (warning)
88.89%
8 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
TsumegoButtonsQueryBuilder
97.30% covered (success)
97.30%
72 / 74
88.89% covered (warning)
88.89%
8 / 9
26
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
1 / 1
6
 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        $this->filterRanks();
49        $this->filterSets();
50        $this->filterTags();
51        $this->queryRank();
52        $this->queryTag();
53        $this->querySet($id);
54        $this->queryFavorites();
55        $this->queryPublished();
56    }
57
58    private function filterRanks(): void
59    {
60        if ($this->tsumegoFilters->query == 'difficulty') // we filter by ranks unless we query a specific difficulty
61            return;
62        $this->tsumegoFilters->filterRanks($this->query);
63    }
64
65    private function filterSets()
66    {
67        if ($this->tsumegoFilters->query == 'topics') // we filter by sets unless we query a specific set
68            return;
69        $this->tsumegoFilters->filterSets($this->query);
70    }
71
72    private function filterTags()
73    {
74        if ($this->tsumegoFilters->query == 'tags') // we filter by tags unless we query a specific tag
75            return;
76        $this->tsumegoFilters->filterTags($this->query);
77    }
78
79    private function queryRank()
80    {
81        if ($this->tsumegoFilters->query != 'difficulty')
82            return;
83        if (empty($_COOKIE['lastSet']))
84        {
85            // when we don't have lastSet, we fallback to showing by topics (the set of current tsumego)
86            $this->tsumegoFilters->query = 'topics';
87            return;
88        }
89        try
90        {
91            $ratingBounds = RatingBounds::coverRank($_COOKIE['lastSet'], '15k');
92            $ratingBounds->addQueryConditions($this->query);
93            $this->description = $_COOKIE['lastSet'] . ' are problems that have a rating ' . $ratingBounds->textualDescription() . '.';
94        }
95        catch (RatingParseException $e)
96        {
97            // when we get bad lastSet value, we fallback to showing by topics (the set of current tsumego)
98            $this->tsumegoFilters->query = 'topics';
99        }
100    }
101
102    private function queryTag()
103    {
104        if ($this->tsumegoFilters->query != 'tags')
105            return;
106
107        $currentTag = $_COOKIE['lastSet'] ?? '';
108        if (empty($currentTag))
109        {
110            $this->tsumegoFilters->query = 'topics';
111            return;
112        }
113
114        $tag = ClassRegistry::init('Tag')->find('first', ['conditions' => ['name' => $currentTag]]);
115        if (!$tag)
116        {
117            $this->tsumegoFilters->query = 'topics';
118            return;
119        }
120        $this->query->query .= ' LEFT JOIN tag_connection ON tag_connection.tsumego_id=tsumego.id';
121        $this->query->conditions[] = 'tag_connection.tag_id=' . $tag['Tag']['id'];
122    }
123
124    private function querySet($id)
125    {
126        if ($this->tsumegoFilters->query != 'topics')
127            return;
128        $this->query->conditions[] = '`set`.id=' . $id;
129    }
130
131    private function queryFavorites()
132    {
133        if ($this->tsumegoFilters->query != 'favorites')
134            return;
135        $this->query->query .= ' JOIN favorite ON `favorite`.user_id =' . Auth::getUserID() . ' AND favorite.tsumego_id = tsumego.id';
136        $this->query->orderBy = ['favorite.id ASC'];
137    }
138
139    private function queryPublished()
140    {
141        if ($this->tsumegoFilters->query != 'published')
142            return;
143        $this->query->query .= ' JOIN schedule ON `schedule`.tsumego_id = tsumego.id AND schedule.set_id = `set`.id';
144        $this->query->conditions[] = "`schedule`.date = '" . date('Y-m-d') . "'";
145    }
146}