Completed
Push — master ( d648a6...70bf01 )
by Sébastien
07:21 queued 12s
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 51
    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
                unset ($translations [$key]);
298
            }
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/custom.png',
422
        Rating::ALL_RATING_ID        => 'images/rating.png',
423
        "cops:books$"             => 'images/allbook.png',
424
        "cops:books:letter"       => 'images/allbook.png',
425
        Publisher::ALL_PUBLISHERS_ID => 'images/publisher.png'
426
    );
427
428
    public function getUpdatedTime () {
429
        if (!is_null ($this->localUpdated)) {
430
            return date (DATE_ATOM, $this->localUpdated);
431
        }
432
        if (is_null (self::$updated)) {
433
            self::$updated = time();
434
        }
435
        return date (DATE_ATOM, self::$updated);
436
    }
437
438 7
    public function getNavLink () {
439 7
        foreach ($this->linkArray as $link) {
440 7
            if ($link->type != Link::OPDS_NAVIGATION_TYPE) { continue; }
441
442 7
            return $link->hrefXhtml ();
443
        }
444
        return "#";
445
    }
446
447 89
    public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pclass = "", $pcount = 0) {
448 89
        global $config;
449 89
        $this->title = $ptitle;
450 89
        $this->id = $pid;
451 89
        $this->content = $pcontent;
452 89
        $this->contentType = $pcontentType;
453 89
        $this->linkArray = $plinkArray;
454 89
        $this->className = $pclass;
455 89
        $this->numberOfElement = $pcount;
456
457 89
        if ($config['cops_show_icons'] == 1)
458 89
        {
459 89
            foreach (self::$icons as $reg => $image)
460
            {
461 89
                if (preg_match ("/" . $reg . "/", $pid)) {
462 51
                    array_push ($this->linkArray, new Link (getUrlWithVersion ($image), "image/png", Link::OPDS_THUMBNAIL_TYPE));
463 51
                    break;
464
                }
465 89
            }
466 89
        }
467
468 89
        if (!is_null (GetUrlParam (DB))) $this->id = str_replace ("cops:", "cops:" . GetUrlParam (DB) . ":", $this->id);
469 89
    }
470
}
471
472
class EntryBook extends Entry
473
{
474
    public $book;
475
476 39
    public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pbook) {
477 39
        parent::__construct ($ptitle, $pid, $pcontent, $pcontentType, $plinkArray);
478 39
        $this->book = $pbook;
479 39
        $this->localUpdated = $pbook->timestamp;
480 39
    }
481
482
    public function getCoverThumbnail () {
483
        foreach ($this->linkArray as $link) {
484
            if ($link->rel == Link::OPDS_THUMBNAIL_TYPE)
485
                return $link->hrefXhtml ();
486
        }
487
        return null;
488
    }
489
490
    public function getCover () {
491
        foreach ($this->linkArray as $link) {
492
            if ($link->rel == Link::OPDS_IMAGE_TYPE)
493
                return $link->hrefXhtml ();
494
        }
495
        return null;
496
    }
