From 892e6a1a9552f4dd21b12f3ccbfa9d1dac569c90 Mon Sep 17 00:00:00 2001 From: "vincent@cubedesigners.com" Date: Wed, 18 Dec 2019 18:14:52 +0000 Subject: [PATCH] wait #3270 @1 --- inc/commons/class.common.ajax.php | 2 +- inc/ws/Controlleur/class.ws.ajax.php | 14 +- inc/ws/DAO/class.ws.dao.book.php | 3644 +++++++++++++------------- 3 files changed, 1843 insertions(+), 1817 deletions(-) diff --git a/inc/commons/class.common.ajax.php b/inc/commons/class.common.ajax.php index 47fae4be1..18ccee259 100644 --- a/inc/commons/class.common.ajax.php +++ b/inc/commons/class.common.ajax.php @@ -583,7 +583,7 @@ Mot de passe : $password"; public static function _formatWsReferenceRef($ref, $type) { - if ($type == '10doigts') { + if ($type === '10doigts') { if (stripos($ref, 'ic') === 0) { return 'C' . substr($ref, 2); } diff --git a/inc/ws/Controlleur/class.ws.ajax.php b/inc/ws/Controlleur/class.ws.ajax.php index 33442d1ea..dc1091798 100644 --- a/inc/ws/Controlleur/class.ws.ajax.php +++ b/inc/ws/Controlleur/class.ws.ajax.php @@ -1316,6 +1316,7 @@ class wsAjax extends cubeAjax public static function importFluidbookSettings($args, &$x) { global $core; + $dao = new wsDAOBook($core->con); new PHPExcel(); @@ -1326,7 +1327,11 @@ class wsAjax extends cubeAjax $ignore = wsUrl::getReadonlySettings(); $sheet = $xls->getActiveSheet()->toArray(); + $nlines = count($sheet); + + $x->addDebug($nlines); + for ($i = 1; $i < $nlines; $i++) { $line = $sheet[$i]; $id = (int)$line[0]; @@ -1341,7 +1346,14 @@ class wsAjax extends cubeAjax } $settings[$col] = $v; } - $dao->setSettings($id, $settings); + // $x->addDebug($id.' : '.json_encode($settings)); + + try { + $dao->setSettings($id, $settings); + }catch (Exception $e){ + $x->addDebug($e->getMessage()); + } } + $x->addAlert(__('Paramètres importés')); } } \ No newline at end of file diff --git a/inc/ws/DAO/class.ws.dao.book.php b/inc/ws/DAO/class.ws.dao.book.php index 5a43a0a20..4d13e4008 100644 --- a/inc/ws/DAO/class.ws.dao.book.php +++ b/inc/ws/DAO/class.ws.dao.book.php @@ -3,1820 +3,1834 @@ class wsDAOBook extends commonDAO { - public static $pagesOfBookCache = array(); - - /** - * wsDAOBook::singleton() - * - * @param mixed $r - * @return - */ - protected function singleton($r) - { - $book = new wsBook(); - $book->book_id = $r->book_id; - $book->cid = $r->cid; - $book->nom = $r->nom; - $book->lang = $r->lang; - $book->theme = $r->theme; - $book->proprietaire = $r->proprietaire_nom; - $book->proprietaire_id = $r->proprietaire_id; - $book->proprietaire_utilisateur = $r->proprietaire_utilisateur; - $book->hash = $r->hash; - $book->compteur_visites = $r->compteur_visites; - $book->status = $r->status; - $book->date_status = $r->date_status; - $book->date = $r->date; - $book->pages = array(); - $book->chapters = $r->chapters; - $book->traductions = $r->traductions; - $book->specialLinks = $r->specialLinks; - $book->specialRulers = $r->specialRulers; - $book->parametres = $r->parametres; - $book->extras = $r->extras; - $book->numerotation = $r->numerotation; - $book->changedate = $r->changedate; - $book->compiledate = $r->compiledate; - $book->compile1date = $r->compile1date; - $book->compilehtml5date = $r->compilehtml5date; - $book->facturable = $r->facturable; - $book->facturable_id = $r->facturable_id; - $book->tache = $r->tache; - if (isset($r->projet)) { - $book->projet = $r->projet; - } - $book->version = $r->version; - $book->composition_update = $r->composition_update; - $book->dir_references = $r->dir_references; - $book->dir_hosting = $r->dir_hosting; - $book->dir_macbook_phonegap_ios = $r->dir_macbook_phonegap_ios; - $book->dir_phonegap_android = $r->dir_phonegap_android; - $book->dir_external = $r->dir_external; - $book->demo_counter = $r->demo_counter; - $book->exportdatas = $r->exportdatas; - - return $book; - } - - protected function cree($r) - { - $book = new wsBook(); - $book->book_id = 'new'; - $book->nom = ''; - $book->cid = null; - $book->lang = 'fr'; - $book->theme = 1; - $book->proprietaire = ''; - $book->proprietaire_id = 0; - $book->hash = ''; - $book->compteur_visites = 20; - $book->status = 0; - $book->date_status = TIME; - $book->date = TIME; - $book->composition_update = TIME; - $book->chapters = json_encode(array()); - $book->parametres = new wsBookParametres(); - $book->tache = 0; - $book->pages = array(); - $book->version = 2; - return $book; - } - - protected function getNextId() - { - $r = $this->con->select('SELECT MAX(book_id) AS book_id FROM books'); - if ($r->book_id < 10000) { - return 10000; - } - return $r->book_id + 1; - } - - public function saveExportDatas($book_id, $datas) - { - $c = $this->con->openCursor('books'); - $c->exportdatas = json_encode($datas); - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function addDemoCount($book_id) - { - - $r = $this->con->select('SELECT demo_counter,nom FROM books WHERE book_id=\'' . $book_id . '\''); - $m = 20; - if ($r->demo_counter > 0 && $r->demo_counter % $m == 0) { - $mail = new cubeMail(); - $mail->charset = 'UTF-8'; - $mail->from = 'contact@fluidbook.com'; - $mail->to = 'tech@fluidbook.com'; - $mail->subject = '[Fluidbook Workshop] Fluidbook consulté via l\'url publique'; - $mail->body = 'Le fluidbook suivant a été consulté ' . $m . ' fois (et ' . $r->demo_counter . ' au total) via l\'url publique : ' . "\r\n" . - 'Fluidbook # ' . $book_id . ' - ' . $r->nom; - $mail->send(); - } - - $this->con->select('UPDATE books SET demo_counter=demo_counter+1 WHERE book_id=\'' . $book_id . '\''); - } - - public function selectByIds($book_ids = array(), $simple = false) - { - if ($simple) { - $table = 'books'; - } else { - $table = 'books_vue'; - } - - $ids = array(); - foreach ($book_ids as $bid) { - fb($bid); - if (intval($bid) > 0) { - $ids[] = $bid; - } - } - - $sql = 'SELECT * FROM ' . $table . ' WHERE book_id IN (' . implode(',', $ids) . ')'; - $books = $this->factory($this->con->select($sql)); - $res = array(); - foreach ($books as $book) { - $res[$book->book_id] = $book; - } - return $res; - } - - public function selectById($book_id = null, $simple = false) - { - if (is_null($book_id)) { - return $this->cree(); - } - if ($simple) { - $table = 'books'; - } else { - $table = 'books_vue'; - } - $sql = 'SELECT * FROM ' . $table . ' WHERE book_id=\'' . $this->con->escape($book_id) . '\' LIMIT 1'; - $r = $this->con->select($sql); - return $this->singleton($r); - } - - public function selectByCid($cid = null, $simple = false) - { - if ($simple) { - $table = 'books'; - } else { - $table = 'books_vue'; - } - - $sql = 'SELECT * FROM ' . $table . ' WHERE cid LIKE BINARY \'' . $this->con->escape($cid) . '\' LIMIT 1'; - $r = $this->con->select($sql); - return $this->singleton($r); - } - - public function selectLuceneToDo() - { - $sql = 'SELECT * FROM books_vue WHERE lucene_timecon->select($sql); - return $this->factory($r); - } - - public function selectLuceneTimeNotSet() - { - $sql = 'SELECT * FROM books_vue WHERE lucene_time=0 AND version=2'; - $r = $this->con->select($sql); - return $this->factory($r); - } - - /** - * wsDAOBook::sauve() - * - * @param mixed $createur - * @param mixed $data - * @return - */ - public function sauve($createur, $data) - { - $c = $this->con->openCursor('books'); - if (isset($data['nom'])) { - $c->nom = $data['nom']; - } - if (isset($data['lang'])) { - $c->lang = $data['lang']; - } - if (isset($data['theme'])) { - $c->theme = $data['theme']; - } - if (isset($data['proprietaire'])) { - $c->proprietaire = $data['proprietaire']; - } - - if ($data['book_id'] == 'new' || $data['book_id'] == '') { - $c->date = TIME; - $c->hash = md5(rand(0, 123456789365469)); - $c->compteur_visites = 20; - $c->parametres = serialize(new wsParametres()); - $c->changedate = TIME; - $book_id = $c->book_id = $this->getNextId(); - - $c->insert(); - } else { - $c->changedate = TIME; - $book_id = $data['book_id']; - $c->update('WHERE book_id=\'' . $this->con->escape($data['book_id']) . '\''); - } - - if (isset(self::$pagesOfBookCache[$book_id])) { - unset(self::$pagesOfBookCache[$book_id]); - } - - return $this->selectById($book_id); - } - - public function duplicate($book_id, $createur, $nom = null, $pages = false, $complete = false) - { - $r = $this->con->select('SELECT * FROM books_vue WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - - $old_id = $book_id; - - - $parametres = unserialize($r->parametres); - $parametres->setParent($this); - if (null === $nom) { - $nom = $parametres->title; - } - $parametres->title = $nom; - - if (!$complete) { - $parametres->pdfReplace = ''; - } - - $c = $this->con->openCursor('books'); - $c->proprietaire = $createur; - $c->date = TIME; - $c->hash = md5(rand(0, 1234567893)); - $c->cid = $this->generateCID(); - $c->compteur_visites = 20; - $c->status = -1; - $c->date_status = TIME; - $c->lang = $r->lang; - $c->parametres = serialize($parametres); - $c->nom = $nom; - $c->theme = $r->theme; - $c->changedate = TIME; - $c->compiledate = 0; - $c->version = 2; - $c->traductions = $r->traductions; - $c->specialLinks = $r->specialLinks; - $c->specialRulers = $r->specialRulers; - $c->composition_update = TIME; - $book_id = $c->book_id = $this->getNextId(); - if ($pages) { - $c->numerotation = $r->numerotation; - $c->chapters = $r->chapters; - $this->con->execute('INSERT INTO book_pages SELECT ' . $book_id . ' AS book_id,book_page,document_id,document_page FROM book_pages WHERE book_id=' . $old_id); - } - if ($complete) { - $c->numerotation = $r->numerotation; - $c->chapters = $r->chapters; - } - $c->insert(); - - $this->saveCompositionVersion($book_id); - - return $this->selectById($book_id); - } - - public function creeEmpty($createur, $lang, $nom) - { - $c = $this->con->openCursor('books'); - - $parametres = new wsBookParametres($this); - $parametres->title = $nom; - - $c->proprietaire = $createur; - $c->cid = $this->generateCID(); - $c->nom = $nom; - $c->date = TIME; - $c->hash = md5(rand(0, 1234567893)); - $c->compteur_visites = 20; - $c->status = -1; - $c->date_status = TIME; - $c->parametres = serialize($parametres); - - $c->theme = 1; - $c->lang = $lang; - $c->changedate = TIME; - $c->compiledate = 0; - $c->version = 2; - $c->composition_update = TIME; - $book_id = $c->book_id = $this->getNextId(); - $c->insert(); - return $this->selectById($book_id); - } - - public function supprime($book_id) - { - $this->con->execute('DELETE FROM book_pages_versions WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - $this->con->execute('DELETE FROM book_pages WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - return $this->con->execute('DELETE FROM books WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function count($limitedToUserRights = false) - { - $filters = $this->makeWhereFromFiltres(); - if ($filters == '1=1') { - $table = 'books'; - } else { - $table = 'books_vue'; - } - - $where = '(' . $filters . ')'; - $where .= $this->limitToUserRights($limitedToUserRights); - $r = $this->con->select('SELECT COUNT(*) AS nb FROM ' . $table . ' WHERE ' . $where); - return $r->nb; - } - - public function getPagesOfBookAt($book_id, $time) - { - $r = $this->con->select('SELECT * FROM book_pages_versions WHERE book_id=\'' . $this->con->escape($book_id) . '\' ORDER BY `update` ASC'); - if (!$r->count()) { - return $this->getPagesOfBook($book_id); - } - if ($r->count() == 1) { - $pages = unserialize($r->composition); - if (null === $pages || !count($pages)) { - return $this->getPagesOfBook($book_id); - } - return $pages; - } - - $pages = null; - while ($r->fetch()) { - if ($r->update > $time) { - - if (is_null($pages)) { - return $this->getPagesOfBook($book_id); - } - $res = unserialize($pages); - if (null === $res || !count($res)) { - return $this->getPagesOfBook($book_id); - } - return $res; - } - if (!count(unserialize($r->composition))) { - continue; - } - $pages = $r->composition; - } - - $res = unserialize($pages); - if (null === $res || !count($res)) { - return $this->getPagesOfBook($book_id); - } - return $res; - } - - public function getDocumentsToUpdate($book_id) - { - $res = array(); - $r = $this->con->select('SELECT DISTINCT d.document_id FROM book_pages b,documents d WHERE b.book_id=\'' . $this->con->escape($book_id) . '\' AND d.version=1 AND b.document_id=d.document_id'); - while ($r->fetch()) { - $res[] = $r->document_id; - } - return $res; - } - - public function getPagesOfBook($book_id, $conversion = true, $force = false) - { - if ($force || !isset(self::$pagesOfBookCache[$book_id])) { - $pages = array(); - - $sql = 'SELECT b.*,d.numberSections AS num,d.conversionInfos AS conversion,d.pages AS doc_pages,d.version AS version FROM book_pages b JOIN documents d ON d.document_id=b.document_id WHERE b.book_id=\'' . $this->con->escape($book_id) . '\' ORDER BY book_page'; - - $r = $this->con->select($sql); - while ($r->fetch()) { - $n = explode(',', $r->num); - - if (isset($n[$r->document_page - 1])) { - $num = $n[$r->document_page - 1]; - } else { - $num = ''; - } - $pages[$r->book_page] = array('document_id' => $r->document_id, - 'document_page' => $r->document_page, - 'version' => $r->version, - 'defaultNum' => $num, - 'nb_pages' => $r->doc_pages - ); - - if ($conversion) { - if ($r->conversion != '') { - $c = unserialize($r->conversion); - $c = $c->pages[$r->document_page]; - } - $qp = array('resolution', 'method', 'quality', 'objects'); - foreach ($qp as $p) { - if (isset($c) && isset($c->$p)) { - $pages[$r->book_page][$p] = $c->$p; - } - } - } - } - if (!count($pages)) { - return []; - } - - self::$pagesOfBookCache[$book_id] = $pages; - } - return self::$pagesOfBookCache[$book_id]; - } - - public function appendDocument($book_id, $document_id) - { - $r = $this->con->select('SELECT MAX(book_page) AS book_page FROM book_pages WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - $lastPage = is_null($r->book_page) ? 0 : $r->book_page; - $this->insertDocument($book_id, $lastPage, $document_id); - } - - public function removePage($book_id, $book_page) - { - // Supprime la page - $this->con->execute('DELETE FROM book_pages WHERE book_page=\'' . $this->con->escape($book_page) . '\' AND book_id=\'' . $this->con->escape($book_id) . '\''); - // Décale les pages suivantes vers le haut - $this->decalePages($book_id, $book_page, -1); - } - - public function insertPage($book_id, $after_page, $document_id, $document_page) - { - // Décale les pages vers le bas - $this->decalePages($book_id, $after_page, 1); - // Insère la page - $c = $this->con->openCursor('book_pages'); - $c->book_id = $book_id; - $c->book_page = $after_page + 1; - $c->document_id = $document_id; - $c->document_page = $document_page; - $c->insert(); - } - - public function insertDocument($book_id, $after_page, $document_id) - { - // Obtiens le book - $book = $this->selectById($book_id); - $num = explode(',', $book->numerotation); - // Obtiens le nombre de pages - $r = $this->con->select('SELECT pages,numberSections FROM documents WHERE document_id=\'' . $this->con->escape($document_id) . '\''); - // Décale les pages vers le bas - if ($after_page > 0) { - $this->decalePages($book_id, $after_page, $r->pages); - } - // Insère les pages - $c = $this->con->openCursor('book_pages'); - $c->book_id = $book_id; - $c->document_id = $document_id; - for ($i = 1; $i <= $r->pages; $i++) { - $c->document_page = $i; - $c->book_page = $after_page + $i; - $c->insert(); - } - // Mets à jour la liste des numéros des pages - $before = array_slice($num, 0, $after_page); - $after = array_slice($num, $after_page, count($num) - $after_page); - - $newnum = $r->numberSections; - if (trim($newnum, ',') == '') { - // If no number detected, we create a numeric list from 1 - $between = range(1, $r->pages); - } else { - // Else, we use numbers detected at conversion - $between = explode(',', $r->numberSections); - } - $num = array_merge($before, $between, $after); - // Mets à jour la numerotation de la publication - $c = $this->con->openCursor('books'); - $c->numerotation = implode(',', $num); - $c->composition_update = TIME; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - - $this->saveCompositionVersion($book_id); - } - - protected function decalePages($book_id, $after_page, $decalage) - { - $decalage = ($decalage >= 0) ? '+' . $decalage : $decalage; - $this->con->execute('UPDATE book_pages SET book_page=book_page' . $decalage . ' WHERE book_page>' . $this->con->escape($after_page) . ' AND book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function getListe($orderby = null, $sens = null, $limit = null, $limitedToUserRights = false) - { - if (!is_null($this->q)) { - $where = '('; - if ($this->search_id) { - $where .= ' book_id=\'' . $this->con->escape($this->q) . '\' OR '; - } - - if (!cubeMath::is_int($this->q)) { - $where .= 'nom LIKE \'%' . $this->con->escape($this->q) . '%\''; - $daoClient = new commonDAOClient($this->con); - $where .= ' OR proprietaire_id IN(' . $daoClient->querySearchByName($this->q) . ') OR '; - } - $limit = null; - $where .= '1=2)'; - } else { - $where = '(' . $this->makeWhereFromFiltres() . ')'; - } - $where .= $this->limitToUserRights($limitedToUserRights); - - $orderby = is_null($orderby) ? 'book_id' : $orderby; - $sens = is_null($sens) ? 'DESC' : $sens; - $limit = is_null($limit) ? '' : $this->con->limit($limit); - - $sql = 'SELECT * FROM books_vue WHERE ' . $where . ' ORDER BY ' . $orderby . ' ' . $sens . ' ' . $limit; - $r = $this->con->select($sql); - return $this->factory($r); - } - - protected function limitToUserRights($utilisateur) - { - if ($utilisateur) { - if (wsDroits::admin()) { - return ''; - } - return ' AND proprietaire IN (' . $utilisateur->ws_rights . ')'; - } - return ''; - } - - protected function makeWhereFromFiltres() - { - if (!is_null($this->filtres)) { - $w = array('1=1'); - if (commonFiltre::test('admin_book', $this->filtres)) { - $w[] = 'super_admin IN (' . implode(',', array_keys($this->filtres['admin_book'])) . ')'; - } - if (commonFiltre::test('status_book', $this->filtres)) { - $w[] = 'status IN(' . implode(',', array_keys($this->filtres['status_book'])) . ')'; - } - if (commonFiltre::test('revendeur_book', $this->filtres)) { - $v = array_keys($this->filtres['revendeur_book']); - $values = array(); - foreach ($v as $r) { - $values[] = $this->con->escape($r); - } - - - $w[] = 'facturable IN(\'' . implode('\',\'', $values) . '\')'; - } - return implode(' AND ', $w); - } else { - return '1=1'; - } - } - - public function setChapters($book_id, $json) - { - $chapters = json_decode($json, true); - $res = array(); - - foreach ($chapters as $c) { - $c['label'] = trim($c['label']); - $n = (string)$c['page']; - $c['label'] = trim(preg_replace('|\s+' . $n . '$|iu', '', $c['label'])); - $res[] = $c; - } - - $json_chapters = json_encode($res); - - $c = $this->con->openCursor('books'); - $c->chapters = $json_chapters; - $c->changedate = TIME; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - - if ($json_chapters && $json_chapters != '[]') { - if (count($res) == 1) { - if ($res[0]['label'] == '' && $res[0]['page'] == '') { - return; - } - } - $c = $this->con->openCursor('books_chapters_versions'); - $c->book_id = $book_id; - $c->chapters = $json_chapters; - $c->time = TIME; - $c->insert(); - } - } - - public function setSpecialLinksAndRulers($book_id, $links, $rulers) - { - $c1 = $this->con->openCursor('special_links_versions'); - $c = $this->con->openCursor('books'); - - if (is_string($links)) { - $links = json_encode(json_decode($links, false)); - } - if (is_string($rulers)) { - $rulers = json_encode(json_decode($rulers, false)); - } - - - $links = wsLinks::encryptLinks(json_decode($links)); - - - if (is_array($links)) { - $links = json_encode($links); - } - if (is_array($rulers)) { - $rulers = json_encode($rulers); - } - - $c1->links = $c->specialLinks = $links; - $c1->rulers = $c->specialRulers = $rulers; - $c1->update = $c->changedate = TIME; - $c1->book_id = $book_id; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - try { - $c1->insert(); - } catch (Exception $e) { - try { - $c1->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\' AND `update`=' . TIME); - } catch (Exception $e) { - - } - } - } - - public function setTheme($book_id, $theme) - { - $c = $this->con->openCursor('books'); - $c->theme = $theme; - $c->changedate = TIME; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function setStatus($book_id, $status) - { - $c = $this->con->openCursor('books'); - if ($status < 2) { - $c->tache = 0; - } - $c->status = $status; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - return $this->selectById($book_id); - } - - public function setChaptersFromOldFluidbook($book_id) - { - $book = $this->selectById($book_id); - $n = explode(',', $book->numerotation); - - $xml = simplexml_load_file('https://ws.fluidbook.com/books/' . $book_id . '/data/links.xml'); - $res = array(); - $chapters = $xml->xpath('//chapters'); - foreach ($chapters as $ch) { - $c = array(); - $c['label'] = (string)$ch->txt; - - $p = intval((string)$ch->page); - if ($p <= 0) { - continue; - } - $c['page'] = $n[$p]; - $c['level'] = intval((string)$ch->level); - $res[] = $c; - } - - $c = $this->con->openCursor('books'); - $c->chapters = json_encode($res); - $c->changedate = TIME; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function saveCompositionVersion($book_id, $time = null) - { - $time = is_null($time) ? TIME : $time; - - $pages = $this->getPagesOfBook($book_id, true, true); - - $c = $this->con->openCursor('book_pages_versions'); - $c->update = $time; - $c->book_id = $book_id; - $c->composition = serialize($pages); - $c->insert(); - } - - public function setLang($book_id, $base, $traductions) - { - // Cleanup user translations - $traductions = json_decode($traductions, true); - foreach ($traductions as $k => $v) { - $traductions[$k] = $v; - } - - $daoLang = new wsDAOLang($this->con); - $lang = $daoLang->selectById($base); - // Cleanup base translations - $baseTraductions = $lang->traductions; - foreach ($baseTraductions as $k => $v) { - $baseTraductions[$k] = $v; - } - // Then compare them. If there is no differences, we don't save translations in the book - if ($traductions == $baseTraductions) { - $t = ''; - } else { - $t = json_encode($traductions); - } - - $c = $this->con->openCursor('books'); - $c->lang = $base; - $c->traductions = $t; - $c->changedate = TIME; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function setSettings($book_id, $settings) - { - $book = $this->selectById($book_id); - $parametres = $book->parametres; - $new = $settings; - foreach ($new as $k => $v) { - if ($k == '_empty_') { - continue; - } - $parametres->$k = $v; - } - - $ip = array(); - if (isset($parametres->stats_exclude_ip) && trim($parametres->stats_exclude_ip) != '') { - $list = $parametres->stats_exclude_ip; - $list = str_replace("\r", "\n", $list); - $e = explode("\n", $list); - foreach ($e as $i) { - $i = trim($i); - if ($i == '') { - continue; - } - $long = ip2long($i); - if ($long !== false) { - $ip[] = $long; - } - } - } - - $file = '/home/stats/www/exclude/' . $book_id; - - if (count($ip)) { - file_put_contents($file, implode(',', $ip)); - chmod($file, 0777); - chown($file, 'stats'); - } else if (file_exists($file)) { - unlink($file); - } - - $c = $this->con->openCursor('books'); - $c->nom = $parametres->title; - $c->parametres = serialize($parametres); - $c->changedate = TIME; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function setProprietaire($book_id, $proprietaire_id) - { - $c = $this->con->openCursor('books'); - $c->proprietaire = $proprietaire_id; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function setTache($book_id, $tache) - { - $c = $this->con->openCursor('books'); - $c->tache = $tache; - $c->status = 2; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function setVersion($book_id, $version) - { - $c = $this->con->openCursor('books'); - $c->version = $version; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function touch($book_id) - { - $c = $this->con->openCursor('books'); - $c->changedate = TIME; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function touchCompile($book_id, $version = 'all') - { - $c = $this->con->openCursor('books'); - if ($version == '2') { - $c->compiledate = TIME; - } elseif ($version == '1') { - $c->compile1date = TIME; - } elseif ($version == 'html5') { - $c->compilehtml5date = TIME; - } else { - $c->compiledate = TIME; - $c->compile1date = TIME; - $c->compilehtml5date = TIME; - } - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function isUpToDate($book, $version) - { - $version = (string)$version; - if ($version == '2') { - if (!file_exists(WS_BOOKS . '/final/' . $book->book_id)) { - return false; - } - if ($book->compiledate < $book->changedate) { - return false; - } - } else if ($version == '1') { - // V1 - if (!file_exists(WS_BOOKS . '/finalv1/' . $book->book_id . '/index.swf')) { - return false; - } - if ($book->compile1date < $book->changedate) { - return false; - } - } else if ($version == 'html5') { - return false; - // HTML5 - $checks = array($book->changedate, cubeFiles::filemtimeRecursive(WS_BOOKS . '/working/' . $book->book_id), cubeFiles::filemtimeRecursive(WS_COMPILE_ASSETS . '/_html5'), cubeFiles::filemtimeRecursive(ROOT . '/inc/ws/Util/html5')); - foreach ($checks as $check) { - if ($check > $book->compilehtml5date) { - return false; - } - } - } - return true; - } - - public function setComposition($book_id, $pages) - { - $numerotation = array(); - $nb_pages = 0; - foreach ($pages as $p) { - $numerotation[] = $p->virtual; - $nb_pages++; - } - - $book = $this->selectById($book_id); - $parametres = $book->parametres; - $parametres->pages = $nb_pages; - - $c = $this->con->openCursor('books'); - $c->parametres = serialize($parametres); - $c->numerotation = implode(',', $numerotation); - $c->changedate = TIME; - - // Check if composition need to be updated - $r = $this->con->select('SELECT * FROM book_pages WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - $tab = array(); - $now = array(); - $ref = array(); - while ($r->fetch()) { - $ref[$r->book_page] = array((int)$r->document_id, (int)$r->document_page); - } - $i = 1; - foreach ($pages as $p) { - $now[$i] = array((int)$p->document_id, (int)$p->document_page); - $i++; - } - if ($now != $ref) { - $this->con->execute('DELETE FROM book_pages WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - - $c1 = $this->con->openCursor('book_pages'); - $c1->book_id = $book_id; - $i = 1; - foreach ($pages as $p) { - $c1->document_id = $p->document_id; - $c1->document_page = $p->document_page; - $c1->book_page = $i; - $c1->insert(); - $i++; - } - $c->composition_update = TIME; - $this->saveCompositionVersion($book_id); - } - - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function setInstallDir($book_id, $dir, $server) - { - $col = 'dir_' . $server; - - $c = $this->con->openCursor('books'); - $c->$col = $dir; - $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); - } - - public function makeTextsIndexes($book, $pages, &$index, &$textes, $simple = false) - { - global $core; - $prefix = ''; - if ($book->parametres->textExtraction == 'poppler') { - $prefix = 'p'; - } else if ($book->parametres->textExtraction == 'fluidbook') { - $prefix = 'f'; - } - - $dir = WS_BOOKS . '/index/' . $book->book_id; - if ($book->parametres->ignoreSearchSeparators != '') { - $dir .= '/' . sha1($book->parametres->ignoreSearchSeparators); - } - if (!file_exists($dir)) { - mkdir($dir, 0777, true); - } - - if ($simple) { - $ifilec = $dir . '/' . $prefix . 'sindex.json'; - } else { - $ifilec = $dir . '/' . $prefix . 'index.json'; - } - $tfilec = $dir . '/' . $prefix . 'textes.json'; - - if (CubeIT_Util_Gzip::file_exists($ifilec) && CubeIT_Util_Gzip::file_exists($tfilec) && (min(CubeIT_Util_Gzip::filemtime($ifilec), CubeIT_Util_Gzip::filemtime($tfilec)) >= max($book->composition_update, filemtime(__FILE__), filemtime(WS_TOOLS . '/fwstk/out/artifacts/fwstk_jar/fwstk.jar')))) { - $index = CubeIT_Util_Gzip::file_get_contents($ifilec); - $textes = CubeIT_Util_Gzip::file_get_contents($tfilec); - return; - } - - if ($book->parametres->ignoreSearchSeparators != "") { - $docs = array(); - foreach ($pages as $p => $i) { - $docs[] = $i['document_id']; - } - $docs = array_unique($docs); - - foreach ($docs as $doc) { - $out = wsDocument::getDir($doc); - - $fwstk = new cubeCommandLine('fwstk.sh'); - $fwstk->setPath(CONVERTER_PATH); - $fwstk->setArg('--input ' . $out . '/crop.pdf'); - $fwstk->setArg('--extractTexts ' . $out . '%s%d.txt'); - $fwstk->setArg('--extractTextsMethod ' . $book->parametres->textExtraction); - $fwstk->setArg('--threads 1'); - $fwstk->setArg('--ignoreSeparators ' . $book->parametres->ignoreSearchSeparators); - $fwstk->execute(); - } - } - - $index = array(); - $textes = array(); - foreach ($pages as $book_page => $infos) { - $tfile = wsDocument::getDir($infos['document_id']) . $prefix . 'p' . $infos['document_page'] . '.txt'; - $ifile = wsDocument::getDir($infos['document_id']) . $prefix . 'i' . $infos['document_page'] . '.txt'; - - if (!file_exists($tfile) || !file_exists($ifile)) { - $daoDoc = new wsDAODocument($core->con); - $out = wsDocument::getDir($infos['document_id']); - - $fwstk = new cubeCommandLine('fwstk.sh'); - $fwstk->setPath(CONVERTER_PATH); - $fwstk->setArg('--input ' . $out . '/crop.pdf'); - $fwstk->setArg('--extractTexts ' . $out . '%s%d.txt'); - $fwstk->setArg('--extractTextsMethod ' . $book->parametres->textExtraction); - if ($book->parametres->ignoreSearchSeparators != '') { - $fwstk->setArg('--ignoreSeparators ' . $book->parametres->ignoreSearchSeparators); - } - $fwstk->setArg('--threads 1'); - $fwstk->execute(); - } - - CubeIT_Util_Gzip::compressIfNotCompressed($tfile); - CubeIT_Util_Gzip::compressIfNotCompressed($ifile); - $text = CubeIT_Util_Gzip::file_get_contents($tfile); - $ipage = CubeIT_Util_Gzip::file_get_contents($ifile); - - if ($simple) { - $this->fillIndexWithWordsSimple($index, $book_page, $ipage); - } else { - $this->fillIndexWithWords($index, $book_page, $ipage); - } - $textes[$book_page] = $text; - } - ksort($index); - - $textes = json_encode($textes); - $index = json_encode($index); - - CubeIT_Util_Gzip::file_put_contents($tfilec, $textes); - CubeIT_Util_Gzip::file_put_contents($ifilec, $index); - } - - public function makeHighlightIndex($book, $pages) - { - $jar = WS_TOOLS . '/fwstk/out/artifacts/fwstk_jar/fwstk.jar'; - - $daoDoc = new wsDAODocument($this->con); - $res = new stdClass(); - foreach ($pages as $book_page => $infos) { - $fby = wsDocument::getDir($infos['document_id']) . 'html/p' . $infos['document_page'] . '.fby'; - // Refresh highlight data if fby file doesn't exists or if fwstk has been updated - $fbymtime = @filemtime($fby); - if (!file_exists($fby) || filemtime($jar) > $fbymtime || filemtime(__FILE__) > $fbymtime) { - $doc = $daoDoc->selectById($infos['document_id']); - $doc->getHighlightTextsData(); - } - - if (file_exists($fby)) { - $words = CubeIT_Util_Json::decode(file_get_contents($fby), CubeIT_Util_Json::TYPE_OBJECT); - - if (is_array($words)) { - foreach ($words as $i => $w) { - $word = $w->word; - $word = trim($word, "\0"); - if ($word == '') { - continue; - } - unset($w->word); - $w->page = $book_page; - $w->idx = $i; - if (!isset($res->{$word})) { - $res->{$word} = array(); - } - $res->{$word}[] = $w; - } - } - } - } - return $res; - } - - protected function _escapeIndex($str) - { - $todelete = array('\ufffd'); - foreach ($todelete as $d) { - $str = str_replace($d, '', $str); - } - return $str; - } - - protected function fillIndexWithWordsSimple(&$index, $page, $ipage) - { - $twords = explode("\n", trim($ipage)); - - foreach ($twords as $woadata) { - $w1 = explode(',', trim($woadata)); - if (count($w1) <= 1) { - continue; - } - list($woa, $worddata) = $w1; - $e = explode("\t", $worddata, 2); - if (count($e) < 2) { - continue; - } - list($total, $wordslist) = $e; - - if ($woa == '') { - continue; - } - - if (!isset($index[$woa])) { - $index[$woa] = array('t' => 0, 'p' => array()); - } - $index[$woa]['t'] += $total; - - $words = explode("\t", $wordslist); - foreach ($words as $word) { - list($wordwa, $count) = explode('$', $word, 2); - if (!isset($index[$woa]['p'][$page])) { - $index[$woa]['p'][$page] = 0; - } - $index[$woa]['p'][$page] += $count; - } - } - } - - protected function fillIndexWithWords(&$index, $page, $ipage) - { - $twords = explode("\n", trim($ipage)); - - foreach ($twords as $woadata) { - $w1 = explode(',', trim($woadata)); - if (count($w1) <= 1) { - continue; - } - list($woa, $worddata) = $w1; - $e = explode("\t", $worddata, 2); - if (count($e) < 2) { - continue; - } - list($total, $wordslist) = $e; - - if ($woa == '') { - continue; - } - - if (!isset($index[$woa])) { - $index[$woa] = array('t' => 0, 'w' => array()); - } - $index[$woa]['t'] += $total; - - $words = explode("\t", $wordslist); - - foreach ($words as $word) { - list($wordwa, $count) = explode('$', $word, 2); - if (!isset($index[$woa]['w'][$wordwa])) { - $index[$woa]['w'][$wordwa] = array('t' => 0, 'p' => array()); - } - if (!isset($index[$woa]['w'][$wordwa]['p'][$page])) { - $index[$woa]['w'][$wordwa]['p'][$page] = 0; - } - $index[$woa]['w'][$wordwa]['t'] += $count; - $index[$woa]['w'][$wordwa]['p'][$page] += $count; - } - } - } - - public function getNumerotationFromDocs($book_id) - { - $pages = $this->getPagesOfBook($book_id); - } - - public function compileTemp($book_id, $version, $dir) - { - if ($version == 'ha' || $version == 'hi') { - if ($version == 'ha') { - $os = 'android'; - } elseif ($version == 'hi') { - $os = 'ios'; - } - $packager = new wsPackagerPhonegap($book_id, $dir, false, true, $os); - $packager->makePackage(false); - } - } - - public function compile($book_id, $version = 'all', $complete = false, $force = false, $dev = false, $book = null, $delete = true) - { - if (is_null($book_id) || !$book_id) { - return; - } - - $v1 = $v2 = $html5 = false; - - if ($version == 'all') { - $v1 = $v2 = $html5 = true; - } else if ($version == '1') { - $v1 = true; - } else if ($version == '2') { - $v2 = true; - } elseif ($version == 'html5') { - $html5 = true; - } - - if (null === $book) { - $book = $this->selectById($book_id); - } - $pages = $this->getPagesOfBook($book_id); - - if (!$force) { - $v1 = $v1 && !$this->isUpToDate($book, 1); - $v2 = $v2 && !$this->isUpToDate($book, 2); - $html5 = $html5 && !$this->isUpToDate($book, 'html5'); - } else { - $v1 = false; - $html5 = true; - $v2 = true; - } - - $res = ''; - if ($v1) { - fb(time(), 'Compile V1'); - $res .= $this->compile1($book_id, $book, $pages); - $this->touchCompile($book_id, '1'); - } - if ($v2) { - fb(time(), 'Compile V2'); - $res .= $this->compile3($book_id, $complete, $book, $pages); - $this->touchCompile($book_id, '2'); - } - if ($html5) { - fb(time(), 'Compile HTML5'); - $res .= $this->compileHTML5($book_id, $book, $dev, $delete); - $this->touchCompile($book_id, 'html5'); - } - if ($v1 || $v2) { - fb(time(), 'Compile PDF & Widget'); - $this->compilePDF($book, $pages); - $this->compileWidget($book, $pages); - } - - fb(time(), 'End Compile'); - return $res; - } - - public function compile1($book_id, $book, $pages) - { - $finalDir = WS_BOOKS . '/finalv1/' . $book_id . '/'; - $packager = new wsPackagerV1($book_id, $finalDir, false); - $packager->makePackage(false); - } - - public function compile3($book_id, $complete, $book, $pages) - { - $res = ''; - - $compilerDir = WS_BOOKS . '/datasCompiler/' . $book_id . '/'; - $finalDir = WS_BOOKS . '/final/' . $book_id . '/'; - - $vdir = new CubeIT_Files_VirtualDirectory($finalDir); - - $debug = false; - - $flex = new cubeFlexCompiler('FluidbookDatas', $compilerDir, 'flash.display.Sprite', explode(';', AS3_SOURCES), MXMLC_PATH, 10, 30, 800, 600, $debug); - $flexLight = new cubeFlexCompiler('FluidbookDatasLight', $compilerDir, 'flash.display.Sprite', explode(';', AS3_SOURCES), MXMLC_PATH, 10, 30, 800, 600, $debug); - - $filesToCopy = array(); - $this->compileFlex($book_id, $complete, $compilerDir, $vdir, $filesToCopy, $book, $pages, $flex, $flexLight, $finalDir); - - $res .= $flex->compile() . "\n\n-------------------\n\n"; - $flexLight->addVariable('datasSize', filesize($compilerDir . '/FluidbookDatas.swf')); - $res .= $flexLight->compile(); - - $filesToCopy['data/fd.swf'] = $compilerDir . '/FluidbookDatas.swf'; - $filesToCopy['data/fdl.swf'] = $compilerDir . '/FluidbookDatasLight.swf'; - - // Copy of files - // Check if dest dir exists - - foreach ($filesToCopy as $local => $source) { - $localPath = $local; - $vdir->copy($source, $localPath); - } - - $workingDir = WS_BOOKS . '/working/' . $book_id . '/'; - $vdir->copyDirectory($workingDir . 'media', 'data'); - $vdir->sync(true); - - return $res; - } - - public function copy($source, $dest) - { - copy($source, $dest); - touch($dest, filemtime($source)); - } - - public static function getDocumentPage($book_id, $book_page) - { - global $core; - $dao = new wsDAOBook($core->con); - $pages = $dao->getPagesOfBook($book_id); - return $pages[$book_page]; - } - - public function compileAir($book_id) - { - $compilerDir = WS_BOOKS . '/air/' . $book_id . '/compiler'; - $finalDir = WS_BOOKS . '/air/' . $book_id . '/'; - - $book = $this->selectById($book_id); - $pages = $this->getPagesOfBook($book_id); - - $src = AS3_FLUIDBOOK_SOURCES . '/_src/'; - $lib10 = AS3_FLUIDBOOK_SOURCES . '/lib10/'; - $libs = array( - $src, - $lib10, - AS3_SOURCES, - $src . 'lib/fluidbook3dLibrary.swc', - $src . 'lib/mdm.swc', - $lib10 . 'flash.swc', - $lib10 . 'flex.swc', - $lib10 . 'framework.swc', - ); - - wsSVN::updateToLastRevision(); - - $swf = 'FluidbookAirProjector' . $book_id; - $flex = new cubeFlexCompiler($swf, $compilerDir, 'com.fluidbook.player.AIRMain', $libs, '/usr/local/flex/bin/mxmlc', 'air', 45, 800, 600, true); - - $this->compileFlex($book_id, true, $compilerDir, $finalDir, $filesToCopy, $book, $pages, $flex, $flex); - $res = $flex->compile(); - - $air = new cubeAIRCompiler($swf . '.swf', '/usr/local/flex/bin', $compilerDir, '2.0'); - $air->setApplicationDatas('com.fluidbook' . $book_id, $book->parametres->title, $book->parametres->title, cubeText::str2URL($book->parametres->title), $book->lang); - $air->setInitialWindow($book->parametres->title); - $res .= $air->compile(); - - return $res; - } - - public function compileFlex($book_id, $complete, $compilerDir, $vdir, &$filesToCopy, $book, $pages, $flex, $flexLight) - { - /* @var $vdir CubeIT_Files_VirtualDirectory */ - - cubePHP::neverStop(); - /* @var $flex cubeFlexCompiler */ - - $workingDir = WS_BOOKS . '/working/' . $book_id . '/'; - - $res = ''; - - $daoDoc = new wsDAODocument($this->con); - $firstDoc = $daoDoc->selectById($pages[1]['document_id']); - $size = $firstDoc->generalInfos['size']; - - $daoLang = new wsDAOLang($this->con); - $lang = $daoLang->selectById($book->lang); - - $langs = $daoLang->selectAll(); - - $daoTheme = new wsDAOTheme($this->con); - $theme = $daoTheme->getThemeOfBook($book_id, true); - - $daoSignature = new wsDAOSignature($this->con); - $signature = $daoSignature->selectById($book->parametres->signature); - - $exportSignature = array('main' => $signature->main, - 'mainLink' => $signature->mainLink, - 'partner' => $signature->partner, - 'partnerLink' => $signature->partnerLink); - - $index = ''; - $textes = ''; - $pageLabels = array(); - - $hash = $book_id; - $hash .= 'kjgl!az4.'; - $hash .= count($pages); - $hash .= round($size[0], 3); - - $hash = sha1($hash); - - $this->makeTextsIndexes($book, $pages, $index, $textes); - - $daoDoc->getLinksAndRulers($book_id, $links, $rulers); - - $audiodescription = array(); - - $imagesassets = array(); - $id = 1; - $ignoreLinks = array(); - foreach ($links as $id => $link) { - $links[$id]['id'] = $id; - $skipCopyAsset = false; - - if (isset($link['image']) && $link['image']) { - $workingFile = $workingDir . '/' . $link['image']; - $assetId = 'link_datas_i_' . md5($link['image']); - - if (isset($imagesassets[$assetId])) { - - } else { - if (file_exists($workingFile)) { - if ($link['page'] <= 1) { - $flexLight->addBitmap($workingFile, $assetId); - } else { - $flex->addBitmap($workingFile, $assetId); - } - } - $imagesassets[$assetId] = true; - } - } - - if ($link['type'] == 16 && $book->parametres->linkFilePrefix) { - if (!CubeIT_Util_Url::isDistant($link['to'])) { - $skipCopyAsset = true; - $links[$id]['to'] = $book->parametres->linkFilePrefix . $link['to']; - } - } - - if ($link['type'] == 15) { - if (isset($imagesassets[$id])) { - continue; - } - if ($link['page'] <= 1) { - $flexLight->addBitmap($workingDir . '/' . $link['to'], 'link_datas_' . $id); - } else { - $flex->addBitmap($workingDir . '/' . $link['to'], 'link_datas_' . $id); - } - $imagesassets[$id] = true; - } else if (in_array($link['type'], array(4, 6, 7, 9, 16, 17, 25))) { - if (!$skipCopyAsset) { - $workingFile = $workingDir . '/' . $link['to']; - if (file_exists($workingFile)) { - $filesToCopy['data/' . $link['to']] = $workingFile; - } - - if ($link['type'] == 4) { - $poster = $link['to']; - $e = explode('.', $poster); - array_pop($e); - array_push($e, 'jpg'); - $poster = implode('.', $e); - - $workingFile = $workingDir . '/' . $poster; - if (file_exists($workingFile)) { - $filesToCopy['data/' . $poster] = $workingFile; - } - } - } - } - - if ($link['type'] == 25) { - $audiodescription[$link['page']] = $link['to']; - $ignoreLinks[] = $id; - } - if ($link['type'] == 26) { - $pageLabels[$link['to']] = $link['page']; - $ignoreLinks[] = $id; - } - } - - foreach ($ignoreLinks as $ignoreLink) { - unset($links[$ignoreLink]); - } - $links = array_values($links); - - $externalsOptions = array('ongletsSWF', 'tabs2DSWF', 'externalChapters', 'externalArchives', 'ambientSound'); - foreach ($externalsOptions as $e) { - if (isset($book->parametres->$e) && $book->parametres->$e != '') { - $f = $workingDir . '/' . $book->parametres->$e; - if (file_exists($f)) { - $filesToCopy['data/' . $book->parametres->$e] = $f; - } - } - } - - $flex->addVariable('audiodescription', $audiodescription, false, true, "JSONObject"); - $flex->addVariable('pagelabels', $pageLabels, false, true, 'JSONObject'); - $flex->addVariable('links', $links, false, true, 'JSONObject'); - - $flex->addVariable('signature', $exportSignature, false, true, 'JSONObject'); - $flexLight->addVariable('datas', $book->parametres->toStandardObject(), false, true, 'JSONObject'); - $flexLight->addVariable('id', $book_id, false, true, 'uint'); - $flexLight->addVariable('cid', $book->cid, false, true, 'String'); - - $traductions = (!count($book->traductions)) ? $lang->traductions : $book->traductions; - $allTraductions = array(); - foreach ($langs as $l) { - $allTraductions[$l->lang_id] = $l->traductions; - } - - $flex->addVariable('traductions', $traductions, false, true, 'JSONObject', false); - $flex->addVariable('allTraductions', $allTraductions, false, true, 'JSONObject'); - $flex->addVariable('chapters', $book->chapters, false, true, 'JSONObject'); - $flex->addVariable('extras', '' . $book->extras . '', false, true, 'XML'); - $flex->addVariable('numerotation', $book->numerotation, false, true, 'String'); - $flexLight->addVariable('theme', $theme->parametres->toStandardObject(), false, true, 'JSONObject'); - $flexLight->addVariable('pages', $book->parametres->pages); - $flexLight->addVariable('fwidth', round($size[0], 4), false, true, 'Number'); - $flexLight->addVariable('fheight', round($size[1], 4), false, true, 'Number'); - $flexLight->addVariable('pagesInDatas', $complete, false, true, 'Boolean'); - $flex->addVariable('index', $index, false, true, 'JSONObject', false, false); - $flex->addVariable('textes', $textes, false, true, 'JSONObject', false, false); - - $rasterized = array(); - $sizes = array(); - - foreach ($pages as $i => $infos) { - $base = wsDocument::getDir($infos['document_id']) . 'p' . $infos['document_page']; - $baset = wsDocument::getDir($infos['document_id']) . 't' . $infos['document_page']; - $swffile = $base . '.swf'; - if (file_exists($swffile)) { - clearstatcache(true, $swffile); - $fsize = filesize($swffile); - } else { - $fsize = 0; - } - - if ($complete) { - $flex->addSWF($swffile, 'page' . $i); - } else { - $filesToCopy['data/p' . $i . '.swf'] = $swffile; - if ($infos['method'] >= wsDocument::BARBARE_PNM) { - $rasterized[$i] = true; - $filesToCopy['data/t' . $i . '.swf'] = $baset . '.swf'; - } else { - $rasterized[$i] = false; - } - } - - $thumb = false; - if ($book->parametres->pdfThumbnails) { - $thumb = wsPDFConvert::getThumbFromPDF($workingDir . '/' . $book->parametres->pdfThumbnails, $i); - } - if (!$thumb) { - $thumb = $base . '.jpg'; - } - - if ($i == 1) { - $flexLight->addBitmap($thumb, 'thumb1'); - } else { - $flex->addBitmap($thumb, 'thumb' . $i); - } - $sizes[$i] = $fsize; - } - - $flexLight->addVariable('rasterized', $rasterized, false, true, 'JSONObject'); - $flexLight->addVariable('sizes', $sizes, false, true, 'JSONObject'); - - if ($book->parametres->soundTheme != '') { - $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/corner-drag.mp3', 'soundDragCorner'); - $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/corner-release.mp3', 'soundReleaseCorner'); - $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/page-flip-1.mp3', 'soundPage0'); - $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/page-flip-2.mp3', 'soundPage1'); - $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/cover-flip.mp3', 'soundCover0'); - } - // Theme assets - $themeRoot = WS_THEMES . '/' . $theme->theme_id . '/'; - - if ($theme->parametres->backgroundImage != '') { - $flexLight->addBitmap($themeRoot . $theme->parametres->backgroundImage, 'background'); - } - if ($theme->parametres->menuImage != '') { - $flex->addBitmap($themeRoot . $theme->parametres->menuImage, 'menu'); - } - if ($theme->parametres->logoLoader != '') { - $flexLight->addBitmap($themeRoot . $theme->parametres->logoLoader, 'logoLoader'); - } - if ($theme->parametres->topBar != '') { - $flexLight->addBitmap($themeRoot . $theme->parametres->topBar, 'topBar'); - } - if ($theme->parametres->logo != '') { - $flex->addBitmap($themeRoot . $theme->parametres->logo, 'logo'); - } - if ($theme->parametres->afterSearch != '') { - $flex->addBitmap($themeRoot . $theme->parametres->afterSearch, 'aftersearch'); - } - if ($theme->parametres->favicon != '') { - $filesToCopy['data/fluidbook.ico'] = $themeRoot . 'fluidbook.ico'; - } - - // Icons assets - $iconsRoot = WS_ICONS . '/' . $theme->parametres->iconSet . '/'; - foreach (wsIcone::$files as $file) { - $flex->addBitmap($iconsRoot . 'nav-' . $file . '.png', 'nav_' . $file); - } - // Share icons - $iconsRoot = WS_ICONS . '/share/'; - foreach (wsIcone::$share as $file) { - $flex->addBitmap($iconsRoot . 'share-' . $file . '.png', 'share_' . $file); - } - - // Multilang - if (trim($book->parametres->multilang) != '') { - $m = str_replace("\r", "\n", trim($book->parametres->multilang)); - $langs = explode("\n", $m); - $langNames = array(); - $countryNames = array(); - $iso = l10n::getISOcodes(); - $chars = '()'; - $vuFlags = array(); - foreach ($langs as $l) { - list($mlang, $flag, $url) = explode(',', trim($l), 3); - if (!isset($vuFlags[$flag])) { - $flex->addBitmap(cubeMedia::getFlagFile($flag), 'flag_' . $flag); - $vuFlags[$flag] = true; - } - $ll = explode('-', $mlang); - $n = cubeText::ucfirst($iso[$ll[0]]); - $langNames[$mlang] = $n; - $cn = cubeCountry::getCountryName($flag, $mlang); - $countryNames[$mlang . '_' . $flag] = $cn; - $chars .= $n . $cn; - } - - $chars = preg_split('/(?addFont(WS_FILES . '/fonts/FluidbookMultilang.ttf', 'MultilangFont', $chars); - $flex->addVariable('langNames', $langNames, false, true, 'JSONObject'); - $flex->addVariable('countryNames', $countryNames, false, true, 'JSONObject'); - } - $flexLight->addVariable('lang', $book->lang); - - // Basket - if ($book->parametres->basket) { - $formats = array('jpg', 'png', 'jpeg'); - $referencesFile = self::getWorkingFile($book->parametres->basketReferences, $book_id, 'commerce'); - - if (file_exists($referencesFile) || CubeIT_Util_Url::isDistant($referencesFile)) { - $ext = CubeIT_Files::getExtension($referencesFile); - if ($ext == 'xml') { - $xml = simplexml_load_file($referencesFile); - $i = 0; - $allref = array(); - foreach ($xml->item as $item) { - $ref = (string)$item['reference']; - if (isset($allref[$ref])) { - continue; - } - $allref[$ref] = true; - foreach ($formats as $f) { - $refimage = $workingDir . 'commerce/' . $ref . '.' . $f; - if (file_exists($refimage)) { - $flex->addBitmap($refimage, "basket_image_" . $ref); - break; - } - } - $i++; - } - } elseif ($ext == 'xlsx') { - $references = wsUtil::excelToArray($referencesFile); - if ($book->parametres->customLinkClass == 'AtlanticDownloadLink') { - $references = wsUtil::atlanticReferences($references, 'local/', null, array($vdir, 'copy')); - } - $flex->addVariable('basketReferences', $references, false, true, "OrderedObject"); - } - } - if (isset($xml)) { - $flex->addVariable('basketReferences', cubeXML::condense($xml->asXML()), false, true, "String"); - } - if ($book->parametres->basketPDFBackground != '') { - $flex->addByteArray($workingDir . 'commerce/' . $book->parametres->basketPDFBackground, 'basket_pdf_background'); - } - } - // Fonts - if ($theme->parametres->fontKit == 'auto') { - if ($lang->font != 'system') { - $font = FONT_PATH . '/' . $lang->font; - $bfont = FONT_PATH . '/B' . $lang->font; - if (!file_exists($bfont)) { - $bfont = $font; - } - - $flex->addFont($bfont, 'BoldFont', $lang->charset); - $flex->addFont($font, 'GeneralFont', $lang->charset); - } - $flex->addFont(FONT_PATH . '/FluidbookCredits.ttf', 'CreditsFont', 'ASCII'); - $flexLight->addFont(FONT_PATH . '/FluidbookLoader.ttf', 'LoaderFont', 'Numerals'); - } else if ($theme->parametres->fontKit == 'vagrounded') { - $flex->addFont(FONT_PATH . '/vagrounded/VAGRoundedStd-Bold.otf', 'BoldFont', $lang->charset); - $flex->addFont(FONT_PATH . '/vagrounded/VAGRoundedStd-Light.otf', 'GeneralFont', $lang->charset); - $flex->addFont(FONT_PATH . '/FluidbookCredits.ttf', 'CreditsFont', 'ASCII'); - $flexLight->addFont(FONT_PATH . '/vagrounded/VAGRoundedStd-Bold.otf', 'LoaderFont', 'Numerals'); - } else if ($theme->parametres->fontKit == 'gill') { - $flex->addFont(FONT_PATH . '/gill/gill.ttf', 'BoldFont', $lang->charset); - $flex->addFont(FONT_PATH . '/gill/gill.ttf', 'GeneralFont', $lang->charset); - $flex->addFont(FONT_PATH . '/FluidbookCredits.ttf', 'CreditsFont', 'ASCII'); - $flexLight->addFont(FONT_PATH . '/gill/gill.ttf', 'LoaderFont', 'Numerals'); - } - - $flexLight->addVariable('checksum', $hash, false, true, 'String'); - } - - - public static function getWorkingFile($path, $book_id, $dir = "") - { - if (CubeIT_Util_Url::isDistant($path) || (substr($path, 0, 1) == '/' && file_exists($path))) { - return $path; - } - - $workingDir = WS_BOOKS . '/working/' . $book_id . '/'; - return $workingDir . trim($dir, '/') . '/' . $path; - } - - public function compileWidget($book, $pages) - { - if (!$book->parametres->widget) { - return; - } - - global $core; - - $finalDir = WS_BOOKS . '/final/' . $book->book_id . '/widget/'; - $finalWidget = $finalDir . 'miniFluidbook.swf'; - - if (!file_exists($finalDir)) { - mkdir($finalDir, 0777, true); - } - - if ($book->parametres->widgetCover) { - $file = 'miniFluidbookCouv.swf'; - } else { - $file = 'miniFluidbook.swf'; - } - $mini = WS_COMPILE_ASSETS . '/_widget/' . $file; - - $from = max(1, $book->parametres->widgetStart); - $to = min($book->parametres->widgetEnd, count($pages)); - - $swfcombine = new cubeCommandLine('swfcombine'); - $swfcombine->setPath(CONVERTER_PATH); - $swfcombine->setArg('merge'); - $swfcombine->setArg('stack1'); - $swfcombine->setArg('z'); - $swfcombine->setArg('o', $finalWidget); - $swfcombine->setArg(null, $mini); - - $tempimage = array(); - $tempswf = array(); - $timg = array(); - - for ($i = $from; $i <= $to; $i++) { - $page = $pages[$i]; - - $timg[$i] = $tempimage[$i] = cubeFiles::tempnam(); - $tempswf[$i] = cubeFiles::tempnam(); - - $it = new imageTools(); - $image = wsDocument::getDir($page['document_id']) . '/html/t150-' . $page['document_page'] . '.jpg'; - - try { - $it->loadImage($image); - $it->resize($book->parametres->widgetSize, 10000); - $it->output('jpeg', $tempimage[$i], 100); - } catch (Exception $e) { - $tempimage[$i] = $image; - } - $jpg2swf = new cubeCommandLine('jpeg2swf'); - $jpg2swf->setEnv('PATH', '/bin:/usr/bin:/usr/local/bin'); - $jpg2swf->setArg('q', $book->parametres->widgetQuality); - $jpg2swf->setArg('o', $tempswf[$i]); - $jpg2swf->setArg(null, $tempimage[$i]); - $jpg2swf->execute(); - - $swfcombine->setArg(null, $tempswf[$i]); - } - $swfcombine->execute(); - - foreach ($timg as $t) { - if (file_exists($t)) { - unlink($t); - } - } - foreach ($tempswf as $t) { - unlink($t); - } - } - - public function compileHTML5($book_id, $book, $dev = false, $delete = true) - { - $version = $book->parametres->mobileLVersion; - if ($dev) { - $version = 'dev'; - } - - $htmlCompiler = wsHTML5::compilerFactory($book_id, $version, false, 'latest', null, false, false, false, $book); - $htmlCompiler->compile($delete); - } - - /* public function indexPDF($book, $pages) { - $indexPath = WS_BOOKS . '/search/' . $book->book_id; - - Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()); - - if (file_exists($indexPath)) { - files::deltree($indexPath); - } - $index = Zend_Search_Lucene::create($indexPath); - - foreach ($pages as $i => $infos) { - $doc = new Zend_Search_Lucene_Document(); - $doc->addField(Zend_Search_Lucene_Field::Text('url', '#' . $i)); - $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', file_get_contents(wsDocument::getDir($infos['document_id']) . 'p' . $infos['document_page'] . '.txt'))); - $index->addDocument($doc); - } - - $c = $this->con->openCursor('books'); - $c->lucene_time = TIME; - $c->update('WHERE book_id=' . $book->book_id); - } */ - - public function compilePDF($book, $pages) - { - $res = wsUtil::compilePDF($book, $pages); - - $finalPDF = WS_BOOKS . '/final/' . $book->book_id . '/data/' . $book->parametres->pdfName; - if ($res) { - $this->copy($res, $finalPDF); - } - } - - public function generateCID() - { - - do { - $res = ''; - for ($i = 0; $i < 8; $i++) { - $j = rand(0, 61); - $res .= $this->base62($j); - } - $r = $this->con->select('SELECT book_id FROM books WHERE cid=\'' . $res . '\''); - if ($r->count() == 0) { - return $res; - } - } while (true); - } - - protected function base62($val) - { - $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $base = strlen($chars); - $str = ''; - do { - $i = $val % $base; - $str = $chars[$i] . $str; - $val = ($val - $i) / $base; - } while ($val > 0); - return $str; - } + public static $pagesOfBookCache = array(); + + /** + * wsDAOBook::singleton() + * + * @param mixed $r + * @return + */ + protected function singleton($r) + { + $book = new wsBook(); + $book->book_id = $r->book_id; + $book->cid = $r->cid; + $book->nom = $r->nom; + $book->lang = $r->lang; + $book->theme = $r->theme; + $book->proprietaire = $r->proprietaire_nom; + $book->proprietaire_id = $r->proprietaire_id; + $book->proprietaire_utilisateur = $r->proprietaire_utilisateur; + $book->hash = $r->hash; + $book->compteur_visites = $r->compteur_visites; + $book->status = $r->status; + $book->date_status = $r->date_status; + $book->date = $r->date; + $book->pages = array(); + $book->chapters = $r->chapters; + $book->traductions = $r->traductions; + $book->specialLinks = $r->specialLinks; + $book->specialRulers = $r->specialRulers; + $book->parametres = $r->parametres; + $book->extras = $r->extras; + $book->numerotation = $r->numerotation; + $book->changedate = $r->changedate; + $book->compiledate = $r->compiledate; + $book->compile1date = $r->compile1date; + $book->compilehtml5date = $r->compilehtml5date; + $book->facturable = $r->facturable; + $book->facturable_id = $r->facturable_id; + $book->tache = $r->tache; + if (isset($r->projet)) { + $book->projet = $r->projet; + } + $book->version = $r->version; + $book->composition_update = $r->composition_update; + $book->dir_references = $r->dir_references; + $book->dir_hosting = $r->dir_hosting; + $book->dir_macbook_phonegap_ios = $r->dir_macbook_phonegap_ios; + $book->dir_phonegap_android = $r->dir_phonegap_android; + $book->dir_external = $r->dir_external; + $book->demo_counter = $r->demo_counter; + $book->exportdatas = $r->exportdatas; + + return $book; + } + + protected function cree($r) + { + $book = new wsBook(); + $book->book_id = 'new'; + $book->nom = ''; + $book->cid = null; + $book->lang = 'fr'; + $book->theme = 1; + $book->proprietaire = ''; + $book->proprietaire_id = 0; + $book->hash = ''; + $book->compteur_visites = 20; + $book->status = 0; + $book->date_status = TIME; + $book->date = TIME; + $book->composition_update = TIME; + $book->chapters = json_encode(array()); + $book->parametres = new wsBookParametres(); + $book->tache = 0; + $book->pages = array(); + $book->version = 2; + return $book; + } + + protected function getNextId() + { + $r = $this->con->select('SELECT MAX(book_id) AS book_id FROM books'); + if ($r->book_id < 10000) { + return 10000; + } + return $r->book_id + 1; + } + + public function saveExportDatas($book_id, $datas) + { + $c = $this->con->openCursor('books'); + $c->exportdatas = json_encode($datas); + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function addDemoCount($book_id) + { + + $r = $this->con->select('SELECT demo_counter,nom FROM books WHERE book_id=\'' . $book_id . '\''); + $m = 20; + if ($r->demo_counter > 0 && $r->demo_counter % $m == 0) { + $mail = new cubeMail(); + $mail->charset = 'UTF-8'; + $mail->from = 'contact@fluidbook.com'; + $mail->to = 'tech@fluidbook.com'; + $mail->subject = '[Fluidbook Workshop] Fluidbook consulté via l\'url publique'; + $mail->body = 'Le fluidbook suivant a été consulté ' . $m . ' fois (et ' . $r->demo_counter . ' au total) via l\'url publique : ' . "\r\n" . + 'Fluidbook # ' . $book_id . ' - ' . $r->nom; + $mail->send(); + } + + $this->con->select('UPDATE books SET demo_counter=demo_counter+1 WHERE book_id=\'' . $book_id . '\''); + } + + public function selectByIds($book_ids = array(), $simple = false) + { + if ($simple) { + $table = 'books'; + } else { + $table = 'books_vue'; + } + + $ids = array(); + foreach ($book_ids as $bid) { + fb($bid); + if (intval($bid) > 0) { + $ids[] = $bid; + } + } + + $sql = 'SELECT * FROM ' . $table . ' WHERE book_id IN (' . implode(',', $ids) . ')'; + $books = $this->factory($this->con->select($sql)); + $res = array(); + foreach ($books as $book) { + $res[$book->book_id] = $book; + } + return $res; + } + + public function selectById($book_id = null, $simple = false) + { + if (is_null($book_id)) { + return $this->cree(); + } + if ($simple) { + $table = 'books'; + } else { + $table = 'books_vue'; + } + $sql = 'SELECT * FROM ' . $table . ' WHERE book_id=\'' . $this->con->escape($book_id) . '\' LIMIT 1'; + $r = $this->con->select($sql); + return $this->singleton($r); + } + + public function selectByCid($cid = null, $simple = false) + { + if ($simple) { + $table = 'books'; + } else { + $table = 'books_vue'; + } + + $sql = 'SELECT * FROM ' . $table . ' WHERE cid LIKE BINARY \'' . $this->con->escape($cid) . '\' LIMIT 1'; + $r = $this->con->select($sql); + return $this->singleton($r); + } + + public function selectLuceneToDo() + { + $sql = 'SELECT * FROM books_vue WHERE lucene_timecon->select($sql); + return $this->factory($r); + } + + public function selectLuceneTimeNotSet() + { + $sql = 'SELECT * FROM books_vue WHERE lucene_time=0 AND version=2'; + $r = $this->con->select($sql); + return $this->factory($r); + } + + /** + * wsDAOBook::sauve() + * + * @param mixed $createur + * @param mixed $data + * @return + */ + public function sauve($createur, $data) + { + $c = $this->con->openCursor('books'); + if (isset($data['nom'])) { + $c->nom = $data['nom']; + } + if (isset($data['lang'])) { + $c->lang = $data['lang']; + } + if (isset($data['theme'])) { + $c->theme = $data['theme']; + } + if (isset($data['proprietaire'])) { + $c->proprietaire = $data['proprietaire']; + } + + if ($data['book_id'] == 'new' || $data['book_id'] == '') { + $c->date = TIME; + $c->hash = md5(rand(0, 123456789365469)); + $c->compteur_visites = 20; + $c->parametres = serialize(new wsParametres()); + $c->changedate = TIME; + $book_id = $c->book_id = $this->getNextId(); + + $c->insert(); + } else { + $c->changedate = TIME; + $book_id = $data['book_id']; + $c->update('WHERE book_id=\'' . $this->con->escape($data['book_id']) . '\''); + } + + if (isset(self::$pagesOfBookCache[$book_id])) { + unset(self::$pagesOfBookCache[$book_id]); + } + + return $this->selectById($book_id); + } + + public function duplicate($book_id, $createur, $nom = null, $pages = false, $complete = false) + { + $r = $this->con->select('SELECT * FROM books_vue WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + + $old_id = $book_id; + + + $parametres = unserialize($r->parametres); + $parametres->setParent($this); + if (null === $nom) { + $nom = $parametres->title; + } + $parametres->title = $nom; + + if (!$complete) { + $parametres->pdfReplace = ''; + } + + $c = $this->con->openCursor('books'); + $c->proprietaire = $createur; + $c->date = TIME; + $c->hash = md5(rand(0, 1234567893)); + $c->cid = $this->generateCID(); + $c->compteur_visites = 20; + $c->status = -1; + $c->date_status = TIME; + $c->lang = $r->lang; + $c->parametres = serialize($parametres); + $c->nom = $nom; + $c->theme = $r->theme; + $c->changedate = TIME; + $c->compiledate = 0; + $c->version = 2; + $c->traductions = $r->traductions; + $c->specialLinks = $r->specialLinks; + $c->specialRulers = $r->specialRulers; + $c->composition_update = TIME; + $book_id = $c->book_id = $this->getNextId(); + if ($pages) { + $c->numerotation = $r->numerotation; + $c->chapters = $r->chapters; + $this->con->execute('INSERT INTO book_pages SELECT ' . $book_id . ' AS book_id,book_page,document_id,document_page FROM book_pages WHERE book_id=' . $old_id); + } + if ($complete) { + $c->numerotation = $r->numerotation; + $c->chapters = $r->chapters; + } + $c->insert(); + + $this->saveCompositionVersion($book_id); + + return $this->selectById($book_id); + } + + public function creeEmpty($createur, $lang, $nom) + { + $c = $this->con->openCursor('books'); + + $parametres = new wsBookParametres($this); + $parametres->title = $nom; + + $c->proprietaire = $createur; + $c->cid = $this->generateCID(); + $c->nom = $nom; + $c->date = TIME; + $c->hash = md5(rand(0, 1234567893)); + $c->compteur_visites = 20; + $c->status = -1; + $c->date_status = TIME; + $c->parametres = serialize($parametres); + + $c->theme = 1; + $c->lang = $lang; + $c->changedate = TIME; + $c->compiledate = 0; + $c->version = 2; + $c->composition_update = TIME; + $book_id = $c->book_id = $this->getNextId(); + $c->insert(); + return $this->selectById($book_id); + } + + public function supprime($book_id) + { + $this->con->execute('DELETE FROM book_pages_versions WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + $this->con->execute('DELETE FROM book_pages WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + return $this->con->execute('DELETE FROM books WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function count($limitedToUserRights = false) + { + $filters = $this->makeWhereFromFiltres(); + if ($filters == '1=1') { + $table = 'books'; + } else { + $table = 'books_vue'; + } + + $where = '(' . $filters . ')'; + $where .= $this->limitToUserRights($limitedToUserRights); + $r = $this->con->select('SELECT COUNT(*) AS nb FROM ' . $table . ' WHERE ' . $where); + return $r->nb; + } + + public function getPagesOfBookAt($book_id, $time) + { + $r = $this->con->select('SELECT * FROM book_pages_versions WHERE book_id=\'' . $this->con->escape($book_id) . '\' ORDER BY `update` ASC'); + if (!$r->count()) { + return $this->getPagesOfBook($book_id); + } + if ($r->count() == 1) { + $pages = unserialize($r->composition); + if (null === $pages || !count($pages)) { + return $this->getPagesOfBook($book_id); + } + return $pages; + } + + $pages = null; + while ($r->fetch()) { + if ($r->update > $time) { + + if (is_null($pages)) { + return $this->getPagesOfBook($book_id); + } + $res = unserialize($pages); + if (null === $res || !count($res)) { + return $this->getPagesOfBook($book_id); + } + return $res; + } + if (!count(unserialize($r->composition))) { + continue; + } + $pages = $r->composition; + } + + $res = unserialize($pages); + if (null === $res || !count($res)) { + return $this->getPagesOfBook($book_id); + } + return $res; + } + + public function getDocumentsToUpdate($book_id) + { + $res = array(); + $r = $this->con->select('SELECT DISTINCT d.document_id FROM book_pages b,documents d WHERE b.book_id=\'' . $this->con->escape($book_id) . '\' AND d.version=1 AND b.document_id=d.document_id'); + while ($r->fetch()) { + $res[] = $r->document_id; + } + return $res; + } + + public function getPagesOfBook($book_id, $conversion = true, $force = false) + { + if ($force || !isset(self::$pagesOfBookCache[$book_id])) { + $pages = array(); + + $sql = 'SELECT b.*,d.numberSections AS num,d.conversionInfos AS conversion,d.pages AS doc_pages,d.version AS version FROM book_pages b JOIN documents d ON d.document_id=b.document_id WHERE b.book_id=\'' . $this->con->escape($book_id) . '\' ORDER BY book_page'; + + $r = $this->con->select($sql); + while ($r->fetch()) { + $n = explode(',', $r->num); + + if (isset($n[$r->document_page - 1])) { + $num = $n[$r->document_page - 1]; + } else { + $num = ''; + } + $pages[$r->book_page] = array('document_id' => $r->document_id, + 'document_page' => $r->document_page, + 'version' => $r->version, + 'defaultNum' => $num, + 'nb_pages' => $r->doc_pages + ); + + if ($conversion) { + if ($r->conversion != '') { + $c = unserialize($r->conversion); + $c = $c->pages[$r->document_page]; + } + $qp = array('resolution', 'method', 'quality', 'objects'); + foreach ($qp as $p) { + if (isset($c) && isset($c->$p)) { + $pages[$r->book_page][$p] = $c->$p; + } + } + } + } + if (!count($pages)) { + return []; + } + + self::$pagesOfBookCache[$book_id] = $pages; + } + return self::$pagesOfBookCache[$book_id]; + } + + public function appendDocument($book_id, $document_id) + { + $r = $this->con->select('SELECT MAX(book_page) AS book_page FROM book_pages WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + $lastPage = is_null($r->book_page) ? 0 : $r->book_page; + $this->insertDocument($book_id, $lastPage, $document_id); + } + + public function removePage($book_id, $book_page) + { + // Supprime la page + $this->con->execute('DELETE FROM book_pages WHERE book_page=\'' . $this->con->escape($book_page) . '\' AND book_id=\'' . $this->con->escape($book_id) . '\''); + // Décale les pages suivantes vers le haut + $this->decalePages($book_id, $book_page, -1); + } + + public function insertPage($book_id, $after_page, $document_id, $document_page) + { + // Décale les pages vers le bas + $this->decalePages($book_id, $after_page, 1); + // Insère la page + $c = $this->con->openCursor('book_pages'); + $c->book_id = $book_id; + $c->book_page = $after_page + 1; + $c->document_id = $document_id; + $c->document_page = $document_page; + $c->insert(); + } + + public function insertDocument($book_id, $after_page, $document_id) + { + // Obtiens le book + $book = $this->selectById($book_id); + $num = explode(',', $book->numerotation); + // Obtiens le nombre de pages + $r = $this->con->select('SELECT pages,numberSections FROM documents WHERE document_id=\'' . $this->con->escape($document_id) . '\''); + // Décale les pages vers le bas + if ($after_page > 0) { + $this->decalePages($book_id, $after_page, $r->pages); + } + // Insère les pages + $c = $this->con->openCursor('book_pages'); + $c->book_id = $book_id; + $c->document_id = $document_id; + for ($i = 1; $i <= $r->pages; $i++) { + $c->document_page = $i; + $c->book_page = $after_page + $i; + $c->insert(); + } + // Mets à jour la liste des numéros des pages + $before = array_slice($num, 0, $after_page); + $after = array_slice($num, $after_page, count($num) - $after_page); + + $newnum = $r->numberSections; + if (trim($newnum, ',') == '') { + // If no number detected, we create a numeric list from 1 + $between = range(1, $r->pages); + } else { + // Else, we use numbers detected at conversion + $between = explode(',', $r->numberSections); + } + $num = array_merge($before, $between, $after); + // Mets à jour la numerotation de la publication + $c = $this->con->openCursor('books'); + $c->numerotation = implode(',', $num); + $c->composition_update = TIME; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + + $this->saveCompositionVersion($book_id); + } + + protected function decalePages($book_id, $after_page, $decalage) + { + $decalage = ($decalage >= 0) ? '+' . $decalage : $decalage; + $this->con->execute('UPDATE book_pages SET book_page=book_page' . $decalage . ' WHERE book_page>' . $this->con->escape($after_page) . ' AND book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function getListe($orderby = null, $sens = null, $limit = null, $limitedToUserRights = false) + { + if (!is_null($this->q)) { + $where = '('; + if ($this->search_id) { + $where .= ' book_id=\'' . $this->con->escape($this->q) . '\' OR '; + } + + if (!cubeMath::is_int($this->q)) { + $where .= 'nom LIKE \'%' . $this->con->escape($this->q) . '%\''; + $daoClient = new commonDAOClient($this->con); + $where .= ' OR proprietaire_id IN(' . $daoClient->querySearchByName($this->q) . ') OR '; + } + $limit = null; + $where .= '1=2)'; + } else { + $where = '(' . $this->makeWhereFromFiltres() . ')'; + } + $where .= $this->limitToUserRights($limitedToUserRights); + + $orderby = is_null($orderby) ? 'book_id' : $orderby; + $sens = is_null($sens) ? 'DESC' : $sens; + $limit = is_null($limit) ? '' : $this->con->limit($limit); + + $sql = 'SELECT * FROM books_vue WHERE ' . $where . ' ORDER BY ' . $orderby . ' ' . $sens . ' ' . $limit; + $r = $this->con->select($sql); + return $this->factory($r); + } + + protected function limitToUserRights($utilisateur) + { + if ($utilisateur) { + if (wsDroits::admin()) { + return ''; + } + return ' AND proprietaire IN (' . $utilisateur->ws_rights . ')'; + } + return ''; + } + + protected function makeWhereFromFiltres() + { + if (!is_null($this->filtres)) { + $w = array('1=1'); + if (commonFiltre::test('admin_book', $this->filtres)) { + $w[] = 'super_admin IN (' . implode(',', array_keys($this->filtres['admin_book'])) . ')'; + } + if (commonFiltre::test('status_book', $this->filtres)) { + $w[] = 'status IN(' . implode(',', array_keys($this->filtres['status_book'])) . ')'; + } + if (commonFiltre::test('revendeur_book', $this->filtres)) { + $v = array_keys($this->filtres['revendeur_book']); + $values = array(); + foreach ($v as $r) { + $values[] = $this->con->escape($r); + } + + + $w[] = 'facturable IN(\'' . implode('\',\'', $values) . '\')'; + } + return implode(' AND ', $w); + } else { + return '1=1'; + } + } + + public function setChapters($book_id, $json) + { + $chapters = json_decode($json, true); + $res = array(); + + foreach ($chapters as $c) { + $c['label'] = trim($c['label']); + $n = (string)$c['page']; + $c['label'] = trim(preg_replace('|\s+' . $n . '$|iu', '', $c['label'])); + $res[] = $c; + } + + $json_chapters = json_encode($res); + + $c = $this->con->openCursor('books'); + $c->chapters = $json_chapters; + $c->changedate = TIME; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + + if ($json_chapters && $json_chapters != '[]') { + if (count($res) == 1) { + if ($res[0]['label'] == '' && $res[0]['page'] == '') { + return; + } + } + $c = $this->con->openCursor('books_chapters_versions'); + $c->book_id = $book_id; + $c->chapters = $json_chapters; + $c->time = TIME; + $c->insert(); + } + } + + public function setSpecialLinksAndRulers($book_id, $links, $rulers) + { + $c1 = $this->con->openCursor('special_links_versions'); + $c = $this->con->openCursor('books'); + + if (is_string($links)) { + $links = json_encode(json_decode($links, false)); + } + if (is_string($rulers)) { + $rulers = json_encode(json_decode($rulers, false)); + } + + + $links = wsLinks::encryptLinks(json_decode($links)); + + + if (is_array($links)) { + $links = json_encode($links); + } + if (is_array($rulers)) { + $rulers = json_encode($rulers); + } + + $c1->links = $c->specialLinks = $links; + $c1->rulers = $c->specialRulers = $rulers; + $c1->update = $c->changedate = TIME; + $c1->book_id = $book_id; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + try { + $c1->insert(); + } catch (Exception $e) { + try { + $c1->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\' AND `update`=' . TIME); + } catch (Exception $e) { + + } + } + } + + public function setTheme($book_id, $theme) + { + $c = $this->con->openCursor('books'); + $c->theme = $theme; + $c->changedate = TIME; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function setStatus($book_id, $status) + { + $c = $this->con->openCursor('books'); + if ($status < 2) { + $c->tache = 0; + } + $c->status = $status; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + return $this->selectById($book_id); + } + + public function setChaptersFromOldFluidbook($book_id) + { + $book = $this->selectById($book_id); + $n = explode(',', $book->numerotation); + + $xml = simplexml_load_file('https://ws.fluidbook.com/books/' . $book_id . '/data/links.xml'); + $res = array(); + $chapters = $xml->xpath('//chapters'); + foreach ($chapters as $ch) { + $c = array(); + $c['label'] = (string)$ch->txt; + + $p = intval((string)$ch->page); + if ($p <= 0) { + continue; + } + $c['page'] = $n[$p]; + $c['level'] = intval((string)$ch->level); + $res[] = $c; + } + + $c = $this->con->openCursor('books'); + $c->chapters = json_encode($res); + $c->changedate = TIME; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function saveCompositionVersion($book_id, $time = null) + { + $time = is_null($time) ? TIME : $time; + + $pages = $this->getPagesOfBook($book_id, true, true); + + $c = $this->con->openCursor('book_pages_versions'); + $c->update = $time; + $c->book_id = $book_id; + $c->composition = serialize($pages); + $c->insert(); + } + + public function setLang($book_id, $base, $traductions) + { + // Cleanup user translations + $traductions = json_decode($traductions, true); + foreach ($traductions as $k => $v) { + $traductions[$k] = $v; + } + + $daoLang = new wsDAOLang($this->con); + $lang = $daoLang->selectById($base); + // Cleanup base translations + $baseTraductions = $lang->traductions; + foreach ($baseTraductions as $k => $v) { + $baseTraductions[$k] = $v; + } + // Then compare them. If there is no differences, we don't save translations in the book + if ($traductions == $baseTraductions) { + $t = ''; + } else { + $t = json_encode($traductions); + } + + $c = $this->con->openCursor('books'); + $c->lang = $base; + $c->traductions = $t; + $c->changedate = TIME; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function setSettings($book_id, $settings) + { + $book = $this->selectById($book_id); + $parametres = $book->parametres; + $new = $settings; + $root = ['lang', 'proprietaire_id', 'status']; + $rootSettings = []; + foreach ($new as $k => $v) { + if ($k == '_empty_') { + continue; + } + if (in_array($k, $root)) { + $rootSettings[$k] = $v; + } else { + try { + $parametres->$k = $v; + } catch (Exception $e) { + + } + } + } + + + $ip = array(); + if (isset($parametres->stats_exclude_ip) && trim($parametres->stats_exclude_ip) != '') { + $list = $parametres->stats_exclude_ip; + $list = str_replace("\r", "\n", $list); + $e = explode("\n", $list); + foreach ($e as $i) { + $i = trim($i); + if ($i == '') { + continue; + } + $long = ip2long($i); + if ($long !== false) { + $ip[] = $long; + } + } + } + + $file = '/home/stats/www/exclude/' . $book_id; + + if (count($ip)) { + file_put_contents($file, implode(',', $ip)); + chmod($file, 0777); + chown($file, 'stats'); + } else if (file_exists($file)) { + unlink($file); + } + + $c = $this->con->openCursor('books'); + $c->nom = $parametres->title; + $c->parametres = serialize($parametres); + $c->changedate = TIME; + foreach ($rootSettings as $k => $v) { + $c->$k = $v; + } + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function setProprietaire($book_id, $proprietaire_id) + { + $c = $this->con->openCursor('books'); + $c->proprietaire = $proprietaire_id; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function setTache($book_id, $tache) + { + $c = $this->con->openCursor('books'); + $c->tache = $tache; + $c->status = 2; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function setVersion($book_id, $version) + { + $c = $this->con->openCursor('books'); + $c->version = $version; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function touch($book_id) + { + $c = $this->con->openCursor('books'); + $c->changedate = TIME; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function touchCompile($book_id, $version = 'all') + { + $c = $this->con->openCursor('books'); + if ($version == '2') { + $c->compiledate = TIME; + } elseif ($version == '1') { + $c->compile1date = TIME; + } elseif ($version == 'html5') { + $c->compilehtml5date = TIME; + } else { + $c->compiledate = TIME; + $c->compile1date = TIME; + $c->compilehtml5date = TIME; + } + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function isUpToDate($book, $version) + { + $version = (string)$version; + if ($version == '2') { + if (!file_exists(WS_BOOKS . '/final/' . $book->book_id)) { + return false; + } + if ($book->compiledate < $book->changedate) { + return false; + } + } else if ($version == '1') { + // V1 + if (!file_exists(WS_BOOKS . '/finalv1/' . $book->book_id . '/index.swf')) { + return false; + } + if ($book->compile1date < $book->changedate) { + return false; + } + } else if ($version == 'html5') { + return false; + // HTML5 + $checks = array($book->changedate, cubeFiles::filemtimeRecursive(WS_BOOKS . '/working/' . $book->book_id), cubeFiles::filemtimeRecursive(WS_COMPILE_ASSETS . '/_html5'), cubeFiles::filemtimeRecursive(ROOT . '/inc/ws/Util/html5')); + foreach ($checks as $check) { + if ($check > $book->compilehtml5date) { + return false; + } + } + } + return true; + } + + public function setComposition($book_id, $pages) + { + $numerotation = array(); + $nb_pages = 0; + foreach ($pages as $p) { + $numerotation[] = $p->virtual; + $nb_pages++; + } + + $book = $this->selectById($book_id); + $parametres = $book->parametres; + $parametres->pages = $nb_pages; + + $c = $this->con->openCursor('books'); + $c->parametres = serialize($parametres); + $c->numerotation = implode(',', $numerotation); + $c->changedate = TIME; + + // Check if composition need to be updated + $r = $this->con->select('SELECT * FROM book_pages WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + $tab = array(); + $now = array(); + $ref = array(); + while ($r->fetch()) { + $ref[$r->book_page] = array((int)$r->document_id, (int)$r->document_page); + } + $i = 1; + foreach ($pages as $p) { + $now[$i] = array((int)$p->document_id, (int)$p->document_page); + $i++; + } + if ($now != $ref) { + $this->con->execute('DELETE FROM book_pages WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + + $c1 = $this->con->openCursor('book_pages'); + $c1->book_id = $book_id; + $i = 1; + foreach ($pages as $p) { + $c1->document_id = $p->document_id; + $c1->document_page = $p->document_page; + $c1->book_page = $i; + $c1->insert(); + $i++; + } + $c->composition_update = TIME; + $this->saveCompositionVersion($book_id); + } + + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function setInstallDir($book_id, $dir, $server) + { + $col = 'dir_' . $server; + + $c = $this->con->openCursor('books'); + $c->$col = $dir; + $c->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\''); + } + + public function makeTextsIndexes($book, $pages, &$index, &$textes, $simple = false) + { + global $core; + $prefix = ''; + if ($book->parametres->textExtraction == 'poppler') { + $prefix = 'p'; + } else if ($book->parametres->textExtraction == 'fluidbook') { + $prefix = 'f'; + } + + $dir = WS_BOOKS . '/index/' . $book->book_id; + if ($book->parametres->ignoreSearchSeparators != '') { + $dir .= '/' . sha1($book->parametres->ignoreSearchSeparators); + } + if (!file_exists($dir)) { + mkdir($dir, 0777, true); + } + + if ($simple) { + $ifilec = $dir . '/' . $prefix . 'sindex.json'; + } else { + $ifilec = $dir . '/' . $prefix . 'index.json'; + } + $tfilec = $dir . '/' . $prefix . 'textes.json'; + + if (CubeIT_Util_Gzip::file_exists($ifilec) && CubeIT_Util_Gzip::file_exists($tfilec) && (min(CubeIT_Util_Gzip::filemtime($ifilec), CubeIT_Util_Gzip::filemtime($tfilec)) >= max($book->composition_update, filemtime(__FILE__), filemtime(WS_TOOLS . '/fwstk/out/artifacts/fwstk_jar/fwstk.jar')))) { + $index = CubeIT_Util_Gzip::file_get_contents($ifilec); + $textes = CubeIT_Util_Gzip::file_get_contents($tfilec); + return; + } + + if ($book->parametres->ignoreSearchSeparators != "") { + $docs = array(); + foreach ($pages as $p => $i) { + $docs[] = $i['document_id']; + } + $docs = array_unique($docs); + + foreach ($docs as $doc) { + $out = wsDocument::getDir($doc); + + $fwstk = new cubeCommandLine('fwstk.sh'); + $fwstk->setPath(CONVERTER_PATH); + $fwstk->setArg('--input ' . $out . '/crop.pdf'); + $fwstk->setArg('--extractTexts ' . $out . '%s%d.txt'); + $fwstk->setArg('--extractTextsMethod ' . $book->parametres->textExtraction); + $fwstk->setArg('--threads 1'); + $fwstk->setArg('--ignoreSeparators ' . $book->parametres->ignoreSearchSeparators); + $fwstk->execute(); + } + } + + $index = array(); + $textes = array(); + foreach ($pages as $book_page => $infos) { + $tfile = wsDocument::getDir($infos['document_id']) . $prefix . 'p' . $infos['document_page'] . '.txt'; + $ifile = wsDocument::getDir($infos['document_id']) . $prefix . 'i' . $infos['document_page'] . '.txt'; + + if (!file_exists($tfile) || !file_exists($ifile)) { + $daoDoc = new wsDAODocument($core->con); + $out = wsDocument::getDir($infos['document_id']); + + $fwstk = new cubeCommandLine('fwstk.sh'); + $fwstk->setPath(CONVERTER_PATH); + $fwstk->setArg('--input ' . $out . '/crop.pdf'); + $fwstk->setArg('--extractTexts ' . $out . '%s%d.txt'); + $fwstk->setArg('--extractTextsMethod ' . $book->parametres->textExtraction); + if ($book->parametres->ignoreSearchSeparators != '') { + $fwstk->setArg('--ignoreSeparators ' . $book->parametres->ignoreSearchSeparators); + } + $fwstk->setArg('--threads 1'); + $fwstk->execute(); + } + + CubeIT_Util_Gzip::compressIfNotCompressed($tfile); + CubeIT_Util_Gzip::compressIfNotCompressed($ifile); + $text = CubeIT_Util_Gzip::file_get_contents($tfile); + $ipage = CubeIT_Util_Gzip::file_get_contents($ifile); + + if ($simple) { + $this->fillIndexWithWordsSimple($index, $book_page, $ipage); + } else { + $this->fillIndexWithWords($index, $book_page, $ipage); + } + $textes[$book_page] = $text; + } + ksort($index); + + $textes = json_encode($textes); + $index = json_encode($index); + + CubeIT_Util_Gzip::file_put_contents($tfilec, $textes); + CubeIT_Util_Gzip::file_put_contents($ifilec, $index); + } + + public function makeHighlightIndex($book, $pages) + { + $jar = WS_TOOLS . '/fwstk/out/artifacts/fwstk_jar/fwstk.jar'; + + $daoDoc = new wsDAODocument($this->con); + $res = new stdClass(); + foreach ($pages as $book_page => $infos) { + $fby = wsDocument::getDir($infos['document_id']) . 'html/p' . $infos['document_page'] . '.fby'; + // Refresh highlight data if fby file doesn't exists or if fwstk has been updated + $fbymtime = @filemtime($fby); + if (!file_exists($fby) || filemtime($jar) > $fbymtime || filemtime(__FILE__) > $fbymtime) { + $doc = $daoDoc->selectById($infos['document_id']); + $doc->getHighlightTextsData(); + } + + if (file_exists($fby)) { + $words = CubeIT_Util_Json::decode(file_get_contents($fby), CubeIT_Util_Json::TYPE_OBJECT); + + if (is_array($words)) { + foreach ($words as $i => $w) { + $word = $w->word; + $word = trim($word, "\0"); + if ($word == '') { + continue; + } + unset($w->word); + $w->page = $book_page; + $w->idx = $i; + if (!isset($res->{$word})) { + $res->{$word} = array(); + } + $res->{$word}[] = $w; + } + } + } + } + return $res; + } + + protected function _escapeIndex($str) + { + $todelete = array('\ufffd'); + foreach ($todelete as $d) { + $str = str_replace($d, '', $str); + } + return $str; + } + + protected function fillIndexWithWordsSimple(&$index, $page, $ipage) + { + $twords = explode("\n", trim($ipage)); + + foreach ($twords as $woadata) { + $w1 = explode(',', trim($woadata)); + if (count($w1) <= 1) { + continue; + } + list($woa, $worddata) = $w1; + $e = explode("\t", $worddata, 2); + if (count($e) < 2) { + continue; + } + list($total, $wordslist) = $e; + + if ($woa == '') { + continue; + } + + if (!isset($index[$woa])) { + $index[$woa] = array('t' => 0, 'p' => array()); + } + $index[$woa]['t'] += $total; + + $words = explode("\t", $wordslist); + foreach ($words as $word) { + list($wordwa, $count) = explode('$', $word, 2); + if (!isset($index[$woa]['p'][$page])) { + $index[$woa]['p'][$page] = 0; + } + $index[$woa]['p'][$page] += $count; + } + } + } + + protected function fillIndexWithWords(&$index, $page, $ipage) + { + $twords = explode("\n", trim($ipage)); + + foreach ($twords as $woadata) { + $w1 = explode(',', trim($woadata)); + if (count($w1) <= 1) { + continue; + } + list($woa, $worddata) = $w1; + $e = explode("\t", $worddata, 2); + if (count($e) < 2) { + continue; + } + list($total, $wordslist) = $e; + + if ($woa == '') { + continue; + } + + if (!isset($index[$woa])) { + $index[$woa] = array('t' => 0, 'w' => array()); + } + $index[$woa]['t'] += $total; + + $words = explode("\t", $wordslist); + + foreach ($words as $word) { + list($wordwa, $count) = explode('$', $word, 2); + if (!isset($index[$woa]['w'][$wordwa])) { + $index[$woa]['w'][$wordwa] = array('t' => 0, 'p' => array()); + } + if (!isset($index[$woa]['w'][$wordwa]['p'][$page])) { + $index[$woa]['w'][$wordwa]['p'][$page] = 0; + } + $index[$woa]['w'][$wordwa]['t'] += $count; + $index[$woa]['w'][$wordwa]['p'][$page] += $count; + } + } + } + + public function getNumerotationFromDocs($book_id) + { + $pages = $this->getPagesOfBook($book_id); + } + + public function compileTemp($book_id, $version, $dir) + { + if ($version == 'ha' || $version == 'hi') { + if ($version == 'ha') { + $os = 'android'; + } elseif ($version == 'hi') { + $os = 'ios'; + } + $packager = new wsPackagerPhonegap($book_id, $dir, false, true, $os); + $packager->makePackage(false); + } + } + + public function compile($book_id, $version = 'all', $complete = false, $force = false, $dev = false, $book = null, $delete = true) + { + if (is_null($book_id) || !$book_id) { + return; + } + + $v1 = $v2 = $html5 = false; + + if ($version == 'all') { + $v1 = $v2 = $html5 = true; + } else if ($version == '1') { + $v1 = true; + } else if ($version == '2') { + $v2 = true; + } elseif ($version == 'html5') { + $html5 = true; + } + + if (null === $book) { + $book = $this->selectById($book_id); + } + $pages = $this->getPagesOfBook($book_id); + + if (!$force) { + $v1 = $v1 && !$this->isUpToDate($book, 1); + $v2 = $v2 && !$this->isUpToDate($book, 2); + $html5 = $html5 && !$this->isUpToDate($book, 'html5'); + } else { + $v1 = false; + $html5 = true; + $v2 = true; + } + + $res = ''; + if ($v1) { + fb(time(), 'Compile V1'); + $res .= $this->compile1($book_id, $book, $pages); + $this->touchCompile($book_id, '1'); + } + if ($v2) { + fb(time(), 'Compile V2'); + $res .= $this->compile3($book_id, $complete, $book, $pages); + $this->touchCompile($book_id, '2'); + } + if ($html5) { + fb(time(), 'Compile HTML5'); + $res .= $this->compileHTML5($book_id, $book, $dev, $delete); + $this->touchCompile($book_id, 'html5'); + } + if ($v1 || $v2) { + fb(time(), 'Compile PDF & Widget'); + $this->compilePDF($book, $pages); + $this->compileWidget($book, $pages); + } + + fb(time(), 'End Compile'); + return $res; + } + + public function compile1($book_id, $book, $pages) + { + $finalDir = WS_BOOKS . '/finalv1/' . $book_id . '/'; + $packager = new wsPackagerV1($book_id, $finalDir, false); + $packager->makePackage(false); + } + + public function compile3($book_id, $complete, $book, $pages) + { + $res = ''; + + $compilerDir = WS_BOOKS . '/datasCompiler/' . $book_id . '/'; + $finalDir = WS_BOOKS . '/final/' . $book_id . '/'; + + $vdir = new CubeIT_Files_VirtualDirectory($finalDir); + + $debug = false; + + $flex = new cubeFlexCompiler('FluidbookDatas', $compilerDir, 'flash.display.Sprite', explode(';', AS3_SOURCES), MXMLC_PATH, 10, 30, 800, 600, $debug); + $flexLight = new cubeFlexCompiler('FluidbookDatasLight', $compilerDir, 'flash.display.Sprite', explode(';', AS3_SOURCES), MXMLC_PATH, 10, 30, 800, 600, $debug); + + $filesToCopy = array(); + $this->compileFlex($book_id, $complete, $compilerDir, $vdir, $filesToCopy, $book, $pages, $flex, $flexLight, $finalDir); + + $res .= $flex->compile() . "\n\n-------------------\n\n"; + $flexLight->addVariable('datasSize', filesize($compilerDir . '/FluidbookDatas.swf')); + $res .= $flexLight->compile(); + + $filesToCopy['data/fd.swf'] = $compilerDir . '/FluidbookDatas.swf'; + $filesToCopy['data/fdl.swf'] = $compilerDir . '/FluidbookDatasLight.swf'; + + // Copy of files + // Check if dest dir exists + + foreach ($filesToCopy as $local => $source) { + $localPath = $local; + $vdir->copy($source, $localPath); + } + + $workingDir = WS_BOOKS . '/working/' . $book_id . '/'; + $vdir->copyDirectory($workingDir . 'media', 'data'); + $vdir->sync(true); + + return $res; + } + + public function copy($source, $dest) + { + copy($source, $dest); + touch($dest, filemtime($source)); + } + + public static function getDocumentPage($book_id, $book_page) + { + global $core; + $dao = new wsDAOBook($core->con); + $pages = $dao->getPagesOfBook($book_id); + return $pages[$book_page]; + } + + public function compileAir($book_id) + { + $compilerDir = WS_BOOKS . '/air/' . $book_id . '/compiler'; + $finalDir = WS_BOOKS . '/air/' . $book_id . '/'; + + $book = $this->selectById($book_id); + $pages = $this->getPagesOfBook($book_id); + + $src = AS3_FLUIDBOOK_SOURCES . '/_src/'; + $lib10 = AS3_FLUIDBOOK_SOURCES . '/lib10/'; + $libs = array( + $src, + $lib10, + AS3_SOURCES, + $src . 'lib/fluidbook3dLibrary.swc', + $src . 'lib/mdm.swc', + $lib10 . 'flash.swc', + $lib10 . 'flex.swc', + $lib10 . 'framework.swc', + ); + + wsSVN::updateToLastRevision(); + + $swf = 'FluidbookAirProjector' . $book_id; + $flex = new cubeFlexCompiler($swf, $compilerDir, 'com.fluidbook.player.AIRMain', $libs, '/usr/local/flex/bin/mxmlc', 'air', 45, 800, 600, true); + + $this->compileFlex($book_id, true, $compilerDir, $finalDir, $filesToCopy, $book, $pages, $flex, $flex); + $res = $flex->compile(); + + $air = new cubeAIRCompiler($swf . '.swf', '/usr/local/flex/bin', $compilerDir, '2.0'); + $air->setApplicationDatas('com.fluidbook' . $book_id, $book->parametres->title, $book->parametres->title, cubeText::str2URL($book->parametres->title), $book->lang); + $air->setInitialWindow($book->parametres->title); + $res .= $air->compile(); + + return $res; + } + + public function compileFlex($book_id, $complete, $compilerDir, $vdir, &$filesToCopy, $book, $pages, $flex, $flexLight) + { + /* @var $vdir CubeIT_Files_VirtualDirectory */ + + cubePHP::neverStop(); + /* @var $flex cubeFlexCompiler */ + + $workingDir = WS_BOOKS . '/working/' . $book_id . '/'; + + $res = ''; + + $daoDoc = new wsDAODocument($this->con); + $firstDoc = $daoDoc->selectById($pages[1]['document_id']); + $size = $firstDoc->generalInfos['size']; + + $daoLang = new wsDAOLang($this->con); + $lang = $daoLang->selectById($book->lang); + + $langs = $daoLang->selectAll(); + + $daoTheme = new wsDAOTheme($this->con); + $theme = $daoTheme->getThemeOfBook($book_id, true); + + $daoSignature = new wsDAOSignature($this->con); + $signature = $daoSignature->selectById($book->parametres->signature); + + $exportSignature = array('main' => $signature->main, + 'mainLink' => $signature->mainLink, + 'partner' => $signature->partner, + 'partnerLink' => $signature->partnerLink); + + $index = ''; + $textes = ''; + $pageLabels = array(); + + $hash = $book_id; + $hash .= 'kjgl!az4.'; + $hash .= count($pages); + $hash .= round($size[0], 3); + + $hash = sha1($hash); + + $this->makeTextsIndexes($book, $pages, $index, $textes); + + $daoDoc->getLinksAndRulers($book_id, $links, $rulers); + + $audiodescription = array(); + + $imagesassets = array(); + $id = 1; + $ignoreLinks = array(); + foreach ($links as $id => $link) { + $links[$id]['id'] = $id; + $skipCopyAsset = false; + + if (isset($link['image']) && $link['image']) { + $workingFile = $workingDir . '/' . $link['image']; + $assetId = 'link_datas_i_' . md5($link['image']); + + if (isset($imagesassets[$assetId])) { + + } else { + if (file_exists($workingFile)) { + if ($link['page'] <= 1) { + $flexLight->addBitmap($workingFile, $assetId); + } else { + $flex->addBitmap($workingFile, $assetId); + } + } + $imagesassets[$assetId] = true; + } + } + + if ($link['type'] == 16 && $book->parametres->linkFilePrefix) { + if (!CubeIT_Util_Url::isDistant($link['to'])) { + $skipCopyAsset = true; + $links[$id]['to'] = $book->parametres->linkFilePrefix . $link['to']; + } + } + + if ($link['type'] == 15) { + if (isset($imagesassets[$id])) { + continue; + } + if ($link['page'] <= 1) { + $flexLight->addBitmap($workingDir . '/' . $link['to'], 'link_datas_' . $id); + } else { + $flex->addBitmap($workingDir . '/' . $link['to'], 'link_datas_' . $id); + } + $imagesassets[$id] = true; + } else if (in_array($link['type'], array(4, 6, 7, 9, 16, 17, 25))) { + if (!$skipCopyAsset) { + $workingFile = $workingDir . '/' . $link['to']; + if (file_exists($workingFile)) { + $filesToCopy['data/' . $link['to']] = $workingFile; + } + + if ($link['type'] == 4) { + $poster = $link['to']; + $e = explode('.', $poster); + array_pop($e); + array_push($e, 'jpg'); + $poster = implode('.', $e); + + $workingFile = $workingDir . '/' . $poster; + if (file_exists($workingFile)) { + $filesToCopy['data/' . $poster] = $workingFile; + } + } + } + } + + if ($link['type'] == 25) { + $audiodescription[$link['page']] = $link['to']; + $ignoreLinks[] = $id; + } + if ($link['type'] == 26) { + $pageLabels[$link['to']] = $link['page']; + $ignoreLinks[] = $id; + } + } + + foreach ($ignoreLinks as $ignoreLink) { + unset($links[$ignoreLink]); + } + $links = array_values($links); + + $externalsOptions = array('ongletsSWF', 'tabs2DSWF', 'externalChapters', 'externalArchives', 'ambientSound'); + foreach ($externalsOptions as $e) { + if (isset($book->parametres->$e) && $book->parametres->$e != '') { + $f = $workingDir . '/' . $book->parametres->$e; + if (file_exists($f)) { + $filesToCopy['data/' . $book->parametres->$e] = $f; + } + } + } + + $flex->addVariable('audiodescription', $audiodescription, false, true, "JSONObject"); + $flex->addVariable('pagelabels', $pageLabels, false, true, 'JSONObject'); + $flex->addVariable('links', $links, false, true, 'JSONObject'); + + $flex->addVariable('signature', $exportSignature, false, true, 'JSONObject'); + $flexLight->addVariable('datas', $book->parametres->toStandardObject(), false, true, 'JSONObject'); + $flexLight->addVariable('id', $book_id, false, true, 'uint'); + $flexLight->addVariable('cid', $book->cid, false, true, 'String'); + + $traductions = (!count($book->traductions)) ? $lang->traductions : $book->traductions; + $allTraductions = array(); + foreach ($langs as $l) { + $allTraductions[$l->lang_id] = $l->traductions; + } + + $flex->addVariable('traductions', $traductions, false, true, 'JSONObject', false); + $flex->addVariable('allTraductions', $allTraductions, false, true, 'JSONObject'); + $flex->addVariable('chapters', $book->chapters, false, true, 'JSONObject'); + $flex->addVariable('extras', '' . $book->extras . '', false, true, 'XML'); + $flex->addVariable('numerotation', $book->numerotation, false, true, 'String'); + $flexLight->addVariable('theme', $theme->parametres->toStandardObject(), false, true, 'JSONObject'); + $flexLight->addVariable('pages', $book->parametres->pages); + $flexLight->addVariable('fwidth', round($size[0], 4), false, true, 'Number'); + $flexLight->addVariable('fheight', round($size[1], 4), false, true, 'Number'); + $flexLight->addVariable('pagesInDatas', $complete, false, true, 'Boolean'); + $flex->addVariable('index', $index, false, true, 'JSONObject', false, false); + $flex->addVariable('textes', $textes, false, true, 'JSONObject', false, false); + + $rasterized = array(); + $sizes = array(); + + foreach ($pages as $i => $infos) { + $base = wsDocument::getDir($infos['document_id']) . 'p' . $infos['document_page']; + $baset = wsDocument::getDir($infos['document_id']) . 't' . $infos['document_page']; + $swffile = $base . '.swf'; + if (file_exists($swffile)) { + clearstatcache(true, $swffile); + $fsize = filesize($swffile); + } else { + $fsize = 0; + } + + if ($complete) { + $flex->addSWF($swffile, 'page' . $i); + } else { + $filesToCopy['data/p' . $i . '.swf'] = $swffile; + if ($infos['method'] >= wsDocument::BARBARE_PNM) { + $rasterized[$i] = true; + $filesToCopy['data/t' . $i . '.swf'] = $baset . '.swf'; + } else { + $rasterized[$i] = false; + } + } + + $thumb = false; + if ($book->parametres->pdfThumbnails) { + $thumb = wsPDFConvert::getThumbFromPDF($workingDir . '/' . $book->parametres->pdfThumbnails, $i); + } + if (!$thumb) { + $thumb = $base . '.jpg'; + } + + if ($i == 1) { + $flexLight->addBitmap($thumb, 'thumb1'); + } else { + $flex->addBitmap($thumb, 'thumb' . $i); + } + $sizes[$i] = $fsize; + } + + $flexLight->addVariable('rasterized', $rasterized, false, true, 'JSONObject'); + $flexLight->addVariable('sizes', $sizes, false, true, 'JSONObject'); + + if ($book->parametres->soundTheme != '') { + $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/corner-drag.mp3', 'soundDragCorner'); + $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/corner-release.mp3', 'soundReleaseCorner'); + $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/page-flip-1.mp3', 'soundPage0'); + $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/page-flip-2.mp3', 'soundPage1'); + $flex->addSound(WS_SOUNDS . '/' . $book->parametres->soundTheme . '/cover-flip.mp3', 'soundCover0'); + } + // Theme assets + $themeRoot = WS_THEMES . '/' . $theme->theme_id . '/'; + + if ($theme->parametres->backgroundImage != '') { + $flexLight->addBitmap($themeRoot . $theme->parametres->backgroundImage, 'background'); + } + if ($theme->parametres->menuImage != '') { + $flex->addBitmap($themeRoot . $theme->parametres->menuImage, 'menu'); + } + if ($theme->parametres->logoLoader != '') { + $flexLight->addBitmap($themeRoot . $theme->parametres->logoLoader, 'logoLoader'); + } + if ($theme->parametres->topBar != '') { + $flexLight->addBitmap($themeRoot . $theme->parametres->topBar, 'topBar'); + } + if ($theme->parametres->logo != '') { + $flex->addBitmap($themeRoot . $theme->parametres->logo, 'logo'); + } + if ($theme->parametres->afterSearch != '') { + $flex->addBitmap($themeRoot . $theme->parametres->afterSearch, 'aftersearch'); + } + if ($theme->parametres->favicon != '') { + $filesToCopy['data/fluidbook.ico'] = $themeRoot . 'fluidbook.ico'; + } + + // Icons assets + $iconsRoot = WS_ICONS . '/' . $theme->parametres->iconSet . '/'; + foreach (wsIcone::$files as $file) { + $flex->addBitmap($iconsRoot . 'nav-' . $file . '.png', 'nav_' . $file); + } + // Share icons + $iconsRoot = WS_ICONS . '/share/'; + foreach (wsIcone::$share as $file) { + $flex->addBitmap($iconsRoot . 'share-' . $file . '.png', 'share_' . $file); + } + + // Multilang + if (trim($book->parametres->multilang) != '') { + $m = str_replace("\r", "\n", trim($book->parametres->multilang)); + $langs = explode("\n", $m); + $langNames = array(); + $countryNames = array(); + $iso = l10n::getISOcodes(); + $chars = '()'; + $vuFlags = array(); + foreach ($langs as $l) { + list($mlang, $flag, $url) = explode(',', trim($l), 3); + if (!isset($vuFlags[$flag])) { + $flex->addBitmap(cubeMedia::getFlagFile($flag), 'flag_' . $flag); + $vuFlags[$flag] = true; + } + $ll = explode('-', $mlang); + $n = cubeText::ucfirst($iso[$ll[0]]); + $langNames[$mlang] = $n; + $cn = cubeCountry::getCountryName($flag, $mlang); + $countryNames[$mlang . '_' . $flag] = $cn; + $chars .= $n . $cn; + } + + $chars = preg_split('/(?addFont(WS_FILES . '/fonts/FluidbookMultilang.ttf', 'MultilangFont', $chars); + $flex->addVariable('langNames', $langNames, false, true, 'JSONObject'); + $flex->addVariable('countryNames', $countryNames, false, true, 'JSONObject'); + } + $flexLight->addVariable('lang', $book->lang); + + // Basket + if ($book->parametres->basket) { + $formats = array('jpg', 'png', 'jpeg'); + $referencesFile = self::getWorkingFile($book->parametres->basketReferences, $book_id, 'commerce'); + + if (file_exists($referencesFile) || CubeIT_Util_Url::isDistant($referencesFile)) { + $ext = CubeIT_Files::getExtension($referencesFile); + if ($ext == 'xml') { + $xml = simplexml_load_file($referencesFile); + $i = 0; + $allref = array(); + foreach ($xml->item as $item) { + $ref = (string)$item['reference']; + if (isset($allref[$ref])) { + continue; + } + $allref[$ref] = true; + foreach ($formats as $f) { + $refimage = $workingDir . 'commerce/' . $ref . '.' . $f; + if (file_exists($refimage)) { + $flex->addBitmap($refimage, "basket_image_" . $ref); + break; + } + } + $i++; + } + } elseif ($ext == 'xlsx') { + $references = wsUtil::excelToArray($referencesFile); + if ($book->parametres->customLinkClass == 'AtlanticDownloadLink') { + $references = wsUtil::atlanticReferences($references, 'local/', null, array($vdir, 'copy')); + } + $flex->addVariable('basketReferences', $references, false, true, "OrderedObject"); + } + } + if (isset($xml)) { + $flex->addVariable('basketReferences', cubeXML::condense($xml->asXML()), false, true, "String"); + } + if ($book->parametres->basketPDFBackground != '') { + $flex->addByteArray($workingDir . 'commerce/' . $book->parametres->basketPDFBackground, 'basket_pdf_background'); + } + } + // Fonts + if ($theme->parametres->fontKit == 'auto') { + if ($lang->font != 'system') { + $font = FONT_PATH . '/' . $lang->font; + $bfont = FONT_PATH . '/B' . $lang->font; + if (!file_exists($bfont)) { + $bfont = $font; + } + + $flex->addFont($bfont, 'BoldFont', $lang->charset); + $flex->addFont($font, 'GeneralFont', $lang->charset); + } + $flex->addFont(FONT_PATH . '/FluidbookCredits.ttf', 'CreditsFont', 'ASCII'); + $flexLight->addFont(FONT_PATH . '/FluidbookLoader.ttf', 'LoaderFont', 'Numerals'); + } else if ($theme->parametres->fontKit == 'vagrounded') { + $flex->addFont(FONT_PATH . '/vagrounded/VAGRoundedStd-Bold.otf', 'BoldFont', $lang->charset); + $flex->addFont(FONT_PATH . '/vagrounded/VAGRoundedStd-Light.otf', 'GeneralFont', $lang->charset); + $flex->addFont(FONT_PATH . '/FluidbookCredits.ttf', 'CreditsFont', 'ASCII'); + $flexLight->addFont(FONT_PATH . '/vagrounded/VAGRoundedStd-Bold.otf', 'LoaderFont', 'Numerals'); + } else if ($theme->parametres->fontKit == 'gill') { + $flex->addFont(FONT_PATH . '/gill/gill.ttf', 'BoldFont', $lang->charset); + $flex->addFont(FONT_PATH . '/gill/gill.ttf', 'GeneralFont', $lang->charset); + $flex->addFont(FONT_PATH . '/FluidbookCredits.ttf', 'CreditsFont', 'ASCII'); + $flexLight->addFont(FONT_PATH . '/gill/gill.ttf', 'LoaderFont', 'Numerals'); + } + + $flexLight->addVariable('checksum', $hash, false, true, 'String'); + } + + + public static function getWorkingFile($path, $book_id, $dir = "") + { + if (CubeIT_Util_Url::isDistant($path) || (substr($path, 0, 1) == '/' && file_exists($path))) { + return $path; + } + + $workingDir = WS_BOOKS . '/working/' . $book_id . '/'; + return $workingDir . trim($dir, '/') . '/' . $path; + } + + public function compileWidget($book, $pages) + { + if (!$book->parametres->widget) { + return; + } + + global $core; + + $finalDir = WS_BOOKS . '/final/' . $book->book_id . '/widget/'; + $finalWidget = $finalDir . 'miniFluidbook.swf'; + + if (!file_exists($finalDir)) { + mkdir($finalDir, 0777, true); + } + + if ($book->parametres->widgetCover) { + $file = 'miniFluidbookCouv.swf'; + } else { + $file = 'miniFluidbook.swf'; + } + $mini = WS_COMPILE_ASSETS . '/_widget/' . $file; + + $from = max(1, $book->parametres->widgetStart); + $to = min($book->parametres->widgetEnd, count($pages)); + + $swfcombine = new cubeCommandLine('swfcombine'); + $swfcombine->setPath(CONVERTER_PATH); + $swfcombine->setArg('merge'); + $swfcombine->setArg('stack1'); + $swfcombine->setArg('z'); + $swfcombine->setArg('o', $finalWidget); + $swfcombine->setArg(null, $mini); + + $tempimage = array(); + $tempswf = array(); + $timg = array(); + + for ($i = $from; $i <= $to; $i++) { + $page = $pages[$i]; + + $timg[$i] = $tempimage[$i] = cubeFiles::tempnam(); + $tempswf[$i] = cubeFiles::tempnam(); + + $it = new imageTools(); + $image = wsDocument::getDir($page['document_id']) . '/html/t150-' . $page['document_page'] . '.jpg'; + + try { + $it->loadImage($image); + $it->resize($book->parametres->widgetSize, 10000); + $it->output('jpeg', $tempimage[$i], 100); + } catch (Exception $e) { + $tempimage[$i] = $image; + } + $jpg2swf = new cubeCommandLine('jpeg2swf'); + $jpg2swf->setEnv('PATH', '/bin:/usr/bin:/usr/local/bin'); + $jpg2swf->setArg('q', $book->parametres->widgetQuality); + $jpg2swf->setArg('o', $tempswf[$i]); + $jpg2swf->setArg(null, $tempimage[$i]); + $jpg2swf->execute(); + + $swfcombine->setArg(null, $tempswf[$i]); + } + $swfcombine->execute(); + + foreach ($timg as $t) { + if (file_exists($t)) { + unlink($t); + } + } + foreach ($tempswf as $t) { + unlink($t); + } + } + + public function compileHTML5($book_id, $book, $dev = false, $delete = true) + { + $version = $book->parametres->mobileLVersion; + if ($dev) { + $version = 'dev'; + } + + $htmlCompiler = wsHTML5::compilerFactory($book_id, $version, false, 'latest', null, false, false, false, $book); + $htmlCompiler->compile($delete); + } + + /* public function indexPDF($book, $pages) { + $indexPath = WS_BOOKS . '/search/' . $book->book_id; + + Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()); + + if (file_exists($indexPath)) { + files::deltree($indexPath); + } + $index = Zend_Search_Lucene::create($indexPath); + + foreach ($pages as $i => $infos) { + $doc = new Zend_Search_Lucene_Document(); + $doc->addField(Zend_Search_Lucene_Field::Text('url', '#' . $i)); + $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', file_get_contents(wsDocument::getDir($infos['document_id']) . 'p' . $infos['document_page'] . '.txt'))); + $index->addDocument($doc); + } + + $c = $this->con->openCursor('books'); + $c->lucene_time = TIME; + $c->update('WHERE book_id=' . $book->book_id); + } */ + + public function compilePDF($book, $pages) + { + $res = wsUtil::compilePDF($book, $pages); + + $finalPDF = WS_BOOKS . '/final/' . $book->book_id . '/data/' . $book->parametres->pdfName; + if ($res) { + $this->copy($res, $finalPDF); + } + } + + public function generateCID() + { + + do { + $res = ''; + for ($i = 0; $i < 8; $i++) { + $j = rand(0, 61); + $res .= $this->base62($j); + } + $r = $this->con->select('SELECT book_id FROM books WHERE cid=\'' . $res . '\''); + if ($r->count() == 0) { + return $res; + } + } while (true); + } + + protected function base62($val) + { + $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $base = strlen($chars); + $str = ''; + do { + $i = $val % $base; + $str = $chars[$i] . $str; + $val = ($val - $i) / $base; + } while ($val > 0); + return $str; + } } -- 2.39.5