Completed
Pull Request — master (#238)
by
unknown
04:22
created

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
define ("VERSION", "1.0.0RC4");
10
define ("DB", "db");
11
date_default_timezone_set($config['default_timezone']);
12
13
14
function useServerSideRendering () {
15 3
    global $config;
16 3
    return preg_match("/" . $config['cops_server_side_render'] . "/", $_SERVER['HTTP_USER_AGENT']);
17
}
18
19
function serverSideRender ($data) {
20
    // Get the templates
21 2
    $theme = getCurrentTemplate ();
22 2
    $header = file_get_contents('templates/' . $theme . '/header.html');
23 2
    $footer = file_get_contents('templates/' . $theme . '/footer.html');
24 2
    $main = file_get_contents('templates/' . $theme . '/main.html');
25 2
    $bookdetail = file_get_contents('templates/' . $theme . '/bookdetail.html');
26 2
    $page = file_get_contents('templates/' . $theme . '/page.html');
27
28
    // Generate the function for the template
29 2
    $template = new doT ();
30 2
    $dot = $template->template ($page, array ("bookdetail" => $bookdetail,
31 2
                                              "header" => $header,
32 2
                                              "footer" => $footer,
33 2
                                              "main" => $main));
34
    // If there is a syntax error in the function created
35
    // $dot will be equal to FALSE
36 2
    if (!$dot) {
37
        return FALSE;
38
    }
39
    // Execute the template
40 2
    if (!empty ($data)) {
41
        return $dot ($data);
42
    }
43
44 2
    return NULL;
45
}
46
47
function getQueryString () {
48 18
    if ( isset($_SERVER['QUERY_STRING']) ) {
49 16
        return $_SERVER['QUERY_STRING'];
50
    }
51 2
    return "";
52
}
53
54
function notFound () {
55
    header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
56
    header("Status: 404 Not Found");
57
58
    $_SERVER['REDIRECT_STATUS'] = 404;
59
}
60
61
function getURLParam ($name, $default = NULL) {
62 101
    if (!empty ($_GET) && isset($_GET[$name]) && $_GET[$name] != "") {
63 24
        return $_GET[$name];
64
    }
65 101
    return $default;
66
}
67
68
function getCurrentOption ($option) {
69 87
    global $config;
70 87
    if (isset($_COOKIE[$option])) {
71 2
        if (isset($config ["cops_" . $option]) && is_array ($config ["cops_" . $option])) {
72
            return explode (",", $_COOKIE[$option]);
73
        } else {
74 2
            return $_COOKIE[$option];
75
        }
76
    }
77 85
    if ($option == "style") {
78 2
        return "default";
79
    }
80
81 85
    if (isset($config ["cops_" . $option])) {
82 85
        return $config ["cops_" . $option];
83
    }
84
85
    return "";
86
}
87
88
function getCurrentCss () {
89 2
    return "templates/" . getCurrentTemplate () . "/styles/style-" . getCurrentOption ("style") . ".css";
90
}
91
92
function getCurrentTemplate () {
93 4
    return getCurrentOption ("template");
94
}
95
96
function getUrlWithVersion ($url) {
97 50
    return $url . "?v=" . VERSION;
98
}
99
100
function xml2xhtml($xml) {
101 35
    return preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', create_function('$m', '
102
        $xhtml_tags = array("br", "hr", "input", "frame", "img", "area", "link", "col", "base", "basefont", "param");
103
        return in_array($m[1], $xhtml_tags) ? "<$m[1]$m[2] />" : "<$m[1]$m[2]></$m[1]>";
104 35
    '), $xml);
105
}
106
107
function display_xml_error($error)
108
{
109
    $return = "";
110
    $return .= str_repeat('-', $error->column) . "^\n";
111
112
    switch ($error->level) {
113
        case LIBXML_ERR_WARNING:
114
            $return .= "Warning $error->code: ";
115
            break;
116
         case LIBXML_ERR_ERROR:
117
            $return .= "Error $error->code: ";
118
            break;
119
        case LIBXML_ERR_FATAL:
120
            $return .= "Fatal Error $error->code: ";
121
            break;
122
    }
123
124
    $return .= trim($error->message) .
125
               "\n  Line: $error->line" .
126
               "\n  Column: $error->column";
127
128
    if ($error->file) {
129
        $return .= "\n  File: $error->file";
130
    }
131
132
    return "$return\n\n--------------------------------------------\n\n";
133
}
134
135
function are_libxml_errors_ok ()
136
{
137 35
    $errors = libxml_get_errors();
138
139 35
    foreach ($errors as $error) {
140
        if ($error->code == 801) return false;
141 35
    }
142 35
    return true;
143
}
144
145
function html2xhtml ($html) {
146 35
    $doc = new DOMDocument();
147 35
    libxml_use_internal_errors(true);
148
149 35
    $doc->loadHTML('<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body>' .
150 35
                        $html  . '</body></html>'); // Load the HTML
151 35
    $output = $doc->saveXML($doc->documentElement); // Transform to an Ansi xml stream
152 35
    $output = xml2xhtml($output);
153 35
    if (preg_match ('#<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></meta></head><body>(.*)</body></html>#ms', $output, $matches)) {
154 35
        $output = $matches [1]; // Remove <html><body>
155 35
    }
156
    /*
157
    // In case of error with summary, use it to debug
158
    $errors = libxml_get_errors();
159
160
    foreach ($errors as $error) {
161
        $output .= display_xml_error($error);
162
    }
163
    */
164
165 35
    if (!are_libxml_errors_ok ()) $output = "HTML code not valid.";
166
167 35
    libxml_use_internal_errors(false);
168 35
    return $output;
169
}
170
171
/**
172
 * This method is a direct copy-paste from
173
 * http://tmont.com/blargh/2010/1/string-format-in-php
174
 */
175
function str_format($format) {
0 ignored issues
show
The parameter $format is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
176 94
    $args = func_get_args();
177 94
    $format = array_shift($args);
178
179 94
    preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE);
180 94
    $offset = 0;
181 94
    foreach ($matches[1] as $data) {
182 94
        $i = $data[0];
183 94
        $format = substr_replace($format, @$args[$i], $offset + $data[1] - 1, 2 + strlen($i));
184 94
        $offset += strlen(@$args[$i]) - 2 - strlen($i);
185 94
    }
186
187 94
    return $format;
188
}
189
190
/**
191
 * Get all accepted languages from the browser and put them in a sorted array
192
 * languages id are normalized : fr-fr -> fr_FR
193
 * @return array of languages
194
 */
195
function getAcceptLanguages() {
196 16
    $langs = array();
197
198 16
    if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
199
        // break up string into pieces (languages and q factors)
200 16
        $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
201 16
        if (preg_match('/^(\w{2})-\w{2}$/', $accept, $matches)) {
202
            // Special fix for IE11 which send fr-FR and nothing else
203 3
            $accept = $accept . "," . $matches[1] . ";q=0.8";
204 3
        }
205 16
        preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $accept, $lang_parse);
