--- /dev/null
+<?php
+
+namespace App\Http\Controllers\Admin\Operations\FluidbookPublication\Services;
+
+use App\Http\Middleware\CheckIfAdmin;
+use App\Models\FluidbookPublication;
+use Cubist\Backpack\Http\Controllers\Base\XSendFileController;
+use Cubist\Util\CommandLine;
+use Cubist\Util\Files\Files;
+use Cubist\Util\Graphics\Image;
+use Cubist\Util\PHP;
+use Illuminate\Support\Facades\Route;
+use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\F;
+
+trait SocialImageOperation
+{
+ protected function setupSocialimageRoutes($segment, $routeName, $controller)
+ {
+ Route::match(['get'], 'services/socialimage/{cid?}', $controller . '@socialImage')->withoutMiddleware([CheckIfAdmin::class]);
+ Route::match(['get'], 'services/facebook_thumbnail', $controller . '@ws2SocialImage')->withoutMiddleware([CheckIfAdmin::class]);
+ }
+
+ public function ws2SocialImage()
+ {
+ if (request()->has('id') && request()->input('id') <= 18972) {
+ $publication = FluidbookPublication::find(request()->input('id'));
+ if (null === $publication) {
+ abort(404);
+ }
+ return $this->_socialImage($publication);
+ } else if (request()->has('cid')) {
+ return $this->socialImage(request()->input('cid'));
+ }
+ abort(404);
+ }
+
+ public function socialImage($cid)
+ {
+ $publication = FluidbookPublication::where('cid', $cid)->first();
+ if (null === $publication) {
+ abort(404);
+ }
+ return $this->_socialImage($publication);
+ }
+
+ public static function socialImagePath($id, $ext = 'jpg')
+ {
+ return Files::mkdir(protected_path('fluidbookpublication/socialimage')) . '/' . $id . '.' . $ext;
+ }
+
+ /**
+ * @param $fluidbook FluidbookPublication
+ * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response|object
+ * @throws \Exception
+ */
+ protected function _socialImage($fluidbook)
+ {
+ PHP::neverStop(true);
+
+ $social = self::createSocialImage($fluidbook);
+ return XSendFileController::sendfile($social);
+ }
+
+ /**
+ * @param $fluidbook FluidbookPublication
+ * @return string
+ */
+ public static function createSocialImage($fluidbook)
+ {
+ $id = $fluidbook->id;
+ $wid = $fluidbook->getAssetDir() . '/';
+
+ if ($fluidbook->facebook_image != '') {
+ $c = $wid . $fluidbook->facebook_image;
+ if (file_exists($c)) {
+ $res = $c;
+ }
+ }
+
+ if (!isset($res)) {
+ $res = self::socialImagePath($id);
+ $limit = max(time() - (3600 * 24 * 30), $fluidbook->updated_at->getTimestamp());
+ $minsize = 20 * 1024;
+
+ if (isset($_GET['force']) || !file_exists($res) || filemtime($res) < $limit || filesize($res) < $minsize) {
+ $lock = self::socialImagePath($id, 'lock');
+ if (!file_exists($lock) || filemtime($lock) < time() - 3600) {
+ touch($lock);
+
+ $url = 'https://workshop.fluidbook.com/viewerh/' . $id . '_' . $fluidbook->hash . '_' . time() . '/?nointerface=1';
+ if ((file_exists($res) && filemtime($res) < $limit) || isset($_GET['forcecompile'])) {
+ $url .= '&force=1';
+ }
+ $url .= '#/page/0';
+
+ $w = 1200;
+ $h = 628;
+
+ $cl = new CommandLine('node');
+ $cl->setArg(null, resource_path('fluidbookpublication/social_screenshot/social_screenshot.js'));
+ $cl->setArg('width', $w);
+ $cl->setArg('height', $h);
+ $cl->setArg('delay', 10);
+ $cl->setArg('scale', 0.5);
+ $cl->setArg('dest', $res);
+ $cl->setArg('url', $url);
+ $cl->execute();
+ unlink($lock);
+ }
+ }
+ }
+ return $res;
+ }
+
+ /**
+ * @param $fluidbook
+ * @return array
+ * @throws \Exception
+ */
+ public static function getSocialImageSize($fluidbook)
+ {
+ $socialImage = self::createSocialImage($fluidbook);
+ $sizeFile = self::socialImagePath($fluidbook->id, 'size');
+ if (!file_exists($sizeFile) || filemtime($sizeFile) < filemtime($socialImage)) {
+ $res = Image::getimagesize($socialImage);
+ file_put_contents($sizeFile, json_encode($res));
+ return $res;
+ }
+ return json_decode(file_get_contents($sizeFile), true);
+ }
+}
namespace App\Jobs;
+use App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\SocialImageOperation;
+use App\Models\Signature;
use App\Fluidbook\SearchIndex;
use App\Fluidbook\SEO\Document;
use App\Models\FluidbookPublication;
$this->config->manifest = $this->writeManifest();
}
- $this->writeGPUDatabase();
-
if ($this->config->form == 'bulle') {
$this->addJsLib('bulle', 'js/libs/fluidbook/forms/fluidbook.form.bulle.js');
} else if ($this->config->form == 'bourbon') {
}
}
- public function writeGPUDatabase()
- {
- $r = $core->con->select('SELECT gpu,rgpu,score FROM gpu');
- $gpu = [];
- while ($r->fetch()) {
- $gpu[$r->gpu] = $r->score;
- $gpu[$r->rgpu] = $r->score;
- }
- $this->config->gupsc = $gpu;
- $this->config->gupse = wsServices::gpuSeparators();
- }
-
public function log($step)
{
-
-
$currenttime = microtime(true);
if (null === $this->logfp) {
$this->logfp = fopen('/var/log/extranet/htmlconversions/' . $this->book_id . '.log', 'w+');
}
}
+ /**
+ * @throws \Exception
+ */
public function getIndexVars()
{
if (null === $this->_indexVars) {
$titre = $this->fluidbookSettings->title;
-
if (null === $this->_signature) {
- $daoSignature = new wsDAOSignature($core->con);
- $this->_signature = $daoSignature->selectById($this->fluidbookSettings->signature);
+ $this->_signature = Signature::find($this->fluidbookSettings->signature);
+ $credits = $this->_signature->credits;
+ } else {
+ $credits = '';
}
-
- $credits = $this->_signature->credits;
-
$hiddenContents = implode("\n", $this->hiddenContents);
-
$bgcolor = $this->themeSettings->loadingBackColor;
// Feuilles de style
$style = array();
foreach ($sheets as $sheet) {
- $style[] = '<link type="text/css" rel="stylesheet" media="screen" href="' . $sheet . '?j=' . TIME . '">';
+ $style[] = '<link type="text/css" rel="stylesheet" media="screen" href="' . $sheet . '?j=' . time() . '">';
}
$style = implode("\n\t\t", $style);
$beginbody = implode("\n", array_unique($this->beginBody));
- $jstime = "?j=" . TIME;
+ $jstime = "?j=" . time();
$iscript = '';
if (count($this->htmlmultimedia)) {
$this->log('Got index vars 2');
- $socialTitle = html::escapeHTML($this->fluidbookSettings->facebook_title ? $this->fluidbookSettings->facebook_title : $titre);
- $socialDescription = html::escapeHTML($this->fluidbookSettings->facebook_description ? $this->fluidbookSettings->facebook_description : $this->fluidbookSettings->seoDescription);
+ $socialTitle = htmlspecialchars($this->fluidbookSettings->facebook_title ?: $titre, ENT_COMPAT);
+ $socialDescription = htmlspecialchars($this->fluidbookSettings->facebook_description ?: $this->fluidbookSettings->seoDescription, ENT_COMPAT);
- $socialImage = 'https://workshop.fluidbook.com/services/facebook_thumbnail?cid=' . $this->getFluidbook()->cid;
- $sizeFile = WS_FILES . '/social_image/' . $this->getFluidbook()->book_id . '.size';
- if (!file_exists($sizeFile)) {
- $dim = Image::getimagesize($socialImage);
- file_put_contents($sizeFile, json_encode($dim));
- $this->log('Got index vars (measure social image)');
- } else {
- $dim = json_decode(file_get_contents($sizeFile), true);
- }
+ $socialImage = 'https://toolbox.fluidbook.com/services/socialimage/' . $this->getFluidbook()->cid;
+ $dim = SocialImageOperation::getSocialImageSize($this->getFluidbook());
$socialImageWidth = $dim[0];
$socialImageHeight = $dim[1];
$convert = "convert $pngFile -resize 64x64^ -gravity center $tmp";
`$convert`;
- $icotool = new cubeCommandLine('icotool');
+ $icotool = new CommandLine('icotool');
$icotool->setArg('c');
$icotool->setArg('o', $icoFile);
$icotool->setArg(null, $tmp);
}
$a = $seoArticle;
unset($a['image']);
- $a['imageurl'] = 'https://workshop.fluidbook.com/services/facebook_thumbnail?cid=' . $this->getFluidbook()->cid . '&j=' . TIME;
+ $a['imageurl'] = 'https://workshop.fluidbook.com/services/facebook_thumbnail?cid=' . $this->getFluidbook()->cid . '&j=' . time();
if ($seoArticle['image']) {
$a['imageurl'] .= '&image=' . $seoArticle['image'];
}
$this->lessVariables['menu-chapters-font-size'] = $this->fluidbookSettings->chaptersFontSize;
foreach ($this->getFluidbook()->chapters as $chapter) {
- if (substr($chapter->page, 0, 1) != '#') {
+ if ($chapter['color'] == '') {
continue;
}
- if ($chapter->color == '') {
- continue;
- }
- $color = trim($chapter->color, '#');
+ $color = trim($chapter['color'], '#');
$lessContents .= '.mview.c_' . $color . '{.menu-color(' . Color::colorToCSS($color) . ');}';
}
$body = '#background, #splash {';
switch ($this->themeSettings->repeat) {
- case wsTheme::REPEAT:
+ case FluidbookTheme::REPEAT:
$body .= 'background-repeat:repeat;';
break;
- case wsTheme::NONE:
+ case FluidbookTheme::NONE:
$body .= 'background-repeat:no-repeat;';
break;
- case wsTheme::RATIO:
+ case FluidbookTheme::RATIO:
$body .= 'background-repeat:no-repeat;';
$body .= 'background-size:cover;';
break;
- case wsTheme::STRETCH:
+ case FluidbookTheme::STRETCH:
$body .= 'background-repeat:no-repeat;';
$body .= 'background-size:100% 100%;';
break;
$body .= 'background-position:';
switch ($this->themeSettings->backgroundVAlign) {
- case wsTheme::TOP:
+ case FluidbookTheme::TOP:
$body .= 'top';
break;
- case wsTheme::MIDDLE:
+ case FluidbookTheme::MIDDLE:
$body .= 'center';
break;
- case wsTheme::BOTTOM:
+ case FluidbookTheme::BOTTOM:
$body .= 'bottom';
break;
}
$body .= ' ';
switch ($this->themeSettings->backgroundHAlign) {
- case wsTheme::LEFT:
+ case FluidbookTheme::LEFT:
$body .= 'left';
break;
- case wsTheme::CENTER:
+ case FluidbookTheme::CENTER:
$body .= 'center';
break;
- case wsTheme::RIGHT:
+ case FluidbookTheme::RIGHT:
$body .= 'right';
break;
}
public function writeXMLArticles()
{
$f = $this->fluidbookSettings->articlesFile;
- if (!$f || !file_exists($this->wdir . '/' . $f) || !is_file($this->wdir . '/' . $f)) {
- return;
- }
$this->lessVariables['articles-title-color'] = '#000000';
$this->lessVariables['articles-font'] = 'Open Sans';
- $f = $this->wdir . '/' . $f;
-
+ if (!$f || !file_exists($this->wdir . '/' . $f) || !is_file($this->wdir . '/' . $f)) {
+ return;
+ }
+ $f = $this->wdir . '/' . $f;
$mapFonts = ['OpenSans' => 'Open Sans'];
$this->addLess('articles');
if ($this->fluidbookSettings->articlesStyle !== 'default') {
--- /dev/null
+const puppeteer = require('puppeteer');
+const commandLineArgs = require('command-line-args');
+const optionDefinitions = [
+ {name: 'url', type: String},
+ {name: 'dest', type: String},
+ {name: 'delay', type: Number, defaultOption: 10},
+ {name: 'scale', type: Number, defaultOption: 1},
+ {name: 'width', type: Number, defaultOption: 1920},
+ {name: 'height', type: Number, defaultOption: 1080}
+];
+
+(async () => {
+ const options = commandLineArgs(optionDefinitions);
+ const browser = await puppeteer.launch({headless: true});
+ const page = await browser.newPage();
+ page.on('console', msg => console.log('PAGE LOG:', msg._text));
+ await page.setViewport({
+ width: options.width / options.scale,
+ height: options.height / options.scale,
+ deviceScaleFactor: options.scale,
+ });
+ await page.setDefaultNavigationTimeout(0);
+ await page.goto(options.url);
+ await new Promise(r => setTimeout(r, 1000 * options.delay));
+ await page.screenshot({path: options.dest, type: 'jpeg', quality: 95});
+ await browser.close();
+})();
\ No newline at end of file