497
}
498
499
class Page
500
{
501
    public $title;
502
    public $subtitle = "";
503
    public $authorName = "";
504
    public $authorUri = "";
505
    public $authorEmail = "";
506
    public $idPage;
507
    public $idGet;
508
    public $query;
509
    public $favicon;
510
    public $n;
511
    public $book;
512
    public $totalNumber = -1;
513
    public $entryArray = array();
514
515 81
    public static function getPage ($pageId, $id, $query, $n)
516
    {
517
        switch ($pageId) {
518 81
            case Base::PAGE_ALL_AUTHORS :
519 3
                return new PageAllAuthors ($id, $query, $n);
520 78
            case Base::PAGE_AUTHORS_FIRST_LETTER :
521 1
                return new PageAllAuthorsLetter ($id, $query, $n);
522 77
            case Base::PAGE_AUTHOR_DETAIL :
523 7
                return new PageAuthorDetail ($id, $query, $n);
524 70
            case Base::PAGE_ALL_TAGS :
525 2
                return new PageAllTags ($id, $query, $n);
526 68
            case Base::PAGE_TAG_DETAIL :
527 1
                return new PageTagDetail ($id, $query, $n);
528 67
            case Base::PAGE_ALL_LANGUAGES :
529 2
                return new PageAllLanguages ($id, $query, $n);
530 65
            case Base::PAGE_LANGUAGE_DETAIL :
531 1
                return new PageLanguageDetail ($id, $query, $n);
532 64
            case Base::PAGE_ALL_CUSTOMS :
533 3
                return new PageAllCustoms ($id, $query, $n);
534 61
            case Base::PAGE_CUSTOM_DETAIL :
535 3
                return new PageCustomDetail ($id, $query, $n);
536 58
            case Base::PAGE_ALL_RATINGS :
537 1
                return new PageAllRating ($id, $query, $n);
538 57
            case Base::PAGE_RATING_DETAIL :
539 1
                return new PageRatingDetail ($id, $query, $n);
540 56
            case Base::PAGE_ALL_SERIES :
541 2
                return new PageAllSeries ($id, $query, $n);
542 54
            case Base::PAGE_ALL_BOOKS :
543 3
                return new PageAllBooks ($id, $query, $n);
544 51
            case Base::PAGE_ALL_BOOKS_LETTER:
545 1
                return new PageAllBooksLetter ($id, $query, $n);
546 50
            case Base::PAGE_ALL_RECENT_BOOKS :
547 4
                return new PageRecentBooks ($id, $query, $n);
548 46
            case Base::PAGE_SERIE_DETAIL :
549 1
                return new PageSerieDetail ($id, $query, $n);
550 45
            case Base::PAGE_OPENSEARCH_QUERY :
551 31
                return new PageQueryResult ($id, $query, $n);
552 14
            case Base::PAGE_BOOK_DETAIL :
553 1
                return new PageBookDetail ($id, $query, $n);
554 13
            case Base::PAGE_ALL_PUBLISHERS:
555 2
                return new PageAllPublishers ($id, $query, $n);
556 11
            case Base::PAGE_PUBLISHER_DETAIL :
557 1
                return new PagePublisherDetail ($id, $query, $n);
558 10
            case Base::PAGE_ABOUT :
559
                return new PageAbout ($id, $query, $n);
560 10
            case Base::PAGE_CUSTOMIZE :
561
                return new PageCustomize ($id, $query, $n);
562 10
            default:
563 10
                $page = new Page ($id, $query, $n);
564 10
                $page->idPage = "cops:catalog";
565 10
                return $page;
566 10
        }
567
    }
568
569 81
    public function __construct($pid, $pquery, $pn) {
570 81
        global $config;
571
572 81
        $this->idGet = $pid;
573 81
        $this->query = $pquery;
574 81
        $this->n = $pn;
575 81
        $this->favicon = $config['cops_icon'];
576 81
        $this->authorName = empty($config['cops_author_name']) ? utf8_encode('Sébastien Lucas') : $config['cops_author_name'];
577 81
        $this->authorUri = empty($config['cops_author_uri']) ? 'http://blog.slucas.fr' : $config['cops_author_uri'];
578 81
        $this->authorEmail = empty($config['cops_author_email']) ? '[email protected]' : $config['cops_author_email'];
579 81
    }
580
581 10
    public function InitializeContent ()
582
    {
583 10
        global $config;
584 10
        $this->title = $config['cops_title_default'];
585 10
        $this->subtitle = $config['cops_subtitle_default'];
586 10
        if (Base::noDatabaseSelected ()) {
587 2
            $i = 0;
588 2
            foreach (Base::getDbNameList () as $key) {
589 2
                $nBooks = Book::getBookCount ($i);
590 2
                array_push ($this->entryArray, new Entry ($key, "cops:{$i}:catalog",
591 2
                                        str_format (localize ("bookword", $nBooks), $nBooks), "text",
592 2
                                        array ( new LinkNavigation ("?" . DB . "={$i}")), "", $nBooks));
593 2
                $i++;
594 2
                Base::clearDb ();
595 2
            }
596 2
        } else {
597 8
            if (!in_array (PageQueryResult::SCOPE_AUTHOR, getCurrentOption ('ignored_categories'))) {
598 7
                array_push ($this->entryArray, Author::getCount());
599 7
            }
600 8
            if (!in_array (PageQueryResult::SCOPE_SERIES, getCurrentOption ('ignored_categories'))) {
601 7
                $series = Serie::getCount();
602 7
                if (!is_null ($series)) array_push ($this->entryArray, $series);
603 7
            }
604 8
            if (!in_array (PageQueryResult::SCOPE_PUBLISHER, getCurrentOption ('ignored_categories'))) {
605 7
                $publisher = Publisher::getCount();
606 7
                if (!is_null ($publisher)) array_push ($this->entryArray, $publisher);
607 7
            }
608 8
            if (!in_array (PageQueryResult::SCOPE_TAG, getCurrentOption ('ignored_categories'))) {
609 7
                $tags = Tag::getCount();
610 7
                if (!is_null ($tags)) array_push ($this->entryArray, $tags);
611 7
            }
612 8
            if (!in_array (PageQueryResult::SCOPE_RATING, getCurrentOption ('ignored_categories'))) {
613 8
                $rating = Rating::getCount();
614 8
                if (!is_null ($rating)) array_push ($this->entryArray, $rating);
615 8
            }
616 8
            if (!in_array ("language", getCurrentOption ('ignored_categories'))) {
617 7
                $languages = Language::getCount();
618 7
                if (!is_null ($languages)) array_push ($this->entryArray, $languages);
619 7
            }
620 8
            foreach ($config['cops_calibre_custom_column'] as $lookup) {
621 4
                $customId = CustomColumn::getCustomId ($lookup);
622 4
                if (!is_null ($customId)) {
623 4
                    array_push ($this->entryArray, CustomColumn::getCount($customId));
624 4
                }
625 8
            }
626 8
            $this->entryArray = array_merge ($this->entryArray, Book::getCount());
627
628 8
            if (Base::isMultipleDatabaseEnabled ()) $this->title =  Base::getDbName ();
629
        }
630 10
    }
631
632 17
    public function isPaginated ()
633
    {
634 17
        return (getCurrentOption ("max_item_per_page") != -1 &&
635 17
                $this->totalNumber != -1 &&
636 17
                $this->totalNumber > getCurrentOption ("max_item_per_page"));
637
    }
638
639 2
    public function getNextLink ()
640
    {
641 2
        $currentUrl = preg_replace ("/\&n=.*?$/", "", "?" . getQueryString ());
642 2
        if (($this->n) * getCurrentOption ("max_item_per_page") < $this->totalNumber) {
643 1
            return new LinkNavigation ($currentUrl . "&n=" . ($this->n + 1), "next", localize ("paging.next.alternate"));
644
        }
645 1
        return NULL;
646
    }
647
648 2
    public function getPrevLink ()
649
    {
650 2
        $currentUrl = preg_replace ("/\&n=.*?$/", "", "?" . getQueryString ());
651 2
        if ($this->n > 1) {
652 1
            return new LinkNavigation ($currentUrl . "&n=" . ($this->n - 1), "previous", localize ("paging.previous.alternate"));
653
        }
654 2
        return NULL;
655
    }
656
657 2
    public function getMaxPage ()
658
    {
659 2
        return ceil ($this->totalNumber / getCurrentOption ("max_item_per_page"));
660
    }
661
662 70
    public function containsBook ()
663
    {
664 70
        if (count ($this->entryArray) == 0) return false;
665 68
        if (get_class ($this->entryArray [0]) == "EntryBook") return true;
666 46
        return false;
667
    }
668
}
669
670
class PageAllAuthors extends Page
671
{
672 3
    public function InitializeContent ()
673
    {
674 3
        $this->title = localize("authors.title");
675 3
        if (getCurrentOption ("author_split_first_letter") == 1) {
676 2
            $this->entryArray = Author::getAllAuthorsByFirstLetter();
677 2
        }
678
        else {
679 1
            $this->entryArray = Author::getAllAuthors();
680
        }
681 3
        $this->idPage = Author::ALL_AUTHORS_ID;
682 3
    }
683
}
684
685
class PageAllAuthorsLetter extends Page
686
{
687 1
    public function InitializeContent ()
688
    {
689 1
        $this->idPage = Author::getEntryIdByLetter ($this->idGet);
690 1
        $this->entryArray = Author::getAuthorsByStartingLetter ($this->idGet);
691 1
        $this->title = str_format (localize ("splitByLetter.letter"), str_format (localize ("authorword", count ($this->entryArray)), count ($this->entryArray)), $this->idGet);
692 1
    }
693
}
694
695
class PageAuthorDetail extends Page
696
{
697 7
    public function InitializeContent ()
698
    {
699 7
        $author = Author::getAuthorById ($this->idGet);
700 7
        $this->idPage = $author->getEntryId ();
701 7
        $this->title = $author->name;
702 7
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByAuthor ($this->idGet, $this->n);
703 7
    }
704
}
705
706
class PageAllPublishers extends Page
707
{
708 2
    public function InitializeContent ()
709
    {
710 2
        $this->title = localize("publishers.title");
711 2
        $this->entryArray = Publisher::getAllPublishers();
712 2
        $this->idPage = Publisher::ALL_PUBLISHERS_ID;
713 2
    }
714
}
715
716
class PagePublisherDetail extends Page
717
{
718 1
    public function InitializeContent ()
719
    {
720 1
        $publisher = Publisher::getPublisherById ($this->idGet);
721 1
        $this->title = $publisher->name;
722 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByPublisher ($this->idGet, $this->n);
723 1
        $this->idPage = $publisher->getEntryId ();
724 1
    }
725
}
726
727
class PageAllTags extends Page
728
{
729 2
    public function InitializeContent ()
730
    {
731 2
        $this->title = localize("tags.title");
732 2
        $this->entryArray = Tag::getAllTags();
733 2
        $this->idPage = Tag::ALL_TAGS_ID;
734 2
    }
735
}
736
737
class PageAllLanguages extends Page
738
{
739 2
    public function InitializeContent ()
740
    {
741 2
        $this->title = localize("languages.title");
742 2
        $this->entryArray = Language::getAllLanguages();
743 2
        $this->idPage = Language::ALL_LANGUAGES_ID;
744 2
    }
745
}
746
747
class PageCustomDetail extends Page
748
{
749 3
    public function InitializeContent ()
750
    {
751 3
        $customId = getURLParam ("custom", NULL);
752 3
        $custom = CustomColumn::getCustomById ($customId, $this->idGet);
753 3
        $this->idPage = $custom->getEntryId ();
754 3
        $this->title = $custom->name;
755 3
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByCustom ($customId, $this->idGet, $this->n);
756 3
    }
757
}
758
759
class PageAllCustoms extends Page
760
{
761 3
    public function InitializeContent ()
762
    {
763 3
        $customId = getURLParam ("custom", NULL);
764 3
        $this->title = CustomColumn::getAllTitle ($customId);
765 3
        $this->entryArray = CustomColumn::getAllCustoms($customId);
766 3
        $this->idPage = CustomColumn::getAllCustomsId ($customId);
767 3
    }
768
}
769
770
class PageTagDetail extends Page
771
{
772 1
    public function InitializeContent ()
773
    {
774 1
        $tag = Tag::getTagById ($this->idGet);
775 1
        $this->idPage = $tag->getEntryId ();
776 1
        $this->title = $tag->name;
777 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByTag ($this->idGet, $this->n);
778 1
    }
779
}
780
781
class PageLanguageDetail extends Page
782
{
783 1
    public function InitializeContent ()
784
    {
785 1
        $language = Language::getLanguageById ($this->idGet);
786 1
        $this->idPage = $language->getEntryId ();
787 1
        $this->title = $language->lang_code;
788 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByLanguage ($this->idGet, $this->n);
789 1
    }
790
}
791
792
class PageAllSeries extends Page
793
{
794 2
    public function InitializeContent ()
795
    {
796 2
        $this->title = localize("series.title");
797 2
        $this->entryArray = Serie::getAllSeries();
798 2
        $this->idPage = Serie::ALL_SERIES_ID;
799 2
    }
800
}
801
802
class PageSerieDetail extends Page
803
{
804 1
    public function InitializeContent ()
805
    {
806 1
        $serie = Serie::getSerieById ($this->idGet);
807 1
        $this->title = $serie->name;
808 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksBySeries ($this->idGet, $this->n);
809 1
        $this->idPage = $serie->getEntryId ();
810 1
    }
811
}
812
813
class PageAllRating extends Page
814
{
815 1
    public function InitializeContent ()
816
    {
817 1
        $this->title = localize("ratings.title");
818 1
        $this->entryArray = Rating::getAllRatings();
819 1
        $this->idPage = Rating::ALL_RATING_ID;
820 1
    }
821
}
822
823
class PageRatingDetail extends Page
824
{
825 1
    public function InitializeContent ()
826
    {
827 1
        $rating = Rating::getRatingById ($this->idGet);
828 1
        $this->idPage = $rating->getEntryId ();
829 1
        $this->title =str_format (localize ("ratingword", $rating->name/2), $rating->name/2);
830 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByRating ($this->idGet, $this->n);
831 1
    }
832
}
833
834
class PageAllBooks extends Page
835
{
836 3
    public function InitializeContent ()
837
    {
838 3
        $this->title = localize ("allbooks.title");
839 3
        if (getCurrentOption ("titles_split_first_letter") == 1) {
840 2
            $this->entryArray = Book::getAllBooks();
841 2
        }
842
        else {
843 1
            list ($this->entryArray, $this->totalNumber) = Book::getBooks ($this->n);
844
        }
845 3
        $this->idPage = Book::ALL_BOOKS_ID;
846 3
    }
847
}
848
849
class PageAllBooksLetter extends Page
850
{
851 1
    public function InitializeContent ()
852
    {
853 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByStartingLetter ($this->idGet, $this->n);
854 1
        $this->idPage = Book::getEntryIdByLetter ($this->idGet);
855
856 1
        $count = $this->totalNumber;
857 1
        if ($count == -1)
858 1
            $count = count ($this->entryArray);
859
860 1
        $this->title = str_format (localize ("splitByLetter.letter"), str_format (localize ("bookword", $count), $count), $this->idGet);
861 1
    }
862
}
863
864
class PageRecentBooks extends Page
865
{
866 4
    public function InitializeContent ()
867
    {
868 4
        $this->title = localize ("recent.title");
869 4
        $this->entryArray = Book::getAllRecentBooks ();
870 4
        $this->idPage = Book::ALL_RECENT_BOOKS_ID;
871 4
    }
872
}
873
874
class PageQueryResult extends Page
875
{
876
    const SCOPE_TAG = "tag";
877
    const SCOPE_RATING = "rating";
878
    const SCOPE_SERIES = "series";
879
    const SCOPE_AUTHOR = "author";
880
    const SCOPE_BOOK = "book";
881
    const SCOPE_PUBLISHER = "publisher";
882
883 24
    private function useTypeahead () {
884 24
        return !is_null (getURLParam ("search"));
885
    }
886
887 29
    private function searchByScope ($scope, $limit = FALSE) {
888 29
        $n = $this->n;
889 29
        $numberPerPage = NULL;
890 29
        $queryNormedAndUp = $this->query;
891 29
        if (useNormAndUp ()) {
892 7
            $queryNormedAndUp = normAndUp ($this->query);
893 7
        }
894 29
        if ($limit) {
895 22
            $n = 1;
896 22
            $numberPerPage = 5;
897 22
        }
898
        switch ($scope) {
899 29
            case self::SCOPE_BOOK :
900 23
                $array = Book::getBooksByStartingLetter ('%' . $queryNormedAndUp, $n, NULL, $numberPerPage);
901 23
                break;
902 28
            case self::SCOPE_AUTHOR :
903 23
                $array = Author::getAuthorsForSearch ('%' . $queryNormedAndUp);
904 23
                break;
905 25
            case self::SCOPE_SERIES :
906 22
                $array = Serie::getAllSeriesByQuery ($queryNormedAndUp);
907 22
                break;
908 24
            case self::SCOPE_TAG :
909 23
                $array = Tag::getAllTagsByQuery ($queryNormedAndUp, $n, NULL, $numberPerPage);
910 23
                break;
911 23
            case self::SCOPE_PUBLISHER :
912 23
                $array = Publisher::getAllPublishersByQuery ($queryNormedAndUp);
913 23
                break;
914
            default:
915
                $array = Book::getBooksByQuery (
916
                    array ("all" => "%" . $queryNormedAndUp . "%"), $n);
917
        }
918
919 29
        return $array;
920
    }
921
922 22
    public function doSearchByCategory () {
923 22
        $database = GetUrlParam (DB);
924 22
        $out = array ();
925 22
        $pagequery = Base::PAGE_OPENSEARCH_QUERY;
926 22
        $dbArray = array ("");
927 22
        $d = $database;
928 22
        $query = $this->query;
929
        // Special case when no databases were chosen, we search on all databases
930 22
        if (Base::noDatabaseSelected ()) {
931 1
            $dbArray = Base::getDbNameList ();
932 1
            $d = 0;
933 1
        }
934 22
        foreach ($dbArray as $key) {
935 22
            if (Base::noDatabaseSelected ()) {
936 1
                array_push ($this->entryArray, new Entry ($key, DB . ":query:{$d}",
937 1
                                        " ", "text",
938 1
                                        array ( new LinkNavigation ("?" . DB . "={$d}")), "tt-header"));
939 1
                Base::getDb ($d);
940 1
            }
941 22
            foreach (array (PageQueryResult::SCOPE_BOOK,
942 22
                            PageQueryResult::SCOPE_AUTHOR,
943 22
                            PageQueryResult::SCOPE_SERIES,
944 22
                            PageQueryResult::SCOPE_TAG,
945 22
                            PageQueryResult::SCOPE_PUBLISHER) as $key) {
946 22
                if (in_array($key, getCurrentOption ('ignored_categories'))) {
947 3
                    continue;
948
                }
949 22
                $array = $this->searchByScope ($key, TRUE);
950
951 22
                $i = 0;
952 22
                if (count ($array) == 2 && is_array ($array [0])) {
953 22
                    $total = $array [1];
954 22
                    $array = $array [0];
955 22
                } else {
956 22
                    $total = count($array);
957
                }
958 22
                if ($total > 0) {
959
                    // Comment to help the perl i18n script
960
                    // str_format (localize("bookword", count($array))
961
                    // str_format (localize("authorword", count($array))
962
                    // str_format (localize("seriesword", count($array))
963
                    // str_format (localize("tagword", count($array))
964
                    // str_format (localize("publisherword", count($array))
965 21
                    array_push ($this->entryArray, new Entry (str_format (localize ("search.result.{$key}"), $this->query), DB . ":query:{$d}:{$key}",
966 21
                                        str_format (localize("{$key}word", $total), $total), "text",
967 21
                                        array ( new LinkNavigation ("?page={$pagequery}&query={$query}&db={$d}&scope={$key}")),
968 21
                                        Base::noDatabaseSelected () ? "" : "tt-header", $total));
969 21
                }
970 22
                if (!Base::noDatabaseSelected () && $this->useTypeahead ()) {
971 6
                    foreach ($array as $entry) {
972 6
                        array_push ($this->entryArray, $entry);
973 6
                        $i++;
974 6
                        if ($i > 4) { break; };
975 6
                    }
976 6
                }
977 22
            }
978 22
            $d++;
979 22
            if (Base::noDatabaseSelected ()) {
980 1
                Base::clearDb ();
981 1
            }
982 22
        }
983 22
        return $out;
984
    }
985
986 31
    public function InitializeContent ()
987
    {
988 31
        $scope = getURLParam ("scope");
989 31
        if (empty ($scope)) {
990 24
            $this->title = str_format (localize ("search.result"), $this->query);
991 24
        } else {
992
            // Comment to help the perl i18n script
993
            // str_format (localize ("search.result.author"), $this->query)
994
            // str_format (localize ("search.result.tag"), $this->query)
995
            // str_format (localize ("search.result.series"), $this->query)
996
            // str_format (localize ("search.result.book"), $this->query)
997
            // str_format (localize ("search.result.publisher"), $this->query)
998 7
            $this->title = str_format (localize ("search.result.{$scope}"), $this->query);
999
        }
1000
1001 31
        $crit = "%" . $this->query . "%";
1002
1003
        // Special case when we are doing a search and no database is selected
1004 31
        if (Base::noDatabaseSelected () && !$this->useTypeahead ()) {
1005 2
            $i = 0;
1006 2
            foreach (Base::getDbNameList () as $key) {
1007 2
                Base::clearDb ();
1008 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...
1009 2
                array_push ($this->entryArray, new Entry ($key, DB . ":query:{$i}",
1010 2
                                        str_format (localize ("bookword", $totalNumber), $totalNumber), "text",
1011 2
                                        array ( new LinkNavigation ("?" . DB . "={$i}&page=9&query=" . $this->query)), "", $totalNumber));
1012 2
                $i++;
1013 2
            }
1014 2
            return;
1015
        }
1016 29
        if (empty ($scope)) {
1017 22
            $this->doSearchByCategory ();
1018 22
            return;
1019
        }
1020
1021 7
        $array = $this->searchByScope ($scope);
1022 7
        if (count ($array) == 2 && is_array ($array [0])) {
1023 2
            list ($this->entryArray, $this->totalNumber) = $array;
1024 2
        } else {
1025 5
            $this->entryArray = $array;
1026
        }
1027 7
    }
1028
}
1029
1030
class PageBookDetail extends Page
1031
{
1032 1
    public function InitializeContent ()
1033
    {
1034 1
        $this->book = Book::getBookById ($this->idGet);
1035 1
        $this->title = $this->book->title;
1036 1
    }
1037
}
1038
1039
class PageAbout extends Page
1040
{
1041
    public function InitializeContent ()
1042
    {
1043
        $this->title = localize ("about.title");
1044
    }
1045
}
1046
1047
class PageCustomize extends Page
1048
{
1049
    private function isChecked ($key, $testedValue = 1) {
1050
        $value = getCurrentOption ($key);
1051
        if (is_array ($value)) {
1052
            if (in_array ($testedValue, $value)) {
1053
                return "checked='checked'";
1054
            }
1055
        } else {
1056
            if ($value == $testedValue) {
1057
                return "checked='checked'";
1058
            }
1059
        }
1060
        return "";
1061
    }
1062
1063
    private function isSelected ($key, $value) {
1064
        if (getCurrentOption ($key) == $value) {
1065
            return "selected='selected'";
1066
        }
1067
        return "";
1068
    }
1069
1070
    private function getStyleList () {
1071
        $result = array ();
1072
        foreach (glob ("templates/" . getCurrentTemplate () . "/styles/style-*.css") as $filename) {
1073
            if (preg_match ('/styles\/style-(.*?)\.css/', $filename, $m)) {
1074
                array_push ($result, $m [1]);
1075
            }
1076
        }
1077
        return $result;
1078
    }
1079
1080
    public function InitializeContent ()
1081
    {
1082
        $this->title = localize ("customize.title");
1083
        $this->entryArray = array ();
1084
1085
        $ignoredBaseArray = array (PageQueryResult::SCOPE_AUTHOR,
1086
                                   PageQueryResult::SCOPE_TAG,
1087
                                   PageQueryResult::SCOPE_SERIES,
1088
                                   PageQueryResult::SCOPE_PUBLISHER,
1089
                                   PageQueryResult::SCOPE_RATING,
1090
                                   "language");
1091
1092
        $content = "";
1093
        array_push ($this->entryArray, new Entry ("Template", "",
1094
                                        "<span style='cursor: pointer;' onclick='$.cookie(\"template\", \"bootstrap\", { expires: 365 });window.location=$(\".headleft\").attr(\"href\");'>Click to switch to Bootstrap</span>", "text",
1095
                                        array ()));
1096
        if (!preg_match("/(Kobo|Kindle\/3.0|EBRD1101)/", $_SERVER['HTTP_USER_AGENT'])) {
1097
            $content .= '<select id="style" onchange="updateCookie (this);">';
1098
            foreach ($this-> getStyleList () as $filename) {
1099
                $content .= "<option value='{$filename}' " . $this->isSelected ("style", $filename) . ">{$filename}</option>";
1100
            }
1101
            $content .= '</select>';
1102
        } else {
1103
            foreach ($this-> getStyleList () as $filename) {
1104
                $content .= "<input type='radio' onchange='updateCookieFromCheckbox (this);' id='style-{$filename}' name='style' value='{$filename}' " . $this->isChecked ("style", $filename) . " /><label for='style-{$filename}'> {$filename} </label>";
1105
            }
1106
        }
1107
        array_push ($this->entryArray, new Entry (localize ("customize.style"), "",
1108
                                        $content, "text",
1109
                                        array ()));
1110
        if (!useServerSideRendering ()) {
1111
            $content = '<input type="checkbox" onchange="updateCookieFromCheckbox (this);" id="use_fancyapps" ' . $this->isChecked ("use_fancyapps") . ' />';
1112
            array_push ($this->entryArray, new Entry (localize ("customize.fancybox"), "",
1113
                                            $content, "text",
1114
                                            array ()));
1115
        }
1116
        $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]+$" />';
1117
        array_push ($this->entryArray, new Entry (localize ("customize.paging"), "",
1118
                                        $content, "text",
1119
                                        array ()));
1120
        $content = '<input type="text" onchange="updateCookie (this);" id="email" value="' . getCurrentOption ("email") . '" />';
1121
        array_push ($this->entryArray, new Entry (localize ("customize.email"), "",
1122
                                        $content, "text",
1123
                                        array ()));
1124
        $content = '<input type="checkbox" onchange="updateCookieFromCheckbox (this);" id="html_tag_filter" ' . $this->isChecked ("html_tag_filter") . ' />';
1125
        array_push ($this->entryArray, new Entry (localize ("customize.filter"), "",
1126
                                        $content, "text",
1127
                                        array ()));
1128
        $content = "";
1129
        foreach ($ignoredBaseArray as $key) {
1130
            $keyPlural = preg_replace ('/(ss)$/', 's', $key . "s");
1131
            $content .=  '<input type="checkbox" name="ignored_categories[]" onchange="updateCookieFromCheckboxGroup (this);" id="ignored_categories_' . $key . '" ' . $this->isChecked ("ignored_categories", $key) . ' > ' . localize ("{$keyPlural}.title") . '</input> ';
1132
        }
1133
1134
        array_push ($this->entryArray, new Entry (localize ("customize.ignored"), "",
1135
                                        $content, "text",
1136
                                        array ()));
1137
    }