206
207 16
        if (count($lang_parse[1])) {
208 16
            $langs = array();
209 16
            foreach ($lang_parse[1] as $lang) {
210
                // Format the language code (not standard among browsers)
211 16
                if (strlen($lang) == 5) {
212 11
                    $lang = str_replace("-", "_", $lang);
213 11
                    $splitted = preg_split("/_/", $lang);
214 11
                    $lang = $splitted[0] . "_" . strtoupper($splitted[1]);
215 11
                }
216 16
                array_push($langs, $lang);
217 16
            }
218
            // create a list like "en" => 0.8
219 16
            $langs = array_combine($langs, $lang_parse[4]);
220
221
            // set default to 1 for any without q factor
222 16
            foreach ($langs as $lang => $val) {
223 16
                if ($val === '') $langs[$lang] = 1;
224 16
            }
225
226
            // sort list based on value
227 16
            arsort($langs, SORT_NUMERIC);
228 16
        }
229 16
    }
230
231 16
    return $langs;
232
}
233
234
/**
235
 * Find the best translation file possible based on the accepted languages
236
 * @return array of language and language file
237
 */
238
function getLangAndTranslationFile() {
239 17
    global $config;
240 17
    $langs = array();
241 17
    $lang = "en";
242 17
    if (!empty($config['cops_language'])) {
243
        $lang = $config['cops_language'];
244
    }
245 17
    elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
246 16
        $langs = getAcceptLanguages();
247 16
    }
248
    //echo var_dump($langs);
249 17
    $lang_file = NULL;
250 17
    foreach ($langs as $language => $val) {
251 16
        $temp_file = dirname(__FILE__). '/lang/Localization_' . $language . '.json';
252 16
        if (file_exists($temp_file)) {
253 16
            $lang = $language;
254 16
            $lang_file = $temp_file;
255 16
            break;
256
        }
257 17
    }
258 17
    if (empty ($lang_file)) {
259 3
        $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json';
260 3
    }
261 17
    return array($lang, $lang_file);
262
}
263
264
/**
265
 * This method is based on this page
266
 * http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/
267
 */
268
function localize($phrase, $count=-1, $reset=false) {
269 114
    global $config;
270 114
    if ($count == 0)
271 114
        $phrase .= ".none";
272 114
    if ($count == 1)
273 114
        $phrase .= ".one";
274 114
    if ($count > 1)
275 114
        $phrase .= ".many";
276
277
    /* Static keyword is used to ensure the file is loaded only once */
278 114
    static $translations = NULL;
279 114
    if ($reset) {
280 16
        $translations = NULL;
281 16
    }
282
    /* If no instance of $translations has occured load the language file */
283 114
    if (is_null($translations)) {
284 17
        $lang_file_en = NULL;
285 17
        list ($lang, $lang_file) = getLangAndTranslationFile();
286 17
        if ($lang != "en") {
287 1
            $lang_file_en = dirname(__FILE__). '/lang/' . 'Localization_en.json';
288 1
        }
289
290 17
        $lang_file_content = file_get_contents($lang_file);
291
        /* Load the language file as a JSON object and transform it into an associative array */
292 17
        $translations = json_decode($lang_file_content, true);
293
294
        /* Clean the array of all unfinished translations */
295 17
        foreach (array_keys ($translations) as $key) {
296 17
            if (preg_match ("/^##TODO##/", $key)) {
297 1
                unset ($translations [$key]);
298 1
            }
299 17
        }
300
        if ($lang_file_en)
0 ignored issues
show
Bug Best Practice introduced by
The expression $lang_file_en of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
301 17
        {
302 1
            $lang_file_content = file_get_contents($lang_file_en);
303 1
            $translations_en = json_decode($lang_file_content, true);
304 1
            $translations = array_merge ($translations_en, $translations);
305 1
        }
306 17
    }
307 114
    if (array_key_exists ($phrase, $translations)) {
308 114
        return $translations[$phrase];
309
    }
310 1
    return $phrase;
311
}
312
313
function addURLParameter($urlParams, $paramName, $paramValue) {
314 58
    if (empty ($urlParams)) {
315 48
        $urlParams = "";
316 48
    }
317 58
    $start = "";
318 58
    if (preg_match ("#^\?(.*)#", $urlParams, $matches)) {
319 15
        $start = "?";
320 15
        $urlParams = $matches[1];
321 15
    }
322 58
    $params = array();
323 58
    parse_str($urlParams, $params);
324 58
    if (empty ($paramValue) && $paramValue != 0) {
325
        unset ($params[$paramName]);
326
    } else {
327 58
        $params[$paramName] = $paramValue;
328
    }
329 58
    return $start . http_build_query($params);
330
}
331
332
function useNormAndUp () {
333 107
    global $config;
334 107
    return $config ['cops_normalized_search'] == "1";
335
}
336
337
function normalizeUtf8String( $s) {
338 8
    include_once 'transliteration.php';
339 8
    return _transliteration_process($s);
340
}
341
342
function normAndUp ($s) {
343 7
    return mb_strtoupper (normalizeUtf8String($s), 'UTF-8');
344
}
345
346
class Link
347
{
348
    const OPDS_THUMBNAIL_TYPE = "http://opds-spec.org/image/thumbnail";
349
    const OPDS_IMAGE_TYPE = "http://opds-spec.org/image";
350
    const OPDS_ACQUISITION_TYPE = "http://opds-spec.org/acquisition";
351
    const OPDS_NAVIGATION_TYPE = "application/atom+xml;profile=opds-catalog;kind=navigation";
352
    const OPDS_PAGING_TYPE = "application/atom+xml;profile=opds-catalog;kind=acquisition";
353
354
    public $href;
355
    public $type;
356
    public $rel;
357
    public $title;
358
    public $facetGroup;
359
    public $activeFacet;
360
361 96
    public function __construct($phref, $ptype, $prel = NULL, $ptitle = NULL, $pfacetGroup = NULL, $pactiveFacet = FALSE) {
362 96
        $this->href = $phref;
363 96
        $this->type = $ptype;
364 96
        $this->rel = $prel;
365 96
        $this->title = $ptitle;
366 96
        $this->facetGroup = $pfacetGroup;
367 96
        $this->activeFacet = $pactiveFacet;
368 96
    }
369
370 10
    public function hrefXhtml () {
371 10
        return $this->href;
372
    }
373
374 95
    public function getScriptName() {
375 95
        $parts = explode('/', $_SERVER["SCRIPT_NAME"]);
376 95
        return $parts[count($parts) - 1];
377
    }
378
}
379
380
class LinkNavigation extends Link
381
{
382 95
    public function __construct($phref, $prel = NULL, $ptitle = NULL) {
383 95
        parent::__construct ($phref, Link::OPDS_NAVIGATION_TYPE, $prel, $ptitle);
384 95
        if (!is_null (GetUrlParam (DB))) $this->href = addURLParameter ($this->href, DB, GetUrlParam (DB));
385 95
        if (!preg_match ("#^\?(.*)#", $this->href) && !empty ($this->href)) $this->href = "?" . $this->href;
386 95
        if (preg_match ("/(bookdetail|getJSON).php/", parent::getScriptName())) {
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getScriptName() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getScriptName().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
387
            $this->href = "index.php" . $this->href;
388
        } else {
389 95
            $this->href = parent::getScriptName() . $this->href;
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getScriptName() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getScriptName().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
390
        }
391 95
    }
392
}
393
394
class LinkFacet extends Link
395
{
396 1
    public function __construct($phref, $ptitle = NULL, $pfacetGroup = NULL, $pactiveFacet = FALSE) {
397 1
        parent::__construct ($phref, Link::OPDS_PAGING_TYPE, "http://opds-spec.org/facet", $ptitle, $pfacetGroup, $pactiveFacet);
398 1
        if (!is_null (GetUrlParam (DB))) $this->href = addURLParameter ($this->href, DB, GetUrlParam (DB));
399 1
        $this->href = parent::getScriptName() . $this->href;
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getScriptName() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getScriptName().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
400 1
    }
401
}
402
403
class Entry
404
{
405
    public $title;
406
    public $id;
407
    public $content;
408
    public $numberOfElement;
409
    public $contentType;
410
    public $linkArray;
411
    public $localUpdated;
412
    public $className;
413
    private static $updated = NULL;
414
415
    public static $icons = array(
416
        Author::ALL_AUTHORS_ID       => 'images/author.png',
417
        Serie::ALL_SERIES_ID         => 'images/serie.png',
418
        Book::ALL_RECENT_BOOKS_ID    => 'images/recent.png',
419
        Tag::ALL_TAGS_ID             => 'images/tag.png',
420
        Language::ALL_LANGUAGES_ID   => 'images/language.png',
421
        CustomColumn::ALL_CUSTOMS_ID => 'images/tag.png',
422
        "cops:books$"             => 'images/allbook.png',
423
        "cops:books:letter"       => 'images/allbook.png',
424
        Publisher::ALL_PUBLISHERS_ID => 'images/publisher.png'
425
    );
426
427
    public function getUpdatedTime () {
428
        if (!is_null ($this->localUpdated)) {
429
            return date (DATE_ATOM, $this->localUpdated);
430
        }
431
        if (is_null (self::$updated)) {
432
            self::$updated = time();
433
        }
434
        return date (DATE_ATOM, self::$updated);
435
    }
436
437 7
    public function getNavLink () {
438 7
        foreach ($this->linkArray as $link) {
439 7
            if ($link->type != Link::OPDS_NAVIGATION_TYPE) { continue; }
440
441 7
            return $link->hrefXhtml ();
442
        }
443
        return "#";
444
    }
445
446 89
    public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pclass = "", $pcount = 0) {
447 89
        global $config;
448 89
        $this->title = $ptitle;
449 89
        $this->id = $pid;
450 89
        $this->content = $pcontent;
451 89
        $this->contentType = $pcontentType;
452 89
        $this->linkArray = $plinkArray;
453 89
        $this->className = $pclass;
454 89
        $this->numberOfElement = $pcount;
455
456 89
        if ($config['cops_show_icons'] == 1)
457 89
        {
458 89
            foreach (self::$icons as $reg => $image)
459
            {
460 89
                if (preg_match ("/" . $reg . "/", $pid)) {
461 50
                    array_push ($this->linkArray, new Link (getUrlWithVersion ($image), "image/png", Link::OPDS_THUMBNAIL_TYPE));
462 50
                    break;
463
                }
464 89
            }
465 89
        }
466
467 89
        if (!is_null (GetUrlParam (DB))) $this->id = str_replace ("cops:", "cops:" . GetUrlParam (DB) . ":", $this->id);
468 89
    }
