Completed
Pull Request — master (#212)
by Markus
09:04
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 (isset($config ["cops_" . $option])) {
78 85
        return $config ["cops_" . $option];
79
    }
80
81
    return "";
82
}
83
84
function getCurrentCss () {
85 2
    return "templates/" . getCurrentTemplate () . "/styles/style-" . getCurrentOption ("style") . ".css";
86
}
87
88
function getCurrentTemplate () {
89 4
    return getCurrentOption ("template");
90
}
91
92
function getUrlWithVersion ($url) {
93 51
    return $url . "?v=" . VERSION;
94
}
95
96
function xml2xhtml($xml) {
97 35
    return preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', create_function('$m', '
98
        $xhtml_tags = array("br", "hr", "input", "frame", "img", "area", "link", "col", "base", "basefont", "param");
99
        return in_array($m[1], $xhtml_tags) ? "<$m[1]$m[2] />" : "<$m[1]$m[2]></$m[1]>";
100 35
    '), $xml);
101
}
102
103
function display_xml_error($error)
104
{
105
    $return = "";
106
    $return .= str_repeat('-', $error->column) . "^\n";
107
108
    switch ($error->level) {
109
        case LIBXML_ERR_WARNING:
110
            $return .= "Warning $error->code: ";
111
            break;
112
         case LIBXML_ERR_ERROR:
113
            $return .= "Error $error->code: ";
114
            break;
115
        case LIBXML_ERR_FATAL:
116
            $return .= "Fatal Error $error->code: ";
117
            break;
118
    }
119
120
    $return .= trim($error->message) .
121
               "\n  Line: $error->line" .
122
               "\n  Column: $error->column";
123
124
    if ($error->file) {
125
        $return .= "\n  File: $error->file";
126
    }
127
128
    return "$return\n\n--------------------------------------------\n\n";
129
}
130
131
function are_libxml_errors_ok ()
132
{
133 35
    $errors = libxml_get_errors();
134
135 35
    foreach ($errors as $error) {
136
        if ($error->code == 801) return false;
137 35
    }
138 35
    return true;
139
}
140
141
function html2xhtml ($html) {
142 35
    $doc = new DOMDocument();
143 35
    libxml_use_internal_errors(true);
144
145 35
    $doc->loadHTML('<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body>' .
146 35
                        $html  . '</body></html>'); // Load the HTML
147 35
    $output = $doc->saveXML($doc->documentElement); // Transform to an Ansi xml stream
148 35
    $output = xml2xhtml($output);
149 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)) {
150 35
        $output = $matches [1]; // Remove <html><body>
151 35
    }
152
    /*
153
    // In case of error with summary, use it to debug
154
    $errors = libxml_get_errors();
155
156
    foreach ($errors as $error) {
157
        $output .= display_xml_error($error);
158
    }
159
    */
160
161 35
    if (!are_libxml_errors_ok ()) $output = "HTML code not valid.";
162
163 35
    libxml_use_internal_errors(false);
164 35
    return $output;
165
}
166
167
/**
168
 * This method is a direct copy-paste from
169
 * http://tmont.com/blargh/2010/1/string-format-in-php
170
 */
171
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...
172 94
    $args = func_get_args();
173 94
    $format = array_shift($args);
174
175 94
    preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE);
176 94
    $offset = 0;
177 94
    foreach ($matches[1] as $data) {
178 94
        $i = $data[0];
179 94
        $format = substr_replace($format, @$args[$i], $offset + $data[1] - 1, 2 + strlen($i));
180 94
        $offset += strlen(@$args[$i]) - 2 - strlen($i);
181 94
    }
182
183 94
    return $format;
184
}
185
186
/**
187
 * Get all accepted languages from the browser and put them in a sorted array
188
 * languages id are normalized : fr-fr -> fr_FR
189
 * @return array of languages
190
 */
191
function getAcceptLanguages() {
192 16
    $langs = array();
193
194 16
    if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
195
        // break up string into pieces (languages and q factors)
196 16
        $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
197 16
        if (preg_match('/^(\w{2})-\w{2}$/', $accept, $matches)) {
198
            // Special fix for IE11 which send fr-FR and nothing else
199 3
            $accept = $accept . "," . $matches[1] . ";q=0.8";
200 3
        }
201 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);
202
203 16
        if (count($lang_parse[1])) {
204 16
            $langs = array();
205 16
            foreach ($lang_parse[1] as $lang) {
206
                // Format the language code (not standard among browsers)
207 16
                if (strlen($lang) == 5) {
208 11
                    $lang = str_replace("-", "_", $lang);
209 11
                    $splitted = preg_split("/_/", $lang);
210 11
                    $lang = $splitted[0] . "_" . strtoupper($splitted[1]);
211 11
                }
212 16
                array_push($langs, $lang);
213 16
            }
214
            // create a list like "en" => 0.8
215 16
            $langs = array_combine($langs, $lang_parse[4]);
216
217
            // set default to 1 for any without q factor
218 16
            foreach ($langs as $lang => $val) {
219 16
                if ($val === '') $langs[$lang] = 1;
220 16
            }
221
222
            // sort list based on value
223 16
            arsort($langs, SORT_NUMERIC);
224 16
        }
225 16
    }
226
227 16
    return $langs;
228
}
229
230
/**
231
 * Find the best translation file possible based on the accepted languages
232
 * @return array of language and language file
233
 */
234
function getLangAndTranslationFile() {
235 17
    global $config;
236 17
    $langs = array();
237 17
    $lang = "en";
238 17
    if (!empty($config['cops_language'])) {
239
        $lang = $config['cops_language'];
240
    }
241 17
    elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
242 16
        $langs = getAcceptLanguages();
243 16
    }
244
    //echo var_dump($langs);
245 17
    $lang_file = NULL;
246 17
    foreach ($langs as $language => $val) {
247 16
        $temp_file = dirname(__FILE__). '/lang/Localization_' . $language . '.json';
248 16
        if (file_exists($temp_file)) {
249 16
            $lang = $language;
250 16
            $lang_file = $temp_file;
251 16
            break;
252
        }
253 17
    }
254 17
    if (empty ($lang_file)) {
255 3
        $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json';
256 3
    }
257 17
    return array($lang, $lang_file);
258
}
259
260
/**
261
 * This method is based on this page
262
 * http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/
263
 */