1138
}
1139
1140
1141
abstract class Base
1142
{
1143
    const PAGE_INDEX = "index";
1144
    const PAGE_ALL_AUTHORS = "1";
1145
    const PAGE_AUTHORS_FIRST_LETTER = "2";
1146
    const PAGE_AUTHOR_DETAIL = "3";
1147
    const PAGE_ALL_BOOKS = "4";
1148
    const PAGE_ALL_BOOKS_LETTER = "5";
1149
    const PAGE_ALL_SERIES = "6";
1150
    const PAGE_SERIE_DETAIL = "7";
1151
    const PAGE_OPENSEARCH = "8";
1152
    const PAGE_OPENSEARCH_QUERY = "9";
1153
    const PAGE_ALL_RECENT_BOOKS = "10";
1154
    const PAGE_ALL_TAGS = "11";
1155
    const PAGE_TAG_DETAIL = "12";
1156
    const PAGE_BOOK_DETAIL = "13";
1157
    const PAGE_ALL_CUSTOMS = "14";
1158
    const PAGE_CUSTOM_DETAIL = "15";
1159
    const PAGE_ABOUT = "16";
1160
    const PAGE_ALL_LANGUAGES = "17";
1161
    const PAGE_LANGUAGE_DETAIL = "18";
1162
    const PAGE_CUSTOMIZE = "19";
1163
    const PAGE_ALL_PUBLISHERS = "20";
1164
    const PAGE_PUBLISHER_DETAIL = "21";
1165
    const PAGE_ALL_RATINGS = "22";
1166
    const PAGE_RATING_DETAIL = "23";
1167
1168
    const COMPATIBILITY_XML_ALDIKO = "aldiko";
1169
1170
    private static $db = NULL;
1171
1172 108
    public static function isMultipleDatabaseEnabled () {
1173 108
        global $config;
1174 108
        return is_array ($config['calibre_directory']);
1175
    }
1176
1177 46
    public static function useAbsolutePath () {
1178 46
        global $config;
1179 46
        $path = self::getDbDirectory();
1180 46
        return preg_match ('/^\//', $path) || // Linux /
1181 46
               preg_match ('/^\w\:/', $path); // Windows X:
1182
    }
1183
1184 45
    public static function noDatabaseSelected () {
1185 45
        return self::isMultipleDatabaseEnabled () && is_null (GetUrlParam (DB));
1186
    }
1187
1188 4
    public static function getDbList () {
1189 4
        global $config;
1190 4
        if (self::isMultipleDatabaseEnabled ()) {
1191 4
            return $config['calibre_directory'];
1192
        } else {
1193 1
            return array ("" => $config['calibre_directory']);
1194
        }
1195
    }
1196
1197 5
    public static function getDbNameList () {
1198 5
        global $config;
1199 5
        if (self::isMultipleDatabaseEnabled ()) {
1200 5
            return array_keys ($config['calibre_directory']);
1201
        } else {
1202
            return array ("");
1203
        }
1204
    }
1205
1206 1
    public static function getDbName ($database = NULL) {
1207 1
        global $config;
1208 1
        if (self::isMultipleDatabaseEnabled ()) {
1209 1
            if (is_null ($database)) $database = GetUrlParam (DB, 0);
1210 1
            if (!is_null($database) && !preg_match('/^\d+$/', $database)) {
1211
                return self::error ($database);
1212
            }
1213 1
            $array = array_keys ($config['calibre_directory']);
1214 1
            return  $array[$database];
1215
        }
1216
        return "";
1217
    }
1218
1219 90
    public static function getDbDirectory ($database = NULL) {
1220 90
        global $config;
1221 90
        if (self::isMultipleDatabaseEnabled ()) {
1222 9
            if (is_null ($database)) $database = GetUrlParam (DB, 0);
1223 9
            if (!is_null($database) && !preg_match('/^\d+$/', $database)) {
1224
                return self::error ($database);
1225
            }
1226 9
            $array = array_values ($config['calibre_directory']);
1227 9
            return  $array[$database];
1228
        }
1229 81
        return $config['calibre_directory'];
1230
    }
1231
1232
1233 61
    public static function getDbFileName ($database = NULL) {
1234 61
        return self::getDbDirectory ($database) .'metadata.db';
1235
    }
1236
1237 2
    private static function error ($database) {
1238 2
        if (php_sapi_name() != "cli") {
1239
            header("location: checkconfig.php?err=1");
1240
        }
1241 2
        throw new Exception("Database <{$database}> not found.");
1242
    }
1243
1244 126
    public static function getDb ($database = NULL) {
1245 126
        if (is_null (self::$db)) {
1246
            try {
1247 61
                if (is_readable (self::getDbFileName ($database))) {
1248 60
                    self::$db = new PDO('sqlite:'. self::getDbFileName ($database));
1249 60
                    if (useNormAndUp ()) {
1250 7
                        self::$db->sqliteCreateFunction ('normAndUp', 'normAndUp', 1);
1251 7
                    }
1252 60
                } else {
1253 2
                    self::error ($database);
1254
                }
1255 61
            } catch (Exception $e) {
1256 2
                self::error ($database);
1257
            }
1258 60
        }
1259 125
        return self::$db;
1260
    }
1261
1262 4
    public static function checkDatabaseAvailability () {
1263 4
        if (self::noDatabaseSelected ()) {
1264 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...
1265 3
                self::getDb ($i);
1266 2
                self::clearDb ();
1267 2
            }
1268 1
        } else {
1269 1
            self::getDb ();
1270
        }
1271 2
        return true;
1272
    }
