Calibre OPDS (and HTML) PHP Server : web-based light alternative to Calibre content server / Calibre2OPDS to serve ebooks (epub, mobi, pdf, ...) http://blog.slucas.fr/en/oss/calibre-opds-php-server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

12 years ago
12 years ago
**2012-11-22** **Added global support for publishers** Files modified: *base.php* - changed class Entry, - adding a constant ```cops:publishers``` to the icon array for the feed. - changed class Page - added branches to the page selector switch - changed Page->public function InitializeContent - added call to pull publisher count from database - changed class PageAllBooks - changed it so ```getCurrentOption``` is actually used... - added page descendant class ```PageAllPublishers``` - handles pulling the publishers category from database - added page descendant class ```PagePublisherDetail``` - handles pulling the books per publisher data from database - changed class PageQueryResult - added constant and switches for publisher search scope - abstract class Base - added constants for the publisher pages *book.php* - added require statement for publisher.php - added ```SQL_BOOKS_BY_PUBLISHER``` query to retrieve books by publisher. - changed class Book - added query constant - added publisher item - added test in case no known publisher - added publishername and url array elements for the JSON output - added public function ```getPublisher``` - added public static function ```getBooksByPublisher``` to fire the query - changed function getJson - added publisher category to search - added publishername (single) and publishertitle(plural) localization entries to i18n translation array *index.php* - added require statement for publisher.php *lang/Localization_en.json - added new localization entries for publisher labels (see below) ``` "publisher.alphabetical.many":"Alphabetical index of the {0} publishers", "publisher.alphabetical.none":"Alphabetical index of absolutely no publisher", "publisher.alphabetical.one":"Alphabetical index of the single publisher", "publisher.name":"Publisher", "publisher.title":"Publishers", "publisherword.many":"{0} publishers", "publisherword.none":"No publisher", "publisherword.one":"1 publisher", "search.result.publisher":"Search result for *{0}* in publishers", ``` *templates\bookdetail.html* - added publisher label and item to bookdetail popup *test\bookTest.php* - added indices and names of publishers added to testdatabase as comment - added test function ```testGetBooksByPublisher``` - changed test function testGetBookById to add assertion for publisher name - changed test function testTypeaheadSearch to add search on partial publisher name. *test\pageTest.php* - changed test function testPageIndex to insert publisher category and adjust page indices - changed test function testPageIndexWithCustomColum to adjust for the changed page indices - added test function testPageAllPublishers - added test function testPagePublishersDetail - added test function testPageSearchScopePublishers *test\BaseWithSomeBooks\metadata.db* - added 5 publishers spread across all 14 books, replacing the original publisher Feedbooks Files added: *publisher.php*
10 years ago
12 years ago
**2012-11-22** **Added global support for publishers** Files modified: *base.php* - changed class Entry, - adding a constant ```cops:publishers``` to the icon array for the feed. - changed class Page - added branches to the page selector switch - changed Page->public function InitializeContent - added call to pull publisher count from database - changed class PageAllBooks - changed it so ```getCurrentOption``` is actually used... - added page descendant class ```PageAllPublishers``` - handles pulling the publishers category from database - added page descendant class ```PagePublisherDetail``` - handles pulling the books per publisher data from database - changed class PageQueryResult - added constant and switches for publisher search scope - abstract class Base - added constants for the publisher pages *book.php* - added require statement for publisher.php - added ```SQL_BOOKS_BY_PUBLISHER``` query to retrieve books by publisher. - changed class Book - added query constant - added publisher item - added test in case no known publisher - added publishername and url array elements for the JSON output - added public function ```getPublisher``` - added public static function ```getBooksByPublisher``` to fire the query - changed function getJson - added publisher category to search - added publishername (single) and publishertitle(plural) localization entries to i18n translation array *index.php* - added require statement for publisher.php *lang/Localization_en.json - added new localization entries for publisher labels (see below) ``` "publisher.alphabetical.many":"Alphabetical index of the {0} publishers", "publisher.alphabetical.none":"Alphabetical index of absolutely no publisher", "publisher.alphabetical.one":"Alphabetical index of the single publisher", "publisher.name":"Publisher", "publisher.title":"Publishers", "publisherword.many":"{0} publishers", "publisherword.none":"No publisher", "publisherword.one":"1 publisher", "search.result.publisher":"Search result for *{0}* in publishers", ``` *templates\bookdetail.html* - added publisher label and item to bookdetail popup *test\bookTest.php* - added indices and names of publishers added to testdatabase as comment - added test function ```testGetBooksByPublisher``` - changed test function testGetBookById to add assertion for publisher name - changed test function testTypeaheadSearch to add search on partial publisher name. *test\pageTest.php* - changed test function testPageIndex to insert publisher category and adjust page indices - changed test function testPageIndexWithCustomColum to adjust for the changed page indices - added test function testPageAllPublishers - added test function testPagePublishersDetail - added test function testPageSearchScopePublishers *test\BaseWithSomeBooks\metadata.db* - added 5 publishers spread across all 14 books, replacing the original publisher Feedbooks Files added: *publisher.php*
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
**2012-11-22** **Added global support for publishers** Files modified: *base.php* - changed class Entry, - adding a constant ```cops:publishers``` to the icon array for the feed. - changed class Page - added branches to the page selector switch - changed Page->public function InitializeContent - added call to pull publisher count from database - changed class PageAllBooks - changed it so ```getCurrentOption``` is actually used... - added page descendant class ```PageAllPublishers``` - handles pulling the publishers category from database - added page descendant class ```PagePublisherDetail``` - handles pulling the books per publisher data from database - changed class PageQueryResult - added constant and switches for publisher search scope - abstract class Base - added constants for the publisher pages *book.php* - added require statement for publisher.php - added ```SQL_BOOKS_BY_PUBLISHER``` query to retrieve books by publisher. - changed class Book - added query constant - added publisher item - added test in case no known publisher - added publishername and url array elements for the JSON output - added public function ```getPublisher``` - added public static function ```getBooksByPublisher``` to fire the query - changed function getJson - added publisher category to search - added publishername (single) and publishertitle(plural) localization entries to i18n translation array *index.php* - added require statement for publisher.php *lang/Localization_en.json - added new localization entries for publisher labels (see below) ``` "publisher.alphabetical.many":"Alphabetical index of the {0} publishers", "publisher.alphabetical.none":"Alphabetical index of absolutely no publisher", "publisher.alphabetical.one":"Alphabetical index of the single publisher", "publisher.name":"Publisher", "publisher.title":"Publishers", "publisherword.many":"{0} publishers", "publisherword.none":"No publisher", "publisherword.one":"1 publisher", "search.result.publisher":"Search result for *{0}* in publishers", ``` *templates\bookdetail.html* - added publisher label and item to bookdetail popup *test\bookTest.php* - added indices and names of publishers added to testdatabase as comment - added test function ```testGetBooksByPublisher``` - changed test function testGetBookById to add assertion for publisher name - changed test function testTypeaheadSearch to add search on partial publisher name. *test\pageTest.php* - changed test function testPageIndex to insert publisher category and adjust page indices - changed test function testPageIndexWithCustomColum to adjust for the changed page indices - added test function testPageAllPublishers - added test function testPagePublishersDetail - added test function testPageSearchScopePublishers *test\BaseWithSomeBooks\metadata.db* - added 5 publishers spread across all 14 books, replacing the original publisher Feedbooks Files added: *publisher.php*
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
**2012-11-22** **Added global support for publishers** Files modified: *base.php* - changed class Entry, - adding a constant ```cops:publishers``` to the icon array for the feed. - changed class Page - added branches to the page selector switch - changed Page->public function InitializeContent - added call to pull publisher count from database - changed class PageAllBooks - changed it so ```getCurrentOption``` is actually used... - added page descendant class ```PageAllPublishers``` - handles pulling the publishers category from database - added page descendant class ```PagePublisherDetail``` - handles pulling the books per publisher data from database - changed class PageQueryResult - added constant and switches for publisher search scope - abstract class Base - added constants for the publisher pages *book.php* - added require statement for publisher.php - added ```SQL_BOOKS_BY_PUBLISHER``` query to retrieve books by publisher. - changed class Book - added query constant - added publisher item - added test in case no known publisher - added publishername and url array elements for the JSON output - added public function ```getPublisher``` - added public static function ```getBooksByPublisher``` to fire the query - changed function getJson - added publisher category to search - added publishername (single) and publishertitle(plural) localization entries to i18n translation array *index.php* - added require statement for publisher.php *lang/Localization_en.json - added new localization entries for publisher labels (see below) ``` "publisher.alphabetical.many":"Alphabetical index of the {0} publishers", "publisher.alphabetical.none":"Alphabetical index of absolutely no publisher", "publisher.alphabetical.one":"Alphabetical index of the single publisher", "publisher.name":"Publisher", "publisher.title":"Publishers", "publisherword.many":"{0} publishers", "publisherword.none":"No publisher", "publisherword.one":"1 publisher", "search.result.publisher":"Search result for *{0}* in publishers", ``` *templates\bookdetail.html* - added publisher label and item to bookdetail popup *test\bookTest.php* - added indices and names of publishers added to testdatabase as comment - added test function ```testGetBooksByPublisher``` - changed test function testGetBookById to add assertion for publisher name - changed test function testTypeaheadSearch to add search on partial publisher name. *test\pageTest.php* - changed test function testPageIndex to insert publisher category and adjust page indices - changed test function testPageIndexWithCustomColum to adjust for the changed page indices - added test function testPageAllPublishers - added test function testPagePublishersDetail - added test function testPageSearchScopePublishers *test\BaseWithSomeBooks\metadata.db* - added 5 publishers spread across all 14 books, replacing the original publisher Feedbooks Files added: *publisher.php*
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
**2012-11-22** **Added global support for publishers** Files modified: *base.php* - changed class Entry, - adding a constant ```cops:publishers``` to the icon array for the feed. - changed class Page - added branches to the page selector switch - changed Page->public function InitializeContent - added call to pull publisher count from database - changed class PageAllBooks - changed it so ```getCurrentOption``` is actually used... - added page descendant class ```PageAllPublishers``` - handles pulling the publishers category from database - added page descendant class ```PagePublisherDetail``` - handles pulling the books per publisher data from database - changed class PageQueryResult - added constant and switches for publisher search scope - abstract class Base - added constants for the publisher pages *book.php* - added require statement for publisher.php - added ```SQL_BOOKS_BY_PUBLISHER``` query to retrieve books by publisher. - changed class Book - added query constant - added publisher item - added test in case no known publisher - added publishername and url array elements for the JSON output - added public function ```getPublisher``` - added public static function ```getBooksByPublisher``` to fire the query - changed function getJson - added publisher category to search - added publishername (single) and publishertitle(plural) localization entries to i18n translation array *index.php* - added require statement for publisher.php *lang/Localization_en.json - added new localization entries for publisher labels (see below) ``` "publisher.alphabetical.many":"Alphabetical index of the {0} publishers", "publisher.alphabetical.none":"Alphabetical index of absolutely no publisher", "publisher.alphabetical.one":"Alphabetical index of the single publisher", "publisher.name":"Publisher", "publisher.title":"Publishers", "publisherword.many":"{0} publishers", "publisherword.none":"No publisher", "publisherword.one":"1 publisher", "search.result.publisher":"Search result for *{0}* in publishers", ``` *templates\bookdetail.html* - added publisher label and item to bookdetail popup *test\bookTest.php* - added indices and names of publishers added to testdatabase as comment - added test function ```testGetBooksByPublisher``` - changed test function testGetBookById to add assertion for publisher name - changed test function testTypeaheadSearch to add search on partial publisher name. *test\pageTest.php* - changed test function testPageIndex to insert publisher category and adjust page indices - changed test function testPageIndexWithCustomColum to adjust for the changed page indices - added test function testPageAllPublishers - added test function testPagePublishersDetail - added test function testPageSearchScopePublishers *test\BaseWithSomeBooks\metadata.db* - added 5 publishers spread across all 14 books, replacing the original publisher Feedbooks Files added: *publisher.php*
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  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 Sbastien Lucas <sebastien@slucas.fr>
  7. */
  8. require_once('base.php');
  9. require_once('serie.php');
  10. require_once('author.php');
  11. require_once('rating.php');
  12. require_once('publisher.php');
  13. require_once('tag.php');
  14. require_once('language.php');
  15. require_once("customcolumn.php");
  16. require_once('data.php');
  17. require_once('resources/php-epub-meta/epub.php');
  18. // Silly thing because PHP forbid string concatenation in class const
  19. define ('SQL_BOOKS_LEFT_JOIN', "left outer join comments on comments.book = books.id
  20. left outer join books_ratings_link on books_ratings_link.book = books.id
  21. left outer join ratings on books_ratings_link.rating = ratings.id ");
  22. define ('SQL_BOOKS_ALL', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . " order by books.sort ");
  23. define ('SQL_BOOKS_BY_PUBLISHER', "select {0} from books_publishers_link, books " . SQL_BOOKS_LEFT_JOIN . "
  24. where books_publishers_link.book = books.id and publisher = ? {1} order by publisher");
  25. define ('SQL_BOOKS_BY_FIRST_LETTER', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . "
  26. where upper (books.sort) like ? order by books.sort");
  27. define ('SQL_BOOKS_BY_AUTHOR', "select {0} from books_authors_link, books " . SQL_BOOKS_LEFT_JOIN . "
  28. left outer join books_series_link on books_series_link.book = books.id
  29. where books_authors_link.book = books.id and author = ? {1} order by series desc, series_index asc, pubdate asc");
  30. define ('SQL_BOOKS_BY_SERIE', "select {0} from books_series_link, books " . SQL_BOOKS_LEFT_JOIN . "
  31. where books_series_link.book = books.id and series = ? {1} order by series_index");
  32. define ('SQL_BOOKS_BY_TAG', "select {0} from books_tags_link, books " . SQL_BOOKS_LEFT_JOIN . "
  33. where books_tags_link.book = books.id and tag = ? {1} order by sort");
  34. define ('SQL_BOOKS_BY_LANGUAGE', "select {0} from books_languages_link, books " . SQL_BOOKS_LEFT_JOIN . "
  35. where books_languages_link.book = books.id and lang_code = ? {1} order by sort");
  36. define ('SQL_BOOKS_BY_CUSTOM', "select {0} from {2}, books " . SQL_BOOKS_LEFT_JOIN . "
  37. where {2}.book = books.id and {2}.{3} = ? {1} order by sort");
  38. define ('SQL_BOOKS_QUERY', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . "
  39. where (
  40. exists (select null from authors, books_authors_link where book = books.id and author = authors.id and authors.name like ?) or
  41. exists (select null from tags, books_tags_link where book = books.id and tag = tags.id and tags.name like ?) or
  42. exists (select null from series, books_series_link on book = books.id and books_series_link.series = series.id and series.name like ?) or
  43. exists (select null from publishers, books_publishers_link where book = books.id and books_publishers_link.publisher = publishers.id and publishers.name like ?) or
  44. title like ?) {1} order by books.sort");
  45. define ('SQL_BOOKS_RECENT', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . "
  46. where 1=1 {1} order by timestamp desc limit ");
  47. define ('SQL_BOOKS_BY_RATING', "select {0} from books " . SQL_BOOKS_LEFT_JOIN . "
  48. where books_ratings_link.book = books.id and ratings.id = ? {1} order by sort");
  49. class Book extends Base {
  50. const ALL_BOOKS_UUID = "urn:uuid";
  51. const ALL_BOOKS_ID = "cops:books";
  52. const ALL_RECENT_BOOKS_ID = "cops:recentbooks";
  53. const BOOK_COLUMNS = "books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index, uuid, has_cover, ratings.rating";
  54. const SQL_BOOKS_LEFT_JOIN = SQL_BOOKS_LEFT_JOIN;
  55. const SQL_BOOKS_ALL = SQL_BOOKS_ALL;
  56. const SQL_BOOKS_BY_PUBLISHER = SQL_BOOKS_BY_PUBLISHER;
  57. const SQL_BOOKS_BY_FIRST_LETTER = SQL_BOOKS_BY_FIRST_LETTER;
  58. const SQL_BOOKS_BY_AUTHOR = SQL_BOOKS_BY_AUTHOR;
  59. const SQL_BOOKS_BY_SERIE = SQL_BOOKS_BY_SERIE;
  60. const SQL_BOOKS_BY_TAG = SQL_BOOKS_BY_TAG;
  61. const SQL_BOOKS_BY_LANGUAGE = SQL_BOOKS_BY_LANGUAGE;
  62. const SQL_BOOKS_BY_CUSTOM = SQL_BOOKS_BY_CUSTOM;
  63. const SQL_BOOKS_QUERY = SQL_BOOKS_QUERY;
  64. const SQL_BOOKS_RECENT = SQL_BOOKS_RECENT;
  65. const SQL_BOOKS_BY_RATING = SQL_BOOKS_BY_RATING;
  66. const BAD_SEARCH = "QQQQQ";
  67. public $id;
  68. public $title;
  69. public $timestamp;
  70. public $pubdate;
  71. public $path;
  72. public $uuid;
  73. public $hasCover;
  74. public $relativePath;
  75. public $seriesIndex;
  76. public $comment;
  77. public $rating;
  78. public $datas = NULL;
  79. public $authors = NULL;
  80. public $publisher = NULL;
  81. public $serie = NULL;
  82. public $tags = NULL;
  83. public $languages = NULL;
  84. public $format = array ();
  85. public function __construct($line) {
  86. $this->id = $line->id;
  87. $this->title = $line->title;
  88. $this->timestamp = strtotime ($line->timestamp);
  89. $this->pubdate = $line->pubdate;
  90. $this->path = Base::getDbDirectory () . $line->path;
  91. $this->relativePath = $line->path;
  92. $this->seriesIndex = $line->series_index;
  93. $this->comment = $line->comment;
  94. $this->uuid = $line->uuid;
  95. $this->hasCover = $line->has_cover;
  96. if (!file_exists ($this->getFilePath ("jpg"))) {
  97. // double check
  98. $this->hasCover = 0;
  99. }
  100. $this->rating = $line->rating;
  101. }
  102. public function getEntryId () {
  103. return self::ALL_BOOKS_UUID.":".$this->uuid;
  104. }
  105. public static function getEntryIdByLetter ($startingLetter) {
  106. return self::ALL_BOOKS_ID.":letter:".$startingLetter;
  107. }
  108. public function getUri () {
  109. return "?page=".parent::PAGE_BOOK_DETAIL."&id=$this->id";
  110. }
  111. public function getDetailUrl () {
  112. $urlParam = $this->getUri ();
  113. if (!is_null (GetUrlParam (DB))) $urlParam = addURLParameter ($urlParam, DB, GetUrlParam (DB));
  114. return 'index.php' . $urlParam;
  115. }
  116. public function getTitle () {
  117. return $this->title;
  118. }
  119. /* Other class (author, series, tag, ...) initialization and accessors */
  120. public function getAuthors () {
  121. if (is_null ($this->authors)) {
  122. $this->authors = Author::getAuthorByBookId ($this->id);
  123. }
  124. return $this->authors;
  125. }
  126. public function getAuthorsName () {
  127. return implode (", ", array_map (function ($author) { return $author->name; }, $this->getAuthors ()));
  128. }
  129. public function getAuthorsSort () {
  130. return implode (", ", array_map (function ($author) { return $author->sort; }, $this->getAuthors ()));
  131. }
  132. public function getPublisher () {
  133. if (is_null ($this->publisher)) {
  134. $this->publisher = Publisher::getPublisherByBookId ($this->id);
  135. }
  136. return $this->publisher;
  137. }
  138. public function getSerie () {
  139. if (is_null ($this->serie)) {
  140. $this->serie = Serie::getSerieByBookId ($this->id);
  141. }
  142. return $this->serie;
  143. }
  144. public function getLanguages () {
  145. $lang = array ();
  146. $result = parent::getDb ()->prepare('select languages.lang_code
  147. from books_languages_link, languages
  148. where books_languages_link.lang_code = languages.id
  149. and book = ?
  150. order by item_order');
  151. $result->execute (array ($this->id));
  152. while ($post = $result->fetchObject ())
  153. {
  154. array_push ($lang, Language::getLanguageString($post->lang_code));
  155. }
  156. return implode (", ", $lang);
  157. }
  158. public function getTags () {
  159. if (is_null ($this->tags)) {
  160. $this->tags = array ();
  161. $result = parent::getDb ()->prepare('select tags.id as id, name
  162. from books_tags_link, tags
  163. where tag = tags.id
  164. and book = ?
  165. order by name');
  166. $result->execute (array ($this->id));
  167. while ($post = $result->fetchObject ())
  168. {
  169. array_push ($this->tags, new Tag ($post));
  170. }
  171. }
  172. return $this->tags;
  173. }
  174. public function getTagsName () {
  175. return implode (", ", array_map (function ($tag) { return $tag->name; }, $this->getTags ()));
  176. }
  177. public function getDatas ()
  178. {
  179. if (is_null ($this->datas)) {
  180. $this->datas = Data::getDataByBook ($this);
  181. }
  182. return $this->datas;
  183. }
  184. /* End of other class (author, series, tag, ...) initialization and accessors */
  185. public static function getFilterString () {
  186. $filter = getURLParam ("tag", NULL);
  187. if (empty ($filter)) return "";
  188. $exists = true;
  189. if (preg_match ("/^!(.*)$/", $filter, $matches)) {
  190. $exists = false;
  191. $filter = $matches[1];
  192. }
  193. $result = "exists (select null from books_tags_link, tags where books_tags_link.book = books.id and books_tags_link.tag = tags.id and tags.name = '" . $filter . "')";
  194. if (!$exists) {
  195. $result = "not " . $result;
  196. }
  197. return "and " . $result;
  198. }
  199. public function GetMostInterestingDataToSendToKindle ()
  200. {
  201. $bestFormatForKindle = array ("EPUB", "PDF", "AZW3", "MOBI");
  202. $bestRank = -1;
  203. $bestData = NULL;
  204. foreach ($this->getDatas () as $data) {
  205. $key = array_search ($data->format, $bestFormatForKindle);
  206. if ($key !== false && $key > $bestRank) {
  207. $bestRank = $key;
  208. $bestData = $data;
  209. }
  210. }
  211. return $bestData;
  212. }
  213. public function getDataById ($idData)
  214. {
  215. $reduced = array_filter ($this->getDatas (), function ($data) use ($idData) {
  216. return $data->id == $idData;
  217. });
  218. return reset ($reduced);
  219. }
  220. public function getRating () {
  221. if (is_null ($this->rating) || $this->rating == 0) {
  222. return "";
  223. }
  224. $retour = "";
  225. for ($i = 0; $i < $this->rating / 2; $i++) {
  226. $retour .= "&#9733;";
  227. }
  228. for ($i = 0; $i < 5 - $this->rating / 2; $i++) {
  229. $retour .= "&#9734;";
  230. }
  231. return $retour;
  232. }
  233. public function getPubDate () {
  234. if (empty ($this->pubdate)) {
  235. return "";
  236. }
  237. $dateY = (int) substr($this->pubdate, 0, 4);
  238. if ($dateY > 102) {
  239. return str_pad($dateY, 4, "0", STR_PAD_LEFT);
  240. }
  241. return "";
  242. }
  243. public function getComment ($withSerie = true) {
  244. $addition = "";
  245. $se = $this->getSerie ();
  246. if (!is_null ($se) && $withSerie) {
  247. $addition = $addition . "<strong>" . localize("content.series") . "</strong>" . str_format (localize ("content.series.data"), $this->seriesIndex, htmlspecialchars ($se->name)) . "<br />\n";
  248. }
  249. if (preg_match ("/<\/(div|p|a|span)>/", $this->comment))
  250. {
  251. return $addition . html2xhtml ($this->comment);
  252. }
  253. else
  254. {
  255. return $addition . htmlspecialchars ($this->comment);
  256. }
  257. }
  258. public function getDataFormat ($format) {
  259. $reduced = array_filter ($this->getDatas (), function ($data) use ($format) {
  260. return $data->format == $format;
  261. });
  262. return reset ($reduced);
  263. }
  264. public function getFilePath ($extension, $idData = NULL, $relative = false)
  265. {
  266. if ($extension == "jpg")
  267. {
  268. $file = "cover.jpg";
  269. }
  270. else
  271. {
  272. $data = $this->getDataById ($idData);
  273. if (!$data) return NULL;
  274. $file = $data->name . "." . strtolower ($data->format);
  275. }
  276. if ($relative)
  277. {
  278. return $this->relativePath."/".$file;
  279. }
  280. else
  281. {
  282. return $this->path."/".$file;
  283. }
  284. }
  285. public function getUpdatedEpub ($idData)
  286. {
  287. global $config;
  288. $data = $this->getDataById ($idData);
  289. try
  290. {
  291. $epub = new EPub ($data->getLocalPath ());
  292. $epub->Title ($this->title);
  293. $authorArray = array ();
  294. foreach ($this->getAuthors() as $author) {
  295. $authorArray [$author->sort] = $author->name;
  296. }
  297. $epub->Authors ($authorArray);
  298. $epub->Language ($this->getLanguages ());
  299. $epub->Description ($this->getComment (false));
  300. $epub->Subjects ($this->getTagsName ());
  301. $epub->Cover2 ($this->getFilePath ("jpg"), "image/jpeg");
  302. $epub->Calibre ($this->uuid);
  303. $se = $this->getSerie ();
  304. if (!is_null ($se)) {
  305. $epub->Serie ($se->name);
  306. $epub->SerieIndex ($this->seriesIndex);
  307. }
  308. if ($config['cops_provide_kepub'] == "1" && preg_match("/Kobo/", $_SERVER['HTTP_USER_AGENT'])) {
  309. $epub->updateForKepub ();
  310. }
  311. $epub->download ($data->getUpdatedFilenameEpub ());
  312. }
  313. catch (Exception $e)
  314. {
  315. echo "Exception : " . $e->getMessage();
  316. }
  317. }
  318. public function getThumbnail ($width, $height, $outputfile = NULL) {
  319. if (is_null ($width) && is_null ($height)) {
  320. return false;
  321. }
  322. $file = $this->getFilePath ("jpg");
  323. // get image size
  324. if ($size = GetImageSize($file)) {
  325. $w = $size[0];
  326. $h = $size[1];
  327. //set new size
  328. if (!is_null ($width)) {
  329. $nw = $width;
  330. if ($nw >= $w) { return false; }
  331. $nh = ($nw*$h)/$w;
  332. } else {
  333. $nh = $height;
  334. if ($nh >= $h) { return false; }
  335. $nw = ($nh*$w)/$h;
  336. }
  337. } else {
  338. return false;
  339. }
  340. //draw the image
  341. $src_img = imagecreatefromjpeg($file);
  342. $dst_img = imagecreatetruecolor($nw,$nh);
  343. imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $nw, $nh, $w, $h);//resizing the image
  344. imagejpeg($dst_img,$outputfile,80);
  345. imagedestroy($src_img);
  346. imagedestroy($dst_img);
  347. return true;
  348. }
  349. public function getLinkArray ()
  350. {
  351. $linkArray = array();
  352. if ($this->hasCover)
  353. {
  354. array_push ($linkArray, Data::getLink ($this, "jpg", "image/jpeg", Link::OPDS_IMAGE_TYPE, "cover.jpg", NULL));
  355. array_push ($linkArray, Data::getLink ($this, "jpg", "image/jpeg", Link::OPDS_THUMBNAIL_TYPE, "cover.jpg", NULL));
  356. }
  357. foreach ($this->getDatas () as $data)
  358. {
  359. if ($data->isKnownType ())
  360. {
  361. array_push ($linkArray, $data->getDataLink (Link::OPDS_ACQUISITION_TYPE, $data->format));
  362. }
  363. }
  364. foreach ($this->getAuthors () as $author) {
  365. array_push ($linkArray, new LinkNavigation ($author->getUri (), "related", str_format (localize ("bookentry.author"), localize ("splitByLetter.book.other"), $author->name)));
  366. }
  367. $serie = $this->getSerie ();
  368. if (!is_null ($serie)) {
  369. array_push ($linkArray, new LinkNavigation ($serie->getUri (), "related", str_format (localize ("content.series.data"), $this->seriesIndex, $serie->name)));
  370. }
  371. return $linkArray;
  372. }
  373. public function getEntry () {
  374. return new EntryBook ($this->getTitle (), $this->getEntryId (),
  375. $this->getComment (), "text/html",
  376. $this->getLinkArray (), $this);
  377. }
  378. public static function getBookCount($database = NULL) {
  379. return parent::executeQuerySingle ('select count(*) from books', $database);
  380. }
  381. public static function getCount() {
  382. global $config;
  383. $nBooks = parent::executeQuerySingle ('select count(*) from books');
  384. $result = array();
  385. $entry = new Entry (localize ("allbooks.title"),
  386. self::ALL_BOOKS_ID,
  387. str_format (localize ("allbooks.alphabetical", $nBooks), $nBooks), "text",
  388. array ( new LinkNavigation ("?page=".parent::PAGE_ALL_BOOKS)), "", $nBooks);
  389. array_push ($result, $entry);
  390. if ($config['cops_recentbooks_limit'] > 0) {
  391. $entry = new Entry (localize ("recent.title"),
  392. self::ALL_RECENT_BOOKS_ID,
  393. str_format (localize ("recent.list"), $config['cops_recentbooks_limit']), "text",
  394. array ( new LinkNavigation ("?page=".parent::PAGE_ALL_RECENT_BOOKS)), "", $config['cops_recentbooks_limit']);
  395. array_push ($result, $entry);
  396. }
  397. return $result;
  398. }
  399. public static function getBooksByAuthor($authorId, $n) {
  400. return self::getEntryArray (self::SQL_BOOKS_BY_AUTHOR, array ($authorId), $n);
  401. }
  402. public static function getBooksByRating($ratingId, $n) {
  403. return self::getEntryArray (self::SQL_BOOKS_BY_RATING, array ($ratingId), $n);
  404. }
  405. public static function getBooksByPublisher($publisherId, $n) {
  406. return self::getEntryArray (self::SQL_BOOKS_BY_PUBLISHER, array ($publisherId), $n);
  407. }
  408. public static function getBooksBySeries($serieId, $n) {
  409. return self::getEntryArray (self::SQL_BOOKS_BY_SERIE, array ($serieId), $n);
  410. }
  411. public static function getBooksByTag($tagId, $n) {
  412. return self::getEntryArray (self::SQL_BOOKS_BY_TAG, array ($tagId), $n);
  413. }
  414. public static function getBooksByLanguage($languageId, $n) {
  415. return self::getEntryArray (self::SQL_BOOKS_BY_LANGUAGE, array ($languageId), $n);
  416. }
  417. public static function getBooksByCustom($customId, $id, $n) {
  418. $query = str_format (self::SQL_BOOKS_BY_CUSTOM, "{0}", "{1}", CustomColumn::getTableLinkName ($customId), CustomColumn::getTableLinkColumn ($customId));
  419. return self::getEntryArray ($query, array ($id), $n);
  420. }
  421. public static function getBookById($bookId) {
  422. $result = parent::getDb ()->prepare('select ' . self::BOOK_COLUMNS . '
  423. from books ' . self::SQL_BOOKS_LEFT_JOIN . '
  424. where books.id = ?');
  425. $result->execute (array ($bookId));
  426. while ($post = $result->fetchObject ())
  427. {
  428. $book = new Book ($post);
  429. return $book;
  430. }
  431. return NULL;
  432. }
  433. public static function getBookByDataId($dataId) {
  434. $result = parent::getDb ()->prepare('select ' . self::BOOK_COLUMNS . ', data.name, data.format
  435. from data, books ' . self::SQL_BOOKS_LEFT_JOIN . '
  436. where data.book = books.id and data.id = ?');
  437. $result->execute (array ($dataId));
  438. while ($post = $result->fetchObject ())
  439. {
  440. $book = new Book ($post);
  441. $data = new Data ($post, $book);
  442. $data->id = $dataId;
  443. $book->datas = array ($data);
  444. return $book;
  445. }
  446. return NULL;
  447. }
  448. public static function getBooksByQuery($query, $n, $database = NULL, $numberPerPage = NULL) {
  449. $i = 0;
  450. $critArray = array ();
  451. foreach (array (PageQueryResult::SCOPE_AUTHOR,
  452. PageQueryResult::SCOPE_TAG,
  453. PageQueryResult::SCOPE_SERIES,
  454. PageQueryResult::SCOPE_PUBLISHER,
  455. PageQueryResult::SCOPE_BOOK) as $key) {
  456. if (in_array($key, getCurrentOption ('ignored_categories')) ||
  457. (!array_key_exists ($key, $query) && !array_key_exists ("all", $query))) {
  458. $critArray [$i] = self::BAD_SEARCH;
  459. }
  460. else {
  461. if (array_key_exists ($key, $query)) {
  462. $critArray [$i] = $query [$key];
  463. } else {
  464. $critArray [$i] = $query ["all"];
  465. }
  466. }
  467. $i++;
  468. }
  469. return self::getEntryArray (self::SQL_BOOKS_QUERY, $critArray, $n, $database, $numberPerPage);
  470. }
  471. public static function getBooks($n) {
  472. list ($entryArray, $totalNumber) = self::getEntryArray (self::SQL_BOOKS_ALL , array (), $n);
  473. return array ($entryArray, $totalNumber);
  474. }
  475. public static function getAllBooks() {
  476. list (, $result) = parent::executeQuery ("select {0}
  477. from books
  478. group by substr (upper (sort), 1, 1)
  479. order by substr (upper (sort), 1, 1)", "substr (upper (sort), 1, 1) as title, count(*) as count", self::getFilterString (), array (), -1);
  480. $entryArray = array();
  481. while ($post = $result->fetchObject ())
  482. {
  483. array_push ($entryArray, new Entry ($post->title, Book::getEntryIdByLetter ($post->title),
  484. str_format (localize("bookword", $post->count), $post->count), "text",
  485. array ( new LinkNavigation ("?page=".parent::PAGE_ALL_BOOKS_LETTER."&id=". rawurlencode ($post->title))), "", $post->count));
  486. }
  487. return $entryArray;
  488. }
  489. public static function getBooksByStartingLetter($letter, $n, $database = NULL, $numberPerPage = NULL) {
  490. return self::getEntryArray (self::SQL_BOOKS_BY_FIRST_LETTER, array ($letter . "%"), $n, $database, $numberPerPage);
  491. }
  492. public static function getEntryArray ($query, $params, $n, $database = NULL, $numberPerPage = NULL) {
  493. list ($totalNumber, $result) = parent::executeQuery ($query, self::BOOK_COLUMNS, self::getFilterString (), $params, $n, $database, $numberPerPage);
  494. $entryArray = array();
  495. while ($post = $result->fetchObject ())
  496. {
  497. $book = new Book ($post);
  498. array_push ($entryArray, $book->getEntry ());
  499. }
  500. return array ($entryArray, $totalNumber);
  501. }
  502. public static function getAllRecentBooks() {
  503. global $config;
  504. list ($entryArray, ) = self::getEntryArray (self::SQL_BOOKS_RECENT . $config['cops_recentbooks_limit'], array (), -1);
  505. return $entryArray;
  506. }
  507. }