264
function localize($phrase, $count=-1, $reset=false) {
265 114
    global $config;
266 114
    if ($count == 0)
267 114
        $phrase .= ".none";
268 114
    if ($count == 1)
269 114
        $phrase .= ".one";
270 114
    if ($count > 1)
271 114
        $phrase .= ".many";
272
273
    /* Static keyword is used to ensure the file is loaded only once */
274 114
    static $translations = NULL;
275 114
    if ($reset) {
276 16
        $translations = NULL;
277 16
    }
278
    /* If no instance of $translations has occured load the language file */
279 114
    if (is_null($translations)) {
280 17
        $lang_file_en = NULL;
281 17
        list ($lang, $lang_file) = getLangAndTranslationFile();
282 17
        if ($lang != "en") {
283 1
            $lang_file_en = dirname(__FILE__). '/lang/' . 'Localization_en.json';
284 1
        }
285
286 17
        $lang_file_content = file_get_contents($lang_file);
287
        /* Load the language file as a JSON object and transform it into an associative array */
288 17
        $translations = json_decode($lang_file_content, true);
289
290
        /* Clean the array of all unfinished translations */
291 17
        foreach (array_keys ($translations) as $key) {
292 17
            if (preg_match ("/^##TODO##/", $key)) {
293
                unset ($translations [$key]);
294
            }
295 17
        }
296
        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...
297 17
        {
298 1
            $lang_file_content = file_get_contents($lang_file_en);
299 1
            $translations_en = json_decode($lang_file_content, true);
300 1
            $translations = array_merge ($translations_en, $translations);
301 1
        }
302 17
    }
303 114
    if (array_key_exists ($phrase, $translations)) {
304 114
        return $translations[$phrase];
305
    }
306 1
    return $phrase;
307
}
308
309
function addURLParameter($urlParams, $paramName, $paramValue) {
310 58
    if (empty ($urlParams)) {
311 48
        $urlParams = "";
312 48
    }
313 58
    $start = "";
314 58
    if (preg_match ("#^\?(.*)#", $urlParams, $matches)) {
315 15
        $start = "?";
316 15
        $urlParams = $matches[1];
317 15
    }
318 58
    $params = array();
319 58
    parse_str($urlParams, $params);
320 58
    if (empty ($paramValue) && $paramValue != 0) {
321
        unset ($params[$paramName]);
322
    } else {
323 58
        $params[$paramName] = $paramValue;
324
    }
325 58
    return $start . http_build_query($params);
326
}
327
328
function useNormAndUp () {
329 113
    global $config;
330 113
    return $config ['cops_normalized_search'] == "1";
331
}
332
333
function normalizeUtf8String( $s) {
334 8
    include_once 'transliteration.php';
335 8
    return _transliteration_process($s);
336
}
337
338
function normAndUp ($s) {
339 7
    return mb_strtoupper (normalizeUtf8String($s), 'UTF-8');
340
}
341
342
class Link
343
{
344
    const OPDS_THUMBNAIL_TYPE = "http://opds-spec.org/image/thumbnail";
345
    const OPDS_IMAGE_TYPE = "http://opds-spec.org/image";
346
    const OPDS_ACQUISITION_TYPE = "http://opds-spec.org/acquisition";
347
    const OPDS_NAVIGATION_TYPE = "application/atom+xml;profile=opds-catalog;kind=navigation";
348
    const OPDS_PAGING_TYPE = "application/atom+xml;profile=opds-catalog;kind=acquisition";
349
350
    public $href;
351
    public $type;
352
    public $rel;
353
    public $title;
354
    public $facetGroup;
355
    public $activeFacet;
356
357 96
    public function __construct($phref, $ptype, $prel = NULL, $ptitle = NULL, $pfacetGroup = NULL, $pactiveFacet = FALSE) {
358 96
        $this->href = $phref;
359 96
        $this->type = $ptype;
360 96
        $this->rel = $prel;
361 96
        $this->title = $ptitle;
362 96
        $this->facetGroup = $pfacetGroup;
363 96
        $this->activeFacet = $pactiveFacet;
364 96
    }
365
366 10
    public function hrefXhtml () {
367 10
        return $this->href;
368
    }
369
370 95
    public function getScriptName() {
371 95
        $parts = explode('/', $_SERVER["SCRIPT_NAME"]);
372 95
        return $parts[count($parts) - 1];
373
    }
374
}
375
376
class LinkNavigation extends Link
377
{
378 95
    public function __construct($phref, $prel = NULL, $ptitle = NULL) {
379 95
        parent::__construct ($phref, Link::OPDS_NAVIGATION_TYPE, $prel, $ptitle);
380 95
        if (!is_null (GetUrlParam (DB))) $this->href = addURLParameter ($this->href, DB, GetUrlParam (DB));
381 95
        if (!preg_match ("#^\?(.*)#", $this->href) && !empty ($this->href)) $this->href = "?" . $this->href;
382 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...
383
            $this->href = "index.php" . $this->href;
384
        } else {
385 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...
386
        }
387 95
    }
388
}
389
390
class LinkFacet extends Link
391
{
392 1
    public function __construct($phref, $ptitle = NULL, $pfacetGroup = NULL, $pactiveFacet = FALSE) {
393 1
        parent::__construct ($phref, Link::OPDS_PAGING_TYPE, "http://opds-spec.org/facet", $ptitle, $pfacetGroup, $pactiveFacet);
394 1
        if (!is_null (GetUrlParam (DB))) $this->href = addURLParameter ($this->href, DB, GetUrlParam (DB));
395 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...
396 1
    }
397
}
398
399
class Entry
400
{
401
    public $title;
402
    public $id;
403
    public $content;
404
    public $numberOfElement;
405
    public $contentType;
406
    public $linkArray;
407
    public $localUpdated;
408
    public $className;
409
    private static $updated = NULL;
410
411
    public static $icons = array(
412
        Author::ALL_AUTHORS_ID       => 'images/author.png',
413
        Serie::ALL_SERIES_ID         => 'images/serie.png',
414
        Book::ALL_RECENT_BOOKS_ID    => 'images/recent.png',
415
        Tag::ALL_TAGS_ID             => 'images/tag.png',
416
        Language::ALL_LANGUAGES_ID   => 'images/language.png',
417
        CustomColumn::ALL_CUSTOMS_ID => 'images/custom.png',
418
        Rating::ALL_RATING_ID        => 'images/rating.png',
419
        "cops:books$"             => 'images/allbook.png',
420
        "cops:books:letter"       => 'images/allbook.png',
421
        Publisher::ALL_PUBLISHERS_ID => 'images/publisher.png'
422
    );
423
424
    public function getUpdatedTime () {
425
        if (!is_null ($this->localUpdated)) {
426
            return date (DATE_ATOM, $this->localUpdated);
427
        }
428
        if (is_null (self::$updated)) {
429
            self::$updated = time();
430
        }
431
        return date (DATE_ATOM, self::$updated);
432
    }
433
434 7
    public function getNavLink () {
435 7
        foreach ($this->linkArray as $link) {
436 7
            if ($link->type != Link::OPDS_NAVIGATION_TYPE) { continue; }
437
438 7
            return $link->hrefXhtml ();
439
        }
440
        return "#";
441
    }
442
443 89
    public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pclass = "", $pcount = 0) {
444 89
        global $config;
445 89
        $this->title = $ptitle;
446 89
        $this->id = $pid;
447 89
        $this->content = $pcontent;
448 89
        $this->contentType = $pcontentType;
449 89
        $this->linkArray = $plinkArray;
450 89
        $this->className = $pclass;
451 89
        $this->numberOfElement = $pcount;
452
453 89
        if ($config['cops_show_icons'] == 1)
454 89
        {
455 89
            foreach (self::$icons as $reg => $image)
456
            {
457 89
                if (preg_match ("/" . $reg . "/", $pid)) {
458 51
                    array_push ($this->linkArray, new Link (getUrlWithVersion ($image), "image/png", Link::OPDS_THUMBNAIL_TYPE));
459 51
                    break;
460
                }
461 89
            }
462 89
        }
463
464 89
        if (!is_null (GetUrlParam (DB))) $this->id = str_replace ("cops:", "cops:" . GetUrlParam (DB) . ":", $this->id);
465 89
    }