469
}
470
471
class EntryBook extends Entry
472
{
473
    public $book;
474
475 39
    public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pbook) {
476 39
        parent::__construct ($ptitle, $pid, $pcontent, $pcontentType, $plinkArray);
477 39
        $this->book = $pbook;
478 39
        $this->localUpdated = $pbook->timestamp;
479 39
    }
480
481
    public function getCoverThumbnail () {
482
        foreach ($this->linkArray as $link) {
483
            if ($link->rel == Link::OPDS_THUMBNAIL_TYPE)
484
                return $link->hrefXhtml ();
485
        }
486
        return null;
487
    }
488
489
    public function getCover () {
490
        foreach ($this->linkArray as $link) {
491
            if ($link->rel == Link::OPDS_IMAGE_TYPE)
492
                return $link->hrefXhtml ();
493
        }
494
        return null;
495
    }
496
}
497
498
class Page
499
{
500
    public $title;
501
    public $subtitle = "";
502
    public $authorName = "";
503
    public $authorUri = "";
504
    public $authorEmail = "";
505
    public $idPage;
506
    public $idGet;
507
    public $query;
508
    public $favicon;
509
    public $n;
510
    public $book;
511
    public $totalNumber = -1;
512
    public $entryArray = array();
513
514 81
    public static function getPage ($pageId, $id, $query, $n)
515
    {
516
        switch ($pageId) {
517 81
            case Base::PAGE_ALL_AUTHORS :
518 3
                return new PageAllAuthors ($id, $query, $n);
519 78
            case Base::PAGE_AUTHORS_FIRST_LETTER :
520 1
                return new PageAllAuthorsLetter ($id, $query, $n);
521 77
            case Base::PAGE_AUTHOR_DETAIL :
522 7
                return new PageAuthorDetail ($id, $query, $n);
523 70
            case Base::PAGE_ALL_TAGS :
524 2
                return new PageAllTags ($id, $query, $n);
525 68
            case Base::PAGE_TAG_DETAIL :
526 1
                return new PageTagDetail ($id, $query, $n);
527 67
            case Base::PAGE_ALL_LANGUAGES :
528 2
                return new PageAllLanguages ($id, $query, $n);
529 65
            case Base::PAGE_LANGUAGE_DETAIL :
530 1
                return new PageLanguageDetail ($id, $query, $n);
531 64
            case Base::PAGE_ALL_CUSTOMS :
532 3
                return new PageAllCustoms ($id, $query, $n);
533 61
            case Base::PAGE_CUSTOM_DETAIL :
534 3
                return new PageCustomDetail ($id, $query, $n);
535 58
            case Base::PAGE_ALL_RATINGS :
536 1
                return new PageAllRating ($id, $query, $n);
537 57
            case Base::PAGE_RATING_DETAIL :
538 1
                return new PageRatingDetail ($id, $query, $n);
539 56
            case Base::PAGE_ALL_SERIES :
540 2
                return new PageAllSeries ($id, $query, $n);
541 54
            case Base::PAGE_ALL_BOOKS :
542 3
                return new PageAllBooks ($id, $query, $n);
543 51
            case Base::PAGE_ALL_BOOKS_LETTER:
544 1
                return new PageAllBooksLetter ($id, $query, $n);
545 50
            case Base::PAGE_ALL_RECENT_BOOKS :
546 4
                return new PageRecentBooks ($id, $query, $n);
547 46
            case Base::PAGE_SERIE_DETAIL :
548 1
                return new PageSerieDetail ($id, $query, $n);
549 45
            case Base::PAGE_OPENSEARCH_QUERY :
550 31
                return new PageQueryResult ($id, $query, $n);
551 14
            case Base::PAGE_BOOK_DETAIL :
552 1
                return new PageBookDetail ($id, $query, $n);
553 13
            case Base::PAGE_ALL_PUBLISHERS:
554 2
                return new PageAllPublishers ($id, $query, $n);
555 11
            case Base::PAGE_PUBLISHER_DETAIL :
556 1
                return new PagePublisherDetail ($id, $query, $n);
557 10
            case Base::PAGE_ABOUT :
558
                return new PageAbout ($id, $query, $n);
559 10
            case Base::PAGE_CUSTOMIZE :
560
                return new PageCustomize ($id, $query, $n);
561 10
            default:
562 10
                $page = new Page ($id, $query, $n);
563 10
                $page->idPage = "cops:catalog";
564 10
                return $page;
565 10
        }
566
    }
567
568 81
    public function __construct($pid, $pquery, $pn) {
569 81
        global $config;
570
571 81
        $this->idGet = $pid;
572 81
        $this->query = $pquery;
573 81
        $this->n = $pn;
574 81
        $this->favicon = $config['cops_icon'];
575 81
        $this->authorName = empty($config['cops_author_name']) ? utf8_encode('S�bastien Lucas') : $config['cops_author_name'];
576 81
        $this->authorUri = empty($config['cops_author_uri']) ? 'http://blog.slucas.fr' : $config['cops_author_uri'];
577 81
        $this->authorEmail = empty($config['cops_author_email']) ? '[email protected]' : $config['cops_author_email'];
578 81
    }
579
580 10
    public function InitializeContent ()
581
    {
582 10
        global $config;
583 10
        $this->title = $config['cops_title_default'];
584 10
        $this->subtitle = $config['cops_subtitle_default'];
585 10
        if (Base::noDatabaseSelected ()) {
586 2
            $i = 0;
587 2
            foreach (Base::getDbNameList () as $key) {
588 2
                $nBooks = Book::getBookCount ($i);
589 2
                array_push ($this->entryArray, new Entry ($key, "cops:{$i}:catalog",
590 2
                                        str_format (localize ("bookword", $nBooks), $nBooks), "text",
591 2
                                        array ( new LinkNavigation ("?" . DB . "={$i}")), "", $nBooks));
592 2
                $i++;
593 2
                Base::clearDb ();
594 2
            }
595 2
        } else {
596 8
            if (!in_array (PageQueryResult::SCOPE_AUTHOR, getCurrentOption ('ignored_categories'))) {
597 7
                array_push ($this->entryArray, Author::getCount());
598 7
            }
599 8
            if (!in_array (PageQueryResult::SCOPE_SERIES, getCurrentOption ('ignored_categories'))) {
600 7
                $series = Serie::getCount();
601 7
                if (!is_null ($series)) array_push ($this->entryArray, $series);
602 7
            }
603 8
            if (!in_array (PageQueryResult::SCOPE_PUBLISHER, getCurrentOption ('ignored_categories'))) {
604 7
                $publisher = Publisher::getCount();
605 7
                if (!is_null ($publisher)) array_push ($this->entryArray, $publisher);
606 7
            }
607 8
            if (!in_array (PageQueryResult::SCOPE_TAG, getCurrentOption ('ignored_categories'))) {
608 7
                $tags = Tag::getCount();
609 7
                if (!is_null ($tags)) array_push ($this->entryArray, $tags);
610 7
            }
611 8
            if (!in_array (PageQueryResult::SCOPE_RATING, getCurrentOption ('ignored_categories'))) {
612 8
                $rating = Rating::getCount();
613 8
                if (!is_null ($rating)) array_push ($this->entryArray, $rating);
614 8
            }
615 8
            if (!in_array ("language", getCurrentOption ('ignored_categories'))) {
616 7
                $languages = Language::getCount();
617 7
                if (!is_null ($languages)) array_push ($this->entryArray, $languages);
618 7
            }
619 8
            foreach ($config['cops_calibre_custom_column'] as $lookup) {
620 4
                $customId = CustomColumn::getCustomId ($lookup);
621 4
                if (!is_null ($customId)) {
622 4
                    array_push ($this->entryArray, CustomColumn::getCount($customId));
623 4
                }
624 8
            }
625 8
            $this->entryArray = array_merge ($this->entryArray, Book::getCount());
626
627 8
            if (Base::isMultipleDatabaseEnabled ()) $this->title =  Base::getDbName ();
628
        }
629 10
    }
630
631 17
    public function isPaginated ()
632
    {
633 17
        return (getCurrentOption ("max_item_per_page") != -1 &&
634 17
                $this->totalNumber != -1 &&
635 17
                $this->totalNumber > getCurrentOption ("max_item_per_page"));
636
    }
637
638 2
    public function getNextLink ()
639
    {
640 2
        $currentUrl = preg_replace ("/\&n=.*?$/", "", "?" . getQueryString ());
641 2
        if (($this->n) * getCurrentOption ("max_item_per_page") < $this->totalNumber) {
642 1
            return new LinkNavigation ($currentUrl . "&n=" . ($this->n + 1), "next", localize ("paging.next.alternate"));
643
        }
644 1
        return NULL;
645
    }
646
647 2
    public function getPrevLink ()
648
    {
649 2
        $currentUrl = preg_replace ("/\&n=.*?$/", "", "?" . getQueryString ());
650 2
        if ($this->n > 1) {
651 1
            return new LinkNavigation ($currentUrl . "&n=" . ($this->n - 1), "previous", localize ("paging.previous.alternate"));
652
        }
653 2
        return NULL;
654
    }
655
656 2
    public function getMaxPage ()
657
    {
658 2
        return ceil ($this->totalNumber / getCurrentOption ("max_item_per_page"));
659
    }
660
661 70
    public function containsBook ()
662
    {
663 70
        if (count ($this->entryArray) == 0) return false;
664 68
        if (get_class ($this->entryArray [0]) == "EntryBook") return true;
665 46
        return false;
666
    }
667
}
668
669
class PageAllAuthors extends Page
670
{
671 3
    public function InitializeContent ()
672
    {
673 3
        $this->title = localize("authors.title");
674 3
        if (getCurrentOption ("author_split_first_letter") == 1) {
675 2
            $this->entryArray = Author::getAllAuthorsByFirstLetter();
676 2
        }
677
        else {
678 1
            $this->entryArray = Author::getAllAuthors();
679
        }
680 3
        $this->idPage = Author::ALL_AUTHORS_ID;
681 3
    }
682
}
683
684
class PageAllAuthorsLetter extends Page
685
{
686 1
    public function InitializeContent ()
687
    {
688 1
        $this->idPage = Author::getEntryIdByLetter ($this->idGet);
689 1
        $this->entryArray = Author::getAuthorsByStartingLetter ($this->idGet);
690 1
        $this->title = str_format (localize ("splitByLetter.letter"), str_format (localize ("authorword", count ($this->entryArray)), count ($this->entryArray)), $this->idGet);
691 1
    }
692
}
693
694
class PageAuthorDetail extends Page
695
{
696 7
    public function InitializeContent ()
697
    {
698 7
        $author = Author::getAuthorById ($this->idGet);
699 7
        $this->idPage = $author->getEntryId ();
700 7
        $this->title = $author->name;
701 7
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByAuthor ($this->idGet, $this->n);
702 7
    }
703
}
704
705
class PageAllPublishers extends Page
706
{
707 2
    public function InitializeContent ()
708
    {
709 2
        $this->title = localize("publishers.title");
710 2
        $this->entryArray = Publisher::getAllPublishers();
711 2
        $this->idPage = Publisher::ALL_PUBLISHERS_ID;
712 2
    }
713
}
714
715
class PagePublisherDetail extends Page
716
{
717 1
    public function InitializeContent ()
718
    {
719 1
        $publisher = Publisher::getPublisherById ($this->idGet);
720 1
        $this->title = $publisher->name;
721 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByPublisher ($this->idGet, $this->n);
722 1
        $this->idPage = $publisher->getEntryId ();
723 1
    }
724
}
725
726
class PageAllTags extends Page
727
{
728 2
    public function InitializeContent ()
729
    {
730 2
        $this->title = localize("tags.title");
731 2
        $this->entryArray = Tag::getAllTags();
732 2
        $this->idPage = Tag::ALL_TAGS_ID;
733 2
    }
734
}
735
736
class PageAllLanguages extends Page
737
{
738 2
    public function InitializeContent ()
739
    {
740 2
        $this->title = localize("languages.title");
741 2
        $this->entryArray = Language::getAllLanguages();
742 2
        $this->idPage = Language::ALL_LANGUAGES_ID;
743 2
    }
744
}
745
746
class PageCustomDetail extends Page
747
{
748 3
    public function InitializeContent ()
749
    {
750 3
        $customId = getURLParam ("custom", NULL);
751 3
        $custom = CustomColumn::getCustomById ($customId, $this->idGet);
752 3
        $this->idPage = $custom->getEntryId ();
753 3
        $this->title = $custom->name;
754 3
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByCustom ($customId, $this->idGet, $this->n);
755 3
    }
756
}
757
758
class PageAllCustoms extends Page
759
{
760 3
    public function InitializeContent ()
761
    {
762 3
        $customId = getURLParam ("custom", NULL);
763 3
        $this->title = CustomColumn::getAllTitle ($customId);
764 3
        $this->entryArray = CustomColumn::getAllCustoms($customId);
765 3
        $this->idPage = CustomColumn::getAllCustomsId ($customId);
766 3
    }
767
}
768
769
class PageTagDetail extends Page
770
{
771 1
    public function InitializeContent ()
772
    {
773 1
        $tag = Tag::getTagById ($this->idGet);
774 1
        $this->idPage = $tag->getEntryId ();
775 1
        $this->title = $tag->name;
776 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByTag ($this->idGet, $this->n);
777 1
    }
778
}
779
780
class PageLanguageDetail extends Page
781
{
782 1
    public function InitializeContent ()
783
    {
784 1
        $language = Language::getLanguageById ($this->idGet);
785 1
        $this->idPage = $language->getEntryId ();
786 1
        $this->title = $language->lang_code;
787 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByLanguage ($this->idGet, $this->n);
788 1
    }
789
}
790
791
class PageAllSeries extends Page
792
{
793 2
    public function InitializeContent ()
794
    {
795 2
        $this->title = localize("series.title");
796 2
        $this->entryArray = Serie::getAllSeries();
797 2
        $this->idPage = Serie::ALL_SERIES_ID;
798 2
    }
799
}
800
801
class PageSerieDetail extends Page
802
{
803 1
    public function InitializeContent ()
804
    {
805 1
        $serie = Serie::getSerieById ($this->idGet);
806 1
        $this->title = $serie->name;
807 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksBySeries ($this->idGet, $this->n);
808 1
        $this->idPage = $serie->getEntryId ();
809 1
    }
810
}
811
812
class PageAllRating extends Page
813
{
814 1
    public function InitializeContent ()
815
    {
816 1
        $this->title = localize("ratings.title");
817 1
        $this->entryArray = Rating::getAllRatings();
818 1
        $this->idPage = Rating::ALL_RATING_ID;
819 1
    }
820
}
821
822
class PageRatingDetail extends Page
823
{
824 1
    public function InitializeContent ()
825
    {
826 1
        $rating = Rating::getRatingById ($this->idGet);
827 1
        $this->idPage = $rating->getEntryId ();
828 1
        $this->title =str_format (localize ("ratingword", $rating->name/2), $rating->name/2);
829 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByRating ($this->idGet, $this->n);
830 1
    }
831
}
832
833
class PageAllBooks extends Page
834
{
835 3
    public function InitializeContent ()
836
    {
837 3
        $this->title = localize ("allbooks.title");
838 3
        if (getCurrentOption ("titles_split_first_letter") == 1) {
839 2
            $this->entryArray = Book::getAllBooks();
840 2
        }
841
        else {
842 1
            list ($this->entryArray, $this->totalNumber) = Book::getBooks ($this->n);
843
        }
844 3
        $this->idPage = Book::ALL_BOOKS_ID;
845 3
    }
846
}
847
848
class PageAllBooksLetter extends Page
849
{
850 1
    public function InitializeContent ()
851
    {
852 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByStartingLetter ($this->idGet, $this->n);
853 1
        $this->idPage = Book::getEntryIdByLetter ($this->idGet);
854
855 1
        $count = $this->totalNumber;
856 1
        if ($count == -1)
857 1
            $count = count ($this->entryArray);
858
859 1
        $this->title = str_format (localize ("splitByLetter.letter"), str_format (localize ("bookword", $count), $count), $this->idGet);
860 1
    }
861
}
862
863
class PageRecentBooks extends Page
864
{
865 4
    public function InitializeContent ()
866
    {
867 4
        $this->title = localize ("recent.title");
868 4
        $this->entryArray = Book::getAllRecentBooks ();
869 4
        $this->idPage = Book::ALL_RECENT_BOOKS_ID;
870 4
    }
871
}
872
873
class PageQueryResult extends Page
874
{
875
    const SCOPE_TAG = "tag";
876
    const SCOPE_RATING = "rating";
877
    const SCOPE_SERIES = "series";
878
    const SCOPE_AUTHOR = "author";
879
    const SCOPE_BOOK = "book";
880
    const SCOPE_PUBLISHER = "publisher";
881
882 24
    private function useTypeahead () {
883 24
        return !is_null (getURLParam ("search"));
884
    }
885
886 29
    private function searchByScope ($scope, $limit = FALSE) {
887 29
        $n = $this->n;
888 29
        $numberPerPage = NULL;
889 29
        $queryNormedAndUp = $this->query;
890 29
        if (useNormAndUp ()) {
891 7
            $queryNormedAndUp = normAndUp ($this->query);
892 7
        }
893 29
        if ($limit) {
894 22
            $n = 1;
895 22
            $numberPerPage = 5;
896 22
        }
897
        switch ($scope) {
898 29
            case self::SCOPE_BOOK :
899 23
                $array = Book::getBooksByStartingLetter ('%' . $queryNormedAndUp, $n, NULL, $numberPerPage);
900 23
                break;
901 28
            case self::SCOPE_AUTHOR :
902 23
                $array = Author::getAuthorsForSearch ('%' . $queryNormedAndUp);
903 23
                break;
904 25
            case self::SCOPE_SERIES :
905 22
                $array = Serie::getAllSeriesByQuery ($queryNormedAndUp);
906 22
                break;
907 24
            case self::SCOPE_TAG :
908 23
                $array = Tag::getAllTagsByQuery ($queryNormedAndUp, $n, NULL, $numberPerPage);
909 23
                break;
910 23
            case self::SCOPE_PUBLISHER :
911 23
                $array = Publisher::getAllPublishersByQuery ($queryNormedAndUp);
912 23
                break;
913
            default:
914
                $array = Book::getBooksByQuery (
915
                    array ("all" => "%" . $queryNormedAndUp . "%"), $n);
916
        }
917
918 29
        return $array;
919
    }
920
921 22
    public function doSearchByCategory () {
922 22
        $database = GetUrlParam (DB);
923 22
        $out = array ();
924 22
        $pagequery = Base::PAGE_OPENSEARCH_QUERY;
925 22
        $dbArray = array ("");
926 22
        $d = $database;
927 22
        $query = $this->query;
928
        // Special case when no databases were chosen, we search on all databases
929 22
        if (Base::noDatabaseSelected ()) {
930 1
            $dbArray = Base::getDbNameList ();
931 1
            $d = 0;
932 1
        }
933 22
        foreach ($dbArray as $key) {
934 22
            if (Base::noDatabaseSelected ()) {
935 1
                array_push ($this->entryArray, new Entry ($key, DB . ":query:{$d}",
936 1
                                        " ", "text",
937 1
                                        array ( new LinkNavigation ("?" . DB . "={$d}")), "tt-header"));
938 1
                Base::getDb ($d);
939 1
            }
940 22
            foreach (array (PageQueryResult::SCOPE_BOOK,
941 22
                            PageQueryResult::SCOPE_AUTHOR,
942 22
                            PageQueryResult::SCOPE_SERIES,
943 22
                            PageQueryResult::SCOPE_TAG,
944 22
                            PageQueryResult::SCOPE_PUBLISHER) as $key) {
945 22
                if (in_array($key, getCurrentOption ('ignored_categories'))) {
946 3
                    continue;
947
                }
948 22
                $array = $this->searchByScope ($key, TRUE);
949
950 22
                $i = 0;
951 22
                if (count ($array) == 2 && is_array ($array [0])) {
952 22
                    $total = $array [1];
953 22
                    $array = $array [0];
954 22
                } else {
955 22
                    $total = count($array);
956
                }
957 22
                if ($total > 0) {
958
                    // Comment to help the perl i18n script
959
                    // str_format (localize("bookword", count($array))
960
                    // str_format (localize("authorword", count($array))
961
                    // str_format (localize("seriesword", count($array))
962
                    // str_format (localize("tagword", count($array))
963
                    // str_format (localize("publisherword", count($array))
964 21
                    array_push ($this->entryArray, new Entry (str_format (localize ("search.result.{$key}"), $this->query), DB . ":query:{$d}:{$key}",
965 21
                                        str_format (localize("{$key}word", $total), $total), "text",
966 21
                                        array ( new LinkNavigation ("?page={$pagequery}&query={$query}&db={$d}&scope={$key}")),
967 21
                                        Base::noDatabaseSelected () ? "" : "tt-header", $total));
968 21
                }
969 22
                if (!Base::noDatabaseSelected () && $this->useTypeahead ()) {
970 6
                    foreach ($array as $entry) {
971 6
                        array_push ($this->entryArray, $entry);
972 6
                        $i++;
973 6
                        if ($i > 4) { break; };
974 6
                    }
975 6
                }
976 22
            }
977 22
            $d++;
978 22
            if (Base::noDatabaseSelected ()) {
979 1
                Base::clearDb ();
980 1
            }
981 22
        }
982 22
        return $out;
983
    }
984
985 31
    public function InitializeContent ()
986
    {
987 31
        $scope = getURLParam ("scope");
988 31
        if (empty ($scope)) {
989 24
            $this->title = str_format (localize ("search.result"), $this->query);
990 24
        } else {
991
            // Comment to help the perl i18n script
992
            // str_format (localize ("search.result.author"), $this->query)
993
            // str_format (localize ("search.result.tag"), $this->query)
994
            // str_format (localize ("search.result.series"), $this->query)
995
            // str_format (localize ("search.result.book"), $this->query)
996
            // str_format (localize ("search.result.publisher"), $this->query)
997 7
            $this->title = str_format (localize ("search.result.{$scope}"), $this->query);
998
        }
999
1000 31
        $crit = "%" . $this->query . "%";
1001
1002
        // Special case when we are doing a search and no database is selected
1003 31
        if (Base::noDatabaseSelected () && !$this->useTypeahead ()) {
1004 2
            $i = 0;
1005 2
            foreach (Base::getDbNameList () as $key) {
1006 2
                Base::clearDb ();
1007 2
                list ($array, $totalNumber) = Book::getBooksByQuery (array ("all" => $crit), 1, $i, 1);
0 ignored issues
show
The assignment to $array is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1008 2
                array_push ($this->entryArray, new Entry ($key, DB . ":query:{$i}",
1009 2
                                        str_format (localize ("bookword", $totalNumber), $totalNumber), "text",
1010 2
                                        array ( new LinkNavigation ("?" . DB . "={$i}&page=9&query=" . $this->query)), "", $totalNumber));
1011 2
                $i++;
1012 2
            }
1013 2
            return;
1014
        }
1015 29
        if (empty ($scope)) {
1016 22
            $this->doSearchByCategory ();
1017 22
            return;
1018
        }
1019
1020 7
        $array = $this->searchByScope ($scope);
1021 7
        if (count ($array) == 2 && is_array ($array [0])) {
1022 2
            list ($this->entryArray, $this->totalNumber) = $array;
1023 2
        } else {
1024 5
            $this->entryArray = $array;
1025
        }
1026 7
    }
1027
}
1028
1029
class PageBookDetail extends Page
1030
{
1031 1
    public function InitializeContent ()
1032
    {
1033 1
        $this->book = Book::getBookById ($this->idGet);
1034 1
        $this->title = $this->book->title;
1035 1
    }
1036
}
1037
1038
class PageAbout extends Page
1039
{
1040
    public function InitializeContent ()
1041
    {
1042
        $this->title = localize ("about.title");
1043
    }
1044
}
1045
1046
class PageCustomize extends Page
1047
{
1048
    private function isChecked ($key, $testedValue = 1) {
1049
        $value = getCurrentOption ($key);
1050
        if (is_array ($value)) {
1051
            if (in_array ($testedValue, $value)) {
1052
                return "checked='checked'";
1053
            }
1054
        } else {
1055
            if ($value == $testedValue) {
1056
                return "checked='checked'";
1057
            }
1058
        }
1059
        return "";
1060
    }
1061
1062
    private function isSelected ($key, $value) {
1063
        if (getCurrentOption ($key) == $value) {
1064
            return "selected='selected'";
1065
        }
1066
        return "";
1067
    }
1068
1069
    private function getStyleList () {
1070
        $result = array ();
1071
        foreach (glob ("templates/" . getCurrentTemplate () . "/styles/style-*.css") as $filename) {
1072
            if (preg_match ('/styles\/style-(.*?)\.css/', $filename, $m)) {
1073
                array_push ($result, $m [1]);
1074
            }
1075
        }
1076
        return $result;
1077
    }
1078
1079
    public function InitializeContent ()
1080
    {
1081
        $this->title = localize ("customize.title");
1082
        $this->entryArray = array ();
1083
1084
        $ignoredBaseArray = array (PageQueryResult::SCOPE_AUTHOR,
1085
                                   PageQueryResult::SCOPE_TAG,
1086
                                   PageQueryResult::SCOPE_SERIES,
1087
                                   PageQueryResult::SCOPE_PUBLISHER,
1088
                                   PageQueryResult::SCOPE_RATING,
1089
                                   "language");
1090
1091
        $content = "";
1092
        array_push ($this->entryArray, new Entry ("Template", "",
1093
                                        "<span style='cursor: pointer;' onclick='$.cookie(\"template\", \"bootstrap\", { expires: 365 });window.location=$(\".headleft\").attr(\"href\");'>Click to switch to Bootstrap</span>", "text",
1094
                                        array ()));
1095
        if (!preg_match("/(Kobo|Kindle\/3.0|EBRD1101)/", $_SERVER['HTTP_USER_AGENT'])) {
1096
            $content .= '<select id="style" onchange="updateCookie (this);">';
1097
            foreach ($this-> getStyleList () as $filename) {
1098
                $content .= "<option value='{$filename}' " . $this->isSelected ("style", $filename) . ">{$filename}</option>";
1099
            }
1100
            $content .= '</select>';
1101
        } else {
1102
            foreach ($this-> getStyleList () as $filename) {
1103
                $content .= "<input type='radio' onchange='updateCookieFromCheckbox (this);' id='style-{$filename}' name='style' value='{$filename}' " . $this->isChecked ("style", $filename) . " /><label for='style-{$filename}'> {$filename} </label>";
1104
            }
1105
        }
1106
        array_push ($this->entryArray, new Entry (localize ("customize.style"), "",
1107
                                        $content, "text",
1108
                                        array ()));
1109
        if (!useServerSideRendering ()) {
1110
            $content = '<input type="checkbox" onchange="updateCookieFromCheckbox (this);" id="use_fancyapps" ' . $this->isChecked ("use_fancyapps") . ' />';
1111
            array_push ($this->entryArray, new Entry (localize ("customize.fancybox"), "",
1112
                                            $content, "text",
1113
                                            array ()));
1114
        }
1115
        $content = '<input type="number" onchange="updateCookie (this);" id="max_item_per_page" value="' . getCurrentOption ("max_item_per_page") . '" min="-1" max="1200" pattern="^[-+]?[0-9]+$" />';
1116
        array_push ($this->entryArray, new Entry (localize ("customize.paging"), "",
1117
                                        $content, "text",
1118
                                        array ()));
1119
        $content = '<input type="text" onchange="updateCookie (this);" id="email" value="' . getCurrentOption ("email") . '" />';
1120
        array_push ($this->entryArray, new Entry (localize ("customize.email"), "",
1121
                                        $content, "text",
1122
                                        array ()));
1123
        $content = '<input type="checkbox" onchange="updateCookieFromCheckbox (this);" id="html_tag_filter" ' . $this->isChecked ("html_tag_filter") . ' />';
1124
        array_push ($this->entryArray, new Entry (localize ("customize.filter"), "",
1125
                                        $content, "text",
1126
                                        array ()));
1127
        $content = "";
1128
        foreach ($ignoredBaseArray as $key) {
1129
            $keyPlural = preg_replace ('/(ss)$/', 's', $key . "s");
1130
            $content .=  '<input type="checkbox" name="ignored_categories[]" onchange="updateCookieFromCheckboxGroup (this);" id="ignored_categories_' . $key . '" ' . $this->isChecked ("ignored_categories", $key) . ' > ' . localize ("{$keyPlural}.title") . '</input> ';
1131
        }
1132
1133
        array_push ($this->entryArray, new Entry (localize ("customize.ignored"), "",
1134
                                        $content, "text",
1135
                                        array ()));
1136
    }
1137
}
1138
1139
1140
abstract class Base
1141
{
1142
    const PAGE_INDEX = "index";
1143
    const PAGE_ALL_AUTHORS = "1";
1144
    const PAGE_AUTHORS_FIRST_LETTER = "2";
1145
    const PAGE_AUTHOR_DETAIL = "3";
1146
    const PAGE_ALL_BOOKS = "4";
1147
    const PAGE_ALL_BOOKS_LETTER = "5";
1148
    const PAGE_ALL_SERIES = "6";
1149
    const PAGE_SERIE_DETAIL = "7";
1150
    const PAGE_OPENSEARCH = "8";
1151
    const PAGE_OPENSEARCH_QUERY = "9";
1152
    const PAGE_ALL_RECENT_BOOKS = "10";
1153
    const PAGE_ALL_TAGS = "11";
1154
    const PAGE_TAG_DETAIL = "12";
1155
    const PAGE_BOOK_DETAIL = "13";
1156
    const PAGE_ALL_CUSTOMS = "14";
1157
    const PAGE_CUSTOM_DETAIL = "15";
1158
    const PAGE_ABOUT = "16";
1159
    const PAGE_ALL_LANGUAGES = "17";
1160
    const PAGE_LANGUAGE_DETAIL = "18";
1161
    const PAGE_CUSTOMIZE = "19";
1162
    const PAGE_ALL_PUBLISHERS = "20";
1163
    const PAGE_PUBLISHER_DETAIL = "21";
1164
    const PAGE_ALL_RATINGS = "22";
1165
    const PAGE_RATING_DETAIL = "23";
1166
1167
    const COMPATIBILITY_XML_ALDIKO = "aldiko";
1168
1169
    private static $db = NULL;
1170
1171 108
    public static function isMultipleDatabaseEnabled () {
1172 108
        global $config;
1173 108
        return is_array ($config['calibre_directory']);
1174
    }
1175
1176 46
    public static function useAbsolutePath () {
1177 46
        global $config;
1178 46
        $path = self::getDbDirectory();
1179 46
        return preg_match ('/^\//', $path) || // Linux /
1180 46
               preg_match ('/^\w\:/', $path); // Windows X:
1181
    }
1182
1183 45
    public static function noDatabaseSelected () {
1184 45
        return self::isMultipleDatabaseEnabled () && is_null (GetUrlParam (DB));
1185
    }
1186
1187 4
    public static function getDbList () {
1188 4
        global $config;
1189 4
        if (self::isMultipleDatabaseEnabled ()) {
1190 4
            return $config['calibre_directory'];
1191
        } else {
1192 1
            return array ("" => $config['calibre_directory']);
1193
        }
1194
    }
1195
1196 5
    public static function getDbNameList () {
1197 5
        global $config;
1198 5
        if (self::isMultipleDatabaseEnabled ()) {
1199 5
            return array_keys ($config['calibre_directory']);
1200
        } else {
1201
            return array ("");
1202
        }
1203
    }
1204
1205 1
    public static function getDbName ($database = NULL) {
1206 1
        global $config;
1207 1
        if (self::isMultipleDatabaseEnabled ()) {
1208 1
            if (is_null ($database)) $database = GetUrlParam (DB, 0);
1209 1
            if (!is_null($database) && !preg_match('/^\d+$/', $database)) {
1210
                return self::error ($database);
1211
            }
1212 1
            $array = array_keys ($config['calibre_directory']);
1213 1
            return  $array[$database];
1214
        }
1215
        return "";
1216
    }
1217
1218 90
    public static function getDbDirectory ($database = NULL) {
1219 90
        global $config;
1220 90
        if (self::isMultipleDatabaseEnabled ()) {
1221 9
            if (is_null ($database)) $database = GetUrlParam (DB, 0);
1222 9
            if (!is_null($database) && !preg_match('/^\d+$/', $database)) {
1223
                return self::error ($database);
1224
            }
1225 9
            $array = array_values ($config['calibre_directory']);
1226 9
            return  $array[$database];
1227
        }
1228 81
        return $config['calibre_directory'];
1229
    }
1230
1231
1232 61
    public static function getDbFileName ($database = NULL) {
1233 61
        return self::getDbDirectory ($database) .'metadata.db';
1234
    }
1235
1236 2
    private static function error ($database) {
1237 2
        if (php_sapi_name() != "cli") {
1238
            header("location: checkconfig.php?err=1");
1239
        }
1240 2
        throw new Exception("Database <{$database}> not found.");
1241
    }
1242
1243 126
    public static function getDb ($database = NULL) {
1244 126
        if (is_null (self::$db)) {
1245
            try {
1246 61
                if (is_readable (self::getDbFileName ($database))) {
1247 60
                    self::$db = new PDO('sqlite:'. self::getDbFileName ($database));
1248 60
                    if (useNormAndUp ()) {
1249 7
                        self::$db->sqliteCreateFunction ('normAndUp', 'normAndUp', 1);
1250 7
                    }
1251 60
                } else {
1252 2
                    self::error ($database);
1253
                }
1254 61
            } catch (Exception $e) {
1255 2
                self::error ($database);
1256
            }
1257 60
        }
1258 125
        return self::$db;
1259
    }
1260
1261 4
    public static function checkDatabaseAvailability () {
1262 4
        if (self::noDatabaseSelected ()) {
1263 3
            for ($i = 0; $i < count (self::getDbList ()); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1264 3
                self::getDb ($i);
1265 2
                self::clearDb ();
1266 2
            }
1267 1
        } else {
1268 1
            self::getDb ();
1269
        }
1270 2
        return true;
1271
    }
1272
1273 58
    public static function clearDb () {
1274 58
        self::$db = NULL;
1275 58
    }
1276
1277 13
    public static function executeQuerySingle ($query, $database = NULL) {
1278 13
        return self::getDb ($database)->query($query)->fetchColumn();
1279
    }
1280
1281 8
    public static function getCountGeneric($table, $id, $pageId, $numberOfString = NULL) {
1282 8
        if (!$numberOfString) {
1283 7
            $numberOfString = $table . ".alphabetical";
1284 7
        }
1285 8
        $count = self::executeQuerySingle ('select count(*) from ' . $table);
1286 8
        if ($count == 0) return NULL;
1287 8
        $entry = new Entry (localize($table . ".title"), $id,
1288 8
            str_format (localize($numberOfString, $count), $count), "text",
1289 8
            array ( new LinkNavigation ("?page=".$pageId)), "", $count);
1290 8
        return $entry;
1291
    }
1292
1293 35
    public static function getEntryArrayWithBookNumber ($query, $columns, $params, $category) {
1294 35
        list (, $result) = self::executeQuery ($query, $columns, "", $params, -1);
1295 35
        $entryArray = array();
1296 35
        while ($post = $result->fetchObject ())
1297
        {
1298 25
            $instance = new $category ($post);
1299 25
            if (property_exists($post, "sort")) {
1300 17
                $title = $post->sort;
1301 17
            } else {
1302 8
                $title = $post->name;
1303
            }
1304 25
            array_push ($entryArray, new Entry ($title, $instance->getEntryId (),
1305 25
                str_format (localize("bookword", $post->count), $post->count), "text",
1306 25
                array ( new LinkNavigation ($instance->getUri ())), "", $post->count));
1307 25
        }
1308 35
        return $entryArray;
1309
    }
1310
1311 73
    public static function executeQuery($query, $columns, $filter, $params, $n, $database = NULL, $numberPerPage = NULL) {
1312 73
        $totalResult = -1;
1313
1314 73
        if (useNormAndUp ()) {
1315 7
            $query = preg_replace("/upper/", "normAndUp", $query);
1316 7
            $columns = preg_replace("/upper/", "normAndUp", $columns);
1317 7
        }
1318
1319 73
        if (is_null ($numberPerPage)) {
1320 71
            $numberPerPage = getCurrentOption ("max_item_per_page");
1321 71
        }
1322
1323 73
        if ($numberPerPage != -1 && $n != -1)
1324 73
        {
1325
            // First check total number of results
1326 28
            $result = self::getDb ($database)->prepare (str_format ($query, "count(*)", $filter));
1327 28
            $result->execute ($params);
1328 28
            $totalResult = $result->fetchColumn ();
1329
1330
            // Next modify the query and params
1331 28
            $query .= " limit ?, ?";
1332 28
            array_push ($params, ($n - 1) * $numberPerPage, $numberPerPage);
1333 28
        }
1334
1335 73
        $result = self::getDb ($database)->prepare(str_format ($query, $columns, $filter));
1336 73
        $result->execute ($params);
1337 73
        return array ($totalResult, $result);
1338
    }
1339
1340
}
1341