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

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1404
     */
1405
    public static function executeFilteredQuery($query, $params, $n, $database = NULL, $virtualLib = NULL,$numberPerPage = NULL) {
1406
    	$totalResult = -1;
1407
    
1408
    	$query = str_format($query, VirtualLib::getVL($database, $virtualLib)->getFilterQuery());
1409
    	
1410
    	if (useNormAndUp ()) {
1411
    		$query = preg_replace("/upper/", "normAndUp", $query);
1412
    	}
1413
    
1414
    	if (is_null ($numberPerPage)) {
1415
    		$numberPerPage = getCurrentOption ("max_item_per_page");
1416
    	}
1417
    
1418
    	if ($numberPerPage != -1 && $n != -1)
1419
    	{
1420
    		// First check total number of results
1421
    		$result = self::getDb ($database)->prepare (str_format ("select count(*) from ({0})", $query));
1422
    		$result->execute ($params);
1423
    		$totalResult = $result->fetchColumn ();
1424
    
1425
    		// Next modify the query and params
1426
    		$query .= " limit ?, ?";
1427
    		array_push ($params, ($n - 1) * $numberPerPage, $numberPerPage);
1428
    	}
1429
    
1430
    	$result = self::getDb ($database)->prepare($query);
1431
    	$result->execute ($params);
1432
    	return array ($totalResult, $result);
1433
    }
1434
1435
    public static function executeQuery($query, $columns, $filter, $params, $n, $database = NULL, $numberPerPage = NULL) {
1436
        $totalResult = -1;
1437
1438
        if (useNormAndUp ()) {
1439
            $query = preg_replace("/upper/", "normAndUp", $query);
1440
            $columns = preg_replace("/upper/", "normAndUp", $columns);
1441
        }
1442
1443
        if (is_null ($numberPerPage)) {
1444
            $numberPerPage = getCurrentOption ("max_item_per_page");
1445
        }
1446
1447
        if ($numberPerPage != -1 && $n != -1)
1448
        {
1449
            // First check total number of results
1450
            $result = self::getDb ($database)->prepare (str_format ($query, "count(*)", $filter));
1451
            $result->execute ($params);
1452
            $totalResult = $result->fetchColumn ();
1453
1454
            // Next modify the query and params
1455
            $query .= " limit ?, ?";
1456
            array_push ($params, ($n - 1) * $numberPerPage, $numberPerPage);
1457
        }
1458
1459
        $result = self::getDb ($database)->prepare(str_format ($query, $columns, $filter));
1460
        $result->execute ($params);
1461
        return array ($totalResult, $result);
1462
    }
1463
1464
    /**
1465
     * Gets a calibre setting from the database.
1466
     * 
1467
     * @param string $name Name of the property
1468
     * @param int $database Database to query from
1469
     * @return string Value of the property
1470
     */
1471
    public static function getCalibreSetting($name, $database = NULL) {
1472
    	$query = str_format(self::SQL_SETTING, $name);
1473
    	return self::executeQuerySingle($query, $database);
1474
    }
1475
}
1476