466
}
467
468
class EntryBook extends Entry
469
{
470
    public $book;
471
472 39
    public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray, $pbook) {
473 39
        parent::__construct ($ptitle, $pid, $pcontent, $pcontentType, $plinkArray);
474 39
        $this->book = $pbook;
475 39
        $this->localUpdated = $pbook->timestamp;
476 39
    }
477
478
    public function getCoverThumbnail () {
479
        foreach ($this->linkArray as $link) {
480
            if ($link->rel == Link::OPDS_THUMBNAIL_TYPE)
481
                return $link->hrefXhtml ();
482
        }
483
        return null;
484
    }
485
486
    public function getCover () {
487
        foreach ($this->linkArray as $link) {
488
            if ($link->rel == Link::OPDS_IMAGE_TYPE)
489
                return $link->hrefXhtml ();
490
        }
491
        return null;
492
    }
493
}
494
495
class Page
496
{
497
    public $title;
498
    public $subtitle = "";
499
    public $authorName = "";
500
    public $authorUri = "";
501
    public $authorEmail = "";
502
    public $idPage;
503
    public $idGet;
504
    public $query;
505
    public $favicon;
506
    public $n;
507
    public $book;
508
    public $totalNumber = -1;
509
    public $entryArray = array();
510
511 81
    public static function getPage ($pageId, $id, $query, $n)
512
    {
513
        switch ($pageId) {
514 81
            case Base::PAGE_ALL_AUTHORS :
515 3
                return new PageAllAuthors ($id, $query, $n);
516 78
            case Base::PAGE_AUTHORS_FIRST_LETTER :
517 1
                return new PageAllAuthorsLetter ($id, $query, $n);
518 77
            case Base::PAGE_AUTHOR_DETAIL :
519 7
                return new PageAuthorDetail ($id, $query, $n);
520 70
            case Base::PAGE_ALL_TAGS :
521 2
                return new PageAllTags ($id, $query, $n);
522 68
            case Base::PAGE_TAG_DETAIL :
523 1
                return new PageTagDetail ($id, $query, $n);
524 67
            case Base::PAGE_ALL_LANGUAGES :
525 2
                return new PageAllLanguages ($id, $query, $n);
526 65
            case Base::PAGE_LANGUAGE_DETAIL :
527 1
                return new PageLanguageDetail ($id, $query, $n);
528 64
            case Base::PAGE_ALL_CUSTOMS :
529 3
                return new PageAllCustoms ($id, $query, $n);
530 61
            case Base::PAGE_CUSTOM_DETAIL :
531 3
                return new PageCustomDetail ($id, $query, $n);
532 58
            case Base::PAGE_ALL_RATINGS :
533 1
                return new PageAllRating ($id, $query, $n);
534 57
            case Base::PAGE_RATING_DETAIL :
535 1
                return new PageRatingDetail ($id, $query, $n);
536 56
            case Base::PAGE_ALL_SERIES :
537 2
                return new PageAllSeries ($id, $query, $n);
538 54
            case Base::PAGE_ALL_BOOKS :
539 3
                return new PageAllBooks ($id, $query, $n);
540 51
            case Base::PAGE_ALL_BOOKS_LETTER:
541 1
                return new PageAllBooksLetter ($id, $query, $n);
542 50
            case Base::PAGE_ALL_RECENT_BOOKS :
543 4
                return new PageRecentBooks ($id, $query, $n);
544 46
            case Base::PAGE_SERIE_DETAIL :
545 1
                return new PageSerieDetail ($id, $query, $n);
546 45
            case Base::PAGE_OPENSEARCH_QUERY :
547 31
                return new PageQueryResult ($id, $query, $n);
548 14
            case Base::PAGE_BOOK_DETAIL :
549 1
                return new PageBookDetail ($id, $query, $n);
550 13
            case Base::PAGE_ALL_PUBLISHERS:
551 2
                return new PageAllPublishers ($id, $query, $n);
552 11
            case Base::PAGE_PUBLISHER_DETAIL :
553 1
                return new PagePublisherDetail ($id, $query, $n);
554 10
            case Base::PAGE_ABOUT :
555
                return new PageAbout ($id, $query, $n);
556 10
            case Base::PAGE_CUSTOMIZE :
557
                return new PageCustomize ($id, $query, $n);
558 10
            default:
559 10
                $page = new Page ($id, $query, $n);
560 10
                $page->idPage = "cops:catalog";
561 10
                return $page;
562 10
        }
563
    }
564
565 81
    public function __construct($pid, $pquery, $pn) {
566 81
        global $config;
567
568 81
        $this->idGet = $pid;
569 81
        $this->query = $pquery;
570 81
        $this->n = $pn;
571 81
        $this->favicon = $config['cops_icon'];
572 81
        $this->authorName = empty($config['cops_author_name']) ? utf8_encode('Sébastien Lucas') : $config['cops_author_name'];
573 81
        $this->authorUri = empty($config['cops_author_uri']) ? 'http://blog.slucas.fr' : $config['cops_author_uri'];
574 81
        $this->authorEmail = empty($config['cops_author_email']) ? '[email protected]' : $config['cops_author_email'];
575 81
    }
576
577 10
    public function InitializeContent ()
578
    {
579 10
        global $config;
580 10
        $this->title = $config['cops_title_default'];
581 10
        $this->subtitle = $config['cops_subtitle_default'];
582 10
        if (Base::noDatabaseSelected ()) {
583 2
            $i = 0;
584 2
            foreach (Base::getDbNameList () as $key) {
585 2
                $nBooks = Book::getBookCount ($i);
586 2
                array_push ($this->entryArray, new Entry ($key, "cops:{$i}:catalog",
587 2
                                        str_format (localize ("bookword", $nBooks), $nBooks), "text",
588 2
                                        array ( new LinkNavigation ("?" . DB . "={$i}")), "", $nBooks));
589 2
                $i++;
590 2
                Base::clearDb ();
591 2
            }
592 2
        } else {
593 8
            if (!in_array (PageQueryResult::SCOPE_AUTHOR, getCurrentOption ('ignored_categories'))) {
594 7
                array_push ($this->entryArray, Author::getCount());
595 7
            }
596 8
            if (!in_array (PageQueryResult::SCOPE_SERIES, getCurrentOption ('ignored_categories'))) {
597 7
                $series = Serie::getCount();
598 7
                if (!is_null ($series)) array_push ($this->entryArray, $series);
599 7
            }
600 8
            if (!in_array (PageQueryResult::SCOPE_PUBLISHER, getCurrentOption ('ignored_categories'))) {
601 7
                $publisher = Publisher::getCount();
602 7
                if (!is_null ($publisher)) array_push ($this->entryArray, $publisher);
603 7
            }
604 8
            if (!in_array (PageQueryResult::SCOPE_TAG, getCurrentOption ('ignored_categories'))) {
605 7
                $tags = Tag::getCount();
606 7
                if (!is_null ($tags)) array_push ($this->entryArray, $tags);
607 7
            }
608 8
            if (!in_array (PageQueryResult::SCOPE_RATING, getCurrentOption ('ignored_categories'))) {
609 8
                $rating = Rating::getCount();
610 8
                if (!is_null ($rating)) array_push ($this->entryArray, $rating);
611 8
            }
612 8
            if (!in_array ("language", getCurrentOption ('ignored_categories'))) {
613 7
                $languages = Language::getCount();
614 7
                if (!is_null ($languages)) array_push ($this->entryArray, $languages);
615 7
            }
616 8
            foreach ($config['cops_calibre_custom_column'] as $lookup) {
617 4
                $customId = CustomColumn::getCustomId ($lookup);
618 4
                if (!is_null ($customId)) {
619 4
                    array_push ($this->entryArray, CustomColumn::getCount($customId));
620 4
                }
621 8
            }
622 8
            $this->entryArray = array_merge ($this->entryArray, Book::getCount());
623
624 8
            if (Base::isMultipleDatabaseEnabled ()) $this->title =  Base::getDbName ();
625
        }
626 10
    }
627
628 17
    public function isPaginated ()
629
    {
630 17
        return (getCurrentOption ("max_item_per_page") != -1 &&
631 17
                $this->totalNumber != -1 &&
632 17
                $this->totalNumber > getCurrentOption ("max_item_per_page"));
633
    }
634
635 2
    public function getNextLink ()
636
    {
637 2
        $currentUrl = preg_replace ("/\&n=.*?$/", "", "?" . getQueryString ());
638 2
        if (($this->n) * getCurrentOption ("max_item_per_page") < $this->totalNumber) {
639 1
            return new LinkNavigation ($currentUrl . "&n=" . ($this->n + 1), "next", localize ("paging.next.alternate"));
640
        }
641 1
        return NULL;
642
    }
643
644 2
    public function getPrevLink ()
645
    {
646 2
        $currentUrl = preg_replace ("/\&n=.*?$/", "", "?" . getQueryString ());
647 2
        if ($this->n > 1) {
648 1
            return new LinkNavigation ($currentUrl . "&n=" . ($this->n - 1), "previous", localize ("paging.previous.alternate"));
649
        }
650 2
        return NULL;
651
    }
652
653 2
    public function getMaxPage ()
654
    {
655 2
        return ceil ($this->totalNumber / getCurrentOption ("max_item_per_page"));
656
    }
657
658 70
    public function containsBook ()
659
    {
660 70
        if (count ($this->entryArray) == 0) return false;
661 68
        if (get_class ($this->entryArray [0]) == "EntryBook") return true;
662 46
        return false;
663
    }
664
}
665
666
class PageAllAuthors extends Page
667
{
668 3
    public function InitializeContent ()
669
    {
670 3
        $this->title = localize("authors.title");
671 3
        if (getCurrentOption ("author_split_first_letter") == 1) {
672 2
            $this->entryArray = Author::getAllAuthorsByFirstLetter();
673 2
        }
674
        else {
675 1
            $this->entryArray = Author::getAllAuthors();
676
        }
677 3
        $this->idPage = Author::ALL_AUTHORS_ID;
678 3
    }
679
}
680
681
class PageAllAuthorsLetter extends Page
682
{
683 1
    public function InitializeContent ()
684
    {
685 1
        $this->idPage = Author::getEntryIdByLetter ($this->idGet);
686 1
        $this->entryArray = Author::getAuthorsByStartingLetter ($this->idGet);
687 1
        $this->title = str_format (localize ("splitByLetter.letter"), str_format (localize ("authorword", count ($this->entryArray)), count ($this->entryArray)), $this->idGet);
688 1
    }
689
}
690
691
class PageAuthorDetail extends Page
692
{
693 7
    public function InitializeContent ()
694
    {
695 7
        $author = Author::getAuthorById ($this->idGet);
696 7
        $this->idPage = $author->getEntryId ();
697 7
        $this->title = $author->name;
698 7
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByAuthor ($this->idGet, $this->n);
699 7
    }
700
}
701
702
class PageAllPublishers extends Page
703
{
704 2
    public function InitializeContent ()
705
    {
706 2
        $this->title = localize("publishers.title");
707 2
        $this->entryArray = Publisher::getAllPublishers();
708 2
        $this->idPage = Publisher::ALL_PUBLISHERS_ID;
709 2
    }
710
}
711
712
class PagePublisherDetail extends Page
713
{
714 1
    public function InitializeContent ()
715
    {
716 1
        $publisher = Publisher::getPublisherById ($this->idGet);
717 1
        $this->title = $publisher->name;
718 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByPublisher ($this->idGet, $this->n);
719 1
        $this->idPage = $publisher->getEntryId ();
720 1
    }
721
}
722
723
class PageAllTags extends Page
724
{
725 2
    public function InitializeContent ()
726
    {
727 2
        $this->title = localize("tags.title");
728 2
        $this->entryArray = Tag::getAllTags();
729 2
        $this->idPage = Tag::ALL_TAGS_ID;
730 2
    }
731
}
732
733
class PageAllLanguages extends Page
734
{
735 2
    public function InitializeContent ()
736
    {
737 2
        $this->title = localize("languages.title");
738 2
        $this->entryArray = Language::getAllLanguages();
739 2
        $this->idPage = Language::ALL_LANGUAGES_ID;
740 2
    }
741
}
742
743
class PageCustomDetail extends Page
744
{
745 3
    public function InitializeContent ()
746
    {
747 3
        $customId = getURLParam ("custom", NULL);
748 3
        $custom = CustomColumn::getCustomById ($customId, $this->idGet);
749 3
        $this->idPage = $custom->getEntryId ();
750 3
        $this->title = $custom->name;
751 3
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByCustom ($customId, $this->idGet, $this->n);
752 3
    }
753
}
754
755
class PageAllCustoms extends Page
756
{
757 3
    public function InitializeContent ()
758
    {
759 3
        $customId = getURLParam ("custom", NULL);
760 3
        $this->title = CustomColumn::getAllTitle ($customId);
761 3
        $this->entryArray = CustomColumn::getAllCustoms($customId);
762 3
        $this->idPage = CustomColumn::getAllCustomsId ($customId);
763 3
    }
764
}
765
766
class PageTagDetail extends Page
767
{
768 1
    public function InitializeContent ()
769
    {
770 1
        $tag = Tag::getTagById ($this->idGet);
771 1
        $this->idPage = $tag->getEntryId ();
772 1
        $this->title = $tag->name;
773 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByTag ($this->idGet, $this->n);
774 1
    }
775
}
776
777
class PageLanguageDetail extends Page
778
{
779 1
    public function InitializeContent ()
780
    {
781 1
        $language = Language::getLanguageById ($this->idGet);
782 1
        $this->idPage = $language->getEntryId ();
783 1
        $this->title = $language->lang_code;
784 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByLanguage ($this->idGet, $this->n);
785 1
    }
786
}
787
788
class PageAllSeries extends Page
789
{
790 2
    public function InitializeContent ()
791
    {
792 2
        $this->title = localize("series.title");
793 2
        $this->entryArray = Serie::getAllSeries();
794 2
        $this->idPage = Serie::ALL_SERIES_ID;
795 2
    }
796
}
797
798
class PageSerieDetail extends Page
799
{
800 1
    public function InitializeContent ()
801
    {
802 1
        $serie = Serie::getSerieById ($this->idGet);
803 1
        $this->title = $serie->name;
804 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksBySeries ($this->idGet, $this->n);
805 1
        $this->idPage = $serie->getEntryId ();
806 1
    }
807
}
808
809
class PageAllRating extends Page
810
{
811 1
    public function InitializeContent ()
812
    {
813 1
        $this->title = localize("ratings.title");
814 1
        $this->entryArray = Rating::getAllRatings();
815 1
        $this->idPage = Rating::ALL_RATING_ID;
816 1
    }
817
}
818
819
class PageRatingDetail extends Page
820
{
821 1
    public function InitializeContent ()
822
    {
823 1
        $rating = Rating::getRatingById ($this->idGet);
824 1
        $this->idPage = $rating->getEntryId ();
825 1
        $this->title =str_format (localize ("ratingword", $rating->name/2), $rating->name/2);
826 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByRating ($this->idGet, $this->n);
827 1
    }
828
}
829
830
class PageAllBooks extends Page
831
{
832 3
    public function InitializeContent ()
833
    {
834 3
        $this->title = localize ("allbooks.title");
835 3
        if (getCurrentOption ("titles_split_first_letter") == 1) {
836 2
            $this->entryArray = Book::getAllBooks();
837 2
        }
838
        else {
839 1
            list ($this->entryArray, $this->totalNumber) = Book::getBooks ($this->n);
840
        }
841 3
        $this->idPage = Book::ALL_BOOKS_ID;
842 3
    }
843
}
844
845
class PageAllBooksLetter extends Page
846
{
847 1
    public function InitializeContent ()
848
    {
849 1
        list ($this->entryArray, $this->totalNumber) = Book::getBooksByStartingLetter ($this->idGet, $this->n);
850 1
        $this->idPage = Book::getEntryIdByLetter ($this->idGet);
851
852 1
        $count = $this->totalNumber;
853 1
        if ($count == -1)
854 1
            $count = count ($this->entryArray);
855
856 1
        $this->title = str_format (localize ("splitByLetter.letter"), str_format (localize ("bookword", $count), $count), $this->idGet);
857 1
    }
858
}
859
860
class PageRecentBooks extends Page
861
{
862 4
    public function InitializeContent ()
863
    {
864 4
        $this->title = localize ("recent.title");
865 4
        $this->entryArray = Book::getAllRecentBooks ();
866 4
        $this->idPage = Book::ALL_RECENT_BOOKS_ID;
867 4
    }
868
}
869
870
class PageQueryResult extends Page
871
{
872
    const SCOPE_TAG = "tag";
873
    const SCOPE_RATING = "rating";
874
    const SCOPE_SERIES = "series";
875
    const SCOPE_AUTHOR = "author";
876
    const SCOPE_BOOK = "book";
877
    const SCOPE_PUBLISHER = "publisher";
878
879 24
    private function useTypeahead () {
880 24
        return !is_null (getURLParam ("search"));
881
    }
882
883 29
    private function searchByScope ($scope, $limit = FALSE) {
884 29
        $n = $this->n;
885 29
        $numberPerPage = NULL;
886 29
        $queryNormedAndUp = $this->query;
887 29
        if (useNormAndUp ()) {
888 7
            $queryNormedAndUp = normAndUp ($this->query);
889 7
        }
890 29
        if ($limit) {
891 22
            $n = 1;
892 22
            $numberPerPage = 5;
893 22
        }
894
        switch ($scope) {
895 29
            case self::SCOPE_BOOK :
896 23
                $array = Book::getBooksByStartingLetter ('%' . $queryNormedAndUp, $n, NULL, $numberPerPage);
897 23
                break;
898 28
            case self::SCOPE_AUTHOR :
899 23
                $array = Author::getAuthorsForSearch ('%' . $queryNormedAndUp);
900 23
                break;
901 25
            case self::SCOPE_SERIES :
902 22
                $array = Serie::getAllSeriesByQuery ($queryNormedAndUp);
903 22
                break;
904 24
            case self::SCOPE_TAG :
905 23
                $array = Tag::getAllTagsByQuery ($queryNormedAndUp, $n, NULL, $numberPerPage);
906 23
                break;
907 23
            case self::SCOPE_PUBLISHER :
908 23
                $array = Publisher::getAllPublishersByQuery ($queryNormedAndUp);
909 23
                break;
910
            default:
911
                $array = Book::getBooksByQuery (
912
                    array ("all" => "%" . $queryNormedAndUp . "%"), $n);
913
        }
914
915 29
        return $array;
916
    }
917
918 22
    public function doSearchByCategory () {
919 22
        $database = GetUrlParam (DB);
920 22
        $out = array ();
921 22
        $pagequery = Base::PAGE_OPENSEARCH_QUERY;
922 22
        $dbArray = array ("");
923 22
        $d = $database;
924 22
        $query = $this->query;
925
        // Special case when no databases were chosen, we search on all databases
926 22
        if (Base::noDatabaseSelected ()) {
927 1
            $dbArray = Base::getDbNameList ();
928 1
            $d = 0;
929 1
        }
930 22
        foreach ($dbArray as $key) {
931 22
            if (Base::noDatabaseSelected ()) {
932 1
                array_push ($this->entryArray, new Entry ($key, DB . ":query:{$d}",
933 1
                                        " ", "text",
934 1
                                        array ( new LinkNavigation ("?" . DB . "={$d}")), "tt-header"));
935 1
                Base::getDb ($d);
936 1
            }
937 22
            foreach (array (PageQueryResult::SCOPE_BOOK,
938 22
                            PageQueryResult::SCOPE_AUTHOR,
939 22
                            PageQueryResult::SCOPE_SERIES,
940 22
                            PageQueryResult::SCOPE_TAG,
941 22
                            PageQueryResult::SCOPE_PUBLISHER) as $key) {
942 22
                if (in_array($key, getCurrentOption ('ignored_categories'))) {
943 3
                    continue;
944
                }
945 22
                $array = $this->searchByScope ($key, TRUE);
946
947 22
                $i = 0;
948 22
                if (count ($array) == 2 && is_array ($array [0])) {
949 22
                    $total = $array [1];
950 22
                    $array = $array [0];
951 22
                } else {
952 22
                    $total = count($array);
953
                }
954 22
                if ($total > 0) {
955
                    // Comment to help the perl i18n script
956
                    // str_format (localize("bookword", count($array))
957
                    // str_format (localize("authorword", count($array))
958
                    // str_format (localize("seriesword", count($array))
959
                    // str_format (localize("tagword", count($array))
960
                    // str_format (localize("publisherword", count($array))
961 21
                    array_push ($this->entryArray, new Entry (str_format (localize ("search.result.{$key}"), $this->query), DB . ":query:{$d}:{$key}",
962 21
                                        str_format (localize("{$key}word", $total), $total), "text",
963 21
                                        array ( new LinkNavigation ("?page={$pagequery}&query={$query}&db={$d}&scope={$key}")),
964 21
                                        Base::noDatabaseSelected () ? "" : "tt-header", $total));
965 21
                }
966 22
                if (!Base::noDatabaseSelected () && $this->useTypeahead ()) {
967 6
                    foreach ($array as $entry) {
968 6
                        array_push ($this->entryArray, $entry);
969 6
                        $i++;
970 6
                        if ($i > 4) { break; };
971 6
                    }
972 6
                }
973 22
            }
974 22
            $d++;
975 22
            if (Base::noDatabaseSelected ()) {
976 1
                Base::clearDb ();
977 1
            }
978 22
        }
979 22
        return $out;
980
    }
981
982 31
    public function InitializeContent ()
983
    {
984 31
        $scope = getURLParam ("scope");
985 31
        if (empty ($scope)) {
986 24
            $this->title = str_format (localize ("search.result"), $this->query);
987 24
        } else {
988
            // Comment to help the perl i18n script
989
            // str_format (localize ("search.result.author"), $this->query)
990
            // str_format (localize ("search.result.tag"), $this->query)
991
            // str_format (localize ("search.result.series"), $this->query)
992
            // str_format (localize ("search.result.book"), $this->query)
993
            // str_format (localize ("search.result.publisher"), $this->query)
994 7
            $this->title = str_format (localize ("search.result.{$scope}"), $this->query);
995
        }
996
997 31
        $crit = "%" . $this->query . "%";
998
999
        // Special case when we are doing a search and no database is selected
1000 31
        if (Base::noDatabaseSelected () && !$this->useTypeahead ()) {
1001 2
            $i = 0;
1002 2
            foreach (Base::getDbNameList () as $key) {
1003 2
                Base::clearDb ();
1004 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...
1005 2
                array_push ($this->entryArray, new Entry ($key, DB . ":query:{$i}",
1006 2
                                        str_format (localize ("bookword", $totalNumber), $totalNumber), "text",
1007 2
                                        array ( new LinkNavigation ("?" . DB . "={$i}&page=9&query=" . $this->query)), "", $totalNumber));
1008 2
                $i++;
1009 2
            }
1010 2
            return;
1011
        }
1012 29
        if (empty ($scope)) {
1013 22
            $this->doSearchByCategory ();
1014 22
            return;
1015
        }
1016
1017 7
        $array = $this->searchByScope ($scope);
1018 7
        if (count ($array) == 2 && is_array ($array [0])) {
1019 2
            list ($this->entryArray, $this->totalNumber) = $array;
1020 2
        } else {
1021 5
            $this->entryArray = $array;
1022
        }
1023 7
    }
1024
}
1025
1026
class PageBookDetail extends Page
1027
{
1028 1
    public function InitializeContent ()
1029
    {
1030 1
        $this->book = Book::getBookById ($this->idGet);
1031 1
        $this->title = $this->book->title;
1032 1
    }
1033
}
1034
1035
class PageAbout extends Page
1036
{
1037
    public function InitializeContent ()
1038
    {
1039
        $this->title = localize ("about.title");
1040
    }
1041
}
1042
1043
class PageCustomize extends Page
1044
{
1045
    private function isChecked ($key, $testedValue = 1) {
1046
        $value = getCurrentOption ($key);
1047
        if (is_array ($value)) {
1048
            if (in_array ($testedValue, $value)) {
1049
                return "checked='checked'";
1050
            }
1051
        } else {
1052
            if ($value == $testedValue) {
1053
                return "checked='checked'";
1054
            }
1055
        }
1056
        return "";
1057
    }
1058
1059
    private function isSelected ($key, $value) {
1060
        if (getCurrentOption ($key) == $value) {
1061
            return "selected='selected'";
1062
        }
1063
        return "";
1064
    }
1065
1066
    private function getStyleList () {
1067
        $result = array ();
1068
        foreach (glob ("templates/" . getCurrentTemplate () . "/styles/style-*.css") as $filename) {
1069
            if (preg_match ('/styles\/style-(.*?)\.css/', $filename, $m)) {
1070
                array_push ($result, $m [1]);
1071
            }
1072
        }
1073
        return $result;
1074
    }
1075
1076
    public function InitializeContent ()
1077
    {
1078
        $this->title = localize ("customize.title");
1079
        $this->entryArray = array ();
1080
1081
        $ignoredBaseArray = array (PageQueryResult::SCOPE_AUTHOR,
1082
                                   PageQueryResult::SCOPE_TAG,
1083
                                   PageQueryResult::SCOPE_SERIES,
1084
                                   PageQueryResult::SCOPE_PUBLISHER,
1085
                                   PageQueryResult::SCOPE_RATING,
1086
                                   "language");
1087
1088
        $content = "";
1089
        array_push ($this->entryArray, new Entry ("Template", "",
1090
                                        "<span style='cursor: pointer;' onclick='$.cookie(\"template\", \"bootstrap\", { expires: 365 });window.location=$(\".headleft\").attr(\"href\");'>Click to switch to Bootstrap</span>", "text",
1091
                                        array ()));
1092
        if (!preg_match("/(Kobo|Kindle\/3.0|EBRD1101)/", $_SERVER['HTTP_USER_AGENT'])) {
1093
            $content .= '<select id="style" onchange="updateCookie (this);">';
1094
            foreach ($this-> getStyleList () as $filename) {
1095
                $content .= "<option value='{$filename}' " . $this->isSelected ("style", $filename) . ">{$filename}</option>";
1096
            }
1097
            $content .= '</select>';
1098
        } else {
1099
            foreach ($this-> getStyleList () as $filename) {
1100
                $content .= "<input type='radio' onchange='updateCookieFromCheckbox (this);' id='style-{$filename}' name='style' value='{$filename}' " . $this->isChecked ("style", $filename) . " /><label for='style-{$filename}'> {$filename} </label>";
1101
            }
1102
        }
1103
        array_push ($this->entryArray, new Entry (localize ("customize.style"), "",
1104
                                        $content, "text",
1105
                                        array ()));
1106
        if (!useServerSideRendering ()) {
1107
            $content = '<input type="checkbox" onchange="updateCookieFromCheckbox (this);" id="use_fancyapps" ' . $this->isChecked ("use_fancyapps") . ' />';
1108
            array_push ($this->entryArray, new Entry (localize ("customize.fancybox"), "",
1109
                                            $content, "text",
1110
                                            array ()));
1111
        }
1112
        $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]+$" />';
1113
        array_push ($this->entryArray, new Entry (localize ("customize.paging"), "",
1114
                                        $content, "text",
1115
                                        array ()));
1116
        $content = '<input type="text" onchange="updateCookie (this);" id="email" value="' . getCurrentOption ("email") . '" />';
1117
        array_push ($this->entryArray, new Entry (localize ("customize.email"), "",
1118
                                        $content, "text",
1119
                                        array ()));
1120
        $content = '<input type="checkbox" onchange="updateCookieFromCheckbox (this);" id="html_tag_filter" ' . $this->isChecked ("html_tag_filter") . ' />';
1121
        array_push ($this->entryArray, new Entry (localize ("customize.filter"), "",
1122
                                        $content, "text",
1123
                                        array ()));
1124
        $content = "";
1125
        foreach ($ignoredBaseArray as $key) {
1126
            $keyPlural = preg_replace ('/(ss)$/', 's', $key . "s");
1127
            $content .=  '<input type="checkbox" name="ignored_categories[]" onchange="updateCookieFromCheckboxGroup (this);" id="ignored_categories_' . $key . '" ' . $this->isChecked ("ignored_categories", $key) . ' > ' . localize ("{$keyPlural}.title") . '</input> ';
1128
        }
1129
1130
        array_push ($this->entryArray, new Entry (localize ("customize.ignored"), "",
1131
                                        $content, "text",
1132
                                        array ()));
1133
    }
