2012-05-28 08:01:33 +03:00
< ? php
/**
* COPS ( Calibre OPDS PHP Server ) class file
*
* @ license GPL 2 ( http :// www . gnu . org / licenses / gpl . html )
* @ author S<EFBFBD> bastien Lucas < sebastien @ slucas . fr >
*/
require_once ( 'base.php' );
2012-05-28 08:05:05 +03:00
require_once ( 'serie.php' );
require_once ( 'author.php' );
2012-06-11 22:30:25 +03:00
require_once ( 'tag.php' );
2012-06-26 15:27:06 +03:00
require_once ( 'data.php' );
2013-01-02 22:50:44 +02:00
require_once ( 'php-epub-meta/epub.php' );
2012-05-28 08:01:33 +03:00
2012-12-04 16:36:10 +02:00
// Silly thing because PHP forbid string concatenation in class const
define ( 'SQL_BOOKS_LEFT_JOIN' , " left outer join comments on comments.book = books.id
left outer join books_ratings_link on books_ratings_link . book = books . id
left outer join ratings on books_ratings_link . rating = ratings . id " );
define ( 'SQL_BOOKS_BY_FIRST_LETTER' , " select { 0} from books " . SQL_BOOKS_LEFT_JOIN . "
where upper ( books . sort ) like ? " );
define ( 'SQL_BOOKS_BY_AUTHOR' , " select { 0} from books_authors_link, books " . SQL_BOOKS_LEFT_JOIN . "
2013-01-11 16:16:15 +02:00
where books_authors_link . book = books . id and author = ? { 1 } order by pubdate " );
2012-12-04 16:36:10 +02:00
define ( 'SQL_BOOKS_BY_SERIE' , " select { 0} from books_series_link, books " . SQL_BOOKS_LEFT_JOIN . "
2013-01-11 16:16:15 +02:00
where books_series_link . book = books . id and series = ? { 1 } order by series_index " );
2012-12-04 16:36:10 +02:00
define ( 'SQL_BOOKS_BY_TAG' , " select { 0} from books_tags_link, books " . SQL_BOOKS_LEFT_JOIN . "
2013-01-11 16:16:15 +02:00
where books_tags_link . book = books . id and tag = ? { 1 } order by sort " );
2012-12-04 16:36:10 +02:00
define ( 'SQL_BOOKS_QUERY' , " select { 0} from books " . SQL_BOOKS_LEFT_JOIN . "
2013-01-11 16:16:15 +02:00
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 } " );
2012-12-04 16:36:10 +02:00
define ( 'SQL_BOOKS_RECENT' , " select { 0} from books " . SQL_BOOKS_LEFT_JOIN . "
2013-01-11 16:16:15 +02:00
where 1 = 1 { 1 } order by timestamp desc limit " );
2012-12-04 16:36:10 +02:00
2012-05-28 08:01:33 +03:00
class Book extends Base {
2012-06-20 18:51:53 +03:00
const ALL_BOOKS_UUID = " urn:uuid " ;
2012-05-28 08:01:33 +03:00
const ALL_BOOKS_ID = " calibre:books " ;
const ALL_RECENT_BOOKS_ID = " calibre:recentbooks " ;
2012-12-04 14:13:58 +02:00
const BOOK_COLUMNS = " books.id as id, books.title as title, text as comment, path, timestamp, pubdate, series_index, uuid, has_cover, ratings.rating " ;
2012-05-28 08:01:33 +03:00
2012-12-04 16:36:10 +02:00
const SQL_BOOKS_LEFT_JOIN = SQL_BOOKS_LEFT_JOIN ;
const SQL_BOOKS_BY_FIRST_LETTER = SQL_BOOKS_BY_FIRST_LETTER ;
const SQL_BOOKS_BY_AUTHOR = SQL_BOOKS_BY_AUTHOR ;
const SQL_BOOKS_BY_SERIE = SQL_BOOKS_BY_SERIE ;
const SQL_BOOKS_BY_TAG = SQL_BOOKS_BY_TAG ;
const SQL_BOOKS_QUERY = SQL_BOOKS_QUERY ;
const SQL_BOOKS_RECENT = SQL_BOOKS_RECENT ;
2012-09-19 19:19:41 +03:00
2012-05-28 08:01:33 +03:00
public $id ;
public $title ;
public $timestamp ;
public $pubdate ;
public $path ;
2012-06-20 18:51:53 +03:00
public $uuid ;
2012-06-23 22:14:54 +03:00
public $hasCover ;
2012-05-28 08:01:33 +03:00
public $relativePath ;
public $seriesIndex ;
public $comment ;
2012-12-04 11:58:39 +02:00
public $rating ;
2012-06-26 15:27:06 +03:00
public $datas = NULL ;
2012-05-28 08:01:33 +03:00
public $authors = NULL ;
public $serie = NULL ;
public $tags = NULL ;
2012-05-28 08:06:12 +03:00
public $format = array ();
2012-06-26 15:27:06 +03:00
2012-05-28 08:07:49 +03:00
public function __construct ( $line ) {
2012-05-28 08:01:33 +03:00
global $config ;
2012-05-28 08:07:49 +03:00
$this -> id = $line -> id ;
$this -> title = $line -> title ;
$this -> timestamp = strtotime ( $line -> timestamp );
$this -> pubdate = strtotime ( $line -> pubdate );
$this -> path = $config [ 'calibre_directory' ] . $line -> path ;
$this -> relativePath = $line -> path ;
$this -> seriesIndex = $line -> series_index ;
$this -> comment = $line -> comment ;
2012-06-20 18:51:53 +03:00
$this -> uuid = $line -> uuid ;
2012-06-23 22:14:54 +03:00
$this -> hasCover = $line -> has_cover ;
2012-12-23 14:56:01 +02:00
if ( ! file_exists ( $this -> getFilePath ( " jpg " ))) {
// double check
$this -> hasCover = 0 ;
}
2012-12-04 14:13:58 +02:00
$this -> rating = $line -> rating ;
2012-05-28 08:01:33 +03:00
}
public function getEntryId () {
2012-06-20 18:51:53 +03:00
return self :: ALL_BOOKS_UUID . " : " . $this -> uuid ;
2012-05-28 08:01:33 +03:00
}
2012-05-28 08:07:49 +03:00
public static function getEntryIdByLetter ( $startingLetter ) {
return self :: ALL_BOOKS_ID . " :letter: " . $startingLetter ;
}
2013-01-03 22:40:43 +02:00
public function getUri () {
return " ?page= " . parent :: PAGE_BOOK_DETAIL . " &id= $this->id " ;
}
public function getDetailUrl () {
global $config ;
if ( $config [ 'cops_use_fancyapps' ] == 0 ) {
return 'index.php' . $this -> getUri ();
} else {
return 'bookdetail.php?id=' . $this -> id ;
}
}
2012-05-28 08:01:33 +03:00
public function getTitle () {
return $this -> title ;
}
public function getAuthors () {
if ( is_null ( $this -> authors )) {
$this -> authors = Author :: getAuthorByBookId ( $this -> id );
}
return $this -> authors ;
}
2013-01-11 16:16:15 +02:00
public function getFilterString () {
$filter = getURLParam ( " tag " , NULL );
if ( is_null ( $filter )) return " " ;
$exists = true ;
if ( preg_match ( " /^!(.*) $ / " , $filter , $matches )) {
$exists = false ;
$filter = $matches [ 1 ];
}
$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 . " ') " ;
if ( ! $exists ) {
$result = " not " . $result ;
}
return " and " . $result ;
}
2012-05-28 08:06:12 +03:00
public function getAuthorsName () {
$authorList = null ;
foreach ( $this -> getAuthors () as $author ) {
if ( $authorList ) {
$authorList = $authorList . " , " . $author -> name ;
}
else
{
$authorList = $author -> name ;
}
}
return $authorList ;
}
2012-05-28 08:01:33 +03:00
public function getSerie () {
if ( is_null ( $this -> serie )) {
$this -> serie = Serie :: getSerieByBookId ( $this -> id );
}
return $this -> serie ;
}
2012-12-03 17:05:13 +02:00
public function getLanguages () {
$lang = array ();
$result = parent :: getDb () -> prepare ( ' select languages . lang_code
from books_languages_link , languages
where books_languages_link . lang_code = languages . id
and book = ?
order by item_order ' );
$result -> execute ( array ( $this -> id ));
while ( $post = $result -> fetchObject ())
{
array_push ( $lang , $post -> lang_code );
}
return implode ( " , " , $lang );
}
2012-05-28 08:01:33 +03:00
public function getTags () {
if ( is_null ( $this -> tags )) {
$this -> tags = array ();
2012-06-11 22:30:25 +03:00
$result = parent :: getDb () -> prepare ( ' select tags . id as id , name
2012-05-28 08:01:33 +03:00
from books_tags_link , tags
where tag = tags . id
and book = ?
order by name ' );
$result -> execute ( array ( $this -> id ));
while ( $post = $result -> fetchObject ())
{
2012-06-11 22:30:25 +03:00
array_push ( $this -> tags , new Tag ( $post -> id , $post -> name ));
2012-05-28 08:01:33 +03:00
}
}
return $this -> tags ;
}
2012-06-26 15:27:06 +03:00
public function getDatas ()
{
if ( is_null ( $this -> datas )) {
$this -> datas = array ();
$result = parent :: getDb () -> prepare ( ' select id , format , name
from data where book = ? ' );
$result -> execute ( array ( $this -> id ));
while ( $post = $result -> fetchObject ())
{
array_push ( $this -> datas , new Data ( $post , $this ));
}
}
return $this -> datas ;
}
2012-12-23 14:42:53 +02:00
public function getDataById ( $idData )
{
foreach ( $this -> getDatas () as $data ) {
if ( $data -> id == $idData ) {
return $data ;
}
}
return NULL ;
}
2012-05-28 08:06:12 +03:00
public function getTagsName () {
$tagList = null ;
foreach ( $this -> getTags () as $tag ) {
if ( $tagList ) {
2012-06-11 22:30:25 +03:00
$tagList = $tagList . " , " . $tag -> name ;
2012-05-28 08:06:12 +03:00
}
else
{
2012-06-11 22:30:25 +03:00
$tagList = $tag -> name ;
2012-05-28 08:06:12 +03:00
}
}
return $tagList ;
}
2012-12-04 11:58:39 +02:00
public function getRating () {
if ( is_null ( $this -> rating ) || $this -> rating == 0 ) {
return " " ;
}
$retour = " " ;
for ( $i = 0 ; $i < $this -> rating / 2 ; $i ++ ) {
$retour .= " ★ " ;
}
for ( $i = 0 ; $i < 5 - $this -> rating / 2 ; $i ++ ) {
$retour .= " ☆ " ;
}
return $retour ;
}
2012-06-12 23:52:39 +03:00
public function getComment ( $withSerie = true ) {
2012-05-28 08:01:33 +03:00
$addition = " " ;
$se = $this -> getSerie ();
2012-06-12 23:52:39 +03:00
if ( ! is_null ( $se ) && $withSerie ) {
2012-06-18 18:02:05 +03:00
$addition = $addition . " <strong> " . localize ( " content.series " ) . " </strong> " . str_format ( localize ( " content.series.data " ), $this -> seriesIndex , htmlspecialchars ( $se -> name )) . " <br /> \n " ;
2012-05-28 08:01:33 +03:00
}
2012-05-30 16:04:23 +03:00
if ( preg_match ( " /< \ /(div|p|a)>/ " , $this -> comment ))
2012-05-30 15:41:06 +03:00
{
2012-07-21 15:31:35 +03:00
return $addition . preg_replace ( " /<(br|hr)>/ " , " < $ 1 /> " , $this -> comment );
2012-05-30 15:41:06 +03:00
}
else
{
return $addition . htmlspecialchars ( $this -> comment );
}
2012-05-28 08:01:33 +03:00
}
2012-06-26 15:45:09 +03:00
public function getDataFormat ( $format ) {
foreach ( $this -> getDatas () as $data )
{
if ( $data -> format == $format )
{
return $data ;
}
}
return NULL ;
}
2012-06-23 23:11:13 +03:00
public function getFilePath ( $extension , $idData = NULL , $relative = false )
2012-05-28 08:01:33 +03:00
{
2012-06-23 23:11:13 +03:00
$file = NULL ;
if ( $extension == " jpg " )
{
$file = " cover.jpg " ;
}
else
{
2012-12-23 14:42:53 +02:00
$data = $this -> getDataById ( $idData );
$file = $data -> name . " . " . strtolower ( $data -> format );
2012-05-28 08:01:33 +03:00
}
2012-06-23 23:11:13 +03:00
if ( $relative )
{
return $this -> relativePath . " / " . $file ;
}
else
{
return $this -> path . " / " . $file ;
}
2012-05-28 08:01:33 +03:00
}
2013-01-02 22:50:44 +02:00
public function getUpdatedEpub ( $idData )
{
$data = $this -> getDataById ( $idData );
try
{
$epub = new EPub ( $data -> getLocalPath ());
$epub -> Title ( $this -> title );
$authorArray = array ();
foreach ( $this -> getAuthors () as $author ) {
$authorArray [ $author -> sort ] = $author -> name ;
}
$epub -> Authors ( $authorArray );
$epub -> Language ( $this -> getLanguages ());
$epub -> Description ( $this -> getComment ( false ));
$epub -> Subjects ( $this -> getTagsName ());
$se = $this -> getSerie ();
if ( ! is_null ( $se )) {
$epub -> Serie ( $se -> name );
$epub -> SerieIndex ( $this -> seriesIndex );
}
$epub -> download ( $data -> getFilename ());
}
catch ( Exception $e )
{
echo " Exception : " . $e -> getMessage ();
}
}
2012-05-28 08:01:33 +03:00
public function getLinkArray ()
{
global $config ;
$linkArray = array ();
2012-06-23 22:14:54 +03:00
if ( $this -> hasCover )
{
2012-06-26 15:27:06 +03:00
array_push ( $linkArray , Data :: getLink ( $this , " jpg " , " image/jpeg " , Link :: OPDS_IMAGE_TYPE , " cover.jpg " , NULL ));
2012-06-23 22:14:54 +03:00
$height = " 50 " ;
if ( preg_match ( '/feed.php/' , $_SERVER [ " SCRIPT_NAME " ])) {
$height = $config [ 'cops_opds_thumbnail_height' ];
}
else
{
$height = $config [ 'cops_html_thumbnail_height' ];
}
array_push ( $linkArray , new Link ( " fetch.php?id= $this->id &height= " . $height , " image/jpeg " , Link :: OPDS_THUMBNAIL_TYPE ));
}
2012-06-26 15:27:06 +03:00
foreach ( $this -> getDatas () as $data )
2012-06-23 22:36:55 +03:00
{
2012-06-26 15:27:06 +03:00
if ( $data -> isKnownType ())
2012-06-23 22:36:55 +03:00
{
2012-06-26 15:27:06 +03:00
array_push ( $linkArray , $data -> getDataLink ( Link :: OPDS_ACQUISITION_TYPE , " Download " ));
2012-05-28 08:01:33 +03:00
}
}
2012-06-23 22:36:55 +03:00
2012-05-28 08:01:33 +03:00
foreach ( $this -> getAuthors () as $author ) {
2012-05-29 21:10:41 +03:00
array_push ( $linkArray , new LinkNavigation ( $author -> getUri (), " related " , str_format ( localize ( " bookentry.author " ), localize ( " splitByLetter.book.other " ), $author -> name )));
2012-05-28 08:01:33 +03:00
}
$serie = $this -> getSerie ();
if ( ! is_null ( $serie )) {
2012-05-29 21:10:41 +03:00
array_push ( $linkArray , new LinkNavigation ( $serie -> getUri (), " related " , str_format ( localize ( " content.series.data " ), $this -> seriesIndex , $serie -> name )));
2012-05-28 08:01:33 +03:00
}
return $linkArray ;
}
public function getEntry () {
2012-05-28 08:05:05 +03:00
return new EntryBook ( $this -> getTitle (), $this -> getEntryId (),
2012-05-28 08:01:33 +03:00
$this -> getComment (), " text/html " ,
2012-05-28 08:05:05 +03:00
$this -> getLinkArray (), $this );
2012-05-28 08:01:33 +03:00
}
public static function getCount () {
2012-05-28 08:05:05 +03:00
global $config ;
2012-05-28 08:01:33 +03:00
$nBooks = parent :: getDb () -> query ( 'select count(*) from books' ) -> fetchColumn ();
2012-05-28 08:05:05 +03:00
$result = array ();
2012-05-29 21:10:41 +03:00
$entry = new Entry ( localize ( " allbooks.title " ),
2012-05-28 08:01:33 +03:00
self :: ALL_BOOKS_ID ,
2012-05-29 21:10:41 +03:00
str_format ( localize ( " allbooks.alphabetical " ), $nBooks ), " text " ,
2012-05-28 08:06:12 +03:00
array ( new LinkNavigation ( " ?page= " . parent :: PAGE_ALL_BOOKS )));
2012-05-28 08:05:05 +03:00
array_push ( $result , $entry );
2012-05-29 21:10:41 +03:00
$entry = new Entry ( localize ( " recent.title " ),
2012-05-28 08:01:33 +03:00
self :: ALL_RECENT_BOOKS_ID ,
2012-05-29 21:10:41 +03:00
str_format ( localize ( " recent.list " ), $config [ 'cops_recentbooks_limit' ]), " text " ,
2012-05-28 08:06:12 +03:00
array ( new LinkNavigation ( " ?page= " . parent :: PAGE_ALL_RECENT_BOOKS )));
2012-05-28 08:05:05 +03:00
array_push ( $result , $entry );
return $result ;
2012-05-28 08:01:33 +03:00
}
2012-09-20 22:15:03 +03:00
public static function getBooksByAuthor ( $authorId , $n ) {
return self :: getEntryArray ( self :: SQL_BOOKS_BY_AUTHOR , array ( $authorId ), $n );
2012-05-28 08:01:33 +03:00
}
2012-09-20 22:15:03 +03:00
public static function getBooksBySeries ( $serieId , $n ) {
return self :: getEntryArray ( self :: SQL_BOOKS_BY_SERIE , array ( $serieId ), $n );
2012-05-28 08:07:49 +03:00
}
2012-09-20 22:15:03 +03:00
public static function getBooksByTag ( $tagId , $n ) {
return self :: getEntryArray ( self :: SQL_BOOKS_BY_TAG , array ( $tagId ), $n );
2012-05-28 08:01:33 +03:00
}
public static function getBookById ( $bookId ) {
2012-05-28 08:07:49 +03:00
$result = parent :: getDb () -> prepare ( 'select ' . self :: BOOK_COLUMNS . '
2012-12-04 16:36:10 +02:00
from books ' . self::SQL_BOOKS_LEFT_JOIN . '
2012-05-28 08:01:33 +03:00
where books . id = ? ' );
$result -> execute ( array ( $bookId ));
while ( $post = $result -> fetchObject ())
{
2012-05-28 08:07:49 +03:00
$book = new Book ( $post );
2012-05-28 08:01:33 +03:00
return $book ;
}
return NULL ;
}
2012-06-24 09:16:47 +03:00
public static function getBookByDataId ( $dataId ) {
2012-12-23 14:42:53 +02:00
$result = parent :: getDb () -> prepare ( 'select ' . self :: BOOK_COLUMNS . ' , data . name , data . format
2012-12-04 16:36:10 +02:00
from data , books ' . self::SQL_BOOKS_LEFT_JOIN . '
2012-06-24 09:16:47 +03:00
where data . book = books . id and data . id = ? ' );
$result -> execute ( array ( $dataId ));
while ( $post = $result -> fetchObject ())
{
$book = new Book ( $post );
2012-12-23 14:42:53 +02:00
$data = new Data ( $post , $book );
$data -> id = $dataId ;
$book -> datas = array ( $data );
2012-06-24 09:16:47 +03:00
return $book ;
}
return NULL ;
}
2012-09-20 22:15:03 +03:00
public static function getBooksByQuery ( $query , $n ) {
return self :: getEntryArray ( self :: SQL_BOOKS_QUERY , array ( " % " . $query . " % " , " % " . $query . " % " ), $n );
2012-05-28 08:01:33 +03:00
}
public static function getAllBooks () {
$result = parent :: getDb () -> query ( " select substr (upper (sort), 1, 1) as title, count(*) as count
from books
group by substr ( upper ( sort ), 1 , 1 )
order by substr ( upper ( sort ), 1 , 1 ) " );
2012-05-28 08:05:05 +03:00
$entryArray = array ();
2012-05-28 08:01:33 +03:00
while ( $post = $result -> fetchObject ())
{
2012-05-28 08:07:49 +03:00
array_push ( $entryArray , new Entry ( $post -> title , Book :: getEntryIdByLetter ( $post -> title ),
2013-01-05 15:33:12 +02:00
str_format ( localize ( " bookword " , $post -> count ), $post -> count ), " text " ,
2012-09-30 15:50:44 +03:00
array ( new LinkNavigation ( " ?page= " . parent :: PAGE_ALL_BOOKS_LETTER . " &id= " . rawurlencode ( $post -> title )))));
2012-05-28 08:01:33 +03:00
}
2012-05-28 08:05:05 +03:00
return $entryArray ;
2012-05-28 08:01:33 +03:00
}
2012-09-18 16:39:22 +03:00
public static function getBooksByStartingLetter ( $letter , $n ) {
2012-09-19 19:19:41 +03:00
return self :: getEntryArray ( self :: SQL_BOOKS_BY_FIRST_LETTER , array ( $letter . " % " ), $n );
}
public static function getEntryArray ( $query , $params , $n ) {
2013-01-11 16:16:15 +02:00
list ( $totalNumber , $result ) = parent :: executeQuery ( $query , self :: BOOK_COLUMNS , self :: getFilterString (), $params , $n );
2012-05-28 08:05:05 +03:00
$entryArray = array ();
2012-05-28 08:01:33 +03:00
while ( $post = $result -> fetchObject ())
{
2012-05-28 08:07:49 +03:00
$book = new Book ( $post );
2012-05-28 08:05:05 +03:00
array_push ( $entryArray , $book -> getEntry ());
2012-05-28 08:01:33 +03:00
}
2012-09-18 16:39:22 +03:00
return array ( $entryArray , $totalNumber );
2012-05-28 08:01:33 +03:00
}
public static function getAllRecentBooks () {
global $config ;
2012-12-04 16:36:10 +02:00
list ( $entryArray , $totalNumber ) = self :: getEntryArray ( self :: SQL_BOOKS_RECENT . $config [ 'cops_recentbooks_limit' ], array (), - 1 );
2012-05-28 08:05:05 +03:00
return $entryArray ;
2012-05-28 08:01:33 +03:00
}
}
?>