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