1134
}
1135
1136
1137
abstract class Base
1138
{
1139
    const PAGE_INDEX = "index";
1140
    const PAGE_ALL_AUTHORS = "1";
1141
    const PAGE_AUTHORS_FIRST_LETTER = "2";
1142
    const PAGE_AUTHOR_DETAIL = "3";
1143
    const PAGE_ALL_BOOKS = "4";
1144
    const PAGE_ALL_BOOKS_LETTER = "5";
1145
    const PAGE_ALL_SERIES = "6";
1146
    const PAGE_SERIE_DETAIL = "7";
1147
    const PAGE_OPENSEARCH = "8";
1148
    const PAGE_OPENSEARCH_QUERY = "9";
1149
    const PAGE_ALL_RECENT_BOOKS = "10";
1150
    const PAGE_ALL_TAGS = "11";
1151
    const PAGE_TAG_DETAIL = "12";
1152
    const PAGE_BOOK_DETAIL = "13";
1153
    const PAGE_ALL_CUSTOMS = "14";
1154
    const PAGE_CUSTOM_DETAIL = "15";
1155
    const PAGE_ABOUT = "16";
1156
    const PAGE_ALL_LANGUAGES = "17";
1157
    const PAGE_LANGUAGE_DETAIL = "18";
1158
    const PAGE_CUSTOMIZE = "19";
1159
    const PAGE_ALL_PUBLISHERS = "20";
1160
    const PAGE_PUBLISHER_DETAIL = "21";
1161
    const PAGE_ALL_RATINGS = "22";
1162
    const PAGE_RATING_DETAIL = "23";
1163
1164
    const COMPATIBILITY_XML_ALDIKO = "aldiko";
1165
1166
    private static $db = NULL;
1167
1168 114
    public static function isMultipleDatabaseEnabled () {
1169 114
        global $config;
1170 114
        return is_array ($config['calibre_directory']);
1171
    }
1172
1173 46
    public static function useAbsolutePath () {
1174 46
        global $config;
1175 46
        $path = self::getDbDirectory();
1176 46
        return preg_match ('/^\//', $path) || // Linux /
1177 46
               preg_match ('/^\w\:/', $path); // Windows X:
1178
    }
1179
1180 45
    public static function noDatabaseSelected () {
1181 45
        return self::isMultipleDatabaseEnabled () && is_null (GetUrlParam (DB));
1182
    }
1183
1184 4
    public static function getDbList () {
1185 4
        global $config;
1186 4
        if (self::isMultipleDatabaseEnabled ()) {
1187 4
            return $config['calibre_directory'];
1188
        } else {
1189 1
            return array ("" => $config['calibre_directory']);
1190
        }
1191
    }
1192
1193 5
    public static function getDbNameList () {
1194 5
        global $config;
1195 5
        if (self::isMultipleDatabaseEnabled ()) {
1196 5
            return array_keys ($config['calibre_directory']);
1197
        } else {
1198
            return array ("");
1199
        }
1200
    }
1201
1202 1
    public static function getDbName ($database = NULL) {
1203 1
        global $config;
1204 1
        if (self::isMultipleDatabaseEnabled ()) {
1205 1
            if (is_null ($database)) $database = GetUrlParam (DB, 0);
1206 1
            if (!is_null($database) && !preg_match('/^\d+$/', $database)) {
1207
                return self::error ($database);
1208
            }
1209 1
            $array = array_keys ($config['calibre_directory']);
1210 1
            return  $array[$database];
1211
        }
1212
        return "";
1213
    }
1214
1215 96
    public static function getDbDirectory ($database = NULL) {
1216 96
        global $config;
1217 96
        if (self::isMultipleDatabaseEnabled ()) {
1218 9
            if (is_null ($database)) $database = GetUrlParam (DB, 0);
1219 9
            if (!is_null($database) && !preg_match('/^\d+$/', $database)) {
1220
                return self::error ($database);
1221
            }
1222 9
            $array = array_values ($config['calibre_directory']);
1223 9
            return  $array[$database];
1224
        }
1225 87
        return $config['calibre_directory'];
1226
    }
1227
1228
1229 67
    public static function getDbFileName ($database = NULL) {
1230 67
        return self::getDbDirectory ($database) .'metadata.db';
1231
    }
1232
1233 2
    private static function error ($database) {
1234 2
        if (php_sapi_name() != "cli") {
1235
            header("location: checkconfig.php?err=1");
1236
        }
1237 2
        throw new Exception("Database <{$database}> not found.");
1238
    }
1239
1240 132
    public static function getDb ($database = NULL) {
1241 132
        if (is_null (self::$db)) {
1242
            try {
1243 67
                if (is_readable (self::getDbFileName ($database))) {
1244 66
                    self::$db = new PDO('sqlite:'. self::getDbFileName ($database));
1245 66
                    if (useNormAndUp ()) {
1246 7
                        self::$db->sqliteCreateFunction ('normAndUp', 'normAndUp', 1);
1247 7
                    }
1248 66
                } else {
1249 2
                    self::error ($database);
1250
                }
1251 67
            } catch (Exception $e) {
1252 2
                self::error ($database);
1253
            }
1254 66
        }
1255 131
        return self::$db;
1256
    }
1257
1258 4
    public static function checkDatabaseAvailability () {
1259 4
        if (self::noDatabaseSelected ()) {
1260 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...
1261 3
                self::getDb ($i);
1262 2
                self::clearDb ();
1263 2
            }
1264 1
        } else {
1265 1
            self::getDb ();
1266
        }
1267 2
        return true;
1268
    }
