first
This commit is contained in:
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\SmartSlider3\BackupSlider;
|
||||
|
||||
|
||||
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
|
||||
|
||||
class BackupData {
|
||||
|
||||
public $NextendImageHelper_Export, $slider, $slides, $generators = array(), $NextendImageManager_ImageData = array(), $imageTranslation = array(), $visuals = array();
|
||||
|
||||
public function __construct() {
|
||||
$this->NextendImageHelper_Export = ResourceTranslator::exportData();
|
||||
}
|
||||
}
|
@ -0,0 +1,570 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\SmartSlider3\BackupSlider;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\AssetManager;
|
||||
use Nextend\Framework\Asset\Builder\BuilderCss;
|
||||
use Nextend\Framework\Asset\Builder\BuilderJs;
|
||||
use Nextend\Framework\Asset\Predefined;
|
||||
use Nextend\Framework\Data\Data;
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
use Nextend\Framework\Image\ImageManager;
|
||||
use Nextend\Framework\Misc\Zip\Creator;
|
||||
use Nextend\Framework\Model\Section;
|
||||
use Nextend\Framework\PageFlow;
|
||||
use Nextend\Framework\Pattern\MVCHelperTrait;
|
||||
use Nextend\Framework\Platform\Platform;
|
||||
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
|
||||
use Nextend\Framework\Url\Url;
|
||||
use Nextend\Framework\View\Html;
|
||||
use Nextend\SmartSlider3\Application\ApplicationSmartSlider3;
|
||||
use Nextend\SmartSlider3\Application\Model\ModelGenerator;
|
||||
use Nextend\SmartSlider3\Application\Model\ModelSliders;
|
||||
use Nextend\SmartSlider3\Application\Model\ModelSlidersXRef;
|
||||
use Nextend\SmartSlider3\Application\Model\ModelSlides;
|
||||
use Nextend\SmartSlider3\Renderable\Component\ComponentCol;
|
||||
use Nextend\SmartSlider3\Renderable\Component\ComponentContent;
|
||||
use Nextend\SmartSlider3\Renderable\Component\ComponentLayer;
|
||||
use Nextend\SmartSlider3\Renderable\Component\ComponentRow;
|
||||
use Nextend\SmartSlider3\Slider\SliderParams;
|
||||
use Nextend\SmartSlider3\Slider\SliderType\SliderTypeFactory;
|
||||
use Nextend\SmartSlider3\Widget\AbstractWidget;
|
||||
use Nextend\SmartSlider3\Widget\WidgetGroupFactory;
|
||||
use Nextend\SmartSlider3Pro\Renderable\Component\ComponentGroup;
|
||||
|
||||
class ExportSlider {
|
||||
|
||||
use MVCHelperTrait;
|
||||
|
||||
private $uniqueCounter = 1;
|
||||
|
||||
/**
|
||||
* @var BackupData
|
||||
*/
|
||||
private $backup;
|
||||
private $sliderId = 0;
|
||||
|
||||
public $images = array(), $visuals = array();
|
||||
|
||||
private $files, $usedNames = array(), $imageTranslation = array();
|
||||
|
||||
public function __construct($MVCHelper, $sliderId) {
|
||||
|
||||
$this->setMVCHelper($MVCHelper);
|
||||
$this->sliderId = $sliderId;
|
||||
}
|
||||
|
||||
public function create($saveAsFile = false) {
|
||||
$this->backup = new BackupData();
|
||||
$slidersModel = new ModelSliders($this);
|
||||
if ($this->backup->slider = $slidersModel->get($this->sliderId)) {
|
||||
|
||||
$zip = new Creator();
|
||||
|
||||
if (empty($this->backup->slider['type'])) {
|
||||
$this->backup->slider['type'] = 'simple';
|
||||
}
|
||||
self::addImage($this->backup->slider['thumbnail']);
|
||||
|
||||
$this->backup->slider['params'] = new SliderParams($this->backup->slider['id'], $this->backup->slider['type'], $this->backup->slider['params'], true);
|
||||
|
||||
if ($this->backup->slider['type'] == 'group') {
|
||||
$xref = new ModelSlidersXRef($this);
|
||||
|
||||
$sliders = $xref->getSliders($this->backup->slider['id'], 'published');
|
||||
foreach ($sliders as $k => $slider) {
|
||||
$export = new self($this->MVCHelper, $slider['slider_id']);
|
||||
|
||||
$fileName = $export->create(true);
|
||||
|
||||
$zip->addFile(file_get_contents($fileName), 'sliders/' . $k . '.ss3');
|
||||
unlink($fileName);
|
||||
}
|
||||
} else {
|
||||
$slidesModel = new ModelSlides($this);
|
||||
$this->backup->slides = $slidesModel->getAll($this->backup->slider['id']);
|
||||
|
||||
|
||||
$sliderType = SliderTypeFactory::getType($this->backup->slider['type']);
|
||||
$sliderType->export($this, $this->backup->slider);
|
||||
|
||||
/** @var AbstractWidget[] $enabledWidgets */
|
||||
$enabledWidgets = array();
|
||||
|
||||
$widgetGroups = WidgetGroupFactory::getGroups();
|
||||
|
||||
$params = $this->backup->slider['params'];
|
||||
foreach ($widgetGroups as $groupName => $group) {
|
||||
$widgetName = $params->get('widget' . $groupName);
|
||||
if ($widgetName && $widgetName != 'disabled') {
|
||||
$widget = $group->getWidget($widgetName);
|
||||
if ($widget) {
|
||||
$enabledWidgets[$groupName] = $widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($enabledWidgets as $k => $widget) {
|
||||
$params->fillDefault($widget->getDefaults());
|
||||
|
||||
$widget->prepareExport($this, $params);
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($this->backup->slides); $i++) {
|
||||
$slide = $this->backup->slides[$i];
|
||||
self::addImage($slide['thumbnail']);
|
||||
$slide['params'] = new Data($slide['params'], true);
|
||||
|
||||
self::addImage($slide['params']->get('backgroundImage'));
|
||||
self::addImage($slide['params']->get('ligthboxImage'));
|
||||
|
||||
if ($slide['params']->has('link')) {
|
||||
// Compatibility fix for the old SS3 import files
|
||||
self::addLightbox($slide['params']->get('link'));
|
||||
}
|
||||
if ($slide['params']->has('href')) {
|
||||
self::addLightbox($slide['params']->get('href'));
|
||||
}
|
||||
|
||||
$layers = json_decode($slide['slide'], true);
|
||||
|
||||
$this->prepareLayer($layers);
|
||||
|
||||
|
||||
if (!empty($slide['generator_id'])) {
|
||||
$generatorModel = new ModelGenerator($this);
|
||||
$this->backup->generators[] = $generatorModel->get($slide['generator_id']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->images = array_unique($this->images);
|
||||
$this->visuals = array_unique($this->visuals);
|
||||
|
||||
foreach ($this->images as $image) {
|
||||
$this->backup->NextendImageManager_ImageData[$image] = ImageManager::getImageData($image, true);
|
||||
if ($this->backup->NextendImageManager_ImageData[$image]) {
|
||||
self::addImage($this->backup->NextendImageManager_ImageData[$image]['tablet']['image']);
|
||||
self::addImage($this->backup->NextendImageManager_ImageData[$image]['mobile']['image']);
|
||||
} else {
|
||||
unset($this->backup->NextendImageManager_ImageData[$image]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->images = array_unique($this->images);
|
||||
|
||||
$usedNames = array();
|
||||
foreach ($this->images as $image) {
|
||||
$file = ResourceTranslator::toPath($image);
|
||||
if (Filesystem::fileexists($file)) {
|
||||
$fileName = strtolower(basename($file));
|
||||
while (in_array($fileName, $usedNames)) {
|
||||
$fileName = $this->uniqueCounter . $fileName;
|
||||
$this->uniqueCounter++;
|
||||
}
|
||||
$usedNames[] = $fileName;
|
||||
|
||||
$this->backup->imageTranslation[$image] = $fileName;
|
||||
$zip->addFile(file_get_contents($file), 'images/' . $fileName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->visuals as $visual) {
|
||||
$this->backup->visuals[] = Section::getById($visual);
|
||||
}
|
||||
|
||||
$zip->addFile(serialize($this->backup), 'data');
|
||||
|
||||
if (!$saveAsFile) {
|
||||
PageFlow::cleanOutputBuffers();
|
||||
header('Content-disposition: attachment; filename*=UTF-8\'\'' . rawurlencode($this->backup->slider['title'] . '.ss3'));
|
||||
header('Content-type: application/zip');
|
||||
// PHPCS - contains binary zip data, so nothing to escape
|
||||
echo $zip->file(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
PageFlow::exitApplication();
|
||||
} else {
|
||||
$file = $this->sliderId . '-' . preg_replace('/[^a-zA-Z0-9_-]/', '', $this->backup->slider['title']) . '.ss3';
|
||||
$folder = Platform::getPublicDirectory();
|
||||
$folder .= '/export/';
|
||||
if (!Filesystem::existsFolder($folder)) {
|
||||
Filesystem::createFolder($folder);
|
||||
}
|
||||
Filesystem::createFile($folder . $file, $zip->file());
|
||||
|
||||
return $folder . $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $layers
|
||||
*/
|
||||
public function prepareLayer($layers) {
|
||||
foreach ($layers as $layer) {
|
||||
|
||||
if (isset($layer['type'])) {
|
||||
switch ($layer['type']) {
|
||||
case 'content':
|
||||
ComponentContent::prepareExport($this, $layer);
|
||||
break;
|
||||
case 'row':
|
||||
ComponentRow::prepareExport($this, $layer);
|
||||
break;
|
||||
case 'col':
|
||||
ComponentCol::prepareExport($this, $layer);
|
||||
break;
|
||||
case 'group':
|
||||
$this->prepareLayer($layer['layers']);
|
||||
break;
|
||||
default:
|
||||
ComponentLayer::prepareExport($this, $layer);
|
||||
}
|
||||
} else {
|
||||
ComponentLayer::prepareExport($this, $layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function createHTML($isZIP = true) {
|
||||
Platform::setIsAdmin(false); //Some features are disabled on the admin area
|
||||
|
||||
$this->files = array();
|
||||
PageFlow::cleanOutputBuffers();
|
||||
AssetManager::createStack();
|
||||
|
||||
Predefined::frontend(true);
|
||||
|
||||
ob_start();
|
||||
|
||||
|
||||
$applicationTypeFrontend = ApplicationSmartSlider3::getInstance()
|
||||
->getApplicationTypeFrontend();
|
||||
|
||||
$applicationTypeFrontend->process('slider', 'display', false, array(
|
||||
'sliderID' => $this->sliderId,
|
||||
'usage' => 'Export as HTML'
|
||||
));
|
||||
|
||||
$slidersModel = new ModelSliders($this);
|
||||
$slider = $slidersModel->get($this->sliderId);
|
||||
$sliderHTML = ob_get_clean();
|
||||
$headHTML = '';
|
||||
|
||||
$css = AssetManager::getCSS(true);
|
||||
foreach ($css['url'] as $url) {
|
||||
$headHTML .= Html::style($url, true, array(
|
||||
'media' => 'screen, print'
|
||||
)) . "\n";
|
||||
}
|
||||
|
||||
array_unshift($css['files'], ResourceTranslator::toPath('$ss3-frontend$/dist/normalize.min.css'));
|
||||
|
||||
foreach ($css['files'] as $file) {
|
||||
if (file_exists($file)) {
|
||||
$headHTML .= $this->addCSSFile($file);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
if ($css['inline'] != '') {
|
||||
$headHTML .= Html::style($css['inline']) . "\n";
|
||||
}
|
||||
|
||||
$js = AssetManager::getJs(true);
|
||||
|
||||
if ($js['globalInline'] != '') {
|
||||
$headHTML .= Html::script($js['globalInline']) . "\n";
|
||||
}
|
||||
|
||||
foreach ($js['url'] as $url) {
|
||||
$headHTML .= Html::scriptFile($url) . "\n";
|
||||
}
|
||||
foreach ($js['files'] as $file) {
|
||||
$path = 'js/' . basename($file);
|
||||
|
||||
if (file_exists($file)) {
|
||||
$this->files[$path] = file_get_contents($file);
|
||||
} else {
|
||||
}
|
||||
$headHTML .= Html::scriptFile($path) . "\n";
|
||||
}
|
||||
|
||||
if ($js['inline'] != '') {
|
||||
$headHTML .= Html::script($js['inline']) . "\n";
|
||||
}
|
||||
|
||||
$sliderHTML = preg_replace_callback('/(src|srcset)=["|\'](.*?)["|\']/i', array(
|
||||
$this,
|
||||
'replaceHTMLImage'
|
||||
), $sliderHTML);
|
||||
|
||||
$sliderHTML = preg_replace_callback('/url\(\s*([\'"]|('))?(\S*\.(?:jpe?g|gif|png))([\'"]|('))?\s*\)[^;}]*?/i', array(
|
||||
$this,
|
||||
'replaceHTMLBGImage'
|
||||
), $sliderHTML);
|
||||
|
||||
$sliderHTML = preg_replace_callback('/(data-href)=["|\'](.*?)["|\']/i', array(
|
||||
$this,
|
||||
'replaceHTMLImage'
|
||||
), $sliderHTML);
|
||||
|
||||
$sliderHTML = preg_replace_callback('/(srcset)=["|\'](.*?)["|\']/i', array(
|
||||
$this,
|
||||
'replaceHTMLRetinaImage'
|
||||
), $sliderHTML);
|
||||
|
||||
$sliderHTML = preg_replace_callback('/(data-n2-lightbox-urls)=["|\'](.*?)["|\']/i', array(
|
||||
$this,
|
||||
'replaceLightboxImages'
|
||||
), $sliderHTML);
|
||||
|
||||
$sliderHTML = preg_replace_callback('/(data-n2-lightbox)=["|\'](.*?)["|\']/i', array(
|
||||
$this,
|
||||
'replaceHTMLImageHrefLightbox'
|
||||
), $sliderHTML);
|
||||
|
||||
$headHTML = preg_replace_callback('/"([^"]*?\.(jpg|png|gif|jpeg|webp|svg|mp4))"/i', array(
|
||||
$this,
|
||||
'replaceJSON'
|
||||
), $headHTML);
|
||||
|
||||
$headHTML = preg_replace_callback('/(--n2bgimage:URL\(")(.*?)("\);)/i', array(
|
||||
$this,
|
||||
'replaceCssBGImage'
|
||||
), $headHTML);
|
||||
|
||||
$this->files['index.html'] = "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge, chrome=1\">\n<title>" . $slider['title'] . "</title>\n" . $headHTML . "</head>\n<body>\n" . $sliderHTML . "</body>\n</html>";
|
||||
|
||||
if (!$isZIP) {
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
$zip = new Creator();
|
||||
foreach ($this->files as $path => $content) {
|
||||
$zip->addFile($content, $path);
|
||||
}
|
||||
PageFlow::cleanOutputBuffers();
|
||||
header('Content-disposition: attachment; filename*=UTF-8\'\'' . rawurlencode($slider['title'] . '.zip'));
|
||||
header('Content-type: application/zip');
|
||||
// PHPCS - contains binary zip data, so nothing to escape
|
||||
echo $zip->file(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
|
||||
Platform::setIsAdmin(false); // Restore admin area
|
||||
|
||||
PageFlow::exitApplication();
|
||||
}
|
||||
|
||||
private static function addProtocol($image) {
|
||||
if (substr($image, 0, 2) == '//') {
|
||||
return Url::addScheme($image);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
public function replaceHTMLImage($found) {
|
||||
$path = Filesystem::absoluteURLToPath(self::addProtocol($found[2]));
|
||||
|
||||
if (substr($path, 0, 5) === "data:") {
|
||||
return $found[0];
|
||||
}
|
||||
|
||||
if (strpos($path, Filesystem::getBasePath()) !== 0) {
|
||||
$imageUrl = Url::relativetoabsolute($path);
|
||||
$path = Filesystem::absoluteURLToPath($imageUrl);
|
||||
}
|
||||
|
||||
if ($path == $found[2]) {
|
||||
return $found[0];
|
||||
}
|
||||
if (Filesystem::fileexists($path)) {
|
||||
if (!isset($this->imageTranslation[$path])) {
|
||||
$fileName = strtolower(basename($path));
|
||||
while (in_array($fileName, $this->usedNames)) {
|
||||
$fileName = $this->uniqueCounter . $fileName;
|
||||
$this->uniqueCounter++;
|
||||
}
|
||||
$this->usedNames[] = $fileName;
|
||||
$this->files['images/' . $fileName] = file_get_contents($path);
|
||||
$this->imageTranslation[$path] = $fileName;
|
||||
} else {
|
||||
$fileName = $this->imageTranslation[$path];
|
||||
}
|
||||
|
||||
return str_replace($found[2], 'images/' . $fileName, $found[0]);
|
||||
} else {
|
||||
return $found[0];
|
||||
}
|
||||
}
|
||||
|
||||
public function replaceHTMLImageHrefLightbox($found) {
|
||||
return $this->replaceHTMLImage($found);
|
||||
}
|
||||
|
||||
public function replaceLightboxImages($found) {
|
||||
$images = explode(',', $found[2]);
|
||||
foreach ($images as $k => $image) {
|
||||
$images[$k] = $this->replaceHTMLImage(array(
|
||||
$image,
|
||||
'',
|
||||
$image
|
||||
));
|
||||
}
|
||||
|
||||
return 'data-n2-lightbox-urls="' . implode(',', $images) . '"';
|
||||
}
|
||||
|
||||
public function replaceHTMLRetinaImage($found) {
|
||||
$srcset = $found[0];
|
||||
|
||||
$replacedImages = array();
|
||||
$explodedSrcs = explode(',', $found[2]);
|
||||
foreach ($explodedSrcs as $explodedSrc) {
|
||||
$exploded = explode(' ', $explodedSrc);
|
||||
$replacedImage = $this->replaceHTMLImage(array(
|
||||
$exploded[0],
|
||||
'',
|
||||
$exploded[0]
|
||||
));
|
||||
$replacedImages[] = $replacedImage . (count($exploded) > 1 ? ' ' . $exploded[1] : '');
|
||||
|
||||
}
|
||||
if (!empty($replacedImages)) {
|
||||
$srcset = $found[1] . '="' . implode(',', $replacedImages) . '"';
|
||||
}
|
||||
|
||||
return $srcset;
|
||||
}
|
||||
|
||||
public function replaceHTMLBGImage($found) {
|
||||
$path = $this->replaceHTMLImage(array(
|
||||
$found[3],
|
||||
'',
|
||||
$found[3]
|
||||
));
|
||||
|
||||
return str_replace($found[3], $path, $found[0]);
|
||||
}
|
||||
|
||||
public function replaceCssBGImage($found) {
|
||||
if (substr($found[2], 0, 9) !== 'http:\/\/' && substr($found[2], 0, 10) !== 'https:\/\/' && substr($found[2], 0, 5) !== 'data:') {
|
||||
return $found[1] . '..\/' . $found[2] . $found[3];
|
||||
}
|
||||
|
||||
return $found[0];
|
||||
}
|
||||
|
||||
public function replaceJSON($found) {
|
||||
$image = ResourceTranslator::toUrl(str_replace('\\/', '/', $found[1]));
|
||||
$path = $this->replaceHTMLImage(array(
|
||||
$image,
|
||||
'',
|
||||
$image
|
||||
));
|
||||
|
||||
return str_replace($found[1], str_replace('/', '\\/', $path), $found[0]);
|
||||
}
|
||||
|
||||
public function addImage($image) {
|
||||
if (!empty($image)) {
|
||||
$this->images[] = $image;
|
||||
}
|
||||
}
|
||||
|
||||
public function addLightbox($url) {
|
||||
preg_match('/^([a-zA-Z]+)\[(.*)]/', $url, $matches);
|
||||
if (!empty($matches)) {
|
||||
if ($matches[1] == 'lightbox') {
|
||||
$data = json_decode($matches[2]);
|
||||
if ($data) {
|
||||
foreach ($data->urls as $image) {
|
||||
$this->addImage($image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addVisual($id) {
|
||||
if (is_numeric($id) && $id > 10000) {
|
||||
$this->visuals[] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
private $basePath;
|
||||
private $baseUrl;
|
||||
|
||||
private function addCSSFile($file) {
|
||||
|
||||
return $this->addCSSFileWithContent($file, file_get_contents($file));
|
||||
}
|
||||
|
||||
private function addCSSFileWithContent($file, $fileContent) {
|
||||
$path = 'css/' . basename($file);
|
||||
|
||||
$this->basePath = dirname($file);
|
||||
$this->baseUrl = Filesystem::pathToAbsoluteURL($this->basePath);
|
||||
|
||||
$fileContent = preg_replace_callback('#url\([\'"]?([^"\'\)]+)[\'"]?\)#', array(
|
||||
$this,
|
||||
'replaceCSSImage'
|
||||
), $fileContent);
|
||||
|
||||
$this->files[$path] = $fileContent;
|
||||
|
||||
return Html::style($path, true, array(
|
||||
'media' => 'screen, print'
|
||||
)) . "\n";
|
||||
}
|
||||
|
||||
public function replaceCSSImage($matches) {
|
||||
if (substr($matches[1], 0, 5) == 'data:') return $matches[0];
|
||||
if (substr($matches[1], 0, 4) == 'http') {
|
||||
$exploded = explode('?', $matches[1]);
|
||||
|
||||
$path = ResourceTranslator::toPath(ResourceTranslator::urlToResource($exploded[0]));
|
||||
if (strpos($path, $this->basePath) === 0) {
|
||||
$exploded = explode('?', $matches[1]);
|
||||
|
||||
return str_replace($matches[1], 'assets/' . $this->addFile($path) . '?' . $exploded[1], $matches[0]);
|
||||
} else {
|
||||
return $matches[0];
|
||||
}
|
||||
}
|
||||
if (substr($matches[1], 0, 2) == '//') return $matches[0];
|
||||
|
||||
$exploded = explode('?', $matches[1]);
|
||||
|
||||
$path = realpath($this->basePath . '/' . $exploded[0]);
|
||||
if ($path === false) {
|
||||
return 'url(' . str_replace(array(
|
||||
'http://',
|
||||
'https://'
|
||||
), '//', $this->baseUrl) . '/' . $matches[1] . ')';
|
||||
}
|
||||
|
||||
return str_replace($matches[1], 'assets/' . $this->addFile($path), $matches[0]);
|
||||
}
|
||||
|
||||
protected function addFile($path) {
|
||||
$path = Filesystem::convertToRealDirectorySeparator($path);
|
||||
|
||||
if (!isset($this->imageTranslation[$path])) {
|
||||
$fileName = strtolower(basename($path));
|
||||
while (in_array($fileName, $this->usedNames)) {
|
||||
$fileName = $this->uniqueCounter . $fileName;
|
||||
$this->uniqueCounter++;
|
||||
}
|
||||
$this->usedNames[] = $fileName;
|
||||
$this->files['css/assets/' . $fileName] = file_get_contents($path);
|
||||
$this->imageTranslation[$path] = $fileName;
|
||||
} else {
|
||||
$fileName = $this->imageTranslation[$path];
|
||||
}
|
||||
|
||||
return $fileName;
|
||||
}
|
||||
}
|
@ -0,0 +1,310 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\SmartSlider3\BackupSlider;
|
||||
|
||||
|
||||
use Nextend\Framework\Cache\StoreImage;
|
||||
use Nextend\Framework\Data\Data;
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
use Nextend\Framework\Image\ImageManager;
|
||||
use Nextend\Framework\Misc\Zip\Reader;
|
||||
use Nextend\Framework\Model\StorageSectionManager;
|
||||
use Nextend\Framework\Notification\Notification;
|
||||
use Nextend\Framework\Pattern\MVCHelperTrait;
|
||||
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
|
||||
use Nextend\Framework\Url\Url;
|
||||
use Nextend\SmartSlider3\Application\Model\ModelGenerator;
|
||||
use Nextend\SmartSlider3\Application\Model\ModelSliders;
|
||||
use Nextend\SmartSlider3\Application\Model\ModelSlides;
|
||||
use Nextend\SmartSlider3\Renderable\Component\ComponentCol;
|
||||
use Nextend\SmartSlider3\Renderable\Component\ComponentContent;
|
||||
use Nextend\SmartSlider3\Renderable\Component\ComponentLayer;
|
||||
use Nextend\SmartSlider3\Renderable\Component\ComponentRow;
|
||||
use Nextend\SmartSlider3\Slider\SliderType\SliderTypeFactory;
|
||||
use Nextend\SmartSlider3\Widget\WidgetGroupFactory;
|
||||
|
||||
class ImportSlider {
|
||||
|
||||
use MVCHelperTrait;
|
||||
|
||||
/**
|
||||
* @var BackupData
|
||||
*/
|
||||
private $backup;
|
||||
private $imageTranslation = array();
|
||||
private $sectionTranslation = array();
|
||||
|
||||
private $sliderId = 0;
|
||||
|
||||
private $replace = false;
|
||||
|
||||
public function __construct($MVCHelper) {
|
||||
|
||||
$this->setMVCHelper($MVCHelper);
|
||||
}
|
||||
|
||||
public function enableReplace() {
|
||||
$this->replace = true;
|
||||
}
|
||||
|
||||
public function import($filePathOrData, $groupID = 0, $imageImportMode = 'clone', $linkedVisuals = 1, $isFilePath = true) {
|
||||
if (!$isFilePath) {
|
||||
$tmp = Filesystem::tempnam();
|
||||
file_put_contents($tmp, $filePathOrData);
|
||||
$filePathOrData = $tmp;
|
||||
}
|
||||
$importData = Reader::read($filePathOrData);
|
||||
if (!$isFilePath) {
|
||||
@unlink($tmp);
|
||||
}
|
||||
if (!is_array($importData)) {
|
||||
Notification::error(n2_('The importing failed at the unzipping part.'));
|
||||
|
||||
return false;
|
||||
} else if (!isset($importData['data'])) {
|
||||
if (array_key_exists("slider.ss2", $importData)) {
|
||||
Notification::error(n2_('You can\'t import sliders from Smart Slider 2.'));
|
||||
} else if (empty($importData)) {
|
||||
Notification::error(n2_('Export file corrupted! Slider data is missing.'));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$parser = new Serialize\Parser;
|
||||
if (!$parser->isValidData($importData['data'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->backup = unserialize($importData['data']);
|
||||
|
||||
if (!empty($this->backup->slider['type']) && $this->backup->slider['type'] == 'group') {
|
||||
// Groups can not be imported into groups
|
||||
$groupID = 0;
|
||||
}
|
||||
|
||||
$this->sectionTranslation = array();
|
||||
$this->importVisuals($this->backup->visuals, $linkedVisuals);
|
||||
|
||||
|
||||
$sliderModel = new ModelSliders($this);
|
||||
|
||||
|
||||
if ($this->replace) {
|
||||
$this->sliderId = $sliderModel->replace($this->backup->slider, $groupID);
|
||||
} else {
|
||||
$this->sliderId = $sliderModel->import($this->backup->slider, $groupID);
|
||||
}
|
||||
|
||||
if (!$this->sliderId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($imageImportMode) {
|
||||
case 'clone':
|
||||
$images = isset($importData['images']) ? $importData['images'] : array();
|
||||
$imageStore = new StoreImage('slider' . $this->sliderId, true);
|
||||
foreach ($images as $file => $content) {
|
||||
$localImage = $imageStore->makeCache($file, $content);
|
||||
if ($localImage) {
|
||||
$this->imageTranslation[$file] = ResourceTranslator::urlToResource(Url::pathToUri($localImage));
|
||||
} else {
|
||||
$this->imageTranslation[$file] = $file;
|
||||
}
|
||||
if (!$this->imageTranslation[$file]) {
|
||||
$this->imageTranslation[$file] = array_search($file, $this->backup->imageTranslation);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'update':
|
||||
$keys = array_keys($this->backup->NextendImageHelper_Export);
|
||||
$values = array_values($this->backup->NextendImageHelper_Export);
|
||||
foreach ($this->backup->imageTranslation as $image => $value) {
|
||||
$this->imageTranslation[$value] = str_replace($keys, $values, $image);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!empty($this->backup->slider['thumbnail'])) {
|
||||
$sliderModel->setThumbnail($this->sliderId, $this->fixImage($this->backup->slider['thumbnail']));
|
||||
}
|
||||
|
||||
foreach ($this->backup->NextendImageManager_ImageData as $image => $data) {
|
||||
$data['tablet']['image'] = $this->fixImage($data['tablet']['image']);
|
||||
$data['mobile']['image'] = $this->fixImage($data['mobile']['image']);
|
||||
$fixedImage = $this->fixImage($image);
|
||||
if (!ImageManager::hasImageData($fixedImage)) {
|
||||
ImageManager::addImageData($this->fixImage($image), $data);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->backup->slider['type'])) {
|
||||
$this->backup->slider['type'] = 'simple';
|
||||
}
|
||||
|
||||
|
||||
if ($this->backup->slider['type'] == 'group') {
|
||||
/**
|
||||
* Import the sliders for the group!
|
||||
*/
|
||||
foreach ($importData['sliders'] as $k => $slider) {
|
||||
$import = new self($this);
|
||||
if ($this->replace) {
|
||||
$import->enableReplace();
|
||||
}
|
||||
$import->import($slider, $this->sliderId, $imageImportMode, $linkedVisuals, false);
|
||||
}
|
||||
} else {
|
||||
|
||||
unset($importData);
|
||||
|
||||
$sliderType = SliderTypeFactory::getType($this->backup->slider['type']);
|
||||
$sliderType->import($this, $this->backup->slider);
|
||||
|
||||
|
||||
$enabledWidgets = array();
|
||||
$widgetGroups = WidgetGroupFactory::getGroups();
|
||||
|
||||
$params = $this->backup->slider['params'];
|
||||
foreach ($widgetGroups as $groupName => $group) {
|
||||
$widgetName = $params->get('widget' . $groupName);
|
||||
if ($widgetName && $widgetName != 'disabled') {
|
||||
$widget = $group->getWidget($widgetName);
|
||||
if ($widget) {
|
||||
$enabledWidgets[$groupName] = $widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($enabledWidgets as $k => $widget) {
|
||||
$params->fillDefault($widget->getDefaults());
|
||||
|
||||
$widget->prepareImport($this, $params);
|
||||
}
|
||||
|
||||
|
||||
$sliderModel->importUpdate($this->sliderId, $params);
|
||||
|
||||
$generatorTranslation = array();
|
||||
$generatorModel = new ModelGenerator($this);
|
||||
foreach ($this->backup->generators as $generator) {
|
||||
$generatorTranslation[$generator['id']] = $generatorModel->import($generator);
|
||||
}
|
||||
|
||||
|
||||
$slidesModel = new ModelSlides($this);
|
||||
for ($i = 0; $i < count($this->backup->slides); $i++) {
|
||||
$slide = $this->backup->slides[$i];
|
||||
$slide['params'] = new Data($slide['params'], true);
|
||||
$slide['thumbnail'] = $this->fixImage($slide['thumbnail']);
|
||||
$slide['params']->set('backgroundImage', $this->fixImage($slide['params']->get('backgroundImage')));
|
||||
$slide['params']->set('ligthboxImage', $this->fixImage($slide['params']->get('ligthboxImage')));
|
||||
|
||||
if ($slide['params']->has('link')) {
|
||||
// Compatibility fix for the old SS3 import files
|
||||
$slide['params']->set('link', $this->fixLightbox($slide['params']->get('link')));
|
||||
}
|
||||
if ($slide['params']->has('href')) {
|
||||
$slide['params']->set('href', $this->fixLightbox($slide['params']->get('href')));
|
||||
}
|
||||
|
||||
$layers = json_decode($slide['slide'], true);
|
||||
|
||||
$this->prepareLayers($layers);
|
||||
|
||||
$slide['slide'] = $layers;
|
||||
|
||||
if (isset($generatorTranslation[$slide['generator_id']])) {
|
||||
$slide['generator_id'] = $generatorTranslation[$slide['generator_id']];
|
||||
}
|
||||
$slidesModel->import($slide, $this->sliderId);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->sliderId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $layers
|
||||
*/
|
||||
public function prepareLayers(&$layers) {
|
||||
for ($i = 0; $i < count($layers); $i++) {
|
||||
|
||||
if (isset($layers[$i]['type'])) {
|
||||
switch ($layers[$i]['type']) {
|
||||
case 'content':
|
||||
ComponentContent::prepareImport($this, $layers[$i]);
|
||||
break;
|
||||
case 'row':
|
||||
ComponentRow::prepareImport($this, $layers[$i]);
|
||||
break;
|
||||
case 'col':
|
||||
ComponentCol::prepareImport($this, $layers[$i]);
|
||||
break;
|
||||
case 'group':
|
||||
$this->prepareLayers($layers[$i]['layers']);
|
||||
break;
|
||||
default:
|
||||
ComponentLayer::prepareImport($this, $layers[$i]);
|
||||
}
|
||||
} else {
|
||||
ComponentLayer::prepareImport($this, $layers[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function fixImage($image) {
|
||||
if (isset($this->backup->imageTranslation[$image]) && isset($this->imageTranslation[$this->backup->imageTranslation[$image]])) {
|
||||
return $this->imageTranslation[$this->backup->imageTranslation[$image]];
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
public function fixSection($idOrRaw) {
|
||||
if (isset($this->sectionTranslation[$idOrRaw])) {
|
||||
return $this->sectionTranslation[$idOrRaw];
|
||||
}
|
||||
|
||||
return $idOrRaw;
|
||||
}
|
||||
|
||||
public function fixLightbox($url) {
|
||||
preg_match('/^([a-zA-Z]+)\[(.*)]/', $url, $matches);
|
||||
if (!empty($matches) && $matches[1] == 'lightbox') {
|
||||
$data = json_decode($matches[2]);
|
||||
if ($data) {
|
||||
$newImages = array();
|
||||
foreach ($data->urls as $image) {
|
||||
$newImages[] = $this->fixImage($image);
|
||||
}
|
||||
$data->urls = $newImages;
|
||||
$url = 'lightbox[' . json_encode($data) . ']';
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
private function importVisuals($records, $linkedVisuals) {
|
||||
if (count($records)) {
|
||||
if (!$linkedVisuals) {
|
||||
foreach ($records as $record) {
|
||||
$this->sectionTranslation[$record['id']] = $record['value'];
|
||||
}
|
||||
} else {
|
||||
$sets = array();
|
||||
foreach ($records as $record) {
|
||||
$storage = StorageSectionManager::getStorage($record['application']);
|
||||
if (!isset($sets[$record['application'] . '_' . $record['section']])) {
|
||||
$sets[$record['application'] . '_' . $record['section']] = $storage->add($record['section'] . 'set', '', $this->backup->slider['title']);
|
||||
}
|
||||
$this->sectionTranslation[$record['id']] = $storage->add($record['section'], $sets[$record['application'] . '_' . $record['section']], $record['value']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SerializeParser
|
||||
*
|
||||
* @copyright Jason Judge
|
||||
*
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
* @link https://github.com/academe/SerializeParser/blob/master/src/Parser.php
|
||||
*
|
||||
* The original code was modified by Nextendweb. We stripped the not relevant parts.
|
||||
*/
|
||||
|
||||
namespace Nextend\SmartSlider3\BackupSlider\Serialize;
|
||||
|
||||
use Nextend\Framework\Notification\Notification;
|
||||
|
||||
class Parser {
|
||||
|
||||
protected $allowedClassNames = [
|
||||
'Nextend\SmartSlider3\BackupSlider\BackupData',
|
||||
'Nextend\SmartSlider3\Slider\SliderParams'
|
||||
];
|
||||
|
||||
/**
|
||||
* This is the recursive parser.
|
||||
*/
|
||||
protected function doParse(StringReader $string) {
|
||||
|
||||
// May be : or ; as a terminator, depending on what the data
|
||||
// type is.
|
||||
|
||||
$type = substr($string->read(2), 0, 1);
|
||||
|
||||
switch ($type) {
|
||||
case 'a':
|
||||
// Associative array: a:length:{[index][value]...}
|
||||
$count = (int)$string->readUntil(':');
|
||||
|
||||
// Eat the opening "{" of the array.
|
||||
$string->read(1);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$this->doParse($string);//array key
|
||||
$this->doParse($string);//array value
|
||||
}
|
||||
|
||||
// Eat "}" terminating the array.
|
||||
$string->read(1);
|
||||
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
// Object: O:length:"class":length:{[property][value]...}
|
||||
$len = (int)$string->readUntil(':');
|
||||
|
||||
// +2 for quotes
|
||||
$class = $string->read(2 + $len);
|
||||
|
||||
if (!in_array($class, $this->allowedClassNames)) {
|
||||
Notification::error(sprintf(n2_('The importing failed as the slider export contained an invalid class name: %1$s'), '<br>' . $class));
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Eat the separator
|
||||
$string->read(1);
|
||||
|
||||
|
||||
// Read the number of properties.
|
||||
$len = (int)$string->readUntil(':');
|
||||
|
||||
// Eat "{" holding the properties.
|
||||
$string->read(1);
|
||||
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$this->doParse($string);//prop key
|
||||
$this->doParse($string);//prop value
|
||||
}
|
||||
|
||||
// Eat "}" terminating properties.
|
||||
$string->read(1);
|
||||
|
||||
break;
|
||||
|
||||
case 's':
|
||||
$len = (int)$string->readUntil(':');
|
||||
$string->read($len + 2);
|
||||
|
||||
// Eat the separator
|
||||
$string->read(1);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
$string->readUntil(';');
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
$string->readUntil(';');
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
// Boolean is 0 or 1
|
||||
$string->read(2);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
break;
|
||||
|
||||
default:
|
||||
Notification::error(sprintf(n2_('The importing failed as we are not able to unserialize the type: "%s"'), '<br>' . $type));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $string
|
||||
*
|
||||
*
|
||||
* Checks if the $string contains any Class names which are not allowed by us!
|
||||
* This is the initial entry point into the recursive parser.
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function isValidData($string) {
|
||||
return $this->doParse(new StringReader($string));
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SerializeParser
|
||||
*
|
||||
* @copyright Jason Judge
|
||||
*
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*
|
||||
* @link https://github.com/academe/SerializeParser/blob/master/src/StringReader.php
|
||||
*/
|
||||
|
||||
namespace Nextend\SmartSlider3\BackupSlider\Serialize;
|
||||
|
||||
/**
|
||||
* Given a string, this class will read through the string using
|
||||
* one of a number of terminating rules:
|
||||
* - One character.
|
||||
* - A specified number of characters.
|
||||
* - Until a matching character is found.
|
||||
*/
|
||||
|
||||
class StringReader
|
||||
{
|
||||
protected $pos = 0;
|
||||
protected $max = 0;
|
||||
protected $string = [];
|
||||
|
||||
public function __construct($string)
|
||||
{
|
||||
// Split the string up into an array of UTF-8 characters.
|
||||
// As an array we can read through it one character at a time.
|
||||
|
||||
//$this->string = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
|
||||
//$this->max = count($this->string) - 1;
|
||||
$this->string = $string;
|
||||
$this->max = strlen($this->string) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next character from the supplied string.
|
||||
* Return null when we have run out of characters.
|
||||
*/
|
||||
public function readOne()
|
||||
{
|
||||
if ($this->pos <= $this->max) {
|
||||
$value = $this->string[$this->pos];
|
||||
$this->pos += 1;
|
||||
} else {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters until we reach the given character $char.
|
||||
* By default, discard that final matching character and return
|
||||
* the rest.
|
||||
*/
|
||||
public function readUntil($char, $discard_char = true)
|
||||
{
|
||||
$value = '';
|
||||
|
||||
while(null !== ($one = $this->readOne())) {
|
||||
if ($one !== $char || !$discard_char) {
|
||||
$value .= $one;
|
||||
}
|
||||
|
||||
if ($one === $char) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read $count characters, or until we have reached the end,
|
||||
* whichever comes first.
|
||||
* By default, remove enclosing double-quotes from the result.
|
||||
*/
|
||||
public function read($count, $strip_quotes = true)
|
||||
{
|
||||
$value = '';
|
||||
|
||||
while($count > 0 && null != ($one = $this->readOne())) {
|
||||
$value .= $one;
|
||||
$count -= 1;
|
||||
}
|
||||
|
||||
return $strip_quotes ? $this->stripQuotes($value) : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a single set of double-quotes from around a string.
|
||||
* abc => abc
|
||||
* "abc" => abc
|
||||
* ""abc"" => "abc"
|
||||
*
|
||||
* @param string string
|
||||
* @returns string
|
||||
*/
|
||||
public function stripQuotes($string)
|
||||
{
|
||||
// Only remove exactly one quote from the start and the end,
|
||||
// and then only if there is one at each end.
|
||||
|
||||
if (strlen($string) < 2 || substr($string, 0, 1) !== '"' || substr($string, -1, 1) !== '"') {
|
||||
// Too short, or does not start or end with a quote.
|
||||
return $string;
|
||||
}
|
||||
|
||||
// Return the middle of the string, from the second character to the second-but-last.
|
||||
return substr($string, 1, -1);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user