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.

263 lines
10KB

  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 <sebastien@slucas.fr>
  7. */
  8. require_once('base.php');
  9. class Book extends Base {
  10. const ALL_BOOKS_ID = "calibre:books";
  11. const ALL_RECENT_BOOKS_ID = "calibre:recentbooks";
  12. public $id;
  13. public $title;
  14. public $timestamp;
  15. public $pubdate;
  16. public $path;
  17. public $relativePath;
  18. public $seriesIndex;
  19. public $comment;
  20. public $authors = NULL;
  21. public $serie = NULL;
  22. public $tags = NULL;
  23. public function __construct($pid, $ptitle, $ptimestamp, $ppubdate, $ppath, $pseriesIndex, $pcomment) {
  24. global $config;
  25. $this->id = $pid;
  26. $this->title = $ptitle;
  27. $this->timestamp = strtotime ($ptimestamp);
  28. $this->pubdate = strtotime ($ppubdate);
  29. $this->path = $config['calibre_directory'] . $ppath;
  30. $this->relativePath = $ppath;
  31. $this->seriesIndex = $pseriesIndex;
  32. $this->comment = $pcomment;
  33. }
  34. public function getEntryId () {
  35. return self::ALL_BOOKS_ID.":".$this->id;
  36. }
  37. public function getTitle () {
  38. return $this->title;
  39. }
  40. public function getAuthors () {
  41. if (is_null ($this->authors)) {
  42. $this->authors = Author::getAuthorByBookId ($this->id);
  43. }
  44. return $this->authors;
  45. }
  46. public function getSerie () {
  47. if (is_null ($this->serie)) {
  48. $this->serie = Serie::getSerieByBookId ($this->id);
  49. }
  50. return $this->serie;
  51. }
  52. public function getTags () {
  53. if (is_null ($this->tags)) {
  54. $this->tags = array ();
  55. $result = parent::getDb ()->prepare('select name
  56. from books_tags_link, tags
  57. where tag = tags.id
  58. and book = ?
  59. order by name');
  60. $result->execute (array ($this->id));
  61. while ($post = $result->fetchObject ())
  62. {
  63. array_push ($this->tags, $post->name);
  64. }
  65. }
  66. return $this->tags;
  67. }
  68. public function getComment () {
  69. $addition = "";
  70. $se = $this->getSerie ();
  71. if (!is_null ($se)) {
  72. $addition = $addition . "<strong>Series : </strong>Book $this->seriesIndex in $se->name<br />\n";
  73. }
  74. return $addition . strip_tags ($this->comment, '<div>');
  75. }
  76. public function getFilePath ($extension, $relative = false)
  77. {
  78. if ($handle = opendir($this->path)) {
  79. while (false !== ($file = readdir($handle))) {
  80. if (preg_match ('/' . $extension . '$/', $file)) {
  81. if ($relative)
  82. {
  83. return $this->relativePath."/".$file;
  84. }
  85. else
  86. {
  87. return $this->path."/".$file;
  88. }
  89. }
  90. }
  91. }
  92. return NULL;
  93. }
  94. public function getLinkArray ()
  95. {
  96. global $config;
  97. $linkArray = array();
  98. if ($handle = opendir($this->path)) {
  99. while (false !== ($file = readdir($handle))) {
  100. if (preg_match ('/jpg$/', $file)) {
  101. if (preg_match ('/^\//', $config['calibre_directory']))
  102. {
  103. array_push ($linkArray, new Link ("fetch.php?id=$this->id", "image/jpeg", "http://opds-spec.org/image"));
  104. }
  105. else
  106. {
  107. array_push ($linkArray, new Link (rawurlencode ($this->path."/".$file), "image/jpeg", "http://opds-spec.org/image"));
  108. }
  109. array_push ($linkArray, new Link ("fetch.php?id=$this->id&width=50", "image/jpeg", "http://opds-spec.org/image/thumbnail"));
  110. }
  111. if (preg_match ('/epub$/', $file)) {
  112. if (preg_match ('/^\//', $config['calibre_directory']))
  113. {
  114. array_push ($linkArray, new Link ("fetch.php?id=$this->id&type=epub", "application/epub+zip", "http://opds-spec.org/acquisition", "Download"));
  115. }
  116. else
  117. {
  118. array_push ($linkArray, new Link (rawurlencode ($this->path."/".$file), "application/epub+zip", "http://opds-spec.org/acquisition", "Download"));
  119. }
  120. }
  121. }
  122. }
  123. foreach ($this->getAuthors () as $author) {
  124. array_push ($linkArray, new LinkNavigation ($author->getUri (), "related", "Other books by $author->name"));
  125. }
  126. $serie = $this->getSerie ();
  127. if (!is_null ($serie)) {
  128. array_push ($linkArray, new LinkNavigation ($serie->getUri (), "related", "Other books by the serie $serie->name"));
  129. }
  130. return $linkArray;
  131. }
  132. public function getEntry () {
  133. parent::addEntryClass (new EntryBook ($this->getTitle (), $this->getEntryId (),
  134. $this->getComment (), "text/html",
  135. $this->getLinkArray (), $this));
  136. }
  137. public static function getCount() {
  138. $nBooks = parent::getDb ()->query('select count(*) from books')->fetchColumn();
  139. parent::addEntryClass (new Entry ("Books",
  140. self::ALL_BOOKS_ID,
  141. "Alphabetical index of the $nBooks books", "text",
  142. array ( new LinkNavigation ("feed.php?page=".parent::PAGE_ALL_BOOKS))));
  143. parent::addEntryClass (new Entry ("Recents books",
  144. self::ALL_RECENT_BOOKS_ID,
  145. "Alphabetical index of the 50 most recent books", "text",
  146. array ( new LinkNavigation ("feed.php?page=".parent::PAGE_ALL_RECENT_BOOKS))));
  147. }
  148. public static function getBooksByAuthor($authorId) {
  149. $result = parent::getDb ()->prepare('select books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index
  150. from books_authors_link, books left outer join comments on comments.book = books.id
  151. where books_authors_link.book = books.id
  152. and author = ?
  153. order by pubdate');
  154. $result->execute (array ($authorId));
  155. while ($post = $result->fetchObject ())
  156. {
  157. $book = new Book ($post->id, $post->title, $post->timestamp, $post->pubdate, $post->path, $post->series_index, $post->comment);
  158. $book->getEntry ();
  159. }
  160. }
  161. public static function getBooksBySeries($serieId) {
  162. $result = parent::getDb ()->prepare('select books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index
  163. from books_series_link, books left outer join comments on comments.book = books.id
  164. where books_series_link.book = books.id and series = ?
  165. order by series_index');
  166. $result->execute (array ($serieId));
  167. while ($post = $result->fetchObject ())
  168. {
  169. $book = new Book ($post->id, $post->title, $post->timestamp, $post->pubdate, $post->path, $post->series_index, $post->comment);
  170. $book->getEntry ();
  171. }
  172. }
  173. public static function getBookById($bookId) {
  174. $result = parent::getDb ()->prepare('select books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index
  175. from books left outer join comments on book = books.id
  176. where books.id = ?');
  177. $result->execute (array ($bookId));
  178. while ($post = $result->fetchObject ())
  179. {
  180. $book = new Book ($post->id, $post->title, $post->timestamp, $post->pubdate, $post->path, $post->series_index, $post->comment);
  181. return $book;
  182. }
  183. return NULL;
  184. }
  185. public static function getBooksByQuery($query) {
  186. $result = parent::getDb ()->prepare("select books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index
  187. from books left outer join comments on book = books.id
  188. where exists (select null from authors, books_authors_link where book = books.id and author = authors.id and authors.name like ?)
  189. or title like ?");
  190. $queryLike = "%" . $query . "%";
  191. $result->execute (array ($queryLike, $queryLike));
  192. while ($post = $result->fetchObject ())
  193. {
  194. $book = new Book ($post->id, $post->title, $post->timestamp, $post->pubdate, $post->path, $post->series_index, $post->comment);
  195. $book->getEntry ();
  196. }
  197. }
  198. public static function getAllBooks() {
  199. $result = parent::getDb ()->query("select substr (upper (sort), 1, 1) as title, count(*) as count
  200. from books
  201. group by substr (upper (sort), 1, 1)
  202. order by substr (upper (sort), 1, 1)");
  203. while ($post = $result->fetchObject ())
  204. {
  205. parent::addEntryClass (new Entry ($post->title, "allbooks_" . $post->title,
  206. "$post->count books", "text",
  207. array ( new LinkNavigation ("feed.php?page=".parent::PAGE_ALL_BOOKS_LETTER."&id=".$post->title))));
  208. }
  209. }
  210. public static function getBooksByStartingLetter($letter) {
  211. $result = parent::getDb ()->prepare('select books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index
  212. from books left outer join comments on book = books.id
  213. where upper (books.sort) like ?');
  214. $queryLike = $letter . "%";
  215. $result->execute (array ($queryLike));
  216. while ($post = $result->fetchObject ())
  217. {
  218. $book = new Book ($post->id, $post->title, $post->timestamp, $post->pubdate, $post->path, $post->series_index, $post->comment);
  219. $book->getEntry ();
  220. }
  221. }
  222. public static function getAllRecentBooks() {
  223. global $config;
  224. $result = parent::getDb ()->query("select books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index
  225. from books left outer join comments on book = books.id
  226. order by timestamp desc limit " . $config['cops_recentbooks_limit']);
  227. while ($post = $result->fetchObject ())
  228. {
  229. $book = new Book ($post->id, $post->title, $post->timestamp, $post->pubdate, $post->path, $post->series_index, $post->comment);
  230. $book->getEntry ();
  231. }
  232. }
  233. }
  234. ?>