first
This commit is contained in:
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset;
|
||||
|
||||
use Nextend\Framework\Misc\Base64;
|
||||
|
||||
class AbstractAsset {
|
||||
|
||||
/**
|
||||
* @var AbstractCache
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
protected $files = array();
|
||||
protected $urls = array();
|
||||
protected $codes = array();
|
||||
protected $globalInline = array();
|
||||
protected $firstCodes = array();
|
||||
protected $inline = array();
|
||||
protected $staticGroupPreload = array();
|
||||
protected $staticGroup = array();
|
||||
|
||||
protected $groups = array();
|
||||
|
||||
public function addFile($pathToFile, $group) {
|
||||
$this->addGroup($group);
|
||||
$this->files[$group][] = $pathToFile;
|
||||
}
|
||||
|
||||
public function addFiles($path, $files, $group) {
|
||||
$this->addGroup($group);
|
||||
foreach ($files as $file) {
|
||||
$this->files[$group][] = $path . DIRECTORY_SEPARATOR . $file;
|
||||
}
|
||||
}
|
||||
|
||||
public function addStaticGroupPreload($file, $group) {
|
||||
$this->staticGroupPreload[$group] = $file;
|
||||
}
|
||||
|
||||
public function addStaticGroup($file, $group) {
|
||||
$this->staticGroup[$group] = $file;
|
||||
}
|
||||
|
||||
private function addGroup($group) {
|
||||
if (!isset($this->files[$group])) {
|
||||
$this->files[$group] = array();
|
||||
}
|
||||
}
|
||||
|
||||
public function addCode($code, $group, $unshift = false) {
|
||||
if (!isset($this->codes[$group])) {
|
||||
$this->codes[$group] = array();
|
||||
}
|
||||
if (!$unshift) {
|
||||
$this->codes[$group][] = $code;
|
||||
} else {
|
||||
array_unshift($this->codes[$group], $code);
|
||||
}
|
||||
}
|
||||
|
||||
public function addUrl($url) {
|
||||
$this->urls[] = $url;
|
||||
}
|
||||
|
||||
public function addFirstCode($code, $unshift = false) {
|
||||
if ($unshift) {
|
||||
array_unshift($this->firstCodes, $code);
|
||||
} else {
|
||||
$this->firstCodes[] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
public function addInline($code, $name = null, $unshift = false) {
|
||||
if ($unshift) {
|
||||
array_unshift($this->inline, $code);
|
||||
|
||||
} else {
|
||||
if ($name) {
|
||||
$this->inline[$name] = $code;
|
||||
} else {
|
||||
$this->inline[] = $code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addGlobalInline($code, $unshift = false) {
|
||||
if ($unshift) {
|
||||
array_unshift($this->globalInline, $code);
|
||||
} else {
|
||||
$this->globalInline[] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
public function loadedFilesEncoded() {
|
||||
return Base64::encode(json_encode(call_user_func_array('array_merge', $this->files) + $this->urls));
|
||||
}
|
||||
|
||||
protected function uniqueFiles() {
|
||||
foreach ($this->files as $group => &$files) {
|
||||
$this->files[$group] = array_values(array_unique($files));
|
||||
}
|
||||
$this->initGroups();
|
||||
}
|
||||
|
||||
public function removeFiles($notNeededFiles) {
|
||||
foreach ($this->files as $group => &$files) {
|
||||
$this->files[$group] = array_diff($files, $notNeededFiles);
|
||||
}
|
||||
}
|
||||
|
||||
public function initGroups() {
|
||||
$this->groups = array_unique(array_merge(array_keys($this->files), array_keys($this->codes)));
|
||||
|
||||
$skeleton = array_map(array(
|
||||
AbstractAsset::class,
|
||||
'emptyArray'
|
||||
), array_flip($this->groups));
|
||||
|
||||
$this->files += $skeleton;
|
||||
$this->codes += $skeleton;
|
||||
}
|
||||
|
||||
private static function emptyArray() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getFiles() {
|
||||
$this->uniqueFiles();
|
||||
|
||||
$files = array();
|
||||
|
||||
if (AssetManager::$cacheAll) {
|
||||
foreach ($this->groups as $group) {
|
||||
if (isset($this->staticGroup[$group])) continue;
|
||||
$files[$group] = $this->cache->getAssetFile($group, $this->files[$group], $this->codes[$group]);
|
||||
}
|
||||
} else {
|
||||
foreach ($this->groups as $group) {
|
||||
if (isset($this->staticGroup[$group])) continue;
|
||||
if (in_array($group, AssetManager::$cachedGroups)) {
|
||||
$files[$group] = $this->cache->getAssetFile($group, $this->files[$group], $this->codes[$group]);
|
||||
} else {
|
||||
foreach ($this->files[$group] as $file) {
|
||||
$files[] = $file;
|
||||
}
|
||||
foreach ($this->codes[$group] as $code) {
|
||||
array_unshift($this->inline, $code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($files['n2'])) {
|
||||
return array('n2' => $files['n2']) + $this->staticGroup + $files;
|
||||
}
|
||||
|
||||
return array_merge($files, $this->staticGroup);
|
||||
}
|
||||
|
||||
public function serialize() {
|
||||
return array(
|
||||
'staticGroupPreload' => $this->staticGroupPreload,
|
||||
'staticGroup' => $this->staticGroup,
|
||||
'files' => $this->files,
|
||||
'urls' => $this->urls,
|
||||
'codes' => $this->codes,
|
||||
'firstCodes' => $this->firstCodes,
|
||||
'inline' => $this->inline,
|
||||
'globalInline' => $this->globalInline
|
||||
);
|
||||
}
|
||||
|
||||
public function unSerialize($array) {
|
||||
$this->staticGroupPreload = array_merge($this->staticGroupPreload, $array['staticGroupPreload']);
|
||||
$this->staticGroup = array_merge($this->staticGroup, $array['staticGroup']);
|
||||
|
||||
foreach ($array['files'] as $group => $files) {
|
||||
if (!isset($this->files[$group])) {
|
||||
$this->files[$group] = $files;
|
||||
} else {
|
||||
$this->files[$group] = array_merge($this->files[$group], $files);
|
||||
}
|
||||
}
|
||||
$this->urls = array_merge($this->urls, $array['urls']);
|
||||
|
||||
foreach ($array['codes'] as $group => $codes) {
|
||||
if (!isset($this->codes[$group])) {
|
||||
$this->codes[$group] = $codes;
|
||||
} else {
|
||||
$this->codes[$group] = array_merge($this->codes[$group], $codes);
|
||||
}
|
||||
}
|
||||
|
||||
$this->firstCodes = array_merge($this->firstCodes, $array['firstCodes']);
|
||||
$this->inline = array_merge($this->inline, $array['inline']);
|
||||
$this->globalInline = array_merge($this->globalInline, $array['globalInline']);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset;
|
||||
|
||||
use Nextend\Framework\Cache\Manifest;
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
|
||||
abstract class AbstractCache {
|
||||
|
||||
public $outputFileType;
|
||||
|
||||
protected $group, $files, $codes;
|
||||
|
||||
public function getAssetFile($group, &$files = array(), &$codes = array()) {
|
||||
$this->group = $group;
|
||||
$this->files = $files;
|
||||
$this->codes = $codes;
|
||||
|
||||
$cache = new Manifest($group, true, true);
|
||||
$hash = $this->getHash();
|
||||
|
||||
return $cache->makeCache($group . "." . $this->outputFileType, $hash, array(
|
||||
$this,
|
||||
'getCachedContent'
|
||||
));
|
||||
}
|
||||
|
||||
protected function getHash() {
|
||||
$hash = '';
|
||||
foreach ($this->files as $file) {
|
||||
$hash .= $this->makeFileHash($file);
|
||||
}
|
||||
foreach ($this->codes as $code) {
|
||||
$hash .= $code;
|
||||
}
|
||||
|
||||
return md5($hash);
|
||||
}
|
||||
|
||||
protected function getCacheFileName() {
|
||||
$hash = '';
|
||||
foreach ($this->files as $file) {
|
||||
$hash .= $this->makeFileHash($file);
|
||||
}
|
||||
foreach ($this->codes as $code) {
|
||||
$hash .= $code;
|
||||
}
|
||||
|
||||
return md5($hash) . "." . $this->outputFileType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Manifest $cache
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCachedContent($cache) {
|
||||
$fileContents = '';
|
||||
foreach ($this->files as $file) {
|
||||
$fileContents .= $this->parseFile($cache, Filesystem::readFile($file), $file) . "\n";
|
||||
}
|
||||
|
||||
foreach ($this->codes as $code) {
|
||||
$fileContents .= $code . "\n";
|
||||
}
|
||||
|
||||
return $fileContents;
|
||||
}
|
||||
|
||||
protected function makeFileHash($file) {
|
||||
return $file . filemtime($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Manifest $cache
|
||||
* @param $content
|
||||
* @param $originalFilePath
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function parseFile($cache, $content, $originalFilePath) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset;
|
||||
|
||||
use Nextend\Framework\Data\Data;
|
||||
use Nextend\Framework\PageFlow;
|
||||
use Nextend\Framework\Plugin;
|
||||
use Nextend\Framework\View\Html;
|
||||
|
||||
/**
|
||||
* Class Manager
|
||||
*
|
||||
*/
|
||||
class AssetManager {
|
||||
|
||||
/**
|
||||
* Helper to safely store AssetManager related optimization data
|
||||
*
|
||||
* @var Data
|
||||
*/
|
||||
public static $stateStorage;
|
||||
|
||||
/**
|
||||
* @var CSS\Asset
|
||||
*/
|
||||
public static $css;
|
||||
|
||||
private static $cssStack = array();
|
||||
|
||||
/**
|
||||
* @var Css\Less\Asset
|
||||
*/
|
||||
public static $less;
|
||||
|
||||
private static $lessStack = array();
|
||||
|
||||
/**
|
||||
* @var Js\Asset
|
||||
*/
|
||||
public static $js;
|
||||
|
||||
private static $jsStack = array();
|
||||
|
||||
/**
|
||||
* @var Fonts\Google\Asset
|
||||
*/
|
||||
public static $googleFonts;
|
||||
|
||||
/**
|
||||
* @var Image\Asset
|
||||
*/
|
||||
public static $image;
|
||||
|
||||
private static $imageStack = array();
|
||||
|
||||
private static $googleFontsStack = array();
|
||||
|
||||
public static $cacheAll = true;
|
||||
|
||||
public static $cachedGroups = array();
|
||||
|
||||
public static function getInstance() {
|
||||
static $instance = null;
|
||||
if (null === $instance) {
|
||||
$instance = new self();
|
||||
self::createStack();
|
||||
|
||||
Plugin::doAction('n2_assets_manager_started');
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public static function createStack() {
|
||||
|
||||
self::$stateStorage = new Data();
|
||||
|
||||
self::$css = new Css\Asset();
|
||||
array_unshift(self::$cssStack, self::$css);
|
||||
|
||||
self::$less = new Css\Less\Asset();
|
||||
array_unshift(self::$lessStack, self::$less);
|
||||
|
||||
self::$js = new Js\Asset();
|
||||
array_unshift(self::$jsStack, self::$js);
|
||||
|
||||
self::$googleFonts = new Fonts\Google\Asset();
|
||||
array_unshift(self::$googleFontsStack, self::$googleFonts);
|
||||
|
||||
self::$image = new Image\Asset();
|
||||
array_unshift(self::$imageStack, self::$image);
|
||||
}
|
||||
|
||||
public static function removeStack() {
|
||||
if (count(self::$cssStack) > 0) {
|
||||
|
||||
self::$stateStorage = new Data();
|
||||
|
||||
/**
|
||||
* @var $previousCSS Css\Asset
|
||||
* @var $previousLESS Css\Less\Asset
|
||||
* @var $previousJS Js\Asset
|
||||
* @var $previousGoogleFons Fonts\Google\Asset
|
||||
* @var $previousImage Image\Asset
|
||||
*/
|
||||
$previousCSS = array_shift(self::$cssStack);
|
||||
self::$css = self::$cssStack[0];
|
||||
|
||||
$previousLESS = array_shift(self::$lessStack);
|
||||
self::$less = self::$lessStack[0];
|
||||
|
||||
$previousJS = array_shift(self::$jsStack);
|
||||
self::$js = self::$jsStack[0];
|
||||
|
||||
$previousGoogleFons = array_shift(self::$googleFontsStack);
|
||||
self::$googleFonts = self::$googleFontsStack[0];
|
||||
|
||||
$previousImage = array_shift(self::$imageStack);
|
||||
self::$image = self::$imageStack[0];
|
||||
|
||||
return array(
|
||||
'css' => $previousCSS->serialize(),
|
||||
'less' => $previousLESS->serialize(),
|
||||
'js' => $previousJS->serialize(),
|
||||
'googleFonts' => $previousGoogleFons->serialize(),
|
||||
'image' => $previousImage->serialize()
|
||||
);
|
||||
}
|
||||
|
||||
echo "Too much remove stack on the asset manager...";
|
||||
PageFlow::exitApplication();
|
||||
|
||||
}
|
||||
|
||||
public static function enableCacheAll() {
|
||||
self::$cacheAll = true;
|
||||
}
|
||||
|
||||
public static function disableCacheAll() {
|
||||
self::$cacheAll = false;
|
||||
}
|
||||
|
||||
public static function addCachedGroup($group) {
|
||||
if (!in_array($group, self::$cachedGroups)) {
|
||||
self::$cachedGroups[] = $group;
|
||||
}
|
||||
}
|
||||
|
||||
public static function loadFromArray($array) {
|
||||
|
||||
self::$css->unSerialize($array['css']);
|
||||
self::$less->unSerialize($array['less']);
|
||||
self::$js->unSerialize($array['js']);
|
||||
self::$googleFonts->unSerialize($array['googleFonts']);
|
||||
self::$image->unSerialize($array['image']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return array|string contains already escaped data
|
||||
*/
|
||||
public static function getCSS($path = false) {
|
||||
if (self::$css) {
|
||||
if ($path) {
|
||||
return self::$css->get();
|
||||
}
|
||||
|
||||
return self::$css->getOutput();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return array|string contains already escaped data
|
||||
*/
|
||||
public static function getJs($path = false) {
|
||||
if (self::$js) {
|
||||
if ($path) {
|
||||
return self::$js->get();
|
||||
}
|
||||
|
||||
return self::$js->getOutput();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function generateAjaxCSS() {
|
||||
|
||||
return Html::style(self::$css->getAjaxOutput());
|
||||
}
|
||||
|
||||
|
||||
public static function generateAjaxJS() {
|
||||
|
||||
return self::$js->getAjaxOutput();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset\Css;
|
||||
|
||||
use Nextend\Framework\Asset\AbstractAsset;
|
||||
use Nextend\Framework\Asset\Fonts\Google\Google;
|
||||
use Nextend\Framework\Platform\Platform;
|
||||
use Nextend\Framework\Plugin;
|
||||
use Nextend\Framework\Settings;
|
||||
use Nextend\Framework\Url\Url;
|
||||
use Nextend\Framework\View\Html;
|
||||
use Nextend\SmartSlider3\SmartSlider3Info;
|
||||
|
||||
class Asset extends AbstractAsset {
|
||||
|
||||
|
||||
public function __construct() {
|
||||
$this->cache = new Cache();
|
||||
}
|
||||
|
||||
public function getOutput() {
|
||||
|
||||
$headerPreload = !!Settings::get('header-preload', '0');
|
||||
|
||||
$needProtocol = !Settings::get('protocol-relative', '1');
|
||||
|
||||
Google::build();
|
||||
|
||||
Less\Less::build();
|
||||
|
||||
$output = "";
|
||||
|
||||
$this->urls = array_unique($this->urls);
|
||||
|
||||
|
||||
foreach ($this->staticGroupPreload as $file) {
|
||||
$url = $this->filterSrc(Url::pathToUri($file, $needProtocol) . '?ver=' . SmartSlider3Info::$revisionShort);
|
||||
$output .= Html::style($url, true, array(
|
||||
'media' => 'all'
|
||||
)) . "\n";
|
||||
if ($headerPreload) {
|
||||
header('Link: <' . $url . '>; rel=preload; as=style', false);
|
||||
}
|
||||
}
|
||||
|
||||
$linkAttributes = array(
|
||||
'media' => 'all'
|
||||
);
|
||||
|
||||
if (!Platform::isAdmin() && Settings::get('async-non-primary-css', 0)) {
|
||||
$linkAttributes = array(
|
||||
'media' => 'print',
|
||||
'onload' => "this.media='all'"
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->urls as $url) {
|
||||
|
||||
$url = $this->filterSrc($url);
|
||||
|
||||
$output .= Html::style($url, true, $linkAttributes) . "\n";
|
||||
}
|
||||
|
||||
foreach ($this->getFiles() as $file) {
|
||||
if (substr($file, 0, 2) == '//') {
|
||||
$url = $this->filterSrc($file);
|
||||
} else {
|
||||
$url = $this->filterSrc(Url::pathToUri($file, $needProtocol) . '?ver=' . SmartSlider3Info::$revisionShort);
|
||||
}
|
||||
$output .= Html::style($url, true, $linkAttributes) . "\n";
|
||||
}
|
||||
|
||||
$inlineText = '';
|
||||
foreach ($this->inline as $key => $value) {
|
||||
if (!is_numeric($key)) {
|
||||
$output .= Html::style($value, false, array(
|
||||
'data-related' => $key
|
||||
)) . "\n";
|
||||
} else {
|
||||
$inlineText .= $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($inlineText)) {
|
||||
$output .= Html::style($inlineText) . "\n";
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function filterSrc($src) {
|
||||
return Plugin::applyFilters('n2_style_loader_src', $src);
|
||||
}
|
||||
|
||||
public function get() {
|
||||
Google::build();
|
||||
Less\Less::build();
|
||||
|
||||
return array(
|
||||
'url' => $this->urls,
|
||||
'files' => array_merge($this->staticGroupPreload, $this->getFiles()),
|
||||
'inline' => implode("\n", $this->inline)
|
||||
);
|
||||
}
|
||||
|
||||
public function getAjaxOutput() {
|
||||
|
||||
$output = implode("\n", $this->inline);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset\Css;
|
||||
|
||||
use Nextend\Framework\Asset\AbstractCache;
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
use Nextend\Framework\Url\Url;
|
||||
|
||||
class Cache extends AbstractCache {
|
||||
|
||||
public $outputFileType = "css";
|
||||
|
||||
private $baseUrl = '';
|
||||
|
||||
private $basePath = '';
|
||||
|
||||
public function getAssetFileFolder() {
|
||||
return Filesystem::getWebCachePath() . DIRECTORY_SEPARATOR . $this->group . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
protected function parseFile($cache, $content, $originalFilePath) {
|
||||
|
||||
$this->basePath = dirname($originalFilePath);
|
||||
$this->baseUrl = Filesystem::pathToAbsoluteURL($this->basePath);
|
||||
|
||||
return preg_replace_callback('#url\([\'"]?([^"\'\)]+)[\'"]?\)#', array(
|
||||
$this,
|
||||
'makeAbsoluteUrl'
|
||||
), $content);
|
||||
}
|
||||
|
||||
private function makeAbsoluteUrl($matches) {
|
||||
if (substr($matches[1], 0, 5) == 'data:') return $matches[0];
|
||||
if (substr($matches[1], 0, 4) == 'http') return $matches[0];
|
||||
if (substr($matches[1], 0, 2) == '//') return $matches[0];
|
||||
|
||||
$exploded = explode('?', $matches[1]);
|
||||
|
||||
$realPath = realpath($this->basePath . '/' . $exploded[0]);
|
||||
if ($realPath === false) {
|
||||
return 'url(' . str_replace(array(
|
||||
'http://',
|
||||
'https://'
|
||||
), '//', $this->baseUrl) . '/' . $matches[1] . ')';
|
||||
}
|
||||
|
||||
$realPath = Filesystem::convertToRealDirectorySeparator($realPath);
|
||||
|
||||
return 'url(' . Url::pathToUri($realPath, false) . (isset($exploded[1]) ? '?' . $exploded[1] : '') . ')';
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset\Css;
|
||||
|
||||
use Nextend\Framework\Asset\AssetManager;
|
||||
|
||||
class Css {
|
||||
|
||||
public static function addFile($pathToFile, $group) {
|
||||
AssetManager::$css->addFile($pathToFile, $group);
|
||||
}
|
||||
|
||||
public static function addFiles($path, $files, $group) {
|
||||
AssetManager::$css->addFiles($path, $files, $group);
|
||||
}
|
||||
|
||||
public static function addStaticGroupPreload($file, $group) {
|
||||
AssetManager::$css->addStaticGroupPreload($file, $group);
|
||||
}
|
||||
|
||||
public static function addStaticGroup($file, $group) {
|
||||
AssetManager::$css->addStaticGroup($file, $group);
|
||||
}
|
||||
|
||||
public static function addCode($code, $group, $unshift = false) {
|
||||
AssetManager::$css->addCode($code, $group, $unshift);
|
||||
}
|
||||
|
||||
public static function addUrl($url) {
|
||||
AssetManager::$css->addUrl($url);
|
||||
}
|
||||
|
||||
public static function addInline($code, $name = null) {
|
||||
AssetManager::$css->addInline($code, $name);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset\Css\Less;
|
||||
|
||||
use Nextend\Framework\Asset\AbstractAsset;
|
||||
|
||||
class Asset extends AbstractAsset {
|
||||
|
||||
public function __construct() {
|
||||
$this->cache = new Cache();
|
||||
}
|
||||
|
||||
protected function uniqueFiles() {
|
||||
$this->initGroups();
|
||||
}
|
||||
|
||||
public function getFiles() {
|
||||
$this->uniqueFiles();
|
||||
|
||||
$files = array();
|
||||
foreach ($this->groups as $group) {
|
||||
$files[$group] = $this->cache->getAssetFile($group, $this->files[$group], $this->codes[$group]);
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset\Css\Less;
|
||||
|
||||
use Exception;
|
||||
use Nextend\Framework\Cache\Manifest;
|
||||
|
||||
class Cache extends \Nextend\Framework\Asset\Css\Cache {
|
||||
|
||||
|
||||
public $outputFileType = "less.css";
|
||||
|
||||
public function getAssetFile($group, &$files = array(), &$codes = array()) {
|
||||
$this->group = $group;
|
||||
$this->files = $files;
|
||||
$this->codes = $codes;
|
||||
|
||||
$cache = new Manifest($group, false, true);
|
||||
$hash = $this->getHash();
|
||||
|
||||
return $cache->makeCache($group . "." . $this->outputFileType, $hash, array(
|
||||
$this,
|
||||
'getCachedContent'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Manifest $cache
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCachedContent($cache) {
|
||||
|
||||
$fileContents = '';
|
||||
|
||||
foreach ($this->files as $parameters) {
|
||||
$compiler = new LessCompiler();
|
||||
|
||||
if (!empty($parameters['importDir'])) {
|
||||
$compiler->addImportDir($parameters['importDir']);
|
||||
}
|
||||
|
||||
$compiler->setVariables($parameters['context']);
|
||||
$fileContents .= $compiler->compileFile($parameters['file']);
|
||||
}
|
||||
|
||||
return $fileContents;
|
||||
}
|
||||
|
||||
protected function makeFileHash($parameters) {
|
||||
return json_encode($parameters) . filemtime($parameters['file']);
|
||||
}
|
||||
|
||||
protected function parseFile($cache, $content, $lessParameters) {
|
||||
|
||||
return parent::parseFile($cache, $content, $lessParameters['file']);
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Asset\Css\Less\Formatter;
|
||||
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class Classic {
|
||||
|
||||
public $indentChar = " ";
|
||||
|
||||
public $break = "\n";
|
||||
public $open = " {";
|
||||
public $close = "}";
|
||||
public $selectorSeparator = ", ";
|
||||
public $assignSeparator = ":";
|
||||
|
||||
public $openSingle = " { ";
|
||||
public $closeSingle = " }";
|
||||
|
||||
public $disableSingle = false;
|
||||
public $breakSelectors = false;
|
||||
|
||||
public $compressColors = false;
|
||||
|
||||
public function __construct() {
|
||||
$this->indentLevel = 0;
|
||||
}
|
||||
|
||||
public function indentStr($n = 0) {
|
||||
return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
|
||||
}
|
||||
|
||||
public function property($name, $value) {
|
||||
return $name . $this->assignSeparator . $value . ";";
|
||||
}
|
||||
|
||||
protected function isEmpty($block) {
|
||||
if (empty($block->lines)) {
|
||||
foreach ($block->children as $child) {
|
||||
if (!$this->isEmpty($child)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function block($block) {
|
||||
$ret = '';
|
||||
if ($this->isEmpty($block)) return $ret;
|
||||
|
||||
$inner = $pre = $this->indentStr();
|
||||
|
||||
$isSingle = !$this->disableSingle && is_null($block->type) && count($block->lines) == 1;
|
||||
|
||||
if (!empty($block->selectors)) {
|
||||
$this->indentLevel++;
|
||||
|
||||
if ($this->breakSelectors) {
|
||||
$selectorSeparator = $this->selectorSeparator . $this->break . $pre;
|
||||
} else {
|
||||
$selectorSeparator = $this->selectorSeparator;
|
||||
}
|
||||
|
||||
$ret .= $pre . implode($selectorSeparator, $block->selectors);
|
||||
if ($isSingle) {
|
||||
$ret .= $this->openSingle;
|
||||
$inner = "";
|
||||
} else {
|
||||
$ret .= $this->open . $this->break;
|
||||
$inner = $this->indentStr();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!empty($block->lines)) {
|
||||
$glue = $this->break . $inner;
|
||||
$ret .= $inner . implode($glue, $block->lines);
|
||||
if (!$isSingle && !empty($block->children)) {
|
||||
$ret .= $this->break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($block->children as $child) {
|
||||
$ret .= $this->block($child);
|
||||
}
|
||||
|
||||
if (!empty($block->selectors)) {
|
||||
if (!$isSingle && empty($block->children)) $ret .= $this->break;
|
||||
|
||||
if ($isSingle) {
|
||||
$ret .= $this->closeSingle . $this->break;
|
||||
} else {
|
||||
$ret .= $pre . $this->close . $this->break;
|
||||
}
|
||||
|
||||
$this->indentLevel--;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Asset\Css\Less\Formatter;
|
||||
|
||||
|
||||
class Compressed extends Classic {
|
||||
|
||||
public $disableSingle = true;
|
||||
public $open = "{";
|
||||
public $selectorSeparator = ",";
|
||||
public $assignSeparator = ":";
|
||||
public $break = "";
|
||||
public $compressColors = true;
|
||||
|
||||
public function indentStr($n = 0) {
|
||||
return "";
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Asset\Css\Less\Formatter;
|
||||
|
||||
|
||||
class Debug extends Classic {
|
||||
|
||||
public $disableSingle = true;
|
||||
public $breakSelectors = true;
|
||||
public $assignSeparator = ": ";
|
||||
public $selectorSeparator = ",";
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Asset\Css\Less;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\AssetManager;
|
||||
use Nextend\Framework\Asset\Css\Css;
|
||||
|
||||
class Less {
|
||||
|
||||
public static function addFile($pathToFile, $group, $context = array(), $importDir = null) {
|
||||
AssetManager::$less->addFile(array(
|
||||
'file' => $pathToFile,
|
||||
'context' => $context,
|
||||
'importDir' => $importDir
|
||||
), $group);
|
||||
}
|
||||
|
||||
public static function build() {
|
||||
foreach (AssetManager::$less->getFiles() as $group => $file) {
|
||||
if (substr($file, 0, 2) == '//') {
|
||||
Css::addUrl($file);
|
||||
} else if (!realpath($file)) {
|
||||
// For database cache the $file contains the content of the generated CSS file
|
||||
Css::addCode($file, $group, true);
|
||||
} else {
|
||||
Css::addFile($file, $group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Asset\Fonts\Google;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\AbstractAsset;
|
||||
use Nextend\Framework\Asset\Css\Css;
|
||||
use Nextend\Framework\Cache\CacheGoogleFont;
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
use Nextend\Framework\Font\FontSettings;
|
||||
use Nextend\Framework\Url\UrlHelper;
|
||||
use Nextend\SmartSlider3\SmartSlider3Info;
|
||||
|
||||
class Asset extends AbstractAsset {
|
||||
|
||||
public function getLoadedFamilies() {
|
||||
return array_keys($this->files);
|
||||
}
|
||||
|
||||
function addFont($family, $style = '400') {
|
||||
$style = (string)$style;
|
||||
if (!isset($this->files[$family])) {
|
||||
$this->files[$family] = array();
|
||||
}
|
||||
if (!in_array($style, $this->files[$family])) {
|
||||
$this->files[$family][] = $style;
|
||||
}
|
||||
}
|
||||
|
||||
public function loadFonts() {
|
||||
|
||||
if (!empty($this->files)) {
|
||||
//https://fonts.googleapis.com/css?display=swap&family=Montserrat:400%7CRoboto:100italic,300,400
|
||||
|
||||
$families = array();
|
||||
foreach ($this->files as $name => $styles) {
|
||||
if (count($styles) && !in_array($name, Google::$excludedFamilies)) {
|
||||
$families[] = $name . ':' . implode(',', $styles);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($families)) {
|
||||
$params = array(
|
||||
'display' => 'swap',
|
||||
'family' => urlencode(implode('|', $families))
|
||||
);
|
||||
|
||||
$url = UrlHelper::add_query_arg($params, 'https://fonts.googleapis.com/css');
|
||||
|
||||
$fontSettings = FontSettings::getPluginsData();
|
||||
if ($fontSettings->get('google-cache', 0)) {
|
||||
$cache = new CacheGoogleFont();
|
||||
|
||||
$path = $cache->makeCache($url, 'css');
|
||||
|
||||
if ($path) {
|
||||
$url = Filesystem::pathToAbsoluteURL($path) . '?ver=' . SmartSlider3Info::$revisionShort;
|
||||
}
|
||||
}
|
||||
|
||||
Css::addUrl($url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Asset\Fonts\Google;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\AssetManager;
|
||||
|
||||
class Google {
|
||||
|
||||
public static $enabled = false;
|
||||
|
||||
public static $excludedFamilies = array();
|
||||
|
||||
public static function addFont($family, $style = '400') {
|
||||
AssetManager::$googleFonts->addFont($family, $style);
|
||||
}
|
||||
|
||||
public static function addFontExclude($family) {
|
||||
self::$excludedFamilies[] = $family;
|
||||
}
|
||||
|
||||
public static function build() {
|
||||
if (self::$enabled) {
|
||||
AssetManager::$googleFonts->loadFonts();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset\Image;
|
||||
|
||||
class Asset {
|
||||
|
||||
protected $images = array();
|
||||
|
||||
public function add($images) {
|
||||
if (!is_array($images)) {
|
||||
$images = array($images);
|
||||
}
|
||||
|
||||
$this->images = array_unique(array_merge($this->images, $images));
|
||||
}
|
||||
|
||||
public function get() {
|
||||
return $this->images;
|
||||
}
|
||||
|
||||
public function match($url) {
|
||||
return in_array($url, $this->images);
|
||||
}
|
||||
|
||||
public function serialize() {
|
||||
return array(
|
||||
'images' => $this->images
|
||||
);
|
||||
}
|
||||
|
||||
public function unSerialize($array) {
|
||||
if (!empty($array['images'])) {
|
||||
$this->add($array['images']);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Asset\Js;
|
||||
|
||||
use Nextend\Framework\Asset\AbstractAsset;
|
||||
use Nextend\Framework\Localization\Localization;
|
||||
use Nextend\Framework\Platform\Platform;
|
||||
use Nextend\Framework\Plugin;
|
||||
use Nextend\Framework\Settings;
|
||||
use Nextend\Framework\Url\Url;
|
||||
use Nextend\Framework\View\Html;
|
||||
use Nextend\SmartSlider3\SmartSlider3Info;
|
||||
|
||||
class Asset extends AbstractAsset {
|
||||
|
||||
public function __construct() {
|
||||
$this->cache = new Cache();
|
||||
}
|
||||
|
||||
public function getOutput() {
|
||||
|
||||
$output = "";
|
||||
|
||||
$needProtocol = !Settings::get('protocol-relative', '1');
|
||||
|
||||
$globalInline = $this->getGlobalInlineScripts();
|
||||
if (!empty($globalInline)) {
|
||||
$output .= Html::script(self::minify_js($globalInline . "\n"));
|
||||
}
|
||||
|
||||
$async = !Platform::isAdmin();
|
||||
$scriptAttributes = array();
|
||||
if ($async) {
|
||||
$scriptAttributes['defer'] = 1;
|
||||
$scriptAttributes['async'] = 1;
|
||||
}
|
||||
|
||||
foreach ($this->urls as $url) {
|
||||
$output .= Html::scriptFile($this->filterSrc($url), $scriptAttributes) . "\n";
|
||||
}
|
||||
|
||||
foreach ($this->getFiles() as $file) {
|
||||
if (substr($file, 0, 2) == '//') {
|
||||
$output .= Html::scriptFile($this->filterSrc($file), $scriptAttributes) . "\n";
|
||||
} else {
|
||||
$output .= Html::scriptFile($this->filterSrc(Url::pathToUri($file, $needProtocol) . '?ver=' . SmartSlider3Info::$revisionShort), $scriptAttributes) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$output .= Html::script(self::minify_js(Localization::toJS() . "\n" . $this->getInlineScripts() . "\n"));
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function filterSrc($src) {
|
||||
return Plugin::applyFilters('n2_script_loader_src', $src);
|
||||
}
|
||||
|
||||
public function get() {
|
||||
return array(
|
||||
'url' => $this->urls,
|
||||
'files' => $this->getFiles(),
|
||||
'inline' => $this->getInlineScripts(),
|
||||
'globalInline' => $this->getGlobalInlineScripts()
|
||||
);
|
||||
}
|
||||
|
||||
public function getAjaxOutput() {
|
||||
|
||||
$output = $this->getInlineScripts();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function getGlobalInlineScripts() {
|
||||
return implode('', $this->globalInline);
|
||||
}
|
||||
|
||||
private function getInlineScripts() {
|
||||
$scripts = '';
|
||||
|
||||
foreach ($this->firstCodes as $script) {
|
||||
$scripts .= $script . "\n";
|
||||
}
|
||||
|
||||
foreach ($this->inline as $script) {
|
||||
$scripts .= $script . "\n";
|
||||
}
|
||||
|
||||
return $this->serveJquery($scripts);
|
||||
}
|
||||
|
||||
public static function serveJquery($script) {
|
||||
if (empty($script)) {
|
||||
return "";
|
||||
}
|
||||
$inline = "_N2.r('documentReady', function(){\n";
|
||||
$inline .= $script;
|
||||
$inline .= "});\n";
|
||||
|
||||
return $inline;
|
||||
}
|
||||
|
||||
public static function minify_js($input) {
|
||||
if (trim($input) === "") return $input;
|
||||
|
||||
return preg_replace(array(
|
||||
// Remove comment(s)
|
||||
'#\s*("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')\s*|\s*\/\*(?!\!|@cc_on)(?>[\s\S]*?\*\/)\s*|\s*(?<![\:\=])\/\/.*(?=[\n\r]|$)|^\s*|\s*$#',
|
||||
// Remove white-space(s) outside the string and regex
|
||||
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/)|\/(?!\/)[^\n\r]*?\/(?=[\s.,;]|[gimuy]|$))|\s*([!%&*\(\)\-=+\[\]\{\}|;:,.<>?\/])\s*#s',
|
||||
// Remove the last semicolon
|
||||
'#;+\}#',
|
||||
// Minify object attribute(s) except JSON attribute(s). From `{'foo':'bar'}` to `{foo:'bar'}`
|
||||
'#([\{,])([\'])(\d+|[a-z_][a-z0-9_]*)\2(?=\:)#i',
|
||||
// --ibid. From `foo['bar']` to `foo.bar`
|
||||
'#([a-z0-9_\)\]])\[([\'"])([a-z_][a-z0-9_]*)\2\]#i'
|
||||
), array(
|
||||
'$1',
|
||||
'$1$2',
|
||||
'}',
|
||||
'$1$3',
|
||||
'$1.$3'
|
||||
), $input);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset\Js;
|
||||
|
||||
use Nextend\Framework\Asset\AbstractCache;
|
||||
use Nextend\Framework\Cache\Manifest;
|
||||
|
||||
class Cache extends AbstractCache {
|
||||
|
||||
public $outputFileType = "js";
|
||||
|
||||
/**
|
||||
* @param Manifest $cache
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCachedContent($cache) {
|
||||
|
||||
$content = '(function(){this._N2=this._N2||{_r:[],_d:[],r:function(){this._r.push(arguments)},d:function(){this._d.push(arguments)}}}).call(window);';
|
||||
$content .= parent::getCachedContent($cache);
|
||||
$content .= "_N2.d('" . $this->group . "');";
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset\Js;
|
||||
|
||||
use Nextend\Framework\Asset\AssetManager;
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
|
||||
class Js {
|
||||
|
||||
public static function addFile($pathToFile, $group) {
|
||||
AssetManager::$js->addFile($pathToFile, $group);
|
||||
}
|
||||
|
||||
public static function addFiles($path, $files, $group) {
|
||||
AssetManager::$js->addFiles($path, $files, $group);
|
||||
}
|
||||
|
||||
public static function addStaticGroup($file, $group) {
|
||||
AssetManager::$js->addStaticGroup($file, $group);
|
||||
}
|
||||
|
||||
public static function addCode($code, $group) {
|
||||
AssetManager::$js->addCode($code, $group);
|
||||
}
|
||||
|
||||
public static function addUrl($url) {
|
||||
AssetManager::$js->addUrl($url);
|
||||
}
|
||||
|
||||
public static function addFirstCode($code, $unshift = false) {
|
||||
AssetManager::$js->addFirstCode($code, $unshift);
|
||||
}
|
||||
|
||||
public static function addInline($code, $unshift = false) {
|
||||
AssetManager::$js->addInline($code, null, $unshift);
|
||||
}
|
||||
|
||||
public static function addGlobalInline($code, $unshift = false) {
|
||||
AssetManager::$js->addGlobalInline($code, $unshift);
|
||||
}
|
||||
|
||||
public static function addInlineFile($path, $unshift = false) {
|
||||
static $loaded = array();
|
||||
if (!isset($loaded[$path])) {
|
||||
AssetManager::$js->addInline(Filesystem::readFile($path), null, $unshift);
|
||||
$loaded[$path] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static function addGlobalInlineFile($path, $unshift = false) {
|
||||
static $loaded = array();
|
||||
if (!isset($loaded[$path])) {
|
||||
AssetManager::$js->addGlobalInline(Filesystem::readFile($path), $unshift);
|
||||
$loaded[$path] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Asset;
|
||||
|
||||
|
||||
use JHtml;
|
||||
use Nextend\Framework\Asset\Css\Css;
|
||||
use Nextend\Framework\Asset\Fonts\Google\Google;
|
||||
use Nextend\Framework\Asset\Js\Js;
|
||||
use Nextend\Framework\Font\FontSources;
|
||||
use Nextend\Framework\Form\Form;
|
||||
use Nextend\Framework\Platform\Platform;
|
||||
use Nextend\Framework\Plugin;
|
||||
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
|
||||
use Nextend\SmartSlider3\Application\Frontend\ApplicationTypeFrontend;
|
||||
use Nextend\SmartSlider3\Settings;
|
||||
|
||||
class Predefined {
|
||||
|
||||
public static function backend($force = false) {
|
||||
static $once;
|
||||
if ($once != null && !$force) {
|
||||
return;
|
||||
}
|
||||
$once = true;
|
||||
wp_enqueue_script('jquery');
|
||||
$jQueryFallback = site_url('wp-includes/js/jquery/jquery.js');
|
||||
|
||||
Js::addGlobalInline('_N2._jQueryFallback=\'' . $jQueryFallback . '\';');
|
||||
|
||||
Js::addFirstCode("_N2.r(['AjaxHelper'],function(){_N2.AjaxHelper.addAjaxArray(" . json_encode(Form::tokenizeUrl()) . ");});");
|
||||
|
||||
Plugin::addAction('afterApplicationContent', array(
|
||||
FontSources::class,
|
||||
'onFontManagerLoadBackend'
|
||||
));
|
||||
}
|
||||
|
||||
public static function frontend($force = false) {
|
||||
static $once;
|
||||
if ($once != null && !$force) {
|
||||
return;
|
||||
}
|
||||
$once = true;
|
||||
AssetManager::getInstance();
|
||||
if (Platform::isAdmin()) {
|
||||
Js::addGlobalInline('window.N2GSAP=' . N2GSAP . ';');
|
||||
Js::addGlobalInline('window.N2PLATFORM="' . Platform::getName() . '";');
|
||||
}
|
||||
|
||||
Js::addGlobalInline('(function(){this._N2=this._N2||{_r:[],_d:[],r:function(){this._r.push(arguments)},d:function(){this._d.push(arguments)}}}).call(window);');
|
||||
|
||||
Js::addStaticGroup(ApplicationTypeFrontend::getAssetsPath() . "/dist/n2.min.js", 'n2');
|
||||
|
||||
FontSources::onFontManagerLoad($force);
|
||||
}
|
||||
|
||||
public static function loadLiteBox() {
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user