1269
1270 64
    public static function clearDb () {
1271 64
        self::$db = NULL;
1272 64
    }
1273
1274 13
    public static function executeQuerySingle ($query, $database = NULL) {
1275 13
        return self::getDb ($database)->query($query)->fetchColumn();
1276
    }
1277
1278 8
    public static function getCountGeneric($table, $id, $pageId, $numberOfString = NULL) {
1279 8
        if (!$numberOfString) {
1280 7
            $numberOfString = $table . ".alphabetical";
1281 7
        }
1282 8
        $count = self::executeQuerySingle ('select count(*) from ' . $table);
1283 8
        if ($count == 0) return NULL;
1284 8
        $entry = new Entry (localize($table . ".title"), $id,
1285 8
            str_format (localize($numberOfString, $count), $count), "text",
1286 8
            array ( new LinkNavigation ("?page=".$pageId)), "", $count);
1287 8
        return $entry;
1288
    }
1289
1290 35
    public static function getEntryArrayWithBookNumber ($query, $columns, $params, $category) {
1291 35
        list (, $result) = self::executeQuery ($query, $columns, "", $params, -1);
1292 35
        $entryArray = array();
1293 35
        while ($post = $result->fetchObject ())
1294
        {
1295 25
            $instance = new $category ($post);
1296 25
            if (property_exists($post, "sort")) {
1297 17
                $title = $post->sort;
1298 17
            } else {
1299 8
                $title = $post->name;
1300
            }
1301 25
            array_push ($entryArray, new Entry ($title, $instance->getEntryId (),
1302 25
                str_format (localize("bookword", $post->count), $post->count), "text",
1303 25
                array ( new LinkNavigation ($instance->getUri ())), "", $post->count));
1304 25
        }
1305 35
        return $entryArray;
1306
    }
