<output-test url="file://$MODULE_DIR$/out/test/fluidbook_tools" />
<exclude-output />
<content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/resources/tools/fwstk/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="Fluidbook\Tools\" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/brick/math" />
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+ use Links;
+
/** @var VirtualDirectory */
protected $vdir;
/**
* @var stdClass
*/
- protected $config;
+ public $config;
/**
* @var Source[]
protected $pages = [];
- /**
- * @var Link[]
- */
- protected $links = [];
-
/**
* @var string
*/
return $res;
}
- public function compileLinks()
- {
- $links = $this->getLinks();
-
- $this->config->links = array();
- $this->config->clinks = array();
- $this->config->bookmarkGroups = array();
-
- // Custom landing page content
-
-// if ($this->book->parametres->tabsHTML5 != '' && file_exists($this->wdir . '/' . $this->book->parametres->tabsHTML5)) {
-// $ext = CubeIT_Files::getExtension($this->book->parametres->tabsHTML5);
-// if ($ext === 'zip') {
-// $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',
-// 'uid' => 'tabs',
-// ];
-// } else if ($ext === 'svg') {
-// $this->vdir->copy($this->wdir . '/' . $this->book->parametres->tabsHTML5, 'data/tabs.svg');
-// $this->config->svgTabs = true;
-// $pagesLists = ['tabsPages', 'tabsSections'];
-// foreach ($pagesLists as $pagesList) {
-// $e = explode(',', $this->book->parametres->$pagesList);
-// $list = [];
-// foreach ($e as $k => $v) {
-// $v = trim($v);
-// if ($v === '') {
-// continue;
-// }
-// if ($v !== '-') {
-// if ($this->book->parametres->tabsPagesNumbers === 'virtual') {
-// $v = $this->virtualToPhysical($v);
-// }
-// }
-// $list[] = $v;
-// }
-// $this->config->$pagesList = $list;
-// }
-// }
-// }
-
- $pagesOfCustomLinks = [];
- $hiddenLinks = [];
-
- $linksCopy = $links;
-
- foreach ($linksCopy as $k => $linkData) {
- if ($linkData['type'] == 35 || $linkData['type'] == 15 || $linkData['type'] == 39) {
- $linkData = wsLinks::decryptLink($linkData);
- $animations = contentLink::parseAnimations($linkData['image_rollover']);
- foreach ($animations as $animation) {
- if (isset($animation['backgroundcolor']) && $animation['backgroundcolor'] !== 'transparent') {
- $dupData = $linkData;
- $dupData['type'] = 14;
- $dupData['to'] = $animation['backgroundcolor'];
-
- $dupData['uid'] = 'b_' . $linkData['uid'];
- $dupData['image_rollover'] = 'addzindex=-1';
- array_push($links, $dupData);
- array_push($links, $linkData);
- unset($links[$k]);
- }
- }
- }
- if (isset($linkData['image']) && $linkData['image'] && $linkData['type'] != 28 && $linkData['type'] != 35) {
- $dupData = $linkData;
- $dupData['image'] = '';
- $dupData['animation'] = '';
- $dupData['to'] = $linkData['image'];
- $dupData['rollover'] = $linkData['image_rollover'];
- $dupData['type'] = 15;
- $dupData['uid'] = 'i_' . $linkData['uid'];
- array_push($links, $dupData);
- }
- if (isset($linkData['animation']) && $linkData['animation']) {
- $dupData = $linkData;
- $dupData['image'] = '';
- $dupData['animation'] = '';
- $dupData['inline'] = true;
- $dupData['interactive'] = false;
- $dupData['alternative'] = $linkData['animation'];
- $dupData['type'] = 6;
- $dupData['uid'] = 'a_' . $linkData['uid'];
- $dupData['video_width'] = $dupData['video_height'] = 0;
- if (wsHTML5Link::isScorm($linkData)) {
- $dupData['scorm'] = true;
- }
- array_push($links, $dupData);
- }
- if ($linkData['type'] == 32) {
- $ids = explode(',', $linkData['to']);
- foreach ($ids as $id) {
- $id = trim($id);
- if ($id === 'tabs') {
- $this->config->tabsHiddenAtStartup = true;
- } else {
- $hiddenLinks[] = $id;
- $hiddenLinks[] = 'i_' . $id;
- }
- }
- }
- }
-
-
- $i = 1;
- $pages = array();
- $cpages = array();
- $ctpages = array();
- $css = array();
- $linkPages = [];
- $allLinksData = [];
- $gamifyCoins = [];
-
- usort($links, array($this, '_sortLinks'));
-
- foreach ($links as $linkData) {
- $link = Link::getInstance($this->base62($i), $linkData, $this);
- if (is_null($link)) {
- continue;
- }
-
- $linksToAdd = [$link];
- if ($link->overlapDoublePage()) {
- $linksToAdd[] = $link->getRightClone();
- }
-
- foreach ($linksToAdd as $lta) {
- /** @var $lta Link */
- // Keep this line because some properties of the link (like blend mode) are parsed with this function
- $c = $lta->getHTMLContainer();
- $css[] = $lta->getCSSContainer();
- if (!isset($pages[$lta->page])) {
- $pages[$lta->page] = ['normal' => []];
- $cpages[$lta->page] = ['normal' => []];
- $ctpages[$lta->page] = ['normal' => []];
- }
-
- $d = $lta->getDepth();
- if ($d < 30) {
- $v = 'ctpages';
- } else if ($d < 50) {
- $v = 'cpages';
- } else {
- $v = 'pages';
- }
-
- $lta->setInitialOrder($i);
- if (!isset($$v[$lta->page][$lta->blendmode])) {
- $$v[$lta->page][$lta->blendmode] = [];
- }
-
- array_push($$v[$lta->page][$lta->blendmode], $lta);
- $i++;
- }
- // 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;
- }
-
- if (strpos($link->page, 'link_') === 0) {
- $linkPages[$link->page] = true;
- }
-
- if ($link->gamifyCoins) {
- $gamifyCoins[$linkData['uid']] = (float)$link->gamifyCoins;
- }
-
- $allLinksData[$linkData['uid']] = $linkData;
-
- if ($link->keep()) {
- $this->hiddenContents[] = $link->getHTMLContainer();
- }
- }
-
- $allpages = range(0, $this->book->parametres->pages + 1);
- if ($this->book->parametres->themeEnableAfterSearch) {
- $allpages[] = 'aftersearch';
- }
- $allpages[] = 'background';
- $allpages[] = 'archives';
- foreach ($linkPages as $linkPage => $true) {
- $allpages[] = $linkPage;
- }
-
- foreach ($allpages as $i) {
- $this->config->links[$i] = $this->_htmlLinkList($pages[$i] ?? []);
- $this->config->clinks[$i] = $this->_htmlLinkList($cpages[$i] ?? []);
- $this->config->ctlinks[$i] = $this->_htmlLinkList($ctpages[$i] ?? []);
- }
-
- if ($this->writeLinksData) {
- $this->config->linksData = $allLinksData;
- }
- $this->config->gamifyCoins = $gamifyCoins;
-
- return $css;
- }
-
/**
* @throws \JsonException
}
}
- public function getLinks()
+ public function getBookSurface()
{
- return [];
+ return $this->getWidth() * $this->getHeight();
}
- protected function getLinksFromPDF()
- {
- $booleans = ['video_loop', 'video_auto_start', 'video_controls', 'video_sound_on'];
- $numbers = ['left', 'top', 'width', 'height'];
-
- $links = [];
-
- for ($i = 1; $i <= $this->getPageCount(); $i++) {
- $s = $this->getSourceOfPage($i);
- $csv = $s->getSource()->getDocument()->getConvertPath() . '/links/p' . $s->getPage() . '.csv';
- if (!file_exists($csv)) {
- $s->getSource()->getDocument()->processLinks();
- }
-
- $fp = fopen($csv, 'rb');
- while (true) {
- $line = fgetcsv($fp, 512, ';', '"');
- // End of file
- if (!$line) {
- break;
- }
- // Commentaire || ligne vide
- if (substr($line[0], 0, 1) === '#' || is_null($line[0])) {
- continue;
- }
- $link = [];
-
- $cols = ['page' => '', 'left' => '', 'top' => '', 'width' => '', 'height' => '', 'type' => '', 'to' => '', 'target' => '_blank', 'video_loop' => true, 'video_auto_start' => true, 'video_controls' => true, 'video_sound_on' => true, 'infobulle' => '', 'numerotation' => 'physical', "inline" => true];
-
- $k = 0;
- foreach ($cols as $col => $default) {
- if (isset($line[$k])) {
- if (in_array($k, $numbers)) {
- $link[$col] = (float)str_replace(',', '.', $line[$k]);
- } else if (in_array($k, $booleans)) {
- $link[$col] = ($line[$k] == '1');
- } else {
- $link[$col] = utf8_encode($line[$k]);
- }
- } else {
- $link[$col] = $default;
- }
- $k++;
- }
-
- if ($link['type'] == 18) {
- $link['infobulle'] = $link['to'];
- $link['to'] = '';
- }
-
- $link['display_area'] = '1';
- $link['page'] = $i;
- $links[] = $link;
- }
-
- }
+ public function getWidth(){
+ return $this->getSourceOfPage(1)->getSource()->getDocument()->getWidth();
+ }
- return $links;
+ public function getHeight(){
+ return $this->getSourceOfPage(1)->getSource()->getDocument()->getHeight();
}
+
}
--- /dev/null
+<?php
+
+namespace Fluidbook\Tools\Compiler;
+
+use Cubist\Util\ArrayUtil;
+use Fluidbook\Tools\Links\ContentLink;
+use Fluidbook\Tools\Links\Link;
+
+trait Links
+{
+ public function compileLinks()
+ {
+ /** @var Link[] $links */
+ $links = $this->getLinks();
+
+ $this->config->links = array();
+ $this->config->clinks = array();
+ $this->config->bookmarkGroups = array();
+
+ // Custom landing page content
+
+// if ($this->book->parametres->tabsHTML5 != '' && file_exists($this->wdir . '/' . $this->book->parametres->tabsHTML5)) {
+// $ext = CubeIT_Files::getExtension($this->book->parametres->tabsHTML5);
+// if ($ext === 'zip') {
+// $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',
+// 'uid' => 'tabs',
+// ];
+// } else if ($ext === 'svg') {
+// $this->vdir->copy($this->wdir . '/' . $this->book->parametres->tabsHTML5, 'data/tabs.svg');
+// $this->config->svgTabs = true;
+// $pagesLists = ['tabsPages', 'tabsSections'];
+// foreach ($pagesLists as $pagesList) {
+// $e = explode(',', $this->book->parametres->$pagesList);
+// $list = [];
+// foreach ($e as $k => $v) {
+// $v = trim($v);
+// if ($v === '') {
+// continue;
+// }
+// if ($v !== '-') {
+// if ($this->book->parametres->tabsPagesNumbers === 'virtual') {
+// $v = $this->virtualToPhysical($v);
+// }
+// }
+// $list[] = $v;
+// }
+// $this->config->$pagesList = $list;
+// }
+// }
+// }
+
+ $pagesOfCustomLinks = [];
+ $hiddenLinks = [];
+
+ $linksCopy = $links;
+
+ foreach ($linksCopy as $k => $linkData) {
+ if ($linkData['type'] == 35 || $linkData['type'] == 15 || $linkData['type'] == 39) {
+ $linkData = wsLinks::decryptLink($linkData);
+ $animations = ContentLink::parseAnimations($linkData['image_rollover']);
+ foreach ($animations as $animation) {
+ if (isset($animation['backgroundcolor']) && $animation['backgroundcolor'] !== 'transparent') {
+ $dupData = $linkData;
+ $dupData['type'] = 14;
+ $dupData['to'] = $animation['backgroundcolor'];
+
+ $dupData['uid'] = 'b_' . $linkData['uid'];
+ $dupData['image_rollover'] = 'addzindex=-1';
+ $links[] = $dupData;
+ $links[] = $linkData;
+ unset($links[$k]);
+ }
+ }
+ }
+ if (isset($linkData['image']) && $linkData['image'] && $linkData['type'] != 28 && $linkData['type'] != 35) {
+ $dupData = $linkData;
+ $dupData['image'] = '';
+ $dupData['animation'] = '';
+ $dupData['to'] = $linkData['image'];
+ $dupData['rollover'] = $linkData['image_rollover'];
+ $dupData['type'] = 15;
+ $dupData['uid'] = 'i_' . $linkData['uid'];
+ $links[] = $dupData;
+ }
+ if (isset($linkData['animation']) && $linkData['animation']) {
+ $dupData = $linkData;
+ $dupData['image'] = '';
+ $dupData['animation'] = '';
+ $dupData['inline'] = true;
+ $dupData['interactive'] = false;
+ $dupData['alternative'] = $linkData['animation'];
+ $dupData['type'] = 6;
+ $dupData['uid'] = 'a_' . $linkData['uid'];
+ $dupData['video_width'] = $dupData['video_height'] = 0;
+ if (Link::isScorm($linkData)) {
+ $dupData['scorm'] = true;
+ }
+ $links[] = $dupData;
+ }
+ if ($linkData['type'] == 32) {
+ $ids = explode(',', $linkData['to']);
+ foreach ($ids as $id) {
+ $id = trim($id);
+ if ($id === 'tabs') {
+ $this->config->tabsHiddenAtStartup = true;
+ } else {
+ $hiddenLinks[] = $id;
+ $hiddenLinks[] = 'i_' . $id;
+ }
+ }
+ }
+ }
+
+
+ $i = 1;
+ $pages = array();
+ $cpages = array();
+ $ctpages = array();
+ $css = array();
+ $linkPages = [];
+ $allLinksData = [];
+ $gamifyCoins = [];
+
+ usort($links, array($this, '_sortLinks'));
+
+ foreach ($links as $linkData) {
+ $link = Link::getInstance(self::base36($i), $linkData, $this);
+ if (is_null($link)) {
+ continue;
+ }
+
+ $linksToAdd = [$link];
+ if ($link->overlapDoublePage()) {
+ $linksToAdd[] = $link->getRightClone();
+ }
+
+ foreach ($linksToAdd as $lta) {
+ /** @var $lta Link */
+ // Keep this line because some properties of the link (like blend mode) are parsed with this function
+ $c = $lta->getHTMLContainer();
+ $css[] = $lta->getCSSContainer();
+ if (!isset($pages[$lta->page])) {
+ $pages[$lta->page] = ['normal' => []];
+ $cpages[$lta->page] = ['normal' => []];
+ $ctpages[$lta->page] = ['normal' => []];
+ }
+
+ $d = $lta->getDepth();
+ if ($d < 30) {
+ $v = 'ctpages';
+ } else if ($d < 50) {
+ $v = 'cpages';
+ } else {
+ $v = 'pages';
+ }
+
+ $lta->setInitialOrder($i);
+ if (!isset($$v[$lta->page][$lta->blendmode])) {
+ $$v[$lta->page][$lta->blendmode] = [];
+ }
+
+ $$v[$lta->page][$lta->blendmode][] = $lta;
+ $i++;
+ }
+ // 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;
+ }
+
+ if (strpos($link->page, 'link_') === 0) {
+ $linkPages[$link->page] = true;
+ }
+
+ if ($link->gamifyCoins) {
+ $gamifyCoins[$linkData['uid']] = (float)$link->gamifyCoins;
+ }
+
+ $allLinksData[$linkData['uid']] = $linkData;
+
+ if ($link->keep()) {
+ $this->hiddenContents[] = $link->getHTMLContainer();
+ }
+ }
+
+ $allpages = range(0, $this->getPageCount() + 1);
+ if ($this->config->themeEnableAfterSearch) {
+ $allpages[] = 'aftersearch';
+ }
+ $allpages[] = 'background';
+ $allpages[] = 'archives';
+ foreach ($linkPages as $linkPage => $true) {
+ $allpages[] = $linkPage;
+ }
+
+ $this->config->links=[];
+ $this->config->clinks=[];
+ $this->config->ctlinks=[];
+
+ foreach ($allpages as $i) {
+ $this->config->links[$i] = $this->_htmlLinkList($pages[$i] ?? []);
+ $this->config->clinks[$i] = $this->_htmlLinkList($cpages[$i] ?? []);
+ $this->config->ctlinks[$i] =
+ $this->_htmlLinkList(
+ $ctpages[$i] ?? []
+ );
+ }
+
+ if (isset($this->writeLinksData) && $this->writeLinksData) {
+ $this->config->linksData = $allLinksData;
+ }
+ $this->config->gamifyCoins = $gamifyCoins;
+
+ return $css;
+ }
+
+ public function getLinks()
+ {
+ return [];
+ }
+
+ protected function getLinksFromPDF()
+ {
+ $booleans = ['video_loop', 'video_auto_start', 'video_controls', 'video_sound_on'];
+ $numbers = ['left', 'top', 'width', 'height'];
+
+ $links = [];
+
+ for ($i = 1; $i <= $this->getPageCount(); $i++) {
+ $s = $this->getSourceOfPage($i);
+ $csv = $s->getSource()->getDocument()->getConvertPath() . '/links/p' . $s->getPage() . '.csv';
+ if (!file_exists($csv)) {
+ $s->getSource()->getDocument()->processLinks();
+ }
+
+ $fp = fopen($csv, 'rb');
+ while (true) {
+ $line = fgetcsv($fp, 512, ';', '"');
+ // End of file
+ if (!$line) {
+ break;
+ }
+ // Commentaire || ligne vide
+ if (substr($line[0], 0, 1) === '#' || is_null($line[0])) {
+ continue;
+ }
+ $link = ['uid' => self::makeUID()];
+
+ $cols = ['page' => '', 'left' => '', 'top' => '', 'width' => '', 'height' => '', 'type' => '', 'to' => '', 'target' => '_blank', 'video_loop' => true, 'video_auto_start' => true, 'video_controls' => true, 'video_sound_on' => true, 'infobulle' => '', 'numerotation' => 'physical', "inline" => true];
+
+ $k = 0;
+
+ foreach ($cols as $col => $default) {
+ if (isset($line[$k])) {
+ if (in_array($col, $numbers)) {
+ $link[$col] = (float)str_replace(',,', '..', $line[$k]);
+ } else if (in_array($k, $booleans)) {
+ $link[$col] = ($line[$k] == '1');
+ } else {
+ $link[$col] = utf8_encode($line[$k]);
+ }
+ } else {
+ $link[$col] = $default;
+ }
+ $k++;
+ }
+
+ if ($link['type'] == 18) {
+ $link['infobulle'] = $link['to'];
+ $link['to'] = '';
+ }
+
+ $link['display_area'] = '1';
+ $link['page'] = $i;
+ $links[] = $link;
+ }
+
+ }
+ return $links;
+ }
+
+ protected static function makeUID()
+ {
+ return substr(md5(uniqid('fblink_', true)), 2, 8) . '00';
+ }
+
+ protected function _htmlLinkList($list)
+ {
+ if (!count($list)) {
+ return [];
+ }
+ $res = [];
+ foreach ($list as $blendmode => $l) {
+ usort($l, [$this, '_sortLinksByDepth']);
+ $res[$blendmode] = [];
+ foreach ($l as $item) {
+ $res[$blendmode][] = $item->getHTMLContainer();
+ }
+
+ }
+ return $res;
+
+ }
+
+ protected function _sortLinksByDepth($a, $b)
+ {
+ $c = $a->getDepth() - $b->getDepth();
+ if ($c === 0) {
+ $c = $b->getSurface() - $a->getSurface();
+ }
+ if ($c === 0) {
+ $c = $b->getInitialOrder() - $a->getInitialOrder();
+ }
+
+ return $c;
+ }
+
+ public function _sortLinks($a, $b)
+ {
+
+ $priorities = array(26 => -1, 35 => 1);
+
+ $pa = isset($priorities[$a['type']]) ? -$priorities[$a['type']] : 0;
+ $pb = isset($priorities[$b['type']]) ? -$priorities[$b['type']] : 0;
+ return $pb - $pa;
+ }
+
+ protected static function base36($val)
+ {
+ $chars = '0123456789abcdefghijklmnopqrstuvwxyz';
+ $base = strlen($chars);
+ $str = '';
+ do {
+ $i = $val % $base;
+ $str = $chars[$i] . $str;
+ $val = ($val - $i) / $base;
+ } while ($val > 0);
+ return $str;
+ }
+
+ /**
+ * @return number
+ */
+ public function getLinkScale()
+ {
+ return (float)$this->config->cssScale;
+ }
+
+}
use Cubist\Util\ObjectUtil;
use Cubist\Util\Text;
use Cubist\Util\Xml;
+use Fluidbook\Tools\Compiler\Compiler;
+use stdClass;
class Link
{
public $border = 0;
public $borderColor = '#ffffff';
public $maxWidth = 0;
- public $wdir;
public $initialOrder = 0;
public $gamifyCoins = 0;
public $tooltipColor = null;
/**
*
* @param integer $id
- * @param stdClass $init
- * @param wsHTML5Compiler $compiler
+ * @param stdClass|array $init
+ * @param Compiler $compiler
* @return Link
*/
public static function getInstance($id, $init, &$compiler)
$this->id = $id;
$this->compiler = $compiler;
- $this->wdir = $this->compiler->wdir;
$this->init();
}
// $this->page is normally an integer but it can also be a string (eg. background / aftersearch)
if (!is_int($this->page)) return false;
- return ($this->page % 2 == 0 && $this->left + $this->width > $this->compiler->width);
+ return ($this->page % 2 == 0 && $this->left + $this->width > $this->compiler->getWidth());
}
public function getRightClone()
{
$res = clone $this;
$res->page++;
- $res->left -= $this->compiler->width;
+ $res->left -= $this->compiler->getWidth();
$res->rightClone = true;
$res->id .= '_c';
$res->init();
{
if ($this->moveOnEvenPage()) {
$this->page--;
- $this->left += $this->compiler->width;
+ $this->left += $this->compiler->getWidth();
}
+
$css = '#l_' . $this->id . '{';
$css .= 'left:' . round($this->left * $this->getCssScale()) . 'px;top:' . round($this->top * $this->getCssScale()) . 'px;';
$css .= 'width:' . round($this->width * $this->getCssScale()) . 'px;height:' . round($this->height * $this->getCssScale()) . 'px;';
if ($this->tooltipMaxWidth) {
$res .= ' data-tooltip-maxwidth="' . $this->tooltipMaxWidth . '" ';
} else {
- $res .= ' data-tooltip-maxwidth="' . $this->compiler->book->parametres->linkTooltipMaxWidth . '" ';
+ $res .= ' data-tooltip-maxwidth="' . $this->compiler->config->linkTooltipMaxWidth . '" ';
}
$res .= ' data-tooltip-touch="1" ';
return $res;