From 9228e7fc56534e71dbfd9948339401a619c419fd Mon Sep 17 00:00:00 2001 From: "vincent@cubedesigners.com" Date: Thu, 29 Mar 2018 16:02:28 +0000 Subject: [PATCH] #2013 --- fluidbook/tools/fwstk/.idea/misc.xml | 1 - fluidbook/tools/fwstk/.idea/workspace.xml | 609 +-- inc/ws/DAO/class.ws.dao.book.php | 3860 +++++++++-------- inc/ws/Metier/class.ws.book.parametres.php | 1077 ++--- .../html5/master/class.ws.html5.compiler.php | 3570 +++++++-------- 5 files changed, 4553 insertions(+), 4564 deletions(-) diff --git a/fluidbook/tools/fwstk/.idea/misc.xml b/fluidbook/tools/fwstk/.idea/misc.xml index cabc5224a..ac8680147 100644 --- a/fluidbook/tools/fwstk/.idea/misc.xml +++ b/fluidbook/tools/fwstk/.idea/misc.xml @@ -229,6 +229,5 @@ - - @@ -220,32 +202,20 @@ - - - - - - - - - - - - - + - - @@ -320,25 +290,26 @@ + - - - + + + + + + + + + + - - - - - - - - + @@ -362,71 +333,27 @@ - - - - - - - - - - + + + + @@ -459,8 +411,6 @@ - - - - - - - - - - - - + - - + - + + @@ -1006,6 +922,12 @@ + + + @@ -1081,61 +1003,55 @@ + + + - - - - + + + + - - C:\Users\Vincent\AppData\Roaming\Subversion 125 @@ -1200,6 +1116,7 @@ + 1487172253077 @@ -1254,7 +1171,7 @@ - @@ -1266,41 +1183,43 @@ - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1339,7 +1258,6 @@ - - - - - - + - + - + - - - - - - + - + - + - - - - - - + - + - + - - - - - - + - + - + - + @@ -1449,7 +1347,7 @@ - + @@ -1458,7 +1356,7 @@ - + @@ -1473,142 +1371,94 @@ - + - + - - - - - + - - - - - + - - - - - + - + - - - - - - - - - - + - - + + - - + - - - - - - - - - - + - - + - + - - + + - - - - - - - - - - - - - - - - - + - - + + - - + + @@ -1619,7 +1469,7 @@ - + @@ -1630,68 +1480,89 @@ - - + - - + - + - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - - + + - + - - - + + + + + - + - - - + + - + - - - + + diff --git a/inc/ws/DAO/class.ws.dao.book.php b/inc/ws/DAO/class.ws.dao.book.php index 49d9dee7a..36ff521b1 100644 --- a/inc/ws/DAO/class.ws.dao.book.php +++ b/inc/ws/DAO/class.ws.dao.book.php @@ -1,1902 +1,1966 @@ 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, $pages = 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); - $parametres->title = $nom; - $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); - } - $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 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) { - if (!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; - } - } - } - } - - 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)); - } - - 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) { - $c1->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\' AND `update`=' . TIME); - } - } - - 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); - - $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); - - foreach ($words as $w) { - $word = $w->word; - $word = trim($word, "\0"); - if ($word == '') { - continue; - } - unset($w->word); - $w->page = $book_page; - 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) { - 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; - } - - $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); - $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) { - $version = $book->parametres->mobileLVersion; - if ($dev) { - $version = 'dev'; - } - - $htmlCompiler = wsHTML5::compilerFactory($book_id, $version); - $htmlCompiler->compile(); - } - - /* 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) { - if (substr($book->parametres->pdfName, 0, 4) == 'http') { - return; - } - if (isset($book->parametres->pdfName) && $book->parametres->pdfName != '') { - $pdfName = $book->parametres->pdfName; - } - - $cacheDir = WS_BOOKS . '/pdf/' . $book->book_id; - if (!file_exists($cacheDir)) { - mkdir($cacheDir, 0777, true); - } - - $normalPDF = $cacheDir . '/normal.pdf'; - $originalPDF = $cacheDir . '/original.pdf'; - $compressedPDF = $cacheDir . '/compressed.pdf'; - - if (file_exists($originalPDF)) { - $fmtime = filemtime($originalPDF); - if ($fmtime >= $book->composition_update) { - $invalid = false; - foreach ($pages as $i => $infos) { - $doc = wsDocument::getDir($infos['document_id']) . 'crop.pdf'; - if (filemtime($doc) > $fmtime) { - $invalid = true; - } - } - } else { - $invalid = true; - } - } else { - $invalid = true; - } - - - if ($invalid) { - $pdfList = array(); - $pagesList = array(); - $nb_pages = array(); - $j = 0; - $k = 0; - $original = true; - - foreach ($pages as $i => $infos) { - if (!isset($firstDoc)) { - $firstDoc = $infos['document_id']; - } - - $doc = wsDocument::getDir($infos['document_id']) . 'crop.pdf'; - if (!isset($pdfList[$doc])) { - $pdfList[$doc] = $j; - $nb_pages[$doc] = $infos['nb_pages']; - $k = $j; - $j++; - } else { - $k = $pdfList[$doc]; - } - $pagesList[$i] = array($k, $infos['document_page']); - - if ($i != $infos['document_page'] || $infos['document_id'] != $firstDoc) { - $original = false; - } - } - - if ($original) { - - $this->copy(wsDocument::getDir($firstDoc) . 'crop.pdf', $originalPDF); - } else { - $args = ''; - foreach ($pdfList as $doc => $index) { - $lettre = cubeMath::toPDFLetter($index, true); - $args .= $lettre . '=' . $doc . ' '; - } - - $args .= ' cat '; - - $ranges = array(); - $currentRange = null; - - foreach ($pagesList as $p) { - $lettre = cubeMath::toPDFLetter($p[0], true); - $page = $p[1]; - - // Initialise l'intervale - if (is_null($currentRange)) { - $currentRange = array('lettre' => $lettre, 'start' => $page, 'end' => $page); - continue; - } - - // Poursuit le remplissage si la lettre est identique et si la page suivante est bien la page suivante dans le document - if ($currentRange['lettre'] == $lettre && $currentRange['end'] + 1 == $page) { - $currentRange['end'] = $page; - continue; - } - - // Ajoute l'intervale à la liste finale - $ranges[] = $currentRange; - - // Réinitialise l'intervale suivant - $currentRange = array('lettre' => $lettre, 'start' => $page, 'end' => $page); - } - - // Ajoute la dernière - if (!is_null($currentRange)) { - $ranges[] = $currentRange; - } - // Si le pdf final est constitué du document complet d'un document - if (count($ranges) == 1 && $ranges[0]['start'] == 1) { - $alldocs = array_keys($pdfList); - $doc = array_pop($alldocs); - if ($nb_pages[$doc] == $ranges[0]['end']) { - $this->copy($doc, $originalPDF); - return; - } - } - - foreach ($ranges as $range) { - $args .= ' ' . $range['lettre'] . $range['start']; - if ($range['start'] == $range['end']) { - continue; - } - $args .= '-' . $range['end']; - } - - $hash = sha1($args); - - $args .= ' output ' . $originalPDF; - - $cached = WS_BOOKS . '/pdf/' . $hash . '.pdf'; - - if (file_exists($cached)) { - $this->copy($cached, $originalPDF); - } else { - $pdftk = new cubeCommandLine('pdftk'); - $pdftk->setPath(CONVERTER_PATH); - $pdftk->setManualArg($args); - $pdftk->execute(); - $this->copy($normalPDF, $cached); - } - } - } - - - if ($book->parametres->pdfReplace) { - $replace = WS_BOOKS . '/working/' . $book->book_id . '/' . $book->parametres->pdfReplace; - if (file_exists($replace)) { - if (!file_exists($normalPDF) || filemtime($normalPDF) < filemtime($replace) || filesize($normalPDF) != filesize($replace)) { - $this->copy($replace, $normalPDF); - } - } - } else { - $this->copy($originalPDF, $normalPDF); - } - $finalPDF = WS_BOOKS . '/final/' . $book->book_id . '/data/' . $book->parametres->pdfName; - - if ($book->parametres->pdfCompress) { - if (!file_exists($compressedPDF) || filemtime($compressedPDF) < filemtime($normalPDF)) { - $gs = new cubeCommandLine('gs', null, true); - $gs->setPath(CONVERTER_PATH); - $gs->setEnv('GS_FONTPATH', '/home/ws/fonts'); - $gs->setArg('-dBATCH'); - $gs->setArg('-dNOPAUSE'); - $gs->setArg('-dNOPROMPT'); - $gs->setArg('-sOutputFile=' . $compressedPDF); - $gs->setArg('-sDEVICE=pdfwrite'); - $gs->setArg('-dPDFSETTINGS=/ebook'); - $gs->setArg('-dColorImageResolution=72'); - $gs->setArg('-dAutoRotatePages=/None'); - $gs->setArg('-dColorConversionStrategy=/LeaveColorUnchanged'); - $gs->setArg(null, $normalPDF); - $gs->execute(); - } - copy($compressedPDF, $finalPDF); - } else { - copy($normalPDF, $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; - } +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, $pages = 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); + $parametres->title = $nom; + $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); + } + $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 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) + { + if (!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; + } + } + } + } + + 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)); + } + + 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) { + $c1->update('WHERE book_id=\'' . $this->con->escape($book_id) . '\' AND `update`=' . TIME); + } + } + + 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); + + $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); + + 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) + { + 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; + } + + $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); + $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) + { + $version = $book->parametres->mobileLVersion; + if ($dev) { + $version = 'dev'; + } + + $htmlCompiler = wsHTML5::compilerFactory($book_id, $version); + $htmlCompiler->compile(); + } + + /* 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) + { + if (substr($book->parametres->pdfName, 0, 4) == 'http') { + return; + } + if (isset($book->parametres->pdfName) && $book->parametres->pdfName != '') { + $pdfName = $book->parametres->pdfName; + } + + $cacheDir = WS_BOOKS . '/pdf/' . $book->book_id; + if (!file_exists($cacheDir)) { + mkdir($cacheDir, 0777, true); + } + + $normalPDF = $cacheDir . '/normal.pdf'; + $originalPDF = $cacheDir . '/original.pdf'; + $compressedPDF = $cacheDir . '/compressed.pdf'; + + if (file_exists($originalPDF)) { + $fmtime = filemtime($originalPDF); + if ($fmtime >= $book->composition_update) { + $invalid = false; + foreach ($pages as $i => $infos) { + $doc = wsDocument::getDir($infos['document_id']) . 'crop.pdf'; + if (filemtime($doc) > $fmtime) { + $invalid = true; + } + } + } else { + $invalid = true; + } + } else { + $invalid = true; + } + + + if ($invalid) { + $pdfList = array(); + $pagesList = array(); + $nb_pages = array(); + $j = 0; + $k = 0; + $original = true; + + foreach ($pages as $i => $infos) { + if (!isset($firstDoc)) { + $firstDoc = $infos['document_id']; + } + + $doc = wsDocument::getDir($infos['document_id']) . 'crop.pdf'; + if (!isset($pdfList[$doc])) { + $pdfList[$doc] = $j; + $nb_pages[$doc] = $infos['nb_pages']; + $k = $j; + $j++; + } else { + $k = $pdfList[$doc]; + } + $pagesList[$i] = array($k, $infos['document_page']); + + if ($i != $infos['document_page'] || $infos['document_id'] != $firstDoc) { + $original = false; + } + } + + if ($original) { + + $this->copy(wsDocument::getDir($firstDoc) . 'crop.pdf', $originalPDF); + } else { + $args = ''; + foreach ($pdfList as $doc => $index) { + $lettre = cubeMath::toPDFLetter($index, true); + $args .= $lettre . '=' . $doc . ' '; + } + + $args .= ' cat '; + + $ranges = array(); + $currentRange = null; + + foreach ($pagesList as $p) { + $lettre = cubeMath::toPDFLetter($p[0], true); + $page = $p[1]; + + // Initialise l'intervale + if (is_null($currentRange)) { + $currentRange = array('lettre' => $lettre, 'start' => $page, 'end' => $page); + continue; + } + + // Poursuit le remplissage si la lettre est identique et si la page suivante est bien la page suivante dans le document + if ($currentRange['lettre'] == $lettre && $currentRange['end'] + 1 == $page) { + $currentRange['end'] = $page; + continue; + } + + // Ajoute l'intervale à la liste finale + $ranges[] = $currentRange; + + // Réinitialise l'intervale suivant + $currentRange = array('lettre' => $lettre, 'start' => $page, 'end' => $page); + } + + // Ajoute la dernière + if (!is_null($currentRange)) { + $ranges[] = $currentRange; + } + // Si le pdf final est constitué du document complet d'un document + if (count($ranges) == 1 && $ranges[0]['start'] == 1) { + $alldocs = array_keys($pdfList); + $doc = array_pop($alldocs); + if ($nb_pages[$doc] == $ranges[0]['end']) { + $this->copy($doc, $originalPDF); + return; + } + } + + foreach ($ranges as $range) { + $args .= ' ' . $range['lettre'] . $range['start']; + if ($range['start'] == $range['end']) { + continue; + } + $args .= '-' . $range['end']; + } + + $hash = sha1($args); + + $args .= ' output ' . $originalPDF; + + $cached = WS_BOOKS . '/pdf/' . $hash . '.pdf'; + + if (file_exists($cached)) { + $this->copy($cached, $originalPDF); + } else { + $pdftk = new cubeCommandLine('pdftk'); + $pdftk->setPath(CONVERTER_PATH); + $pdftk->setManualArg($args); + $pdftk->execute(); + $this->copy($normalPDF, $cached); + } + } + } + + + if ($book->parametres->pdfReplace) { + $replace = WS_BOOKS . '/working/' . $book->book_id . '/' . $book->parametres->pdfReplace; + if (file_exists($replace)) { + if (!file_exists($normalPDF) || filemtime($normalPDF) < filemtime($replace) || filesize($normalPDF) != filesize($replace)) { + $this->copy($replace, $normalPDF); + } + } + } else { + $this->copy($originalPDF, $normalPDF); + } + $finalPDF = WS_BOOKS . '/final/' . $book->book_id . '/data/' . $book->parametres->pdfName; + + if ($book->parametres->pdfCompress) { + if (!file_exists($compressedPDF) || filemtime($compressedPDF) < filemtime($normalPDF)) { + $gs = new cubeCommandLine('gs', null, true); + $gs->setPath(CONVERTER_PATH); + $gs->setEnv('GS_FONTPATH', '/home/ws/fonts'); + $gs->setArg('-dBATCH'); + $gs->setArg('-dNOPAUSE'); + $gs->setArg('-dNOPROMPT'); + $gs->setArg('-sOutputFile=' . $compressedPDF); + $gs->setArg('-sDEVICE=pdfwrite'); + $gs->setArg('-dPDFSETTINGS=/ebook'); + $gs->setArg('-dColorImageResolution=72'); + $gs->setArg('-dAutoRotatePages=/None'); + $gs->setArg('-dColorConversionStrategy=/LeaveColorUnchanged'); + $gs->setArg(null, $normalPDF); + $gs->execute(); + } + copy($compressedPDF, $finalPDF); + } else { + copy($normalPDF, $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; + } } diff --git a/inc/ws/Metier/class.ws.book.parametres.php b/inc/ws/Metier/class.ws.book.parametres.php index 3e61a9f8e..fa092ad76 100644 --- a/inc/ws/Metier/class.ws.book.parametres.php +++ b/inc/ws/Metier/class.ws.book.parametres.php @@ -1,541 +1,544 @@ parent)) { - // return; - // } - - // . - $swfFilter = new stdClass(); - $swfFilter->name = __('Animation SWF') . ' (*.swf)'; - $swfFilter->extensions = '*.swf'; - - $multimediaFilter = new stdClass(); - $multimediaFilter->name = __('Archive ZIP') . ' (*.zip)'; - $multimediaFilter->extensions = '*.zip'; - - $pdfFilter = new stdClass(); - $pdfFilter->name = __('Document PDF') . ' (*.pdf)'; - $pdfFilter->extensions = '*.pdf'; - - $basketFilter = new stdClass(); - $basketFilter->name = __('Liste de produits') . ' (*.xml, *.xlsx)'; - $basketFilter->extensions = '*.xml;*.xlsx'; - - $imageFilter = new stdClass(); - $imageFilter->name = __('Images') . ' (*.jpg, *.png)'; - $imageFilter->extensions = '*.jpg;*.jpeg;*.png'; - - $epsFilter = new stdClass(); - $epsFilter->name = __('Fichier vectoriel') . ' (*.ai, *.eps)'; - $epsFilter->extensions = '*.ai;*.eps'; - - $svgFilter = new stdClass(); - $svgFilter->name = __('Fichier SVG') . ' (*.svg)'; - $svgFilter->extensions = '*.svg'; - - $imageExtraFilter = new stdClass(); - $imageExtraFilter->name = __('Images') . ' (*.svg, *.jpg, *.png, *.gif)'; - $imageExtraFilter->extensions = '*.svg;*.jpg;*.png;*.gif'; - - $soundFilter = new stdClass(); - $soundFilter->name = __('Fichier sonore') . ' (*.mp3, *.wav)'; - $soundFilter->extensions = '*.mp3;*.wav'; - - $branches = array('master : git (stable)' => 'stable', - 'master : local (dev)' => 'dev'); - $gitbranches = json_decode(file_get_contents(WS_CACHE . '/activebranches')); - foreach ($gitbranches as $b) { - if ($b == 'master') { - continue; - } - $branches[$b . ' : git'] = $b . '|git'; - $branches[$b . ' : local'] = $b . '|local'; - } - $extraVisibility = [ - __('Navigation horizontale') => 'horizontal', - __('Navigation burger') => 'burger', - __('Navigations horizontale et burger') => 'both']; - - $extraType = [ - __('Icône + Label') => 'icon', - __('Image') => 'image']; - - $this->fields['mobileLVersion'] = array('type' => 'combo', 'default' => 'stable', 'editable' => true, - 'label' => __('Version logicielle'), 'grade' => 1, - 'datas' => $branches - ); - $this->fields['mobileVersion'] = array('type' => 'combo', 'default' => 'html5-desktop', 'editable' => true, 'label' => __('Version mobile'), 'grade' => 3, - 'datas' => array(__('Rediriger vers le PDF') => 'pdf', - __('Version HTML5 recommandée (vecteurs sur desktop)') => 'html5-desktop', - __('Version HTML5 vecteurs') => 'html5', - __("Version HTML5 en images") => 'html5-images') - ); - - $this->fields['version'] = array('type' => 'combo', 'default' => '2', 'editable' => true, 'label' => __('Version'), 'datas' => array('1' => '1', '2' => '2'), 'grade' => 3); - $this->fields['title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre de la publication"), 'embed' => false); - $this->fields['url_link'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __("URL du lien de retour au site")); - $this->fields['signature'] = array('type' => 'combo', 'default' => '1', 'editable' => true, 'label' => __('Signature'), 'grade' => 3, 'datas' => wsDroits::getSignatures()); - $this->forms['important'] = array('label' => __('Description de la publication'), - 'fieldsnames' => array('version', 'mobileLVersion', 'mobileVersion', 'title', 'url_link', 'signature')); - // . - // . - - $this->fields['email_title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre de l'email") . ' "' . __('Envoyer à un ami') . '"', 'hint' => __('Laisser vide pour utiliser la valeur par défaut')); - $this->fields['email_body'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __("Corps de l'email") . ' "' . __('Envoyer à un ami') . '"', 'hint' => __('Laisser vide pour utiliser la valeur par défaut')); - $this->fields['email_editable'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Permettre au lecteur de modifier le corps de l'email")); - $this->fields['askAcknowledge'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Demander au destinataire un accusé de réception"), 'grade' => 3); - $this->fields['sendasfluidbook'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Envoyer le mail comme Fluidbook"), 'grade' => 3, 'hint' => __("L'expéditeur apparaîtra en reply-to")); - $this->fields['email_mailto'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Envoyer le mail via le client mail du visiteur (mailto:)"), 'grade' => 3); - - $this->fields['facebook_title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre du contenu partagé"), 'hint' => __('Titre proposé sur les fonction de partage (par défaut, titre de la publication)')); - $this->fields['facebook_description'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __("Description du contenu partagé"), 'grade' => 1, 'hint' => __('Description proposée sur les fonctions de partage (par défaut, vide)')); - $this->fields['twitter_description'] = array('type' => 'textarea', 'default' => '%title% : %short%', 'editable' => true, 'label' => __("Contenu Partage court"), 'hint' => __('Contenu du partagé sur les partages courts')); - $this->fields['facebook_image'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Miniature affichée'), 'fileFilter' => $imageFilter); - - $this->fields['share'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer les fonctions de partage')); - $this->fields['friend'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('E-mail')); - $this->fields['facebook'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Facebook')); - $this->fields['twitter'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Twitter')); - $this->fields['googleplus'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Google +')); - $this->fields['linkedin'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('LinkedIn')); - $this->fields['viadeo'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Viadeo')); - $this->fields['customSharer'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Classe personnalisée de partage"), 'grade' => 5); - $this->fields['friendWidth'] = array('type' => 'integer', 'default' => 319, 'editable' => true, 'label' => __('Largeur du menu'), 'grade' => 5); - $this->fields['friendHeight'] = array('type' => 'integer', 'default' => 500, 'editable' => true, 'label' => __('Largeur du menu'), 'grade' => 5); - $this->forms['share'] = array('label' => __('Fonctions de partage'), - 'fieldsnames' => array('share', '|', 'email_title', 'email_body', 'email_editable', 'askAcknowledge', 'sendasfluidbook', 'email_mailto', '|', - 'facebook_title', 'facebook_description', 'facebook_image', 'twitter_description', '|', - 'friend', 'facebook', 'twitter', 'googleplus', 'linkedin', 'viadeo', '|', 'customSharer', '|', 'friendWidth', 'friendHeight')); - // . - $this->fields['pages'] = array('type' => 'integer', 'default' => '', 'editable' => false, 'label' => __('Nombre de pages')); - $this->fields['width'] = array('type' => 'float', 'default' => '', 'editable' => false, 'label' => __('Largeur')); - $this->fields['height'] = array('type' => 'float', 'default' => '', 'editable' => false, 'label' => __('Hauteur')); - // . - $this->fields['visualisationMode'] = array('type' => 'combo', 'default' => '3', 'editable' => true, 'label' => __("Mode de visualisation 3D"), - 'datas' => array(__('Mode 3D') => '0', - __('Mode 2D (caméra fixe et pages à plat)') => '1', - __("Laisser le choix à l'utilisateur (mode 3D par défaut)") => '2', - __("Laisser le choix à l'utilisateur (mode 2D par défaut)") => '3')); - $this->fields['viewMode'] = array('type' => 'combo', 'default' => '0', 'editable' => true, 'label' => __("Mode de visualisation (beta)"), - 'datas' => array(__('Classique') => '0', - __("Diaporama") => '1'), 'grade' => 5); - $this->fields['antialiasReading'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Amélioration de la lisibilité en mode 2D")); - $this->fields['pagesBaseAngle'] = array('type' => 'integer', 'default' => '2', 'editable' => true, 'label' => __('Angle de base entre les pages'), 'grade' => 3, - 'hint' => __("0 : Publication à plat") . "\n" . __('2 : Valeur par défaut')); - $this->fields['extraXSpace'] = array('type' => 'integer', 'default' => '0', 'editable' => true, 'label' => __('Marge supplémentaire horizontale'), 'grade' => 3); - $this->fields['extraYSpace'] = array('type' => 'integer', 'default' => '0', 'editable' => true, 'label' => __('Marge supplémentaire verticale'), 'grade' => 3); - $this->fields['centerBook'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Centrer la publication sur les couvertures'), 'grade' => 2); - $this->fields['correctCenter'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Corriger les lignes blanches entre les pages'), 'grade' => 2); - $this->fields['maxResolution'] = array('type' => 'combo', 'default' => 300, 'editable' => true, 'datas' => array('300dpi' => 300, '150dpi' => 150), 'grade' => 2, 'label' => __('Résolution maximale des pages')); - $this->forms['3d_mode'] = array('label' => __('Options de visualisation'), - 'fieldsnames' => array('visualisationMode', 'antialiasReading', 'correctCenter', 'pagesBaseAngle', 'centerBook', '|', 'extraXSpace', 'extraYSpace', '|', 'viewMode', '|', 'maxResolution')); - - $this->fields['preload'] = array('type' => 'integer', 'default' => 16, 'editable' => true, 'label' => __('Nombre de pages à précharger'), 'grade' => 3); - - $this->fields['navOrder'] = array('type' => 'textarea', 'default' => 'index, chapters, search, print, friend, bookmark, pdf, archives, basket, fullscreen, sound, 3d, extra, extra1, extra2, extra3, extra4, extra5, help, lang', 'editable' => true, 'label' => __('Ordre des icônes dans la nav'), 'grade' => 3); - $this->fields['tooltipTimer'] = array('type' => 'float', 'default' => 3, "editable" => true, 'label' => __("Temps maximum d'apparition des infos-bulles (en secondes)")); - - - $this->forms['general'] = array('label' => __('Fonctionnalités générales'), - 'fieldsnames' => array('navOrder', 'tooltipTimer', 'preload', 'pages', 'width', 'height')); - //. - // - - $this->forms['menu'] = array('label' => __('Menu'), 'fieldsnames' => ['afterSearchDisplayForHTML', '|']); - $this->fields['afterSearchDisplayForHTML'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Afficher l\'image après le moteur de recherche sur la version HTML5'), 'grade' => 1); - $extraNum = 5; - for ($i = 0; $i <= $extraNum; $i++) { - if ($i > 0) { - $j = $i; - $this->fields['navExtraIcon' . $j] = array('type' => 'freefile', 'default' => '', 'editable' => true, 'label' => __('Icône supplémentaire') . ' ' . $j, 'fileFilter' => $imageExtraFilter); - $this->fields['navExtraType' . $j] = array('type' => 'combo', 'datas' => $extraType, 'default' => 'icon', 'editable' => true, 'label' => __('Type')); - $this->fields['navExtraLink' . $j] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("URL") . ' ' . $j); - $this->fields['navExtraVisibility' . $j] = array('type' => 'combo', 'datas' => $extraVisibility, 'default' => 'both', 'editable' => true, 'label' => __("Visible") . ' ' . $j); - $this->forms['menu']['fieldsnames'] = array_merge($this->forms['menu']['fieldsnames'], ['navExtraIcon' . $j, 'navExtraType' . $j, 'navExtraLink' . $j, 'navExtraVisibility' . $j, '|']); - } else { - $j = ''; - $this->fields['navExtraImage' . $j] = array('type' => 'freefile', 'default' => '', 'editable' => true, 'label' => __('Image pour navigation'), 'fileFilter' => $imageExtraFilter); - $this->fields['navExtraImageMobile' . $j] = array('type' => 'freefile', 'default' => '', 'editable' => true, 'label' => __('Image pour mobile'), 'fileFilter' => $imageExtraFilter); - $this->fields['navExtraLink' . $j] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("URL")); - $this->fields['navExtraTooltip' . $j] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Infobulle ou label")); - $this->forms['menu']['fieldsnames'] = array_merge($this->forms['menu']['fieldsnames'], ['navExtraImage' . $j, 'navExtraImageMobile' . $j, 'navExtraLink' . $j, 'navExtraTooltip' . $j, '|']); - } - } - - - $this->fields['landingPage'] = array('type' => 'freefile', 'default' => '', 'editable' => true, 'label' => __('Landing Page content'), 'grade' => 3); - $this->forms['landing'] = array('label' => __('Custom Landing Page'), 'fieldsnames' => array('landingPage')); - - - $this->fields['fullscreen'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer le mode plein-écran')); - $this->fields['fullscreenAuto'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Lancer la publication en mode plein écran (lorsque possible)')); - $this->forms['fs'] = array('label' => __('Plein écran'), - 'fieldsnames' => array('fullscreen', 'fullscreenAuto')); - - - $this->fields['bookmark'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer les marques-pages')); - $this->fields['bookmarkSendEnable'] = array('type' => 'boolean', 'default' => 'true', 'editable' => true, 'label' => __("Activer l'envoi des marques-pages par e-mail")); - $this->fields['bookmark_email_title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre de l'email") . ' "' . __('Envoyer à un ami') . '"', 'hint' => __('Laisser vide pour utiliser la valeur par défaut')); - $this->fields['bookmark_email_body'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __("Corps de l'email") . ' "' . __('Envoyer à un ami') . '"', 'hint' => __('Laisser vide pour utiliser la valeur par défaut')); - $this->fields['bookmarkCornerSize'] = array('type' => 'integer', 'default' => 8, 'editable' => true, 'label' => __("Taille des marques-pages"), 'hint' => __('Taille relative à la largeur de la page')); - $this->fields['bookmarkOffset'] = array('type' => 'integer', 'default' => 0, 'editable' => true, 'label' => __("Décaler de x pixels vers l'intérieur")); - $this->fields['bookmarkBlinkOnPageChange'] = array('type' => 'boolean', 'default' => 'false', 'editable' => true, 'label' => __('Faire clignoter le marque page à l\'apparition de la page')); - $this->fields['bookmarkUsePDF'] = array('type' => 'combo', 'default' => 'pages', 'editable' => true, 'label' => __('PDF à utiliser pour l\'envoi ou le téléchargement de pages marquées'), - 'datas' => [__('PDF des pages') => 'pages', - __('PDF de remplacement') => 'download', - __('PDF des miniatures') => 'thumbnails']); - $this->forms['bookmark'] = array('label' => __('Marques-pages'), - 'fieldsnames' => array('bookmark', '|', 'bookmarkSendEnable', 'bookmark_email_title', 'bookmark_email_body', '|', 'bookmarkCornerSize', 'bookmarkOffset', 'bookmarkBlinkOnPageChange', 'bookmarkUsePDF')); - - $this->fields['help'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Activer l'aide")); - $this->fields['helpBookmarks'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Améliorer l'aide des marques-pages")); - $this->fields['helpStartup'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Afficher l'aide au démarrage")); - $this->fields['helpStartupTime'] = array('type' => 'integer', 'default' => 15, 'editable' => true, 'label' => __("Temps d'affichage en secondes")); - $this->fields['helpArrowTooltip'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Bulle affichée au niveau de la flèche de droite'), 'grade' => 5); - $this->forms['help'] = array('label' => __('Aide'), - 'fieldsnames' => array('help', '|', 'helpStartup', 'helpStartupTime', '|', 'helpBookmarks', '|', 'helpArrowTooltip')); - // . - // - $this->fields['indexAutoScroll'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Activer le scroll automatique')); - $this->fields['pdfThumbnails'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('PDF utilisé pour générer les miniatures'), 'grade' => 1, 'fileFilter' => $pdfFilter); - - $this->forms['index'] = array('label' => __('Index'), 'fieldsnames' => array('indexAutoScroll', 'pdfThumbnails')); - - // . - // - $this->fields['print'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Activer l'impression")); - $this->fields['printMode'] = array('type' => 'combo', 'default' => 'vector', 'editable' => true, 'label' => __("Mode d'impression"), - 'datas' => array(__('Bitmap') => 'bitmap', - __('Vectoriel') => 'vector', - __('PDF') => 'pdf')); - $this->fields['printCoverWithMarks'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Imprimer les couvertures avec les pages marquées"), 'grade' => 3); - $this->forms['print'] = array('label' => __('Impression'), - 'fieldsnames' => array('print', 'printMode', 'printCoverWithMarks')); - - - $this->fields['search'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer le moteur de recherche')); - $this->fields['highlightResults'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Surligner les résultats')); - $this->fields['highlightAllOccurences'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Surligner toutes les occurences'), 'hint' => __('Même sur les pages non considérées comme un résultat')); - $this->fields['ignoreSearch'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Mots à ignorer'), - 'hint' => __('Liste des mots à ignorer séparés par des virgules'), 'grade' => 5); - $this->fields['ignoreSearchSeparators'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Caractères à ne pas considérer comme un séparateur de mot')); - $this->fields['ignoreWordLimit'] = ['type' => 'integer', 'default' => 3, 'editable' => true, 'label' => __('Ignorer les mots de moins de X caractères')]; - $this->fields['textExtraction'] = array('type' => 'combo', 'default' => 'pdfbox', 'editable' => true, 'label' => __("Méthode d'extraction des textes"), - 'datas' => array(__('PDFBox') => 'pdfbox', - __('Poppler') => 'poppler', - __('Fluidbook (expérimentation basée sur PDFBox)') => 'fluidbook')); - $this->fields['searchShowNoResultsPages'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Afficher les pages sans résultats")); - $this->fields['searchPageSelectionAlgorithm'] = array('type' => 'combo', 'editable' => true, 'default' => 'AND', - 'datas' => [__('les double-pages qui contiennent tous les mots recherchés (ET logique)') => 'AND', __('les double-page qui contiennent un des mots recherché (OU logique)') => 'OR'], 'label' => __('Algorithme de sélection des résultats')); - $this->fields['searchWordSelectionAlgorithm'] = array('type' => 'combo', 'editable' => true, 'default' => 'begins', - 'datas' => [__('mot commençant par la requête') => 'begins', __('mot correspondant exactement à la requête') => 'exact', __('mot contenant la requête') => 'contains'], - 'label' => __('Algorithme de sélection des occurences')); - - $this->forms['search'] = array('label' => __('Moteur de recherche'), - 'fieldsnames' => array('search', '|', 'ignoreWordLimit', 'ignoreSearch', 'ignoreSearchSeparators', - '|', 'searchWordSelectionAlgorithm', 'searchPageSelectionAlgorithm', - '|', 'highlightResults', 'highlightAllOccurences', - '|', 'searchShowNoResultsPages', - '|', 'textExtraction')); - - $this->fields['soundTheme'] = array('type' => 'combo', 'default' => 'classic', 'editable' => true, 'label' => __("Thème sonore"), - 'datas' => array(__('Pas de son') => '', - __('Classique') => 'classic', - __("Papier épais") => 'heavy', - __("Papier fin") => 'light')); - $this->fields['soundOn'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Activer les effets sonores à l'ouverture")); - $this->fields['ambientSound'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Ambiance sonore'), 'grade' => 3, 'fileFilter' => $soundFilter); - $this->fields['ambientSoundVolume'] = array('type' => 'integer', 'default' => 50, 'editable' => true, - 'label' => __("Volume de l'ambiance sonore"), - 'min' => 0, 'max' => 100); - $this->forms['sound'] = array('label' => __('Effets sonores'), - 'fieldsnames' => array('soundTheme', 'soundOn', '|', 'ambientSound', 'ambientSoundVolume')); - // . - $this->fields['pdf'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Activer les fonctions de téléchargement")); - $this->fields['pdfName'] = array('type' => 'text', 'default' => 'document.pdf', 'editable' => true, 'label' => __("Nom du fichier PDF")); - $this->fields['pdfComplex'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Téchargement de PDF avancé'), "hint" => __("Permet à l'utilisateur de sélectionner les pages qu'il souhaite télécharger"), 'grade' => 3); - $this->fields['pdfCompress'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Compression du fichier PDF')); - $this->fields['pdfReplace'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('PDF de remplacement'), 'grade' => 3, 'fileFilter' => $pdfFilter); - $this->fields['offlineExport'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Téléchargement des versions offline'), "hint" => __('Valable si le téléchargement avancé est activé'), 'grade' => 3); - $this->forms['pdf'] = array('label' => __('Fonction de téléchargement'), - 'fieldsnames' => array('pdf', 'pdfName', 'pdfReplace', 'pdfCompress', 'pdfComplex', 'offlineExport')); - // . - $this->fields['zoomMode'] = array('type' => 'combo', 'default' => '0', 'editable' => true, 'label' => __("Mode de zoom"), 'grade' => 3, - 'datas' => array(__('Normal') => '0', - __('Une page') => '1', - __('Zoom désactivé') => '2')); - $this->fields['zoom'] = array('type' => 'integer', 'default' => 200, 'editable' => true, 'label' => __('Zoom par défaut (atteint au clic)')); - $this->fields['zoomw'] = array('type' => 'integer', 'default' => 300, 'editable' => true, 'label' => __("Zoom maximal (atteint à l'aide de la molette)")); - $this->forms['zoom'] = array('label' => __('Zoom'), - 'fieldsnames' => array('zoomMode', '|', 'zoom', 'zoomw')); - // . - $this->fields['stats'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer les statistiques Fluidbook'), 'grade' => 3); - $this->fields['stats_score'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Afficher les scores dans les rapports'), 'grade' => 5); - $this->fields['stats_exclude_ip'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Exclure les IP suivantes des statistiques'), 'grade' => 3, 'hint' => sprintf(__('Indiquer une adresse ip de la forme %s par ligne'), 'www.xxx.yyy.zzz')); - $this->fields['googleAnalytics'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Code Google Analytics'), 'size' => 10); - $this->fields['googleAnalyticsCustom'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Code Stats personnalisé (placé avant fermeture de head)')); - $this->fields['statsCustom'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Code Stats personnalisé (placé avant fermeture du body)')); - $this->fields['xiti'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Code XiTi global')); - $this->fields['xiti_page'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Modèle code xiti (pour tags relatifs aux pages)')); - $this->forms['stats'] = array('label' => __('Statistiques'), - 'fieldsnames' => array('stats', 'stats_score', 'stats_exclude_ip', '|', 'googleAnalytics', '|', 'googleAnalyticsCustom', 'statsCustom', '|', 'xiti', 'xiti_page')); - - $this->fields['displayChaptersPopup'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Always display chapters in a popup'), 'grade' => 1); - $this->fields['displayChaptersIcon'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Affiche l'icône du sommaire"), 'grade' => 1); - $this->fields['displayChaptersLine'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Affiche une ligne entre le label et le numéro de page"), 'grade' => 5); - $this->fields['chaptersPage'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Faire pointer le sommaire sur la page'), 'grade' => 3, 'hint' => __('Laisser vide pour utiliser le sommaire classique'), 'size' => 5); - $this->fields['displayChaptersAtStart'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Afficher le sommaire au chargement de la publication"), 'grade' => 3); - $this->fields['chaptersColumns'] = array('type' => 'integer', 'default' => 1, 'editable' => true, 'label' => __('Afficher le sommaire sur x colonne(s)'), 'grade' => 3); - $this->fields['chaptersColMaxWidth'] = array('type' => 'integer', 'default' => 300, 'editable' => true, 'label' => __("Largeur max d'une colonne"), 'grade' => 3); - $this->fields['chaptersLevelLimit'] = array('type' => 'integer', 'default' => 5, 'editable' => true, 'label' => __('Limiter à x niveaux')); - $this->fields['externalChapters'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Sommaire personnalisé'), 'grade' => 3, 'fileFilter' => $swfFilter, 'hint' => __('Laisser vide pour utiliser le sommaire classique')); - $this->fields['externalChaptersHTML'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Sommaire personnalisé (HTML5)'), 'grade' => 3, 'fileFilter' => $multimediaFilter, 'hint' => __('Laisser vide pour utiliser le sommaire classique')); - $this->fields['fullExternalChapters'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Sommaire totalement personnalisé"), 'grade' => 3, 'hint' => __('Supprime la flèche de fermeture, titre prédéfini et couleur de fond')); - $this->fields['mobileChaptersStyle'] = array('type' => 'combo', 'default' => 'classic', 'editable' => true, 'label' => __('Style des chapîtres') . ' (' . __('version mobile') . ')' - , 'datas' => array(__('Classique') => 'classic', - __('INA') => 'ina')); - - $this->fields['chaptersPosition'] = array('type' => 'combo', 'default' => 'center', 'editable' => true, 'label' => __("Position du sommaire"), - 'datas' => array(__('Centré') => 'center', - __("Aligné sur l'icône") => 'chaptersIcon')); - $this->fields['chaptersCascade'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Sommaire en cascade"), 'grade' => 3); - - $this->forms['sommaire'] = array('label' => __('Sommaire'), - 'fieldsnames' => array('displayChaptersIcon', 'displayChaptersPopup', 'displayChaptersAtStart', 'chaptersPage', 'chaptersPosition', 'chaptersLevelLimit', 'chaptersCascade', '|', 'chaptersColMaxWidth', 'chaptersColumns', 'displayChaptersLine', '|', 'externalChapters', 'fullExternalChapters', '|', 'externalChaptersHTML', '|', 'mobileChaptersStyle')); - // . - - $this->fields['ongletsXML'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('XML de configuration des onglets'), 'grade' => 5); - $this->fields['ongletsSWF'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('SWF pour onglets personnalisés'), 'grade' => 3, 'fileFilter' => $swfFilter); - - $this->fields['tabs2DSWF'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('SWF pour onglets 2D'), 'grade' => 3, 'fileFilter' => $swfFilter); - - $this->fields['tabsHTML5'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Onglets HTML5'), 'grade' => 3); - - $this->fields['flatTabsAbsolute'] = array('type' => 'boolean', 'default' => false, "editable" => true, - 'label' => __("Positionnement relatif à l'interface"), 'grade' => 5); - - $this->forms['tabs'] = array('label' => __('Onglets'), - 'fieldsnames' => array('ongletsSWF', 'ongletsXML', '|', 'tabs2DSWF', 'flatTabsAbsolute', '|', 'tabsHTML5')); - - $this->fields['customLinkClass'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Classe pour les liens personnalisés'), 'grade' => 5); - $this->fields['permanentLinks'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Liens visibles en permanence'), 'grade' => 3); - $this->fields['ignoreLinksTypes'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Ignorer les liens de type'), 'hint' => __('Liste des numéros séparés par des virgules'), 'grade' => 5); - $this->fields['linkBlinkTime'] = array('type' => 'float', 'default' => 1.0, 'editable' => true, 'label' => __("Temps d'apparition du lien à l'ouverture de la page (en secondes)")); - $this->fields['linkTooltipManager'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Gestionnaire des info-bulles"), 'grade' => 5); - $this->fields['linkTracker'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Tracking des liens'), 'grade' => 5); - $this->fields['linkTrackerRegexp'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Tracking des liens applicables aux liens du domaine'), 'grade' => 5); - $this->fields['linkFilePrefix'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Préfixer les liens de téléchargement')); - $this->fields['linkMultimediaPerformanceMode'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Mode perfomance pour les liens multimédia'), 'grade' => 5); - $this->fields['linkMultimediaQuality'] = array('type' => 'float', 'default' => 1.0, 'editable' => true, 'label' => __('Qualité de rendu des animations'), 'grade' => 5); - $this->fields['linkCornerSize'] = array('type' => 'integer', 'default' => '10', 'editable' => true, 'label' => __('Taille des liens de coins de page'), 'hint' => __("Pourcentage de la largeur de la page")); - $this->fields['linkTooltipMaxWidth'] = array('type' => 'integer', 'default' => '140', 'editable' => true, 'label' => __('Largeur max des infobulles des liens de type "infobulle"')); - $this->fields['videoReset'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Réinitialiser les vidéos après la lecture'), 'grade' => 3); - $this->fields['videoBigPlay'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Afficher le gros bouton Play'), 'grade' => 3); - $this->fields['brightcovePlayerId'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Brightcove Player Id'), 'grade' => 3); - $this->fields['brightcovePlayerSecret'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Brightcove Player Secret'), 'grade' => 3); - $this->forms['multimedia'] = array('label' => __('Liens et multimédia'), - 'fieldsnames' => array('permanentLinks', 'linkBlinkTime', 'customLinkClass', 'ignoreLinksTypes', 'linkTooltipManager', 'linkCornerSize', 'linkTooltipMaxWidth', '|', 'linkTracker', 'linkTrackerRegexp', '|', 'linkFilePrefix', '|', 'linkMultimediaPerformanceMode', 'linkMultimediaQuality', '|', 'videoReset', 'videoBigPlay', '|', 'brightcovePlayerId', 'brightcovePlayerSecret')); - //. - $this->fields['externalArchives'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Archives'), 'grade' => 3, 'fileFilter' => $imageFilter); - $this->fields['externalArchivesBack'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Image de fond'), 'grade' => 3, 'fileFilter' => $imageFilter); - $this->fields['archivesLink'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Lien'), 'grade' => 5); - $this->fields['archivesLabel'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Label'), 'grade' => 5); - - $this->forms['archives'] = array('label' => __('Archives'), - 'fieldsnames' => array('externalArchives', 'externalArchivesBack', '|', 'archivesLink', 'archivesLabel')); - // . - $this->fields['form'] = array('type' => 'combo', 'default' => '', 'editable' => true, 'grade' => 5, 'label' => __('Formulaire'), 'datas' => array(__('Aucun') => '', __('Bulle Groupe') => 'bulle')); - $this->forms['form'] = array('label' => __('Formulaire'), - 'fieldsnames' => array('form')); - - $this->fields['cookieConsent'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Message cookie')); - $this->fields['cookieConsentMessage'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Texte du consentement')); - $this->fields['cookieConsentAutoclose'] = array('type' => 'integer', 'default' => '0', 'editable' => true, 'label' => __('Masquer automatiquement après x secondes')); - $this->forms['privacy'] = array('label' => __('Respect de la vie privée'), - 'fieldsnames' => array('cookieConsent', 'cookieConsentMessage', 'cookieConsentAutoclose')); - - //. - $this->fields['basket'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Panier activé'), 'grade' => 5); - $this->fields['basketManager'] = array('type' => 'combo', 'default' => 'classic', 'editable' => true, 'label' => __("Manager de panier"), - 'datas' => array(__('Classic') => 'com.fluidbook.player.basket.BasketManager', - 'Grdf' => 'com.fluidbook.player.basket.custom.grdf.GrdfBasketManager', - 'Grdf 2013' => 'com.fluidbook.player.basket.custom.grdf.grdf2013.GrdfBasketManager2013', - 'Grdf 2015' => 'com.fluidbook.player.basket.custom.grdf.grdf2015.GrdfBasketManager2015', - 'Essilor' => 'com.fluidbook.player.basket.custom.essilor.EssilorBasketManager', - 'Essilor Recap' => 'com.fluidbook.player.basket.custom.essilorrecap.EssilorRecapBasketManager', - 'Wesco Ventes' => 'com.fluidbook.player.basket.custom.wesco.WescoBasketManager', - 'Atlantic Download' => 'com.fluidbook.player.basket.custom.atlantic.AtlanticDownloadBasketManager' - ), 'grade' => 5); - $this->fields['basketReferences'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Références produits'), 'grade' => 3, 'fileFilter' => $basketFilter, 'hint' => __('Fichier contenant les références produits'), 'dir' => 'commerce'); - $this->fields['basketImages'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Images des produits'), 'grade' => 5, 'fileFilter' => $imageFilter, 'hint' => __('Chaque image doit avoir pour nom exact la référence du produit'), - 'multiple' => true, 'dir' => 'commerce'); - $this->fields['basketPDFBackground'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Fond du PDF (bon de commande)'), 'grade' => 5, 'fileFilter' => $epsFilter, 'hint' => __('Fond du bon de commande'), 'dir' => 'commerce'); - - $this->forms['basket'] = array('label' => __('Panier'), - 'fieldsnames' => array('basket', 'basketManager', 'basketReferences', 'basketImages', 'basketPDFBackground')); - // . - $this->fields['offlineLink'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __("URL du Fluidbook"), 'hint' => __('URL du fluidbook utilisée pour la version Offline (CD-ROM, clé USB, Exécutables)')); - $this->fields['offlineTitle'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre de l'application")); - $this->forms['offline'] = array('label' => __('Version offline'), - 'fieldsnames' => array('offlineTitle', 'offlineLink')); - - $this->fields['alwaysHTML5'] = array('type' => 'boolean', 'default' => 'false', 'editable' => true, 'label' => __('Toujours utiliser la version HTML5'), 'grade' => 1); - - $this->fields['html5priority'] = array('type' => 'combo', 'default' => 'true', 'editable' => true, 'label' => __("Rediriger vers la version HTML5"), 'grade' => 1, - 'datas' => array(__('Si l\'utilisateur a un appareil tactile') => 'false', - __('Si flash n\'est pas installé') => 'notinstalled', - __("Si flash n'est pas pas installé ou bloqué") => 'true')); - - $this->fields['flashBlockedWait'] = array('type' => 'float', 'default' => 1.5, 'editable' => true, 'label' => __("Temps d'attente avant de considérer flash comme bloqué")); - - - $this->fields['navOrderH'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Ordre des icônes dans la nav') . ' (' . __('Si différente') . ')', 'grade' => 3); - - $this->fields['menuBreakpoint'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Breakpoint burger menu'), 'hint' => 'Par défaut 1023px', 'grade' => 3); - - - $this->fields['mobileTransitions'] = array('type' => 'combo', 'default' => 'flip', 'editable' => true, 'label' => __('Transitions entre les pages'), 'grade' => 3, - 'datas' => array(__('Aucune transition') => 'none', - __('Glisser') => 'slide', - __('Tourner') => 'flip') - ); - $this->fields['mobileNavigationType'] = array('type' => 'combo', 'default' => 'book', 'editable' => true, 'label' => __('Mode de navigation'), 'grade' => 5, - 'datas' => array(__('Normal (automatique)') => 'book', - __('Normal (double page)') => 'landscape', - __('Normal (une page)') => 'portrait', - __('Magazine tablette') => 'tab') - ); - $this->fields['rasterizePages'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Ecraser les pages'), 'hint' => '1-3,5 = 1,2,3,5', 'grade' => 1); - $this->fields['vectorPages'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Conserver les pages en vecteur'), 'hint' => '1-3,5 = 1,2,3,5', 'grade' => 1); - - - $this->fields['mobileTransitionDuration'] = array('type' => 'float', 'default' => '0.75', 'editable' => true, 'label' => __('Durée de la transition')); - $this->fields['mobileLinksRevealAnim'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Animer les liens après un changement de page"), 'grade' => 3); - - $this->fields['mobileIconVector'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Utiliser les icônes vectorielles')); - $this->fields['mobileServerConfig'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Inclure les fichiers de configuration serveur'), 'grade' => 3); - - $this->fields['mobilePlugins'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Plugin'), 'grade' => 5); - - $this->fields['mobileVideosPath'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Chemin vers les vidéos'), 'grade' => 5); - $this->fields['mobileExtraXSpace'] = array('type' => 'integer', 'default' => '0', 'editable' => true, 'label' => __('Marge supplémentaire horizontale'), 'grade' => 3); - $this->fields['mobileNavScale'] = array('type' => 'integer', 'default' => '100', 'editable' => true, 'label' => __('Taille du menu (en %)'), 'grade' => 3); - - $this->fields['mobileIgnoreBackgroundLinks'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Ignorer les liens de background')); - - $this->forms['mobile'] = array('label' => __('Version mobile'), - 'fieldsnames' => array('alwaysHTML5', 'html5priority', 'flashBlockedWait', 'mobileNavigationType', '|', 'rasterizePages', 'vectorPages', '|', 'mobileNavScale', '|', 'mobileTransitions', 'mobileTransitionDuration', "mobileLinksRevealAnim", '|', 'menuBreakpoint', 'navOrderH', '|', 'mobileIconVector', 'mobileServerConfig', 'mobilePlugins', '|', 'mobileVideosPath', '|', 'mobileExtraXSpace', '|', 'mobileIgnoreBackgroundLinks')); - - - $this->fields['phonegapId'] = array('type' => 'text', 'default' => 'com.fluidbook.phonegap.$id', 'editable' => true, 'label' => __("Identifiant de l'identifiant"), 'grade' => 5, 'hint' => __('De la forme') . ' com.fluidbook.phonegap.xxxxx'); - $this->fields['phonegapVersion'] = array('type' => 'text', 'default' => '1.0.0', 'editable' => true, 'label' => __("Version de l'application"), 'grade' => 5, 'hint' => __('De la forme') . ' 1.2.3'); - $this->fields['phonegapPlugins'] = array('type' => 'textarea', 'default' => 'ChildBrowser', 'editable' => true, 'label' => __('Plugins Phonegap'), 'grade' => 5); - $defaultScreenshots = "P,0\nL,2\nL,index"; - $this->fields['appScreenshots'] = array('type' => 'textarea', 'default' => $defaultScreenshots, 'editable' => true, 'label' => 'Générer les screenshots', 'grade' => 5, 'hint' => __('Une ligne par vue à générer de la forme X,Y (X : P(ortrait) ou L(andscape), Y : numéro de page ou vue (1, index))')); - - $this->forms['phonegap'] = array('label' => __('Applications mobile'), - 'fieldsnames' => array('phonegapId', 'phonegapVersion', 'phonegapPlugins', 'appScreenshots')); - - $this->fields['secureURL'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __('URL de sécurisation'), 'grade' => 5, 'hint' => __('URL intérrogé pour vérifier si le visiteur à les droits pour consulter la publication')); - $this->fields['secureURLRedirect'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __('Redirection'), 'grade' => 5, 'hint' => __("Si l'authentification échoue, redirection vers cette adresse")); - $this->fields['preventRightClick'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Essayer d'empêcher le clic droit"), 'grade' => 1); - $this->forms['secure'] = array('label' => __('Sécurisation'), - 'fieldsnames' => array('secureURL', 'secureURLRedirect', '|', 'preventRightClick')); - - $this->fields['seoVersion'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Générer une version pour les moteurs de recherche')); - $this->fields['seoRobots'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Autoriser le parcours par les moteurs de recherche')); - $this->fields['seoDescription'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Meta tag Description')); - $this->fields['seoKeywords'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Meta tag Keywords')); - - $this->forms['seo'] = array('label' => __('Optimisation pour les moteurs de recherche'), - 'fieldsnames' => array('seoVersion', 'seoRobots', 'seoDescription', "seoKeywords")); - - $this->fields['home'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Accueil de l'interface multibrochure"), 'grade' => 5); - $this->fields['multilang'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Langues'), 'hint' => __('Code langue') . ',' . __('Code pays') . ',' . __('URL')); - $this->fields['country'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Pays de la brochure')); - $this->fields['multilangDisplay'] = array('type' => 'combo', 'default' => 'lang', 'editable' => true, 'label' => __('Affichage'), - 'datas' => array(__('Langue') => 'lang', - __('Langue') . ' (' . __('Pays') . ')' => 'lang_country', - __('Pays') . ' (' . __('Langue') . ')' => 'country_lang')); - $this->forms['multibrochure'] = array('label' => __('Multibrochure'), - 'fieldsnames' => array('home', 'country', 'multilangDisplay', 'multilang')); - - $this->fields['plv'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Activer le mode PLV'), 'grade' => 3); - $this->fields['plvTimer'] = array('type' => 'integer', 'min' => 1, 'max' => 60, 'default' => 5, 'editable' => true, 'label' => __('Temps'), 'grade' => 3); - $this->fields['plvMode'] = array('type' => 'combo', 'default' => 'first', 'editable' => true, 'label' => __('Arrivé à la dernière page'), 'grade' => 3, - 'datas' => array(__('Remonter vers la première page') => 'back', - __('Recommencer à la première page') => 'first')); - $this->forms['plv'] = array('label' => __('Mode PLV'), - 'fieldsnames' => array('plv', 'plvTimer', 'plvMode')); - - $this->fields['widget'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Générer le widget'), 'grade' => 3); - $this->fields['widgetCover'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Afficher la couverture') . ')', 'grade' => 3); - $this->fields['widgetSize'] = array('type' => 'integer', 'default' => 200, 'editable' => true, 'label' => __('Optimiser pour une hauteur de (en pixels)'), 'grade' => 3); - $this->fields['widgetQuality'] = array('type' => 'integer', 'default' => 85, 'min' => 0, 'max' => 100, 'editable' => true, 'label' => __('Qualité JPEG'), 'grade' => 3); - $this->fields['widgetStart'] = array('type' => 'integer', 'default' => 1, 'editable' => true, 'label' => __('Page de début'), 'grade' => 3); - $this->fields['widgetEnd'] = array('type' => 'integer', 'default' => 8, 'editable' => true, 'label' => __('Page de fin'), 'grade' => 3); - $this->forms['widget'] = array('label' => __('Widget') . ' (' . __('Mini Fluidbook') . ')', - 'fieldsnames' => array('widget', 'widgetCover', 'widgetSize', 'widgetQuality', 'widgetStart', 'widgetEnd')); - - $this->fields['extras'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Extras'), 'grade' => 3); - $this->fields['v1SWF'] = array('type' => 'freefile', 'default' => '', 'editable' => true, - 'label' => __('Index.swf spécifique'), 'grade' => 5, 'fileFilter' => $swfFilter); - $this->forms['v1'] = array('label' => __('Options spécifiques au fluidbook version 1'), - 'fieldsnames' => array('extras', 'v1SWF')); - - $this->fields['themeEnableAfterSearch'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Afficher l'image supplémentaire à droite du moteur de recherche"), 'grade' => 3); - $this->forms['theme'] = array('label' => __('Options du thème'), - 'fieldsnames' => array('themeEnableAfterSearch')); - - $this->fields['forceCompileOnDownload'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Forcer la compilation lors du téléchargement'), 'grade' => 3); - $this->fields['htmlExtension'] = array('type' => 'text', 'default' => 'html', 'editable' => true, 'label' => __('Extension des fichiers html'), 'grade' => 5, 'hint' => __('Ex : php, htm, html, phtml, asp'), 'grade' => 5); - $this->fields['htmlPrepend'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Code à insérer en tête des fichiers'), 'grade' => 5); - $this->fields['baseUrl'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Base de l\'url'), 'grade' => 5, 'grade' => 5); - - $this->forms['package'] = array('label' => __('Option d\'export'), - 'fieldsnames' => array('htmlExtension', 'htmlPrepend', 'baseUrl', 'forceCompileOnDownload')); - - $this->fields['disableDemo'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Désactiver le lien de démo'), 'grade' => 5); - $this->fields['redirectDemo'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Rediriger le lien de démo vers'), 'grade' => 5); - $this->forms['demo'] = array('label' => __('Lien de démo'), - 'fieldsnames' => array('disableDemo', 'redirectDemo')); - - - $this->fields['scorm_enable'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Activer SCORM'), 'grade' => 5); - $this->fields['scorm_id'] = array('type' => 'text', 'default' => 'MFMCTE091mobile', 'editable' => true, 'label' => __('Identifiant SCORM'), 'grade' => 5); - $this->fields['scorm_org'] = array('type' => 'text', 'default' => 'ACME-ORG-1350650111249', 'editable' => true, 'label' => __('Organisation SCORM'), 'grade' => 5); - $this->fields['scorm_title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Titre SCORM'), 'grade' => 5, 'hint' => __('Laisser vide pour utiliser le titre de la publication')); - $this->fields['scorm_variables'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Variables SCORM'), 'grade' => 5, 'hint' => __('Laisser vide pour utiliser le titre de la publication')); - - $this->forms['scorm'] = array('label' => __('SCORM'), - 'fieldsnames' => array('scorm_enable', 'scorm_id', 'scorm_org', 'scorm_title', 'scorm_variables')); - } +class wsBookParametres extends wsParametres +{ + + public function __construct($parent) + { + parent::__construct($parent); + } + + /** + * wsBookParametres::initFields() + * + * @return + */ + protected function initFields() + { + parent::initFields(); + // if (is_null($this->parent)) { + // return; + // } + + // . + $swfFilter = new stdClass(); + $swfFilter->name = __('Animation SWF') . ' (*.swf)'; + $swfFilter->extensions = '*.swf'; + + $multimediaFilter = new stdClass(); + $multimediaFilter->name = __('Archive ZIP') . ' (*.zip)'; + $multimediaFilter->extensions = '*.zip'; + + $pdfFilter = new stdClass(); + $pdfFilter->name = __('Document PDF') . ' (*.pdf)'; + $pdfFilter->extensions = '*.pdf'; + + $basketFilter = new stdClass(); + $basketFilter->name = __('Liste de produits') . ' (*.xml, *.xlsx)'; + $basketFilter->extensions = '*.xml;*.xlsx'; + + $imageFilter = new stdClass(); + $imageFilter->name = __('Images') . ' (*.jpg, *.png)'; + $imageFilter->extensions = '*.jpg;*.jpeg;*.png'; + + $epsFilter = new stdClass(); + $epsFilter->name = __('Fichier vectoriel') . ' (*.ai, *.eps)'; + $epsFilter->extensions = '*.ai;*.eps'; + + $svgFilter = new stdClass(); + $svgFilter->name = __('Fichier SVG') . ' (*.svg)'; + $svgFilter->extensions = '*.svg'; + + $imageExtraFilter = new stdClass(); + $imageExtraFilter->name = __('Images') . ' (*.svg, *.jpg, *.png, *.gif)'; + $imageExtraFilter->extensions = '*.svg;*.jpg;*.png;*.gif'; + + $soundFilter = new stdClass(); + $soundFilter->name = __('Fichier sonore') . ' (*.mp3, *.wav)'; + $soundFilter->extensions = '*.mp3;*.wav'; + + $branches = array('master : git (stable)' => 'stable', + 'master : local (dev)' => 'dev'); + $gitbranches = json_decode(file_get_contents(WS_CACHE . '/activebranches')); + foreach ($gitbranches as $b) { + if ($b == 'master') { + continue; + } + $branches[$b . ' : git'] = $b . '|git'; + $branches[$b . ' : local'] = $b . '|local'; + } + $extraVisibility = [ + __('Navigation horizontale') => 'horizontal', + __('Navigation burger') => 'burger', + __('Navigations horizontale et burger') => 'both']; + + $extraType = [ + __('Icône + Label') => 'icon', + __('Image') => 'image']; + + $this->fields['mobileLVersion'] = array('type' => 'combo', 'default' => 'stable', 'editable' => true, + 'label' => __('Version logicielle'), 'grade' => 1, + 'datas' => $branches + ); + $this->fields['mobileVersion'] = array('type' => 'combo', 'default' => 'html5-desktop', 'editable' => true, 'label' => __('Version mobile'), 'grade' => 3, + 'datas' => array(__('Rediriger vers le PDF') => 'pdf', + __('Version HTML5 recommandée (vecteurs sur desktop)') => 'html5-desktop', + __('Version HTML5 vecteurs') => 'html5', + __("Version HTML5 en images") => 'html5-images') + ); + + $this->fields['version'] = array('type' => 'combo', 'default' => '2', 'editable' => true, 'label' => __('Version'), 'datas' => array('1' => '1', '2' => '2'), 'grade' => 3); + $this->fields['title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre de la publication"), 'embed' => false); + $this->fields['url_link'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __("URL du lien de retour au site")); + $this->fields['signature'] = array('type' => 'combo', 'default' => '1', 'editable' => true, 'label' => __('Signature'), 'grade' => 3, 'datas' => wsDroits::getSignatures()); + $this->forms['important'] = array('label' => __('Description de la publication'), + 'fieldsnames' => array('version', 'mobileLVersion', 'mobileVersion', 'title', 'url_link', 'signature')); + // . + // . + + $this->fields['email_title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre de l'email") . ' "' . __('Envoyer à un ami') . '"', 'hint' => __('Laisser vide pour utiliser la valeur par défaut')); + $this->fields['email_body'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __("Corps de l'email") . ' "' . __('Envoyer à un ami') . '"', 'hint' => __('Laisser vide pour utiliser la valeur par défaut')); + $this->fields['email_editable'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Permettre au lecteur de modifier le corps de l'email")); + $this->fields['askAcknowledge'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Demander au destinataire un accusé de réception"), 'grade' => 3); + $this->fields['sendasfluidbook'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Envoyer le mail comme Fluidbook"), 'grade' => 3, 'hint' => __("L'expéditeur apparaîtra en reply-to")); + $this->fields['email_mailto'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Envoyer le mail via le client mail du visiteur (mailto:)"), 'grade' => 3); + + $this->fields['facebook_title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre du contenu partagé"), 'hint' => __('Titre proposé sur les fonction de partage (par défaut, titre de la publication)')); + $this->fields['facebook_description'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __("Description du contenu partagé"), 'grade' => 1, 'hint' => __('Description proposée sur les fonctions de partage (par défaut, vide)')); + $this->fields['twitter_description'] = array('type' => 'textarea', 'default' => '%title% : %short%', 'editable' => true, 'label' => __("Contenu Partage court"), 'hint' => __('Contenu du partagé sur les partages courts')); + $this->fields['facebook_image'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Miniature affichée'), 'fileFilter' => $imageFilter); + + $this->fields['share'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer les fonctions de partage')); + $this->fields['friend'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('E-mail')); + $this->fields['facebook'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Facebook')); + $this->fields['twitter'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Twitter')); + $this->fields['googleplus'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Google +')); + $this->fields['linkedin'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('LinkedIn')); + $this->fields['viadeo'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Viadeo')); + $this->fields['customSharer'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Classe personnalisée de partage"), 'grade' => 5); + $this->fields['friendWidth'] = array('type' => 'integer', 'default' => 319, 'editable' => true, 'label' => __('Largeur du menu'), 'grade' => 5); + $this->fields['friendHeight'] = array('type' => 'integer', 'default' => 500, 'editable' => true, 'label' => __('Largeur du menu'), 'grade' => 5); + $this->forms['share'] = array('label' => __('Fonctions de partage'), + 'fieldsnames' => array('share', '|', 'email_title', 'email_body', 'email_editable', 'askAcknowledge', 'sendasfluidbook', 'email_mailto', '|', + 'facebook_title', 'facebook_description', 'facebook_image', 'twitter_description', '|', + 'friend', 'facebook', 'twitter', 'googleplus', 'linkedin', 'viadeo', '|', 'customSharer', '|', 'friendWidth', 'friendHeight')); + // . + $this->fields['pages'] = array('type' => 'integer', 'default' => '', 'editable' => false, 'label' => __('Nombre de pages')); + $this->fields['width'] = array('type' => 'float', 'default' => '', 'editable' => false, 'label' => __('Largeur')); + $this->fields['height'] = array('type' => 'float', 'default' => '', 'editable' => false, 'label' => __('Hauteur')); + // . + $this->fields['visualisationMode'] = array('type' => 'combo', 'default' => '3', 'editable' => true, 'label' => __("Mode de visualisation 3D"), + 'datas' => array(__('Mode 3D') => '0', + __('Mode 2D (caméra fixe et pages à plat)') => '1', + __("Laisser le choix à l'utilisateur (mode 3D par défaut)") => '2', + __("Laisser le choix à l'utilisateur (mode 2D par défaut)") => '3')); + $this->fields['viewMode'] = array('type' => 'combo', 'default' => '0', 'editable' => true, 'label' => __("Mode de visualisation (beta)"), + 'datas' => array(__('Classique') => '0', + __("Diaporama") => '1'), 'grade' => 5); + $this->fields['antialiasReading'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Amélioration de la lisibilité en mode 2D")); + $this->fields['pagesBaseAngle'] = array('type' => 'integer', 'default' => '2', 'editable' => true, 'label' => __('Angle de base entre les pages'), 'grade' => 3, + 'hint' => __("0 : Publication à plat") . "\n" . __('2 : Valeur par défaut')); + $this->fields['extraXSpace'] = array('type' => 'integer', 'default' => '0', 'editable' => true, 'label' => __('Marge supplémentaire horizontale'), 'grade' => 3); + $this->fields['extraYSpace'] = array('type' => 'integer', 'default' => '0', 'editable' => true, 'label' => __('Marge supplémentaire verticale'), 'grade' => 3); + $this->fields['centerBook'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Centrer la publication sur les couvertures'), 'grade' => 2); + $this->fields['correctCenter'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Corriger les lignes blanches entre les pages'), 'grade' => 2); + $this->fields['maxResolution'] = array('type' => 'combo', 'default' => 300, 'editable' => true, 'datas' => array('300dpi' => 300, '150dpi' => 150), 'grade' => 2, 'label' => __('Résolution maximale des pages')); + $this->forms['3d_mode'] = array('label' => __('Options de visualisation'), + 'fieldsnames' => array('visualisationMode', 'antialiasReading', 'correctCenter', 'pagesBaseAngle', 'centerBook', '|', 'extraXSpace', 'extraYSpace', '|', 'viewMode', '|', 'maxResolution')); + + $this->fields['preload'] = array('type' => 'integer', 'default' => 16, 'editable' => true, 'label' => __('Nombre de pages à précharger'), 'grade' => 3); + + $this->fields['navOrder'] = array('type' => 'textarea', 'default' => 'index, chapters, search, print, friend, bookmark, pdf, archives, basket, fullscreen, sound, 3d, extra, extra1, extra2, extra3, extra4, extra5, help, lang', 'editable' => true, 'label' => __('Ordre des icônes dans la nav'), 'grade' => 3); + $this->fields['tooltipTimer'] = array('type' => 'float', 'default' => 3, "editable" => true, 'label' => __("Temps maximum d'apparition des infos-bulles (en secondes)")); + + + $this->forms['general'] = array('label' => __('Fonctionnalités générales'), + 'fieldsnames' => array('navOrder', 'tooltipTimer', 'preload', 'pages', 'width', 'height')); + //. + // + + $this->forms['menu'] = array('label' => __('Menu'), 'fieldsnames' => ['afterSearchDisplayForHTML', '|']); + $this->fields['afterSearchDisplayForHTML'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Afficher l\'image après le moteur de recherche sur la version HTML5'), 'grade' => 1); + $extraNum = 5; + for ($i = 0; $i <= $extraNum; $i++) { + if ($i > 0) { + $j = $i; + $this->fields['navExtraIcon' . $j] = array('type' => 'freefile', 'default' => '', 'editable' => true, 'label' => __('Icône supplémentaire') . ' ' . $j, 'fileFilter' => $imageExtraFilter); + $this->fields['navExtraType' . $j] = array('type' => 'combo', 'datas' => $extraType, 'default' => 'icon', 'editable' => true, 'label' => __('Type')); + $this->fields['navExtraLink' . $j] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("URL") . ' ' . $j); + $this->fields['navExtraVisibility' . $j] = array('type' => 'combo', 'datas' => $extraVisibility, 'default' => 'both', 'editable' => true, 'label' => __("Visible") . ' ' . $j); + $this->forms['menu']['fieldsnames'] = array_merge($this->forms['menu']['fieldsnames'], ['navExtraIcon' . $j, 'navExtraType' . $j, 'navExtraLink' . $j, 'navExtraVisibility' . $j, '|']); + } else { + $j = ''; + $this->fields['navExtraImage' . $j] = array('type' => 'freefile', 'default' => '', 'editable' => true, 'label' => __('Image pour navigation'), 'fileFilter' => $imageExtraFilter); + $this->fields['navExtraImageMobile' . $j] = array('type' => 'freefile', 'default' => '', 'editable' => true, 'label' => __('Image pour mobile'), 'fileFilter' => $imageExtraFilter); + $this->fields['navExtraLink' . $j] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("URL")); + $this->fields['navExtraTooltip' . $j] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Infobulle ou label")); + $this->forms['menu']['fieldsnames'] = array_merge($this->forms['menu']['fieldsnames'], ['navExtraImage' . $j, 'navExtraImageMobile' . $j, 'navExtraLink' . $j, 'navExtraTooltip' . $j, '|']); + } + } + + + $this->fields['landingPage'] = array('type' => 'freefile', 'default' => '', 'editable' => true, 'label' => __('Landing Page content'), 'grade' => 3); + $this->forms['landing'] = array('label' => __('Custom Landing Page'), 'fieldsnames' => array('landingPage')); + + + $this->fields['fullscreen'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer le mode plein-écran')); + $this->fields['fullscreenAuto'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Lancer la publication en mode plein écran (lorsque possible)')); + $this->forms['fs'] = array('label' => __('Plein écran'), + 'fieldsnames' => array('fullscreen', 'fullscreenAuto')); + + + $this->fields['bookmark'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer les marques-pages')); + $this->fields['bookmarkSendEnable'] = array('type' => 'boolean', 'default' => 'true', 'editable' => true, 'label' => __("Activer l'envoi des marques-pages par e-mail")); + $this->fields['bookmark_email_title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre de l'email") . ' "' . __('Envoyer à un ami') . '"', 'hint' => __('Laisser vide pour utiliser la valeur par défaut')); + $this->fields['bookmark_email_body'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __("Corps de l'email") . ' "' . __('Envoyer à un ami') . '"', 'hint' => __('Laisser vide pour utiliser la valeur par défaut')); + $this->fields['bookmarkCornerSize'] = array('type' => 'integer', 'default' => 8, 'editable' => true, 'label' => __("Taille des marques-pages"), 'hint' => __('Taille relative à la largeur de la page')); + $this->fields['bookmarkOffset'] = array('type' => 'integer', 'default' => 0, 'editable' => true, 'label' => __("Décaler de x pixels vers l'intérieur")); + $this->fields['bookmarkBlinkOnPageChange'] = array('type' => 'boolean', 'default' => 'false', 'editable' => true, 'label' => __('Faire clignoter le marque page à l\'apparition de la page')); + $this->fields['bookmarkUsePDF'] = array('type' => 'combo', 'default' => 'pages', 'editable' => true, 'label' => __('PDF à utiliser pour l\'envoi ou le téléchargement de pages marquées'), + 'datas' => [__('PDF des pages') => 'pages', + __('PDF de remplacement') => 'download', + __('PDF des miniatures') => 'thumbnails']); + $this->forms['bookmark'] = array('label' => __('Marques-pages'), + 'fieldsnames' => array('bookmark', '|', 'bookmarkSendEnable', 'bookmark_email_title', 'bookmark_email_body', '|', 'bookmarkCornerSize', 'bookmarkOffset', 'bookmarkBlinkOnPageChange', 'bookmarkUsePDF')); + + $this->fields['help'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Activer l'aide")); + $this->fields['helpBookmarks'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Améliorer l'aide des marques-pages")); + $this->fields['helpStartup'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Afficher l'aide au démarrage")); + $this->fields['helpStartupTime'] = array('type' => 'integer', 'default' => 15, 'editable' => true, 'label' => __("Temps d'affichage en secondes")); + $this->fields['helpArrowTooltip'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Bulle affichée au niveau de la flèche de droite'), 'grade' => 5); + $this->forms['help'] = array('label' => __('Aide'), + 'fieldsnames' => array('help', '|', 'helpStartup', 'helpStartupTime', '|', 'helpBookmarks', '|', 'helpArrowTooltip')); + // . + // + $this->fields['indexAutoScroll'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Activer le scroll automatique')); + $this->fields['pdfThumbnails'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('PDF utilisé pour générer les miniatures'), 'grade' => 1, 'fileFilter' => $pdfFilter); + + $this->forms['index'] = array('label' => __('Index'), 'fieldsnames' => array('indexAutoScroll', 'pdfThumbnails')); + + // . + // + $this->fields['print'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Activer l'impression")); + $this->fields['printMode'] = array('type' => 'combo', 'default' => 'vector', 'editable' => true, 'label' => __("Mode d'impression"), + 'datas' => array(__('Bitmap') => 'bitmap', + __('Vectoriel') => 'vector', + __('PDF') => 'pdf')); + $this->fields['printCoverWithMarks'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Imprimer les couvertures avec les pages marquées"), 'grade' => 3); + $this->forms['print'] = array('label' => __('Impression'), + 'fieldsnames' => array('print', 'printMode', 'printCoverWithMarks')); + + + $this->fields['search'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer le moteur de recherche')); + $this->fields['highlightResults'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Surligner les résultats')); + $this->fields['highlightAllOccurences'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Surligner toutes les occurences'), 'hint' => __('Même sur les pages non considérées comme un résultat')); + $this->fields['ignoreSearch'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Mots à ignorer'), + 'hint' => __('Liste des mots à ignorer séparés par des virgules'), 'grade' => 5); + $this->fields['ignoreSearchSeparators'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Caractères à ne pas considérer comme un séparateur de mot')); + $this->fields['ignoreWordLimit'] = ['type' => 'integer', 'default' => 3, 'editable' => true, 'label' => __('Ignorer les mots de moins de X caractères')]; + $this->fields['textExtraction'] = array('type' => 'combo', 'default' => 'pdfbox', 'editable' => true, 'label' => __("Méthode d'extraction des textes"), + 'datas' => array(__('PDFBox') => 'pdfbox', + __('Poppler') => 'poppler', + __('Fluidbook (expérimentation basée sur PDFBox)') => 'fluidbook')); + $this->fields['searchShowNoResultsPages'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Afficher les pages sans résultats")); + $this->fields['searchPageSelectionAlgorithm'] = array('type' => 'combo', 'editable' => true, 'default' => 'AND', + 'datas' => [__('les double-pages qui contiennent tous les mots recherchés (ET logique)') => 'AND', __('les double-page qui contiennent un des mots recherché (OU logique)') => 'OR'], 'label' => __('Algorithme de sélection des résultats')); + $this->fields['searchWordSelectionAlgorithm'] = array('type' => 'combo', 'editable' => true, 'default' => 'begins', + 'datas' => [__('mot commençant par la requête') => 'begins', __('mot correspondant exactement à la requête') => 'exact', __('mot contenant la requête') => 'contains', __('expression exacte') => 'expression'], + 'label' => __('Algorithme de sélection des occurences')); + + $this->forms['search'] = array('label' => __('Moteur de recherche'), + 'fieldsnames' => array('search', '|', 'ignoreWordLimit', 'ignoreSearch', 'ignoreSearchSeparators', + '|', 'searchWordSelectionAlgorithm', 'searchPageSelectionAlgorithm', + '|', 'highlightResults', 'highlightAllOccurences', + '|', 'searchShowNoResultsPages', + '|', 'textExtraction')); + + $this->fields['soundTheme'] = array('type' => 'combo', 'default' => 'classic', 'editable' => true, 'label' => __("Thème sonore"), + 'datas' => array(__('Pas de son') => '', + __('Classique') => 'classic', + __("Papier épais") => 'heavy', + __("Papier fin") => 'light')); + $this->fields['soundOn'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Activer les effets sonores à l'ouverture")); + $this->fields['ambientSound'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Ambiance sonore'), 'grade' => 3, 'fileFilter' => $soundFilter); + $this->fields['ambientSoundVolume'] = array('type' => 'integer', 'default' => 50, 'editable' => true, + 'label' => __("Volume de l'ambiance sonore"), + 'min' => 0, 'max' => 100); + $this->forms['sound'] = array('label' => __('Effets sonores'), + 'fieldsnames' => array('soundTheme', 'soundOn', '|', 'ambientSound', 'ambientSoundVolume')); + // . + $this->fields['pdf'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Activer les fonctions de téléchargement")); + $this->fields['pdfName'] = array('type' => 'text', 'default' => 'document.pdf', 'editable' => true, 'label' => __("Nom du fichier PDF")); + $this->fields['pdfComplex'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Téchargement de PDF avancé'), "hint" => __("Permet à l'utilisateur de sélectionner les pages qu'il souhaite télécharger"), 'grade' => 3); + $this->fields['pdfCompress'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Compression du fichier PDF')); + $this->fields['pdfReplace'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('PDF de remplacement'), 'grade' => 3, 'fileFilter' => $pdfFilter); + $this->fields['offlineExport'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Téléchargement des versions offline'), "hint" => __('Valable si le téléchargement avancé est activé'), 'grade' => 3); + $this->forms['pdf'] = array('label' => __('Fonction de téléchargement'), + 'fieldsnames' => array('pdf', 'pdfName', 'pdfReplace', 'pdfCompress', 'pdfComplex', 'offlineExport')); + // . + $this->fields['zoomMode'] = array('type' => 'combo', 'default' => '0', 'editable' => true, 'label' => __("Mode de zoom"), 'grade' => 3, + 'datas' => array(__('Normal') => '0', + __('Une page') => '1', + __('Zoom désactivé') => '2')); + $this->fields['zoom'] = array('type' => 'integer', 'default' => 200, 'editable' => true, 'label' => __('Zoom par défaut (atteint au clic)')); + $this->fields['zoomw'] = array('type' => 'integer', 'default' => 300, 'editable' => true, 'label' => __("Zoom maximal (atteint à l'aide de la molette)")); + $this->forms['zoom'] = array('label' => __('Zoom'), + 'fieldsnames' => array('zoomMode', '|', 'zoom', 'zoomw')); + // . + $this->fields['stats'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Activer les statistiques Fluidbook'), 'grade' => 3); + $this->fields['stats_score'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Afficher les scores dans les rapports'), 'grade' => 5); + $this->fields['stats_exclude_ip'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Exclure les IP suivantes des statistiques'), 'grade' => 3, 'hint' => sprintf(__('Indiquer une adresse ip de la forme %s par ligne'), 'www.xxx.yyy.zzz')); + $this->fields['googleAnalytics'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Code Google Analytics'), 'size' => 10); + $this->fields['googleAnalyticsCustom'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Code Stats personnalisé (placé avant fermeture de head)')); + $this->fields['statsCustom'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Code Stats personnalisé (placé avant fermeture du body)')); + $this->fields['xiti'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Code XiTi global')); + $this->fields['xiti_page'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Modèle code xiti (pour tags relatifs aux pages)')); + $this->forms['stats'] = array('label' => __('Statistiques'), + 'fieldsnames' => array('stats', 'stats_score', 'stats_exclude_ip', '|', 'googleAnalytics', '|', 'googleAnalyticsCustom', 'statsCustom', '|', 'xiti', 'xiti_page')); + + $this->fields['displayChaptersPopup'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Always display chapters in a popup'), 'grade' => 1); + $this->fields['displayChaptersIcon'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Affiche l'icône du sommaire"), 'grade' => 1); + $this->fields['displayChaptersLine'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Affiche une ligne entre le label et le numéro de page"), 'grade' => 5); + $this->fields['chaptersPage'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Faire pointer le sommaire sur la page'), 'grade' => 3, 'hint' => __('Laisser vide pour utiliser le sommaire classique'), 'size' => 5); + $this->fields['displayChaptersAtStart'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Afficher le sommaire au chargement de la publication"), 'grade' => 3); + $this->fields['chaptersColumns'] = array('type' => 'integer', 'default' => 1, 'editable' => true, 'label' => __('Afficher le sommaire sur x colonne(s)'), 'grade' => 3); + $this->fields['chaptersColMaxWidth'] = array('type' => 'integer', 'default' => 300, 'editable' => true, 'label' => __("Largeur max d'une colonne"), 'grade' => 3); + $this->fields['chaptersLevelLimit'] = array('type' => 'integer', 'default' => 5, 'editable' => true, 'label' => __('Limiter à x niveaux')); + $this->fields['externalChapters'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Sommaire personnalisé'), 'grade' => 3, 'fileFilter' => $swfFilter, 'hint' => __('Laisser vide pour utiliser le sommaire classique')); + $this->fields['externalChaptersHTML'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Sommaire personnalisé (HTML5)'), 'grade' => 3, 'fileFilter' => $multimediaFilter, 'hint' => __('Laisser vide pour utiliser le sommaire classique')); + $this->fields['fullExternalChapters'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Sommaire totalement personnalisé"), 'grade' => 3, 'hint' => __('Supprime la flèche de fermeture, titre prédéfini et couleur de fond')); + $this->fields['mobileChaptersStyle'] = array('type' => 'combo', 'default' => 'classic', 'editable' => true, 'label' => __('Style des chapîtres') . ' (' . __('version mobile') . ')' + , 'datas' => array(__('Classique') => 'classic', + __('INA') => 'ina')); + + $this->fields['chaptersPosition'] = array('type' => 'combo', 'default' => 'center', 'editable' => true, 'label' => __("Position du sommaire"), + 'datas' => array(__('Centré') => 'center', + __("Aligné sur l'icône") => 'chaptersIcon')); + $this->fields['chaptersCascade'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Sommaire en cascade"), 'grade' => 3); + + $this->forms['sommaire'] = array('label' => __('Sommaire'), + 'fieldsnames' => array('displayChaptersIcon', 'displayChaptersPopup', 'displayChaptersAtStart', 'chaptersPage', 'chaptersPosition', 'chaptersLevelLimit', 'chaptersCascade', '|', 'chaptersColMaxWidth', 'chaptersColumns', 'displayChaptersLine', '|', 'externalChapters', 'fullExternalChapters', '|', 'externalChaptersHTML', '|', 'mobileChaptersStyle')); + // . + + $this->fields['ongletsXML'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('XML de configuration des onglets'), 'grade' => 5); + $this->fields['ongletsSWF'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('SWF pour onglets personnalisés'), 'grade' => 3, 'fileFilter' => $swfFilter); + + $this->fields['tabs2DSWF'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('SWF pour onglets 2D'), 'grade' => 3, 'fileFilter' => $swfFilter); + + $this->fields['tabsHTML5'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Onglets HTML5'), 'grade' => 3); + + $this->fields['flatTabsAbsolute'] = array('type' => 'boolean', 'default' => false, "editable" => true, + 'label' => __("Positionnement relatif à l'interface"), 'grade' => 5); + + $this->forms['tabs'] = array('label' => __('Onglets'), + 'fieldsnames' => array('ongletsSWF', 'ongletsXML', '|', 'tabs2DSWF', 'flatTabsAbsolute', '|', 'tabsHTML5')); + + $this->fields['customLinkClass'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Classe pour les liens personnalisés'), 'grade' => 5); + $this->fields['permanentLinks'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Liens visibles en permanence'), 'grade' => 3); + $this->fields['ignoreLinksTypes'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Ignorer les liens de type'), 'hint' => __('Liste des numéros séparés par des virgules'), 'grade' => 5); + $this->fields['linkBlinkTime'] = array('type' => 'float', 'default' => 1.0, 'editable' => true, 'label' => __("Temps d'apparition du lien à l'ouverture de la page (en secondes)")); + $this->fields['linkTooltipManager'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Gestionnaire des info-bulles"), 'grade' => 5); + $this->fields['linkTracker'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Tracking des liens'), 'grade' => 5); + $this->fields['linkTrackerRegexp'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Tracking des liens applicables aux liens du domaine'), 'grade' => 5); + $this->fields['linkFilePrefix'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Préfixer les liens de téléchargement')); + $this->fields['linkMultimediaPerformanceMode'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Mode perfomance pour les liens multimédia'), 'grade' => 5); + $this->fields['linkMultimediaQuality'] = array('type' => 'float', 'default' => 1.0, 'editable' => true, 'label' => __('Qualité de rendu des animations'), 'grade' => 5); + $this->fields['linkCornerSize'] = array('type' => 'integer', 'default' => '10', 'editable' => true, 'label' => __('Taille des liens de coins de page'), 'hint' => __("Pourcentage de la largeur de la page")); + $this->fields['linkTooltipMaxWidth'] = array('type' => 'integer', 'default' => '140', 'editable' => true, 'label' => __('Largeur max des infobulles des liens de type "infobulle"')); + $this->fields['videoReset'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Réinitialiser les vidéos après la lecture'), 'grade' => 3); + $this->fields['videoBigPlay'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Afficher le gros bouton Play'), 'grade' => 3); + $this->fields['brightcovePlayerId'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Brightcove Player Id'), 'grade' => 3); + $this->fields['brightcovePlayerSecret'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Brightcove Player Secret'), 'grade' => 3); + $this->forms['multimedia'] = array('label' => __('Liens et multimédia'), + 'fieldsnames' => array('permanentLinks', 'linkBlinkTime', 'customLinkClass', 'ignoreLinksTypes', 'linkTooltipManager', 'linkCornerSize', 'linkTooltipMaxWidth', '|', 'linkTracker', 'linkTrackerRegexp', '|', 'linkFilePrefix', '|', 'linkMultimediaPerformanceMode', 'linkMultimediaQuality', '|', 'videoReset', 'videoBigPlay', '|', 'brightcovePlayerId', 'brightcovePlayerSecret')); + //. + $this->fields['externalArchives'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Archives'), 'grade' => 3, 'fileFilter' => $imageFilter); + $this->fields['externalArchivesBack'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Image de fond'), 'grade' => 3, 'fileFilter' => $imageFilter); + $this->fields['archivesLink'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Lien'), 'grade' => 5); + $this->fields['archivesLabel'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Label'), 'grade' => 5); + + $this->forms['archives'] = array('label' => __('Archives'), + 'fieldsnames' => array('externalArchives', 'externalArchivesBack', '|', 'archivesLink', 'archivesLabel')); + // . + $this->fields['form'] = array('type' => 'combo', 'default' => '', 'editable' => true, 'grade' => 5, 'label' => __('Formulaire'), 'datas' => array(__('Aucun') => '', __('Bulle Groupe') => 'bulle')); + $this->forms['form'] = array('label' => __('Formulaire'), + 'fieldsnames' => array('form')); + + $this->fields['cookieConsent'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Message cookie')); + $this->fields['cookieConsentMessage'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Texte du consentement')); + $this->fields['cookieConsentAutoclose'] = array('type' => 'integer', 'default' => '0', 'editable' => true, 'label' => __('Masquer automatiquement après x secondes')); + $this->forms['privacy'] = array('label' => __('Respect de la vie privée'), + 'fieldsnames' => array('cookieConsent', 'cookieConsentMessage', 'cookieConsentAutoclose')); + + //. + $this->fields['basket'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Panier activé'), 'grade' => 5); + $this->fields['basketManager'] = array('type' => 'combo', 'default' => 'classic', 'editable' => true, 'label' => __("Manager de panier"), + 'datas' => array(__('Classic') => 'com.fluidbook.player.basket.BasketManager', + 'Grdf' => 'com.fluidbook.player.basket.custom.grdf.GrdfBasketManager', + 'Grdf 2013' => 'com.fluidbook.player.basket.custom.grdf.grdf2013.GrdfBasketManager2013', + 'Grdf 2015' => 'com.fluidbook.player.basket.custom.grdf.grdf2015.GrdfBasketManager2015', + 'Essilor' => 'com.fluidbook.player.basket.custom.essilor.EssilorBasketManager', + 'Essilor Recap' => 'com.fluidbook.player.basket.custom.essilorrecap.EssilorRecapBasketManager', + 'Wesco Ventes' => 'com.fluidbook.player.basket.custom.wesco.WescoBasketManager', + 'Atlantic Download' => 'com.fluidbook.player.basket.custom.atlantic.AtlanticDownloadBasketManager' + ), 'grade' => 5); + $this->fields['basketReferences'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Références produits'), 'grade' => 3, 'fileFilter' => $basketFilter, 'hint' => __('Fichier contenant les références produits'), 'dir' => 'commerce'); + $this->fields['basketImages'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Images des produits'), 'grade' => 5, 'fileFilter' => $imageFilter, 'hint' => __('Chaque image doit avoir pour nom exact la référence du produit'), + 'multiple' => true, 'dir' => 'commerce'); + $this->fields['basketPDFBackground'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Fond du PDF (bon de commande)'), 'grade' => 5, 'fileFilter' => $epsFilter, 'hint' => __('Fond du bon de commande'), 'dir' => 'commerce'); + + $this->forms['basket'] = array('label' => __('Panier'), + 'fieldsnames' => array('basket', 'basketManager', 'basketReferences', 'basketImages', 'basketPDFBackground')); + // . + $this->fields['offlineLink'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __("URL du Fluidbook"), 'hint' => __('URL du fluidbook utilisée pour la version Offline (CD-ROM, clé USB, Exécutables)')); + $this->fields['offlineTitle'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Titre de l'application")); + $this->forms['offline'] = array('label' => __('Version offline'), + 'fieldsnames' => array('offlineTitle', 'offlineLink')); + + $this->fields['alwaysHTML5'] = array('type' => 'boolean', 'default' => 'false', 'editable' => true, 'label' => __('Toujours utiliser la version HTML5'), 'grade' => 1); + + $this->fields['html5priority'] = array('type' => 'combo', 'default' => 'true', 'editable' => true, 'label' => __("Rediriger vers la version HTML5"), 'grade' => 1, + 'datas' => array(__('Si l\'utilisateur a un appareil tactile') => 'false', + __('Si flash n\'est pas installé') => 'notinstalled', + __("Si flash n'est pas pas installé ou bloqué") => 'true')); + + $this->fields['flashBlockedWait'] = array('type' => 'float', 'default' => 1.5, 'editable' => true, 'label' => __("Temps d'attente avant de considérer flash comme bloqué")); + + + $this->fields['navOrderH'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Ordre des icônes dans la nav') . ' (' . __('Si différente') . ')', 'grade' => 3); + + $this->fields['menuBreakpoint'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Breakpoint burger menu'), 'hint' => 'Par défaut 1023px', 'grade' => 3); + + + $this->fields['mobileTransitions'] = array('type' => 'combo', 'default' => 'flip', 'editable' => true, 'label' => __('Transitions entre les pages'), 'grade' => 3, + 'datas' => array(__('Aucune transition') => 'none', + __('Glisser') => 'slide', + __('Tourner') => 'flip') + ); + $this->fields['mobileNavigationType'] = array('type' => 'combo', 'default' => 'book', 'editable' => true, 'label' => __('Mode de navigation'), 'grade' => 5, + 'datas' => array(__('Normal (automatique)') => 'book', + __('Normal (double page)') => 'landscape', + __('Normal (une page)') => 'portrait', + __('Magazine tablette') => 'tab') + ); + $this->fields['rasterizePages'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Ecraser les pages'), 'hint' => '1-3,5 = 1,2,3,5', 'grade' => 1); + $this->fields['vectorPages'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Conserver les pages en vecteur'), 'hint' => '1-3,5 = 1,2,3,5', 'grade' => 1); + + + $this->fields['mobileTransitionDuration'] = array('type' => 'float', 'default' => '0.75', 'editable' => true, 'label' => __('Durée de la transition')); + $this->fields['mobileLinksRevealAnim'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Animer les liens après un changement de page"), 'grade' => 3); + + $this->fields['mobileIconVector'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Utiliser les icônes vectorielles')); + $this->fields['mobileServerConfig'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Inclure les fichiers de configuration serveur'), 'grade' => 3); + + $this->fields['mobilePlugins'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Plugin'), 'grade' => 5); + + $this->fields['mobileVideosPath'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Chemin vers les vidéos'), 'grade' => 5); + $this->fields['mobileExtraXSpace'] = array('type' => 'integer', 'default' => '0', 'editable' => true, 'label' => __('Marge supplémentaire horizontale'), 'grade' => 3); + $this->fields['mobileNavScale'] = array('type' => 'integer', 'default' => '100', 'editable' => true, 'label' => __('Taille du menu (en %)'), 'grade' => 3); + + $this->fields['mobileIgnoreBackgroundLinks'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Ignorer les liens de background')); + + $this->forms['mobile'] = array('label' => __('Version mobile'), + 'fieldsnames' => array('alwaysHTML5', 'html5priority', 'flashBlockedWait', 'mobileNavigationType', '|', 'rasterizePages', 'vectorPages', '|', 'mobileNavScale', '|', 'mobileTransitions', 'mobileTransitionDuration', "mobileLinksRevealAnim", '|', 'menuBreakpoint', 'navOrderH', '|', 'mobileIconVector', 'mobileServerConfig', 'mobilePlugins', '|', 'mobileVideosPath', '|', 'mobileExtraXSpace', '|', 'mobileIgnoreBackgroundLinks')); + + + $this->fields['phonegapId'] = array('type' => 'text', 'default' => 'com.fluidbook.phonegap.$id', 'editable' => true, 'label' => __("Identifiant de l'identifiant"), 'grade' => 5, 'hint' => __('De la forme') . ' com.fluidbook.phonegap.xxxxx'); + $this->fields['phonegapVersion'] = array('type' => 'text', 'default' => '1.0.0', 'editable' => true, 'label' => __("Version de l'application"), 'grade' => 5, 'hint' => __('De la forme') . ' 1.2.3'); + $this->fields['phonegapPlugins'] = array('type' => 'textarea', 'default' => 'ChildBrowser', 'editable' => true, 'label' => __('Plugins Phonegap'), 'grade' => 5); + $defaultScreenshots = "P,0\nL,2\nL,index"; + $this->fields['appScreenshots'] = array('type' => 'textarea', 'default' => $defaultScreenshots, 'editable' => true, 'label' => 'Générer les screenshots', 'grade' => 5, 'hint' => __('Une ligne par vue à générer de la forme X,Y (X : P(ortrait) ou L(andscape), Y : numéro de page ou vue (1, index))')); + + $this->forms['phonegap'] = array('label' => __('Applications mobile'), + 'fieldsnames' => array('phonegapId', 'phonegapVersion', 'phonegapPlugins', 'appScreenshots')); + + $this->fields['secureURL'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __('URL de sécurisation'), 'grade' => 5, 'hint' => __('URL intérrogé pour vérifier si le visiteur à les droits pour consulter la publication')); + $this->fields['secureURLRedirect'] = array('type' => 'text', 'default' => 'http://', 'editable' => true, 'label' => __('Redirection'), 'grade' => 5, 'hint' => __("Si l'authentification échoue, redirection vers cette adresse")); + $this->fields['preventRightClick'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __("Essayer d'empêcher le clic droit"), 'grade' => 1); + $this->forms['secure'] = array('label' => __('Sécurisation'), + 'fieldsnames' => array('secureURL', 'secureURLRedirect', '|', 'preventRightClick')); + + $this->fields['seoVersion'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Générer une version pour les moteurs de recherche')); + $this->fields['seoRobots'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Autoriser le parcours par les moteurs de recherche')); + $this->fields['seoDescription'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Meta tag Description')); + $this->fields['seoKeywords'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Meta tag Keywords')); + + $this->forms['seo'] = array('label' => __('Optimisation pour les moteurs de recherche'), + 'fieldsnames' => array('seoVersion', 'seoRobots', 'seoDescription', "seoKeywords")); + + $this->fields['home'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __("Accueil de l'interface multibrochure"), 'grade' => 5); + $this->fields['multilang'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Langues'), 'hint' => __('Code langue') . ',' . __('Code pays') . ',' . __('URL')); + $this->fields['country'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Pays de la brochure')); + $this->fields['multilangDisplay'] = array('type' => 'combo', 'default' => 'lang', 'editable' => true, 'label' => __('Affichage'), + 'datas' => array(__('Langue') => 'lang', + __('Langue') . ' (' . __('Pays') . ')' => 'lang_country', + __('Pays') . ' (' . __('Langue') . ')' => 'country_lang')); + $this->forms['multibrochure'] = array('label' => __('Multibrochure'), + 'fieldsnames' => array('home', 'country', 'multilangDisplay', 'multilang')); + + $this->fields['plv'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Activer le mode PLV'), 'grade' => 3); + $this->fields['plvTimer'] = array('type' => 'integer', 'min' => 1, 'max' => 60, 'default' => 5, 'editable' => true, 'label' => __('Temps'), 'grade' => 3); + $this->fields['plvMode'] = array('type' => 'combo', 'default' => 'first', 'editable' => true, 'label' => __('Arrivé à la dernière page'), 'grade' => 3, + 'datas' => array(__('Remonter vers la première page') => 'back', + __('Recommencer à la première page') => 'first')); + $this->forms['plv'] = array('label' => __('Mode PLV'), + 'fieldsnames' => array('plv', 'plvTimer', 'plvMode')); + + $this->fields['widget'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Générer le widget'), 'grade' => 3); + $this->fields['widgetCover'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __('Afficher la couverture') . ')', 'grade' => 3); + $this->fields['widgetSize'] = array('type' => 'integer', 'default' => 200, 'editable' => true, 'label' => __('Optimiser pour une hauteur de (en pixels)'), 'grade' => 3); + $this->fields['widgetQuality'] = array('type' => 'integer', 'default' => 85, 'min' => 0, 'max' => 100, 'editable' => true, 'label' => __('Qualité JPEG'), 'grade' => 3); + $this->fields['widgetStart'] = array('type' => 'integer', 'default' => 1, 'editable' => true, 'label' => __('Page de début'), 'grade' => 3); + $this->fields['widgetEnd'] = array('type' => 'integer', 'default' => 8, 'editable' => true, 'label' => __('Page de fin'), 'grade' => 3); + $this->forms['widget'] = array('label' => __('Widget') . ' (' . __('Mini Fluidbook') . ')', + 'fieldsnames' => array('widget', 'widgetCover', 'widgetSize', 'widgetQuality', 'widgetStart', 'widgetEnd')); + + $this->fields['extras'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Extras'), 'grade' => 3); + $this->fields['v1SWF'] = array('type' => 'freefile', 'default' => '', 'editable' => true, + 'label' => __('Index.swf spécifique'), 'grade' => 5, 'fileFilter' => $swfFilter); + $this->forms['v1'] = array('label' => __('Options spécifiques au fluidbook version 1'), + 'fieldsnames' => array('extras', 'v1SWF')); + + $this->fields['themeEnableAfterSearch'] = array('type' => 'boolean', 'default' => true, 'editable' => true, 'label' => __("Afficher l'image supplémentaire à droite du moteur de recherche"), 'grade' => 3); + $this->forms['theme'] = array('label' => __('Options du thème'), + 'fieldsnames' => array('themeEnableAfterSearch')); + + $this->fields['forceCompileOnDownload'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Forcer la compilation lors du téléchargement'), 'grade' => 3); + $this->fields['htmlExtension'] = array('type' => 'text', 'default' => 'html', 'editable' => true, 'label' => __('Extension des fichiers html'), 'grade' => 5, 'hint' => __('Ex : php, htm, html, phtml, asp'), 'grade' => 5); + $this->fields['htmlPrepend'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Code à insérer en tête des fichiers'), 'grade' => 5); + $this->fields['baseUrl'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Base de l\'url'), 'grade' => 5, 'grade' => 5); + + $this->forms['package'] = array('label' => __('Option d\'export'), + 'fieldsnames' => array('htmlExtension', 'htmlPrepend', 'baseUrl', 'forceCompileOnDownload')); + + $this->fields['disableDemo'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Désactiver le lien de démo'), 'grade' => 5); + $this->fields['redirectDemo'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Rediriger le lien de démo vers'), 'grade' => 5); + $this->forms['demo'] = array('label' => __('Lien de démo'), + 'fieldsnames' => array('disableDemo', 'redirectDemo')); + + + $this->fields['scorm_enable'] = array('type' => 'boolean', 'default' => false, 'editable' => true, 'label' => __('Activer SCORM'), 'grade' => 5); + $this->fields['scorm_id'] = array('type' => 'text', 'default' => 'MFMCTE091mobile', 'editable' => true, 'label' => __('Identifiant SCORM'), 'grade' => 5); + $this->fields['scorm_org'] = array('type' => 'text', 'default' => 'ACME-ORG-1350650111249', 'editable' => true, 'label' => __('Organisation SCORM'), 'grade' => 5); + $this->fields['scorm_title'] = array('type' => 'text', 'default' => '', 'editable' => true, 'label' => __('Titre SCORM'), 'grade' => 5, 'hint' => __('Laisser vide pour utiliser le titre de la publication')); + $this->fields['scorm_variables'] = array('type' => 'textarea', 'default' => '', 'editable' => true, 'label' => __('Variables SCORM'), 'grade' => 5, 'hint' => __('Laisser vide pour utiliser le titre de la publication')); + + $this->forms['scorm'] = array('label' => __('SCORM'), + 'fieldsnames' => array('scorm_enable', 'scorm_id', 'scorm_org', 'scorm_title', 'scorm_variables')); + } } diff --git a/inc/ws/Util/html5/master/class.ws.html5.compiler.php b/inc/ws/Util/html5/master/class.ws.html5.compiler.php index 3a8ef1c11..e971ff095 100644 --- a/inc/ws/Util/html5/master/class.ws.html5.compiler.php +++ b/inc/ws/Util/html5/master/class.ws.html5.compiler.php @@ -1,286 +1,291 @@ array('ExternalFileUtil'), - 'android' => array('webintent')); - public $pluginCSS = array(); - public $pluginJs = array(); - public $htmlmultimedia = array(); - protected $cssX = array(); - protected $cssY = array(); - protected $cssWidths = array(); - protected $pdf2htmlRatio; - protected $scale; - protected $multiply; - protected $div = array(); - protected $numerotation; - protected $fontDocs = array(); - protected $dir; - protected $z = 3; - public $vdir; - public $wdir; - - /** - * - * @var wsBook - */ - public $book; - protected $pages; - protected $theme; - public $version; - public $book_id; - protected $themeRoot; - - /** - * - * @var wsDAOBook - */ - protected $daoBook; - protected $needToRecompileContents = true; - protected $needToRecompileSettings = true; - public $width; - public $height; - protected $cssWidth; - protected $cssHeight; - protected $cssOneWidth; - protected $cssOneHeight; - protected $cssScale; - protected $cssSVGScale; - protected $optimalWidth = 567; - protected $optimalHeight = 709; - protected $additionalConfig = array(); - protected $fontScale = 1; - protected $cache = array(); - protected $backgroundsPrefix = array(); - protected $svg = true; - protected $config = array(); - protected $assets = ''; - protected $phonegap = false; - protected $phonegapVersion; - protected $standalone = false; - protected $hiddenContents = array(); - protected $appcache; - protected $home; - protected $widget = true; - protected $multiApp = false; - protected $pageLabels = array(); - protected $stylesheets = array(); - protected $logfp = null; - protected $logtime = null; - protected $beginBody = array(); - protected $seoArticles = []; - protected $securityPolicyWhitelist = ['*.google-analytics.com', '*.youtube.com', '*.ytimg.com']; - - - function __construct($book_id, $version = 'stable', $phonegap = false, $phonegapVersion = 'latest', $dir = null, $standalone = false, $appcache = false, $home = false) { - global $core; - - $this->phonegapVersion = wsHTML5::getPhonegapVersion($phonegapVersion); - $this->appcache = $appcache; - $this->multiApp = $this->home = $home; - $this->version = $version; - - if ($version == 'stable') { - $this->assets = WS_COMPILE_ASSETS . '/player/branches/master'; - } else if ($version == 'dev') { - $this->assets = WS_COMPILE_ASSETS . '/player/local/master'; - } else { - list($branch, $location) = explode('|', $version); - $this->assets = WS_COMPILE_ASSETS . '/player/' . ($location == 'git' ? 'branches' : $location) . '/' . $branch; - } - - $this->phonegap = $phonegap; - $this->standalone = $standalone || $this->phonegap; - $this->appcache = $appcache; - $this->widget = !$this->phonegap; - - cubePHP::set_memory('4G'); - - if (trim($book_id) == '') { - return; - } - $this->book_id = $book_id; - $this->log('Start compilation'); - - if (is_null($dir)) { - $this->dir = WS_BOOKS . '/html5/' . $book_id . '/'; - } else { - $this->dir = $dir; - } - $this->vdir = new CubeIT_Files_VirtualDirectory($this->dir); - $this->wdir = WS_BOOKS . '/working/' . $this->book_id . '/'; - - $this->daoBook = new wsDAOBook($core->con); - $this->book = $this->daoBook->selectById($book_id); - $this->pages = $this->daoBook->getPagesOfBook($book_id); - - - $daoTheme = new wsDAOTheme($core->con); - $this->theme = $daoTheme->getThemeOfBook($book_id, true); - $this->themeRoot = WS_THEMES . '/' . $this->theme->theme_id . '/'; - - $daoDoc = new wsDAODocument($core->con); - $firstDoc = $daoDoc->selectById($this->pages[1]['document_id']); - $size = $firstDoc->generalInfos['size']; - - $this->log('Got data from database'); - - $this->width = round($size[0], 3); - $this->height = round($size[1], 3); - - $imagesize = CubeIT_Image::getimagesize(wsDocument::getDir($this->pages[1]['document_id']) . 'html/h150-' . $this->pages[1]['document_page'] . '.jpg'); - $this->pdf2htmlRatio = round(($imagesize[0] * 0.48) / $this->width, 3); - - $this->cssScale = $this->z * min($this->optimalWidth / $this->width, $this->optimalHeight / $this->height); - $this->cssOneScale = $this->z * min(($this->optimalWidth * 2) / $this->width, $this->optimalHeight / $this->height); - - $this->cssWidth = $this->width * $this->cssScale; - $this->cssHeight = $this->height * $this->cssScale; - - $this->cssOneWidth = $this->width * $this->cssOneScale; - $this->cssOneHeight = $this->height * $this->cssOneScale; - - $this->cssSVGScale = 1; - - $this->scale = 1; - if ($this->book->parametres->zoomMode == 1) { - $this->multiply = $this->pdf2htmlRatio * $this->scale * $this->cssOneScale; - } else { - $this->multiply = $this->pdf2htmlRatio * $this->scale * $this->cssScale; - } - $this->numerotation = explode(',', $this->book->numerotation); - - $this->initConfig(); - $this->log('Defined dimensions'); - } - - public function initConfig() { - $this->config = cubeObject::merge($this->book->parametres->toStandardObject(), $this->theme->parametres->toStandardObject()); - $this->config->rasterizePages = cubeArray::parseRange($this->config->rasterizePages); - $this->config->vectorPages = array_diff(cubeArray::parseRange($this->config->vectorPages), $this->config->rasterizePages); - } - - public function log($step) { - $currenttime = microtime(true); - if (null === $this->logfp) { - $this->logfp = fopen('/var/log/extranet/htmlconversions/' . $this->book_id . '.log', 'w+'); - } - if (null === $this->logtime) { - $this->logtime = $currenttime; - } - $time = $currenttime - $this->logtime; - $log = $step . ' | ' . round($time, 3) . 's' . "\n"; - fwrite($this->logfp, $log); - fflush($this->logfp); - $this->logtime = $currenttime; - } - - public function addFacebookSDK() { - $lang = str_replace('-', '_', $this->book->lang); - $e = explode('_', $lang); - if (count($e) > 1) { - $e[1] = mb_strtoupper($lang); - } - $lang = implode('_', $e); - - $langsMap = ['fr' => 'fr_FR', 'en' => 'en_US']; - - if (isset($langsMap[$lang])) { - $lang = $langsMap[$lang]; - } - - $this->beginBody[] = "
+class wsHTML5Compiler +{ + protected static $resolutions = array(150, 300); + public $maxRes = 300; + + public $jsFiles = array( + 'js/libs/modernizr/modernizr.min.js', + 'js/libs/modernizr/tests.js', + 'js/libs/cube/fb.js', + 'js/libs/cube/util.js', + 'js/libs/screenfull.min.js', + 'js/libs/storage.js', + 'js/libs/keymaster.js', + 'js/libs/jquery/jquery.min.js', + 'js/libs/jquery/jquery.transform.js', + 'js/libs/jquery/jquery.form.min.js', + 'js/libs/jquery/jquery.mousewheel.min.js', + 'js/libs/jquery/jquery.hashchange.min.js', + 'js/libs/jquery/perfect-scrollbar.jquery.min.js', + 'js/libs/mmenu/jquery.mmenu.min.js', + 'js/libs/mmenu/jquery.mmenu.rtl.min.js', + 'js/libs/mmenu/jquery.mmenu.offcanvas.min.js', + 'js/libs/gsap/TweenMax.min.js', + 'js/libs/gsap/jquery.gsap.min.js', + 'js/libs/gal/gal.js', + 'js/libs/gal/gal.filesystem.js', + 'js/libs/hammer.min.js', + 'js/libs/fluidbook/forms/fluidbook.form.bulle.js', + 'js/libs/fluidbook/fluidbook.utils.js', + 'js/libs/fluidbook/fluidbook.links.js', + 'js/libs/fluidbook/fluidbook.support.js', + 'js/libs/fluidbook/fluidbook.video.js', + 'js/libs/fluidbook/fluidbook.viewport.js', + 'js/libs/fluidbook/fluidbook.desktop.js', + 'js/libs/fluidbook/fluidbook.service.js', + 'js/libs/fluidbook/fluidbook.share.js', + 'js/libs/fluidbook/fluidbook.l10n.js', + 'js/libs/fluidbook/fluidbook.slider.js', + 'js/libs/fluidbook/fluidbook.nav.js', + 'js/libs/fluidbook/fluidbook.interface.js', + 'js/libs/fluidbook/fluidbook.touch.js', + 'js/libs/fluidbook/fluidbook.loader.js', + 'js/libs/fluidbook/fluidbook.search.js', + 'js/libs/fluidbook/fluidbook.help.js', + 'js/libs/fluidbook/fluidbook.resize.js', + 'js/libs/fluidbook/fluidbook.stats.js', + 'js/libs/fluidbook/fluidbook.cache.js', + 'js/libs/fluidbook/fluidbook.tooltip.js', + 'js/libs/fluidbook/fluidbook.bookmarks.js', + 'js/libs/fluidbook/fluidbook.background.js', + 'js/libs/fluidbook/fluidbook.pad.js', + 'js/libs/fluidbook/fluidbook.audiodescription.js', + 'js/libs/fluidbook/fluidbook.privacy.js', + 'js/libs/fluidbook/fluidbook.zoom.js', + 'js/libs/fluidbook/fluidbook.menu.js', + 'js/libs/fluidbook/fluidbook.sound.js', + 'js/libs/fluidbook/fluidbook.scorm.js', + 'js/libs/fluidbook/menu/fluidbook.chapters.js', + 'js/libs/fluidbook/menu/fluidbook.index.js', + 'js/libs/fluidbook/fluidbook.landingpage.js', + 'js/libs/fluidbook/fluidbook.js', + 'js/main.js'); + + public $specialJsFiles = array(); + + public $debugJsFiles = array( + 'js/libs/Three.js', + 'data/search.index.js', + ); + public $testJsFiles = array( + 'js/libs/cube/fb.js', + 'js/libs/modernizr/modernizr.min.js', + 'js/libs/modernizr/tests.js', + 'js/libs/jquery/jquery.min.js', + 'js/libs/jquery/jquery.transform.min.js', + 'js/libs/jquery/jquery.mousewheel.min.js', + 'js/libs/jquery/jquery.hashchange.min.js', + 'js/tester.js' + ); + public $widgetJsFiles = array( + 'js/libs/cube/fb.js', + 'js/libs/modernizr/modernizr.min.js', + 'js/libs/modernizr/tests.js', + 'js/libs/jquery/jquery.min.js', + 'js/libs/jquery/jquery.transit.js', + 'js/widget.js' + ); + + // Collection of LESS files to be compiled + // Filename with no extension, relative to the /style directory in the player build folder + public $lessFiles = ['fluidbook']; + + public $specialCSS = array(); + public $phonegapStandardPlugins = array('ios' => array('ExternalFileUtil'), + 'android' => array('webintent')); + public $pluginCSS = array(); + public $pluginJs = array(); + public $htmlmultimedia = array(); + protected $cssX = array(); + protected $cssY = array(); + protected $cssWidths = array(); + protected $pdf2htmlRatio; + protected $scale; + protected $multiply; + protected $div = array(); + protected $numerotation; + protected $fontDocs = array(); + protected $dir; + protected $z = 3; + public $vdir; + public $wdir; + + /** + * + * @var wsBook + */ + public $book; + protected $pages; + protected $theme; + public $version; + public $book_id; + protected $themeRoot; + + /** + * + * @var wsDAOBook + */ + protected $daoBook; + protected $needToRecompileContents = true; + protected $needToRecompileSettings = true; + public $width; + public $height; + protected $cssWidth; + protected $cssHeight; + protected $cssOneWidth; + protected $cssOneHeight; + protected $cssScale; + protected $cssSVGScale; + protected $optimalWidth = 567; + protected $optimalHeight = 709; + protected $additionalConfig = array(); + protected $fontScale = 1; + protected $cache = array(); + protected $backgroundsPrefix = array(); + protected $svg = true; + protected $config = array(); + protected $assets = ''; + protected $phonegap = false; + protected $phonegapVersion; + protected $standalone = false; + protected $hiddenContents = array(); + protected $appcache; + protected $home; + protected $widget = true; + protected $multiApp = false; + protected $pageLabels = array(); + protected $stylesheets = array(); + protected $logfp = null; + protected $logtime = null; + protected $beginBody = array(); + protected $seoArticles = []; + protected $securityPolicyWhitelist = ['*.google-analytics.com', '*.youtube.com', '*.ytimg.com']; + + + function __construct($book_id, $version = 'stable', $phonegap = false, $phonegapVersion = 'latest', $dir = null, $standalone = false, $appcache = false, $home = false) + { + global $core; + + $this->phonegapVersion = wsHTML5::getPhonegapVersion($phonegapVersion); + $this->appcache = $appcache; + $this->multiApp = $this->home = $home; + $this->version = $version; + + if ($version == 'stable') { + $this->assets = WS_COMPILE_ASSETS . '/player/branches/master'; + } else if ($version == 'dev') { + $this->assets = WS_COMPILE_ASSETS . '/player/local/master'; + } else { + list($branch, $location) = explode('|', $version); + $this->assets = WS_COMPILE_ASSETS . '/player/' . ($location == 'git' ? 'branches' : $location) . '/' . $branch; + } + + $this->phonegap = $phonegap; + $this->standalone = $standalone || $this->phonegap; + $this->appcache = $appcache; + $this->widget = !$this->phonegap; + + cubePHP::set_memory('4G'); + + if (trim($book_id) == '') { + return; + } + $this->book_id = $book_id; + $this->log('Start compilation'); + + if (is_null($dir)) { + $this->dir = WS_BOOKS . '/html5/' . $book_id . '/'; + } else { + $this->dir = $dir; + } + $this->vdir = new CubeIT_Files_VirtualDirectory($this->dir); + $this->wdir = WS_BOOKS . '/working/' . $this->book_id . '/'; + + $this->daoBook = new wsDAOBook($core->con); + $this->book = $this->daoBook->selectById($book_id); + $this->pages = $this->daoBook->getPagesOfBook($book_id); + + + $daoTheme = new wsDAOTheme($core->con); + $this->theme = $daoTheme->getThemeOfBook($book_id, true); + $this->themeRoot = WS_THEMES . '/' . $this->theme->theme_id . '/'; + + $daoDoc = new wsDAODocument($core->con); + $firstDoc = $daoDoc->selectById($this->pages[1]['document_id']); + $size = $firstDoc->generalInfos['size']; + + $this->log('Got data from database'); + + $this->width = round($size[0], 3); + $this->height = round($size[1], 3); + + $imagesize = CubeIT_Image::getimagesize(wsDocument::getDir($this->pages[1]['document_id']) . 'html/h150-' . $this->pages[1]['document_page'] . '.jpg'); + $this->pdf2htmlRatio = round(($imagesize[0] * 0.48) / $this->width, 3); + + $this->cssScale = $this->z * min($this->optimalWidth / $this->width, $this->optimalHeight / $this->height); + $this->cssOneScale = $this->z * min(($this->optimalWidth * 2) / $this->width, $this->optimalHeight / $this->height); + + $this->cssWidth = $this->width * $this->cssScale; + $this->cssHeight = $this->height * $this->cssScale; + + $this->cssOneWidth = $this->width * $this->cssOneScale; + $this->cssOneHeight = $this->height * $this->cssOneScale; + + $this->cssSVGScale = 1; + + $this->scale = 1; + if ($this->book->parametres->zoomMode == 1) { + $this->multiply = $this->pdf2htmlRatio * $this->scale * $this->cssOneScale; + } else { + $this->multiply = $this->pdf2htmlRatio * $this->scale * $this->cssScale; + } + $this->numerotation = explode(',', $this->book->numerotation); + + $this->initConfig(); + $this->log('Defined dimensions'); + } + + public function initConfig() + { + $this->config = cubeObject::merge($this->book->parametres->toStandardObject(), $this->theme->parametres->toStandardObject()); + $this->config->rasterizePages = cubeArray::parseRange($this->config->rasterizePages); + $this->config->vectorPages = array_diff(cubeArray::parseRange($this->config->vectorPages), $this->config->rasterizePages); + } + + public function log($step) + { + $currenttime = microtime(true); + if (null === $this->logfp) { + $this->logfp = fopen('/var/log/extranet/htmlconversions/' . $this->book_id . '.log', 'w+'); + } + if (null === $this->logtime) { + $this->logtime = $currenttime; + } + $time = $currenttime - $this->logtime; + $log = $step . ' | ' . round($time, 3) . 's' . "\n"; + fwrite($this->logfp, $log); + fflush($this->logfp); + $this->logtime = $currenttime; + } + + public function addFacebookSDK() + { + $lang = str_replace('-', '_', $this->book->lang); + $e = explode('_', $lang); + if (count($e) > 1) { + $e[1] = mb_strtoupper($lang); + } + $lang = implode('_', $e); + + $langsMap = ['fr' => 'fr_FR', 'en' => 'en_US']; + + if (isset($langsMap[$lang])) { + $lang = $langsMap[$lang]; + } + + $this->beginBody[] = "
"; - $this->securityPolicyWhitelist[] = '*.facebook.net'; - $this->securityPolicyWhitelist[] = 'data:'; - } - - public function addPageLabel($page, $label) { - $this->pageLabels[$label] = $page; - } - - public function getResolutions() { - $res = []; - foreach (self::$resolutions as $r) { - if ($r > $this->maxRes) { - continue; - } - $res[] = $r; - } - if ($this->widget) { - $res = array_merge(array(36), $res); - } - return $res; - } - - public function getCssScale() { - return $this->cssScale; - } - - public function virtualToPhysical($virtual) { - if (isset($this->pageLabels[$virtual])) { - return $virtual; - } - if (!in_array($virtual, $this->numerotation)) { - return 1; - } - $p = array_search($virtual, $this->numerotation); - return $p + 1; - } - - public function compile($delete = true) { - - $this->log('Start compile process'); - - // Raw copy of some directories - $directories = array('style/fonts', 'images', 'sound', 'video'); - foreach ($directories as $directory) { - $from = $this->assets . '/' . $directory; - $this->vdir->copyDirectory($from, $directory); - } - - $this->log('Copied assets'); - $this->loadPlugins(); - $this->log('Plugins loaded'); - $this->writeImages(); - $this->log('Images written'); - $linksCSS = $this->writeLinks(); - $this->log('Links written'); - $this->writeCSS('data/style/style_%d.css', $linksCSS); - $this->log('CSS written'); - $this->writeLangs(); - $this->log('Langs written'); - $this->writeIndex(); - $this->log('Index written'); - $this->writeSounds(); - $this->log('Sound written'); - $this->writeTexts(); - $this->log('Texts written'); - $this->writeExtras(); - $this->log('Extras written'); - $this->writeJs(); - $this->log('Js written'); - $this->writeSEO(); - $this->vdir->sync($delete); - $this->log('Files Synced'); - } - - protected function loadPlugins() { - $e = explode("\n", $this->book->parametres->mobilePlugins); - - $main = array_pop($this->jsFiles); - - $plugins = array(); - - foreach ($e as $plugin) { - $plugin = trim($plugin); - if ($plugin == '') { - continue; - } - - $d = 'plugins/' . str_replace('.', '/', $plugin); - $dir = $this->assets . '/' . $d; - if (!file_exists($dir)) { - continue; - } - - $plugins[] = $plugin; - - if (file_exists($dir . '/plugin.js')) { - $f = $d . '/plugin.js'; - $this->pluginJs[] = $f; - $this->vdir->copy($dir . '/plugin.js', $f); - } - if (file_exists($dir . '/plugin.css')) { - $f = $d . '/plugin.css'; - $this->pluginCSS[] = $f; - $this->vdir->copy($dir . '/plugin.css', $f); - } - } - - $this->config->plugins = $plugins; - - array_push($this->jsFiles, $main); - } - - public function getVideosFormats($poster = true) { - $res = []; - // - // if (!$this->phonegap) { - // $res = array('ogv', 'webm', 'mp4', 'flv'); - // } elseif ($this->phonegap == 'ios') { - // $res = array('mp4'); - // } else if ($this->phonegap == 'android') { - // $res = array('webm', 'mp4'); - // } - - $res[] = 'mp4'; - - if ($poster) { - $res[] = 'jpg'; - } - return $res; - } - - /** - * Helper function to add a unique script entry to the JS stack. - * Normally this is a relative path but it can be an external URL. - * External URLs are added to the pluginJs collection instead of jsFiles. - * Duplicate paths are ignored. - * @param $path - */ - public function addJs($path, $collection = null) { - - if (null === $collection) { - // If JS is external, it will be included via the pluginJs collection - // Otherwise, it will be compiled into the main JS file - $collection = (preg_match('#^https?://#i', $path) === 1) ? 'pluginJs' : 'jsFiles'; - } - - if (!in_array($path, $this->$collection)) { - $this->{$collection}[] = $path; - } - } - - /** - * Helper function to add a unique stylesheet entry to the LESS stack for compilation - * Duplicate paths are ignored. - * @param $path The path of the file relative to the /style folder, without any extension - * @param $extra_files Optional array of extra files that should be copied across for use during LESS compilation - */ - public function addLess($path) { - if (!in_array($path, $this->lessFiles)) { - $this->lessFiles[] = $path; - } - } - - protected function writeSounds() { - if ($this->book->parametres->soundTheme == '') { - return; - } - $this->vdir->copyDirectory(WS_SOUNDS . '/' . $this->book->parametres->soundTheme, 'data/sounds'); - } - - protected function writeIndex() { - global $core; - - $html = file_get_contents($this->assets . '/_index.html'); - $uhtml = $html; - - $titre = $this->book->parametres->title; - - - $daoSignature = new wsDAOSignature($core->con); - $signature = $daoSignature->selectById($this->book->parametres->signature); - - $exportSignature = array('main' => $signature->main, - 'mainLink' => $signature->mainLink, - 'partner' => $signature->partner, - 'partnerLink' => $signature->partnerLink); - - $credits = ''; - if ($signature->partner != '') { - $credits = '' . $signature->partner . ' '; - } - $credits .= '' . $signature->main . ''; - - $hiddenContents = implode("\n", $this->hiddenContents); - - $bgcolor = $this->theme->parametres->loadingBackColor; - - // Google analytics - $ga = ''; - if ($this->book->parametres->googleAnalytics != '') { - $ga = cubePage::googleAnalytics($this->book->parametres->googleAnalytics); - } - if ($this->book->parametres->googleAnalyticsCustom != '') { - $ga .= $this->book->parametres->googleAnalyticsCustom; - } - - $statsfooter = ''; - if ($this->book->parametres->statsCustom != '') { - $statsfooter = $this->book->parametres->statsCustom; - } - // Feuilles de style - $sheets = array_merge($this->stylesheets, $this->specialCSS); - - $style = array(); - foreach ($sheets as $sheet) { - $style[] = ''; - } - $style = implode("\n\t\t", $style); - - $pagesContents = ''; - - $cache = ''; - - $beginbody = implode("\n", array_unique($this->beginBody)); - - $iscript = ''; - if (count($this->htmlmultimedia)) { - $iscript .= '' . "\n"; - } - - $script = ''; - $script .= '' . "\n"; - $script .= '' . "\n"; - if ($this->book->parametres->scorm_enable) { - $script .= '' . "\n"; - $this->writeScorm(); - } - if (count($this->specialJsFiles)) { - $script .= '' . "\n"; - } - foreach ($this->pluginJs as $p) { - $script .= '' . "\n"; - } - $script .= $iscript; - $description = ''; - - $socialTitle = $this->book->parametres->facebook_title ? $this->book->parametres->facebook_title : $titre; - $socialDescription = $this->book->parametres->seoDescription ? $this->book->parametres->seoDescription : $this->book->parametres->seoDescription; - $socialImage = 'https://workshop.fluidbook.com/services/facebook_thumbnail?id=' . $this->book_id . '&j=' . time(); - $dim = CubeIT_Image::getimagesize($socialImage); - $socialImageWidth = $dim[0]; - $socialImageHeight = $dim[1]; - - $twittercard = ' + $this->securityPolicyWhitelist[] = '*.facebook.net'; + $this->securityPolicyWhitelist[] = 'data:'; + } + + public function addPageLabel($page, $label) + { + $this->pageLabels[$label] = $page; + } + + public function getResolutions() + { + $res = []; + foreach (self::$resolutions as $r) { + if ($r > $this->maxRes) { + continue; + } + $res[] = $r; + } + if ($this->widget) { + $res = array_merge(array(36), $res); + } + return $res; + } + + public function getCssScale() + { + return $this->cssScale; + } + + public function virtualToPhysical($virtual) + { + if (isset($this->pageLabels[$virtual])) { + return $virtual; + } + if (!in_array($virtual, $this->numerotation)) { + return 1; + } + $p = array_search($virtual, $this->numerotation); + return $p + 1; + } + + public function compile($delete = true) + { + + $this->log('Start compile process'); + + // Raw copy of some directories + $directories = array('style/fonts', 'images', 'sound', 'video'); + foreach ($directories as $directory) { + $from = $this->assets . '/' . $directory; + $this->vdir->copyDirectory($from, $directory); + } + + $this->log('Copied assets'); + $this->loadPlugins(); + $this->log('Plugins loaded'); + $this->writeImages(); + $this->log('Images written'); + $linksCSS = $this->writeLinks(); + $this->log('Links written'); + $this->writeCSS('data/style/style_%d.css', $linksCSS); + $this->log('CSS written'); + $this->writeLangs(); + $this->log('Langs written'); + $this->writeIndex(); + $this->log('Index written'); + $this->writeSounds(); + $this->log('Sound written'); + $this->writeTexts(); + $this->log('Texts written'); + $this->writeExtras(); + $this->log('Extras written'); + $this->writeJs(); + $this->log('Js written'); + $this->writeSEO(); + $this->vdir->sync($delete); + $this->log('Files Synced'); + } + + protected function loadPlugins() + { + $e = explode("\n", $this->book->parametres->mobilePlugins); + + $main = array_pop($this->jsFiles); + + $plugins = array(); + + foreach ($e as $plugin) { + $plugin = trim($plugin); + if ($plugin == '') { + continue; + } + + $d = 'plugins/' . str_replace('.', '/', $plugin); + $dir = $this->assets . '/' . $d; + if (!file_exists($dir)) { + continue; + } + + $plugins[] = $plugin; + + if (file_exists($dir . '/plugin.js')) { + $f = $d . '/plugin.js'; + $this->pluginJs[] = $f; + $this->vdir->copy($dir . '/plugin.js', $f); + } + if (file_exists($dir . '/plugin.css')) { + $f = $d . '/plugin.css'; + $this->pluginCSS[] = $f; + $this->vdir->copy($dir . '/plugin.css', $f); + } + } + + $this->config->plugins = $plugins; + + array_push($this->jsFiles, $main); + } + + public function getVideosFormats($poster = true) + { + $res = []; + // + // if (!$this->phonegap) { + // $res = array('ogv', 'webm', 'mp4', 'flv'); + // } elseif ($this->phonegap == 'ios') { + // $res = array('mp4'); + // } else if ($this->phonegap == 'android') { + // $res = array('webm', 'mp4'); + // } + + $res[] = 'mp4'; + + if ($poster) { + $res[] = 'jpg'; + } + return $res; + } + + /** + * Helper function to add a unique script entry to the JS stack. + * Normally this is a relative path but it can be an external URL. + * External URLs are added to the pluginJs collection instead of jsFiles. + * Duplicate paths are ignored. + * @param $path + */ + public function addJs($path, $collection = null) + { + + if (null === $collection) { + // If JS is external, it will be included via the pluginJs collection + // Otherwise, it will be compiled into the main JS file + $collection = (preg_match('#^https?://#i', $path) === 1) ? 'pluginJs' : 'jsFiles'; + } + + if (!in_array($path, $this->$collection)) { + $this->{$collection}[] = $path; + } + } + + /** + * Helper function to add a unique stylesheet entry to the LESS stack for compilation + * Duplicate paths are ignored. + * @param $path The path of the file relative to the /style folder, without any extension + * @param $extra_files Optional array of extra files that should be copied across for use during LESS compilation + */ + public function addLess($path) + { + if (!in_array($path, $this->lessFiles)) { + $this->lessFiles[] = $path; + } + } + + protected function writeSounds() + { + if ($this->book->parametres->soundTheme == '') { + return; + } + $this->vdir->copyDirectory(WS_SOUNDS . '/' . $this->book->parametres->soundTheme, 'data/sounds'); + } + + protected function writeIndex() + { + global $core; + + $html = file_get_contents($this->assets . '/_index.html'); + $uhtml = $html; + + $titre = $this->book->parametres->title; + + + $daoSignature = new wsDAOSignature($core->con); + $signature = $daoSignature->selectById($this->book->parametres->signature); + + $exportSignature = array('main' => $signature->main, + 'mainLink' => $signature->mainLink, + 'partner' => $signature->partner, + 'partnerLink' => $signature->partnerLink); + + $credits = ''; + if ($signature->partner != '') { + $credits = '' . $signature->partner . ' '; + } + $credits .= '' . $signature->main . ''; + + $hiddenContents = implode("\n", $this->hiddenContents); + + $bgcolor = $this->theme->parametres->loadingBackColor; + + // Google analytics + $ga = ''; + if ($this->book->parametres->googleAnalytics != '') { + $ga = cubePage::googleAnalytics($this->book->parametres->googleAnalytics); + } + if ($this->book->parametres->googleAnalyticsCustom != '') { + $ga .= $this->book->parametres->googleAnalyticsCustom; + } + + $statsfooter = ''; + if ($this->book->parametres->statsCustom != '') { + $statsfooter = $this->book->parametres->statsCustom; + } + // Feuilles de style + $sheets = array_merge($this->stylesheets, $this->specialCSS); + + $style = array(); + foreach ($sheets as $sheet) { + $style[] = ''; + } + $style = implode("\n\t\t", $style); + + $pagesContents = ''; + + $cache = ''; + + $beginbody = implode("\n", array_unique($this->beginBody)); + + $iscript = ''; + if (count($this->htmlmultimedia)) { + $iscript .= '' . "\n"; + } + + $script = ''; + $script .= '' . "\n"; + $script .= '' . "\n"; + if ($this->book->parametres->scorm_enable) { + $script .= '' . "\n"; + $this->writeScorm(); + } + if (count($this->specialJsFiles)) { + $script .= '' . "\n"; + } + foreach ($this->pluginJs as $p) { + $script .= '' . "\n"; + } + $script .= $iscript; + $description = ''; + + $socialTitle = $this->book->parametres->facebook_title ? $this->book->parametres->facebook_title : $titre; + $socialDescription = $this->book->parametres->seoDescription ? $this->book->parametres->seoDescription : $this->book->parametres->seoDescription; + $socialImage = 'https://workshop.fluidbook.com/services/facebook_thumbnail?id=' . $this->book_id . '&j=' . time(); + $dim = CubeIT_Image::getimagesize($socialImage); + $socialImageWidth = $dim[0]; + $socialImageHeight = $dim[1]; + + $twittercard = ' '; - $opengraph = ' + $opengraph = ' '; - $favicon = ''; - $hasIos = false; - if ($this->theme->parametres->iosicon != '') { - $hasIos = true; - $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->iosicon, 'data/apple-touch-icon.png'); - $favicon .= ''; - } - if ($this->theme->parametres->favicon != '') { - - $pngFile = $this->themeRoot . '/' . $this->theme->parametres->favicon; - $icoFile = $this->themeRoot . '/favicon.ico'; - if (!file_exists($icoFile) || filemtime($icoFile) < filemtime($pngFile) || filemtime(__FILE__) > filemtime($icoFile)) { - $tmp = CubeIT_Files::tempnam() . '.png'; - $convert = "convert $pngFile -resize 64x64^ -gravity center $tmp"; - `$convert`; - - $icotool = new cubeCommandLine('icotool'); - $icotool->setArg('c'); - $icotool->setArg('o', $icoFile); - $icotool->setArg(null, $tmp); - $icotool->execute(); - - unlink($tmp); - } - $this->vdir->copy($pngFile, 'data/favicon.png'); - $this->vdir->copy($icoFile, 'data/favicon.ico'); - $favicon .= ''; - $favicon .= ''; - $favicon .= ''; - if (!$hasIos) { - $favicon .= ''; - } - } - - $print = $this->writePrint(); - $message = sprintf($this->__('Your browser is not up to date and is not able to run this publication. %sLearn more%s'), '
', ''); - - $splash = ''; - if ($this->theme->parametres->logoLoader && file_exists($this->themeRoot . $this->theme->parametres->logoLoader)) { - $dim = CubeIT_Image::getimagesize($this->themeRoot . $this->theme->parametres->logoLoader); - if ($dim !== false) { - $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->logoLoader, 'data/images/' . $this->theme->parametres->logoLoader); - $splash .= ''; - } - } - - $svgfiles = array($this->assets . '/images/interface.svg', WS_ICONS . '/' . $this->theme->parametres->iconSet . '/interface.svg'); - $svg = ''; - foreach ($svgfiles as $svgfile) { - if (file_exists($svgfile)) { - $svg .= file_get_contents($svgfile); - } else { - die($svgfile . ' does not exist'); - } - } - - if ($this->phonegap) { - $csp = "securityPolicyWhitelist)) . "; img-src * data:\">"; - } - $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'pagesContents', 'description', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon', 'svg', 'beginbody', 'csp', 'opengraph', 'twittercard'); - foreach ($vars as $v) { - if (isset($$v)) { - $html = str_replace('', $$v, $html); - } else { - $html = str_replace('', '', $html); - } - } - - $scripts = array(); - foreach ($this->debugJsFiles as $js) { - $scripts[] = ''; - } - foreach ($this->jsFiles as $js) { - $scripts[] = ''; - } - foreach ($this->pluginJs as $js) { - $scripts[] = ''; - } - - $scripts[] = ''; - $scripts[] = $iscript; - $script = implode("\n\t\t", $scripts); - - $scripts = array(); - foreach ($this->testJsFiles as $js) { - $scripts[] = ''; - } - $scripts[] = ''; - $script_test = implode("\n\t\t", $scripts); - - $thtml = $uhtml; - - $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'pagesContents', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon'); - foreach ($vars as $v) { - $uhtml = str_replace('', $$v, $uhtml); - } - - $script .= "\n\t\t" . ''; - $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'print', 'hiddenContents', 'splash', 'message'); - foreach ($vars as $v) { - $thtml = str_replace('', $$v, $thtml); - } - - $this->vdir->file_put_contents('index.html', $html); - $this->vdir->file_put_contents('indexu.html', $uhtml); - $this->vdir->file_put_contents('indext.html', $thtml); - - // Write widget html - if ($this->widget) { - $whtml = file_get_contents($this->assets . '/widget.html'); - $script = ''; - $script .= ''; - - $style = ''; - $vars = array('titre', 'style', 'script'); - foreach ($vars as $v) { - $whtml = str_replace('', $$v, $whtml); - } - $this->vdir->file_put_contents('widget.html', $whtml); - } - } - - function writeSEO() { - foreach ($this->seoArticles as $seoArticle) { - $html = file_get_contents($this->assets . '/_seo.html'); - $a = $seoArticle; - unset($a['image']); - $a['imageurl'] = 'https://workshop.fluidbook.com/services/facebook_thumbnail?id=15793&j=' . time(); - if ($seoArticle['image']) { - $a['imageurl'] .= '&image=' . $seoArticle['image']; - } - $dim = CubeIT_Image::getimagesize($a['imageurl']); - $a['imagewidth'] = $dim[0]; - $a['imageheight'] = $dim[1]; - foreach ($a as $k => $v) { - $html = str_replace('$' . $k, $v, $html); - } - $this->vdir->file_put_contents('p/' . $seoArticle['url'], $html); - } - } - - protected function writeScorm() { - $manifest = file_get_contents($this->assets . '/_imsmanifest.xml'); - if (!$this->book->parametres->scorm_title) { - $this->book->parametres->scorm_title = $this->book->parametres->title; - } - if (!$this->book->parametres->scorm_id) { - $this->book->parametres->scorm_id = 'fb_' . $this->book->parametres->id; - } - if (!$this->book->parametres->scorm_org) { - $this->book->parametres->scorm_org = 'Fluidbook'; - } - $vars = array('scorm_id', 'scorm_org', 'scorm_title'); - foreach ($vars as $v) { - $manifest = str_replace('$' . $v, $this->book->parametres->$v, $manifest); - } - $this->vdir->file_put_contents('imsmanifest.xml', $manifest); - - $variables = []; - $e = CubeIT_Text::explodeNewLines($this->book->parametres->scorm_variables); - foreach ($e as $item) { - $item = trim($item); - if ($item == '') { - continue; - } - $f = explode('=', $item, 2); - $variables[$f[0]] = $f[1]; - } - $this->config->scorm_variables = $this->book->parametres->scorm_variables = $variables; - } - - protected function writePrint() { - - if (!$this->book->parametres->print && !$this->book->parametres->pdf) { - return; - } - - $this->vdir->copy(WS_BOOKS . '/final/' . $this->book->book_id . '/data/' . $this->book->parametres->pdfName, 'data/' . $this->book->parametres->pdfName); - return ''; - } - - protected function addFilesInfos($key, $file) { - if (!file_exists($file)) { - return; - } - if (!isset($this->config->filesInfos)) { - $this->config->filesInfos = array(); - } - $infos = array('filesize' => filesize($file)); - $dim = CubeIT_Image::getimagesize($file); - if ($dim !== false) { - $infos['width'] = $dim[0]; - $infos['height'] = $dim[1]; - } - $this->config->filesInfos[$key] = $infos; - } - - protected function __($str) { - if (!isset($this->config->l10n)) { - $this->writeLangs(); - } - - if (isset($this->config->l10n['default']->$str)) { - return $this->config->l10n['default']->$str; - } else { - return $str; - } - } - - protected function writeLangs() { - global $core; - $daoLang = new wsDAOLang($core->con); - $lang = $daoLang->selectById($this->book->lang); - $langs = $daoLang->selectAll(); - - $traductions = (!count($this->book->traductions)) ? $lang->traductions : $this->book->traductions; - - $this->config->l10n = array(); - $this->config->l10n['default'] = $traductions; - $this->config->defaultLang = $this->book->lang; - - foreach ($langs as $lang) { - $this->config->l10n[$lang->lang_id] = $lang->traductions; - } - $iso = l10n::getISOcodes(); - if ($this->book->parametres->multilang != '') { - $flagsDir = 'images/flags'; - if (!file_exists($flagsDir)) { - mkdir($flagsDir); - } - $ml = str_replace("\r", "\n", $this->book->parametres->multilang); - $ml = str_replace("\n\n", "\n", $ml); - $e = explode("\n", $ml); - $m = array(); - foreach ($e as $l1) { - $l = explode(',', $l1); - $flag = $l[1]; - - $ll = explode('-', $l[0]); - - $this->vdir->copy(cubeMedia::getFlagFile($flag), $flagsDir . '/' . $flag . '.png'); - $l[3] = cubeText::ucfirst($iso[$l[0]]); - $l[4] = cubeCountry::getCountryName($flag, $ll[0]); - $m[] = implode(',', $l); - } - - $this->config->multilang = implode("\n", $m); - } - } - - protected function writeExtras() { - if ($this->theme->parametres->afterSearch != '') { - $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->afterSearch, 'data/images/' . $this->theme->parametres->afterSearch); - } - if ($this->book->parametres->externalArchives != '') { - $this->addFilesInfos('archives', $this->wdir . '/' . $this->book->parametres->externalArchives); - $this->vdir->copy($this->wdir . '/' . $this->book->parametres->externalArchives, 'data/images/' . $this->book->parametres->externalArchives); - } - - if ($this->book->parametres->navExtraImage != '') { - $this->vdir->copy($this->wdir . '/' . $this->book->parametres->navExtraImage, 'data/images/' . $this->book->parametres->navExtraImage); - } - - if ($this->book->parametres->navExtraImageMobile != '') { - $this->vdir->copy($this->wdir . '/' . $this->book->parametres->navExtraImageMobile, 'data/images/' . $this->book->parametres->navExtraImageMobile); - } - - for ($i = 1; $i <= 5; $i++) { - $ic = $this->book->parametres->{'navExtraIcon' . $i}; - if ($ic != '') { - $this->vdir->copy($this->wdir . '/' . $ic, 'data/images/' . $ic); - } - } - - } - - protected function writeLinks() { - global $core; - - if ($this->book->parametres->customLinkClass == 'WescoSalesLink') { - $this->specialJsFiles[] = 'js/libs/interact.min.js'; - $this->specialJsFiles[] = 'js/libs/fluidbook/special/wescosales.js'; - $this->specialCSS[] = 'wescosales'; - } - - if ($this->book->parametres->customLinkClass == 'AtlanticDownloadLink') { - $this->specialJsFiles[] = 'js/libs/fluidbook/special/atlanticdownload.js'; - $this->specialCSS[] = 'atlanticdownload'; - } - - $this->config->links = array(); - $this->config->clinks = array(); - $this->config->bookmarkGroups = array(); - - $ignore = $this->book->parametres->ignoreLinksTypes; - if (!$ignore) { - $ignore = array(); - } else { - $ignore = split(',', $ignore); - } - - if ($this->book->parametres->externalChaptersHTML != '') { - $d = $this->unzipFile($this->book->parametres->externalChaptersHTML, false, 'data/chapters/'); - $meta = $this->getConfigZIP($d['dir']); - $this->config->externalChaptersSize = new stdClass(); - $this->config->externalChaptersSize->width = $meta['width']; - $this->config->externalChaptersSize->height = $meta['height']; - $this->vdir->copyDirectory($d['dir'], $d['fdir']); - } - - $daoDoc = new wsDAODocument($core->con); - $daoDoc->getLinksAndRulers($this->book_id, $links, $rulers); - - // Custom landing page content - if ($this->book->parametres->landingPage != '') { - $d = $this->unzipFile($this->book->parametres->landingPage, false, 'data/landing-page/'); - $this->vdir->copyDirectory($d['dir'], $d['fdir']); - } - - if ($this->book->parametres->tabsHTML5 != '') { - $links[] = [ - 'page' => 'background', - 'top' => 0, - 'left' => 0, - 'width' => 100, - 'height' => 100, - 'type' => 6, - 'to' => $this->book->parametres->tabsHTML5, - 'alternative' => $this->book->parametres->tabsHTML5, - 'image' => '', - 'inline' => 1, - 'interactive' => 1, - 'class' => 'tabslink', - ]; - } - - - foreach ($links as $linkData) { - if (isset($linkData['image']) && $linkData['image'] && $linkData['type'] != 28) { - $dupData = $linkData; - $dupData['image'] = ''; - $dupData['to'] = $linkData['image']; - $dupData['type'] = 15; - array_push($links, $dupData); - } - } - - $i = 0; - $pages = array(); - $cpages = array(); - $css = array(); - - usort($links, array($this, '_sortLinks')); - - foreach ($links as $linkData) { - if (in_array($linkData['type'], $ignore)) { - continue; - } - if ($linkData['type'] == 28) { - $this->addSEOArticle($linkData['page'], $linkData['to'], $linkData['extra'], $linkData['image']); - continue; - } - $link = wsHTML5Link::getInstance($this->base62($i), $linkData, $this); - if (is_null($link)) { - continue; - } - - // Make old "aftersearch" link compatible with new "extra" menu option by extracting link URL - if ($link->page == 'aftersearch') { - $this->config->afterSearchLink = $link->to; - $this->config->afterSearchTooltip = $link->infobulle; - } - - - $c = $link->getHTMLContainer(); - $css[] = $link->getCSSContainer(); - if (!isset($pages[$link->page])) { - $pages[$link->page] = ''; - $cpages[$link->page] = ''; - } - if ($link instanceof contentLink) { - $cpages[$link->page] .= $c; - } else { - $pages[$link->page] .= $c; - } - - if ($link->keep()) { - $this->hiddenContents[] = $c; - } - $i++; - } - - $allpages = range(0, $this->book->parametres->pages + 1); - if ($this->book->parametres->themeEnableAfterSearch) { - $allpages[] = 'aftersearch'; - } - $allpages[] = 'background'; - $allpages[] = 'archives'; - - foreach ($allpages as $i) { - - $c = ''; - $cc = ''; - if (isset($pages[$i])) { - $c = $pages[$i]; - } - if (isset($cpages[$i])) { - $cc = $cpages[$i]; - } - $this->config->links[$i] = $c; - $this->config->clinks[$i] = $cc; - } - return $css; - } - - public function addSEOArticle($page, $title, $intro, $image) { - $this->seoArticles[$title] = ['title' => $title, 'description' => $intro, 'image' => $image, 'content' => '', 'page' => $page, 'url' => CubeIT_Text::str2URL($title) . '.html']; - } - - public function _sortLinks($a, $b) { - $priorities = array(26 => 1); - - $pa = isset($priorities[$a['type']]) ? $priorities[$a['type']] : 0; - $pb = isset($priorities[$b['type']]) ? $priorities[$b['type']] : 0; - return $pb - $pa; - } - - public function addBookmarkGroup($link) { - if ($link['left'] > $this->book->parametres->width) { - //$link['page']++; - } - if ($link['page'] <= 0 || $link['page'] > $this->book->parametres->pages) { - return; - } - - $this->config->bookmarkGroups[] = array('page' => ($link['page']), 'nb' => $link['to'], 'name' => $link['extra']); - } - - public function addAudiodescription($link) { - $this->config->audiodescription[$link['page']] = $link['to']; - $this->copyLinkFile($link['to'], 'data/audiodescription/'); - } - - protected function writeJs() { - $config = $this->writeConfig(); - $this->vdir->file_put_contents('data/datas.js', $config); - $finals = array('fluidbook' => $this->jsFiles); - if ($this->book->parametres->scorm_enable) { - $finals['scorm'] = array(); - $finals['scorm'][] = 'js/libs/scorm/apiwrapper.js'; - $finals['scorm'][] = 'js/libs/scorm/scorm.js'; - } - if (count($this->specialJsFiles)) { - $finals['special'] = $this->specialJsFiles; - } - if ($this->widget) { - $finals['widget'] = $this->widgetJsFiles; - } - - foreach ($finals as $jsfinal => $files) { - $mintime = 0; - $hash = hash('sha256', json_encode($files)); - $minimized = $this->assets . '/js/min/' . $jsfinal . '-' . $hash . '-min.js'; - if (!file_exists(dirname($minimized))) { - mkdir(dirname($minimized)); - } - if (file_exists($minimized)) { - $mintime = filemtime($minimized); - $reminimize = false; - } else { - $mintime = 0; - $reminimize = true; - } - - if (!$reminimize) { - foreach ($files as $file) { - if (filemtime($this->assets . '/' . $file) > $mintime) { - $reminimize = true; - break; - } - } - } - - if (!$reminimize) { - if (filemtime(__FILE__) > $mintime || (file_exists(__DIR__ . '/class.ws.html5.links.php') && filemtime(__DIR__ . '/class.ws.html5.links.php') > $mintime)) { - $reminimize = true; - } - } - - if ($reminimize) { - $js = ''; - foreach ($files as $file) { - $js .= file_get_contents($this->assets . '/' . $file); - $js .= ";\n\n"; - } - $tmp = cubeFiles::tempnam(); - file_put_contents($tmp, $js); - - unlink($minimized); - - $uglify = new CubeIT_CommandLine('/usr/local/bin/uglifyjs'); - $uglify->setArg('o', $minimized); - $uglify->setArg(null, $tmp); - $uglify->execute(); - $uglify->debug(); - - if (!file_exists($minimized)) { - die('An error occured while uglifying : ' . $uglify->output); - } - } - $dest = 'data/' . $jsfinal . '.js'; - $this->vdir->copy($minimized, $dest); - } - - - if ($this->phonegap) { - $this->vdir->copy(WS_COMPILE_ASSETS . '/_html5/js/libs/phonegap/' . $this->phonegapVersion . '/cordova-' . $this->phonegap . '.js', 'data/cordova.js'); - } - - } - - public function writeTexts() { - $this->daoBook->makeTextsIndexes($this->book, $this->pages, $index, $textes, true); - $this->vdir->file_put_contents('data/search.index.js', 'var INDEX=' . $index . ';' . "\r"); - if ($this->book->parametres->highlightResults) { - $this->vdir->file_put_contents('data/search.highlight.js', 'var HIGHLIGHTS=' . json_encode($this->daoBook->makeHighlightIndex($this->book, $this->pages)) . ";\r"); - } - } - - public function supportSVG() { - if (!$this->phonegap) { - return false; - } else if ($this->phonegap == 'ios') { - return true; - } else { - return false; - } - } - - protected function writeConfig() { - $this->config->numerotation = explode(',', $this->book->numerotation); - $this->config->id = $this->book->book_id; - $this->config->cid = $this->book->cid; - $this->config->cacheDate = TIME; - $this->config->width = $this->cssWidth; - $this->config->height = $this->cssHeight; - $this->config->optimalWidth = $this->optimalWidth; - $this->config->optimalHeight = $this->optimalHeight; - $this->config->chapters = $this->book->chapters; - $this->config->videoFormats = $this->getVideosFormats(false); - $this->config->htmlmultimedia = $this->htmlmultimedia; - $this->config->phonegap = $this->phonegap; - $this->config->retinaResolution = min($this->book->parametres->maxResolution, $this->maxRes); - $this->config->pageLabels = $this->pageLabels; - $this->config->pageZoomFactor = $this->z; - $this->config->multiply = $this->multiply; - $this->config->cssScale = $this->cssScale; - $this->config->pdfZoomFactor = $this->pdf2htmlRatio; - if ($this->home) { - $this->config->home = 'http://home'; - } - $this->config->multiApp = $this->multiApp; - foreach ($this->additionalConfig as $k => $v) { - $this->config->$k = $v; - } - if ($this->phonegap && ($this->book->parametres->offlineLink == '' || $this->book->parametres->offlineLink == 'http://')) { - $this->config->share = false; - } - - // We need to be able to reference both navOrder and navOrderH so convert both to arrays - // We also make sure there are no empty items in the arrays (see: http://php.net/manual/en/function.array-filter.php#111091) - $this->config->navOrder = array_filter(array_map('trim', explode(',', $this->config->navOrder)), 'strlen'); - $this->config->navOrderH = array_filter(array_map('trim', explode(',', $this->config->navOrderH)), 'strlen'); - - $this->config->standalone = $this->standalone; - if ($this->config->phonegap) { - $this->config->manifest = $this->writeManifest(); - } - - if ($this->config->basket) { - if (file_exists($this->config->basketReferences) || CubeIT_Util_Url::isDistant($this->config->basketReferences)) { - $referencesFile = $this->config->basketReferences; - } else { - $referencesFile = $this->wdir . '/commerce/' . $this->config->basketReferences; - } - - if (file_exists($referencesFile) || CubeIT_Util_Url::isDistant($referencesFile)) { - $ext = CubeIT_Files::getExtension($referencesFile); - if ($ext == 'xlsx') { - $this->config->basketReferences = wsUtil::excelToArray($referencesFile); - if ($this->book->parametres->customLinkClass == 'AtlanticDownloadLink') { - $this->config->basketReferences = wsUtil::atlanticReferences($this->config->basketReferences, 'local/', array($this, 'log'), array($this->vdir, "copy")); - } - } - $this->log("Done cart references"); - } - } - $this->config->seoArticles = $this->seoArticles; - - return 'var DATAS=' . json_encode($this->config) . ';' . "\n"; - } - - protected function writeManifest() { - $res = array(); - } - - protected function writeIcons() { - $res = array(); - // Get the colors used to colorize graphics - if ($this->theme->parametres->colorizeIcons) { - $couleurI = $this->theme->parametres->couleurI; - } else { - $couleurI = 'FFFFFF'; - } - - $couleurM = $this->theme->parametres->subTextColor; - - $bookmarksDisabledColors = array('star' => $this->theme->parametres->bookmarkStarDisabledColor, 'bookmark' => $this->theme->parametres->bookmarkBackgroundColor); - $bookmarksEnabledColors = array('star' => $this->theme->parametres->bookmarkStarEnabledColor, 'bookmark' => $this->theme->parametres->bookmarkBackgroundColor); - $subTextColor = $this->theme->parametres->subTextColor; - - $arrowsColor = $this->theme->parametres->arrowsColor; - // Set the icon list with the color - $icons = array('interface-down' => $arrowsColor, 'interface-close' => $arrowsColor, - 'interface-audio-description-on' => $arrowsColor, 'interface-audio-description-off' => $arrowsColor, - 'help-fingers' => $couleurI, 'help-mouse' => $couleurI, - 'bookmark-left-off' => $bookmarksDisabledColors, 'bookmark-left-on' => $bookmarksEnabledColors, - 'bookmark-right-off' => $bookmarksDisabledColors, 'bookmark-right-on' => $bookmarksEnabledColors - ); - - $this->config->iconsDimensions = array(); - $makepng = !$this->supportSVG(); - $tmpdir = CubeIT_Files::tmpdir(); - foreach ($icons as $icon => $color) { - wsTools::colorizeAndRasterizeIcon($this->theme->parametres->iconSet, $icon, $color, $tmpdir, 4, $w, $h); - $this->config->iconsDimensions[$icon] = array($w, $h); - } - $this->vdir->copyDirectory($tmpdir, 'data/images'); - $this->vdir->addTemp($tmpdir); - return $res; - } - - protected function writeImages() { - global $core; - - switch ($this->book->parametres->mobileVersion) { - case 'html5-desktop': - $this->backgroundsPrefix = array('t', 'p'); - $this->svg = true; - break; - case 'html5-images': - $this->backgroundsPrefix = array('t'); - $this->svg = false; - break; - default: - $this->backgroundsPrefix = array('p'); - $this->svg = true; - break; - } - - $thumbs = array(); - foreach ($this->pages as $page => $infos) { - $docdir = wsDocument::getDir($infos['document_id']); - if ($this->svg) { - $full = $docdir . 'html/fp' . $infos['document_page'] . '.svg'; - $fullopt = $docdir . 'html/fo' . $infos['document_page'] . '%s.svg'; - $orig = $docdir . 'html/tp' . $infos['document_page'] . '.svg'; - $opt = $docdir . 'html/to' . $infos['document_page'] . '.svg'; - - if (!file_exists($full) || filemtime($full) < 1503671520) { - if (!isset($doc) || $doc->document_id != $infos['document_id']) { - $dao = new wsDAODocument($core->con); - $doc = $dao->selectById($infos['document_id']); - } - $doc->makeSVGFile($infos['document_page']); - } - wsDocument::extractTexts($full, $orig); - wsTools::optimizeSVG($orig, $opt); - wsTools::optimizeSVG($full, $fullopt, [150, 300]); - - if (in_array($page, $this->config->vectorPages)) { - $this->vdir->copy(str_replace('%s', '-150', $fullopt), 'data/contents/p' . $page . '.svg'); - } else { - $this->vdir->copy($opt, 'data/contents/p' . $page . '.svg'); - } - } - - - foreach ($this->getResolutions() as $r) { - foreach ($this->backgroundsPrefix as $backgroundsPrefix) { - $srcPrefix = $backgroundsPrefix; - if ($backgroundsPrefix == 'p') { - $srcPrefix = 'h'; - } - $ok = $this->vdir->copy($docdir . 'html/' . $srcPrefix . $r . '-' . $infos['document_page'] . '.jpg', 'data/background/' . $r . '/' . $backgroundsPrefix . $page . '.jpg'); - if (!$ok && $r = 300) { - $this->maxRes = 150; - } - } - } - - $thumb = false; - if ($this->book->parametres->pdfThumbnails) { - $thumb = wsPDFConvert::getThumbFromPDF(WS_BOOKS . '/working/' . $this->book->book_id . '/' . $this->book->parametres->pdfThumbnails, $page); - } - if (!$thumb) { - $thumb = $docdir . 'p' . $infos['document_page'] . '.jpg'; - } - - $thumbs[$page] = $thumb; - $this->vdir->copy($thumb, 'data/thumbnails/p' . $page . '.jpg'); - - if ($page == 1) { - $this->_makeCover($docdir . 'html/t36-' . $infos['document_page'] . '.jpg'); - } - - $this->log('Copied image ' . $page); - } - - - $this->makeThumbSprites($thumbs); - $this->log('Made thumbnails'); - } - - public function makeThumbSprites(array $thumbs) { - $cols = 10; - $rows = 10; - $perSprite = $cols * $rows; - $k = 0; - $res = ''; - $pages = count($thumbs); - - $hash = ''; - for ($i = 1; $i <= $pages; $i += $perSprite) { - $num = min(1 + $pages - $i, $perSprite); - $srows = ceil($num / $cols); - $files = array(); - $mtime = 0; - for ($j = 0; $j < $perSprite; $j++) { - $p = $i + $j; - if ($p > $pages) { - break; - } - $files[] = $thumbs[$p]; - $hash .= $thumbs[$p] . '--' . filemtime($thumbs[$p]); - } - - $cache = WS_CACHE . '/thumbsprites/' . hash('sha256', $hash) . '.jpg'; - $dest = 'data/thumbnails/s' . $k . '.jpg'; - if (!file_exists($cache)) { - $ratio = $this->width / $this->height; - $thumbh = round(100 / $ratio); - $cmd = 'montage ' . implode(' ', $files) . ' -geometry 100x' . $thumbh . '!+0+0 -background transparent -tile ' . $cols . 'x' . $srows . ' ' . $cache; - $res .= `$cmd`; - } - $this->vdir->copy($cache, $dest); - $k++; - } - return $res; - } - - protected function _makeCover($orig) { - $size = CubeIT_Image::getimagesize($orig); - $w = $size[0]; - $h = $size[1]; - - $tmp = cubeFiles::tempnam() . '.png'; - - $c = new cubeCommandLine('convert'); - $c->setArg(null, ROOT . '/images/ws/shade-cover-app.png'); - $c->setManualArg('-resize ' . round($w / 3) . 'x' . $h); - $c->setArg(null, $tmp); - $c->execute(); - - $res = cubeFiles::tempnam() . '.jpg'; - - $convert = new cubeCommandLine('composite'); - $cmd = '-compose Multiply '; - $cmd .= $tmp . ' ' . $orig . ' '; - $cmd .= $res; - $convert->setManualArg($cmd); - $convert->execute(); - - $this->vdir->copy($res, 'cover.jpg', true); - - unlink($tmp); - } - - protected function _lessBoolean($val) { - return $val ? 'true' : 'false'; - } - - protected function writeCSS($file, $links) { - $res = array(); - - $lessContents = ''; - - $lessVariables = array(); - $lessVariables['slider-display'] = $this->_lessBoolean($this->theme->parametres->pagesBar); - $lessVariables['slider-thumb-background'] = wsHTML5::colorToCSS($this->theme->parametres->pageBarThumbBack); - - // General theme - $cssWidth = $this->cssWidth; - $cssHeight = $this->cssHeight; - $cssScale = $this->cssScale; - $w2 = ($cssWidth * 2) . 'px'; - - - $h = $cssHeight . 'px'; - - $wm = ($this->width * $this->multiply) . 'px'; - $hm = ($this->height * $this->multiply) . 'px'; - $w = $cssWidth . 'px'; - $offsetLeft = round(($this->optimalWidth - $cssWidth) / 2, 3); - $offsetLeft2 = $offsetLeft * 2; - $offsetTop = round(($this->optimalHeight - $cssHeight) / 2, 3); - $navTop = ($cssHeight - 40 - 100) / 2; - $leftOfRightPage = (floor($cssWidth) - 1) . 'px'; - - $lessVariables['z'] = $this->z; - $lessVariables['book-page-width'] = $w; - $lessVariables['book-page-height'] = $h; - $lessVariables['book-page-ratio'] = floatval($w) / floatval($h); - - $lessVariables['shadow-opacity'] = wsHTML5::colorToArray($this->theme->parametres->bookShadeColor)['opacity'] * 1.2; - $lessVariables['edges-display'] = $this->_lessBoolean($this->theme->parametres->usePageEdges); - - $res[] = '.portrait #pages,.portrait .doublePage.page,.page,.doublePage._3d{width:' . $w . ';max-width:' . $w . ';height:' . $h . ';max-height:' . $h . '}'; - $res[] = '.doublePage,#pages,#links,#searchHighlights{width:' . $w2 . ';max-width:' . $w2 . ';height:' . $h . ';max-height:' . $h . '}'; - $res[] = '.landscape .doublePage._2d.axis_x.next{' . wsHTML5::writeCSSUA('transform', 'translate3d(' . $w2 . ',0,0)') . '}'; - $res[] = '.landscape .doublePage._2d.axis_x.prev{' . wsHTML5::writeCSSUA('transform', 'translate3d(-' . $w2 . ',0,0)') . '}'; - $res[] = '.portrait .doublePage._2d.axis_x.next{' . wsHTML5::writeCSSUA('transform', 'translate3d(' . $w . ',0,0)') . '}'; - $res[] = '.portrait .doublePage._2d.axis_x.prev{' . wsHTML5::writeCSSUA('transform', 'translate3d(-' . $w . ',0,0)') . '}'; - $res[] = '.doublePage._2d.axis_y.next{' . wsHTML5::writeCSSUA('transform', 'translate3d(0,' . $h . ',0)') . '}'; - $res[] = '.doublePage._2d.axis_y.prev{' . wsHTML5::writeCSSUA('transform', 'translate3d(0,-' . $h . ',0)') . '}'; - - $res[] = '.doublePage._3d{left:' . $w . ';}'; - $res[] = '#links.right{left:-' . $w . ';}'; - $res[] = '.landscape .page.right{left:' . $w . '}'; - - $lessVariables['page-number-color'] = wsHTML5::colorToCSS($this->theme->parametres->colorPageNumber); - $lessVariables['display-page-number'] = $this->_lessBoolean($this->theme->parametres->displayPageNumber); - $lessVariables['page-transition-duration'] = $this->book->parametres->mobileTransitionDuration . 's'; - - - $res[] = '.background{width:100%;height:100%}'; - - if ($this->cssSVGScale != 1) { - $texts = '.texts{' . wsHTML5::writeCSSUA('transform-origin', 'top left') . ';'; - $texts .= wsHTML5::writeCSSUA('transform', 'scale(' . round((1 / $this->multiply) * $cssScale * $this->cssSVGScale, 3) . ')') . ';'; - $texts .= 'width:' . ($wm / $this->cssSVGScale) . 'px; max-width:' . ($wm / $this->cssSVGScale) . 'px;'; - $texts .= 'height:' . ($hm / $this->cssSVGScale) . 'px; max-height:' . ($hm / $this->cssSVGScale) . 'px;'; - $texts .= '}'; - } else { - $texts = '.texts{width:' . floor(floatval($w) + 4) . 'px;height:' . floor(floatval($h) + 4) . 'px;}'; - } - $res[] = $texts; - - // Theme - $shade = '.page .shade{'; - $shade .= 'opacity:' . min(($this->theme->parametres->shadeAlpha * 2) / 100, 1) . ';'; - $shade .= '}'; - $res[] = $shade; - - // SVG - $res[] = 'svg .fill-c-menu-back{fill:' . wsHTML5::colorToCSS($this->theme->parametres->couleurB) . ';}'; - $res[] = 'svg .fill-c-menu-text{fill:' . wsHTML5::colorToCSS($this->theme->parametres->subTextColor) . ';}'; - - // Background - $res[] = $this->_cssBackground(); - - // Archives - // Header - $header = 'header{'; - $header .= 'height:' . $this->theme->parametres->menuHeight . 'px;'; - if ($this->theme->parametres->menuImage != '') { - $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->menuImage, 'data/images/' . $this->theme->parametres->menuImage); - $header .= 'background-image:url(../images/' . $this->theme->parametres->menuImage . ');'; - $header .= 'background-repeat:no-repeat;'; - $header .= 'background-size:100% ' . $this->theme->parametres->menuHeight . 'px;'; - } else { - $header .= 'background-color:' . wsHTML5::colorToCSS($this->theme->parametres->menuColor) . ';'; - } - $header .= '}'; - $res[] = $header; - - //Icons - $res = array_merge($res, $this->writeIcons()); - $res[] = '#nav #locales{background-color:' . wsHTML5::colorToCSS($this->theme->parametres->couleurI) . ';}'; - - // Logo - $logo = '#logo{'; - if ($this->theme->parametres->logo) { - $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->logo, 'data/images/' . $this->theme->parametres->logo); - $dim = CubeIT_Image::getimagesize($this->themeRoot . '/' . $this->theme->parametres->logo); - $logo .= 'background-image:url(../images/' . $this->theme->parametres->logo . ');width:' . $dim[0] . 'px;height:' . $dim[1] . 'px;'; - } - $logo .= '}'; - $res[] = $logo; - - // Credits - $res[] = 'footer,footer a{color:' . wsHTML5::colorToCSS($this->theme->parametres->creditsColor) . ';}'; - - // Arrows - $lessVariables['arrows-background'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA); - $lessVariables['arrows-color'] = wsHTML5::colorToCSS($this->theme->parametres->arrowsColor); - - // Loader - $lessVariables['loader-background-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA); - $lessVariables['loader-foreground-color'] = wsHTML5::colorToCSS($this->theme->parametres->arrowsColor); - - // Audio description buttons - $lessVariables['audiodescription-background'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA); - $lessVariables['audiodescription-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA); - - // Links Styles - $lessVariables['links-color'] = wsHTML5::colorToCSS($this->theme->parametres->linksColor); - $res = array_merge($res, $links); - - // Bookmarks - if (!isset($this->book->parametres->bookmarkCornerSize)) { - $this->book->parametres->bookmarkCornerSize = 10; - } - $lessVariables['bookmark-corner-size'] = round($this->width * $this->book->parametres->bookmarkCornerSize * 0.0075 * $this->z) . 'px'; - $lessVariables['bookmark-corner-offset'] = $this->book->parametres->bookmarkOffset . 'px'; - - // Menus - $menuColor = new CubeIT_Graphics_Color($this->theme->parametres->couleurB); - $menuColor->setAlpha(1); - $menuTextColor = wsHTML5::colorToCSS($this->theme->parametres->subTextColor); - $menuBreakpoint = empty($this->book->parametres->menuBreakpoint) ? '1023px' : $this->book->parametres->menuBreakpoint; - - $lessVariables['menu-breakpoint'] = $menuBreakpoint; - $lessVariables['menu-background'] = $menuColor->toCSS(); - if ($this->theme->parametres->subSecondaryColor) { - $lessVariables['menu-button-background'] = wsHTML5::colorToCSS($this->theme->parametres->subSecondaryColor); - } else { - $lessVariables['menu-background-green'] = 'max(45, min(255-45, green(@menu-background)))'; - $lessVariables['menu-background-red'] = 'max(45, min(255-45, red(@menu-background)))'; - $lessVariables['menu-background-blue'] = 'max(45, min(255-45, blue(@menu-background)))'; - $lessVariables['menu-button-background'] = 'overlay(rgb(@menu-background-red, @menu-background-green, @menu-background-blue), #c0c0c0)'; - } - - $lessVariables['menu-text'] = $menuTextColor; - $lessVariables['menu-field-background'] = wsHTML5::colorToCSS($this->theme->parametres->subFieldColor); - $lessVariables['menu-field-text'] = wsHTML5::colorToCSS($this->theme->parametres->subTextFieldColor); - $lessVariables['menu-select-background'] = wsHTML5::colorToCSS($this->theme->parametres->subSelectColor); - $lessVariables['menu-select-text'] = wsHTML5::colorToCSS($this->theme->parametres->subTextSelectColor); - $lessVariables['icon-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurI); - $lessVariables['menu-overlay'] = wsHTML5::colorToCSS($this->theme->parametres->popupVideoOverlay); - - // Chapters - - - foreach ($this->book->chapters as $chapter) { - if (substr($chapter->page, 0, 1) != '#') { - continue; - } - if ($chapter->color == '') { - continue; - } - $color = trim($chapter->color, '#'); - $lessContents .= '.mview.c_' . $color . '{.menu-color(#' . $color . ');}'; - } - - // Archives - if ($this->book->parametres->externalArchivesBack) { - $this->vdir->copy($this->wdir . '/' . $this->book->parametres->externalArchivesBack, 'data/images/' . $this->book->parametres->externalArchivesBack); - $res[] = '.mview.archives{background-image:url("../images/' . $this->book->parametres->externalArchivesBack . '");}'; - } - - # Index - $ratio = $this->width / $this->height; - $thumbh = round(100 / $ratio); - $this->config->thumbHeight = $thumbh; - $lessVariables['thumb-height'] = $thumbh . 'px'; - - #tooltip - $lessVariables['tooltip-background'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipBackColor); - $lessVariables['tooltip-color'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipTextColor); - - # ZoomPopup close button background - $res[] = '.zoomPopupClose {background-color:' . wsHTML5::colorToCSS($this->theme->parametres->couleurB) . ';}'; - - - $this->_writeLess($lessVariables, $lessContents); - - $res = array_chunk($res, 3500); - foreach ($res as $k => $css) { - $this->stylesheets[] = 'data/style/style_' . $k . '.css'; - $this->vdir->file_put_contents(sprintf($file, $k), implode("\n", $css)); - $this->log('Write CSS ' . sprintf($file, $k)); - } - return count($res); - } - - protected function _writeLess($variables, $lessContents = '') { - if ($this->widget) { - $this->lessFiles[] = 'widget'; - } - foreach ($this->specialCSS as $s) { - $this->lessFiles[] = 'special/' . $s; - } - - $tmp = CubeIT_Files::tmpdir(); - - $from = $this->assets . '/style/*'; - `cp -r $from $tmp`; - - $bookVariables = array(); - foreach ($variables as $k => $v) { - $bookVariables[] = '@' . trim($k) . ':' . $v . ';'; - } - file_put_contents($tmp . '/book-variables.less', implode("\n", $bookVariables)); - file_put_contents($tmp . '/additional.less', $lessContents); - - foreach ($this->lessFiles as $f) { - $source_less = $this->assets . '/style/' . $f . '.less'; - $destination_less = $tmp . '/' . $f . '.less'; - $destination_css = $tmp . '/' . $f . '.css'; - - if (!file_exists($source_less)) { - continue; - } - - // LESS file might be in a subfolder, so create if it doesn't exist - if (!is_dir(dirname($destination_less))) { - mkdir(dirname($destination_less), 0777, true); - } - - // Less files must be copied to temporary directory so they'll - // have access to the variables generated in book-variables.less - copy($source_less, $destination_less); - $less = new CubeIT_CommandLine('/usr/local/bin/lessc'); - $less->setArg(null, $destination_less); - $less->setArg(null, $destination_css); - $less->execute(); - $less->debug(); - if (!file_exists($destination_css)) { - die($less->output); - } - $this->vdir->copy($destination_css, 'style/' . $f . '.css'); - if ($f != 'widget') { - $this->stylesheets[] = 'style/' . $f . '.css'; - } - } - } - - protected function _cssBackground() { - $body = '#background,#splash{'; - $body .= 'background-color:#' . $this->theme->parametres->backgroundColor . ' !important;'; - switch ($this->theme->parametres->repeat) { - case wsTheme::REPEAT: - $body .= 'background-repeat:repeat;'; - break; - case wsTheme::NONE: - $body .= 'background-repeat:no-repeat;'; - break; - case wsTheme::RATIO: - $body .= 'background-repeat:no-repeat;'; - $body .= 'background-size:cover;'; - break; - case wsTheme::STRETCH: - $body .= 'background-repeat:no-repeat;'; - $body .= 'background-size:100% 100%;'; - break; - } - if ($this->theme->parametres->backgroundImage != '') { - $bi = $this->themeRoot . '/' . $this->theme->parametres->backgroundImage; - if (file_exists($bi)) { - $dbi = CubeIT_Image::getimagesize($bi); - $this->config->backgroundImageDimensions = array('width' => $dbi[0], 'height' => $dbi[1]); - } - - $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->backgroundImage, 'data/images/' . $this->theme->parametres->backgroundImage); - $body .= 'background-image:url(../images/' . $this->theme->parametres->backgroundImage . ');'; - $body .= 'background-position:'; - - switch ($this->theme->parametres->backgroundVAlign) { - case wsTheme::TOP: - $body .= 'top'; - break; - case wsTheme::MIDDLE: - $body .= 'center'; - break; - case wsTheme::BOTTOM: - $body .= 'bottom'; - break; - } - $body .= ' '; - switch ($this->theme->parametres->backgroundHAlign) { - case wsTheme::LEFT: - $body .= 'left'; - break; - case wsTheme::CENTER: - $body .= 'center'; - break; - case wsTheme::RIGHT: - $body .= 'right'; - break; - } - $body .= ';'; - } - - $body .= '}'; - - return $body; - } - - public static function writeCSSUA($property, $value) { - $res = array(); - foreach (self::$uaPrefixes as $prefix) { - $res[] = $prefix . $property . ':' . $value; - } - return implode(';', $res); - } - - protected function base62($val) { - $chars = '0123456789abcdefghijklmnopqrstuvwxyz'; - $base = strlen($chars); - $str = ''; - do { - $i = $val % $base; - $str = $chars[$i] . $str; - $val = ($val - $i) / $base; - } while ($val > 0); - return $str; - } - - public function copyLinkDir($source, $dest) { - $this->vdir->copyDirectory($source, $dest); - } - - public function simpleCopyLinkFile($source, $dest, $addVdir = true) { - if ($addVdir) { - $dest = $dest; - } - - $this->vdir->copy($source, $dest); - } - - public function copyLinkFile($source, $dest, $video = false) { - if ($video && $this->book->parametres->mobileVideosPath != '') { - - } - - $origDir = $this->wdir; - $types = $this->getVideosFormats(); - if ($video) { - wsTools::encodeWebVideos($origDir . $source, null, true); - $e = explode('.', $source); - array_pop($e); - $base = implode('.', $e); - $source = array(); - foreach ($types as $type) { - $source[] = $base . '.' . $type; - } - } - - if (!is_array($source)) { - $source = array($source); - } - - foreach ($source as $so) { - $s = $origDir . $so; - if (file_exists($s)) { - $d = $dest . '/' . $so; - $this->simpleCopyLinkFile($s, $d, false); - } - } - } - - public function __destruct() { - - } - - - public function unzipFile($file, $moveAssets = false, $baseDir = null) { - $fdir = is_null($baseDir) ? 'data/links/' . str_replace('.', '_', $file) : $baseDir; - - $tmp = CubeIT_Files::tmpdir(); - $dir = $tmp . '/' . $fdir; - if (file_exists($dir) && is_file($dir)) { - unlink($dir); - } - if (!file_exists($dir)) { - mkdir($dir, 0777, true); - } - $unzip = new cubeCommandLine('unzip'); - $unzip->setArg(null, $this->wdir . '/' . $file); - $unzip->setArg('d', $dir); - $unzip->execute(); - - if ($moveAssets) { - `mv $dir/Assets/* $dir`; - rmdir($dir . '/Assets'); - } - - return array('dir' => $dir, 'fdir' => $fdir); - } - - public function getConfigZIP($d) { - $res = array('width' => 0, 'height' => 0); - if (file_exists($d . '/index.html')) { - $doc = new DOMDocument(); - $doc->loadHTMLFile($d . '/index.html'); - $xpath = new DOMXPath($doc); - $c = $xpath->query("//canvas"); - foreach ($c as $canvas) { - /* @var $canvas DOMElement */ - $res['width'] = intval((string)$canvas->getAttribute('width')); - $res['height'] = intval((string)$canvas->getAttribute('height')); - } - - $r = array('html' => 'index.html', 'inject' => array(), 'injectcss' => array(), 'injectjs' => array()); - } else { - $r = array('html' => false, 'inject' => array(file_get_contents($d . '/init.js')), 'injectcss' => array('multimedia.css'), 'injectjs' => array('multimedia.js')); - } - $res = array_merge($res, $r); - return $res; - } + $favicon = ''; + $hasIos = false; + if ($this->theme->parametres->iosicon != '') { + $hasIos = true; + $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->iosicon, 'data/apple-touch-icon.png'); + $favicon .= ''; + } + if ($this->theme->parametres->favicon != '') { + + $pngFile = $this->themeRoot . '/' . $this->theme->parametres->favicon; + $icoFile = $this->themeRoot . '/favicon.ico'; + if (!file_exists($icoFile) || filemtime($icoFile) < filemtime($pngFile) || filemtime(__FILE__) > filemtime($icoFile)) { + $tmp = CubeIT_Files::tempnam() . '.png'; + $convert = "convert $pngFile -resize 64x64^ -gravity center $tmp"; + `$convert`; + + $icotool = new cubeCommandLine('icotool'); + $icotool->setArg('c'); + $icotool->setArg('o', $icoFile); + $icotool->setArg(null, $tmp); + $icotool->execute(); + + unlink($tmp); + } + $this->vdir->copy($pngFile, 'data/favicon.png'); + $this->vdir->copy($icoFile, 'data/favicon.ico'); + $favicon .= ''; + $favicon .= ''; + $favicon .= ''; + if (!$hasIos) { + $favicon .= ''; + } + } + + $print = $this->writePrint(); + $message = sprintf($this->__('Your browser is not up to date and is not able to run this publication. %sLearn more%s'), '
', ''); + + $splash = ''; + if ($this->theme->parametres->logoLoader && file_exists($this->themeRoot . $this->theme->parametres->logoLoader)) { + $dim = CubeIT_Image::getimagesize($this->themeRoot . $this->theme->parametres->logoLoader); + if ($dim !== false) { + $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->logoLoader, 'data/images/' . $this->theme->parametres->logoLoader); + $splash .= ''; + } + } + + $svgfiles = array($this->assets . '/images/interface.svg', WS_ICONS . '/' . $this->theme->parametres->iconSet . '/interface.svg'); + $svg = ''; + foreach ($svgfiles as $svgfile) { + if (file_exists($svgfile)) { + $svg .= file_get_contents($svgfile); + } else { + die($svgfile . ' does not exist'); + } + } + + if ($this->phonegap) { + $csp = "securityPolicyWhitelist)) . "; img-src * data:\">"; + } + $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'pagesContents', 'description', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon', 'svg', 'beginbody', 'csp', 'opengraph', 'twittercard'); + foreach ($vars as $v) { + if (isset($$v)) { + $html = str_replace('', $$v, $html); + } else { + $html = str_replace('', '', $html); + } + } + + $scripts = array(); + foreach ($this->debugJsFiles as $js) { + $scripts[] = ''; + } + foreach ($this->jsFiles as $js) { + $scripts[] = ''; + } + foreach ($this->pluginJs as $js) { + $scripts[] = ''; + } + + $scripts[] = ''; + $scripts[] = $iscript; + $script = implode("\n\t\t", $scripts); + + $scripts = array(); + foreach ($this->testJsFiles as $js) { + $scripts[] = ''; + } + $scripts[] = ''; + $script_test = implode("\n\t\t", $scripts); + + $thtml = $uhtml; + + $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'pagesContents', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon'); + foreach ($vars as $v) { + $uhtml = str_replace('', $$v, $uhtml); + } + + $script .= "\n\t\t" . ''; + $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'print', 'hiddenContents', 'splash', 'message'); + foreach ($vars as $v) { + $thtml = str_replace('', $$v, $thtml); + } + + $this->vdir->file_put_contents('index.html', $html); + $this->vdir->file_put_contents('indexu.html', $uhtml); + $this->vdir->file_put_contents('indext.html', $thtml); + + // Write widget html + if ($this->widget) { + $whtml = file_get_contents($this->assets . '/widget.html'); + $script = ''; + $script .= ''; + + $style = ''; + $vars = array('titre', 'style', 'script'); + foreach ($vars as $v) { + $whtml = str_replace('', $$v, $whtml); + } + $this->vdir->file_put_contents('widget.html', $whtml); + } + } + + function writeSEO() + { + foreach ($this->seoArticles as $seoArticle) { + $html = file_get_contents($this->assets . '/_seo.html'); + $a = $seoArticle; + unset($a['image']); + $a['imageurl'] = 'https://workshop.fluidbook.com/services/facebook_thumbnail?id=15793&j=' . time(); + if ($seoArticle['image']) { + $a['imageurl'] .= '&image=' . $seoArticle['image']; + } + $dim = CubeIT_Image::getimagesize($a['imageurl']); + $a['imagewidth'] = $dim[0]; + $a['imageheight'] = $dim[1]; + foreach ($a as $k => $v) { + $html = str_replace('$' . $k, $v, $html); + } + $this->vdir->file_put_contents('p/' . $seoArticle['url'], $html); + } + } + + protected function writeScorm() + { + $manifest = file_get_contents($this->assets . '/_imsmanifest.xml'); + if (!$this->book->parametres->scorm_title) { + $this->book->parametres->scorm_title = $this->book->parametres->title; + } + if (!$this->book->parametres->scorm_id) { + $this->book->parametres->scorm_id = 'fb_' . $this->book->parametres->id; + } + if (!$this->book->parametres->scorm_org) { + $this->book->parametres->scorm_org = 'Fluidbook'; + } + $vars = array('scorm_id', 'scorm_org', 'scorm_title'); + foreach ($vars as $v) { + $manifest = str_replace('$' . $v, $this->book->parametres->$v, $manifest); + } + $this->vdir->file_put_contents('imsmanifest.xml', $manifest); + + $variables = []; + $e = CubeIT_Text::explodeNewLines($this->book->parametres->scorm_variables); + foreach ($e as $item) { + $item = trim($item); + if ($item == '') { + continue; + } + $f = explode('=', $item, 2); + $variables[$f[0]] = $f[1]; + } + $this->config->scorm_variables = $this->book->parametres->scorm_variables = $variables; + } + + protected function writePrint() + { + + if (!$this->book->parametres->print && !$this->book->parametres->pdf) { + return; + } + + $this->vdir->copy(WS_BOOKS . '/final/' . $this->book->book_id . '/data/' . $this->book->parametres->pdfName, 'data/' . $this->book->parametres->pdfName); + return ''; + } + + protected function addFilesInfos($key, $file) + { + if (!file_exists($file)) { + return; + } + if (!isset($this->config->filesInfos)) { + $this->config->filesInfos = array(); + } + $infos = array('filesize' => filesize($file)); + $dim = CubeIT_Image::getimagesize($file); + if ($dim !== false) { + $infos['width'] = $dim[0]; + $infos['height'] = $dim[1]; + } + $this->config->filesInfos[$key] = $infos; + } + + protected function __($str) + { + if (!isset($this->config->l10n)) { + $this->writeLangs(); + } + + if (isset($this->config->l10n['default']->$str)) { + return $this->config->l10n['default']->$str; + } else { + return $str; + } + } + + protected function writeLangs() + { + global $core; + $daoLang = new wsDAOLang($core->con); + $lang = $daoLang->selectById($this->book->lang); + $langs = $daoLang->selectAll(); + + $traductions = (!count($this->book->traductions)) ? $lang->traductions : $this->book->traductions; + + $this->config->l10n = array(); + $this->config->l10n['default'] = $traductions; + $this->config->defaultLang = $this->book->lang; + + foreach ($langs as $lang) { + $this->config->l10n[$lang->lang_id] = $lang->traductions; + } + $iso = l10n::getISOcodes(); + if ($this->book->parametres->multilang != '') { + $flagsDir = 'images/flags'; + if (!file_exists($flagsDir)) { + mkdir($flagsDir); + } + $ml = str_replace("\r", "\n", $this->book->parametres->multilang); + $ml = str_replace("\n\n", "\n", $ml); + $e = explode("\n", $ml); + $m = array(); + foreach ($e as $l1) { + $l = explode(',', $l1); + $flag = $l[1]; + + $ll = explode('-', $l[0]); + + $this->vdir->copy(cubeMedia::getFlagFile($flag), $flagsDir . '/' . $flag . '.png'); + $l[3] = cubeText::ucfirst($iso[$l[0]]); + $l[4] = cubeCountry::getCountryName($flag, $ll[0]); + $m[] = implode(',', $l); + } + + $this->config->multilang = implode("\n", $m); + } + } + + protected function writeExtras() + { + if ($this->theme->parametres->afterSearch != '') { + $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->afterSearch, 'data/images/' . $this->theme->parametres->afterSearch); + } + if ($this->book->parametres->externalArchives != '') { + $this->addFilesInfos('archives', $this->wdir . '/' . $this->book->parametres->externalArchives); + $this->vdir->copy($this->wdir . '/' . $this->book->parametres->externalArchives, 'data/images/' . $this->book->parametres->externalArchives); + } + + if ($this->book->parametres->navExtraImage != '') { + $this->vdir->copy($this->wdir . '/' . $this->book->parametres->navExtraImage, 'data/images/' . $this->book->parametres->navExtraImage); + } + + if ($this->book->parametres->navExtraImageMobile != '') { + $this->vdir->copy($this->wdir . '/' . $this->book->parametres->navExtraImageMobile, 'data/images/' . $this->book->parametres->navExtraImageMobile); + } + + for ($i = 1; $i <= 5; $i++) { + $ic = $this->book->parametres->{'navExtraIcon' . $i}; + if ($ic != '') { + $this->vdir->copy($this->wdir . '/' . $ic, 'data/images/' . $ic); + } + } + + } + + protected function writeLinks() + { + global $core; + + if ($this->book->parametres->customLinkClass == 'WescoSalesLink') { + $this->specialJsFiles[] = 'js/libs/interact.min.js'; + $this->specialJsFiles[] = 'js/libs/fluidbook/special/wescosales.js'; + $this->specialCSS[] = 'wescosales'; + } + + if ($this->book->parametres->customLinkClass == 'AtlanticDownloadLink') { + $this->specialJsFiles[] = 'js/libs/fluidbook/special/atlanticdownload.js'; + $this->specialCSS[] = 'atlanticdownload'; + } + + $this->config->links = array(); + $this->config->clinks = array(); + $this->config->bookmarkGroups = array(); + + $ignore = $this->book->parametres->ignoreLinksTypes; + if (!$ignore) { + $ignore = array(); + } else { + $ignore = split(',', $ignore); + } + + if ($this->book->parametres->externalChaptersHTML != '') { + $d = $this->unzipFile($this->book->parametres->externalChaptersHTML, false, 'data/chapters/'); + $meta = $this->getConfigZIP($d['dir']); + $this->config->externalChaptersSize = new stdClass(); + $this->config->externalChaptersSize->width = $meta['width']; + $this->config->externalChaptersSize->height = $meta['height']; + $this->vdir->copyDirectory($d['dir'], $d['fdir']); + } + + $daoDoc = new wsDAODocument($core->con); + $daoDoc->getLinksAndRulers($this->book_id, $links, $rulers); + + // Custom landing page content + if ($this->book->parametres->landingPage != '') { + $d = $this->unzipFile($this->book->parametres->landingPage, false, 'data/landing-page/'); + $this->vdir->copyDirectory($d['dir'], $d['fdir']); + } + + if ($this->book->parametres->tabsHTML5 != '') { + $links[] = [ + 'page' => 'background', + 'top' => 0, + 'left' => 0, + 'width' => 100, + 'height' => 100, + 'type' => 6, + 'to' => $this->book->parametres->tabsHTML5, + 'alternative' => $this->book->parametres->tabsHTML5, + 'image' => '', + 'inline' => 1, + 'interactive' => 1, + 'class' => 'tabslink', + ]; + } + + + foreach ($links as $linkData) { + if (isset($linkData['image']) && $linkData['image'] && $linkData['type'] != 28) { + $dupData = $linkData; + $dupData['image'] = ''; + $dupData['to'] = $linkData['image']; + $dupData['type'] = 15; + array_push($links, $dupData); + } + } + + $i = 0; + $pages = array(); + $cpages = array(); + $css = array(); + + usort($links, array($this, '_sortLinks')); + + foreach ($links as $linkData) { + if (in_array($linkData['type'], $ignore)) { + continue; + } + if ($linkData['type'] == 28) { + $this->addSEOArticle($linkData['page'], $linkData['to'], $linkData['extra'], $linkData['image']); + continue; + } + $link = wsHTML5Link::getInstance($this->base62($i), $linkData, $this); + if (is_null($link)) { + continue; + } + + // Make old "aftersearch" link compatible with new "extra" menu option by extracting link URL + if ($link->page == 'aftersearch') { + $this->config->afterSearchLink = $link->to; + $this->config->afterSearchTooltip = $link->infobulle; + } + + + $c = $link->getHTMLContainer(); + $css[] = $link->getCSSContainer(); + if (!isset($pages[$link->page])) { + $pages[$link->page] = ''; + $cpages[$link->page] = ''; + } + if ($link instanceof contentLink) { + $cpages[$link->page] .= $c; + } else { + $pages[$link->page] .= $c; + } + + if ($link->keep()) { + $this->hiddenContents[] = $c; + } + $i++; + } + + $allpages = range(0, $this->book->parametres->pages + 1); + if ($this->book->parametres->themeEnableAfterSearch) { + $allpages[] = 'aftersearch'; + } + $allpages[] = 'background'; + $allpages[] = 'archives'; + + foreach ($allpages as $i) { + + $c = ''; + $cc = ''; + if (isset($pages[$i])) { + $c = $pages[$i]; + } + if (isset($cpages[$i])) { + $cc = $cpages[$i]; + } + $this->config->links[$i] = $c; + $this->config->clinks[$i] = $cc; + } + return $css; + } + + public function addSEOArticle($page, $title, $intro, $image) + { + $this->seoArticles[$title] = ['title' => $title, 'description' => $intro, 'image' => $image, 'content' => '', 'page' => $page, 'url' => CubeIT_Text::str2URL($title) . '.html']; + } + + public function _sortLinks($a, $b) + { + $priorities = array(26 => 1); + + $pa = isset($priorities[$a['type']]) ? $priorities[$a['type']] : 0; + $pb = isset($priorities[$b['type']]) ? $priorities[$b['type']] : 0; + return $pb - $pa; + } + + public function addBookmarkGroup($link) + { + if ($link['left'] > $this->book->parametres->width) { + //$link['page']++; + } + if ($link['page'] <= 0 || $link['page'] > $this->book->parametres->pages) { + return; + } + + $this->config->bookmarkGroups[] = array('page' => ($link['page']), 'nb' => $link['to'], 'name' => $link['extra']); + } + + public function addAudiodescription($link) + { + $this->config->audiodescription[$link['page']] = $link['to']; + $this->copyLinkFile($link['to'], 'data/audiodescription/'); + } + + protected function writeJs() + { + $config = $this->writeConfig(); + $this->vdir->file_put_contents('data/datas.js', $config); + $finals = array('fluidbook' => $this->jsFiles); + if ($this->book->parametres->scorm_enable) { + $finals['scorm'] = array(); + $finals['scorm'][] = 'js/libs/scorm/apiwrapper.js'; + $finals['scorm'][] = 'js/libs/scorm/scorm.js'; + } + if (count($this->specialJsFiles)) { + $finals['special'] = $this->specialJsFiles; + } + if ($this->widget) { + $finals['widget'] = $this->widgetJsFiles; + } + + foreach ($finals as $jsfinal => $files) { + $mintime = 0; + $hash = hash('sha256', json_encode($files)); + $minimized = $this->assets . '/js/min/' . $jsfinal . '-' . $hash . '-min.js'; + if (!file_exists(dirname($minimized))) { + mkdir(dirname($minimized)); + } + if (file_exists($minimized)) { + $mintime = filemtime($minimized); + $reminimize = false; + } else { + $mintime = 0; + $reminimize = true; + } + + if (!$reminimize) { + foreach ($files as $file) { + if (filemtime($this->assets . '/' . $file) > $mintime) { + $reminimize = true; + break; + } + } + } + + if (!$reminimize) { + if (filemtime(__FILE__) > $mintime || (file_exists(__DIR__ . '/class.ws.html5.links.php') && filemtime(__DIR__ . '/class.ws.html5.links.php') > $mintime)) { + $reminimize = true; + } + } + + if ($reminimize) { + $js = ''; + foreach ($files as $file) { + $js .= file_get_contents($this->assets . '/' . $file); + $js .= ";\n\n"; + } + $tmp = cubeFiles::tempnam(); + file_put_contents($tmp, $js); + + unlink($minimized); + + $uglify = new CubeIT_CommandLine('/usr/local/bin/uglifyjs'); + $uglify->setArg('o', $minimized); + $uglify->setArg(null, $tmp); + $uglify->execute(); + $uglify->debug(); + + if (!file_exists($minimized)) { + die('An error occured while uglifying : ' . $uglify->output); + } + } + $dest = 'data/' . $jsfinal . '.js'; + $this->vdir->copy($minimized, $dest); + } + + + if ($this->phonegap) { + $this->vdir->copy(WS_COMPILE_ASSETS . '/_html5/js/libs/phonegap/' . $this->phonegapVersion . '/cordova-' . $this->phonegap . '.js', 'data/cordova.js'); + } + + } + + public function writeTexts() + { + $this->daoBook->makeTextsIndexes($this->book, $this->pages, $index, $textes, true); + $this->vdir->file_put_contents('data/search.index.js', 'var INDEX=' . $index . ';' . "\r"); + if ($this->book->parametres->highlightResults) { + $this->vdir->file_put_contents('data/search.highlight.js', 'var HIGHLIGHTS=' . json_encode($this->daoBook->makeHighlightIndex($this->book, $this->pages)) . ";\r"); + } + if ($this->book->parametres->searchWordSelectionAlgorithm == 'expression') { + $this->vdir->file_put_contents('data/search.texts.js', 'var TEXTS=' . $textes . ";\r"); + } + } + + public function supportSVG() + { + if (!$this->phonegap) { + return false; + } else if ($this->phonegap == 'ios') { + return true; + } else { + return false; + } + } + + protected function writeConfig() + { + $this->config->numerotation = explode(',', $this->book->numerotation); + $this->config->id = $this->book->book_id; + $this->config->cid = $this->book->cid; + $this->config->cacheDate = TIME; + $this->config->width = $this->cssWidth; + $this->config->height = $this->cssHeight; + $this->config->optimalWidth = $this->optimalWidth; + $this->config->optimalHeight = $this->optimalHeight; + $this->config->chapters = $this->book->chapters; + $this->config->videoFormats = $this->getVideosFormats(false); + $this->config->htmlmultimedia = $this->htmlmultimedia; + $this->config->phonegap = $this->phonegap; + $this->config->retinaResolution = min($this->book->parametres->maxResolution, $this->maxRes); + $this->config->pageLabels = $this->pageLabels; + $this->config->pageZoomFactor = $this->z; + $this->config->multiply = $this->multiply; + $this->config->cssScale = $this->cssScale; + $this->config->pdfZoomFactor = $this->pdf2htmlRatio; + if ($this->home) { + $this->config->home = 'http://home'; + } + $this->config->multiApp = $this->multiApp; + foreach ($this->additionalConfig as $k => $v) { + $this->config->$k = $v; + } + if ($this->phonegap && ($this->book->parametres->offlineLink == '' || $this->book->parametres->offlineLink == 'http://')) { + $this->config->share = false; + } + + // We need to be able to reference both navOrder and navOrderH so convert both to arrays + // We also make sure there are no empty items in the arrays (see: http://php.net/manual/en/function.array-filter.php#111091) + $this->config->navOrder = array_filter(array_map('trim', explode(',', $this->config->navOrder)), 'strlen'); + $this->config->navOrderH = array_filter(array_map('trim', explode(',', $this->config->navOrderH)), 'strlen'); + + $this->config->standalone = $this->standalone; + if ($this->config->phonegap) { + $this->config->manifest = $this->writeManifest(); + } + + if ($this->config->basket) { + if (file_exists($this->config->basketReferences) || CubeIT_Util_Url::isDistant($this->config->basketReferences)) { + $referencesFile = $this->config->basketReferences; + } else { + $referencesFile = $this->wdir . '/commerce/' . $this->config->basketReferences; + } + + if (file_exists($referencesFile) || CubeIT_Util_Url::isDistant($referencesFile)) { + $ext = CubeIT_Files::getExtension($referencesFile); + if ($ext == 'xlsx') { + $this->config->basketReferences = wsUtil::excelToArray($referencesFile); + if ($this->book->parametres->customLinkClass == 'AtlanticDownloadLink') { + $this->config->basketReferences = wsUtil::atlanticReferences($this->config->basketReferences, 'local/', array($this, 'log'), array($this->vdir, "copy")); + } + } + $this->log("Done cart references"); + } + } + $this->config->seoArticles = $this->seoArticles; + + return 'var DATAS=' . json_encode($this->config) . ';' . "\n"; + } + + protected function writeManifest() + { + $res = array(); + } + + protected function writeIcons() + { + $res = array(); + // Get the colors used to colorize graphics + if ($this->theme->parametres->colorizeIcons) { + $couleurI = $this->theme->parametres->couleurI; + } else { + $couleurI = 'FFFFFF'; + } + + $couleurM = $this->theme->parametres->subTextColor; + + $bookmarksDisabledColors = array('star' => $this->theme->parametres->bookmarkStarDisabledColor, 'bookmark' => $this->theme->parametres->bookmarkBackgroundColor); + $bookmarksEnabledColors = array('star' => $this->theme->parametres->bookmarkStarEnabledColor, 'bookmark' => $this->theme->parametres->bookmarkBackgroundColor); + $subTextColor = $this->theme->parametres->subTextColor; + + $arrowsColor = $this->theme->parametres->arrowsColor; + // Set the icon list with the color + $icons = array('interface-down' => $arrowsColor, 'interface-close' => $arrowsColor, + 'interface-audio-description-on' => $arrowsColor, 'interface-audio-description-off' => $arrowsColor, + 'help-fingers' => $couleurI, 'help-mouse' => $couleurI, + 'bookmark-left-off' => $bookmarksDisabledColors, 'bookmark-left-on' => $bookmarksEnabledColors, + 'bookmark-right-off' => $bookmarksDisabledColors, 'bookmark-right-on' => $bookmarksEnabledColors + ); + + $this->config->iconsDimensions = array(); + $makepng = !$this->supportSVG(); + $tmpdir = CubeIT_Files::tmpdir(); + foreach ($icons as $icon => $color) { + wsTools::colorizeAndRasterizeIcon($this->theme->parametres->iconSet, $icon, $color, $tmpdir, 4, $w, $h); + $this->config->iconsDimensions[$icon] = array($w, $h); + } + $this->vdir->copyDirectory($tmpdir, 'data/images'); + $this->vdir->addTemp($tmpdir); + return $res; + } + + protected function writeImages() + { + global $core; + + switch ($this->book->parametres->mobileVersion) { + case 'html5-desktop': + $this->backgroundsPrefix = array('t', 'p'); + $this->svg = true; + break; + case 'html5-images': + $this->backgroundsPrefix = array('t'); + $this->svg = false; + break; + default: + $this->backgroundsPrefix = array('p'); + $this->svg = true; + break; + } + + $thumbs = array(); + foreach ($this->pages as $page => $infos) { + $docdir = wsDocument::getDir($infos['document_id']); + if ($this->svg) { + $full = $docdir . 'html/fp' . $infos['document_page'] . '.svg'; + $fullopt = $docdir . 'html/fo' . $infos['document_page'] . '%s.svg'; + $orig = $docdir . 'html/tp' . $infos['document_page'] . '.svg'; + $opt = $docdir . 'html/to' . $infos['document_page'] . '.svg'; + + if (!file_exists($full) || filemtime($full) < 1503671520) { + if (!isset($doc) || $doc->document_id != $infos['document_id']) { + $dao = new wsDAODocument($core->con); + $doc = $dao->selectById($infos['document_id']); + } + $doc->makeSVGFile($infos['document_page']); + } + wsDocument::extractTexts($full, $orig); + wsTools::optimizeSVG($orig, $opt); + wsTools::optimizeSVG($full, $fullopt, [150, 300]); + + if (in_array($page, $this->config->vectorPages)) { + $this->vdir->copy(str_replace('%s', '-150', $fullopt), 'data/contents/p' . $page . '.svg'); + } else { + $this->vdir->copy($opt, 'data/contents/p' . $page . '.svg'); + } + } + + + foreach ($this->getResolutions() as $r) { + foreach ($this->backgroundsPrefix as $backgroundsPrefix) { + $srcPrefix = $backgroundsPrefix; + if ($backgroundsPrefix == 'p') { + $srcPrefix = 'h'; + } + $ok = $this->vdir->copy($docdir . 'html/' . $srcPrefix . $r . '-' . $infos['document_page'] . '.jpg', 'data/background/' . $r . '/' . $backgroundsPrefix . $page . '.jpg'); + if (!$ok && $r = 300) { + $this->maxRes = 150; + } + } + } + + $thumb = false; + if ($this->book->parametres->pdfThumbnails) { + $thumb = wsPDFConvert::getThumbFromPDF(WS_BOOKS . '/working/' . $this->book->book_id . '/' . $this->book->parametres->pdfThumbnails, $page); + } + if (!$thumb) { + $thumb = $docdir . 'p' . $infos['document_page'] . '.jpg'; + } + + $thumbs[$page] = $thumb; + $this->vdir->copy($thumb, 'data/thumbnails/p' . $page . '.jpg'); + + if ($page == 1) { + $this->_makeCover($docdir . 'html/t36-' . $infos['document_page'] . '.jpg'); + } + + $this->log('Copied image ' . $page); + } + + + $this->makeThumbSprites($thumbs); + $this->log('Made thumbnails'); + } + + public function makeThumbSprites(array $thumbs) + { + $cols = 10; + $rows = 10; + $perSprite = $cols * $rows; + $k = 0; + $res = ''; + $pages = count($thumbs); + + $hash = ''; + for ($i = 1; $i <= $pages; $i += $perSprite) { + $num = min(1 + $pages - $i, $perSprite); + $srows = ceil($num / $cols); + $files = array(); + $mtime = 0; + for ($j = 0; $j < $perSprite; $j++) { + $p = $i + $j; + if ($p > $pages) { + break; + } + $files[] = $thumbs[$p]; + $hash .= $thumbs[$p] . '--' . filemtime($thumbs[$p]); + } + + $cache = WS_CACHE . '/thumbsprites/' . hash('sha256', $hash) . '.jpg'; + $dest = 'data/thumbnails/s' . $k . '.jpg'; + if (!file_exists($cache)) { + $ratio = $this->width / $this->height; + $thumbh = round(100 / $ratio); + $cmd = 'montage ' . implode(' ', $files) . ' -geometry 100x' . $thumbh . '!+0+0 -background transparent -tile ' . $cols . 'x' . $srows . ' ' . $cache; + $res .= `$cmd`; + } + $this->vdir->copy($cache, $dest); + $k++; + } + return $res; + } + + protected function _makeCover($orig) + { + $size = CubeIT_Image::getimagesize($orig); + $w = $size[0]; + $h = $size[1]; + + $tmp = cubeFiles::tempnam() . '.png'; + + $c = new cubeCommandLine('convert'); + $c->setArg(null, ROOT . '/images/ws/shade-cover-app.png'); + $c->setManualArg('-resize ' . round($w / 3) . 'x' . $h); + $c->setArg(null, $tmp); + $c->execute(); + + $res = cubeFiles::tempnam() . '.jpg'; + + $convert = new cubeCommandLine('composite'); + $cmd = '-compose Multiply '; + $cmd .= $tmp . ' ' . $orig . ' '; + $cmd .= $res; + $convert->setManualArg($cmd); + $convert->execute(); + + $this->vdir->copy($res, 'cover.jpg', true); + + unlink($tmp); + } + + protected function _lessBoolean($val) + { + return $val ? 'true' : 'false'; + } + + protected function writeCSS($file, $links) + { + $res = array(); + + $lessContents = ''; + + $lessVariables = array(); + $lessVariables['slider-display'] = $this->_lessBoolean($this->theme->parametres->pagesBar); + $lessVariables['slider-thumb-background'] = wsHTML5::colorToCSS($this->theme->parametres->pageBarThumbBack); + + // General theme + $cssWidth = $this->cssWidth; + $cssHeight = $this->cssHeight; + $cssScale = $this->cssScale; + $w2 = ($cssWidth * 2) . 'px'; + + + $h = $cssHeight . 'px'; + + $wm = ($this->width * $this->multiply) . 'px'; + $hm = ($this->height * $this->multiply) . 'px'; + $w = $cssWidth . 'px'; + $offsetLeft = round(($this->optimalWidth - $cssWidth) / 2, 3); + $offsetLeft2 = $offsetLeft * 2; + $offsetTop = round(($this->optimalHeight - $cssHeight) / 2, 3); + $navTop = ($cssHeight - 40 - 100) / 2; + $leftOfRightPage = (floor($cssWidth) - 1) . 'px'; + + $lessVariables['z'] = $this->z; + $lessVariables['book-page-width'] = $w; + $lessVariables['book-page-height'] = $h; + $lessVariables['book-page-ratio'] = floatval($w) / floatval($h); + + $lessVariables['shadow-opacity'] = wsHTML5::colorToArray($this->theme->parametres->bookShadeColor)['opacity'] * 1.2; + $lessVariables['edges-display'] = $this->_lessBoolean($this->theme->parametres->usePageEdges); + + $res[] = '.portrait #pages,.portrait .doublePage.page,.page,.doublePage._3d{width:' . $w . ';max-width:' . $w . ';height:' . $h . ';max-height:' . $h . '}'; + $res[] = '.doublePage,#pages,#links,#searchHighlights{width:' . $w2 . ';max-width:' . $w2 . ';height:' . $h . ';max-height:' . $h . '}'; + $res[] = '.landscape .doublePage._2d.axis_x.next{' . wsHTML5::writeCSSUA('transform', 'translate3d(' . $w2 . ',0,0)') . '}'; + $res[] = '.landscape .doublePage._2d.axis_x.prev{' . wsHTML5::writeCSSUA('transform', 'translate3d(-' . $w2 . ',0,0)') . '}'; + $res[] = '.portrait .doublePage._2d.axis_x.next{' . wsHTML5::writeCSSUA('transform', 'translate3d(' . $w . ',0,0)') . '}'; + $res[] = '.portrait .doublePage._2d.axis_x.prev{' . wsHTML5::writeCSSUA('transform', 'translate3d(-' . $w . ',0,0)') . '}'; + $res[] = '.doublePage._2d.axis_y.next{' . wsHTML5::writeCSSUA('transform', 'translate3d(0,' . $h . ',0)') . '}'; + $res[] = '.doublePage._2d.axis_y.prev{' . wsHTML5::writeCSSUA('transform', 'translate3d(0,-' . $h . ',0)') . '}'; + + $res[] = '.doublePage._3d{left:' . $w . ';}'; + $res[] = '#links.right{left:-' . $w . ';}'; + $res[] = '.landscape .page.right{left:' . $w . '}'; + + $lessVariables['page-number-color'] = wsHTML5::colorToCSS($this->theme->parametres->colorPageNumber); + $lessVariables['display-page-number'] = $this->_lessBoolean($this->theme->parametres->displayPageNumber); + $lessVariables['page-transition-duration'] = $this->book->parametres->mobileTransitionDuration . 's'; + + + $res[] = '.background{width:100%;height:100%}'; + + if ($this->cssSVGScale != 1) { + $texts = '.texts{' . wsHTML5::writeCSSUA('transform-origin', 'top left') . ';'; + $texts .= wsHTML5::writeCSSUA('transform', 'scale(' . round((1 / $this->multiply) * $cssScale * $this->cssSVGScale, 3) . ')') . ';'; + $texts .= 'width:' . ($wm / $this->cssSVGScale) . 'px; max-width:' . ($wm / $this->cssSVGScale) . 'px;'; + $texts .= 'height:' . ($hm / $this->cssSVGScale) . 'px; max-height:' . ($hm / $this->cssSVGScale) . 'px;'; + $texts .= '}'; + } else { + $texts = '.texts{width:' . floor(floatval($w) + 4) . 'px;height:' . floor(floatval($h) + 4) . 'px;}'; + } + $res[] = $texts; + + // Theme + $shade = '.page .shade{'; + $shade .= 'opacity:' . min(($this->theme->parametres->shadeAlpha * 2) / 100, 1) . ';'; + $shade .= '}'; + $res[] = $shade; + + // SVG + $res[] = 'svg .fill-c-menu-back{fill:' . wsHTML5::colorToCSS($this->theme->parametres->couleurB) . ';}'; + $res[] = 'svg .fill-c-menu-text{fill:' . wsHTML5::colorToCSS($this->theme->parametres->subTextColor) . ';}'; + + // Background + $res[] = $this->_cssBackground(); + + // Archives + // Header + $header = 'header{'; + $header .= 'height:' . $this->theme->parametres->menuHeight . 'px;'; + if ($this->theme->parametres->menuImage != '') { + $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->menuImage, 'data/images/' . $this->theme->parametres->menuImage); + $header .= 'background-image:url(../images/' . $this->theme->parametres->menuImage . ');'; + $header .= 'background-repeat:no-repeat;'; + $header .= 'background-size:100% ' . $this->theme->parametres->menuHeight . 'px;'; + } else { + $header .= 'background-color:' . wsHTML5::colorToCSS($this->theme->parametres->menuColor) . ';'; + } + $header .= '}'; + $res[] = $header; + + //Icons + $res = array_merge($res, $this->writeIcons()); + $res[] = '#nav #locales{background-color:' . wsHTML5::colorToCSS($this->theme->parametres->couleurI) . ';}'; + + // Logo + $logo = '#logo{'; + if ($this->theme->parametres->logo) { + $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->logo, 'data/images/' . $this->theme->parametres->logo); + $dim = CubeIT_Image::getimagesize($this->themeRoot . '/' . $this->theme->parametres->logo); + $logo .= 'background-image:url(../images/' . $this->theme->parametres->logo . ');width:' . $dim[0] . 'px;height:' . $dim[1] . 'px;'; + } + $logo .= '}'; + $res[] = $logo; + + // Credits + $res[] = 'footer,footer a{color:' . wsHTML5::colorToCSS($this->theme->parametres->creditsColor) . ';}'; + + // Arrows + $lessVariables['arrows-background'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA); + $lessVariables['arrows-color'] = wsHTML5::colorToCSS($this->theme->parametres->arrowsColor); + + // Loader + $lessVariables['loader-background-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA); + $lessVariables['loader-foreground-color'] = wsHTML5::colorToCSS($this->theme->parametres->arrowsColor); + + // Audio description buttons + $lessVariables['audiodescription-background'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA); + $lessVariables['audiodescription-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA); + + // Links Styles + $lessVariables['links-color'] = wsHTML5::colorToCSS($this->theme->parametres->linksColor); + $res = array_merge($res, $links); + + // Bookmarks + if (!isset($this->book->parametres->bookmarkCornerSize)) { + $this->book->parametres->bookmarkCornerSize = 10; + } + $lessVariables['bookmark-corner-size'] = round($this->width * $this->book->parametres->bookmarkCornerSize * 0.0075 * $this->z) . 'px'; + $lessVariables['bookmark-corner-offset'] = $this->book->parametres->bookmarkOffset . 'px'; + + // Menus + $menuColor = new CubeIT_Graphics_Color($this->theme->parametres->couleurB); + $menuColor->setAlpha(1); + $menuTextColor = wsHTML5::colorToCSS($this->theme->parametres->subTextColor); + $menuBreakpoint = empty($this->book->parametres->menuBreakpoint) ? '1023px' : $this->book->parametres->menuBreakpoint; + + $lessVariables['menu-breakpoint'] = $menuBreakpoint; + $lessVariables['menu-background'] = $menuColor->toCSS(); + if ($this->theme->parametres->subSecondaryColor) { + $lessVariables['menu-button-background'] = wsHTML5::colorToCSS($this->theme->parametres->subSecondaryColor); + } else { + $lessVariables['menu-background-green'] = 'max(45, min(255-45, green(@menu-background)))'; + $lessVariables['menu-background-red'] = 'max(45, min(255-45, red(@menu-background)))'; + $lessVariables['menu-background-blue'] = 'max(45, min(255-45, blue(@menu-background)))'; + $lessVariables['menu-button-background'] = 'overlay(rgb(@menu-background-red, @menu-background-green, @menu-background-blue), #c0c0c0)'; + } + + $lessVariables['menu-text'] = $menuTextColor; + $lessVariables['menu-field-background'] = wsHTML5::colorToCSS($this->theme->parametres->subFieldColor); + $lessVariables['menu-field-text'] = wsHTML5::colorToCSS($this->theme->parametres->subTextFieldColor); + $lessVariables['menu-select-background'] = wsHTML5::colorToCSS($this->theme->parametres->subSelectColor); + $lessVariables['menu-select-text'] = wsHTML5::colorToCSS($this->theme->parametres->subTextSelectColor); + $lessVariables['icon-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurI); + $lessVariables['menu-overlay'] = wsHTML5::colorToCSS($this->theme->parametres->popupVideoOverlay); + + // Chapters + + + foreach ($this->book->chapters as $chapter) { + if (substr($chapter->page, 0, 1) != '#') { + continue; + } + if ($chapter->color == '') { + continue; + } + $color = trim($chapter->color, '#'); + $lessContents .= '.mview.c_' . $color . '{.menu-color(#' . $color . ');}'; + } + + // Archives + if ($this->book->parametres->externalArchivesBack) { + $this->vdir->copy($this->wdir . '/' . $this->book->parametres->externalArchivesBack, 'data/images/' . $this->book->parametres->externalArchivesBack); + $res[] = '.mview.archives{background-image:url("../images/' . $this->book->parametres->externalArchivesBack . '");}'; + } + + # Index + $ratio = $this->width / $this->height; + $thumbh = round(100 / $ratio); + $this->config->thumbHeight = $thumbh; + $lessVariables['thumb-height'] = $thumbh . 'px'; + + #tooltip + $lessVariables['tooltip-background'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipBackColor); + $lessVariables['tooltip-color'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipTextColor); + + # ZoomPopup close button background + $res[] = '.zoomPopupClose {background-color:' . wsHTML5::colorToCSS($this->theme->parametres->couleurB) . ';}'; + + + $this->_writeLess($lessVariables, $lessContents); + + $res = array_chunk($res, 3500); + foreach ($res as $k => $css) { + $this->stylesheets[] = 'data/style/style_' . $k . '.css'; + $this->vdir->file_put_contents(sprintf($file, $k), implode("\n", $css)); + $this->log('Write CSS ' . sprintf($file, $k)); + } + return count($res); + } + + protected function _writeLess($variables, $lessContents = '') + { + if ($this->widget) { + $this->lessFiles[] = 'widget'; + } + foreach ($this->specialCSS as $s) { + $this->lessFiles[] = 'special/' . $s; + } + + $tmp = CubeIT_Files::tmpdir(); + + $from = $this->assets . '/style/*'; + `cp -r $from $tmp`; + + $bookVariables = array(); + foreach ($variables as $k => $v) { + $bookVariables[] = '@' . trim($k) . ':' . $v . ';'; + } + file_put_contents($tmp . '/book-variables.less', implode("\n", $bookVariables)); + file_put_contents($tmp . '/additional.less', $lessContents); + + foreach ($this->lessFiles as $f) { + $source_less = $this->assets . '/style/' . $f . '.less'; + $destination_less = $tmp . '/' . $f . '.less'; + $destination_css = $tmp . '/' . $f . '.css'; + + if (!file_exists($source_less)) { + continue; + } + + // LESS file might be in a subfolder, so create if it doesn't exist + if (!is_dir(dirname($destination_less))) { + mkdir(dirname($destination_less), 0777, true); + } + + // Less files must be copied to temporary directory so they'll + // have access to the variables generated in book-variables.less + copy($source_less, $destination_less); + $less = new CubeIT_CommandLine('/usr/local/bin/lessc'); + $less->setArg(null, $destination_less); + $less->setArg(null, $destination_css); + $less->execute(); + $less->debug(); + if (!file_exists($destination_css)) { + die($less->output); + } + $this->vdir->copy($destination_css, 'style/' . $f . '.css'); + if ($f != 'widget') { + $this->stylesheets[] = 'style/' . $f . '.css'; + } + } + } + + protected function _cssBackground() + { + $body = '#background,#splash{'; + $body .= 'background-color:#' . $this->theme->parametres->backgroundColor . ' !important;'; + switch ($this->theme->parametres->repeat) { + case wsTheme::REPEAT: + $body .= 'background-repeat:repeat;'; + break; + case wsTheme::NONE: + $body .= 'background-repeat:no-repeat;'; + break; + case wsTheme::RATIO: + $body .= 'background-repeat:no-repeat;'; + $body .= 'background-size:cover;'; + break; + case wsTheme::STRETCH: + $body .= 'background-repeat:no-repeat;'; + $body .= 'background-size:100% 100%;'; + break; + } + if ($this->theme->parametres->backgroundImage != '') { + $bi = $this->themeRoot . '/' . $this->theme->parametres->backgroundImage; + if (file_exists($bi)) { + $dbi = CubeIT_Image::getimagesize($bi); + $this->config->backgroundImageDimensions = array('width' => $dbi[0], 'height' => $dbi[1]); + } + + $this->vdir->copy($this->themeRoot . '/' . $this->theme->parametres->backgroundImage, 'data/images/' . $this->theme->parametres->backgroundImage); + $body .= 'background-image:url(../images/' . $this->theme->parametres->backgroundImage . ');'; + $body .= 'background-position:'; + + switch ($this->theme->parametres->backgroundVAlign) { + case wsTheme::TOP: + $body .= 'top'; + break; + case wsTheme::MIDDLE: + $body .= 'center'; + break; + case wsTheme::BOTTOM: + $body .= 'bottom'; + break; + } + $body .= ' '; + switch ($this->theme->parametres->backgroundHAlign) { + case wsTheme::LEFT: + $body .= 'left'; + break; + case wsTheme::CENTER: + $body .= 'center'; + break; + case wsTheme::RIGHT: + $body .= 'right'; + break; + } + $body .= ';'; + } + + $body .= '}'; + + return $body; + } + + public static function writeCSSUA($property, $value) + { + $res = array(); + foreach (self::$uaPrefixes as $prefix) { + $res[] = $prefix . $property . ':' . $value; + } + return implode(';', $res); + } + + protected function base62($val) + { + $chars = '0123456789abcdefghijklmnopqrstuvwxyz'; + $base = strlen($chars); + $str = ''; + do { + $i = $val % $base; + $str = $chars[$i] . $str; + $val = ($val - $i) / $base; + } while ($val > 0); + return $str; + } + + public function copyLinkDir($source, $dest) + { + $this->vdir->copyDirectory($source, $dest); + } + + public function simpleCopyLinkFile($source, $dest, $addVdir = true) + { + if ($addVdir) { + $dest = $dest; + } + + $this->vdir->copy($source, $dest); + } + + public function copyLinkFile($source, $dest, $video = false) + { + if ($video && $this->book->parametres->mobileVideosPath != '') { + + } + + $origDir = $this->wdir; + $types = $this->getVideosFormats(); + if ($video) { + wsTools::encodeWebVideos($origDir . $source, null, true); + $e = explode('.', $source); + array_pop($e); + $base = implode('.', $e); + $source = array(); + foreach ($types as $type) { + $source[] = $base . '.' . $type; + } + } + + if (!is_array($source)) { + $source = array($source); + } + + foreach ($source as $so) { + $s = $origDir . $so; + if (file_exists($s)) { + $d = $dest . '/' . $so; + $this->simpleCopyLinkFile($s, $d, false); + } + } + } + + public function __destruct() + { + + } + + + public function unzipFile($file, $moveAssets = false, $baseDir = null) + { + $fdir = is_null($baseDir) ? 'data/links/' . str_replace('.', '_', $file) : $baseDir; + + $tmp = CubeIT_Files::tmpdir(); + $dir = $tmp . '/' . $fdir; + if (file_exists($dir) && is_file($dir)) { + unlink($dir); + } + if (!file_exists($dir)) { + mkdir($dir, 0777, true); + } + $unzip = new cubeCommandLine('unzip'); + $unzip->setArg(null, $this->wdir . '/' . $file); + $unzip->setArg('d', $dir); + $unzip->execute(); + + if ($moveAssets) { + `mv $dir/Assets/* $dir`; + rmdir($dir . '/Assets'); + } + + return array('dir' => $dir, 'fdir' => $fdir); + } + + public function getConfigZIP($d) + { + $res = array('width' => 0, 'height' => 0); + if (file_exists($d . '/index.html')) { + $doc = new DOMDocument(); + $doc->loadHTMLFile($d . '/index.html'); + $xpath = new DOMXPath($doc); + $c = $xpath->query("//canvas"); + foreach ($c as $canvas) { + /* @var $canvas DOMElement */ + $res['width'] = intval((string)$canvas->getAttribute('width')); + $res['height'] = intval((string)$canvas->getAttribute('height')); + } + + $r = array('html' => 'index.html', 'inject' => array(), 'injectcss' => array(), 'injectjs' => array()); + } else { + $r = array('html' => false, 'inject' => array(file_get_contents($d . '/init.js')), 'injectcss' => array('multimedia.css'), 'injectjs' => array('multimedia.js')); + } + $res = array_merge($res, $r); + return $res; + } } -- 2.39.5