1273
1274 58
    public static function clearDb () {
1275 58
        self::$db = NULL;
1276 58
    }
1277
1278 13
    public static function executeQuerySingle ($query, $database = NULL) {
1279 13
        return self::getDb ($database)->query($query)->fetchColumn();
1280
    }
1281
1282 8
    public static function getCountGeneric($table, $id, $pageId, $numberOfString = NULL) {
1283 8
        if (!$numberOfString) {
1284 7
            $numberOfString = $table . ".alphabetical";
1285 7
        }
1286 8
        $count = self::executeQuerySingle ('select count(*) from ' . $table);
1287 8
        if ($count == 0) return NULL;
1288 8
        $entry = new Entry (localize($table . ".title"), $id,
1289 8
            str_format (localize($numberOfString, $count), $count), "text",
1290 8
            array ( new LinkNavigation ("?page=".$pageId)), "", $count);
1291 8
        return $entry;
1292
    }
1293
1294 35
    public static function getEntryArrayWithBookNumber ($query, $columns, $params, $category) {
1295 35
        list (, $result) = self::executeQuery ($query, $columns, "", $params, -1);
1296 35
        $entryArray = array();
1297 35
        while ($post = $result->fetchObject ())
1298
        {
1299 25
            $instance = new $category ($post);
1300 25
            if (property_exists($post, "sort")) {
1301 17
                $title = $post->sort;
1302 17
            } else {
1303 8
                $title = $post->name;
1304
            }
1305 25
            array_push ($entryArray, new Entry ($title, $instance->getEntryId (),
1306 25
                str_format (localize("bookword", $post->count), $post->count), "text",
1307 25
                array ( new LinkNavigation ($instance->getUri ())), "", $post->count));
1308 25
        }
1309 35
        return $entryArray;
1310
    }
