1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
<?php
/**
* SmileyFavorites
*
* This model provides access to the favored smileys of an user.
*
* @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
* @category Stud.IP
* @package smiley
* @since 2.3
*
* @uses DBManager
* @uses Smiley
*/
class SmileyFavorites
{
/**
* Returns whether the ability to favor smiley is enabled.
*
* @return bool
*/
public static function isEnabled()
{
$state = null;
if ($state === null) {
$state = DBManager::get()
->query("SHOW COLUMNS FROM user_info LIKE 'smiley_favorite%'")
->fetchColumn();
}
return $state;
}
/**
* Returns a list of how often a smiley has been favored.
*
* @return Array Associative array with smiley name as key and according
* favored numbers as value
*/
public static function getUsage()
{
$usage = [];
$query = "SELECT user_id, smiley_favorite FROM user_info WHERE smiley_favorite != ''";
$statement = DBManager::get()->prepare($query);
$statement->execute([]);
$temp = $statement->fetchGrouped(PDO::FETCH_COLUMN);
foreach ($temp as $user_id => $favorite_string) {
$favorites = explode(',', $favorite_string);
$smileys = Smiley::getByIds($favorites);
foreach ($smileys as $smiley) {
if (!isset($usage[$smiley->name])) {
$usage[$smiley->name] = 0;
}
$usage[$smiley->name] += 1;
}
}
return $usage;
}
/**
* Garbage collector. Removes all smiley ids from the users' favorites
* that are no longer in the database.
*
* @return int Number of changed records
*/
public static function gc()
{
$smileys = Smiley::getGrouped('all', Smiley::FETCH_ID);
$query = "SELECT user_id, smiley_favorite FROM user_info WHERE smiley_favorite != ''";
$statement = DBManager::get()->prepare($query);
$statement->execute([]);
$temp = $statement->fetchGrouped(PDO::FETCH_COLUMN);
$changed = 0;
foreach ($temp as $user_id => $favorite_string) {
$old_favorites = explode(',', $favorite_string);
$new_favorites = array_intersect($smileys, $old_favorites);
if (count($old_favorites) > count($new_favorites)) {
$favorites = new self($user_id);
$favorites->set($new_favorites);
$changed += 1;
}
}
return $changed;
}
private $user_id;
private $favorites = [];
/**
* Initializes an user's favorites
*
* @param String $user_id Id of the user
*/
public function __construct($user_id)
{
$this->user_id = $user_id;
$query = "SELECT smiley_favorite FROM user_info WHERE user_id = ?";
$statement = DBManager::get()->prepare($query);
$statement->execute([$this->user_id]);
$favorite_string = $statement->fetchColumn() ?: '';
$this->favorites = explode(',', $favorite_string);
$this->favorites = array_filter($this->favorites);
}
/**
* Returns the user's favored smileys' ids.
*
* @return Array Ids of the smileys the user has vaored
*/
public function get()
{
return $this->favorites;
}
/**
* Updates the user's favored smileys.
*
* @param Array $favorites Ids of the user's favored smileys
*/
public function set($favorites = [])
{
$favorite_string = implode(',', $favorites);
if (mb_strlen($favorite_string) > 255) {
throw new OutOfBoundsException;
}
DBManager::get()
->prepare("UPDATE user_info SET smiley_favorite = ? WHERE user_id = ?")
->execute([$favorite_string, $this->user_id]);
$this->favorites = $favorites;
}
/**
* Returns whether the smiley with the given id is favored by the user.
*
* @param int $smiley_id Id of the smiley
* @return bool True if the smiley is favored by the user, false otherwise
*/
public function contain($smiley_id)
{
return in_array($smiley_id, $this->favorites);
}
/**
* Toggles whether a smiley is favored by the user. You can either provide
* an acutal state or omit the state to toggle the current state.
*
* @param int $smiley_id Id of the smiley to favor/disfavor
* @param mixed $favorite Either a boolean state or null to toggle current state
* @return bool True if the smiley is favored by the user, false otherwise
*/
public function toggle($smiley_id, $favorite = null)
{
if ($favorite === null) {
$favorite = !$this->contain($smiley_id);
}
$favorites = $this->favorites;
if ($favorite) {
$favorites[] = $smiley_id;
} else {
$favorites = array_diff($favorites, [$smiley_id]);
}
$this->set($favorites);
return $this->contain($smiley_id);
}
}
|