1307
1308 73
    public static function executeQuery($query, $columns, $filter, $params, $n, $database = NULL, $numberPerPage = NULL) {
1309 73
        $totalResult = -1;
1310
1311 73
        if (useNormAndUp ()) {
1312 7
            $query = preg_replace("/upper/", "normAndUp", $query);
1313 7
            $columns = preg_replace("/upper/", "normAndUp", $columns);
1314 7
        }
1315
1316 73
        if (is_null ($numberPerPage)) {
1317 71
            $numberPerPage = getCurrentOption ("max_item_per_page");
1318 71
        }
1319
1320 73
        if ($numberPerPage != -1 && $n != -1)
1321 73
        {
1322
            // First check total number of results
1323 28
            $result = self::getDb ($database)->prepare (str_format ($query, "count(*)", $filter));
1324 28
            $result->execute ($params);
1325 28
            $totalResult = $result->fetchColumn ();
1326
1327
            // Next modify the query and params
1328 28
            $query .= " limit ?, ?";
1329 28
            array_push ($params, ($n - 1) * $numberPerPage, $numberPerPage);
1330 28
        }
1331
1332 73
        $result = self::getDb ($database)->prepare(str_format ($query, $columns, $filter));
1333 73
        $result->execute ($params);
1334 73
        return array ($totalResult, $result);
1335
    }
1336
1337
}
1338