1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* COPS (Calibre OPDS PHP Server) class file |
4
|
|
|
* |
5
|
|
|
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html) |
6
|
|
|
* @author Sébastien Lucas <[email protected]> |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
// Silly thing because PHP forbid string concatenation in class const |
10
|
|
|
define ('SQL_BOOKS_LEFT_JOIN', 'left outer join comments on comments.book = books.id |
11
|
|
|
left outer join books_ratings_link on books_ratings_link.book = books.id |
12
|
|
|
left outer join ratings on books_ratings_link.rating = ratings.id '); |
13
|
|
|
define ('SQL_BOOKS_ALL', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' order by books.sort '); |
14
|
|
|
define ('SQL_BOOKS_BY_PUBLISHER', 'select {0} from books_publishers_link, books ' . SQL_BOOKS_LEFT_JOIN . ' |
15
|
|
|
where books_publishers_link.book = books.id and publisher = ? {1} order by publisher'); |
16
|
|
|
define ('SQL_BOOKS_BY_FIRST_LETTER', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' |
17
|
|
|
where upper (books.sort) like ? order by books.sort'); |
18
|
|
|
define ('SQL_BOOKS_BY_AUTHOR', 'select {0} from books_authors_link, books ' . SQL_BOOKS_LEFT_JOIN . ' |
19
|
|
|
left outer join books_series_link on books_series_link.book = books.id |
20
|
|
|
where books_authors_link.book = books.id and author = ? {1} order by series desc, series_index asc, pubdate asc'); |
21
|
|
|
define ('SQL_BOOKS_BY_SERIE', 'select {0} from books_series_link, books ' . SQL_BOOKS_LEFT_JOIN . ' |
22
|
|
|
where books_series_link.book = books.id and series = ? {1} order by series_index'); |
23
|
|
|
define ('SQL_BOOKS_BY_TAG', 'select {0} from books_tags_link, books ' . SQL_BOOKS_LEFT_JOIN . ' |
24
|
|
|
where books_tags_link.book = books.id and tag = ? {1} order by sort'); |
25
|
|
|
define ('SQL_BOOKS_BY_LANGUAGE', 'select {0} from books_languages_link, books ' . SQL_BOOKS_LEFT_JOIN . ' |
26
|
|
|
where books_languages_link.book = books.id and lang_code = ? {1} order by sort'); |
27
|
|
|
define ('SQL_BOOKS_BY_CUSTOM', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' |
28
|
|
|
where {2}.book = books.id and {2}.{3} = ? {1} order by sort'); |
29
|
|
|
define ('SQL_BOOKS_BY_CUSTOM_BOOL_TRUE', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' |
30
|
|
|
where {2}.book = books.id and {2}.value = 1 {1} order by sort'); |
31
|
|
|
define ('SQL_BOOKS_BY_CUSTOM_BOOL_FALSE', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' |
32
|
|
|
where {2}.book = books.id and {2}.value = 0 {1} order by sort'); |
33
|
|
|
define ('SQL_BOOKS_BY_CUSTOM_BOOL_NULL', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' |
34
|
|
|
where books.id not in (select book from {2}) {1} order by sort'); |
35
|
|
|
define ('SQL_BOOKS_BY_CUSTOM_RATING', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' |
36
|
|
|
left join {2} on {2}.book = books.id |
37
|
|
|
left join {3} on {3}.id = {2}.{4} |
38
|
|
|
where {3}.value = ? order by sort'); |
39
|
|
|
define ('SQL_BOOKS_BY_CUSTOM_RATING_NULL', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' |
40
|
|
|
left join {2} on {2}.book = books.id |
41
|
|
|
left join {3} on {3}.id = {2}.{4} |
42
|
|
|
where ((books.id not in (select {2}.book from {2})) or ({3}.value = 0)) {1} order by sort'); |
43
|
|
|
define ('SQL_BOOKS_BY_CUSTOM_DATE', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' |
44
|
|
|
where {2}.book = books.id and date({2}.value) = ? {1} order by sort'); |
45
|
|
|
define ('SQL_BOOKS_BY_CUSTOM_DIRECT', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' |
46
|
|
|
where {2}.book = books.id and {2}.value = ? {1} order by sort'); |
47
|
|
|
define ('SQL_BOOKS_BY_CUSTOM_DIRECT_ID', 'select {0} from {2}, books ' . SQL_BOOKS_LEFT_JOIN . ' |
48
|
|
|
where {2}.book = books.id and {2}.id = ? {1} order by sort'); |
49
|
|
|
define ('SQL_BOOKS_QUERY', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' |
50
|
|
|
where ( |
51
|
|
|
exists (select null from authors, books_authors_link where book = books.id and author = authors.id and authors.name like ?) or |
52
|
|
|
exists (select null from tags, books_tags_link where book = books.id and tag = tags.id and tags.name like ?) or |
53
|
|
|
exists (select null from series, books_series_link on book = books.id and books_series_link.series = series.id and series.name like ?) or |
54
|
|
|
exists (select null from publishers, books_publishers_link where book = books.id and books_publishers_link.publisher = publishers.id and publishers.name like ?) or |
55
|
|
|
title like ?) {1} order by books.sort'); |
56
|
|
|
define ('SQL_BOOKS_RECENT', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' |
57
|
|
|
where 1=1 {1} order by timestamp desc limit '); |
58
|
|
|
define ('SQL_BOOKS_BY_RATING', 'select {0} from books ' . SQL_BOOKS_LEFT_JOIN . ' |
59
|
|
|
where books_ratings_link.book = books.id and ratings.id = ? {1} order by sort'); |
60
|
|
|
|
61
|
|
|
require('Identifier.php'); |
62
|
|
|
|
63
|
|
|
class Book extends Base |
64
|
|
|
{ |
65
|
|
|
const ALL_BOOKS_UUID = 'urn:uuid'; |
66
|
|
|
const ALL_BOOKS_ID = 'cops:books'; |
67
|
|
|
const ALL_RECENT_BOOKS_ID = 'cops:recentbooks'; |
68
|
|
|
const BOOK_COLUMNS = 'books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index, uuid, has_cover, ratings.rating'; |
69
|
|
|
|
70
|
|
|
const SQL_BOOKS_LEFT_JOIN = SQL_BOOKS_LEFT_JOIN; |
71
|
|
|
const SQL_BOOKS_ALL = SQL_BOOKS_ALL; |
72
|
|
|
const SQL_BOOKS_BY_PUBLISHER = SQL_BOOKS_BY_PUBLISHER; |
73
|
|
|
const SQL_BOOKS_BY_FIRST_LETTER = SQL_BOOKS_BY_FIRST_LETTER; |
74
|
|
|
const SQL_BOOKS_BY_AUTHOR = SQL_BOOKS_BY_AUTHOR; |
75
|
|
|
const SQL_BOOKS_BY_SERIE = SQL_BOOKS_BY_SERIE; |
76
|
|
|
const SQL_BOOKS_BY_TAG = SQL_BOOKS_BY_TAG; |
77
|
|
|
const SQL_BOOKS_BY_LANGUAGE = SQL_BOOKS_BY_LANGUAGE; |
78
|
|
|
const SQL_BOOKS_BY_CUSTOM = SQL_BOOKS_BY_CUSTOM; |
79
|
|
|
const SQL_BOOKS_BY_CUSTOM_BOOL_TRUE = SQL_BOOKS_BY_CUSTOM_BOOL_TRUE; |
80
|
|
|
const SQL_BOOKS_BY_CUSTOM_BOOL_FALSE = SQL_BOOKS_BY_CUSTOM_BOOL_FALSE; |
81
|
|
|
const SQL_BOOKS_BY_CUSTOM_BOOL_NULL = SQL_BOOKS_BY_CUSTOM_BOOL_NULL; |
82
|
|
|
const SQL_BOOKS_BY_CUSTOM_RATING = SQL_BOOKS_BY_CUSTOM_RATING; |
83
|
|
|
const SQL_BOOKS_BY_CUSTOM_RATING_NULL = SQL_BOOKS_BY_CUSTOM_RATING_NULL; |
84
|
|
|
const SQL_BOOKS_BY_CUSTOM_DATE = SQL_BOOKS_BY_CUSTOM_DATE; |
85
|
|
|
const SQL_BOOKS_BY_CUSTOM_DIRECT = SQL_BOOKS_BY_CUSTOM_DIRECT; |
86
|
|
|
const SQL_BOOKS_BY_CUSTOM_DIRECT_ID = SQL_BOOKS_BY_CUSTOM_DIRECT_ID; |
87
|
|
|
const SQL_BOOKS_QUERY = SQL_BOOKS_QUERY; |
88
|
|
|
const SQL_BOOKS_RECENT = SQL_BOOKS_RECENT; |
89
|
|
|
const SQL_BOOKS_BY_RATING = SQL_BOOKS_BY_RATING; |
90
|
|
|
|
91
|
|
|
const BAD_SEARCH = 'QQQQQ'; |
92
|
|
|
|
93
|
|
|
public $id; |
94
|
|
|
public $title; |
95
|
|
|
public $timestamp; |
96
|
|
|
public $pubdate; |
97
|
|
|
public $path; |
98
|
|
|
public $uuid; |
99
|
|
|
public $hasCover; |
100
|
|
|
public $relativePath; |
101
|
|
|
public $seriesIndex; |
102
|
|
|
public $comment; |
103
|
|
|
public $rating; |
104
|
|
|
public $datas = NULL; |
105
|
|
|
public $authors = NULL; |
106
|
|
|
public $publisher = NULL; |
107
|
|
|
public $serie = NULL; |
108
|
|
|
public $tags = NULL; |
109
|
|
|
public $identifiers = NULL; |
110
|
|
|
public $languages = NULL; |
111
|
78 |
|
public $format = array (); |
112
|
78 |
|
|
113
|
78 |
|
|
114
|
78 |
|
public function __construct($line) { |
115
|
78 |
|
$this->id = $line->id; |
116
|
78 |
|
$this->title = $line->title; |
117
|
78 |
|
$this->timestamp = strtotime($line->timestamp); |
118
|
78 |
|
$this->pubdate = $line->pubdate; |
119
|
78 |
|
$this->path = Base::getDbDirectory() . $line->path; |
120
|
78 |
|
$this->relativePath = $line->path; |
121
|
78 |
|
$this->seriesIndex = $line->series_index; |
122
|
78 |
|
$this->comment = $line->comment; |
123
|
|
|
$this->uuid = $line->uuid; |
124
|
44 |
|
$this->hasCover = $line->has_cover; |
125
|
|
|
if (!file_exists($this->getFilePath('jpg'))) { |
126
|
78 |
|
// double check |
127
|
78 |
|
$this->hasCover = 0; |
128
|
|
|
} |
129
|
42 |
|
$this->rating = $line->rating; |
130
|
42 |
|
} |
131
|
|
|
|
132
|
|
|
public function getEntryId() { |
133
|
4 |
|
return self::ALL_BOOKS_UUID.':'.$this->uuid; |
134
|
4 |
|
} |
135
|
|
|
|
136
|
|
|
public static function getEntryIdByLetter ($startingLetter) { |
137
|
3 |
|
return self::ALL_BOOKS_ID.':letter:'.$startingLetter; |
138
|
3 |
|
} |
139
|
|
|
|
140
|
|
|
public function getUri () { |
141
|
3 |
|
return '?page='.parent::PAGE_BOOK_DETAIL.'&id=' . $this->id; |
142
|
3 |
|
} |
143
|
3 |
|
|
144
|
3 |
|
public function getDetailUrl () { |
145
|
|
|
$urlParam = $this->getUri(); |
146
|
|
View Code Duplication |
if (!is_null(GetUrlParam(DB))) $urlParam = addURLParameter($urlParam, DB, GetUrlParam (DB)); |
|
|
|
|
147
|
43 |
|
return 'index.php' . $urlParam; |
148
|
43 |
|
} |
149
|
|
|
|
150
|
|
|
public function getTitle () { |
151
|
|
|
return $this->title; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/* Other class (author, series, tag, ...) initialization and accessors */ |
155
|
|
|
|
156
|
49 |
|
/** |
157
|
49 |
|
* @return Author[] |
158
|
49 |
|
*/ |
159
|
|
|
public function getAuthors () { |
160
|
49 |
|
if (is_null($this->authors)) { |
161
|
|
|
$this->authors = Author::getAuthorByBookId($this->id); |
162
|
|
|
} |
163
|
|
|
return $this->authors; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
public function getAuthorsName () { |
167
|
|
|
return implode(', ', array_map(function ($author) { return $author->name; }, $this->getAuthors())); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
public function getAuthorsSort () { |
171
|
5 |
|
return implode(', ', array_map(function ($author) { return $author->sort; }, $this->getAuthors())); |
172
|
5 |
|
} |
173
|
5 |
|
|
174
|
|
|
public function getPublisher () { |
175
|
5 |
|
if (is_null($this->publisher)) { |
176
|
|
|
$this->publisher = Publisher::getPublisherByBookId($this->id); |
177
|
|
|
} |
178
|
|
|
return $this->publisher; |
179
|
|
|
} |
180
|
|
|
|
181
|
48 |
|
/** |
182
|
48 |
|
* @return Serie |
183
|
48 |
|
*/ |
184
|
|
|
public function getSerie() { |
185
|
48 |
|
if (is_null($this->serie)) { |
186
|
|
|
$this->serie = Serie::getSerieByBookId($this->id); |
187
|
|
|
} |
188
|
|
|
return $this->serie; |
189
|
|
|
} |
190
|
|
|
|
191
|
10 |
|
/** |
192
|
10 |
|
* @return string |
193
|
10 |
|
*/ |
194
|
|
|
public function getLanguages() { |
195
|
|
|
$lang = array(); |
196
|
|
|
$result = parent::getDb()->prepare('select languages.lang_code |
|
|
|
|
197
|
|
|
from books_languages_link, languages |
198
|
10 |
|
where books_languages_link.lang_code = languages.id |
199
|
10 |
|
and book = ? |
200
|
|
|
order by item_order'); |
201
|
10 |
|
$result->execute(array($this->id)); |
202
|
|
|
while ($post = $result->fetchObject()) |
203
|
10 |
|
{ |
204
|
|
|
array_push($lang, Language::getLanguageString($post->lang_code)); |
205
|
|
|
} |
206
|
|
|
return implode(', ', $lang); |
207
|
|
|
} |
208
|
|
|
|
209
|
10 |
|
/** |
210
|
10 |
|
* @return Tag[] |
211
|
10 |
|
*/ |
212
|
|
View Code Duplication |
public function getTags() { |
|
|
|
|
213
|
10 |
|
if (is_null ($this->tags)) { |
214
|
|
|
$this->tags = array(); |
215
|
|
|
|
216
|
|
|
$result = parent::getDb()->prepare('select tags.id as id, name |
|
|
|
|
217
|
|
|
from books_tags_link, tags |
218
|
10 |
|
where tag = tags.id |
219
|
10 |
|
and book = ? |
220
|
|
|
order by name'); |
221
|
9 |
|
$result->execute(array($this->id)); |
222
|
|
|
while ($post = $result->fetchObject()) |
223
|
|
|
{ |
224
|
10 |
|
array_push($this->tags, new Tag($post)); |
225
|
|
|
} |
226
|
|
|
} |
227
|
|
|
return $this->tags; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
public function getTagsName() { |
231
|
|
|
return implode(', ', array_map(function ($tag) { return $tag->name; }, $this->getTags())); |
232
|
|
|
} |
233
|
|
|
|
234
|
62 |
|
|
235
|
|
|
/** |
236
|
62 |
|
* @return Identifiers[] |
237
|
62 |
|
*/ |
238
|
|
View Code Duplication |
public function getIdentifiers() { |
|
|
|
|
239
|
62 |
|
if (is_null ($this->identifiers)) { |
240
|
|
|
$this->identifiers = array(); |
241
|
|
|
|
242
|
|
|
$result = parent::getDb()->prepare('select type, val, id |
|
|
|
|
243
|
|
|
from identifiers |
244
|
58 |
|
where book = ? |
245
|
58 |
|
order by type'); |
246
|
58 |
|
$result->execute(array($this->id)); |
247
|
|
|
while ($post = $result->fetchObject()) |
248
|
3 |
|
{ |
249
|
3 |
|
array_push($this->identifiers, new Identifier($post)); |
250
|
1 |
|
} |
251
|
1 |
|
|
252
|
|
|
} |
253
|
|
|
return $this->identifiers; |
254
|
3 |
|
} |
255
|
|
|
|
256
|
3 |
|
/** |
257
|
1 |
|
* @return Data[] |
258
|
|
|
*/ |
259
|
|
|
public function getDatas() |
260
|
3 |
|
{ |
261
|
|
|
if (is_null($this->datas)) { |
262
|
|
|
$this->datas = Data::getDataByBook($this); |
263
|
4 |
|
} |
264
|
|
|
return $this->datas; |
265
|
4 |
|
} |
266
|
4 |
|
|
267
|
4 |
|
/* End of other class (author, series, tag, ...) initialization and accessors */ |
268
|
4 |
|
|
269
|
4 |
|
public static function getFilterString() { |
270
|
4 |
|
$filter = getURLParam('tag', NULL); |
271
|
4 |
|
if (empty($filter)) return ''; |
272
|
4 |
|
|
273
|
|
|
$exists = true; |
274
|
|
|
if (preg_match("/^!(.*)$/", $filter, $matches)) { |
275
|
4 |
|
$exists = false; |
276
|
|
|
$filter = $matches[1]; |
277
|
|
|
} |
278
|
3 |
|
|
279
|
|
|
$result = 'exists (select null from books_tags_link, tags where books_tags_link.book = books.id and books_tags_link.tag = tags.id and tags.name = "' . $filter . '")'; |
280
|
|
|
|
281
|
3 |
|
if (!$exists) { |
282
|
3 |
|
$result = 'not ' . $result; |
283
|
3 |
|
} |
284
|
|
|
|
285
|
|
|
return 'and ' . $result; |
286
|
8 |
|
} |
287
|
8 |
|
|
288
|
3 |
|
public function GetMostInterestingDataToSendToKindle() |
289
|
|
|
{ |
290
|
5 |
|
$bestFormatForKindle = array('EPUB', 'PDF', 'AZW3', 'MOBI'); |
291
|
5 |
|
$bestRank = -1; |
292
|
5 |
|
$bestData = NULL; |
293
|
|
|
foreach ($this->getDatas() as $data) { |
294
|
5 |
|
$key = array_search($data->format, $bestFormatForKindle); |
295
|
3 |
|
if ($key !== false && $key > $bestRank) { |
296
|
|
|
$bestRank = $key; |
297
|
5 |
|
$bestData = $data; |
298
|
|
|
} |
299
|
|
|
} |
300
|
15 |
|
return $bestData; |
301
|
15 |
|
} |
302
|
2 |
|
|
303
|
|
|
public function getDataById($idData) |
304
|
13 |
|
{ |
305
|
13 |
|
$reduced = array_filter($this->getDatas(), function ($data) use ($idData) { |
306
|
12 |
|
return $data->id == $idData; |
307
|
|
|
}); |
308
|
1 |
|
return reset($reduced); |
309
|
|
|
} |
310
|
|
|
|
311
|
43 |
|
public function getRating() { |
312
|
43 |
|
if (is_null($this->rating) || $this->rating == 0) { |
313
|
43 |
|
return ''; |
314
|
43 |
|
} |
315
|
38 |
|
$retour = ''; |
316
|
|
|
for ($i = 0; $i < $this->rating / 2; $i++) { |
317
|
43 |
|
$retour .= '★'; |
318
|
|
|
} |
319
|
37 |
|
for ($i = 0; $i < 5 - $this->rating / 2; $i++) { |
320
|
|
|
$retour .= '☆'; |
321
|
|
|
} |
322
|
|
|
return $retour; |
323
|
31 |
|
} |
324
|
|
|
|
325
|
|
|
public function getPubDate() { |
326
|
|
|
if (empty ($this->pubdate)) { |
327
|
|
|
return ''; |
328
|
12 |
|
} |
329
|
12 |
|
$dateY = (int) substr($this->pubdate, 0, 4); |
330
|
12 |
|
if ($dateY > 102) { |
331
|
12 |
|
return str_pad($dateY, 4, '0', STR_PAD_LEFT); |
332
|
|
|
} |
333
|
|
|
return ''; |
334
|
78 |
|
} |
335
|
|
|
|
336
|
78 |
|
public function getComment($withSerie = true) { |
337
|
|
|
$addition = ''; |
338
|
78 |
|
$se = $this->getSerie (); |
339
|
|
|
if (!is_null ($se) && $withSerie) { |
340
|
|
|
$addition = $addition . '<strong>' . localize('content.series') . '</strong>' . str_format(localize('content.series.data'), $this->seriesIndex, htmlspecialchars($se->name)) . "<br />\n"; |
341
|
|
|
} |
342
|
2 |
|
return $addition . html2xhtml($this->comment); |
343
|
2 |
|
} |
344
|
2 |
|
|
345
|
|
|
public function getDataFormat($format) { |
346
|
|
|
$reduced = array_filter($this->getDatas(), function ($data) use ($format) { |
347
|
78 |
|
return $data->format == $format; |
348
|
|
|
}); |
349
|
3 |
|
return reset($reduced); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
public function getFilePath($extension, $idData = NULL, $relative = false) |
353
|
78 |
|
{ |
354
|
|
|
if ($extension == 'jpg') |
355
|
|
|
{ |
356
|
|
|
$file = 'cover.jpg'; |
357
|
|
|
} |
358
|
|
|
else |
359
|
|
|
{ |
360
|
|
|
$data = $this->getDataById($idData); |
361
|
|
|
if (!$data) return NULL; |
362
|
|
|
$file = $data->name . '.' . strtolower($data->format); |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
if ($relative) |
366
|
|
|
{ |
367
|
|
|
return $this->relativePath.'/'.$file; |
368
|
|
|
} |
369
|
|
|
else |
370
|
|
|
{ |
371
|
|
|
return $this->path.'/'.$file; |
372
|
|
|
} |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
public function getUpdatedEpub($idData) |
376
|
|
|
{ |
377
|
|
|
global $config; |
378
|
|
|
$data = $this->getDataById($idData); |
379
|
|
|
|
380
|
|
|
try |
381
|
|
|
{ |
382
|
|
|
$epub = new EPub($data->getLocalPath()); |
383
|
|
|
|
384
|
|
|
$epub->Title($this->title); |
385
|
|
|
$authorArray = array(); |
386
|
|
|
foreach ($this->getAuthors() as $author) { |
387
|
|
|
$authorArray[$author->sort] = $author->name; |
388
|
|
|
} |
389
|
|
|
$epub->Authors($authorArray); |
|
|
|
|
390
|
|
|
$epub->Language($this->getLanguages()); |
391
|
|
|
$epub->Description ($this->getComment(false)); |
392
|
|
|
$epub->Subjects($this->getTagsName()); |
|
|
|
|
393
|
|
|
$epub->Cover2($this->getFilePath('jpg'), 'image/jpeg'); |
|
|
|
|
394
|
|
|
$epub->Calibre($this->uuid); |
395
|
3 |
|
$se = $this->getSerie(); |
396
|
3 |
|
if (!is_null($se)) { |
397
|
1 |
|
$epub->Serie($se->name); |
398
|
|
|
$epub->SerieIndex($this->seriesIndex); |
399
|
|
|
} |
400
|
3 |
|
$filename = $data->getUpdatedFilenameEpub(); |
401
|
|
|
if ($config['cops_provide_kepub'] == '1' && preg_match('/Kobo/', $_SERVER['HTTP_USER_AGENT'])) { |
402
|
3 |
|
$epub->updateForKepub(); |
403
|
3 |
|
$filename = $data->getUpdatedFilenameKepub(); |
404
|
3 |
|
} |
405
|
|
|
$epub->download($filename); |
406
|
3 |
|
} |
407
|
2 |
|
catch (Exception $e) |
408
|
2 |
|
{ |
409
|
1 |
|
echo 'Exception : ' . $e->getMessage(); |
410
|
|
|
} |
411
|
2 |
|
} |
412
|
2 |
|
|
413
|
2 |
|
public function getThumbnail($width, $height, $outputfile = NULL) { |
414
|
|
|
if (is_null($width) && is_null($height)) { |
415
|
|
|
return false; |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
$file = $this->getFilePath('jpg'); |
419
|
|
|
// get image size |
420
|
2 |
|
if ($size = GetImageSize($file)) { |
421
|
2 |
|
$w = $size[0]; |
422
|
2 |
|
$h = $size[1]; |
423
|
2 |
|
//set new size |
424
|
2 |
|
if (!is_null($width)) { |
425
|
2 |
|
$nw = $width; |
426
|
|
|
if ($nw >= $w) { return false; } |
427
|
2 |
|
$nh = ($nw*$h)/$w; |
428
|
|
|
} else { |
429
|
|
|
$nh = $height; |
430
|
44 |
|
if ($nh >= $h) { return false; } |
431
|
|
|
$nw = ($nh*$w)/$h; |
432
|
44 |
|
} |
433
|
|
|
} else { |
434
|
44 |
|
return false; |
435
|
|
|
} |
436
|
18 |
|
|
437
|
|
|
//draw the image |
438
|
18 |
|
$src_img = imagecreatefromjpeg($file); |
439
|
|
|
$dst_img = imagecreatetruecolor($nw,$nh); |
440
|
|
|
imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $nw, $nh, $w, $h);//resizing the image |
441
|
44 |
|
imagejpeg($dst_img,$outputfile,80); |
442
|
|
|
imagedestroy($src_img); |
443
|
44 |
|
imagedestroy($dst_img); |
444
|
|
|
|
445
|
44 |
|
return true; |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
public function getLinkArray () |
449
|
44 |
|
{ |
450
|
|
|
$linkArray = array(); |
451
|
44 |
|
|
452
|
|
|
if ($this->hasCover) |
453
|
|
|
{ |
454
|
44 |
|
array_push($linkArray, Data::getLink($this, 'jpg', 'image/jpeg', Link::OPDS_IMAGE_TYPE, 'cover.jpg', NULL)); |
455
|
44 |
|
|
456
|
41 |
|
array_push($linkArray, Data::getLink($this, 'jpg', 'image/jpeg', Link::OPDS_THUMBNAIL_TYPE, 'cover.jpg', NULL)); |
457
|
|
|
} |
458
|
|
|
|
459
|
44 |
|
foreach ($this->getDatas() as $data) |
460
|
|
|
{ |
461
|
|
|
if ($data->isKnownType()) |
462
|
|
|
{ |
463
|
41 |
|
array_push($linkArray, $data->getDataLink(Link::OPDS_ACQUISITION_TYPE, $data->format)); |
464
|
41 |
|
} |
465
|
41 |
|
} |
466
|
41 |
|
|
467
|
|
|
foreach ($this->getAuthors() as $author) { |
468
|
|
|
/* @var $author Author */ |
469
|
3 |
|
array_push($linkArray, new LinkNavigation($author->getUri(), 'related', str_format(localize('bookentry.author'), localize('splitByLetter.book.other'), $author->name))); |
470
|
3 |
|
} |
471
|
|
|
|
472
|
|
|
$serie = $this->getSerie(); |
473
|
21 |
|
if (!is_null ($serie)) { |
474
|
21 |
|
array_push($linkArray, new LinkNavigation($serie->getUri(), 'related', str_format(localize('content.series.data'), $this->seriesIndex, $serie->name))); |
475
|
21 |
|
} |
476
|
21 |
|
|
477
|
21 |
|
return $linkArray; |
478
|
21 |
|
} |
479
|
21 |
|
|
480
|
21 |
|
|
481
|
21 |
|
public function getEntry() { |
482
|
21 |
|
return new EntryBook($this->getTitle(), $this->getEntryId(), |
483
|
21 |
|
$this->getComment(), 'text/html', |
484
|
21 |
|
$this->getLinkArray(), $this); |
485
|
21 |
|
} |
486
|
21 |
|
|
487
|
21 |
|
public static function getBookCount($database = NULL) { |
488
|
|
|
return parent::executeQuerySingle('select count(*) from books', $database); |
|
|
|
|
489
|
21 |
|
} |
490
|
|
|
|
491
|
|
|
public static function getCount() { |
492
|
8 |
|
global $config; |
493
|
8 |
|
$nBooks = parent::executeQuerySingle('select count(*) from books'); |
|
|
|
|
494
|
|
|
$result = array(); |
495
|
|
|
$entry = new Entry(localize('allbooks.title'), |
496
|
1 |
|
self::ALL_BOOKS_ID, |
497
|
1 |
|
str_format(localize('allbooks.alphabetical', $nBooks), $nBooks), 'text', |
498
|
|
|
array(new LinkNavigation('?page='.parent::PAGE_ALL_BOOKS)), '', $nBooks); |
499
|
|
|
array_push($result, $entry); |
500
|
2 |
|
if ($config['cops_recentbooks_limit'] > 0) { |
501
|
2 |
|
$entry = new Entry(localize('recent.title'), |
502
|
|
|
self::ALL_RECENT_BOOKS_ID, |
503
|
|
|
str_format(localize('recent.list'), $config['cops_recentbooks_limit']), 'text', |
504
|
2 |
|
array ( new LinkNavigation ('?page='.parent::PAGE_ALL_RECENT_BOOKS)), '', $config['cops_recentbooks_limit']); |
505
|
2 |
|
array_push($result, $entry); |
506
|
|
|
} |
507
|
|
|
return $result; |
508
|
2 |
|
} |
509
|
2 |
|
|
510
|
|
|
public static function getBooksByAuthor($authorId, $n) { |
511
|
|
|
return self::getEntryArray(self::SQL_BOOKS_BY_AUTHOR, array($authorId), $n); |
512
|
2 |
|
} |
513
|
2 |
|
|
514
|
|
|
public static function getBooksByRating($ratingId, $n) { |
515
|
|
|
return self::getEntryArray(self::SQL_BOOKS_BY_RATING, array($ratingId), $n); |
516
|
|
|
} |
517
|
|
|
|
518
|
|
|
public static function getBooksByPublisher($publisherId, $n) { |
519
|
|
|
return self::getEntryArray(self::SQL_BOOKS_BY_PUBLISHER, array($publisherId), $n); |
520
|
|
|
} |
521
|
|
|
|
522
|
4 |
|
public static function getBooksBySeries($serieId, $n) { |
523
|
4 |
|
return self::getEntryArray(self::SQL_BOOKS_BY_SERIE, array($serieId), $n); |
524
|
|
|
} |
525
|
4 |
|
|
526
|
|
|
public static function getBooksByTag($tagId, $n) { |
527
|
|
|
return self::getEntryArray(self::SQL_BOOKS_BY_TAG, array($tagId), $n); |
528
|
37 |
|
} |
529
|
37 |
|
|
530
|
37 |
|
public static function getBooksByLanguage($languageId, $n) { |
531
|
|
|
return self::getEntryArray(self::SQL_BOOKS_BY_LANGUAGE, array($languageId), $n); |
532
|
37 |
|
} |
533
|
37 |
|
|
534
|
|
|
/** |
535
|
36 |
|
* @param $customColumn CustomColumn |
536
|
36 |
|
* @param $id integer |
537
|
|
|
* @param $n integer |
538
|
1 |
|
* @return array |
539
|
|
|
*/ |
540
|
|
|
public static function getBooksByCustom($customColumn, $id, $n) { |
541
|
1 |
|
list($query, $params) = $customColumn->getQuery($id); |
542
|
1 |
|
|
543
|
1 |
|
return self::getEntryArray($query, $params, $n); |
544
|
|
|
} |
545
|
1 |
|
|
546
|
1 |
|
public static function getBookById($bookId) { |
547
|
|
|
$result = parent::getDb()->prepare('select ' . self::BOOK_COLUMNS . ' |
|
|
|
|
548
|
1 |
|
from books ' . self::SQL_BOOKS_LEFT_JOIN . ' |
549
|
1 |
|
where books.id = ?'); |
550
|
1 |
|
$result->execute(array($bookId)); |
551
|
1 |
|
while ($post = $result->fetchObject()) |
552
|
1 |
|
{ |
553
|
|
|
$book = new Book($post); |
554
|
|
|
return $book; |
555
|
|
|
} |
556
|
|
|
return NULL; |
557
|
2 |
|
} |
558
|
2 |
|
|
559
|
2 |
|
public static function getBookByDataId($dataId) { |
560
|
2 |
|
$result = parent::getDb()->prepare('select ' . self::BOOK_COLUMNS . ', data.name, data.format |
|
|
|
|
561
|
2 |
|
from data, books ' . self::SQL_BOOKS_LEFT_JOIN . ' |
562
|
2 |
|
where data.book = books.id and data.id = ?'); |
563
|
2 |
|
$result->execute(array($dataId)); |
564
|
2 |
|
while ($post = $result->fetchObject()) |
565
|
2 |
|
{ |
566
|
2 |
|
$book = new Book($post); |
567
|
|
|
$data = new Data($post, $book); |
568
|
|
|
$data->id = $dataId; |
569
|
|
|
$book->datas = array($data); |
570
|
2 |
|
return $book; |
571
|
|
|
} |
572
|
|
|
return NULL; |
573
|
2 |
|
} |
574
|
|
|
|
575
|
|
|
public static function getBooksByQuery($query, $n, $database = NULL, $numberPerPage = NULL) { |
576
|
2 |
|
$i = 0; |
577
|
|
|
$critArray = array(); |
578
|
2 |
|
foreach (array(PageQueryResult::SCOPE_AUTHOR, |
579
|
|
|
PageQueryResult::SCOPE_TAG, |
580
|
|
|
PageQueryResult::SCOPE_SERIES, |
581
|
1 |
|
PageQueryResult::SCOPE_PUBLISHER, |
582
|
1 |
|
PageQueryResult::SCOPE_BOOK) as $key) { |
583
|
1 |
|
if (in_array($key, getCurrentOption('ignored_categories')) || |
584
|
|
|
(!array_key_exists($key, $query) && !array_key_exists('all', $query))) { |
585
|
|
|
$critArray[$i] = self::BAD_SEARCH; |
586
|
3 |
|
} |
587
|
|
|
else { |
588
|
|
|
if (array_key_exists($key, $query)) { |
589
|
3 |
|
$critArray[$i] = $query[$key]; |
590
|
|
|
} else { |
591
|
|
|
$critArray[$i] = $query["all"]; |
592
|
3 |
|
} |
593
|
|
|
} |
594
|
3 |
|
$i++; |
595
|
3 |
|
} |
596
|
|
|
return self::getEntryArray(self::SQL_BOOKS_QUERY, $critArray, $n, $database, $numberPerPage); |
597
|
3 |
|
} |
598
|
3 |
|
|
599
|
3 |
|
public static function getBooks($n) { |
600
|
|
|
list ($entryArray, $totalNumber) = self::getEntryArray(self::SQL_BOOKS_ALL , array (), $n); |
601
|
3 |
|
return array($entryArray, $totalNumber); |
602
|
|
|
} |
603
|
|
|
|
604
|
25 |
View Code Duplication |
public static function getAllBooks() { |
|
|
|
|
605
|
25 |
|
/* @var $result PDOStatement */ |
606
|
|
|
|
607
|
|
|
list (, $result) = parent::executeQuery('select {0} |
|
|
|
|
608
|
55 |
|
from books |
609
|
|
|
group by substr (upper (sort), 1, 1) |
610
|
|
|
order by substr (upper (sort), 1, 1)', 'substr (upper (sort), 1, 1) as title, count(*) as count', self::getFilterString(), array(), -1); |
611
|
55 |
|
|
612
|
|
|
$entryArray = array(); |
613
|
55 |
|
while ($post = $result->fetchObject()) |
614
|
55 |
|
{ |
615
|
|
|
array_push($entryArray, new Entry($post->title, Book::getEntryIdByLetter($post->title), |
616
|
41 |
|
str_format(localize('bookword', $post->count), $post->count), 'text', |
617
|
41 |
|
array(new LinkNavigation('?page='.parent::PAGE_ALL_BOOKS_LETTER.'&id='. rawurlencode($post->title))), '', $post->count)); |
618
|
|
|
} |
619
|
55 |
|
return $entryArray; |
620
|
|
|
} |
621
|
|
|
|
622
|
5 |
|
public static function getBooksByStartingLetter($letter, $n, $database = NULL, $numberPerPage = NULL) { |
623
|
5 |
|
return self::getEntryArray(self::SQL_BOOKS_BY_FIRST_LETTER, array($letter . '%'), $n, $database, $numberPerPage); |
624
|
5 |
|
} |
625
|
5 |
|
|
626
|
|
|
public static function getEntryArray($query, $params, $n, $database = NULL, $numberPerPage = NULL) { |
627
|
|
|
/* @var $totalNumber integer */ |
628
|
|
|
/* @var $result PDOStatement */ |
629
|
|
|
list($totalNumber, $result) = parent::executeQuery($query, self::BOOK_COLUMNS, self::getFilterString(), $params, $n, $database, $numberPerPage); |
|
|
|
|
630
|
|
|
|
631
|
|
|
$entryArray = array(); |
632
|
|
|
while ($post = $result->fetchObject()) |
633
|
|
|
{ |
634
|
5 |
|
$book = new Book($post); |
635
|
5 |
|
array_push($entryArray, $book->getEntry()); |
636
|
|
|
} |
637
|
5 |
|
return array($entryArray, $totalNumber); |
638
|
2 |
|
} |
639
|
2 |
|
|
640
|
2 |
|
public static function getAllRecentBooks() { |
641
|
2 |
|
global $config; |
642
|
2 |
|
list ($entryArray, ) = self::getEntryArray(self::SQL_BOOKS_RECENT . $config['cops_recentbooks_limit'], array(), -1); |
643
|
1 |
|
return $entryArray; |
644
|
|
|
} |
645
|
2 |
|
|
646
|
|
|
/** |
647
|
|
|
* The values of all the specified columns |
648
|
|
|
* |
649
|
|
|
* @param string[] $columns |
650
|
|
|
* @return CustomColumn[] |
651
|
5 |
|
*/ |
652
|
|
|
public function getCustomColumnValues($columns, $asArray = false) { |
653
|
|
|
$result = array(); |
654
|
|
|
|
655
|
|
|
foreach ($columns as $lookup) { |
656
|
|
|
$col = CustomColumnType::createByLookup($lookup); |
657
|
|
|
if (!is_null($col)) { |
658
|
|
|
$cust = $col->getCustomByBook($this); |
659
|
|
|
if (!is_null($cust)) { |
660
|
|
|
if ($asArray) { |
661
|
|
|
array_push($result, $cust->toArray()); |
662
|
|
|
} else { |
663
|
|
|
array_push($result, $cust); |
664
|
|
|
} |
665
|
|
|
} |
666
|
|
|
} |
667
|
|
|
} |
668
|
|
|
|
669
|
|
|
return $result; |
670
|
|
|
} |
671
|
|
|
} |
672
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.