1311
1312 73
    public static function executeQuery($query, $columns, $filter, $params, $n, $database = NULL, $numberPerPage = NULL) {
1313 73
        $totalResult = -1;
1314
1315 73
        if (useNormAndUp ()) {
1316 7
            $query = preg_replace("/upper/", "normAndUp", $query);
1317 7
            $columns = preg_replace("/upper/", "normAndUp", $columns);
1318 7
        }
1319
1320 73
        if (is_null ($numberPerPage)) {
1321 71
            $numberPerPage = getCurrentOption ("max_item_per_page");
1322 71
        }
1323
1324 73
        if ($numberPerPage != -1 && $n != -1)
1325 73
        {
1326
            // First check total number of results
1327 28
            $result = self::getDb ($database)->prepare (str_format ($query, "count(*)", $filter));
1328 28
            $result->execute ($params);
1329 28
            $totalResult = $result->fetchColumn ();
1330
1331
            // Next modify the query and params
1332 28
            $query .= " limit ?, ?";
1333 28
            array_push ($params, ($n - 1) * $numberPerPage, $numberPerPage);
1334 28
        }
1335
1336 73
        $result = self::getDb ($database)->prepare(str_format ($query, $columns, $filter));
1337 73
        $result->execute ($params);
1338 73
        return array ($totalResult, $result);
1339
    }
1340
1341
}
1342