|
1
|
|
|
<?php defined('BASEPATH') or exit('No direct script access allowed'); |
|
2
|
|
|
|
|
3
|
|
|
class TrackerInline extends Auth_Controller { |
|
4
|
|
|
private $userID; |
|
5
|
|
|
|
|
6
|
7 |
|
public function __construct() { |
|
7
|
7 |
|
parent::__construct(FALSE); |
|
8
|
|
|
|
|
9
|
|
|
$this->load->library('vendor/Limiter'); |
|
10
|
|
|
$this->load->library('form_validation'); |
|
11
|
|
|
|
|
12
|
|
|
//1000 requests per hour to either AJAX request. |
|
13
|
|
|
if($this->limiter->limit('tracker_general', 1000)) { |
|
14
|
|
|
$this->output->set_status_header('429', 'Rate limit reached'); //rate limited reached |
|
15
|
|
|
exit(); |
|
|
|
|
|
|
16
|
|
|
} |
|
17
|
|
|
|
|
18
|
|
|
$this->userID = (int) $this->User->id; |
|
19
|
|
|
} |
|
20
|
|
|
|
|
21
|
|
|
/** |
|
22
|
|
|
* Used locally to update the users' latest read chapter of a series. |
|
23
|
|
|
* |
|
24
|
|
|
* REQ_PARAMS: id, chapter |
|
25
|
|
|
* METHOD: POST |
|
26
|
|
|
* URL: /ajax/update_inline |
|
27
|
|
|
*/ |
|
28
|
|
View Code Duplication |
public function update() { |
|
29
|
|
|
$this->form_validation->set_rules('id', 'Chapter ID', 'required|ctype_digit'); |
|
30
|
|
|
$this->form_validation->set_rules('chapter', 'Chapter', 'required'); |
|
31
|
|
|
|
|
32
|
|
|
if($this->form_validation->run() === TRUE) { |
|
33
|
|
|
$success = $this->Tracker->list->updateByID($this->userID, $this->input->post('id'), $this->input->post('chapter')); |
|
34
|
|
|
if($success) { |
|
35
|
|
|
$this->output->set_status_header('200'); //Success! |
|
36
|
|
|
} else { |
|
37
|
|
|
$this->output->set_status_header('400', 'Unable to update?'); |
|
38
|
|
|
} |
|
39
|
|
|
} else { |
|
40
|
|
|
$this->output->set_status_header('400', 'Missing/invalid parameters.'); |
|
41
|
|
|
} |
|
42
|
|
|
} |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* Used locally to remove (multiple) series from a users' list. |
|
46
|
|
|
* |
|
47
|
|
|
* REQ_PARAMS: id[] |
|
48
|
|
|
* METHOD: POST |
|
49
|
|
|
* URL: /ajax/delete_inline |
|
50
|
|
|
*/ |
|
51
|
|
|
public function delete() { |
|
52
|
|
|
$this->form_validation->set_rules('id[]', 'List of IDs', 'required|ctype_digit'); |
|
53
|
|
|
|
|
54
|
|
|
if($this->form_validation->run() === TRUE) { |
|
55
|
|
|
$status = $this->Tracker->list->deleteByIDList($this->input->post('id[]')); |
|
56
|
|
|
switch($status['code']) { |
|
57
|
|
|
case 0: |
|
58
|
|
|
$this->output->set_status_header('200'); //Success! |
|
59
|
|
|
break; |
|
60
|
|
|
case 1: |
|
61
|
|
|
$this->output->set_status_header('400', 'Request contains invalid IDs'); |
|
62
|
|
|
break; |
|
63
|
|
|
case 2: |
|
64
|
|
|
$this->output->set_status_header('400', 'Request contains invalid elements.'); |
|
65
|
|
|
break; |
|
66
|
|
|
} |
|
67
|
|
|
} else { |
|
68
|
|
|
$this->output->set_status_header('400', 'Request contained invalid elements!'); |
|
69
|
|
|
} |
|
70
|
|
|
} |
|
71
|
|
|
|
|
72
|
|
|
/** |
|
73
|
|
|
* Used to import a tracker exported list. |
|
74
|
|
|
* |
|
75
|
|
|
* REQ_PARAMS: json |
|
76
|
|
|
* METHOD: POST |
|
77
|
|
|
* URL: /import_list |
|
78
|
|
|
*/ |
|
79
|
|
View Code Duplication |
public function import() { |
|
80
|
|
|
$this->form_validation->set_rules('json', 'JSON String', 'required|is_valid_json'); |
|
81
|
|
|
|
|
82
|
|
|
if($this->form_validation->run() === TRUE) { |
|
83
|
|
|
$status = $this->Tracker->portation->importFromJSON($this->input->post('json')); |
|
84
|
|
|
switch($status['code']) { |
|
85
|
|
|
case 0: |
|
86
|
|
|
$this->output->set_status_header('200'); //Success |
|
87
|
|
|
break; |
|
88
|
|
|
case 1: |
|
89
|
|
|
$this->output->set_status_header('400', 'JSON contains invalid keys'); |
|
90
|
|
|
break; |
|
91
|
|
|
case 2: |
|
92
|
|
|
$this->output->set_status_header('400', 'Unable to add some rows from JSON'); |
|
93
|
|
|
//$this->_render_json(json_encode($status['failed_rows'])); //TODO: We should list what rows these are. |
|
94
|
|
|
break; |
|
95
|
|
|
} |
|
96
|
|
|
} else { |
|
97
|
|
|
if(!$this->form_validation->isRuleValid('is_valid_json')) { |
|
98
|
|
|
$this->output->set_status_header('400', 'File isn\'t valid JSON!'); |
|
99
|
|
|
} else { |
|
100
|
|
|
$this->output->set_status_header('400', 'No file sent'); |
|
101
|
|
|
} |
|
102
|
|
|
} |
|
103
|
|
|
} |
|
104
|
|
|
|
|
105
|
|
|
/** |
|
106
|
|
|
* Used to export a users' list. |
|
107
|
|
|
* |
|
108
|
|
|
* REQ_PARAMS: N/A |
|
109
|
|
|
* METHOD: GET/POST |
|
110
|
|
|
* URL: /export_list |
|
111
|
|
|
*/ |
|
112
|
|
|
public function export() { |
|
113
|
|
|
$trackerData = $this->Tracker->portation->export(); |
|
114
|
|
|
$this->_render_json($trackerData, TRUE); |
|
115
|
|
|
} |
|
116
|
|
|
|
|
117
|
|
|
/** |
|
118
|
|
|
* Used to set chapter user tags |
|
119
|
|
|
* |
|
120
|
|
|
* REQ_PARAMS: id, tag_string |
|
121
|
|
|
* METHOD: POST |
|
122
|
|
|
* URL: /tag_update |
|
123
|
|
|
*/ |
|
124
|
|
|
public function tag_update() { |
|
125
|
|
|
$this->form_validation->set_rules('id', 'Chapter ID', 'required|ctype_digit'); |
|
126
|
|
|
$this->form_validation->set_rules('tag_string', 'Tag String', 'max_length[255]|is_valid_tag_string|not_equals[none]'); |
|
127
|
|
|
|
|
128
|
|
|
if($this->form_validation->run() === TRUE) { |
|
129
|
|
|
$tag_string = $this->_clean_tag_string($this->input->post('tag_string')); |
|
130
|
|
|
|
|
131
|
|
|
$success = $this->Tracker->tag->updateByID($this->userID, $this->input->post('id'), $tag_string); |
|
132
|
|
|
if($success) { |
|
133
|
|
|
$this->output->set_status_header('200'); //Success! |
|
134
|
|
|
} else { |
|
135
|
|
|
$this->output->set_status_header('400', 'Unable to set tags?'); |
|
136
|
|
|
} |
|
137
|
|
|
} else { |
|
138
|
|
|
$errorArr = $this->form_validation->error_array(); |
|
139
|
|
|
if(in_array('max_length', $errorArr)) { |
|
140
|
|
|
$this->output->set_status_header('400', 'Tag string is too long! Max length is 255 characters.'); |
|
141
|
|
|
} else if(in_array('not_equals', $errorArr)) { |
|
142
|
|
|
$this->output->set_status_header('400', '"none" is a restricted tag.'); |
|
143
|
|
|
} else if(in_array('is_valid_tag_string', $errorArr)) { |
|
144
|
|
|
$this->output->set_status_header('400', 'Tags can only contain: lowercase a-z, 0-9, -, :, & _. They can also only have one MAL metatag.'); |
|
145
|
|
|
} else { |
|
146
|
|
|
$this->output->set_status_header('400', 'Missing/invalid parameters.'); |
|
147
|
|
|
} |
|
148
|
|
|
} |
|
149
|
|
|
} |
|
150
|
|
|
private function _clean_tag_string(string $tag_string) { |
|
151
|
|
|
$tag_array = explode(',', $tag_string); |
|
152
|
|
|
$tag_array = array_unique($tag_array); |
|
153
|
|
|
$tag_array = array_filter($tag_array); |
|
154
|
|
|
|
|
155
|
|
|
return implode(',', $tag_array); |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* Used to set chapter user category |
|
160
|
|
|
* |
|
161
|
|
|
* REQ_PARAMS: id[], category |
|
162
|
|
|
* METHOD: POST |
|
163
|
|
|
* URL: /set_category |
|
164
|
|
|
*/ |
|
165
|
|
View Code Duplication |
public function set_category() { |
|
166
|
|
|
$this->form_validation->set_rules('id[]', 'List of IDs', 'required|ctype_digit'); |
|
167
|
|
|
$this->form_validation->set_rules('category', 'Category Name', 'required|is_valid_category'); |
|
168
|
|
|
|
|
169
|
|
|
if($this->form_validation->run() === TRUE) { |
|
170
|
|
|
$status = $this->Tracker->category->setByIDList($this->input->post('id[]'), $this->input->post('category')); |
|
171
|
|
|
switch($status['code']) { |
|
172
|
|
|
case 0: |
|
173
|
|
|
$this->output->set_status_header('200'); //Success! |
|
174
|
|
|
break; |
|
175
|
|
|
case 1: |
|
176
|
|
|
$this->output->set_status_header('400', 'Request contains invalid IDs'); |
|
177
|
|
|
break; |
|
178
|
|
|
case 2: |
|
179
|
|
|
$this->output->set_status_header('400', 'Request contains invalid category.'); |
|
180
|
|
|
break; |
|
181
|
|
|
} |
|
182
|
|
|
} else { |
|
183
|
|
|
$this->output->set_status_header('400', 'Request contained invalid elements!'); |
|
184
|
|
|
} |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
/** |
|
188
|
|
|
* Used to permanently hide the current notice. |
|
189
|
|
|
* |
|
190
|
|
|
* REQ_PARAMS: [none] |
|
191
|
|
|
* METHOD: POST |
|
192
|
|
|
* URL: /ajax/hide_notice |
|
193
|
|
|
*/ |
|
194
|
|
|
public function hide_notice() { |
|
195
|
|
|
$status = $this->User->hideLatestNotice(); |
|
|
|
|
|
|
196
|
|
|
if($this->User->hideLatestNotice()) { |
|
197
|
|
|
$this->output->set_status_header('200'); //Success! |
|
198
|
|
|
} else { |
|
199
|
|
|
$this->output->set_status_header('400', 'Something went wrong'); |
|
200
|
|
|
} |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
|
|
204
|
|
|
/** |
|
205
|
|
|
* Used locally to ignore the latest chapter of a series so it doesn't clog up the current unread list. |
|
206
|
|
|
* |
|
207
|
|
|
* REQ_PARAMS: id, chapter |
|
208
|
|
|
* METHOD: POST |
|
209
|
|
|
* URL: /ajax/ignore_inline |
|
210
|
|
|
*/ |
|
211
|
|
View Code Duplication |
public function ignore() { |
|
212
|
|
|
$this->form_validation->set_rules('id', 'Chapter ID', 'required|ctype_digit'); |
|
213
|
|
|
$this->form_validation->set_rules('chapter', 'Chapter', 'required'); |
|
214
|
|
|
|
|
215
|
|
|
if($this->form_validation->run() === TRUE) { |
|
216
|
|
|
$success = $this->Tracker->list->ignoreByID($this->userID, $this->input->post('id'), $this->input->post('chapter')); |
|
217
|
|
|
if($success) { |
|
218
|
|
|
$this->output->set_status_header('200'); //Success! |
|
219
|
|
|
} else { |
|
220
|
|
|
$this->output->set_status_header('400', 'Unable to ignore?'); |
|
221
|
|
|
} |
|
222
|
|
|
} else { |
|
223
|
|
|
$this->output->set_status_header('400', 'Missing/invalid parameters.'); |
|
224
|
|
|
} |
|
225
|
|
|
} |
|
226
|
|
|
|
|
227
|
|
|
/** |
|
228
|
|
|
* Used to set MAL ID |
|
229
|
|
|
* |
|
230
|
|
|
* REQ_PARAMS: id, mal_id |
|
231
|
|
|
* METHOD: POST |
|
232
|
|
|
* URL: /set_mal_id |
|
233
|
|
|
*/ |
|
234
|
|
|
public function set_mal_id() { |
|
235
|
|
|
$this->form_validation->set_rules('id', 'Chapter ID', 'required|ctype_digit'); |
|
236
|
|
|
$this->form_validation->set_rules('mal_id', 'MAL ID', 'regex_match[/^[0-9]*$/]'); |
|
237
|
|
|
|
|
238
|
|
|
if($this->form_validation->run() === TRUE) { |
|
239
|
|
|
$malID = (is_numeric($this->input->post('mal_id')) ? $this->input->post('mal_id') : NULL); |
|
240
|
|
|
$success = $this->Tracker->list->setMalID($this->userID, $this->input->post('id'), $malID); |
|
241
|
|
|
if($success) { |
|
242
|
|
|
$this->output->set_status_header('200'); //Success! |
|
243
|
|
|
} else { |
|
244
|
|
|
$this->output->set_status_header('400', 'Unable to set MAL ID?'); |
|
245
|
|
|
} |
|
246
|
|
|
} else { |
|
247
|
|
|
$errorArr = $this->form_validation->error_array(); |
|
248
|
|
|
if(in_array('regex_match', $errorArr)) { |
|
249
|
|
|
$this->output->set_status_header('400', 'MAL id must be numeric or null.'); |
|
250
|
|
|
} else { |
|
251
|
|
|
$this->output->set_status_header('400', 'Missing/invalid parameters.'); |
|
252
|
|
|
} |
|
253
|
|
|
} |
|
254
|
|
|
} |
|
255
|
|
|
} |
|
256
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exitexpression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.