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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
|
<?php
/**
* Clipboard.class.php - model class for a clipboard (Merkzettel)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* @author Moritz Strohm <strohm@data-quest.de>
* @copyright 2018-2019
* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
* @category Stud.IP
* @since 4.5
*/
/**
* The Clipboard class extends the wish list functionality of the clipboard
* in the old literature management to allow it to be used in other areas of the
* Stud.IP system. Furthermore, clipboards managed by this class
* are stored permanently in the database until they are deleted.
*
* @property string id database column
* @property string user_id database column
* @property string name database column: The name of the clipboard.
* @property string allowed_item_class database column: The StudipItem class
* name where items have to be children of in order to be used
* with the clipboard.
* This attribute defaults to 'StudipItem' which means that by default
* all implementations of StudipItem can be inserted into a clipboard.
* If only items of a special implementation of StudipItem shall be
* able to be inserted into the clipboard this attribute has to be set
* to the class name of that implementation.
* @property string mkdate database column
* @property string chdate database column
* @property SimpleORMapCollection user belongs_to User
* @property SimpleORMapCollection items has_many WishListItem
*/
class Clipboard extends SimpleORMap
{
protected static function configure($config = [])
{
$config['db_table'] = 'clipboards';
$config['belongs_to']['user'] = [
'class_name' => User::class,
'foreign_key' => 'user_id',
'assoc_func' => 'find'
];
$config['has_many']['items'] = [
'class_name' => ClipboardItem::class,
'assoc_foreign_key' => 'clipboard_id',
'on_delete' => 'delete',
'on_store' => 'store'
];
parent::configure($config);
}
/**
* This class returns all clipboards for a specified user,
* optionally filtered by required item range types.
*
* @param string $user_id: The ID of the user whose clipboards
* shall be returned.
* @param array $item_range_types: The range types which at least one item
* of the clipboard must have to be included in the result set.
*
* @returns Clipboard[] An array of clipboard objects which are
* associated with the user specified by $user_id.
*/
public static function getClipboardsForUser($user_id = '', $item_range_types = [])
{
if (!$user_id) {
return [];
}
if (is_array($item_range_types) and count($item_range_types) > 0) {
return self::findBySql(
"INNER JOIN clipboard_items
ON clipboards.id = clipboard_items.clipboard_id
WHERE
clipboards.user_id = :user_id
AND
clipboard_items.range_type IN ( :range_types )
GROUP BY clipboards.id ORDER BY name ASC, mkdate ASC",
[
'user_id' => $user_id,
'range_types' => $item_range_types
]
);
} else {
return self::findBySql(
'user_id = :user_id ORDER BY name ASC, mkdate ASC',
[
'user_id' => $user_id
]
);
}
}
/**
* Adds an item to the clipboard by specifying the
* ID of the object that shall be added to it.
*
* @param string $range_id The ID of the object that shall be added.
*
* @throws ClipboardException If an error occurs.
*
* @returns ClipboardItem A ClipboardItem instance on success,
* false on failure.
*/
public function addItem($range_id = null, $range_type = 'StudipItem')
{
if (($range_id === null) or !is_a($range_type, 'StudipItem', true)) {
//Either the range_id is not set or the range_type does not
//name a StudipItem class.
throw new ClipboardException(
_('Die Daten zum Hinzufügen eines Eintrags sind ungültig!')
);
}
//Check if the item already exists:
$item = ClipboardItem::findOneBySql(
'clipboard_id = :clipboard_id
AND range_id = :range_id
AND range_type = :range_type',
[
'clipboard_id' => $this->id,
'range_id' => $range_id,
'range_type' => $range_type
]
);
if ($item) {
//Item already exists and nothing has to be modified.
return $item;
}
//Item does not exist: create it.
$item = new ClipboardItem();
$item->clipboard_id = $this->id;
$item->range_id = $range_id;
$item->range_type = $range_type;
if (!$item->store()) {
throw new ClipboardException(
_('Fehler beim Speichern des Eintrags!')
);
}
return $item;
}
/**
* Removes an item from the clipboard by specifying the ID of the
* object that shall be removed from the pad.
*
* @param string $range_id The ID of the object that shall be removed.
*
* @returns bool True on success, false on failure.
*/
public function removeItem($range_id = null)
{
if ($range_id === null) {
//The range_id is not set.
return false;
}
return ClipboardItem::deleteBySql(
'clipboard_id = :clipboard_id AND range_id = :range_id',
[
'clipboard_id' => $this->id,
'range_id' => $range_id
]
) > 0;
}
/**
* Formats the content of the clipboard for display.
* This method should be overloaded by derived classes
* to output the data of the clipboard with appropriate names
* and other attributes which may be needed.
*
* @returns string[][] A two-dimensional array with strings.
* The first dimension represents the list of clipboard items.
* The second dimension represents an item and holds at least
* the following attributes of the item: id, name.
* These attributes are the keys of the second array dimension.
* The array has the following structure:
* [
* [
* 'id' => (id of the item)
* 'name' => (name of the item)
* ],
* [
* …
* ]
* ]
*
* Derived classes may add further attributes to the array,
* if necessary.
*/
public function getContent()
{
if (!$this->items) {
return [];
}
$content = [];
foreach ($this->items as $item) {
//Only those elements which store the IDs of objects
//from the allowed content class or its descendants
//are added to the $content array.
if (is_a($item->range_type, $this->allowed_item_class, true)) {
$content[] = [
'id' => $item->id,
'range_type' => $item->range_type,
'range_id' => $item->range_id,
'name' => $item->__toString()
];
}
}
return $content;
}
/**
* Retrieves all range-IDs of objects that are associated
* with this clipboard. The objects can be filtered by their
* range type.
*
* @param string|string[] $range_types The class name(s) of the objects
* which shall be included in the result set.
* This parameter can be a string or an array of strings.
*
* @returns string[] An array with all range-IDs that match
* the specified range type.
*/
public function getAllRangeIds($range_types = 'StudipItem')
{
if (!$range_types) {
//If no range types are specified we cannot retrieve range-IDs:
return [];
}
if (!is_array($range_types)) {
//Make $range_types an array:
$range_types = [$range_types];
}
$db = DBManager::get();
$stmt = $db->prepare(
"SELECT range_id FROM clipboard_items
WHERE range_type IN ( :range_types )
AND clipboard_id = :clipboard_id;"
);
$stmt->execute(
[
'range_types' => $range_types,
'clipboard_id' => $this->id
]
);
return $stmt->fetchAll(
PDO::FETCH_COLUMN,
0
);
}
/**
* Retrieves specific range-IDs of objects that are associated
* with this clipboard and referenced by the specified clipboard item-IDs.
* The objects can be filtered by their range type, too.
*
* @param string|string[] $range_types The class name(s) of the objects
* which shall be included in the result set. This parameter
* can be an array or a string.
*
* @param string[] $item_ids The item-IDs of the clipboard items
* whose range-IDs shall be included in the result set.
* Note that the clipboard items must be associated with this clipboard.
*
* @returns string[] An array with all range-IDs that match
* the specified range type.
*/
public function getSomeRangeIds($range_types = 'StudipItem', $item_ids = [])
{
if ((!is_array($item_ids) and !$item_ids) or !$range_types) {
//Item-IDs is either an array or empty or it isn't even an array
//or $range_types is not set.
//We cannot use it to retrieve range-IDs.
return [];
}
$db = DBManager::get();
if (!is_array($range_types)) {
//Make $range_types an array:
$range_types = [$range_types];
}
$stmt = $db->prepare(
"SELECT range_id FROM clipboard_items
WHERE range_type IN ( :range_types )
AND clipboard_id = :clipboard_id
AND id IN ( :item_ids );"
);
$stmt->execute(
[
'range_types' => $range_types,
'clipboard_id' => $this->id,
'item_ids' => $item_ids
]
);
return $stmt->fetchAll(
PDO::FETCH_COLUMN,
0
);
}
}
|