2013-09-12 00:51:45 +03:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* CalibreDbLoader class
|
|
|
|
*
|
|
|
|
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
|
|
|
* @author Didier Corbière <didier.corbiere@opale-concept.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
require_once(realpath(dirname(__FILE__)) . '/BookInfos.class.php');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calibre database sql file that comes unmodified from Calibre project:
|
|
|
|
* /calibre/resources/metadata_sqlite.sql
|
|
|
|
*/
|
|
|
|
define('CalibreCreateDbSql', realpath(dirname(__FILE__)) . '/metadata_sqlite.sql');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* CalibreDbLoader class allows to open or create a new Calibre database,
|
|
|
|
* and then add BookInfos objects into the database
|
|
|
|
*/
|
|
|
|
class CalibreDbLoader
|
|
|
|
{
|
|
|
|
private $mDb = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open a Calibre database (or create if database does not exist)
|
|
|
|
*
|
|
|
|
* @param string Calibre database file name
|
|
|
|
* @param boolean Force database creation
|
|
|
|
*/
|
|
|
|
public function __construct($inDbFileName, $inCreate = false)
|
|
|
|
{
|
2013-09-25 04:03:52 +03:00
|
|
|
if ($inCreate) {
|
2013-09-12 00:51:45 +03:00
|
|
|
$this->CreateDatabase($inDbFileName);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$this->OpenDatabase($inDbFileName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create an sqlite database
|
|
|
|
*
|
|
|
|
* @param string Database file name
|
|
|
|
* @throws Exception if error
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
private function CreateDatabase($inDbFileName)
|
|
|
|
{
|
|
|
|
// Read the sql file
|
|
|
|
$content = file_get_contents(CalibreCreateDbSql);
|
|
|
|
if ($content === false) {
|
2013-09-25 04:03:52 +03:00
|
|
|
$error = sprintf('Cannot read sql file: %s', CalibreCreateDbSql);
|
2013-09-12 00:51:45 +03:00
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the database file
|
|
|
|
if (file_exists($inDbFileName) && !unlink($inDbFileName)) {
|
|
|
|
$error = sprintf('Cannot remove database file: %s', $inDbFileName);
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the new database file
|
|
|
|
$this->OpenDatabase($inDbFileName);
|
|
|
|
|
|
|
|
// Create the database tables
|
|
|
|
try {
|
|
|
|
$sqlArray = explode('CREATE ', $content);
|
|
|
|
foreach ($sqlArray as $sql) {
|
|
|
|
$sql = trim($sql);
|
|
|
|
if (empty($sql)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$sql = 'CREATE ' . $sql;
|
|
|
|
$str = strtolower($sql);
|
|
|
|
if (strpos($str, 'create view') !== false) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strpos($str, 'title_sort') !== false) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception $e) {
|
|
|
|
$error = sprintf('Cannot create database: %s', $e->getMessage());
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open an sqlite database
|
|
|
|
*
|
|
|
|
* @param string Database file name
|
|
|
|
* @throws Exception if error
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
private function OpenDatabase($inDbFileName)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
// Init the Data Source Name
|
|
|
|
$dsn = 'sqlite:' . $inDbFileName;
|
|
|
|
// Open the database
|
|
|
|
$this->mDb = new PDO($dsn); // Send an exception if error
|
|
|
|
$this->mDb->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
//echo sprintf('Init database ok for: %s%s', $dsn, '<br />');
|
|
|
|
}
|
|
|
|
catch (Exception $e) {
|
|
|
|
$error = sprintf('Cannot open database [%s]: %s', $dsn, $e->getMessage());
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an epub to the db
|
|
|
|
*
|
|
|
|
* @param string Epub file name
|
|
|
|
* @throws Exception if error
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function AddEpub($inFileName)
|
|
|
|
{
|
|
|
|
// Load the book infos
|
|
|
|
$bookInfos = new BookInfos();
|
|
|
|
$bookInfos->LoadFromEpub($inFileName);
|
|
|
|
// Add the book
|
|
|
|
$this->AddBook($bookInfos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a new book into the db
|
|
|
|
*
|
|
|
|
* @param object BookInfo object
|
|
|
|
* @throws Exception if error
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
private function AddBook($inBookInfo)
|
|
|
|
{
|
2013-09-17 03:08:23 +03:00
|
|
|
$sql = 'insert into books(title, sort, series_index, uuid, path) values(:title, :sort, :serieindex, :uuid, :path)';
|
2013-09-12 00:51:45 +03:00
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':title', $inBookInfo->mTitle);
|
2013-09-13 13:19:17 +03:00
|
|
|
$stmt->bindParam(':sort', $inBookInfo->mTitle);
|
2013-09-17 03:08:23 +03:00
|
|
|
$stmt->bindParam(':serieindex', $inBookInfo->mSerieIndex);
|
2013-09-12 00:51:45 +03:00
|
|
|
$stmt->bindParam(':uuid', $inBookInfo->mUuid);
|
|
|
|
$stmt->bindParam(':path', $inBookInfo->mPath);
|
|
|
|
$stmt->execute();
|
|
|
|
// Get the book id
|
|
|
|
$sql = 'select id, title from books where uuid=:uuid';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':uuid', $inBookInfo->mUuid);
|
|
|
|
$stmt->execute();
|
|
|
|
$idBook = null;
|
|
|
|
while ($post = $stmt->fetchObject()) {
|
|
|
|
if (!isset($idBook)) {
|
|
|
|
$idBook = $post->id;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$error = sprintf('Multiple book id for uuid: %s (already in title "%s")', $inBookInfo->mUuid, $post->title);
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!isset($idBook)) {
|
|
|
|
$error = sprintf('Cannot find book id for uuid: %s', $inBookInfo->mUuid);
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
// Add the book formats
|
|
|
|
$sql = 'insert into data(book, format, name, uncompressed_size) values(:idBook, :format, :name, 0)';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':idBook', $idBook, PDO::PARAM_INT);
|
|
|
|
$stmt->bindParam(':format', $inBookInfo->mFormat);
|
|
|
|
$stmt->bindParam(':name', $inBookInfo->mName);
|
|
|
|
$stmt->execute();
|
|
|
|
// Add the book identifiers
|
|
|
|
if (!empty($inBookInfo->mUri)) {
|
|
|
|
$sql = 'insert into identifiers(book, type, val) values(:idBook, :type, :value)';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$type = 'URI';
|
|
|
|
$stmt->bindParam(':idBook', $idBook, PDO::PARAM_INT);
|
|
|
|
$stmt->bindParam(':type', $type);
|
|
|
|
$stmt->bindParam(':value', $inBookInfo->mUri);
|
|
|
|
$stmt->execute();
|
|
|
|
}
|
2013-09-17 03:08:23 +03:00
|
|
|
// Add the book serie
|
|
|
|
if (!empty($inBookInfo->mSerie)) {
|
|
|
|
// Get the serie id
|
|
|
|
$sql = 'select id from series where name=:serie';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':serie', $inBookInfo->mSerie);
|
|
|
|
$stmt->execute();
|
|
|
|
$post = $stmt->fetchObject();
|
|
|
|
if ($post) {
|
|
|
|
$idSerie = $post->id;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Add a new serie
|
|
|
|
$sql = 'insert into series(name, sort) values(:serie, :sort)';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':serie', $inBookInfo->mSerie);
|
|
|
|
$stmt->bindParam(':sort', $inBookInfo->mSerie);
|
|
|
|
$stmt->execute();
|
|
|
|
// Get the serie id
|
|
|
|
$sql = 'select id from series where name=:serie';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':serie', $inBookInfo->mSerie);
|
|
|
|
$stmt->execute();
|
|
|
|
$idSerie = null;
|
|
|
|
while ($post = $stmt->fetchObject()) {
|
|
|
|
if (!isset($idSerie)) {
|
|
|
|
$idSerie = $post->id;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$error = sprintf('Multiple series for name: %s', $inBookInfo->mSerie);
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!isset($idSerie)) {
|
|
|
|
$error = sprintf('Cannot find serie id for name: %s', $inBookInfo->mSerie);
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Add the book serie link
|
|
|
|
$sql = 'insert into books_series_link(book, series) values(:idBook, :idSerie)';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':idBook', $idBook, PDO::PARAM_INT);
|
|
|
|
$stmt->bindParam(':idSerie', $idSerie, PDO::PARAM_INT);
|
|
|
|
$stmt->execute();
|
|
|
|
}
|
|
|
|
// Add the book authors
|
2013-09-13 02:07:28 +03:00
|
|
|
foreach ($inBookInfo->mAuthors as $authorSort => $author) {
|
2013-09-12 00:51:45 +03:00
|
|
|
// Get the author id
|
|
|
|
$sql = 'select id from authors where name=:author';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':author', $author);
|
|
|
|
$stmt->execute();
|
|
|
|
$post = $stmt->fetchObject();
|
|
|
|
if ($post) {
|
|
|
|
$idAuthor = $post->id;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Add a new author
|
|
|
|
$sql = 'insert into authors(name, sort) values(:author, :sort)';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':author', $author);
|
2013-09-13 02:07:28 +03:00
|
|
|
$stmt->bindParam(':sort', $authorSort);
|
2013-09-12 00:51:45 +03:00
|
|
|
$stmt->execute();
|
|
|
|
// Get the author id
|
|
|
|
$sql = 'select id from authors where name=:author';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':author', $author);
|
|
|
|
$stmt->execute();
|
|
|
|
$idAuthor = null;
|
|
|
|
while ($post = $stmt->fetchObject()) {
|
|
|
|
if (!isset($idAuthor)) {
|
|
|
|
$idAuthor = $post->id;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$error = sprintf('Multiple authors for name: %s', $author);
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!isset($idAuthor)) {
|
|
|
|
$error = sprintf('Cannot find author id for name: %s', $author);
|
|
|
|
throw new Exception($error);
|
|
|
|
}
|
|
|
|
}
|
2013-09-17 03:08:23 +03:00
|
|
|
// Add the book author link
|
|
|
|
$sql = 'insert into books_authors_link(book, author) values(:idBook, :idAuthor)';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->bindParam(':idBook', $idBook, PDO::PARAM_INT);
|
|
|
|
$stmt->bindParam(':idAuthor', $idAuthor, PDO::PARAM_INT);
|
|
|
|
$stmt->execute();
|
2013-09-12 00:51:45 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check database for debug
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
private function CheckDatabase()
|
|
|
|
{
|
|
|
|
// Retrieve some infos for check only
|
|
|
|
$sql = 'select id, title, sort from books';
|
|
|
|
$stmt = $this->mDb->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
while ($post = $stmt->fetchObject()) {
|
|
|
|
$id = $post->id;
|
|
|
|
$title = $post->title;
|
|
|
|
$sort = $post->sort;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
?>
|