Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Mars 2013-10-08 00:14:44 +02:00
commit 356a1e263b
28 changed files with 547 additions and 192 deletions

5
.travis.yml Normal file
View file

@ -0,0 +1,5 @@
language: php
php:
- 5.5
- 5.4
- 5.3

View file

@ -10,6 +10,7 @@ define ("VERSION", "0.7.0beta");
define ("DB", "db");
date_default_timezone_set($config['default_timezone']);
function useServerSideRendering () {
global $config;
return preg_match("/" . $config['cops_server_side_render'] . "/", $_SERVER['HTTP_USER_AGENT']);
@ -168,7 +169,7 @@ function localize($phrase, $count=-1) {
/* Load the language file as a JSON object and transform it into an associative array */
$translations = json_decode($lang_file_content, true);
/* Clean the array of all translations unfinished */
/* Clean the array of all unfinished translations */
foreach ($translations as $key => $val) {
if (preg_match ("/^##TODO##/", $key)) {
unset ($translations [$key]);
@ -286,14 +287,17 @@ class Entry
return date (DATE_ATOM, self::$updated);
}
public function getContentArray () {
$navlink = "#";
public function getNavLink () {
foreach ($this->linkArray as $link) {
if ($link->type != Link::OPDS_NAVIGATION_TYPE) { continue; }
$navlink = $link->hrefXhtml ();
return $link->hrefXhtml ();
}
return array ( "title" => $this->title, "content" => $this->content, "navlink" => $navlink );
return "#";
}
public function getContentArray () {
return array ( "title" => $this->title, "content" => $this->content, "navlink" => $this->getNavLink () );
}
public function __construct($ptitle, $pid, $pcontent, $pcontentType, $plinkArray) {
@ -664,18 +668,41 @@ class PageRecentBooks extends Page
class PageQueryResult extends Page
{
const SCOPE_TAG = "tag";
const SCOPE_SERIES = "series";
const SCOPE_AUTHOR = "author";
const SCOPE_BOOK = "book";
public function InitializeContent ()
{
global $config;
$scope = getURLParam ("scope");
switch ($scope) {
case self::SCOPE_AUTHOR :
$this->title = str_format (localize ("search.result.author"), $this->query);
break;
case self::SCOPE_TAG :
$this->title = str_format (localize ("search.result.tag"), $this->query);
break;
case self::SCOPE_SERIES :
$this->title = str_format (localize ("search.result.series"), $this->query);
break;
case self::SCOPE_BOOK :
$this->title = str_format (localize ("search.result.book"), $this->query);
break;
default:
$this->title = str_format (localize ("search.result"), $this->query);
$currentPage = getURLParam ("current", NULL);
}
$crit = "%" . $this->query . "%";
$bad = "QQQQQ";
// Special case when we are doing a search and no database is selected
if (is_array ($config['calibre_directory']) && is_null (GetUrlParam (DB))) {
$i = 0;
foreach ($config['calibre_directory'] as $key => $value) {
Base::clearDb ();
list ($array, $totalNumber) = Book::getBooksByQuery ($this->query, $this->n, $i);
list ($array, $totalNumber) = Book::getBooksByQuery (array ($crit, $crit, $crit, $crit), $this->n, $i);
array_push ($this->entryArray, new Entry ($key, DB . ":query:{$i}",
str_format (localize ("bookword", count($array)), count($array)), "text",
array ( new LinkNavigation ("?" . DB . "={$i}&page=9&query=" . $this->query))));
@ -683,14 +710,23 @@ class PageQueryResult extends Page
}
return;
}
switch ($currentPage) {
case Base::PAGE_ALL_AUTHORS :
case Base::PAGE_AUTHORS_FIRST_LETTER :
switch ($scope) {
case self::SCOPE_AUTHOR :
$this->entryArray = Author::getAuthorsByStartingLetter ('%' . $this->query);
break;
case self::SCOPE_TAG :
$this->entryArray = Tag::getAllTagsByQuery ($this->query);
break;
case self::SCOPE_SERIES :
$this->entryArray = Serie::getAllSeriesByQuery ($this->query);
break;
case self::SCOPE_BOOK :
list ($this->entryArray, $this->totalNumber) = Book::getBooksByQuery (
array ($bad, $bad, $bad, $crit), $this->n);
break;
default:
list ($this->entryArray, $this->totalNumber) = Book::getBooksByQuery ($this->query, $this->n);
list ($this->entryArray, $this->totalNumber) = Book::getBooksByQuery (
array ($crit, $crit, $crit, $crit), $this->n);
}
}
}

View file

@ -32,7 +32,11 @@ define ('SQL_BOOKS_BY_LANGUAGE', "select {0} from books_languages_link, books "
define ('SQL_BOOKS_BY_CUSTOM', "select {0} from {2}, books " . SQL_BOOKS_LEFT_JOIN . "
where {2}.book = books.id and {2}.{3} = ? {1} order by sort");
define ('SQL_BOOKS_QUERY', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . "
where (exists (select null from authors, books_authors_link where book = books.id and author = authors.id and authors.name like ?) or title like ?) {1} order by books.sort");
where (
exists (select null from authors, books_authors_link where book = books.id and author = authors.id and authors.name like ?) or
exists (select null from tags, books_tags_link where book = books.id and tag = tags.id and tags.name like ?) or
exists (select null from series, books_series_link on book = books.id and books_series_link.series = series.id and series.name like ?) or
title like ?) {1} order by books.sort");
define ('SQL_BOOKS_RECENT', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . "
where 1=1 {1} order by timestamp desc limit ");
@ -524,7 +528,7 @@ where data.book = books.id and data.id = ?');
}
public static function getBooksByQuery($query, $n, $database = NULL) {
return self::getEntryArray (self::SQL_BOOKS_QUERY, array ("%" . $query . "%", "%" . $query . "%"), $n, $database);
return self::getEntryArray (self::SQL_BOOKS_QUERY, $query, $n, $database);
}
public static function getAllBooks() {
@ -570,10 +574,47 @@ function getJson ($complete = false) {
global $config;
$page = getURLParam ("page", Base::PAGE_INDEX);
$query = getURLParam ("query");
$search = getURLParam ("search");
$qid = getURLParam ("id");
$n = getURLParam ("n", "1");
$database = GetUrlParam (DB);
if ($search) {
$out = array ();
$arrayTag = Tag::getAllTagsByQuery ($query);
$arraySeries = Serie::getAllSeriesByQuery ($query);
$arrayAuthor = Author::getAuthorsByStartingLetter ('%' . $query);
list ($arrayBook, $totalNumber) = Book::getBooksByStartingLetter ('%' . $query, -1);
foreach (array ("book" => $arrayBook,
"author" => $arrayAuthor,
"series" => $arraySeries,
"tag" => $arrayTag) as $key => $array) {
$i = 0;
$pagequery = Base::PAGE_OPENSEARCH_QUERY;
foreach ($array as $entry) {
if (count($array) > 0) {
// Comment to help the perl i18n script
// str_format (localize("bookword", count($array))
// str_format (localize("authorword", count($array)
// str_format (localize("seriesword", count($array)
// str_format (localize("tagword", count($array)
array_push ($out, array ("title" => str_format (localize("{$key}word", count($array)), count($array)),
"class" => "tt-header",
"navlink" => "index.php?page={$pagequery}&query={$query}&db={$database}&scope={$key}"));
}
if ($entry instanceof EntryBook) {
array_push ($out, array ("class" => "", "title" => $entry->title, "navlink" => $entry->book->getDetailUrl ()));
} else {
array_push ($out, array ("class" => "", "title" => $entry->title, "navlink" => $entry->getNavLink ()));
}
$i++;
if ($i > 4) { break; };
}
}
return $out;
}
$currentPage = Page::getPage ($page, $qid, $query, $n);
$currentPage->InitializeContent ();

View file

@ -103,8 +103,8 @@
/*
* generate a invalid OPDS stream to allow bad OPDS client to use search
* Example of non compliant OPDS client : FBReader (was working in May 2012), Moon+ Reader
* Example of good OPDS client : Mantano
* Example of non compliant OPDS client : Moon+ Reader
* Example of good OPDS client : Mantano, FBReader
* 1 : enable support for non compliant OPDS client
* 0 : always generate valid OPDS code
*/

View file

@ -43,12 +43,19 @@
"recent.title":"Els més recents",
"##TODO##search.alternate":"Search",
"##TODO##search.result":"Search result for *{0}*",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"##TODO##search.sortorder.asc":"Asc",
"##TODO##search.sortorder.desc":"Desc",
"series.alphabetical.many":"{0} sèries ordenades alfabèticament",
"##TODO##series.alphabetical.none":"Alphabetical index of absolutely no series",
"series.alphabetical.one":"Índex alfabètic d'una sola sèrie",
"series.title":"Sèries",
"seriesword.many":"sèries",
"seriesword.none":"Cap sèrie",
"seriesword.one":"1 sèrie",
"##TODO##sort.alternate":"Sort",
"splitByLetter.book.other":"Altres llibres",
"splitByLetter.letter":"{0} ({1})",
@ -56,6 +63,9 @@
"##TODO##tags.alphabetical.none":"Alphabetical index of absolutely no tag",
"tags.alphabetical.one":"Llistat alfabètic de la única etiqueta",
"tags.title":"Etiquetes",
"tagword.many":"etiquetes",
"tagword.none":"Cap etiqueta",
"tagword.one":"1 etiqueta",
"tagword.title":"Etiquetes",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",

View file

@ -1,5 +1,5 @@
{
"##TODO##about.title":"About COPS",
"about.title":"Über COPS",
"allbooks.alphabetical.many":"Alphabetischer Index der {0} Bücher",
"##TODO##allbooks.alphabetical.none":"Alphabetical index of absolutely no book",
"allbooks.alphabetical.one":"Alphabetischer Index des einzigen Buchs",
@ -16,59 +16,69 @@
"bookword.none":"Kein Buch",
"bookword.one":"1 Buch",
"bookword.title":"Bücher",
"##TODO##cog.alternate":"Search, sort and filters",
"cog.alternate":"Suche, Sortierung und Filter",
"content.series":"Serien: ",
"content.series.data":"Buch {0} der {1} - Reihe",
"content.summary":"Inhalt: ",
"##TODO##customize.email":"Set your email (to allow book emailing)",
"##TODO##customize.fancybox":"Use a Lightbox",
"##TODO##customize.filter":"Enable tag filtering",
"##TODO##customize.paging":"Max number of books per page (-1 to disable)",
"##TODO##customize.style":"Theme",
"##TODO##customize.title":"Customize COPS UI",
"##TODO##home.alternate":"Home",
"customize.email":"Geben Sie Ihre E-Mail-Adresse an (erlaubt das Zusenden von Büchern)",
"customize.fancybox":"Benutze die Lightbox",
"customize.filter":"Erlaube das Filtern durch Tags",
"customize.paging":"Maximale Anzahl von Büchern pro Seite (-1 zum deaktivieren)",
"customize.style":"Thema",
"customize.title":"Anpassungen an COPS",
"home.alternate":"Startseite",
"i18n.coversection":"Umschlag",
"language.title":"Sprache",
"##TODO##languages.alphabetical.many":"Alphabetical index of the {0} languages",
"languages.alphabetical.many":"Alphabetischer Index der {0} Sprachen",
"##TODO##languages.alphabetical.none":"Alphabetical index of absolutely no language",
"##TODO##languages.alphabetical.one":"Alphabetical index of the single language",
"##TODO##languages.title":"Languages",
"##TODO##mail.messagenotsent":"Message could not be sent.",
"##TODO##mail.messagesent":"Message has been sent",
"##TODO##paging.next.alternate":"Next",
"##TODO##paging.previous.alternate":"Previous",
"##TODO##permalink.alternate":"Permalink",
"##TODO##pubdate.title":"Publication year",
"languages.alphabetical.one":"Alphabetischer Index der einen Sprache",
"languages.title":"Sprachen",
"mail.messagenotsent":"E-Mail konnte nicht gesendet werden.",
"mail.messagesent":"E-Mail wurde gesendet.",
"paging.next.alternate":"Nächste",
"paging.previous.alternate":"Vorherige",
"permalink.alternate":"Permalink",
"pubdate.title":"Veröffentlichung",
"recent.list":"{0} neue Bücher",
"recent.title":"Neuzugänge",
"##TODO##search.alternate":"Search",
"search.alternate":"Suche",
"search.result":"Suchergebnis für",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"search.sortorder.asc":"Auf",
"search.sortorder.desc":"Ab",
"series.alphabetical.many":"Alphabetischer Index der {0} Serien",
"##TODO##series.alphabetical.none":"Alphabetical index of absolutely no series",
"series.alphabetical.one":"Alphabetischer Index der Serie",
"series.title":"Serien",
"##TODO##sort.alternate":"Sort",
"seriesword.many":"{0} Serien",
"seriesword.none":"Keine Serie",
"seriesword.one":"1 Serie",
"sort.alternate":"Sortierung",
"splitByLetter.book.other":"Andere Bücher",
"splitByLetter.letter":"{0} unter {1}",
"tags.alphabetical.many":"Alphabetischer Index der {0} Schlagwörter",
"##TODO##tags.alphabetical.none":"Alphabetical index of absolutely no tag",
"tags.alphabetical.one":"Alphabetischer Index des Schlagworts",
"tags.title":"Schlagwörter",
"tagword.many":"{0} Schlagwörter",
"tagword.none":"Kein Schlagwort",
"tagword.one":"1 Schlagwort",
"tagword.title":"Schlagwörter",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",
"##TODO##languages.afr":"Afrikaans",
"##TODO##languages.aka":"Akan",
"##TODO##languages.sqi":"Albanian",
"##TODO##languages.amh":"Amharic",
"##TODO##languages.ara":"Arabic",
"##TODO##languages.arg":"Aragonese",
"##TODO##languages.hye":"Armenian",
"##TODO##languages.asm":"Assamese",
"##TODO##languages.ava":"Avaric",
"##TODO##languages.ave":"Avestan",
"languages.abk":"Abchasisch",
"languages.aaf":"Afar",
"languages.afr":"Afrikaans",
"languages.aka":"Akan",
"languages.sqi":"Albanisch",
"languages.amh":"Amharisch",
"languages.ara":"Arabisch",
"languages.arg":"Aragonisch",
"languages.hye":"Armenisch",
"languages.asm":"Assamesisch",
"languages.ava":"Awarisch",
"languages.ave":"Avestisch",
"##TODO##languages.aym":"Aymara",
"##TODO##languages.aze":"Azerbaijani",
"##TODO##languages.bam":"Bambara",
@ -78,38 +88,38 @@
"##TODO##languages.ben":"Bengali",
"##TODO##languages.bih":"Bihari",
"##TODO##languages.bis":"Bislama",
"##TODO##languages.bos":"Bosnian",
"languages.bos":"Bosnisch",
"##TODO##languages.bre":"Breton",
"##TODO##languages.bul":"Bulgarian",
"languages.bul":"Bulgarisch",
"##TODO##languages.mya":"Burmese",
"##TODO##languages.cat":"Catalan",
"##TODO##languages.cha":"Chamorro",
"##TODO##languages.che":"Chechen",
"##TODO##languages.nya":"Chichewa",
"##TODO##languages.zho":"Chinese",
"languages.zho":"Chinesisch",
"##TODO##languages.chv":"Chuvash",
"##TODO##languages.cor":"Cornish",
"##TODO##languages.cos":"Corsican",
"##TODO##languages.cre":"Cree",
"##TODO##languages.hrv":"Croatian",
"##TODO##languages.ces":"Czech",
"##TODO##languages.dan":"Danish",
"languages.hrv":"Kroatisch",
"languages.ces":"Tschechisch",
"languages.dan":"Dänisch",
"##TODO##languages.div":"Divehi",
"##TODO##languages.nld":"Dutch",
"languages.nld":"Niederländisch",
"##TODO##languages.dzo":"Dzongkha",
"##TODO##languages.eng":"English",
"##TODO##languages.epo":"Esperanto",
"languages.eng":"Englisch",
"languages.epo":"Esperanto",
"##TODO##languages.est":"Estonian",
"##TODO##languages.ewe":"Ewe",
"##TODO##languages.fao":"Faroese",
"##TODO##languages.fij":"Fijian",
"##TODO##languages.fin":"Finnish",
"##TODO##languages.fra":"French",
"languages.fin":"Finnisch",
"languages.fra":"Französisch",
"##TODO##languages.ful":"Fula",
"##TODO##languages.glg":"Galician",
"##TODO##languages.kat":"Georgian",
"##TODO##languages.deu":"German",
"##TODO##languages.ell":"Greek",
"languages.kat":"Georgisch",
"languages.deu":"Deutsch",
"languages.ell":"Griechisch",
"##TODO##languages.grn":"Guaraní",
"##TODO##languages.guj":"Gujarati",
"##TODO##languages.hat":"Haitian",
@ -118,21 +128,21 @@
"##TODO##languages.her":"Herero",
"##TODO##languages.hin":"Hindi",
"##TODO##languages.hmo":"Hiri Motu",
"##TODO##languages.hun":"Hungarian",
"languages.hun":"Ungarisch",
"##TODO##languages.ina":"Interlingua",
"##TODO##languages.ind":"Indonesian",
"languages.ind":"Indonesisch",
"##TODO##languages.ile":"Interlingue",
"##TODO##languages.gle":"Irish",
"languages.gle":"Irisch",
"##TODO##languages.ibo":"Igbo",
"##TODO##languages.ipk":"Inupiaq",
"##TODO##languages.ido":"Ido",
"##TODO##languages.isl":"Icelandic",
"##TODO##languages.ita":"Italian",
"languages.isl":"Isländisch",
"languages.ita":"Italienisch",
"##TODO##languages.iku":"Inuktitut",
"##TODO##languages.jpn":"Japanese",
"languages.jpn":"Japanisch",
"##TODO##languages.jav":"Javanese",
"##TODO##languages.kal":"Kalaallisut",
"##TODO##languages.kan":"Kannada",
"languages.kan":"Kanaresisch",
"##TODO##languages.kau":"Kanuri",
"##TODO##languages.kas":"Kashmiri",
"##TODO##languages.kaz":"Kazakh",
@ -142,11 +152,11 @@
"##TODO##languages.kir":"Kyrgyz",
"##TODO##languages.kom":"Komi",
"##TODO##languages.kon":"Kongo",
"##TODO##languages.kor":"Korean",
"languages.kor":"Koreanisch",
"##TODO##languages.kur":"Kurdish",
"##TODO##languages.kua":"Kwanyama",
"##TODO##languages.lat":"Latin",
"##TODO##languages.ltz":"Luxembourgish",
"languages.lat":"Lateinisch",
"languages.ltz":"Luxemburgisch",
"##TODO##languages.lug":"Ganda",
"##TODO##languages.lim":"Limburgish",
"##TODO##languages.lin":"Lingala",
@ -163,7 +173,7 @@
"##TODO##languages.mri":"Māori",
"##TODO##languages.mar":"Marathi",
"##TODO##languages.mah":"Marshallese",
"##TODO##languages.mon":"Mongolian",
"languages.mon":"Mongolisch",
"##TODO##languages.nau":"Nauru",
"##TODO##languages.nav":"Navajo",
"##TODO##languages.nob":"Norwegian Bokmål",
@ -171,7 +181,7 @@
"##TODO##languages.nep":"Nepali",
"##TODO##languages.ndo":"Ndonga",
"##TODO##languages.nno":"Norwegian Nynorsk",
"##TODO##languages.nor":"Norwegian",
"languages.nor":"Norwegisch",
"##TODO##languages.iii":"Nuosu",
"##TODO##languages.nbl":"South Ndebele",
"##TODO##languages.oci":"Occitan",
@ -182,22 +192,22 @@
"##TODO##languages.oss":"Ossetian",
"##TODO##languages.pan":"Panjabi",
"##TODO##languages.pli":"Pāli",
"##TODO##languages.fas":"Persian",
"##TODO##languages.pol":"Polish",
"languages.fas":"Persisch",
"languages.pol":"Polnisch",
"##TODO##languages.pus":"Pashto",
"##TODO##languages.por":"Portuguese",
"languages.por":"Portugisisch",
"##TODO##languages.que":"Quechua",
"##TODO##languages.roh":"Romansh",
"##TODO##languages.run":"Kirundi",
"##TODO##languages.ron":"Romanian",
"##TODO##languages.rus":"Russian",
"languages.rus":"Russisch",
"##TODO##languages.san":"Sanskrit",
"##TODO##languages.srd":"Sardinian",
"##TODO##languages.snd":"Sindhi",
"##TODO##languages.sme":"Northern Sami",
"##TODO##languages.smo":"Samoan",
"##TODO##languages.sag":"Sango",
"##TODO##languages.srp":"Serbian",
"languages.srp":"Serbisch",
"##TODO##languages.gla":"Scottish Gaelic",
"##TODO##languages.sna":"Shona",
"##TODO##languages.sin":"Sinhala",
@ -205,11 +215,11 @@
"##TODO##languages.slv":"Slovene",
"##TODO##languages.som":"Somali",
"##TODO##languages.sot":"Southern Sotho",
"##TODO##languages.spa":"Spanish",
"languages.spa":"Spanisch",
"##TODO##languages.sun":"Sundanese",
"##TODO##languages.swa":"Swahili",
"##TODO##languages.ssw":"Swati",
"##TODO##languages.swe":"Swedish",
"languages.swe":"Schwedisch",
"##TODO##languages.tam":"Tamil",
"##TODO##languages.tel":"Telugu",
"##TODO##languages.tgk":"Tajik",
@ -220,17 +230,17 @@
"##TODO##languages.tgl":"Tagalog",
"##TODO##languages.tsn":"Tswana",
"##TODO##languages.ton":"Tonga",
"##TODO##languages.tur":"Turkish",
"languages.tur":"Türkisch",
"##TODO##languages.tso":"Tsonga",
"##TODO##languages.tat":"Tatar",
"##TODO##languages.twi":"Twi",
"##TODO##languages.tah":"Tahitian",
"##TODO##languages.uig":"Uighur",
"##TODO##languages.ukr":"Ukrainian",
"languages.ukr":"Ukrainisch",
"##TODO##languages.urd":"Urdu",
"##TODO##languages.uzb":"Uzbek",
"##TODO##languages.ven":"Venda",
"##TODO##languages.vie":"Vietnamese",
"languages.vie":"Vietnamesisch",
"##TODO##languages.vol":"Volapük",
"##TODO##languages.win":"Walloon",
"##TODO##languages.cym":"Welsh",

View file

@ -43,12 +43,19 @@
"recent.title":"Recent additions",
"search.alternate":"Search",
"search.result":"Search result for *{0}*",
"search.result.author":"Search result for *{0}* in authors",
"search.result.book":"Search result for *{0}* in books",
"search.result.series":"Search result for *{0}* in series",
"search.result.tag":"Search result for *{0}* in tags",
"search.sortorder.asc":"Asc",
"search.sortorder.desc":"Desc",
"series.alphabetical.many":"Alphabetical index of the {0} series",
"series.alphabetical.none":"Alphabetical index of absolutely no series",
"series.alphabetical.one":"Alphabetical index of the single series",
"series.title":"Series",
"seriesword.many":"{0} series",
"seriesword.none":"No series",
"seriesword.one":"1 series",
"sort.alternate":"Sort",
"splitByLetter.book.other":"Other books",
"splitByLetter.letter":"{0} starting with {1}",
@ -56,6 +63,9 @@
"tags.alphabetical.none":"Alphabetical index of absolutely no tag",
"tags.alphabetical.one":"Alphabetical index of the single tag",
"tags.title":"Tags",
"tagword.many":"{0} tags",
"tagword.none":"No tag",
"tagword.one":"1 tag",
"tagword.title":"Tags",
"languages.abk":"Abkhaz",
"languages.aaf":"Afar",

View file

@ -43,12 +43,19 @@
"recent.title":"Añadidos recientemente",
"##TODO##search.alternate":"Search",
"##TODO##search.result":"Search result for *{0}*",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"##TODO##search.sortorder.asc":"Asc",
"##TODO##search.sortorder.desc":"Desc",
"series.alphabetical.many":"Indice alfabético de {0}",
"##TODO##series.alphabetical.none":"Alphabetical index of absolutely no series",
"series.alphabetical.one":"Indice de una sola serie",
"series.title":"Series:",
"seriesword.many":"series",
"seriesword.none":"Sin series",
"seriesword.one":"1 serie",
"##TODO##sort.alternate":"Sort",
"splitByLetter.book.other":"Otros libros",
"splitByLetter.letter":"{0} que empiezan por {1}",
@ -56,6 +63,9 @@
"##TODO##tags.alphabetical.none":"Alphabetical index of absolutely no tag",
"tags.alphabetical.one":"Listado Alfabético de la unica etiqueta",
"tags.title":"etiquetas",
"tagword.many":"etiquetas",
"tagword.none":"Sin etiquetas",
"tagword.one":"1 etiqueta",
"tagword.title":"Etiquetas",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",

View file

@ -43,12 +43,19 @@
"recent.title":"Ajouts récents",
"search.alternate":"Rechercher",
"search.result":"Résultats pour *{0}*",
"search.result.author":"Résultats pour *{0}* dans les auteurs",
"search.result.book":"Résultats pour *{0}* dans les livres",
"search.result.series":"Résultats pour *{0}* dans les colllections",
"search.result.tag":"Résultats pour *{0}* dans les étiquettes",
"search.sortorder.asc":"Crois.",
"search.sortorder.desc":"Décrois.",
"series.alphabetical.many":"Index alphabétique de {0} collections",
"##TODO##series.alphabetical.none":"Alphabetical index of absolutely no series",
"series.alphabetical.one":"Index alphabétique de la seule collection",
"series.title":"Collections",
"seriesword.many":"{0} collections",
"seriesword.none":"Pas de collection",
"seriesword.one":"1 collection",
"sort.alternate":"Trier",
"splitByLetter.book.other":"Autres livres",
"splitByLetter.letter":"{0} débutant par {1}",
@ -56,6 +63,9 @@
"##TODO##tags.alphabetical.none":"Alphabetical index of absolutely no tag",
"tags.alphabetical.one":"Index alphabétique de la seule étiquette",
"tags.title":"Étiquettes",
"tagword.many":"{0} étiquettes",
"tagword.none":"Sans étiquette",
"tagword.one":"1 étiquette",
"tagword.title":"Étiquettes",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",

View file

@ -43,12 +43,19 @@
"recent.title":"Ultime aggiunte",
"search.alternate":"Cerca",
"search.result":"Risultati per *{0}*",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"search.sortorder.asc":"Asc",
"search.sortorder.desc":"Disc",
"series.alphabetical.many":"Indice alfabetico di {0} collane",
"series.alphabetical.none":"Indice alfabetico indipendente dalla collana",
"series.alphabetical.one":"Indice alfabetico di una sola collana",
"series.title":"Collane",
"seriesword.many":"{0} collane",
"seriesword.none":"Nessuna collana",
"seriesword.one":"1 collana",
"sort.alternate":"Ordina",
"splitByLetter.book.other":"Altri libri",
"splitByLetter.letter":"{0} che iniziano per {1}",
@ -56,6 +63,9 @@
"tags.alphabetical.none":"Indice alfabetico indipendente dall'argomento",
"tags.alphabetical.one":"Indice alfabetico del solo argomento",
"tags.title":"Argomenti",
"tagword.many":"{0} argomenti",
"tagword.none":"Senza argomento",
"tagword.one":"1 argomento",
"tagword.title":"Argomenti",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",

View file

@ -43,12 +43,19 @@
"recent.title":"Nylig lagt til",
"search.alternate":"Søk",
"search.result":"Søkeresultat for *{0}*",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"search.sortorder.asc":"Stigende",
"search.sortorder.desc":"Synkende",
"series.alphabetical.many":"Alfabetisk indeks for {0} serier",
"series.alphabetical.none":"Alfabetisk indeks for ingen serier",
"series.alphabetical.one":"Alfabetisk indeks for èn enkelt serie",
"series.title":"Serier",
"seriesword.many":"{0} serier",
"seriesword.none":"Ingen serier",
"seriesword.one":"1 serie",
"sort.alternate":"Sorter",
"splitByLetter.book.other":"Andre bøker",
"splitByLetter.letter":"{0} begynner med {1}",
@ -56,6 +63,9 @@
"tags.alphabetical.none":"Alfabetisk indeks for ingen stikkord",
"tags.alphabetical.one":"Alfabetisk indeks for ett enkelt stikkord",
"tags.title":"Stikkord",
"tagword.many":"{0} stikkord",
"tagword.none":"Ingen stikkord",
"tagword.one":"1 stikkord",
"tagword.title":"Stikkord",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",

View file

@ -43,12 +43,19 @@
"recent.title":"Recent toegevoegde boeken",
"search.alternate":"Zoeken",
"search.result":"Zoekresultaat voor *{0}*",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"search.sortorder.asc":"A-Z",
"search.sortorder.desc":"Z-A",
"series.alphabetical.many":"Alfabetische index van {0} series",
"series.alphabetical.none":"Alfabetische index van absoluut geen ekele serie",
"series.alphabetical.one":"Alfabetische index van 1 serie",
"series.title":"Series",
"seriesword.many":"{0} series",
"seriesword.none":"Geen series",
"seriesword.one":"1 serie",
"sort.alternate":"Sorteren",
"splitByLetter.book.other":"Andere boeken",
"splitByLetter.letter":"{0} beginnend met {1}",
@ -56,6 +63,9 @@
"tags.alphabetical.none":"Alfabetische index van absoluut geen enkele tag",
"tags.alphabetical.one":"Alfabetische index van 1 tag",
"tags.title":"Tags",
"tagword.many":"{0} tags",
"tagword.none":"Geen tag",
"tagword.one":"1 tag",
"tagword.title":"Tags",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",

View file

@ -43,12 +43,19 @@
"recent.title":"Adições recentes",
"search.alternate":"Busca",
"search.result":"Resultado da busca por *{0}*",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"search.sortorder.asc":"Asc",
"search.sortorder.desc":"Desc",
"series.alphabetical.many":"Índice alfabético das {0} séries",
"series.alphabetical.none":"Índice alfabético de nenhuma série",
"series.alphabetical.one":"Índice alfabético de uma série",
"series.title":"Séries",
"seriesword.many":"{0} séries",
"seriesword.none":"Sem séries",
"seriesword.one":"1 série",
"sort.alternate":"Ordenar",
"splitByLetter.book.other":"Outros livros",
"splitByLetter.letter":"{0} começando com {1}",
@ -56,6 +63,9 @@
"tags.alphabetical.none":"Índice alfabético de nenhuma etiqueta",
"##TODO##tags.alphabetical.one":"Alphabetical index of the single tag",
"tags.title":"Etiquetas",
"tagword.many":"{0} etiquetas",
"tagword.none":"Sem etiquetas",
"tagword.one":"1 etiqueta",
"tagword.title":"Etiquetas",
"languages.abk":"Abcázia",
"languages.aaf":"Afar",

View file

@ -43,12 +43,19 @@
"recent.title":"Недавние поступления",
"##TODO##search.alternate":"Search",
"##TODO##search.result":"Search result for *{0}*",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"##TODO##search.sortorder.asc":"Asc",
"##TODO##search.sortorder.desc":"Desc",
"series.alphabetical.many":"Алфавитный указатель для {0} серий",
"##TODO##series.alphabetical.none":"Alphabetical index of absolutely no series",
"series.alphabetical.one":"Алфавитный указатель для одной серии",
"series.title":"Серии",
"seriesword.many":"{0} серий(и)",
"seriesword.none":"Нет серий",
"seriesword.one":"1 серия",
"##TODO##sort.alternate":"Sort",
"splitByLetter.book.other":"Другие книги",
"splitByLetter.letter":"{0} начать с {1}",
@ -56,6 +63,9 @@
"##TODO##tags.alphabetical.none":"Alphabetical index of absolutely no tag",
"tags.alphabetical.one":"Алфавитный указатель для одного тэга",
"tags.title":"Тэги",
"tagword.many":"{0} тэгов(а)",
"tagword.none":"Нет тэгов",
"tagword.one":"1 тэг",
"tagword.title":"Тэги",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",

View file

@ -43,12 +43,19 @@
"recent.title":"最近添加",
"search.alternate":"搜索",
"search.result":"*{0}* 的搜索结果",
"##TODO##search.result.author":"Search result for *{0}* in authors",
"##TODO##search.result.book":"Search result for *{0}* in books",
"##TODO##search.result.series":"Search result for *{0}* in series",
"##TODO##search.result.tag":"Search result for *{0}* in tags",
"search.sortorder.asc":"升序",
"search.sortorder.desc":"降序",
"series.alphabetical.many":"{0} 个系列的字母索引",
"series.alphabetical.none":"Alphabetical index of absolutely no series",
"series.alphabetical.one":"Alphabetical index of the single series",
"series.title":"系列",
"seriesword.many":"{0} 系列",
"seriesword.none":"没有系列",
"seriesword.one":"1 个系列",
"sort.alternate":"排序",
"splitByLetter.book.other":"其他书籍",
"splitByLetter.letter":"{0} 以 {1} 开头",
@ -56,6 +63,9 @@
"tags.alphabetical.none":"Alphabetical index of absolutely no tag",
"tags.alphabetical.one":"Alphabetical index of the single tag",
"tags.title":"标签",
"tagword.many":"{0} 标签",
"tagword.none":"没有标签",
"tagword.one":"1 个标签",
"tagword.title":"标签",
"##TODO##languages.abk":"Abkhaz",
"##TODO##languages.aaf":"Afar",

23
phpunit.xml Normal file
View file

@ -0,0 +1,23 @@
<phpunit>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<!-- this is the path of the files included in your clover report -->
<directory suffix=".php">./</directory>
<exclude>
<directory suffix=".php">./resources</directory>
</exclude>
<exclude>
<directory suffix=".php">./test</directory>
</exclude>
</whitelist>
</filter>
<logging>
<log type="coverage-clover" target="./clover.xml"/>
</logging>
<testsuites>
<testsuite name="COPS">
<directory>test</directory>
</testsuite>
</testsuites>
</phpunit>

File diff suppressed because one or more lines are too long

View file

@ -58,8 +58,7 @@
.mfp-ajax-cur {
cursor: progress; }
.mfp-zoom-out-cur,
.mfp-zoom-out-cur .mfp-image-holder .mfp-close {
.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
cursor: -moz-zoom-out;
cursor: -webkit-zoom-out;
cursor: zoom-out; }
@ -97,11 +96,9 @@
left: 8px;
right: 8px;
z-index: 1044; }
.mfp-preloader a {
.mfp-preloader a {
color: #cccccc; }
.mfp-preloader a:hover {
.mfp-preloader a:hover {
color: white; }
.mfp-s-ready .mfp-preloader {
@ -110,8 +107,7 @@
.mfp-s-error .mfp-content {
display: none; }
button.mfp-close,
button.mfp-arrow {
button.mfp-close, button.mfp-arrow {
overflow: visible;
cursor: pointer;
background: transparent;
@ -122,7 +118,6 @@ button.mfp-arrow {
z-index: 1046;
-webkit-box-shadow: none;
box-shadow: none; }
button::-moz-focus-inner {
padding: 0;
border: 0; }
@ -176,17 +171,13 @@ button::-moz-focus-inner {
width: 90px;
height: 110px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
.mfp-arrow:active {
.mfp-arrow:active {
margin-top: -54px; }
.mfp-arrow:hover,
.mfp-arrow:focus {
.mfp-arrow:hover, .mfp-arrow:focus {
opacity: 1; }
.mfp-arrow:before, .mfp-arrow:after,
.mfp-arrow .mfp-b,
.mfp-arrow .mfp-a {
.mfp-arrow:before, .mfp-arrow:after,
.mfp-arrow .mfp-b,
.mfp-arrow .mfp-a {
content: '';
display: block;
width: 0;
@ -197,13 +188,13 @@ button::-moz-focus-inner {
margin-top: 35px;
margin-left: 35px;
border: medium inset transparent; }
.mfp-arrow:after,
.mfp-arrow .mfp-a {
.mfp-arrow:after,
.mfp-arrow .mfp-a {
border-top-width: 13px;
border-bottom-width: 13px;
top: 8px; }
.mfp-arrow:before,
.mfp-arrow .mfp-b {
.mfp-arrow:before,
.mfp-arrow .mfp-b {
border-top-width: 21px;
border-bottom-width: 21px; }
@ -231,19 +222,19 @@ button::-moz-focus-inner {
.mfp-iframe-holder {
padding-top: 40px;
padding-bottom: 40px; }
.mfp-iframe-holder .mfp-content {
.mfp-iframe-holder .mfp-content {
line-height: 0;
width: 100%;
max-width: 900px; }
.mfp-iframe-holder .mfp-close {
top: -40px; }
.mfp-iframe-scaler {
width: 100%;
height: 0;
overflow: hidden;
padding-top: 56.25%; }
.mfp-iframe-scaler iframe {
.mfp-iframe-scaler iframe {
position: absolute;
display: block;
top: 0;
@ -253,9 +244,6 @@ button::-moz-focus-inner {
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
background: black; }
.mfp-iframe-holder .mfp-close {
top: -40px; }
/* Main image in popup */
img.mfp-img {
width: auto;
@ -270,7 +258,9 @@ img.mfp-img {
margin: 0 auto; }
/* The shadow behind the image */
.mfp-figure:after {
.mfp-figure {
line-height: 0; }
.mfp-figure:after {
content: '';
position: absolute;
left: 0;
@ -283,9 +273,11 @@ img.mfp-img {
z-index: -1;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
background: #444444; }
.mfp-figure {
line-height: 0; }
.mfp-figure small {
color: #bdbdbd;
display: block;
font-size: 12px;
line-height: 14px; }
.mfp-bottom-bar {
margin-top: -36px;
@ -302,12 +294,6 @@ img.mfp-img {
word-wrap: break-word;
padding-right: 36px; }
.mfp-figure small {
color: #bdbdbd;
display: block;
font-size: 12px;
line-height: 14px; }
.mfp-image-holder .mfp-content {
max-width: 100%; }
@ -321,15 +307,16 @@ img.mfp-img {
.mfp-img-mobile .mfp-image-holder {
padding-left: 0;
padding-right: 0; }
.mfp-img-mobile img.mfp-img {
padding: 0; }
/* The shadow behind the image */
.mfp-img-mobile .mfp-figure {
/* The shadow behind the image */ }
.mfp-img-mobile .mfp-figure:after {
top: 0;
bottom: 0; }
.mfp-img-mobile .mfp-figure small {
display: inline;
margin-left: 5px; }
.mfp-img-mobile .mfp-bottom-bar {
background: rgba(0, 0, 0, 0.6);
bottom: 0;
@ -340,14 +327,11 @@ img.mfp-img {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.mfp-img-mobile .mfp-bottom-bar:empty {
padding: 0; }
.mfp-img-mobile .mfp-counter {
right: 5px;
top: 3px; }
.mfp-img-mobile .mfp-close {
top: 0;
right: 0;
@ -357,11 +341,7 @@ img.mfp-img {
background: rgba(0, 0, 0, 0.6);
position: fixed;
text-align: center;
padding: 0; }
.mfp-img-mobile .mfp-figure small {
display: inline;
margin-left: 5px; } }
padding: 0; } }
@media all and (max-width: 900px) {
.mfp-arrow {
-webkit-transform: scale(0.75);

View file

@ -1,7 +1,8 @@
/* Laura Doktorova https://github.com/olado/doT */(function(){function o(){var a={"&":"&#38;","<":"&#60;",">":"&#62;",'"':"&#34;","'":"&#39;","/":"&#47;"},b=/&(?!#?\w+;)|<|>|"|'|\//g;return function(){return this?this.replace(b,function(c){return a[c]||c}):this}}function p(a,b,c){return(typeof b==="string"?b:b.toString()).replace(a.define||i,function(l,e,f,g){if(e.indexOf("def.")===0)e=e.substring(4);if(!(e in c))if(f===":"){a.defineParams&&g.replace(a.defineParams,function(n,h,d){c[e]={arg:h,text:d}});e in c||(c[e]=g)}else(new Function("def","def['"+
e+"']="+g))(c);return""}).replace(a.use||i,function(l,e){if(a.useParams)e=e.replace(a.useParams,function(g,n,h,d){if(c[h]&&c[h].arg&&d){g=(h+":"+d).replace(/'|\\/g,"_");c.__exp=c.__exp||{};c.__exp[g]=c[h].text.replace(RegExp("(^|[^\\w$])"+c[h].arg+"([^\\w$])","g"),"$1"+d+"$2");return n+"def.__exp['"+g+"']"}});var f=(new Function("def","return "+e))(c);return f?p(a,f,c):f})}function m(a){return a.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}var j={version:"1.0.0",templateSettings:{evaluate:/\{\{([\s\S]+?\}?)\}\}/g,
/* Laura Doktorova https://github.com/olado/doT */
(function(){function o(){var a={"&":"&#38;","<":"&#60;",">":"&#62;",'"':"&#34;","'":"&#39;","/":"&#47;"},b=/&(?!#?\w+;)|<|>|"|'|\//g;return function(){return this?this.replace(b,function(c){return a[c]||c}):this}}function p(a,b,c){return(typeof b==="string"?b:b.toString()).replace(a.define||i,function(l,e,f,g){if(e.indexOf("def.")===0)e=e.substring(4);if(!(e in c))if(f===":"){a.defineParams&&g.replace(a.defineParams,function(n,h,d){c[e]={arg:h,text:d}});e in c||(c[e]=g)}else(new Function("def","def['"+
e+"']="+g))(c);return""}).replace(a.use||i,function(l,e){if(a.useParams)e=e.replace(a.useParams,function(g,n,h,d){if(c[h]&&c[h].arg&&d){g=(h+":"+d).replace(/'|\\/g,"_");c.__exp=c.__exp||{};c.__exp[g]=c[h].text.replace(RegExp("(^|[^\\w$])"+c[h].arg+"([^\\w$])","g"),"$1"+d+"$2");return n+"def.__exp['"+g+"']"}});var f=(new Function("def","return "+e))(c);return f?p(a,f,c):f})}function m(a){return a.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}var j={version:"1.0.1",templateSettings:{evaluate:/\{\{([\s\S]+?(\}?)+)\}\}/g,
interpolate:/\{\{=([\s\S]+?)\}\}/g,encode:/\{\{!([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,useParams:/(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,defineParams:/^\s*([\w$]+):([\s\S]+)/,conditional:/\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,varname:"it",strip:true,append:true,selfcontained:false},template:undefined,
compile:undefined};if(typeof module!=="undefined"&&module.exports)module.exports=j;else if(typeof define==="function"&&define.amd)define(function(){return j});else(function(){return this||(0,eval)("this")})().doT=j;String.prototype.encodeHTML=o();var q={append:{start:"'+(",end:")+'",endencode:"||'').toString().encodeHTML()+'"},split:{start:"';out+=(",end:");out+='",endencode:"||'').toString().encodeHTML();out+='"}},i=/$^/;j.template=function(a,b,c){b=b||j.templateSettings;var l=b.append?q.append:
q.split,e,f=0,g;a=b.use||b.define?p(b,a,c||{}):a;a=("var out='"+(b.strip?a.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):a).replace(/'|\\/g,"\\$&").replace(b.interpolate||i,function(h,d){return l.start+m(d)+l.end}).replace(b.encode||i,function(h,d){e=true;return l.start+m(d)+l.endencode}).replace(b.conditional||i,function(h,d,k){return d?k?"';}else if("+m(k)+"){out+='":"';}else{out+='":k?"';if("+m(k)+"){out+='":"';}out+='"}).replace(b.iterate||i,function(h,
d,k,r){if(!d)return"';} } out+='";f+=1;g=r||"i"+f;d=m(d);return"';var arr"+f+"="+d+";if(arr"+f+"){var "+k+","+g+"=-1,l"+f+"=arr"+f+".length-1;while("+g+"<l"+f+"){"+k+"=arr"+f+"["+g+"+=1];out+='"}).replace(b.evaluate||i,function(h,d){return"';"+m(d)+"out+='"})+"';return out;").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r").replace(/(\s|;|\}|^|\{)out\+='';/g,"$1").replace(/\+''/g,"").replace(/(\s|;|\}|^|\{)out\+=''\+/g,"$1out+=");if(e&&b.selfcontained)a="String.prototype.encodeHTML=("+
compile:undefined},q;if(typeof module!=="undefined"&&module.exports)module.exports=j;else if(typeof define==="function"&&define.amd)define(function(){return j});else{q=function(){return this||(0,eval)("this")}();q.doT=j}String.prototype.encodeHTML=o();var r={append:{start:"'+(",end:")+'",endencode:"||'').toString().encodeHTML()+'"},split:{start:"';out+=(",end:");out+='",endencode:"||'').toString().encodeHTML();out+='"}},i=/$^/;j.template=function(a,b,c){b=b||j.templateSettings;var l=b.append?r.append:
r.split,e,f=0,g;a=b.use||b.define?p(b,a,c||{}):a;a=("var out='"+(b.strip?a.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):a).replace(/'|\\/g,"\\$&").replace(b.interpolate||i,function(h,d){return l.start+m(d)+l.end}).replace(b.encode||i,function(h,d){e=true;return l.start+m(d)+l.endencode}).replace(b.conditional||i,function(h,d,k){return d?k?"';}else if("+m(k)+"){out+='":"';}else{out+='":k?"';if("+m(k)+"){out+='":"';}out+='"}).replace(b.iterate||i,function(h,
d,k,s){if(!d)return"';} } out+='";f+=1;g=s||"i"+f;d=m(d);return"';var arr"+f+"="+d+";if(arr"+f+"){var "+k+","+g+"=-1,l"+f+"=arr"+f+".length-1;while("+g+"<l"+f+"){"+k+"=arr"+f+"["+g+"+=1];out+='"}).replace(b.evaluate||i,function(h,d){return"';"+m(d)+"out+='"})+"';return out;").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r").replace(/(\s|;|\}|^|\{)out\+='';/g,"$1").replace(/\+''/g,"").replace(/(\s|;|\}|^|\{)out\+=''\+/g,"$1out+=");if(e&&b.selfcontained)a="String.prototype.encodeHTML=("+
o.toString()+"());"+a;try{return new Function(b.varname,a)}catch(n){typeof console!=="undefined"&&console.log("Could not create a template function: "+a);throw n;}};j.compile=function(a,b){return j.template(a,null,b)}})();

View file

@ -72,4 +72,22 @@ order by series.sort');
}
return $entryArray;
}
public static function getAllSeriesByQuery($query) {
$result = parent::getDb ()->prepare('select series.id as id, series.name as name, series.sort as sort, count(*) as count
from series, books_series_link
where series.id = series and series.name like ?
group by series.id, series.name, series.sort
order by series.sort');
$entryArray = array();
$result->execute (array ('%' . $query . '%'));
while ($post = $result->fetchObject ())
{
$serie = new Serie ($post->id, $post->sort);
array_push ($entryArray, new Entry ($serie->name, $serie->getEntryId (),
str_format (localize("bookword", $post->count), $post->count), "text",
array ( new LinkNavigation ($serie->getUri ()))));
}
return $entryArray;
}
}

18
tag.php
View file

@ -61,4 +61,22 @@ order by tags.name');
}
return $entryArray;
}
public static function getAllTagsByQuery($query) {
$result = parent::getDb ()->prepare('select tags.id as id, tags.name as name, count(*) as count
from tags, books_tags_link
where tags.id = tag and tags.name like ?
group by tags.id, tags.name
order by tags.name');
$entryArray = array();
$result->execute (array ('%' . $query . '%'));
while ($post = $result->fetchObject ())
{
$tag = new Tag ($post->id, $post->name);
array_push ($entryArray, new Entry ($tag->name, $tag->getEntryId (),
str_format (localize("bookword", $post->count), $post->count), "text",
array ( new LinkNavigation ($tag->getUri ()))));
}
return $entryArray;
}
}

View file

@ -17,7 +17,6 @@
</button>
</div>
<div class="stop">
<input type="hidden" name="current" value="{{=it.page}}" />
<input type="hidden" name="page" value="9" />
{{? it.databaseId != ""}}
<input type="hidden" name="db" value="{{=it.databaseId}}" />

14
test/baseTest.php Normal file
View file

@ -0,0 +1,14 @@
<?php
require_once (dirname(__FILE__) . "/config_test.php");
require_once (dirname(__FILE__) . "/../base.php");
class BaseTest extends PHPUnit_Framework_TestCase
{
public function testAddURLParameter ()
{
$this->assertEquals ("?db=0", addURLParameter ("?", "db", "0"));
$this->assertEquals ("?key=value&db=0", addURLParameter ("?key=value", "db", "0"));
$this->assertEquals ("?key=value&otherKey=&db=0", addURLParameter ("?key=value&otherKey", "db", "0"));
}
}

100
test/bookTest.php Normal file
View file

@ -0,0 +1,100 @@
<?php
require_once (dirname(__FILE__) . "/config_test.php");
require_once (dirname(__FILE__) . "/../book.php");
class StackTest extends PHPUnit_Framework_TestCase
{
public function testGetBookCount ()
{
$this->assertEquals (14, Book::getBookCount ());
}
public function testGetCount ()
{
$entryArray = Book::getCount ();
$this->assertEquals (2, count($entryArray));
$entryAllBooks = $entryArray [0];
$this->assertEquals ("Alphabetical index of the 14 books", $entryAllBooks->content);
$entryRecentBooks = $entryArray [1];
$this->assertEquals ("50 most recent books", $entryRecentBooks->content);
}
public function testGetCountRecent ()
{
global $config;
$config['cops_recentbooks_limit'] = 0;
$entryArray = Book::getCount ();
$this->assertEquals (1, count($entryArray));
$config['cops_recentbooks_limit'] = 2;
$entryArray = Book::getCount ();
$entryRecentBooks = $entryArray [1];
$this->assertEquals ("2 most recent books", $entryRecentBooks->content);
$config['cops_recentbooks_limit'] = 50;
}
public function testGetBooksByAuthor ()
{
// All book by Arthur Conan Doyle
global $config;
$config['cops_max_item_per_page'] = 5;
list ($entryArray, $totalNumber) = Book::getBooksByAuthor (1, 1);
$this->assertEquals (5, count($entryArray));
$this->assertEquals (8, $totalNumber);
list ($entryArray, $totalNumber) = Book::getBooksByAuthor (1, 2);
$this->assertEquals (3, count($entryArray));
$this->assertEquals (8, $totalNumber);
$config['cops_max_item_per_page'] = -1;
list ($entryArray, $totalNumber) = Book::getBooksByAuthor (1, -1);
$this->assertEquals (8, count($entryArray));
$this->assertEquals (-1, $totalNumber);
}
public function testGetBooksBySeries ()
{
// All book from the Sherlock Holmes series
list ($entryArray, $totalNumber) = Book::getBooksBySeries (1, -1);
$this->assertEquals (7, count($entryArray));
$this->assertEquals (-1, $totalNumber);
}
public function testGetBooksByTag ()
{
// All book with the Fiction tag
list ($entryArray, $totalNumber) = Book::getBooksByTag (1, -1);
$this->assertEquals (14, count($entryArray));
$this->assertEquals (-1, $totalNumber);
}
public function testGetBooksByLanguage ()
{
// All english book (= all books)
list ($entryArray, $totalNumber) = Book::getBooksByLanguage (1, -1);
$this->assertEquals (14, count($entryArray));
$this->assertEquals (-1, $totalNumber);
}
public function testGetBookById ()
{
// also check most of book's class methods
$book = Book::getBookById(2);
$this->assertEquals ("The Return of Sherlock Holmes", $book->getTitle ());
$this->assertEquals ("urn:uuid:87ddbdeb-1e27-4d06-b79b-4b2a3bfc6a5f", $book->getEntryId ());
$this->assertEquals ("index.php?page=13&id=2", $book->getDetailUrl ());
$this->assertEquals ("Doyle, Arthur Conan", $book->getAuthorsName ());
$this->assertEquals ("Fiction, Mystery & Detective, Short Stories", $book->getTagsName ());
$this->assertEquals ('<p class="description">The Return of Sherlock Holmes is a collection of 13 Sherlock Holmes stories, originally published in 1903-1904, by Arthur Conan Doyle.<br />The book was first published on March 7, 1905 by Georges Newnes, Ltd and in a Colonial edition by Longmans. 30,000 copies were made of the initial print run. The US edition by McClure, Phillips &amp; Co. added another 28,000 to the run.<br />This was the first Holmes collection since 1893, when Holmes had "died" in "The Adventure of the Final Problem". Having published The Hound of the Baskervilles in 19011902 (although setting it before Holmes\' death) Doyle came under intense pressure to revive his famous character.</p>', $book->getComment (false));
}
}

4
test/config_test.php Normal file
View file

@ -0,0 +1,4 @@
<?php
require_once (dirname(__FILE__) . "/../config_default.php");
$config['calibre_directory'] = dirname(__FILE__) . "/";

BIN
test/metadata.db Normal file

Binary file not shown.

View file

@ -60,6 +60,8 @@ sub handleLanguageFile {
my ($file) = @_;
(my $lang = $file) =~ s/Localization_(\w\w)\.json/$1/;
my $file = "../lang/" . $file;
my $total = 0;
my $translated = 0;
debug ("language file: $file / $lang \n");
@ -80,12 +82,16 @@ sub handleLanguageFile {
print OUTPUT "{\n";
foreach my $name (@strings) {
$total++ if ($name !~ /^languages\.\w{3}$/);
if (not exists ($values{$lang}{$name})) {
print OUTPUT "\"##TODO##$name\":\"$values{en}{$name}\",\n";
} else {
$translated++ if ($name !~ /^languages\.\w{3}$/);
print OUTPUT "\"$name\":\"$values{$lang}{$name}\",\n";
}
}
my $percentage = ($translated * 100) / $total;
debug (" $translated / $total ($percentage %) \n");
print OUTPUT "\"DO_NOT_TRANSLATE\":\"end\"\n";
print OUTPUT "}\n";

View file

@ -237,7 +237,7 @@ function navigateTo (url) {
function updatePage (data) {
var result;
filterList = {};
data ["c"] = currentData ["c"];
data.c = currentData.c;
if (false && $("section").length && currentData.isPaginated === 0 && data.isPaginated === 0) {
// Partial update (for now disabled)
debug_log ("Partial update");
@ -251,7 +251,7 @@ function updatePage (data) {
}
document.title = data.title;
currentData = data;
setTimeout( function() { $("input[name=query]").focus() }, 500 );
setTimeout( function() { $("input[name=query]").focus(); }, 500 );
debug_log (elapsed ());
@ -325,7 +325,7 @@ function link_Clicked (event) {
before = new Date ();
var jsonurl = url.replace ("index", "getJSON");
$.getJSON(jsonurl, function(data) {
data ["c"] = currentData ["c"];
data.c = currentData.c;
var detail = "";
if (data.page === "16") {
detail = data.fullhtml;