'js/libs/fluidbook/fluidbook.desktop.js',
'js/libs/fluidbook/fluidbook.service.js',
'js/libs/fluidbook/fluidbook.l10n.js',
+ 'js/libs/fluidbook/fluidbook.slider.js',
'js/libs/fluidbook/fluidbook.nav.js',
'js/libs/fluidbook/fluidbook.touch.js',
'js/libs/fluidbook/fluidbook.interact.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 $lessFilesExtras = []; // Extra files that will be copied when compiling LESS (eg. used to allow video-js-core.css to be copied)
+ // 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 $lessFilesExtras = []; // Extra files that will be copied when compiling LESS (eg. used to allow video-js-core.css to be copied)
public $specialCSS = array();
public $phonegapStandardPlugins = array('ios' => array('ExternalFileUtil'),
protected $multiApp = false;
protected $pageLabels = array();
protected $stylesheets = array();
+ protected $logfp = null;
+ protected $logtime = null;
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;
return;
}
$this->book_id = $book_id;
+ $this->log('Start compilation');
if (is_null($dir)) {
$this->dir = WS_BOOKS . '/html5/' . $book_id . '/';
if (!file_exists($this->dir)) {
mkdir($this->dir, 0777, true);
}
+ $this->log('Clean vdir');
$this->daoBook = new wsDAOBook($core->con);
$this->book = $this->daoBook->selectById($book_id);
$this->config = cubeObject::merge($this->book->parametres->toStandardObject(), $this->theme->parametres->toStandardObject());
}
+ 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);
+ $this->logtime = $currenttime;
+ }
+
public function addPageLabel($page, $label) {
$this->pageLabels[$label] = $page;
}
public function compile() {
+ $this->log('Start compile process');
+
$dirsToCreate = array('data/images', 'data/contents', 'data/background', 'data/thumbnails', 'data/style');
if (in_array('flv', $this->getVideosFormats())) {
$dirsToCreate[] = 'swf';
if (file_exists($this->vdir . '/swf')) {
$this->copy($this->assets . '/swf/video.swf', $this->vdir . '/swf/video.swf');
}
-
+ $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($this->vdir . '/data/style/style_%d.css', $linksCSS);
+ $this->log('CSS written');
$this->writeLangs();
+ $this->log('Langs written');
$this->writeIndex();
+ $this->log('Index written');
$this->writeTexts();
+ $this->log('Texts written');
$this->writeExtras();
+ $this->log('Extras written');
$this->writeJs();
+ $this->log('Js written');
$this->writeCache();
+ $this->log('Cache written');
}
protected function loadPlugins() {
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');
-// }
+ //
+ // 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';
+ $res[] = 'mp4';
if ($poster) {
$res[] = 'jpg';
file_put_contents($cacheFile, implode("\n", $lines));
}
- /**
- * 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) {
-
- // 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 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) {
+
+ // 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, $extra_files = []) {
- if (!in_array($path, $this->lessFiles)) {
- $this->lessFiles[] = $path;
- }
-
- // Make sure no duplicates are added here either
- $this->lessFilesExtras = array_unique(array_merge($this->lessFilesExtras, $extra_files));
+ /**
+ * 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, $extra_files = []) {
+ if (!in_array($path, $this->lessFiles)) {
+ $this->lessFiles[] = $path;
+ }
+
+ // Make sure no duplicates are added here either
+ $this->lessFilesExtras = array_unique(array_merge($this->lessFilesExtras, $extra_files));
}
protected function writeIndex() {
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);
}
- $vars = array('titre', 'credits', 'ga', 'style', 'script', 'pagesContents', 'description', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon', 'svg');
+ $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'pagesContents', 'description', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon', 'svg');
foreach ($vars as $v) {
$html = str_replace('<!-- $' . $v . ' -->', $$v, $html);
}
$thtml = $uhtml;
- $vars = array('titre', 'credits', 'ga', 'style', 'script', 'pagesContents', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon');
+ $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'pagesContents', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon');
foreach ($vars as $v) {
$uhtml = str_replace('<!-- $' . $v . ' -->', $$v, $uhtml);
}
$script .= "\n\t\t" . '<script type="text/javascript" charset="utf-8">window.tester = true;</script>';
- $vars = array('titre', 'credits', 'ga', 'style', 'script', 'print', 'hiddenContents', 'splash', 'message');
+ $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'print', 'hiddenContents', 'splash', 'message');
foreach ($vars as $v) {
$thtml = str_replace('<!-- $' . $v . ' -->', $$v, $thtml);
}
}
if (file_exists($minimized)) {
$mintime = filemtime($minimized);
- $reminimize = false;
+ $reminimize = false;
} else {
$mintime = 0;
$reminimize = true;
if ($this->backgroundsPrefix == 'p') {
$srcPrefix = 'h';
}
+ $thumbs = array();
foreach ($this->pages as $page => $infos) {
+ $docdir = wsDocument::getDir($infos['document_id']);
if ($this->svg) {
- $orig = wsDocument::getDir($infos['document_id']) . 'html/p' . $infos['document_page'] . '.svg';
- $opt = wsDocument::getDir($infos['document_id']) . 'html/o' . $infos['document_page'] . '.svg';
+ $orig = $docdir . 'html/p' . $infos['document_page'] . '.svg';
+ $opt = $docdir . 'html/o' . $infos['document_page'] . '.svg';
$svg = $orig;
if (file_exists($opt) && filesize($opt) > 0) {
}
foreach ($this->getResolutions() as $r) {
- $ok = $this->copy(wsDocument::getDir($infos['document_id']) . 'html/' . $srcPrefix . $r . '-' . $infos['document_page'] . '.jpg', $this->vdir . '/data/background/' . $r . '/' . $this->backgroundsPrefix . $page . '.jpg');
+ $ok = $this->copy($docdir . 'html/' . $srcPrefix . $r . '-' . $infos['document_page'] . '.jpg', $this->vdir . '/data/background/' . $r . '/' . $this->backgroundsPrefix . $page . '.jpg');
if (!$ok && $r = 300) {
$this->maxRes = 150;
}
+ $this->copy(WS_DOCS . '/' . $infos['document_id'] . '/p' . $infos['document_page'] . '.jpg', $this->vdir . '/data/thumbnails/p' . $page . '.jpg');
}
$thumb = false;
$thumb = wsPDFConvert::getThumbFromPDF(WS_BOOKS . '/working/' . $this->book->book_id . '/' . $this->book->parametres->pdfThumbnails, $page);
}
if (!$thumb) {
- $thumb = wsDocument::getDir($infos['document_id']) . 'p' . $infos['document_page'] . '.jpg';
+ $thumb = $docdir . 'p' . $infos['document_page'] . '.jpg';
}
-
- $this->copy($thumb, $this->vdir . '/data/thumbnails/p' . $page . '.jpg');
+ $thumbs[$page] = $thumb;
if ($page == 1) {
- $this->_makeCover(wsDocument::getDir($infos['document_id']) . 'html/t36-' . $infos['document_page'] . '.jpg');
+ $this->_makeCover($docdir . 'html/t36-' . $infos['document_page'] . '.jpg');
+ }
+ $this->makeThumbSprites($thumbs);
+ $this->log('Copied image ' . $page);
+ }
+ }
+
+ 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 = $this->vdir . '/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`;
}
+ copy($cache, $dest);
+ $k++;
}
+ return $res;
}
protected function _makeCover($orig) {
return true;
}
+ protected function _lessBoolean($val) {
+ return $val ? 'true' : 'false';
+ }
+
protected function writeCSS($file, $links) {
$res = array();
$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;
$offsetLeft2 = $offsetLeft * 2;
$offsetTop = round(($this->optimalHeight - $cssHeight) / 2, 3);
$navTop = ($cssHeight - 40 - 100) / 2;
- $leftOfRightPage=(floor($cssWidth)-1).'px';
+ $leftOfRightPage = (floor($cssWidth) - 1) . 'px';
+ $lessVariables['z'] = $this->z;
+ $lessVariables['book-page-width'] = $w;
+ $lessVariables['book-page-height'] = $h;
$res[] = '.portrait #pages,.portrait .doublePage.page,.page,.doublePage._3d,#shadow>div{width:' . $w . ';max-width:' . $w . ';height:' . $h . ';max-height:' . $h . '}';
$res[] = '.doublePage,#pages,#links{width:' . $w2 . ';max-width:' . $w2 . ';height:' . $h . ';max-height:' . $h . '}';
$res[] = '#links.right{left:-' . $w . ';}';
$res[] = '.landscape #shadow>div.right{left: ' . $w . ';}';
$res[] = '.landscape .page.right{left:' . $w . '}';
- if ($this->theme->parametres->displayPageNumber) {
- $res[] = '#pagesnumbers{font-size: ' . (12 * $this->z) . 'px;margin: ' . (5 * $this->z) . 'px 0 0 0;top:' . $h . ';color:' . wsHTML5::colorToCSS($this->theme->parametres->colorPageNumber) . '}';
- $res[] = '#pagesnumbers div{width:' . $w . '}';
- } else {
- $res[] = '#pagesnumbers{display:none;}';
- }
+
+ $lessVariables['page-number-color'] = wsHTML5::colorToCSS($this->theme->parametres->colorPageNumber);
+ $lessVariables['display-page-number'] = $this->_lessBoolean($this->theme->parametres->displayPageNumber);
+
$res[] = '.doublePage._2d,.doublePage._3d{' . wsHTML5::writeCSSUA('transition', 'all ' . $this->book->parametres->mobileTransitionDuration . 's ease-in-out') . '}';
$res[] = '.background{' . wsHTML5::writeCSSUA('transform-origin', 'top left') . ';}';
$res[] = '#shadow>div{' . wsHTML5::writeCSSUA('box-shadow', '0 0 20px ' . $shadowColor) . '}';
}
+ $lessVariables['links-color']=wsHTML5::colorToCSS($this->theme->parametres->linksColor);
+
// Links Styles
$res = array_merge($res, $links);
- $res[] = '.link a.displayArea:hover,.link a.displayArea.animating{background-color:' . wsHTML5::colorToCSS($this->theme->parametres->linksColor, 0.4) . ';}';
- $res[] = '.link a.displayArea:hover{opacity:1 !important;}';
- $res[] = '.link a.displayArea{-webkit-tap-highlight-color:' . wsHTML5::colorToCSS($this->theme->parametres->linksColor, 0.4) . ';background-color:' . wsHTML5::colorToCSS($this->theme->parametres->linksColor, 0.0001) . ';}';
// Bookmarks
if (!isset($this->book->parametres->bookmarkCornerSize)) {
# Index
$ratio = $this->width / $this->height;
$thumbh = round(100 / $ratio);
+ $this->config->thumbHeight = $thumbh;
$lessVariables['thumb-height'] = $thumbh . 'px';
- # Tooltip
- $res[] = '#tooltip{background-color:' . wsHTML5::colorToCSS($this->theme->parametres->tooltipBackColor) . ';color:' . wsHTML5::colorToCSS($this->theme->parametres->tooltipTextColor) . ';}';
+ #tooltip
+ $lessVariables['tooltip-background'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipBackColor);
+ $lessVariables['tooltip-color'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipTextColor);
- # ZoomPopup close button background
+ # ZoomPopup close button background
$res[] = '.zoomPopupClose {background-color:' . wsHTML5::colorToCSS($this->theme->parametres->couleurB) . ';}';
$tmp = CubeIT_Files::tmpdir();
- copy($this->assets . '/style/variables.less', $tmp . '/variables.less');
- copy($this->assets . '/style/mixins.less', $tmp . '/mixins.less');
+ $from = $this->assets . '/style/*';
+ `cp -r $from $tmp`;
$bookVariables = array();
foreach ($variables as $k => $v) {
}
file_put_contents($tmp . '/book-variables.less', implode("\n", $bookVariables));
- // Also copy any "extra" files that might be needed by LESS compilation
- // (eg. video-js-core.css is needed by videojs.less)
- foreach ($this->lessFilesExtras as $extra) {
- $destination_extra = $tmp . '/' . $extra;
+ // Also copy any "extra" files that might be needed by LESS compilation
+ // (eg. video-js-core.css is needed by videojs.less)
+ foreach ($this->lessFilesExtras as $extra) {
+ $destination_extra = $tmp . '/' . $extra;
if (!is_dir(dirname($destination_extra))) {
mkdir(dirname($destination_extra), 0777, true);
}
- copy($this->assets . '/style/' . $extra, $destination_extra);
- }
+ copy($this->assets . '/style/' . $extra, $destination_extra);
+ }
foreach ($this->lessFiles as $f) {
- $source_less = $this->assets . '/style/' . $f . '.less';
- $destination_less = $tmp . '/' . $f . '.less';
- $destination_css = 'style/' . $f . '.css';
+ $source_less = $this->assets . '/style/' . $f . '.less';
+ $destination_less = $tmp . '/' . $f . '.less';
+ $destination_css = 'style/' . $f . '.css';
if (!file_exists($source_less)) {
continue;
}
- // LESS file might be in a subfolder, so create if it doesn't exist
+ // 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);
}
- // Generated CSS file might be in a subfolder, so create if it doesn't exist
+ // Generated CSS file might be in a subfolder, so create if it doesn't exist
if (!is_dir(dirname($this->vdir . '/' . $f . '.css'))) {
mkdir(dirname($this->vdir . '/' . $f . '.css'), 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);
+ // have access to the variables generated in book-variables.less
+ copy($source_less, $destination_less);
$less = new CubeIT_CommandLine('lessc');
$less->setArg('plugin', 'less-plugin-clean-css');
$less->setArg(null, $destination_less);