first
This commit is contained in:
11
wp-content/plugins/smart-slider-3/Defines.php
Normal file
11
wp-content/plugins/smart-slider-3/Defines.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
if (!defined('NEXTEND_SMARTSLIDER_3_URL_PATH')) {
|
||||
define('NEXTEND_SMARTSLIDER_3_URL_PATH', 'smart-slider3');
|
||||
}
|
||||
|
||||
define('N2WORDPRESS', 1);
|
||||
define('N2JOOMLA', 0);
|
||||
|
||||
define('N2GSAP', 0);
|
||||
define('N2SSPRO', 0);
|
203
wp-content/plugins/smart-slider-3/Nextend/Autoloader.php
Normal file
203
wp-content/plugins/smart-slider-3/Nextend/Autoloader.php
Normal file
@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend;
|
||||
|
||||
class Autoloader {
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
private $aliases = array(
|
||||
'N2Data' => '\\Nextend\\Framework\\Data\\Data',
|
||||
'N2SmartSliderBackup' => '\\Nextend\\SmartSlider3\\BackupSlider\\BackupData',
|
||||
'N2SmartSliderImport' => '\\Nextend\\SmartSlider3\\BackupSlider\\ImportSlider',
|
||||
'N2SmartSliderExport' => '\\Nextend\\SmartSlider3\\BackupSlider\\ExportSlider',
|
||||
);
|
||||
|
||||
/**
|
||||
* An associative array where the key is a namespace prefix and the value
|
||||
* is an array of base directories for classes in that namespace.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $prefixes = array();
|
||||
|
||||
public function __construct() {
|
||||
$this->addNamespace('Nextend\\', dirname(__FILE__));
|
||||
|
||||
|
||||
$this->register();
|
||||
|
||||
$currentPath = dirname(__FILE__) . '/';
|
||||
foreach (scandir($currentPath) as $file) {
|
||||
if ($file == '.' || $file == '..') continue;
|
||||
$path = $currentPath . $file;
|
||||
if (is_dir($path)) {
|
||||
|
||||
$className = '\\Nextend\\' . $file . '\\' . $file;
|
||||
|
||||
if (class_exists($className) && is_callable(array(
|
||||
$className,
|
||||
'getInstance'
|
||||
))) {
|
||||
call_user_func_array(array(
|
||||
$className,
|
||||
'getInstance'
|
||||
), array());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nextend::getInstance();
|
||||
}
|
||||
|
||||
public static function getInstance() {
|
||||
if (self::$instance == null) {
|
||||
self::$instance = new Autoloader();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register loader with SPL autoloader stack.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register() {
|
||||
spl_autoload_register(array(
|
||||
$this,
|
||||
'loadClass'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a base directory for a namespace prefix.
|
||||
*
|
||||
* @param string $prefix The namespace prefix.
|
||||
* @param string $base_dir A base directory for class files in the
|
||||
* namespace.
|
||||
* @param bool $prepend If true, prepend the base directory to the stack
|
||||
* instead of appending it; this causes it to be searched first rather
|
||||
* than last.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addNamespace($prefix, $base_dir, $prepend = false) {
|
||||
// normalize namespace prefix
|
||||
$prefix = trim($prefix, '\\') . '\\';
|
||||
|
||||
// normalize the base directory with a trailing separator
|
||||
$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';
|
||||
|
||||
// initialize the namespace prefix array
|
||||
if (isset($this->prefixes[$prefix]) === false) {
|
||||
$this->prefixes[$prefix] = array();
|
||||
}
|
||||
|
||||
// retain the base directory for the namespace prefix
|
||||
if ($prepend) {
|
||||
array_unshift($this->prefixes[$prefix], $base_dir);
|
||||
} else {
|
||||
array_push($this->prefixes[$prefix], $base_dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the class file for a given class name.
|
||||
*
|
||||
* @param string $class The fully-qualified class name.
|
||||
*
|
||||
* @return mixed The mapped file name on success, or boolean false on
|
||||
* failure.
|
||||
*/
|
||||
public function loadClass($class) {
|
||||
// the current namespace prefix
|
||||
$prefix = $class;
|
||||
|
||||
// work backwards through the namespace names of the fully-qualified
|
||||
// class name to find a mapped file name
|
||||
while (false !== $pos = strrpos($prefix, '\\')) {
|
||||
|
||||
// retain the trailing namespace separator in the prefix
|
||||
$prefix = substr($class, 0, $pos + 1);
|
||||
|
||||
// the rest is the relative class name
|
||||
$relative_class = substr($class, $pos + 1);
|
||||
|
||||
// try to load a mapped file for the prefix and relative class
|
||||
$mapped_file = $this->loadMappedFile($prefix, $relative_class);
|
||||
if ($mapped_file) {
|
||||
return $mapped_file;
|
||||
}
|
||||
|
||||
// remove the trailing namespace separator for the next iteration
|
||||
// of strrpos()
|
||||
$prefix = rtrim($prefix, '\\');
|
||||
}
|
||||
|
||||
if (isset($this->aliases[$class]) && class_exists($this->aliases[$class])) {
|
||||
/**
|
||||
* Create class alias for old class names
|
||||
*/
|
||||
class_alias($this->aliases[$class], $class);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// never found a mapped file
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the mapped file for a namespace prefix and relative class.
|
||||
*
|
||||
* @param string $prefix The namespace prefix.
|
||||
* @param string $relative_class The relative class name.
|
||||
*
|
||||
* @return mixed Boolean false if no mapped file can be loaded, or the
|
||||
* name of the mapped file that was loaded.
|
||||
*/
|
||||
protected function loadMappedFile($prefix, $relative_class) {
|
||||
// are there any base directories for this namespace prefix?
|
||||
if (isset($this->prefixes[$prefix]) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// look through base directories for this namespace prefix
|
||||
foreach ($this->prefixes[$prefix] as $base_dir) {
|
||||
|
||||
// replace the namespace prefix with the base directory,
|
||||
// replace namespace separators with directory separators
|
||||
// in the relative class name, append with .php
|
||||
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
||||
|
||||
// if the mapped file exists, require it
|
||||
if ($this->requireFile($file)) {
|
||||
// yes, we're done
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// never found it
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a file exists, require it from the file system.
|
||||
*
|
||||
* @param string $file The file to require.
|
||||
*
|
||||
* @return bool True if the file exists, false if not.
|
||||
*/
|
||||
protected function requireFile($file) {
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Autoloader::getInstance();
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Acl;
|
||||
|
||||
use Nextend\Framework\Pattern\MVCHelperTrait;
|
||||
|
||||
abstract class AbstractPlatformAcl {
|
||||
|
||||
/**
|
||||
* @param $action
|
||||
* @param MVCHelperTrait $MVCHelper
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function authorise($action, $MVCHelper);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Acl;
|
||||
|
||||
use Nextend\Framework\Acl\Joomla\JoomlaAcl;
|
||||
use Nextend\Framework\Acl\WordPress\WordPressAcl;
|
||||
use Nextend\Framework\Pattern\MVCHelperTrait;
|
||||
|
||||
class Acl {
|
||||
|
||||
/**
|
||||
* @var AbstractPlatformAcl
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
public function __construct() {
|
||||
self::$instance = new WordPressAcl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $action
|
||||
* @param MVCHelperTrait $MVCHelper
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function canDo($action, $MVCHelper) {
|
||||
return self::$instance->authorise($action, $MVCHelper);
|
||||
}
|
||||
}
|
||||
|
||||
new Acl();
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Acl\WordPress;
|
||||
|
||||
use Nextend\Framework\Acl\AbstractPlatformAcl;
|
||||
use function current_user_can;
|
||||
|
||||
class WordPressAcl extends AbstractPlatformAcl {
|
||||
|
||||
public function authorise($action, $MVCHelper) {
|
||||
return current_user_can($action) && current_user_can('unfiltered_html');
|
||||
}
|
||||
}
|
93
wp-content/plugins/smart-slider-3/Nextend/Framework/Api.php
Normal file
93
wp-content/plugins/smart-slider-3/Nextend/Framework/Api.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework;
|
||||
|
||||
|
||||
use Exception;
|
||||
use JHttp;
|
||||
use Nextend\Framework\Misc\Base64;
|
||||
use Nextend\Framework\Misc\HttpClient;
|
||||
use Nextend\Framework\Notification\Notification;
|
||||
use Nextend\Framework\Platform\Platform;
|
||||
use Nextend\Framework\Request\Request;
|
||||
use Nextend\Framework\Url\Url;
|
||||
|
||||
class Api {
|
||||
|
||||
private static $api = 'https://api.nextendweb.com/v1/';
|
||||
|
||||
public static function getApiUrl() {
|
||||
|
||||
return self::$api;
|
||||
}
|
||||
|
||||
public static function api($posts, $returnUrl = false) {
|
||||
|
||||
$api = self::getApiUrl();
|
||||
|
||||
$posts_default = array(
|
||||
'platform' => Platform::getName()
|
||||
);
|
||||
|
||||
$posts = $posts + $posts_default;
|
||||
|
||||
if ($returnUrl) {
|
||||
return $api . '?' . http_build_query($posts, '', '&');
|
||||
}
|
||||
$request = wp_remote_post($api, array(
|
||||
'timeout' => 20,
|
||||
'body' => $posts
|
||||
));
|
||||
if (is_wp_error($request)) {
|
||||
foreach ($request->get_error_messages() as $errorMessage) {
|
||||
Notification::error($errorMessage);
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
$data = wp_remote_retrieve_body($request);
|
||||
$headers = wp_remote_retrieve_headers($request);
|
||||
$contentType = $headers['content-type'];
|
||||
}
|
||||
|
||||
|
||||
switch ($contentType) {
|
||||
case 'text/html; charset=UTF-8':
|
||||
|
||||
Notification::error(sprintf('Unexpected response from the API.<br>Contact us (support@nextendweb.com) with the following log:') . '<br><textarea style="width: 100%;height:200px;font-size:8px;">' . Base64::encode($data) . '</textarea>');
|
||||
|
||||
return array(
|
||||
'status' => 'ERROR_HANDLED'
|
||||
);
|
||||
break;
|
||||
case 'application/json':
|
||||
return json_decode($data, true);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function parseHeaders(array $headers, $header = null) {
|
||||
$output = array();
|
||||
if ('HTTP' === substr($headers[0], 0, 4)) {
|
||||
list(, $output['status'], $output['status_text']) = explode(' ', $headers[0]);
|
||||
unset($headers[0]);
|
||||
}
|
||||
foreach ($headers as $v) {
|
||||
$h = preg_split('/:\s*/', $v);
|
||||
if (count($h) >= 2) {
|
||||
$output[strtolower($h[0])] = $h[1];
|
||||
}
|
||||
}
|
||||
if (null !== $header) {
|
||||
if (isset($output[strtolower($header)])) {
|
||||
return $output[strtolower($header)];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Application;
|
||||
|
||||
use Nextend\Framework\Pattern\SingletonTrait;
|
||||
use Nextend\Framework\Plugin;
|
||||
|
||||
abstract class AbstractApplication {
|
||||
|
||||
use SingletonTrait;
|
||||
|
||||
protected $key = '';
|
||||
|
||||
protected function init() {
|
||||
|
||||
//PluggableApplication\Nextend\SmartSlider3\Application\ApplicationSmartSlider3
|
||||
Plugin::doAction('PluggableApplication\\' . get_class($this), array($this));
|
||||
}
|
||||
|
||||
public function getKey() {
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function enqueueAssets() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Application;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Nextend\Framework\Controller\AbstractController;
|
||||
use Nextend\Framework\Pattern\GetAssetsPathTrait;
|
||||
use Nextend\Framework\Pattern\MVCHelperTrait;
|
||||
use Nextend\Framework\Plugin;
|
||||
use Nextend\Framework\Request\Request;
|
||||
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
|
||||
use Nextend\Framework\Router\Router;
|
||||
use Nextend\Framework\View\AbstractLayout;
|
||||
|
||||
abstract class AbstractApplicationType {
|
||||
|
||||
use GetAssetsPathTrait, MVCHelperTrait;
|
||||
|
||||
/** @var AbstractApplication */
|
||||
protected $application;
|
||||
|
||||
/** @var Router */
|
||||
protected $router;
|
||||
|
||||
protected $key = '';
|
||||
|
||||
/** @var AbstractLayout */
|
||||
protected $layout;
|
||||
|
||||
protected $externalControllers = array();
|
||||
|
||||
/**
|
||||
* AbstractApplicationType constructor.
|
||||
*
|
||||
* @param AbstractApplication $application
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($application) {
|
||||
|
||||
$this->setMVCHelper($this);
|
||||
|
||||
$this->application = $application;
|
||||
|
||||
ResourceTranslator::createResource('$' . $this->getKey() . '$', self::getAssetsPath(), self::getAssetsUri());
|
||||
|
||||
$this->createRouter();
|
||||
|
||||
|
||||
//PluggableApplicationType\Nextend\SmartSlider3\Application\Admin\ApplicationTypeAdmin
|
||||
Plugin::doAction('PluggableApplicationType\\' . get_class($this), array($this));
|
||||
}
|
||||
|
||||
public function getKey() {
|
||||
return $this->application->getKey() . '-' . $this->key;
|
||||
}
|
||||
|
||||
protected function createRouter() {
|
||||
|
||||
}
|
||||
|
||||
public function processRequest($defaultControllerName, $defaultActionName, $ajax = false, $args = array()) {
|
||||
|
||||
$controllerName = trim(Request::$REQUEST->getCmd("nextendcontroller"));
|
||||
if (empty($controllerName)) {
|
||||
$controllerName = $defaultControllerName;
|
||||
}
|
||||
|
||||
$actionName = trim(Request::$REQUEST->getCmd("nextendaction"));
|
||||
if (empty($actionName)) {
|
||||
$actionName = $defaultActionName;
|
||||
}
|
||||
|
||||
$this->process($controllerName, $actionName, $ajax, $args);
|
||||
}
|
||||
|
||||
public function process($controllerName, $actionName, $ajax = false, $args = array()) {
|
||||
|
||||
if ($ajax) {
|
||||
Request::$isAjax = true;
|
||||
}
|
||||
|
||||
/** @var AbstractController $controller */
|
||||
$controller = $this->getController($controllerName, $ajax);
|
||||
|
||||
$controller->doAction($actionName, $args);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $controllerName
|
||||
* @param bool $ajax
|
||||
*
|
||||
* @return AbstractController
|
||||
*/
|
||||
protected function getController($controllerName, $ajax = false) {
|
||||
|
||||
$methodName = 'getController' . ($ajax ? 'Ajax' : '') . $controllerName;
|
||||
|
||||
if (method_exists($this, $methodName)) {
|
||||
|
||||
return call_user_func(array(
|
||||
$this,
|
||||
$methodName
|
||||
));
|
||||
} else if (isset($this->externalControllers[$controllerName])) {
|
||||
|
||||
return call_user_func(array(
|
||||
$this->externalControllers[$controllerName],
|
||||
$methodName
|
||||
));
|
||||
}
|
||||
|
||||
return $this->getDefaultController($controllerName, $ajax);
|
||||
}
|
||||
|
||||
protected abstract function getDefaultController($controllerName, $ajax = false);
|
||||
|
||||
public function getApplication() {
|
||||
|
||||
return $this->application;
|
||||
}
|
||||
|
||||
public function getApplicationType() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Router
|
||||
*/
|
||||
public function getRouter() {
|
||||
return $this->router;
|
||||
}
|
||||
|
||||
public function enqueueAssets() {
|
||||
|
||||
$this->application->enqueueAssets();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AbstractLayout $layout
|
||||
*/
|
||||
public function setLayout($layout) {
|
||||
$this->layout = $layout;
|
||||
}
|
||||
|
||||
public function addExternalController($name, $source) {
|
||||
|
||||
$this->externalControllers[$name] = $source;
|
||||
}
|
||||
|
||||
public function getLogo() {
|
||||
|
||||
return file_get_contents(self::getAssetsPath() . '/images/logo.svg');
|
||||
}
|
||||
}
|
@ -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() {
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Browse\Block\BrowseManager;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\Js\Js;
|
||||
use Nextend\Framework\View\AbstractBlock;
|
||||
use Nextend\SmartSlider3\Application\Admin\TraitAdminUrl;
|
||||
|
||||
class BlockBrowseManager extends AbstractBlock {
|
||||
|
||||
use TraitAdminUrl;
|
||||
|
||||
public function display() {
|
||||
|
||||
Js::addFirstCode("new _N2.NextendBrowse('" . $this->getAjaxUrlBrowse() . "', " . (defined('N2_IMAGE_UPLOAD_DISABLE') ? 0 : 1) . ");");
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Browse;
|
||||
|
||||
|
||||
use Nextend\Framework\Browse\Block\BrowseManager\BlockBrowseManager;
|
||||
use Nextend\Framework\Pattern\VisualManagerTrait;
|
||||
|
||||
class BrowseManager {
|
||||
|
||||
use VisualManagerTrait;
|
||||
|
||||
public function display() {
|
||||
|
||||
$fontManagerBlock = new BlockBrowseManager($this->MVCHelper);
|
||||
$fontManagerBlock->display();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,388 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Browse\BulletProof;
|
||||
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
use Nextend\Framework\Image\ImageEdit;
|
||||
use Nextend\Framework\Request\Request;
|
||||
|
||||
/**
|
||||
* BULLETPROOF,
|
||||
*
|
||||
* This is a one-file solution for a quick and safe way of
|
||||
* uploading, watermarking, cropping and resizing images
|
||||
* during and after uploads with PHP with best security.
|
||||
*
|
||||
* This class is heavily commented, to be as much friendly as possible.
|
||||
* Please help out by posting out some bugs/flaws if you encounter any. Thanks!
|
||||
*
|
||||
* @category Image uploader
|
||||
* @package BulletProof
|
||||
* @version 1.4.0
|
||||
* @author samayo
|
||||
* @link https://github.com/samayo/BulletProof
|
||||
* @license Luke 3:11 ( Free )
|
||||
*/
|
||||
class BulletProof {
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Image Upload Properties
|
||||
\--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Set a group of default image types to upload.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $imageType = array(
|
||||
"jpg",
|
||||
"jpeg",
|
||||
"png",
|
||||
"gif",
|
||||
"webp",
|
||||
"svg"
|
||||
);
|
||||
|
||||
/**
|
||||
* Set a default file size to upload. Values are in bytes. Remember: 1kb ~ 1000 bytes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $imageSize = array(
|
||||
"min" => 1,
|
||||
"max" => 20000000
|
||||
);
|
||||
|
||||
/**
|
||||
* Set a default min & maximum height & width for image to upload.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $imageDimension = array(
|
||||
"height" => 10000,
|
||||
"width" => 10000
|
||||
);
|
||||
|
||||
/**
|
||||
* Set a default folder to upload images, if it does not exist, it will be created.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $uploadDir = "uploads";
|
||||
|
||||
/**
|
||||
* To get the real image/mime type. i.e gif, jpeg, png, ....
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $getMimeType;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Image Upload Methods
|
||||
\--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Stores image types to upload
|
||||
*
|
||||
* @param array $fileTypes - ex: ['jpg', 'doc', 'txt'].
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function fileTypes(array $fileTypes) {
|
||||
$this->imageType = $fileTypes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimum and Maximum allowed image size for upload (in bytes),
|
||||
*
|
||||
* @param array $fileSize - ex: ['min'=>500, 'max'=>1000]
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function limitSize(array $fileSize) {
|
||||
$this->imageSize = $fileSize;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default & maximum allowed height and width image to download.
|
||||
*
|
||||
* @param array $dimensions
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function limitDimension(array $dimensions) {
|
||||
$this->imageDimension = $dimensions;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the real image's Extension/mime type
|
||||
*
|
||||
* @param $imageName
|
||||
*
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function getMimeType($imageName) {
|
||||
if (!file_exists($imageName)) {
|
||||
throw new Exception("Image " . $imageName . " does not exist");
|
||||
}
|
||||
|
||||
$listOfMimeTypes = array(
|
||||
1 => "gif",
|
||||
"jpeg",
|
||||
"png",
|
||||
"swf",
|
||||
"psd",
|
||||
"bmp",
|
||||
"tiff",
|
||||
"tiff",
|
||||
"jpc",
|
||||
"jp2",
|
||||
"jpx",
|
||||
"jb2",
|
||||
"swc",
|
||||
"iff",
|
||||
"wbmp",
|
||||
"xmb",
|
||||
"ico",
|
||||
"webp",
|
||||
"svg"
|
||||
);
|
||||
|
||||
$imageType = ImageEdit::exif_imagetype($imageName);
|
||||
if (isset($listOfMimeTypes[$imageType])) {
|
||||
return $listOfMimeTypes[$imageType];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handy method for getting image dimensions (W & H) in pixels.
|
||||
*
|
||||
* @param $getImage - The image name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getPixels($getImage) {
|
||||
list($width, $height) = getImageSize($getImage);
|
||||
|
||||
return array(
|
||||
"width" => $width,
|
||||
"height" => $height
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename file either from method or by generating a random one.
|
||||
*
|
||||
* @param $isNameProvided - A new name for the file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function imageRename($isNameProvided) {
|
||||
if ($isNameProvided) {
|
||||
return $isNameProvided . "." . $this->getMimeType;
|
||||
}
|
||||
|
||||
return uniqid(true) . "_" . str_shuffle(implode(range("E", "Q"))) . "." . $this->getMimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified upload dir, if it does not exist, create a new one.
|
||||
*
|
||||
* @param $directoryName - directory name where you want your files to be uploaded
|
||||
*
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function uploadDir($directoryName) {
|
||||
if (!file_exists($directoryName) && !is_dir($directoryName)) {
|
||||
|
||||
$createFolder = Filesystem::createFolder("" . $directoryName);
|
||||
if (!$createFolder) {
|
||||
throw new Exception("Folder " . $directoryName . " could not be created");
|
||||
}
|
||||
}
|
||||
$this->uploadDir = $directoryName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* For getting common error messages from FILES[] array during upload.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function commonUploadErrors($key) {
|
||||
$uploadErrors = array(
|
||||
UPLOAD_ERR_OK => "...",
|
||||
UPLOAD_ERR_INI_SIZE => "File is larger than the specified amount set by the server",
|
||||
UPLOAD_ERR_FORM_SIZE => "File is larger than the specified amount specified by browser",
|
||||
UPLOAD_ERR_PARTIAL => "File could not be fully uploaded. Please try again later",
|
||||
UPLOAD_ERR_NO_FILE => "File is not found",
|
||||
UPLOAD_ERR_NO_TMP_DIR => "Can't write to disk, due to server configuration ( No tmp dir found )",
|
||||
UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk. Please check you file permissions",
|
||||
UPLOAD_ERR_EXTENSION => "A PHP extension has halted this file upload process"
|
||||
);
|
||||
|
||||
return $uploadErrors[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple file check and delete wrapper.
|
||||
*
|
||||
* @param $fileToDelete
|
||||
*
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function deleteFile($fileToDelete) {
|
||||
if (file_exists($fileToDelete) && !unlink($fileToDelete)) {
|
||||
throw new Exception("File may have been deleted or does not exist");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Final image uploader method, to check for errors and upload
|
||||
*
|
||||
* @param $fileToUpload
|
||||
* @param null $isNameProvided
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function upload($fileToUpload, $isNameProvided = null) {
|
||||
|
||||
$isMedia = false;
|
||||
// Check if any errors are thrown by the FILES[] array
|
||||
if ($fileToUpload["error"]) {
|
||||
throw new Exception($this->commonUploadErrors($fileToUpload["error"]));
|
||||
}
|
||||
|
||||
if (function_exists("mime_content_type")) {
|
||||
$rawMime = mime_content_type($fileToUpload["tmp_name"]);
|
||||
} else {
|
||||
if (!empty($fileToUpload['name'])) {
|
||||
$path_parts = pathinfo($fileToUpload['name']);
|
||||
switch ($path_parts['extension']) {
|
||||
case 'mp4':
|
||||
$rawMime = 'video/mp4';
|
||||
break;
|
||||
case 'mp3':
|
||||
$rawMime = 'audio/mpeg';
|
||||
break;
|
||||
default:
|
||||
$rawMime = '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ($rawMime) {
|
||||
case 'video/mp4':
|
||||
$this->getMimeType = 'mp4';
|
||||
$isMedia = true;
|
||||
break;
|
||||
case 'audio/mpeg':
|
||||
$this->getMimeType = 'mp3';
|
||||
$isMedia = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$isMedia) {
|
||||
// First get the real file extension
|
||||
$this->getMimeType = $this->getMimeType($fileToUpload["tmp_name"]);
|
||||
|
||||
$specialImage = false;
|
||||
if ($this->getMimeType === false) {
|
||||
if (isset($fileToUpload["type"]) && strpos($fileToUpload["type"], 'image/') !== false) {
|
||||
$this->getMimeType = str_replace(array(
|
||||
'image/',
|
||||
'svg+xml'
|
||||
), array(
|
||||
'',
|
||||
'svg'
|
||||
), $fileToUpload["type"]);
|
||||
$specialImage = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this file type is allowed for upload
|
||||
if (!in_array($this->getMimeType, $this->imageType)) {
|
||||
throw new Exception(" This is not allowed file type!
|
||||
Please only upload ( " . implode(", ", $this->imageType) . " ) file types");
|
||||
}
|
||||
|
||||
//Check if size (in bytes) of the image are above or below of defined in 'limitSize()'
|
||||
if ($fileToUpload["size"] < $this->imageSize["min"] || $fileToUpload["size"] > $this->imageSize["max"]) {
|
||||
throw new Exception("File sizes must be between " . implode(" to ", $this->imageSize) . " bytes");
|
||||
}
|
||||
|
||||
// check if image is valid pixel-wise.
|
||||
if (!$specialImage) {
|
||||
$pixel = $this->getPixels($fileToUpload["tmp_name"]);
|
||||
|
||||
if ($pixel["width"] < 4 || $pixel["height"] < 4) {
|
||||
throw new Exception("This file is either too small or corrupted to be an image");
|
||||
}
|
||||
|
||||
if ($pixel["height"] > $this->imageDimension["height"] || $pixel["width"] > $this->imageDimension["width"]) {
|
||||
throw new Exception("Image pixels/size must be below " . implode(", ", $this->imageDimension) . " pixels");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create upload directory if it does not exist
|
||||
$this->uploadDir($this->uploadDir);
|
||||
|
||||
$i = '';
|
||||
$newFileName = $this->imageRename($isNameProvided);
|
||||
|
||||
while (file_exists($this->uploadDir . "/" . $newFileName)) {
|
||||
// The file already uploaded, nothing to do here
|
||||
if (self::isFilesIdentical($this->uploadDir . "/" . $newFileName, $fileToUpload["tmp_name"])) {
|
||||
return $this->uploadDir . "/" . $newFileName;
|
||||
}
|
||||
$i++;
|
||||
$newFileName = $this->imageRename($isNameProvided . $i);
|
||||
}
|
||||
|
||||
// Upload the file
|
||||
$moveUploadedFile = $this->moveUploadedFile($fileToUpload["tmp_name"], $this->uploadDir . "/" . $newFileName);
|
||||
|
||||
if ($moveUploadedFile) {
|
||||
return $this->uploadDir . "/" . $newFileName;
|
||||
} else {
|
||||
throw new Exception(" File could not be uploaded. Unknown error occurred. ");
|
||||
}
|
||||
}
|
||||
|
||||
public function moveUploadedFile($uploaded_file, $new_file) {
|
||||
if (!is_uploaded_file($uploaded_file)) {
|
||||
return copy($uploaded_file, $new_file);
|
||||
}
|
||||
|
||||
return move_uploaded_file($uploaded_file, $new_file);
|
||||
}
|
||||
|
||||
private static function isFilesIdentical($fn1, $fn2) {
|
||||
if (filetype($fn1) !== filetype($fn2)) return FALSE;
|
||||
|
||||
if (filesize($fn1) !== filesize($fn2)) return FALSE;
|
||||
|
||||
if (sha1_file($fn1) != sha1_file($fn2)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Browse\BulletProof;
|
||||
|
||||
|
||||
class Exception extends \Exception {
|
||||
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Browse;
|
||||
|
||||
use Exception;
|
||||
use Nextend\Framework\Browse\BulletProof\BulletProof;
|
||||
use Nextend\Framework\Controller\Admin\AdminAjaxController;
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
use Nextend\Framework\Image\Image;
|
||||
use Nextend\Framework\Notification\Notification;
|
||||
use Nextend\Framework\Request\Request;
|
||||
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
|
||||
|
||||
class ControllerAjaxBrowse extends AdminAjaxController {
|
||||
|
||||
public function actionIndex() {
|
||||
$this->validateToken();
|
||||
$root = Filesystem::convertToRealDirectorySeparator(Filesystem::getImagesFolder());
|
||||
$path = Filesystem::realpath($root . '/' . ltrim(rtrim(Request::$REQUEST->getVar('path', ''), '/'), '/'));
|
||||
if (strpos($path, $root) !== 0) {
|
||||
$path = $root;
|
||||
}
|
||||
$_directories = glob($path . '/*', GLOB_ONLYDIR);
|
||||
$directories = array();
|
||||
for ($i = 0; $i < count($_directories); $i++) {
|
||||
$directories[basename($_directories[$i])] = Filesystem::toLinux($this->relative($_directories[$i], $root));
|
||||
}
|
||||
|
||||
$extensions = array(
|
||||
'jpg',
|
||||
'jpeg',
|
||||
'png',
|
||||
'gif',
|
||||
'mp4',
|
||||
'mp3',
|
||||
'svg',
|
||||
'webp'
|
||||
);
|
||||
$_files = scandir($path);
|
||||
$files = array();
|
||||
for ($i = 0; $i < count($_files); $i++) {
|
||||
$_files[$i] = $path . DIRECTORY_SEPARATOR . $_files[$i];
|
||||
$ext = strtolower(pathinfo($_files[$i], PATHINFO_EXTENSION));
|
||||
if (self::check_utf8($_files[$i]) && in_array($ext, $extensions)) {
|
||||
$files[basename($_files[$i])] = ResourceTranslator::urlToResource(Filesystem::pathToAbsoluteURL($_files[$i]));
|
||||
}
|
||||
}
|
||||
$relativePath = Filesystem::toLinux($this->relative($path, $root));
|
||||
if (!$relativePath) {
|
||||
$relativePath = '';
|
||||
}
|
||||
$this->response->respond(array(
|
||||
'fullPath' => $path,
|
||||
'path' => $relativePath,
|
||||
'directories' => (object)$directories,
|
||||
'files' => (object)$files
|
||||
));
|
||||
}
|
||||
|
||||
private static function check_utf8($str) {
|
||||
$len = strlen($str);
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$c = ord($str[$i]);
|
||||
if ($c > 128) {
|
||||
if (($c > 247)) return false; elseif ($c > 239) $bytes = 4;
|
||||
elseif ($c > 223) $bytes = 3;
|
||||
elseif ($c > 191) $bytes = 2;
|
||||
else return false;
|
||||
if (($i + $bytes) > $len) return false;
|
||||
while ($bytes > 1) {
|
||||
$i++;
|
||||
$b = ord($str[$i]);
|
||||
if ($b < 128 || $b > 191) return false;
|
||||
$bytes--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function actionUpload() {
|
||||
if (defined('N2_IMAGE_UPLOAD_DISABLE')) {
|
||||
Notification::error(n2_('You are not allowed to upload!'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
$this->validateToken();
|
||||
|
||||
$root = Filesystem::getImagesFolder();
|
||||
$folder = ltrim(rtrim(Request::$REQUEST->getVar('path', ''), '/'), '/');
|
||||
$path = Filesystem::realpath($root . '/' . $folder);
|
||||
|
||||
if ($path === false || $path == '') {
|
||||
$folder = preg_replace("/[^A-Za-z0-9]/", '', $folder);
|
||||
if (empty($folder)) {
|
||||
Notification::error(n2_('Folder is missing!'));
|
||||
$this->response->error();
|
||||
} else {
|
||||
Filesystem::createFolder($root . '/' . $folder);
|
||||
$path = Filesystem::realpath($root . '/' . $folder);
|
||||
}
|
||||
}
|
||||
|
||||
$relativePath = Filesystem::toLinux($this->relative($path, $root));
|
||||
if (!$relativePath) {
|
||||
$relativePath = '';
|
||||
}
|
||||
$response = array(
|
||||
'path' => $relativePath
|
||||
);
|
||||
try {
|
||||
$image = Request::$FILES->getVar('image');
|
||||
if ($image['name'] !== null) {
|
||||
$info = pathinfo($image['name']);
|
||||
$fileName = preg_replace('/[^a-zA-Z0-9_-]/', '', $info['filename']);
|
||||
if (strlen($fileName) == 0) {
|
||||
$fileName = '';
|
||||
}
|
||||
|
||||
$upload = new BulletProof();
|
||||
$file = $upload->uploadDir($path)
|
||||
->upload($image, $fileName);
|
||||
$response['name'] = basename($file);
|
||||
$response['url'] = ResourceTranslator::urlToResource(Filesystem::pathToAbsoluteURL($file));
|
||||
|
||||
Image::onImageUploaded($file);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Notification::error($e->getMessage());
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
|
||||
$this->response->respond($response);
|
||||
}
|
||||
|
||||
private function relative($path, $root) {
|
||||
return substr(Filesystem::convertToRealDirectorySeparator($path), strlen($root));
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Cache;
|
||||
|
||||
|
||||
use Nextend\Framework\Cache\Storage\AbstractStorage;
|
||||
|
||||
abstract class AbstractCache {
|
||||
|
||||
protected $group = '';
|
||||
protected $isAccessible = false;
|
||||
|
||||
/** @var AbstractStorage */
|
||||
public $storage;
|
||||
|
||||
protected $_storageEngine = 'filesystem';
|
||||
|
||||
/**
|
||||
* @param string $engine
|
||||
*
|
||||
* @return AbstractStorage
|
||||
*/
|
||||
public static function getStorage($engine = "filesystem") {
|
||||
static $storage = null;
|
||||
if ($storage === null) {
|
||||
$storage = array(
|
||||
'filesystem' => new Storage\Filesystem(),
|
||||
'database' => new Storage\Database()
|
||||
);
|
||||
}
|
||||
|
||||
return $storage[$engine];
|
||||
}
|
||||
|
||||
public static function clearAll() {
|
||||
self::getStorage('filesystem')
|
||||
->clearAll();
|
||||
self::getStorage('filesystem')
|
||||
->clearAll('web');
|
||||
}
|
||||
|
||||
public static function clearGroup($group) {
|
||||
self::getStorage('filesystem')
|
||||
->clear($group);
|
||||
self::getStorage('filesystem')
|
||||
->clear($group, 'web');
|
||||
self::getStorage('database')
|
||||
->clear($group);
|
||||
self::getStorage('database')
|
||||
->clear($group, 'web');
|
||||
}
|
||||
|
||||
public function __construct($group, $isAccessible = false) {
|
||||
$this->group = $group;
|
||||
$this->isAccessible = $isAccessible;
|
||||
$this->storage = self::getStorage($this->_storageEngine);
|
||||
}
|
||||
|
||||
protected function clearCurrentGroup() {
|
||||
$this->storage->clear($this->group, $this->getScope());
|
||||
}
|
||||
|
||||
protected function getScope() {
|
||||
if ($this->isAccessible) {
|
||||
return 'web';
|
||||
}
|
||||
|
||||
return 'notweb';
|
||||
}
|
||||
|
||||
protected function exists($key) {
|
||||
return $this->storage->exists($this->group, $key, $this->getScope());
|
||||
}
|
||||
|
||||
protected function get($key) {
|
||||
return $this->storage->get($this->group, $key, $this->getScope());
|
||||
}
|
||||
|
||||
protected function set($key, $value) {
|
||||
$this->storage->set($this->group, $key, $value, $this->getScope());
|
||||
}
|
||||
|
||||
protected function getPath($key) {
|
||||
return $this->storage->getPath($this->group, $key, $this->getScope());
|
||||
}
|
||||
|
||||
protected function remove($key) {
|
||||
return $this->storage->remove($this->group, $key, $this->getScope());
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Cache;
|
||||
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
use Nextend\Framework\Misc\HttpClient;
|
||||
|
||||
class CacheGoogleFont extends AbstractCache {
|
||||
|
||||
protected $_storageEngine = 'filesystem';
|
||||
private $fontExtension;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('googlefonts', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return boolean|string The path of the cached file
|
||||
*/
|
||||
public function makeCache($url, $extension) {
|
||||
|
||||
$hash = $this->generateHash($url);
|
||||
|
||||
$fileName = $hash;
|
||||
$fileNameWithExtension = $fileName . '.' . $extension;
|
||||
|
||||
$isCached = $this->exists($fileNameWithExtension);
|
||||
|
||||
if ($isCached) {
|
||||
if (!$this->testManifestFile($fileName)) {
|
||||
$isCached = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isCached) {
|
||||
|
||||
$cssContent = HttpClient::get($url);
|
||||
|
||||
if (!$cssContent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($extension === 'css') {
|
||||
$fontExtensions = array(
|
||||
'woff2',
|
||||
'ttf'
|
||||
);
|
||||
|
||||
foreach ($fontExtensions as $this->fontExtension) {
|
||||
$cssContent = preg_replace_callback('/url\(["\']?(.*?\.' . $this->fontExtension . ')["\']?\)/i', function ($matches) {
|
||||
|
||||
$url = $matches[1];
|
||||
|
||||
$cache = new CacheGoogleFont();
|
||||
|
||||
$path = $cache->makeCache($url, $this->fontExtension);
|
||||
|
||||
if ($path) {
|
||||
$url = Filesystem::pathToAbsoluteURL($path);
|
||||
}
|
||||
|
||||
return 'url(' . $url . ')';
|
||||
}, $cssContent);
|
||||
}
|
||||
}
|
||||
|
||||
$this->set($fileNameWithExtension, $cssContent);
|
||||
|
||||
$this->createManifestFile($fileName);
|
||||
}
|
||||
|
||||
return $this->getPath($fileNameWithExtension);
|
||||
}
|
||||
|
||||
private function generateHash($url) {
|
||||
return md5($url);
|
||||
}
|
||||
|
||||
protected function testManifestFile($fileName) {
|
||||
$manifestKey = $this->getManifestKey($fileName);
|
||||
if ($this->exists($manifestKey)) {
|
||||
|
||||
$manifestData = json_decode($this->get($manifestKey), true);
|
||||
|
||||
if ($manifestData['mtime'] > strtotime('-30 days')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function createManifestFile($fileName) {
|
||||
|
||||
$this->set($this->getManifestKey($fileName), json_encode($this->getManifestData()));
|
||||
}
|
||||
|
||||
private function getManifestData() {
|
||||
|
||||
return array(
|
||||
'mtime' => time()
|
||||
);
|
||||
}
|
||||
|
||||
protected function getManifestKey($fileName) {
|
||||
return $fileName . '.manifest';
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Cache;
|
||||
|
||||
use DateTime;
|
||||
|
||||
class CacheImage extends AbstractCache {
|
||||
|
||||
protected $_storageEngine = 'filesystem';
|
||||
|
||||
protected $lazy = false;
|
||||
|
||||
public function __construct($group) {
|
||||
parent::__construct($group, true);
|
||||
}
|
||||
|
||||
protected function getScope() {
|
||||
return 'image';
|
||||
}
|
||||
|
||||
public function setLazy($lazy) {
|
||||
$this->lazy = $lazy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $fileExtension
|
||||
* @param callable $callable
|
||||
* @param array $parameters
|
||||
* @param bool $hash
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function makeCache($fileExtension, $callable, $parameters = array(), $hash = false) {
|
||||
|
||||
if (!$hash) {
|
||||
$hash = $this->generateHash($fileExtension, $callable, $parameters);
|
||||
}
|
||||
|
||||
if (strpos($parameters[1], '?') !== false) {
|
||||
$fileNameParts = explode('?', $parameters[1]);
|
||||
$keepFileName = pathinfo($fileNameParts[0], PATHINFO_FILENAME);
|
||||
} else {
|
||||
$keepFileName = pathinfo($parameters[1], PATHINFO_FILENAME);
|
||||
}
|
||||
|
||||
$fileName = $hash . (!empty($keepFileName) ? '/' . $keepFileName : '');
|
||||
$fileNameWithExtension = $fileName . '.' . $fileExtension;
|
||||
|
||||
$isCached = $this->exists($fileNameWithExtension);
|
||||
if ($isCached) {
|
||||
if (!$this->testManifestFile($fileName, $parameters[1])) {
|
||||
$isCached = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isCached) {
|
||||
if ($this->lazy) {
|
||||
return $parameters[1];
|
||||
}
|
||||
|
||||
array_unshift($parameters, $this->getPath($fileNameWithExtension));
|
||||
call_user_func_array($callable, $parameters);
|
||||
|
||||
$this->createManifestFile($fileName, $parameters[2]);
|
||||
}
|
||||
|
||||
return $this->getPath($fileNameWithExtension);
|
||||
}
|
||||
|
||||
private function generateHash($fileExtension, $callable, $parameters) {
|
||||
return md5(json_encode(array(
|
||||
$fileExtension,
|
||||
$callable,
|
||||
$parameters
|
||||
)));
|
||||
}
|
||||
|
||||
protected function testManifestFile($fileName, $originalFile) {
|
||||
$manifestKey = $this->getManifestKey($fileName);
|
||||
if ($this->exists($manifestKey)) {
|
||||
|
||||
$manifestData = json_decode($this->get($manifestKey), true);
|
||||
|
||||
$newManifestData = $this->getManifestData($originalFile);
|
||||
if ($manifestData['mtime'] == $newManifestData['mtime']) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Backward compatibility
|
||||
$this->createManifestFile($fileName, $originalFile);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function createManifestFile($fileName, $originalFile) {
|
||||
|
||||
$this->set($this->getManifestKey($fileName), json_encode($this->getManifestData($originalFile)));
|
||||
}
|
||||
|
||||
private function getManifestData($originalFile) {
|
||||
$manifestData = array();
|
||||
if (strpos($originalFile, '//') !== false) {
|
||||
$manifestData['mtime'] = $this->getRemoteMTime($originalFile);
|
||||
} else {
|
||||
$manifestData['mtime'] = filemtime($originalFile);
|
||||
}
|
||||
|
||||
return $manifestData;
|
||||
}
|
||||
|
||||
private function getRemoteMTime($url) {
|
||||
if (ini_get('allow_url_fopen')) {
|
||||
$h = get_headers($url, 1);
|
||||
if (!$h || strpos($h[0], '200') !== false) {
|
||||
foreach ($h as $k => $v) {
|
||||
if (strtolower(trim($k)) == "last-modified") {
|
||||
return (new DateTime($v))->getTimestamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function getManifestKey($fileName) {
|
||||
return $fileName . '.manifest';
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Cache;
|
||||
|
||||
class Manifest extends AbstractCache {
|
||||
|
||||
private $isRaw = false;
|
||||
|
||||
private $manifestData;
|
||||
|
||||
public function __construct($group, $isAccessible = false, $isRaw = false) {
|
||||
parent::__construct($group, $isAccessible);
|
||||
$this->isRaw = $isRaw;
|
||||
}
|
||||
|
||||
protected function decode($data) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $fileName
|
||||
* @param $hash
|
||||
* @param callback $callable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function makeCache($fileName, $hash, $callable) {
|
||||
if (!$this->isCached($fileName, $hash)) {
|
||||
|
||||
$return = call_user_func($callable, $this);
|
||||
if ($return === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->createCacheFile($fileName, $hash, $return);
|
||||
}
|
||||
if ($this->isAccessible) {
|
||||
return $this->getPath($fileName);
|
||||
}
|
||||
|
||||
return $this->decode($this->get($fileName));
|
||||
}
|
||||
|
||||
private function isCached($fileName, $hash) {
|
||||
|
||||
|
||||
$manifestKey = $this->getManifestKey($fileName);
|
||||
if ($this->exists($manifestKey)) {
|
||||
|
||||
$this->manifestData = json_decode($this->get($manifestKey), true);
|
||||
|
||||
if (!$this->isCacheValid($this->manifestData) || $this->manifestData['hash'] != $hash || !$this->exists($fileName)) {
|
||||
$this->clean($fileName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function createCacheFile($fileName, $hash, $content) {
|
||||
|
||||
$this->manifestData = array();
|
||||
|
||||
$this->manifestData['hash'] = $hash;
|
||||
$this->addManifestData($this->manifestData);
|
||||
|
||||
$this->set($this->getManifestKey($fileName), json_encode($this->manifestData));
|
||||
|
||||
$this->set($fileName, $this->isRaw ? $content : json_encode($content));
|
||||
|
||||
if ($this->isAccessible) {
|
||||
return $this->getPath($fileName);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
protected function isCacheValid(&$manifestData) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function addManifestData(&$manifestData) {
|
||||
|
||||
}
|
||||
|
||||
public function clean($fileName) {
|
||||
|
||||
$this->remove($this->getManifestKey($fileName));
|
||||
$this->remove($fileName);
|
||||
}
|
||||
|
||||
protected function getManifestKey($fileName) {
|
||||
return $fileName . '.manifest';
|
||||
}
|
||||
|
||||
public function getData($key, $default = 0) {
|
||||
return isset($this->manifestData[$key]) ? $this->manifestData[$key] : $default;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Cache\Storage;
|
||||
|
||||
|
||||
abstract class AbstractStorage {
|
||||
|
||||
protected $paths = array();
|
||||
|
||||
public function isFilesystem() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract function clearAll($scope = 'notweb');
|
||||
|
||||
public abstract function clear($group, $scope = 'notweb');
|
||||
|
||||
public abstract function exists($group, $key, $scope = 'notweb');
|
||||
|
||||
public abstract function set($group, $key, $value, $scope = 'notweb');
|
||||
|
||||
public abstract function get($group, $key, $scope = 'notweb');
|
||||
|
||||
public abstract function remove($group, $key, $scope = 'notweb');
|
||||
|
||||
public abstract function getPath($group, $key, $scope = 'notweb');
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Cache\Storage;
|
||||
|
||||
use Nextend\Framework\Model\ApplicationSection;
|
||||
use Nextend\Framework\Platform\Platform;
|
||||
|
||||
class Database extends AbstractStorage {
|
||||
|
||||
protected $db;
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$this->paths['web'] = 'web';
|
||||
$this->paths['notweb'] = 'notweb';
|
||||
$this->paths['image'] = 'image';
|
||||
|
||||
$this->db = new ApplicationSection('cache');
|
||||
}
|
||||
|
||||
public function clearAll($scope = 'notweb') {
|
||||
|
||||
}
|
||||
|
||||
public function clear($group, $scope = 'notweb') {
|
||||
|
||||
$this->db->delete($scope . '/' . $group);
|
||||
}
|
||||
|
||||
public function exists($group, $key, $scope = 'notweb') {
|
||||
|
||||
if ($this->db->get($scope . '/' . $group, $key)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function set($group, $key, $value, $scope = 'notweb') {
|
||||
|
||||
$this->db->set($scope . '/' . $group, $key, $value);
|
||||
}
|
||||
|
||||
public function get($group, $key, $scope = 'notweb') {
|
||||
return $this->db->get($scope . '/' . $group, $key);
|
||||
}
|
||||
|
||||
public function remove($group, $key, $scope = 'notweb') {
|
||||
$this->db->delete($scope . '/' . $group, $key);
|
||||
}
|
||||
|
||||
public function getPath($group, $key, $scope = 'notweb') {
|
||||
|
||||
return Platform::getSiteUrl() . '?nextendcache=1&g=' . urlencode($group) . '&k=' . urlencode($key);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Cache\Storage;
|
||||
|
||||
|
||||
class Filesystem extends AbstractStorage {
|
||||
|
||||
public function __construct() {
|
||||
$this->paths['web'] = \Nextend\Framework\Filesystem\Filesystem::getWebCachePath();
|
||||
$this->paths['notweb'] = \Nextend\Framework\Filesystem\Filesystem::getNotWebCachePath();
|
||||
$this->paths['image'] = \Nextend\Framework\Filesystem\Filesystem::getImagesFolder();
|
||||
}
|
||||
|
||||
public function isFilesystem() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function clearAll($scope = 'notweb') {
|
||||
if (\Nextend\Framework\Filesystem\Filesystem::existsFolder($this->paths[$scope])) {
|
||||
\Nextend\Framework\Filesystem\Filesystem::deleteFolder($this->paths[$scope]);
|
||||
}
|
||||
}
|
||||
|
||||
public function clear($group, $scope = 'notweb') {
|
||||
|
||||
if (\Nextend\Framework\Filesystem\Filesystem::existsFolder($this->paths[$scope] . '/' . $group)) {
|
||||
\Nextend\Framework\Filesystem\Filesystem::deleteFolder($this->paths[$scope] . '/' . $group);
|
||||
}
|
||||
}
|
||||
|
||||
public function exists($group, $key, $scope = 'notweb') {
|
||||
if (\Nextend\Framework\Filesystem\Filesystem::existsFile($this->paths[$scope] . '/' . $group . '/' . $key)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function set($group, $key, $value, $scope = 'notweb') {
|
||||
$path = $this->paths[$scope] . '/' . $group . '/' . $key;
|
||||
$dir = dirname($path);
|
||||
if (!\Nextend\Framework\Filesystem\Filesystem::existsFolder($dir)) {
|
||||
\Nextend\Framework\Filesystem\Filesystem::createFolder($dir);
|
||||
}
|
||||
\Nextend\Framework\Filesystem\Filesystem::createFile($path, $value);
|
||||
}
|
||||
|
||||
public function get($group, $key, $scope = 'notweb') {
|
||||
return \Nextend\Framework\Filesystem\Filesystem::readFile($this->paths[$scope] . '/' . $group . '/' . $key);
|
||||
}
|
||||
|
||||
public function remove($group, $key, $scope = 'notweb') {
|
||||
if ($this->exists($group, $key, $scope)) {
|
||||
@unlink($this->paths[$scope] . '/' . $group . '/' . $key);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPath($group, $key, $scope = 'notweb') {
|
||||
return $this->paths[$scope] . DIRECTORY_SEPARATOR . $group . DIRECTORY_SEPARATOR . $key;
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Cache;
|
||||
|
||||
class StoreImage extends AbstractCache {
|
||||
|
||||
protected $_storageEngine = 'filesystem';
|
||||
|
||||
protected function getScope() {
|
||||
return 'image';
|
||||
}
|
||||
|
||||
public function makeCache($fileName, $content) {
|
||||
if (!$this->isImage($fileName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->exists($fileName)) {
|
||||
$this->set($fileName, $content);
|
||||
}
|
||||
|
||||
return $this->getPath($fileName);
|
||||
}
|
||||
|
||||
private function isImage($fileName) {
|
||||
$supported_image = array(
|
||||
'gif',
|
||||
'jpg',
|
||||
'jpeg',
|
||||
'png',
|
||||
'mp4',
|
||||
'mp3',
|
||||
'webp',
|
||||
'svg'
|
||||
);
|
||||
|
||||
$ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
||||
if (in_array($ext, $supported_image)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
18
wp-content/plugins/smart-slider-3/Nextend/Framework/Cast.php
Normal file
18
wp-content/plugins/smart-slider-3/Nextend/Framework/Cast.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework;
|
||||
|
||||
|
||||
class Cast {
|
||||
|
||||
/**
|
||||
* @param $number
|
||||
*
|
||||
* @return string the JavaScript float representation of the string
|
||||
*/
|
||||
public static function floatToString($number) {
|
||||
|
||||
return json_encode(floatval($number));
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Content;
|
||||
|
||||
abstract class AbstractPlatformContent {
|
||||
|
||||
/**
|
||||
* @param $keyword
|
||||
*
|
||||
* @return array links
|
||||
* $links[] = array(
|
||||
* 'title' => '',
|
||||
* 'link' => '',
|
||||
* 'info' => ''
|
||||
* );
|
||||
*/
|
||||
abstract public function searchLink($keyword);
|
||||
|
||||
|
||||
/**
|
||||
* @param $keyword
|
||||
*
|
||||
* @return array links
|
||||
* $links[] = array(
|
||||
* 'title' => '',
|
||||
* 'description' => '',
|
||||
* 'image' => '',
|
||||
* 'link' => '',
|
||||
* 'info' => ''
|
||||
* );
|
||||
*/
|
||||
abstract public function searchContent($keyword);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Content;
|
||||
|
||||
use Nextend\Framework\Content\Joomla\JoomlaContent;
|
||||
use Nextend\Framework\Content\WordPress\WordPressContent;
|
||||
|
||||
class Content {
|
||||
|
||||
/**
|
||||
* @var AbstractPlatformContent
|
||||
*/
|
||||
private static $platformContent;
|
||||
|
||||
public function __construct() {
|
||||
self::$platformContent = new WordPressContent();
|
||||
}
|
||||
|
||||
public static function searchLink($keyword) {
|
||||
return self::$platformContent->searchLink($keyword);
|
||||
}
|
||||
|
||||
public static function searchContent($keyword) {
|
||||
return self::$platformContent->searchContent($keyword);
|
||||
}
|
||||
}
|
||||
|
||||
new Content();
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Content;
|
||||
|
||||
|
||||
use Nextend\Framework\Controller\Admin\AdminAjaxController;
|
||||
use Nextend\Framework\Request\Request;
|
||||
|
||||
class ControllerAjaxContent extends AdminAjaxController {
|
||||
|
||||
public function actionSearchLink() {
|
||||
$this->validateToken();
|
||||
|
||||
$keyword = Request::$REQUEST->getVar('keyword', '');
|
||||
$this->response->respond(Content::searchLink($keyword));
|
||||
}
|
||||
|
||||
public function actionSearchContent() {
|
||||
$this->validateToken();
|
||||
|
||||
$keyword = Request::$REQUEST->getVar('keyword', '');
|
||||
$this->response->respond(Content::searchContent($keyword));
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Content\WordPress;
|
||||
|
||||
use Nextend\Framework\Content\AbstractPlatformContent;
|
||||
use WP_Query;
|
||||
use function get_post_thumbnail_id;
|
||||
use function get_post_type;
|
||||
use function get_post_type_object;
|
||||
use function get_the_excerpt;
|
||||
use function get_the_ID;
|
||||
use function get_the_permalink;
|
||||
use function get_the_title;
|
||||
use function wp_get_attachment_url;
|
||||
|
||||
class WordPressContent extends AbstractPlatformContent {
|
||||
|
||||
public function searchLink($keyword) {
|
||||
|
||||
$the_query = new WP_Query('post_type=any&posts_per_page=20&post_status=publish&s=' . $keyword);
|
||||
|
||||
$links = array();
|
||||
if ($the_query->have_posts()) {
|
||||
while ($the_query->have_posts()) {
|
||||
$the_query->the_post();
|
||||
|
||||
$link = array(
|
||||
'title' => get_the_title(),
|
||||
'link' => get_the_permalink(),
|
||||
'info' => get_post_type_object(get_post_type())->labels->singular_name
|
||||
);
|
||||
|
||||
$links[] = $link;
|
||||
|
||||
}
|
||||
}
|
||||
/* Restore original Post Data */
|
||||
wp_reset_postdata();
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
public function searchContent($keyword) {
|
||||
|
||||
$the_query = new WP_Query('post_type=any&posts_per_page=20&post_status=publish&s=' . $keyword);
|
||||
|
||||
$links = array();
|
||||
if ($the_query->have_posts()) {
|
||||
while ($the_query->have_posts()) {
|
||||
$the_query->the_post();
|
||||
|
||||
$link = array(
|
||||
'title' => get_the_title(),
|
||||
'description' => get_the_excerpt(),
|
||||
'image' => wp_get_attachment_url(get_post_thumbnail_id(get_the_ID())),
|
||||
'link' => get_the_permalink(),
|
||||
'info' => get_post_type_object(get_post_type())->labels->singular_name
|
||||
);
|
||||
|
||||
$links[] = $link;
|
||||
|
||||
}
|
||||
}
|
||||
/* Restore original Post Data */
|
||||
wp_reset_postdata();
|
||||
|
||||
return $links;
|
||||
}
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Controller;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Nextend\Framework\Acl\Acl;
|
||||
use Nextend\Framework\Application\AbstractApplication;
|
||||
use Nextend\Framework\Application\AbstractApplicationType;
|
||||
use Nextend\Framework\Asset\AssetManager;
|
||||
use Nextend\Framework\Asset\Predefined;
|
||||
use Nextend\Framework\Form\Form;
|
||||
use Nextend\Framework\Notification\Notification;
|
||||
use Nextend\Framework\Pattern\GetPathTrait;
|
||||
use Nextend\Framework\Pattern\MVCHelperTrait;
|
||||
use Nextend\Framework\Plugin;
|
||||
use Nextend\Framework\Request\Request;
|
||||
use Nextend\SmartSlider3\Application\ApplicationSmartSlider3;
|
||||
|
||||
abstract class AbstractController {
|
||||
|
||||
use GetPathTrait;
|
||||
use MVCHelperTrait;
|
||||
|
||||
/**
|
||||
* @var AbstractApplicationType
|
||||
*/
|
||||
protected $applicationType;
|
||||
|
||||
/** @var callback[] */
|
||||
protected $externalActions = array();
|
||||
|
||||
/**
|
||||
* AbstractController constructor.
|
||||
*
|
||||
* @param AbstractApplicationType $applicationType
|
||||
*/
|
||||
public function __construct($applicationType) {
|
||||
|
||||
//PluggableController\Nextend\SmartSlider3\Application\Admin\Slider\ControllerSlider
|
||||
Plugin::doAction('PluggableController\\' . get_class($this), array($this));
|
||||
|
||||
|
||||
$this->applicationType = $applicationType;
|
||||
$this->setMVCHelper($this->applicationType);
|
||||
|
||||
AssetManager::getInstance();
|
||||
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $actionName
|
||||
* @param callback $callable
|
||||
*/
|
||||
public function addExternalAction($actionName, $callable) {
|
||||
|
||||
$this->externalActions[$actionName] = $callable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractApplication
|
||||
*/
|
||||
public function getApplication() {
|
||||
return $this->applicationType->getApplication();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractApplicationType
|
||||
*/
|
||||
public function getApplicationType() {
|
||||
return $this->applicationType;
|
||||
}
|
||||
|
||||
public function getRouter() {
|
||||
return $this->applicationType->getRouter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $actionName
|
||||
* @param array $args
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
final public function doAction($actionName, $args = array()) {
|
||||
|
||||
$originalActionName = $actionName;
|
||||
|
||||
if (method_exists($this, 'action' . $actionName)) {
|
||||
|
||||
call_user_func_array(array(
|
||||
$this,
|
||||
'action' . $actionName
|
||||
), $args);
|
||||
|
||||
} else if (isset($this->externalActions[$actionName]) && is_callable($this->externalActions[$actionName])) {
|
||||
|
||||
call_user_func_array($this->externalActions[$actionName], $args);
|
||||
|
||||
} else {
|
||||
|
||||
$actionName = $this->missingAction($this, $actionName);
|
||||
|
||||
if (method_exists($this, 'action' . $actionName)) {
|
||||
|
||||
call_user_func_array(array(
|
||||
$this,
|
||||
'action' . $actionName
|
||||
), $args);
|
||||
|
||||
} else {
|
||||
throw new Exception(sprintf('Missing action (%s) for controller (%s)', $originalActionName, static::class));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected function missingAction($controllerName, $actionName) {
|
||||
|
||||
return 'index';
|
||||
}
|
||||
|
||||
public function initialize() {
|
||||
Predefined::frontend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check ACL permissions
|
||||
*
|
||||
* @param $action
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canDo($action) {
|
||||
return Acl::canDo($action, $this);
|
||||
}
|
||||
|
||||
public function redirect($url, $statusCode = 302, $terminate = true) {
|
||||
Request::redirect($url, $statusCode, $terminate);
|
||||
}
|
||||
|
||||
public function validatePermission($permission) {
|
||||
|
||||
if (!$this->canDo($permission)) {
|
||||
Notification::error(n2_('You are not authorised to view this resource.'));
|
||||
|
||||
ApplicationSmartSlider3::getInstance()
|
||||
->getApplicationTypeAdmin()
|
||||
->process('sliders', 'index');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validateVariable($condition, $property) {
|
||||
|
||||
if (!$condition) {
|
||||
Notification::error(sprintf(n2_('Missing parameter: %s'), $property));
|
||||
|
||||
ApplicationSmartSlider3::getInstance()
|
||||
->getApplicationTypeAdmin()
|
||||
->process('sliders', 'index');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validateDatabase($condition, $showError = true) {
|
||||
if (!$condition) {
|
||||
if ($showError) {
|
||||
Notification::error(n2_('Database error'));
|
||||
|
||||
ApplicationSmartSlider3::getInstance()
|
||||
->getApplicationTypeAdmin()
|
||||
->process('sliders', 'index');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validateToken() {
|
||||
if (!Form::checkToken()) {
|
||||
Notification::error(n2_('Security token mismatch'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Controller\Admin;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\Js\Js;
|
||||
use Nextend\Framework\Asset\Predefined;
|
||||
use Nextend\Framework\Controller\AbstractController;
|
||||
|
||||
abstract class AbstractAdminController extends AbstractController {
|
||||
|
||||
public function initialize() {
|
||||
// Prevent browser from cache on backward button.
|
||||
header("Cache-Control: no-store");
|
||||
|
||||
Js::addGlobalInline('window.N2DISABLESCHEDULER=1;');
|
||||
|
||||
parent::initialize();
|
||||
|
||||
Predefined::frontend();
|
||||
Predefined::backend();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Controller\Admin;
|
||||
|
||||
|
||||
use Nextend\Framework\Controller\AjaxController;
|
||||
|
||||
class AdminAjaxController extends AjaxController {
|
||||
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Controller\Admin;
|
||||
|
||||
use Nextend\Framework\Notification\Notification;
|
||||
use Nextend\Framework\Request\Request;
|
||||
use Nextend\Framework\Visual\ModelVisual;
|
||||
|
||||
abstract class AdminVisualManagerAjaxController extends AdminAjaxController {
|
||||
|
||||
protected $type = '';
|
||||
|
||||
/**
|
||||
* @return ModelVisual
|
||||
*/
|
||||
public abstract function getModel();
|
||||
|
||||
public function actionCreateSet() {
|
||||
$this->validateToken();
|
||||
|
||||
$this->validatePermission('smartslider_edit');
|
||||
|
||||
$name = Request::$REQUEST->getVar('name');
|
||||
$this->validateVariable(!empty($name), 'set name');
|
||||
|
||||
$model = $this->getModel();
|
||||
if (($set = $model->createSet($name))) {
|
||||
$this->response->respond(array(
|
||||
'set' => $set
|
||||
));
|
||||
}
|
||||
|
||||
Notification::error(n2_('Unexpected error'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
public function actionRenameSet() {
|
||||
$this->validateToken();
|
||||
|
||||
$this->validatePermission('smartslider_edit');
|
||||
|
||||
$setId = Request::$REQUEST->getInt('setId');
|
||||
$this->validateVariable($setId > 0, 'set');
|
||||
|
||||
$name = Request::$REQUEST->getVar('name');
|
||||
$this->validateVariable(!empty($name), 'set name');
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
if (($set = $model->renameSet($setId, $name))) {
|
||||
$this->response->respond(array(
|
||||
'set' => $set
|
||||
));
|
||||
}
|
||||
|
||||
Notification::error(n2_('Set is not editable'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
public function actionDeleteSet() {
|
||||
$this->validateToken();
|
||||
|
||||
$this->validatePermission('smartslider_delete');
|
||||
|
||||
$setId = Request::$REQUEST->getInt('setId');
|
||||
$this->validateVariable($setId > 0, 'set');
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
if (($set = $model->deleteSet($setId))) {
|
||||
$this->response->respond(array(
|
||||
'set' => $set
|
||||
));
|
||||
}
|
||||
|
||||
Notification::error(n2_('Set is not editable'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
public function actionLoadVisualsForSet() {
|
||||
$this->validateToken();
|
||||
|
||||
|
||||
$setId = Request::$REQUEST->getInt('setId');
|
||||
$this->validateVariable($setId > 0, 'set');
|
||||
|
||||
$model = $this->getModel();
|
||||
$visuals = $model->getVisuals($setId);
|
||||
if (is_array($visuals)) {
|
||||
$this->response->respond(array(
|
||||
'visuals' => $visuals
|
||||
));
|
||||
}
|
||||
|
||||
Notification::error(n2_('Unexpected error'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
public function actionLoadSetByVisualId() {
|
||||
$this->validateToken();
|
||||
|
||||
$visualId = Request::$REQUEST->getInt('visualId');
|
||||
$this->validateVariable($visualId > 0, 'visual');
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
$set = $model->getSetByVisualId($visualId);
|
||||
|
||||
if (is_array($set) && is_array($set['visuals'])) {
|
||||
$this->response->respond(array(
|
||||
'set' => $set
|
||||
));
|
||||
}
|
||||
|
||||
Notification::error(n2_('Visual do not exists'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
public function actionAddVisual() {
|
||||
$this->validateToken();
|
||||
|
||||
$this->validatePermission('smartslider_edit');
|
||||
|
||||
$setId = Request::$REQUEST->getInt('setId');
|
||||
$this->validateVariable($setId > 0, 'set');
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
if (($visual = $model->addVisual($setId, Request::$REQUEST->getVar('value')))) {
|
||||
$this->response->respond(array(
|
||||
'visual' => $visual
|
||||
));
|
||||
}
|
||||
|
||||
Notification::error(n2_('Not editable'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
public function actionDeleteVisual() {
|
||||
$this->validateToken();
|
||||
|
||||
$this->validatePermission('smartslider_delete');
|
||||
|
||||
$visualId = Request::$REQUEST->getInt('visualId');
|
||||
$this->validateVariable($visualId > 0, 'visual');
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
if (($visual = $model->deleteVisual($visualId))) {
|
||||
$this->response->respond(array(
|
||||
'visual' => $visual
|
||||
));
|
||||
}
|
||||
|
||||
Notification::error(n2_('Not editable'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
public function actionChangeVisual() {
|
||||
$this->validateToken();
|
||||
|
||||
$this->validatePermission('smartslider_edit');
|
||||
|
||||
$visualId = Request::$REQUEST->getInt('visualId');
|
||||
$this->validateVariable($visualId > 0, 'visual');
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
if (($visual = $model->changeVisual($visualId, Request::$REQUEST->getVar('value')))) {
|
||||
$this->response->respond(array(
|
||||
'visual' => $visual
|
||||
));
|
||||
}
|
||||
|
||||
Notification::error(n2_('Unexpected error'));
|
||||
$this->response->error();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Controller;
|
||||
|
||||
use Nextend\Framework\Form\Form;
|
||||
use Nextend\Framework\Notification\Notification;
|
||||
use Nextend\Framework\PageFlow;
|
||||
use Nextend\Framework\Response\ResponseAjax;
|
||||
|
||||
class AjaxController extends AbstractController {
|
||||
|
||||
/** @var ResponseAjax */
|
||||
protected $response;
|
||||
|
||||
public function __construct($applicationType) {
|
||||
PageFlow::cleanOutputBuffers();
|
||||
|
||||
$this->response = new ResponseAjax($applicationType);
|
||||
parent::__construct($applicationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ResponseAjax
|
||||
*/
|
||||
public function getResponse() {
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
public function validateToken() {
|
||||
|
||||
if (!Form::checkToken()) {
|
||||
Notification::error(n2_('Security token mismatch. Please refresh the page!'));
|
||||
$this->response->error();
|
||||
}
|
||||
}
|
||||
|
||||
public function validatePermission($permission) {
|
||||
|
||||
if (!$this->canDo($permission)) {
|
||||
|
||||
Notification::error(n2_('You are not authorised to view this resource.'));
|
||||
|
||||
$this->response->error();
|
||||
}
|
||||
}
|
||||
|
||||
public function validateVariable($condition, $property) {
|
||||
|
||||
if (!$condition) {
|
||||
Notification::error(sprintf(n2_('Missing parameter: %s'), $property));
|
||||
$this->response->error();
|
||||
}
|
||||
}
|
||||
|
||||
public function validateDatabase($condition, $showError = true) {
|
||||
if (!$condition) {
|
||||
Notification::error(n2_('Database error'));
|
||||
$this->response->error();
|
||||
}
|
||||
}
|
||||
|
||||
public function redirect($url, $statusCode = 302, $terminate = true) {
|
||||
$this->response->redirect($url);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Data;
|
||||
|
||||
|
||||
class Data {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $_data = array();
|
||||
|
||||
public function __construct($data = null, $json = false) {
|
||||
|
||||
if ($data) {
|
||||
if (is_array($data)) {
|
||||
$this->loadArray($data);
|
||||
} else {
|
||||
$this->loadJSON($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $json
|
||||
*/
|
||||
public function loadJSON($json) {
|
||||
if ($json !== null) {
|
||||
$array = json_decode($json, true);
|
||||
if (is_array($array)) $this->_data = array_merge($this->_data, $array);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $array
|
||||
*/
|
||||
public function loadArray($array) {
|
||||
if (!$this->_data) $this->_data = array();
|
||||
if (is_array($array)) $this->_data = array_merge($this->_data, $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function toJSON() {
|
||||
return json_encode($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray() {
|
||||
return (array)$this->_data;
|
||||
}
|
||||
|
||||
public function has($key) {
|
||||
|
||||
return isset($this->_data[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = '') {
|
||||
if (isset($this->_data[$key])) return $this->_data[$key];
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function getIfEmpty($key, $default = '') {
|
||||
if (isset($this->_data[$key]) && !empty($this->_data[$key])) return $this->_data[$key];
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
$this->_data[$key] = $value;
|
||||
}
|
||||
|
||||
public function un_set($key) {
|
||||
if (isset($this->_data[$key])) {
|
||||
unset($this->_data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
public function fillDefault($defaults) {
|
||||
$this->_data = array_merge($defaults, $this->_data);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Database;
|
||||
|
||||
abstract class AbstractPlatformConnector {
|
||||
|
||||
protected $_prefixJoker = '#__';
|
||||
|
||||
protected $_prefix = '';
|
||||
|
||||
public function getPrefix() {
|
||||
return $this->_prefix;
|
||||
}
|
||||
|
||||
public function parsePrefix($query) {
|
||||
return str_replace($this->_prefixJoker, $this->_prefix, $query);
|
||||
}
|
||||
|
||||
abstract public function insertId();
|
||||
|
||||
abstract public function query($query, $attributes = false);
|
||||
|
||||
/**
|
||||
* Return with one row by query string
|
||||
*
|
||||
* @param string $query
|
||||
* @param array|bool $attributes for parameter binding
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function queryRow($query, $attributes = false);
|
||||
|
||||
abstract public function queryAll($query, $attributes = false, $type = "assoc", $key = null);
|
||||
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @param bool $escape
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function quote($text, $escape = true);
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param null $as
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function quoteName($name, $as = null);
|
||||
|
||||
public function checkError($result) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getCharsetCollate();
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Database;
|
||||
|
||||
|
||||
abstract class AbstractPlatformConnectorTable {
|
||||
|
||||
protected $primaryKeyColumn = "id";
|
||||
|
||||
/** @var AbstractPlatformConnector */
|
||||
protected static $connector;
|
||||
|
||||
protected $tableName;
|
||||
|
||||
public function __construct($tableName) {
|
||||
|
||||
$this->tableName = self::$connector->getPrefix() . $tableName;
|
||||
}
|
||||
|
||||
public function getTableName() {
|
||||
return $this->tableName;
|
||||
}
|
||||
|
||||
abstract public function findByPk($primaryKey);
|
||||
|
||||
abstract public function findByAttributes(array $attributes, $fields = false, $order = false);
|
||||
|
||||
abstract public function findAll($order = false);
|
||||
|
||||
/**
|
||||
* Return with all row by attributes
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param bool|array $fields
|
||||
* @param bool|string $order
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function findAllByAttributes(array $attributes, $fields = false, $order = false);
|
||||
|
||||
/**
|
||||
* Insert new row
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
abstract public function insert(array $attributes);
|
||||
|
||||
abstract public function insertId();
|
||||
|
||||
/**
|
||||
* Update row(s) by param(s)
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $conditions
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function update(array $attributes, array $conditions);
|
||||
|
||||
/**
|
||||
* Update one row by primary key with $attributes
|
||||
*
|
||||
* @param mixed $primaryKey
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function updateByPk($primaryKey, array $attributes);
|
||||
|
||||
/**
|
||||
* Delete one with by primary key
|
||||
*
|
||||
* @param mixed $primaryKey
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function deleteByPk($primaryKey);
|
||||
|
||||
/**
|
||||
* Delete all rows by attributes
|
||||
*
|
||||
* @param array $conditions
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function deleteByAttributes(array $conditions);
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Database;
|
||||
|
||||
use Nextend\Framework\Database\Joomla\JoomlaConnector;
|
||||
use Nextend\Framework\Database\Joomla\JoomlaConnectorTable;
|
||||
use Nextend\Framework\Database\WordPress\WordPressConnector;
|
||||
use Nextend\Framework\Database\WordPress\WordPressConnectorTable;
|
||||
use Nextend\Framework\Pattern\SingletonTrait;
|
||||
|
||||
class Database {
|
||||
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var AbstractPlatformConnector
|
||||
*/
|
||||
private static $platformConnector;
|
||||
|
||||
protected function init() {
|
||||
self::$platformConnector = new WordPressConnector();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
*
|
||||
* @return AbstractPlatformConnectorTable
|
||||
*/
|
||||
public static function getTable($tableName) {
|
||||
return new WordPressConnectorTable($tableName);
|
||||
}
|
||||
|
||||
public static function getPrefix() {
|
||||
return self::$platformConnector->getPrefix();
|
||||
}
|
||||
|
||||
public static function parsePrefix($query) {
|
||||
return self::$platformConnector->parsePrefix($query);
|
||||
}
|
||||
|
||||
public static function insertId() {
|
||||
|
||||
return self::$platformConnector->insertId();
|
||||
}
|
||||
|
||||
public static function query($query, $attributes = false) {
|
||||
|
||||
return self::$platformConnector->query($query, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with one row by query string
|
||||
*
|
||||
* @param string $query
|
||||
* @param array|bool $attributes for parameter binding
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function queryRow($query, $attributes = false) {
|
||||
|
||||
return self::$platformConnector->queryRow($query, $attributes);
|
||||
}
|
||||
|
||||
public static function queryAll($query, $attributes = false, $type = "assoc", $key = null) {
|
||||
|
||||
return self::$platformConnector->queryAll($query, $attributes, $type, $key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @param bool $escape
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function quote($text, $escape = true) {
|
||||
|
||||
return self::$platformConnector->quote($text, $escape);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param null $as
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function quoteName($name, $as = null) {
|
||||
|
||||
return self::$platformConnector->quoteName($name, $as);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getCharsetCollate() {
|
||||
|
||||
return self::$platformConnector->getCharsetCollate();
|
||||
}
|
||||
}
|
||||
|
||||
Database::getInstance();
|
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Database\WordPress;
|
||||
|
||||
use Nextend\Framework\Database\AbstractPlatformConnector;
|
||||
use Nextend\Framework\Notification\Notification;
|
||||
use Nextend\SmartSlider3\Platform\SmartSlider3Platform;
|
||||
use wpdb;
|
||||
|
||||
class WordPressConnector extends AbstractPlatformConnector {
|
||||
|
||||
/** @var wpdb $wpdb */
|
||||
private $db;
|
||||
|
||||
public function __construct() {
|
||||
/** @var wpdb $wpdb */ global $wpdb;
|
||||
$this->db = $wpdb;
|
||||
$this->_prefix = $wpdb->prefix;
|
||||
|
||||
WordPressConnectorTable::init($this, $this->db);
|
||||
}
|
||||
|
||||
public function query($query, $attributes = false) {
|
||||
if ($attributes) {
|
||||
foreach ($attributes as $key => $value) {
|
||||
$replaceTo = is_numeric($value) ? $value : $this->db->prepare('%s', $value);
|
||||
$query = str_replace($key, $replaceTo, $query);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->checkError($this->db->query($query));
|
||||
}
|
||||
|
||||
public function insertId() {
|
||||
return $this->db->insert_id;
|
||||
}
|
||||
|
||||
private function _querySQL($query, $attributes = false) {
|
||||
|
||||
$args = array('');
|
||||
|
||||
if ($attributes) {
|
||||
foreach ($attributes as $key => $value) {
|
||||
$replaceTo = is_numeric($value) ? '%d' : '%s';
|
||||
$query = str_replace($key, $replaceTo, $query);
|
||||
$args[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (count($args) > 1) {
|
||||
$args[0] = $query;
|
||||
|
||||
return call_user_func_array(array(
|
||||
$this->db,
|
||||
'prepare'
|
||||
), $args);
|
||||
} else {
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
||||
public function queryRow($query, $attributes = false) {
|
||||
return $this->checkError($this->db->get_row($this->_querySQL($query, $attributes), ARRAY_A));
|
||||
}
|
||||
|
||||
public function queryAll($query, $attributes = false, $type = "assoc", $key = null) {
|
||||
$result = $this->checkError($this->db->get_results($this->_querySQL($query, $attributes), $type == 'assoc' ? ARRAY_A : OBJECT_K));
|
||||
if (!$key) {
|
||||
return $result;
|
||||
}
|
||||
$realResult = array();
|
||||
|
||||
for ($i = 0; $i < count($result); $i++) {
|
||||
$key = $type == 'assoc' ? $result[i][$key] : $result[i]->{$key};
|
||||
$realResult[$key] = $result[i];
|
||||
}
|
||||
|
||||
return $realResult;
|
||||
}
|
||||
|
||||
public function quote($text, $escape = true) {
|
||||
return '\'' . (esc_sql($text)) . '\'';
|
||||
}
|
||||
|
||||
public function quoteName($name, $as = null) {
|
||||
if (strpos($name, '.') !== false) {
|
||||
return $name;
|
||||
} else {
|
||||
$q = '`';
|
||||
if (strlen($q) == 1) {
|
||||
return $q . $name . $q;
|
||||
} else {
|
||||
return $q[0] . $name . $q[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function checkError($result) {
|
||||
if (!empty($this->db->last_error)) {
|
||||
if (is_admin()) {
|
||||
$lastError = $this->db->last_error;
|
||||
$lastQuery = $this->db->last_query;
|
||||
|
||||
$possibleErrors = array(
|
||||
'Duplicate entry' => 'Your table column doesn\'t have auto increment, while it should have.',
|
||||
'command denied' => 'Your database user has limited access and isn\'t able to run all commands which are necessary for our code to work.',
|
||||
'Duplicate key name' => 'Your database user has limited access and isn\'t able to run DROP or ALTER database commands.',
|
||||
'Can\'t DROP' => 'Your database user has limited access and isn\'t able to run DROP or ALTER database commands.'
|
||||
);
|
||||
|
||||
$errorMessage = sprintf(n2_('If you see this message after the repair database process, please %1$scontact us%2$s with the log:'), '<a href="https://smartslider3.com/contact-us/support/" target="_blank">', '</a>');
|
||||
|
||||
foreach ($possibleErrors as $error => $cause) {
|
||||
if (strpos($lastError, $error) !== false) {
|
||||
$errorMessage = n2_($cause) . ' ' . n2_('Contact your server host and ask them to fix this for you!');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$message = array(
|
||||
n2_('Unexpected database error.'),
|
||||
'',
|
||||
'<a href="' . wp_nonce_url(add_query_arg(array('repairss3' => '1'), SmartSlider3Platform::getAdminUrl()), 'repairss3') . '" class="n2_button n2_button--big n2_button--blue">' . n2_('Try to repair database') . '</a>',
|
||||
'',
|
||||
$errorMessage,
|
||||
'',
|
||||
'<b>' . $lastError . '</b>',
|
||||
$lastQuery
|
||||
);
|
||||
Notification::error(implode('<br>', $message), array(
|
||||
'wide' => true
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getCharsetCollate() {
|
||||
|
||||
return $this->db->get_charset_collate();
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Database\WordPress;
|
||||
|
||||
use Nextend\Framework\Database\AbstractPlatformConnector;
|
||||
use Nextend\Framework\Database\AbstractPlatformConnectorTable;
|
||||
use wpdb;
|
||||
|
||||
class WordPressConnectorTable extends AbstractPlatformConnectorTable {
|
||||
|
||||
/** @var wpdb */
|
||||
protected static $db;
|
||||
|
||||
/**
|
||||
* @param AbstractPlatformConnector $connector
|
||||
* @param wpdb $db
|
||||
*/
|
||||
public static function init($connector, $db) {
|
||||
self::$connector = $connector;
|
||||
self::$db = $db;
|
||||
}
|
||||
|
||||
public function findByPk($primaryKey) {
|
||||
$query = self::$db->prepare("SELECT * FROM " . $this->tableName . " WHERE " . self::$connector->quoteName($this->primaryKeyColumn) . " = %s", $primaryKey);
|
||||
|
||||
return self::$connector->checkError(self::$db->get_row($query, ARRAY_A));
|
||||
}
|
||||
|
||||
public function findByAttributes(array $attributes, $fields = false, $order = false) {
|
||||
|
||||
return self::$connector->checkError(self::$db->get_row($this->_findByAttributesSQL($attributes, $fields, $order), ARRAY_A));
|
||||
}
|
||||
|
||||
|
||||
public function findAll($order = false) {
|
||||
|
||||
return self::$connector->checkError(self::$db->get_results($this->_findByAttributesSQL(array(), false, $order), ARRAY_A));
|
||||
}
|
||||
|
||||
public function findAllByAttributes(array $attributes, $fields = false, $order = false) {
|
||||
|
||||
return self::$connector->checkError(self::$db->get_results($this->_findByAttributesSQL($attributes, $fields, $order), ARRAY_A));
|
||||
}
|
||||
|
||||
public function insert(array $attributes) {
|
||||
return self::$connector->checkError(self::$db->insert($this->tableName, $attributes));
|
||||
}
|
||||
|
||||
public function insertId() {
|
||||
return self::$db->insert_id;
|
||||
}
|
||||
|
||||
public function update(array $attributes, array $conditions) {
|
||||
|
||||
return self::$connector->checkError(self::$db->update($this->tableName, $attributes, $conditions));
|
||||
}
|
||||
|
||||
public function updateByPk($primaryKey, array $attributes) {
|
||||
|
||||
$where = array();
|
||||
$where[$this->primaryKeyColumn] = $primaryKey;
|
||||
self::$connector->checkError(self::$db->update($this->tableName, $attributes, $where));
|
||||
}
|
||||
|
||||
public function deleteByPk($primaryKey) {
|
||||
$where = array();
|
||||
$where[$this->primaryKeyColumn] = $primaryKey;
|
||||
self::$connector->checkError(self::$db->delete($this->tableName, $where));
|
||||
}
|
||||
|
||||
public function deleteByAttributes(array $conditions) {
|
||||
self::$connector->checkError(self::$db->delete($this->tableName, $conditions));
|
||||
}
|
||||
|
||||
private function _findByAttributesSQL(array $attributes, $fields = array(), $order = false) {
|
||||
|
||||
$args = array('');
|
||||
|
||||
$query = 'SELECT ';
|
||||
if (!empty($fields)) {
|
||||
|
||||
$fields = array_map(array(
|
||||
self::$connector,
|
||||
'quoteName'
|
||||
), $fields);
|
||||
|
||||
$query .= implode(', ', $fields);
|
||||
} else {
|
||||
$query .= '*';
|
||||
}
|
||||
$query .= ' FROM ' . $this->tableName;
|
||||
|
||||
$where = array();
|
||||
foreach ($attributes as $key => $val) {
|
||||
$valueFormat = is_numeric($val) ? '%d' : '%s';
|
||||
if ($key === 'hash') {
|
||||
/**
|
||||
* @see SSDEV-3927
|
||||
* Hashes are typically 32 character long and generated by md5 hashing algorithm.
|
||||
* In rare cases the hashed value might consist of numbers only, which can lead to overflow.
|
||||
* MD5 hashes should be prepared always as string values.
|
||||
*/
|
||||
|
||||
$valueFormat = '%s';
|
||||
}
|
||||
$where[] = self::$connector->quoteName($key) . ' = ' . $valueFormat;
|
||||
$args[] = $val;
|
||||
}
|
||||
if (count($where)) {
|
||||
$query .= ' WHERE ' . implode(' AND ', $where);
|
||||
}
|
||||
|
||||
if ($order) {
|
||||
$query .= ' ORDER BY ' . $order;
|
||||
}
|
||||
|
||||
if (count($args) > 1) {
|
||||
$args[0] = $query;
|
||||
|
||||
return call_user_func_array(array(
|
||||
self::$db,
|
||||
'prepare'
|
||||
), $args);
|
||||
} else {
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* fast-image-size base class
|
||||
*
|
||||
* @package fast-image-size
|
||||
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nextend\Framework\FastImageSize;
|
||||
|
||||
use Nextend\Framework\Pattern\SingletonTrait;
|
||||
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
|
||||
|
||||
class FastImageSize {
|
||||
|
||||
use SingletonTrait;
|
||||
|
||||
private static $cache = array();
|
||||
|
||||
/**
|
||||
* @param string $image
|
||||
* @param array $attributes
|
||||
*/
|
||||
public static function initAttributes($image, &$attributes) {
|
||||
|
||||
$size = self::getSize($image);
|
||||
|
||||
if ($size) {
|
||||
$attributes['width'] = $size['width'];
|
||||
$attributes['height'] = $size['height'];
|
||||
}
|
||||
}
|
||||
|
||||
public static function getWidth($image) {
|
||||
|
||||
$size = self::getSize($image);
|
||||
|
||||
if ($size) {
|
||||
return $size['width'];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function getSize($image) {
|
||||
$imagePath = ResourceTranslator::toPath($image);
|
||||
|
||||
if (!isset(self::$cache[$imagePath])) {
|
||||
if (empty($imagePath)) {
|
||||
self::$cache[$imagePath] = false;
|
||||
} else {
|
||||
self::$cache[$imagePath] = self::getInstance()
|
||||
->getImageSize($imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
return self::$cache[$imagePath];
|
||||
}
|
||||
|
||||
/** @var array Size info that is returned */
|
||||
protected $size = array();
|
||||
|
||||
/** @var string Data retrieved from remote */
|
||||
protected $data = '';
|
||||
|
||||
/** @var array List of supported image types and associated image types */
|
||||
protected $supportedTypes = array(
|
||||
'png' => array('png'),
|
||||
'gif' => array('gif'),
|
||||
'jpeg' => array(
|
||||
'jpeg',
|
||||
'jpg'
|
||||
),
|
||||
'webp' => array(
|
||||
'webp',
|
||||
),
|
||||
'svg' => array(
|
||||
'svg',
|
||||
)
|
||||
);
|
||||
|
||||
/** @var array Class map that links image extensions/mime types to class */
|
||||
protected $classMap;
|
||||
|
||||
/** @var array An array containing the classes of supported image types */
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* Get image dimensions of supplied image
|
||||
*
|
||||
* @param string $file Path to image that should be checked
|
||||
* @param string $type Mimetype of image
|
||||
*
|
||||
* @return array|bool Array with image dimensions if successful, false if not
|
||||
*/
|
||||
public function getImageSize($file, $type = '') {
|
||||
// Reset values
|
||||
$this->resetValues();
|
||||
|
||||
// Treat image type as unknown if extension or mime type is unknown
|
||||
if (!preg_match('/\.([a-z0-9]+)$/i', $file, $match) && empty($type)) {
|
||||
$this->getImagesizeUnknownType($file);
|
||||
} else {
|
||||
$extension = (empty($type) && isset($match[1])) ? $match[1] : preg_replace('/.+\/([a-z0-9-.]+)$/i', '$1', $type);
|
||||
|
||||
$this->getImageSizeByExtension($file, $extension);
|
||||
}
|
||||
|
||||
return sizeof($this->size) > 1 ? $this->size : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dimensions of image if type is unknown
|
||||
*
|
||||
* @param string $filename Path to file
|
||||
*/
|
||||
protected function getImagesizeUnknownType($filename) {
|
||||
// Grab the maximum amount of bytes we might need
|
||||
$data = $this->getImage($filename, 0, Type\TypeJpeg::JPEG_MAX_HEADER_SIZE, false);
|
||||
|
||||
if ($data !== false) {
|
||||
$this->loadAllTypes();
|
||||
foreach ($this->type as $imageType) {
|
||||
$imageType->getSize($filename);
|
||||
|
||||
if (sizeof($this->size) > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image size by file extension
|
||||
*
|
||||
* @param string $file Path to image that should be checked
|
||||
* @param string $extension Extension/type of image
|
||||
*/
|
||||
protected function getImageSizeByExtension($file, $extension) {
|
||||
$extension = strtolower($extension);
|
||||
$this->loadExtension($extension);
|
||||
if (isset($this->classMap[$extension])) {
|
||||
$this->classMap[$extension]->getSize($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset values to default
|
||||
*/
|
||||
protected function resetValues() {
|
||||
$this->size = array();
|
||||
$this->data = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mime type based on supplied image
|
||||
*
|
||||
* @param int $type Type of image
|
||||
*/
|
||||
public function setImageType($type) {
|
||||
$this->size['type'] = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size info
|
||||
*
|
||||
* @param array $size Array containing size info for image
|
||||
*/
|
||||
public function setSize($size) {
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image from specified path/source
|
||||
*
|
||||
* @param string $filename Path to image
|
||||
* @param int $offset Offset at which reading of the image should start
|
||||
* @param int $length Maximum length that should be read
|
||||
* @param bool $forceLength True if the length needs to be the specified
|
||||
* length, false if not. Default: true
|
||||
*
|
||||
* @return false|string Image data or false if result was empty
|
||||
*/
|
||||
public function getImage($filename, $offset, $length, $forceLength = true) {
|
||||
if (empty($this->data)) {
|
||||
$this->data = @file_get_contents($filename, false, null, $offset, $length);
|
||||
}
|
||||
|
||||
// Force length to expected one. Return false if data length
|
||||
// is smaller than expected length
|
||||
if ($forceLength === true) {
|
||||
return (strlen($this->data) < $length) ? false : substr($this->data, $offset, $length);
|
||||
}
|
||||
|
||||
return empty($this->data) ? false : $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get return data
|
||||
*
|
||||
* @return array|bool Size array if dimensions could be found, false if not
|
||||
*/
|
||||
protected function getReturnData() {
|
||||
return sizeof($this->size) > 1 ? $this->size : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all supported types
|
||||
*/
|
||||
protected function loadAllTypes() {
|
||||
foreach ($this->supportedTypes as $imageType => $extension) {
|
||||
$this->loadType($imageType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an image type by extension
|
||||
*
|
||||
* @param string $extension Extension of image
|
||||
*/
|
||||
protected function loadExtension($extension) {
|
||||
if (isset($this->classMap[$extension])) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->supportedTypes as $imageType => $extensions) {
|
||||
if (in_array($extension, $extensions, true)) {
|
||||
$this->loadType($imageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an image type
|
||||
*
|
||||
* @param string $imageType Mimetype
|
||||
*/
|
||||
protected function loadType($imageType) {
|
||||
if (isset($this->type[$imageType])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$className = '\\' . __NAMESPACE__ . '\Type\Type' . ucfirst($imageType);
|
||||
|
||||
$this->type[$imageType] = new $className($this);
|
||||
|
||||
// Create class map
|
||||
foreach ($this->supportedTypes[$imageType] as $ext) {
|
||||
/** @var Type\TypeInterface */
|
||||
$this->classMap[$ext] = $this->type[$imageType];
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* fast-image-size image type base
|
||||
*
|
||||
* @package fast-image-size
|
||||
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nextend\Framework\FastImageSize\Type;
|
||||
|
||||
use Nextend\Framework\FastImageSize\FastImageSize;
|
||||
|
||||
abstract class TypeBase implements TypeInterface {
|
||||
|
||||
/** @var FastImageSize */
|
||||
protected $fastImageSize;
|
||||
|
||||
/**
|
||||
* Base constructor for image types
|
||||
*
|
||||
* @param FastImageSize $fastImageSize
|
||||
*/
|
||||
public function __construct(FastImageSize $fastImageSize) {
|
||||
$this->fastImageSize = $fastImageSize;
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* fast-image-size image type gif
|
||||
*
|
||||
* @package fast-image-size
|
||||
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nextend\Framework\FastImageSize\Type;
|
||||
|
||||
class TypeGif extends TypeBase {
|
||||
|
||||
/** @var string GIF87a header */
|
||||
const GIF87A_HEADER = "\x47\x49\x46\x38\x37\x61";
|
||||
|
||||
/** @var string GIF89a header */
|
||||
const GIF89A_HEADER = "\x47\x49\x46\x38\x39\x61";
|
||||
|
||||
/** @var int GIF header size */
|
||||
const GIF_HEADER_SIZE = 6;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize($filename) {
|
||||
// Get data needed for reading image dimensions as outlined by GIF87a
|
||||
// and GIF89a specifications
|
||||
$data = $this->fastImageSize->getImage($filename, 0, self::GIF_HEADER_SIZE + self::SHORT_SIZE * 2);
|
||||
|
||||
$type = substr($data, 0, self::GIF_HEADER_SIZE);
|
||||
if ($type !== self::GIF87A_HEADER && $type !== self::GIF89A_HEADER) {
|
||||
return;
|
||||
}
|
||||
|
||||
$size = unpack('vwidth/vheight', substr($data, self::GIF_HEADER_SIZE, self::SHORT_SIZE * 2));
|
||||
|
||||
$this->fastImageSize->setSize($size);
|
||||
$this->fastImageSize->setImageType(IMAGETYPE_GIF);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* fast-image-size image type interface
|
||||
*
|
||||
* @package fast-image-size
|
||||
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nextend\Framework\FastImageSize\Type;
|
||||
|
||||
interface TypeInterface {
|
||||
|
||||
/** @var int 4-byte long size */
|
||||
const LONG_SIZE = 4;
|
||||
|
||||
/** @var int 2-byte short size */
|
||||
const SHORT_SIZE = 2;
|
||||
|
||||
/**
|
||||
* Get size of supplied image
|
||||
*
|
||||
* @param string $filename File name of image
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getSize($filename);
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* fast-image-size image type jpeg
|
||||
*
|
||||
* @package fast-image-size
|
||||
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nextend\Framework\FastImageSize\Type;
|
||||
|
||||
class TypeJpeg extends TypeBase {
|
||||
|
||||
/** @var int JPEG max header size. Headers can be bigger, but we'll abort
|
||||
* going through the header after this */
|
||||
const JPEG_MAX_HEADER_SIZE = 786432; // = 768 kiB
|
||||
|
||||
/** @var string JPEG header */
|
||||
const JPEG_HEADER = "\xFF\xD8";
|
||||
|
||||
/** @var string Start of frame marker */
|
||||
const SOF_START_MARKER = "\xFF";
|
||||
|
||||
/** @var string End of image (EOI) marker */
|
||||
const JPEG_EOI_MARKER = "\xD9";
|
||||
|
||||
/** @var array JPEG SOF markers */
|
||||
protected $sofMarkers = array(
|
||||
"\xC0",
|
||||
"\xC1",
|
||||
"\xC2",
|
||||
"\xC3",
|
||||
"\xC5",
|
||||
"\xC6",
|
||||
"\xC7",
|
||||
"\xC9",
|
||||
"\xCA",
|
||||
"\xCB",
|
||||
"\xCD",
|
||||
"\xCE",
|
||||
"\xCF"
|
||||
);
|
||||
|
||||
/** @var string|bool JPEG data stream */
|
||||
protected $data = '';
|
||||
|
||||
/** @var int Data length */
|
||||
protected $dataLength = 0;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize($filename) {
|
||||
// Do not force the data length
|
||||
$this->data = $this->fastImageSize->getImage($filename, 0, self::JPEG_MAX_HEADER_SIZE, false);
|
||||
|
||||
// Check if file is jpeg
|
||||
if ($this->data === false || substr($this->data, 0, self::SHORT_SIZE) !== self::JPEG_HEADER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Look through file for SOF marker
|
||||
$size = $this->getSizeInfo();
|
||||
|
||||
$this->fastImageSize->setSize($size);
|
||||
$this->fastImageSize->setImageType(IMAGETYPE_JPEG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size info from image data
|
||||
*
|
||||
* @return array An array with the image's size info or an empty array if
|
||||
* size info couldn't be found
|
||||
*/
|
||||
protected function getSizeInfo() {
|
||||
$size = array();
|
||||
// since we check $i + 1 we need to stop one step earlier
|
||||
$this->dataLength = strlen($this->data) - 1;
|
||||
|
||||
$sofStartRead = true;
|
||||
|
||||
// Look through file for SOF marker
|
||||
for ($i = 2; $i < $this->dataLength; $i++) {
|
||||
$marker = $this->getNextMarker($i, $sofStartRead);
|
||||
|
||||
if (in_array($marker, $this->sofMarkers)) {
|
||||
// Extract size info from SOF marker
|
||||
return $this->extractSizeInfo($i);
|
||||
} else {
|
||||
// Extract length only
|
||||
$markerLength = $this->extractMarkerLength($i);
|
||||
|
||||
if ($markerLength < 2) {
|
||||
return $size;
|
||||
}
|
||||
|
||||
$i += $markerLength - 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract marker length from data
|
||||
*
|
||||
* @param int $i Current index
|
||||
*
|
||||
* @return int Length of current marker
|
||||
*/
|
||||
protected function extractMarkerLength($i) {
|
||||
// Extract length only
|
||||
list(, $unpacked) = unpack("H*", substr($this->data, $i, self::LONG_SIZE));
|
||||
|
||||
// Get width and height from unpacked size info
|
||||
$markerLength = hexdec(substr($unpacked, 0, 4));
|
||||
|
||||
return $markerLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract size info from data
|
||||
*
|
||||
* @param int $i Current index
|
||||
*
|
||||
* @return array Size info of current marker
|
||||
*/
|
||||
protected function extractSizeInfo($i) {
|
||||
// Extract size info from SOF marker
|
||||
list(, $unpacked) = unpack("H*", substr($this->data, $i - 1 + self::LONG_SIZE, self::LONG_SIZE));
|
||||
|
||||
// Get width and height from unpacked size info
|
||||
$size = array(
|
||||
'width' => hexdec(substr($unpacked, 4, 4)),
|
||||
'height' => hexdec(substr($unpacked, 0, 4)),
|
||||
);
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next JPEG marker in file
|
||||
*
|
||||
* @param int $i Current index
|
||||
* @param bool $sofStartRead Flag whether SOF start padding was already read
|
||||
*
|
||||
* @return string Next JPEG marker in file
|
||||
*/
|
||||
protected function getNextMarker(&$i, &$sofStartRead) {
|
||||
$this->skipStartPadding($i, $sofStartRead);
|
||||
|
||||
do {
|
||||
if ($i >= $this->dataLength) {
|
||||
return self::JPEG_EOI_MARKER;
|
||||
}
|
||||
$marker = $this->data[$i];
|
||||
$i++;
|
||||
} while ($marker == self::SOF_START_MARKER);
|
||||
|
||||
return $marker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip over any possible padding until we reach a byte without SOF start
|
||||
* marker. Extraneous bytes might need to require proper treating.
|
||||
*
|
||||
* @param int $i Current index
|
||||
* @param bool $sofStartRead Flag whether SOF start padding was already read
|
||||
*/
|
||||
protected function skipStartPadding(&$i, &$sofStartRead) {
|
||||
if (!$sofStartRead) {
|
||||
while ($this->data[$i] !== self::SOF_START_MARKER) {
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* fast-image-size image type png
|
||||
*
|
||||
* @package fast-image-size
|
||||
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nextend\Framework\FastImageSize\Type;
|
||||
|
||||
class TypePng extends TypeBase {
|
||||
|
||||
/** @var string PNG header */
|
||||
const PNG_HEADER = "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a";
|
||||
|
||||
/** @var int PNG IHDR offset */
|
||||
const PNG_IHDR_OFFSET = 12;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize($filename) {
|
||||
// Retrieve image data including the header, the IHDR tag, and the
|
||||
// following 2 chunks for the image width and height
|
||||
$data = $this->fastImageSize->getImage($filename, 0, self::PNG_IHDR_OFFSET + 3 * self::LONG_SIZE);
|
||||
|
||||
// Check if header fits expected format specified by RFC 2083
|
||||
if (substr($data, 0, self::PNG_IHDR_OFFSET - self::LONG_SIZE) !== self::PNG_HEADER || substr($data, self::PNG_IHDR_OFFSET, self::LONG_SIZE) !== 'IHDR') {
|
||||
return;
|
||||
}
|
||||
|
||||
$size = unpack('Nwidth/Nheight', substr($data, self::PNG_IHDR_OFFSET + self::LONG_SIZE, self::LONG_SIZE * 2));
|
||||
$this->fastImageSize->setSize($size);
|
||||
$this->fastImageSize->setImageType(IMAGETYPE_PNG);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\FastImageSize\Type;
|
||||
|
||||
class TypeSvg extends TypeBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize($filename) {
|
||||
|
||||
$data = $this->fastImageSize->getImage($filename, 0, 100);
|
||||
|
||||
preg_match('/width="([0-9]+)"/', $data, $matches);
|
||||
if ($matches && $matches[1] > 0) {
|
||||
$size = array();
|
||||
$size['width'] = $matches[1];
|
||||
|
||||
preg_match('/height="([0-9]+)"/', $data, $matches);
|
||||
if ($matches && $matches[1] > 0) {
|
||||
$size['height'] = $matches[1];
|
||||
$this->fastImageSize->setSize($size);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
preg_match('/viewBox=["\']([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)["\']/i', $data, $matches);
|
||||
|
||||
if ($matches) {
|
||||
$this->fastImageSize->setSize(array(
|
||||
'width' => $matches[3] - $matches[1],
|
||||
'height' => $matches[4] - $matches[2],
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* fast-image-size image type webp
|
||||
*
|
||||
* @package fast-image-size
|
||||
* @copyright (c) Marc Alexander <admin@m-a-styles.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Nextend\Framework\FastImageSize\Type;
|
||||
|
||||
use Nextend\Framework\FastImageSize\FastImageSize;
|
||||
|
||||
class TypeWebp extends TypeBase {
|
||||
|
||||
/** @var string RIFF header */
|
||||
const WEBP_RIFF_HEADER = "RIFF";
|
||||
|
||||
/** @var string Webp header */
|
||||
const WEBP_HEADER = "WEBP";
|
||||
|
||||
/** @var string VP8 chunk header */
|
||||
const VP8_HEADER = "VP8";
|
||||
|
||||
/** @var string Simple(lossy) webp format */
|
||||
const WEBP_FORMAT_SIMPLE = ' ';
|
||||
|
||||
/** @var string Lossless webp format */
|
||||
const WEBP_FORMAT_LOSSLESS = 'L';
|
||||
|
||||
/** @var string Extended webp format */
|
||||
const WEBP_FORMAT_EXTENDED = 'X';
|
||||
|
||||
/** @var int WEBP header size needed for retrieving image size */
|
||||
const WEBP_HEADER_SIZE = 30;
|
||||
|
||||
/** @var array Size info array */
|
||||
protected $size;
|
||||
|
||||
/**
|
||||
* Constructor for webp image type. Adds missing constant if necessary.
|
||||
*
|
||||
* @param FastImageSize $fastImageSize
|
||||
*/
|
||||
public function __construct(FastImageSize $fastImageSize) {
|
||||
parent::__construct($fastImageSize);
|
||||
|
||||
if (!defined('IMAGETYPE_WEBP')) {
|
||||
define('IMAGETYPE_WEBP', 18);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize($filename) {
|
||||
// Do not force length of header
|
||||
$data = $this->fastImageSize->getImage($filename, 0, self::WEBP_HEADER_SIZE);
|
||||
|
||||
$this->size = array();
|
||||
|
||||
$webpFormat = substr($data, 15, 1);
|
||||
|
||||
if (!$this->hasWebpHeader($data) || !$this->isValidFormat($webpFormat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = substr($data, 16, 14);
|
||||
|
||||
$this->getWebpSize($data, $webpFormat);
|
||||
|
||||
$this->fastImageSize->setSize($this->size);
|
||||
$this->fastImageSize->setImageType(IMAGETYPE_WEBP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if $data has valid WebP header
|
||||
*
|
||||
* @param string $data Image data
|
||||
*
|
||||
* @return bool True if $data has valid WebP header, false if not
|
||||
*/
|
||||
protected function hasWebpHeader($data) {
|
||||
$riffSignature = substr($data, 0, self::LONG_SIZE);
|
||||
$webpSignature = substr($data, 8, self::LONG_SIZE);
|
||||
$vp8Signature = substr($data, 12, self::SHORT_SIZE + 1);
|
||||
|
||||
return !empty($data) && $riffSignature === self::WEBP_RIFF_HEADER && $webpSignature === self::WEBP_HEADER && $vp8Signature === self::VP8_HEADER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if $format is a valid WebP format
|
||||
*
|
||||
* @param string $format Format string
|
||||
*
|
||||
* @return bool True if format is valid WebP format, false if not
|
||||
*/
|
||||
protected function isValidFormat($format) {
|
||||
return in_array($format, array(
|
||||
self::WEBP_FORMAT_SIMPLE,
|
||||
self::WEBP_FORMAT_LOSSLESS,
|
||||
self::WEBP_FORMAT_EXTENDED
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get webp size info depending on format type and set size array values
|
||||
*
|
||||
* @param string $data Data string
|
||||
* @param string $format Format string
|
||||
*/
|
||||
protected function getWebpSize($data, $format) {
|
||||
switch ($format) {
|
||||
case self::WEBP_FORMAT_SIMPLE:
|
||||
$this->size = unpack('vwidth/vheight', substr($data, 10, 4));
|
||||
break;
|
||||
|
||||
case self::WEBP_FORMAT_LOSSLESS:
|
||||
// Lossless uses 14-bit values so we'll have to use bitwise shifting
|
||||
$this->size = array(
|
||||
'width' => ord($data[5]) + ((ord($data[6]) & 0x3F) << 8) + 1,
|
||||
'height' => (ord($data[6]) >> 6) + (ord($data[7]) << 2) + ((ord($data[8]) & 0xF) << 10) + 1,
|
||||
);
|
||||
break;
|
||||
|
||||
case self::WEBP_FORMAT_EXTENDED:
|
||||
// Extended uses 24-bit values cause 14-bit for lossless wasn't weird enough
|
||||
$this->size = array(
|
||||
'width' => ord($data[8]) + (ord($data[9]) << 8) + (ord($data[10]) << 16) + 1,
|
||||
'height' => ord($data[11]) + (ord($data[12]) << 8) + (ord($data[13]) << 16) + 1,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,356 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Filesystem;
|
||||
|
||||
use Nextend\Framework\Url\Url;
|
||||
|
||||
if (!defined('NEXTEND_RELATIVE_CACHE_WEB')) {
|
||||
define('NEXTEND_RELATIVE_CACHE_WEB', '/cache/nextend/web');
|
||||
define('NEXTEND_CUSTOM_CACHE', 0);
|
||||
} else {
|
||||
define('NEXTEND_CUSTOM_CACHE', 1);
|
||||
}
|
||||
if (!defined('NEXTEND_RELATIVE_CACHE_NOTWEB')) {
|
||||
define('NEXTEND_RELATIVE_CACHE_NOTWEB', '/cache/nextend/notweb');
|
||||
}
|
||||
|
||||
abstract class AbstractPlatformFilesystem {
|
||||
|
||||
public $paths = array();
|
||||
|
||||
/**
|
||||
* @var string Absolute path which match to the baseuri. It must not end with /
|
||||
* @example /asd/xyz/wordpress
|
||||
*/
|
||||
protected $_basepath;
|
||||
|
||||
protected $dirPermission = 0777;
|
||||
|
||||
protected $filePermission = 0666;
|
||||
|
||||
|
||||
protected $translate = array();
|
||||
|
||||
public function init() {
|
||||
|
||||
}
|
||||
|
||||
public function getPaths() {
|
||||
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
public function check($base, $folder) {
|
||||
static $checked = array();
|
||||
if (!isset($checked[$base . '/' . $folder])) {
|
||||
$cacheFolder = $base . '/' . $folder;
|
||||
if (!$this->existsFolder($cacheFolder)) {
|
||||
if ($this->is_writable($base)) {
|
||||
$this->createFolder($cacheFolder);
|
||||
} else {
|
||||
die('<div style="position:fixed;background:#fff;width:100%;height:100%;top:0;left:0;z-index:100000;">' . sprintf('<h2><b>%s</b> is not writable.</h2>', esc_html($base)) . '</div>');
|
||||
}
|
||||
} else if (!$this->is_writable($cacheFolder)) {
|
||||
die('<div style="position:fixed;background:#fff;width:100%;height:100%;top:0;left:0;z-index:100000;">' . sprintf('<h2><b>%s</b> is not writable.</h2>', esc_html($cacheFolder)) . '</div>');
|
||||
}
|
||||
$checked[$base . '/' . $folder] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function measurePermission($testDir) {
|
||||
while ('.' != $testDir && !is_dir($testDir)) {
|
||||
$testDir = dirname($testDir);
|
||||
}
|
||||
|
||||
if ($stat = @stat($testDir)) {
|
||||
$this->dirPermission = $stat['mode'] & 0007777;
|
||||
$this->filePermission = $this->dirPermission & 0000666;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function toLinux($path) {
|
||||
return str_replace(DIRECTORY_SEPARATOR, '/', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBasePath() {
|
||||
|
||||
return $this->_basepath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*/
|
||||
public function setBasePath($path) {
|
||||
|
||||
$this->_basepath = $path;
|
||||
}
|
||||
|
||||
public function getWebCachePath() {
|
||||
|
||||
return $this->getBasePath() . NEXTEND_RELATIVE_CACHE_WEB;
|
||||
}
|
||||
|
||||
public function getNotWebCachePath() {
|
||||
return $this->getBasePath() . NEXTEND_RELATIVE_CACHE_NOTWEB;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function pathToAbsoluteURL($path) {
|
||||
return Url::pathToUri($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function pathToRelativePath($path) {
|
||||
|
||||
return preg_replace('/^' . preg_quote($this->_basepath, '/') . '/', '', str_replace('/', DIRECTORY_SEPARATOR, $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function pathToAbsolutePath($path) {
|
||||
|
||||
return $this->_basepath . str_replace('/', DIRECTORY_SEPARATOR, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function absoluteURLToPath($url) {
|
||||
|
||||
$fullUri = Url::getFullUri();
|
||||
if (substr($url, 0, strlen($fullUri)) == $fullUri) {
|
||||
|
||||
return str_replace($fullUri, $this->_basepath, $url);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function fileexists($file) {
|
||||
return is_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function safefileexists($file) {
|
||||
return realpath($file) && is_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $dir
|
||||
*
|
||||
* @return array Folder names without trailing slash
|
||||
*/
|
||||
public function folders($dir) {
|
||||
if (!is_dir($dir)) {
|
||||
return array();
|
||||
}
|
||||
$folders = array();
|
||||
foreach (scandir($dir) as $file) {
|
||||
if ($file == '.' || $file == '..') continue;
|
||||
if (is_dir($dir . DIRECTORY_SEPARATOR . $file)) $folders[] = $file;
|
||||
}
|
||||
|
||||
return $folders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_writable($path) {
|
||||
return is_writable($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createFolder($path) {
|
||||
|
||||
return mkdir($path, $this->dirPermission, true);
|
||||
}
|
||||
|
||||
public function deleteFolder($dir) {
|
||||
if (!is_dir($dir) || is_link($dir)) return unlink($dir);
|
||||
foreach (scandir($dir) as $file) {
|
||||
if ($file == '.' || $file == '..') continue;
|
||||
if (!$this->deleteFolder($dir . DIRECTORY_SEPARATOR . $file)) {
|
||||
chmod($dir . DIRECTORY_SEPARATOR . $file, $this->dirPermission);
|
||||
if (!$this->deleteFolder($dir . DIRECTORY_SEPARATOR . $file)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
public function existsFolder($path) {
|
||||
return is_dir($path);
|
||||
}
|
||||
|
||||
public function files($path) {
|
||||
$files = array();
|
||||
if (is_dir($path)) {
|
||||
if ($dh = opendir($path)) {
|
||||
while (($file = readdir($dh)) !== false) {
|
||||
if ($file[0] != ".") {
|
||||
$files[] = $file;
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function existsFile($path) {
|
||||
|
||||
return file_exists($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $buffer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function createFile($path, $buffer) {
|
||||
return file_put_contents($path, $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function readFile($path) {
|
||||
return file_get_contents($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert dir alias to normal format
|
||||
*
|
||||
* @param $pathName
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function dirFormat($pathName) {
|
||||
return str_replace(".", DIRECTORY_SEPARATOR, $pathName);
|
||||
}
|
||||
|
||||
public function getImagesFolder() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function realpath($path) {
|
||||
return rtrim(realpath($path), '/\\');
|
||||
}
|
||||
|
||||
public function registerTranslate($from, $to) {
|
||||
$this->translate[$from] = $to;
|
||||
}
|
||||
|
||||
protected function trailingslashit($string) {
|
||||
return $this->untrailingslashit($string) . '/';
|
||||
}
|
||||
|
||||
protected function untrailingslashit($string) {
|
||||
return rtrim($string, '/\\');
|
||||
}
|
||||
|
||||
public function convertToRealDirectorySeparator($path) {
|
||||
return str_replace(DIRECTORY_SEPARATOR == '/' ? '\\' : '/', DIRECTORY_SEPARATOR, $path);
|
||||
}
|
||||
|
||||
public function get_temp_dir() {
|
||||
static $temp = '';
|
||||
if (defined('SS_TEMP_DIR')) return $this->trailingslashit(SS_TEMP_DIR);
|
||||
|
||||
if ($temp) return $this->trailingslashit($temp);
|
||||
|
||||
if (function_exists('sys_get_temp_dir')) {
|
||||
$temp = sys_get_temp_dir();
|
||||
if (@is_dir($temp) && $this->is_writable($temp)) return $this->trailingslashit($temp);
|
||||
}
|
||||
|
||||
$temp = ini_get('upload_tmp_dir');
|
||||
if (@is_dir($temp) && $this->is_writable($temp)) return $this->trailingslashit($temp);
|
||||
|
||||
$temp = $this->getNotWebCachePath() . '/';
|
||||
if (is_dir($temp) && $this->is_writable($temp)) return $temp;
|
||||
|
||||
return '/tmp/';
|
||||
}
|
||||
|
||||
public function tempnam($filename = '', $dir = '') {
|
||||
if (empty($dir)) {
|
||||
$dir = $this->get_temp_dir();
|
||||
}
|
||||
|
||||
if (empty($filename) || '.' == $filename || '/' == $filename || '\\' == $filename) {
|
||||
$filename = time();
|
||||
}
|
||||
|
||||
// Use the basename of the given file without the extension as the name for the temporary directory
|
||||
$temp_filename = basename($filename);
|
||||
$temp_filename = preg_replace('|\.[^.]*$|', '', $temp_filename);
|
||||
|
||||
// If the folder is falsey, use its parent directory name instead.
|
||||
if (!$temp_filename) {
|
||||
return $this->tempnam(dirname($filename), $dir);
|
||||
}
|
||||
|
||||
// Suffix some random data to avoid filename conflicts
|
||||
$temp_filename .= '-' . md5(uniqid(rand() . time()));
|
||||
$temp_filename .= '.tmp';
|
||||
$temp_filename = $dir . $temp_filename;
|
||||
|
||||
$fp = @fopen($temp_filename, 'x');
|
||||
if (!$fp && is_writable($dir) && file_exists($temp_filename)) {
|
||||
return $this->tempnam($filename, $dir);
|
||||
}
|
||||
if ($fp) {
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
return $temp_filename;
|
||||
}
|
||||
}
|
@ -0,0 +1,275 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Filesystem;
|
||||
|
||||
use Nextend\Framework\Filesystem\Joomla\JoomlaFilesystem;
|
||||
use Nextend\Framework\Filesystem\WordPress\WordPressFilesystem;
|
||||
|
||||
class Filesystem {
|
||||
|
||||
/**
|
||||
* @var AbstractPlatformFilesystem
|
||||
*/
|
||||
private static $platformFilesystem;
|
||||
|
||||
public function __construct() {
|
||||
self::$platformFilesystem = new WordPressFilesystem();
|
||||
|
||||
self::$platformFilesystem->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractPlatformFilesystem
|
||||
*/
|
||||
public static function get() {
|
||||
|
||||
return self::$platformFilesystem;
|
||||
}
|
||||
|
||||
public static function getPaths() {
|
||||
|
||||
return self::$platformFilesystem->getPaths();
|
||||
}
|
||||
|
||||
public static function check($base, $folder) {
|
||||
|
||||
self::$platformFilesystem->check($base, $folder);
|
||||
}
|
||||
|
||||
public static function measurePermission($testDir) {
|
||||
|
||||
self::$platformFilesystem->measurePermission($testDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toLinux($path) {
|
||||
|
||||
return self::$platformFilesystem->toLinux($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getBasePath() {
|
||||
|
||||
return self::$platformFilesystem->getBasePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*/
|
||||
public static function setBasePath($path) {
|
||||
|
||||
self::$platformFilesystem->setBasePath($path);
|
||||
}
|
||||
|
||||
public static function getWebCachePath() {
|
||||
|
||||
return self::$platformFilesystem->getWebCachePath();
|
||||
}
|
||||
|
||||
public static function getNotWebCachePath() {
|
||||
|
||||
return self::$platformFilesystem->getNotWebCachePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function pathToAbsoluteURL($path) {
|
||||
|
||||
return self::$platformFilesystem->pathToAbsoluteURL($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function pathToRelativePath($path) {
|
||||
|
||||
return self::$platformFilesystem->pathToRelativePath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function pathToAbsolutePath($path) {
|
||||
|
||||
return self::$platformFilesystem->pathToAbsolutePath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function absoluteURLToPath($url) {
|
||||
|
||||
return self::$platformFilesystem->absoluteURLToPath($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function fileexists($file) {
|
||||
|
||||
return self::$platformFilesystem->fileexists($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function safefileexists($file) {
|
||||
|
||||
return self::$platformFilesystem->safefileexists($file);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $dir
|
||||
*
|
||||
* @return array Folder names without trailing slash
|
||||
*/
|
||||
public static function folders($dir) {
|
||||
|
||||
return self::$platformFilesystem->folders($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_writable($path) {
|
||||
|
||||
return self::$platformFilesystem->is_writable($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function createFolder($path) {
|
||||
|
||||
return self::$platformFilesystem->createFolder($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $dir
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteFolder($dir) {
|
||||
|
||||
return self::$platformFilesystem->deleteFolder($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function existsFolder($path) {
|
||||
|
||||
return self::$platformFilesystem->existsFolder($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function files($path) {
|
||||
|
||||
return self::$platformFilesystem->files($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function existsFile($path) {
|
||||
|
||||
return self::$platformFilesystem->existsFile($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $buffer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function createFile($path, $buffer) {
|
||||
|
||||
return self::$platformFilesystem->createFile($path, $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function readFile($path) {
|
||||
|
||||
return self::$platformFilesystem->readFile($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert dir alias to normal format
|
||||
*
|
||||
* @param $pathName
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function dirFormat($pathName) {
|
||||
|
||||
return self::$platformFilesystem->dirFormat($pathName);
|
||||
}
|
||||
|
||||
public static function getImagesFolder() {
|
||||
|
||||
return self::$platformFilesystem->getImagesFolder();
|
||||
}
|
||||
|
||||
public static function realpath($path) {
|
||||
|
||||
return self::$platformFilesystem->realpath($path);
|
||||
}
|
||||
|
||||
public static function registerTranslate($from, $to) {
|
||||
|
||||
self::$platformFilesystem->registerTranslate($from, $to);
|
||||
}
|
||||
|
||||
public static function convertToRealDirectorySeparator($path) {
|
||||
|
||||
return self::$platformFilesystem->convertToRealDirectorySeparator($path);
|
||||
}
|
||||
|
||||
public static function get_temp_dir() {
|
||||
|
||||
return self::$platformFilesystem->get_temp_dir();
|
||||
}
|
||||
|
||||
public static function tempnam($filename = '', $dir = '') {
|
||||
|
||||
return self::$platformFilesystem->tempnam($filename = '', $dir = '');
|
||||
}
|
||||
}
|
||||
|
||||
new Filesystem();
|
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Filesystem\WordPress;
|
||||
|
||||
use Nextend\Framework\Filesystem\AbstractPlatformFilesystem;
|
||||
use Nextend\Framework\Platform\Platform;
|
||||
use Nextend\Framework\Url\Url;
|
||||
use function get_current_blog_id;
|
||||
|
||||
class WordPressFilesystem extends AbstractPlatformFilesystem {
|
||||
|
||||
public function init() {
|
||||
|
||||
$this->paths[] = realpath(ABSPATH);
|
||||
|
||||
$this->_basepath = realpath(WP_CONTENT_DIR);
|
||||
|
||||
$this->paths[] = $this->_basepath;
|
||||
|
||||
$this->paths[] = realpath(WP_PLUGIN_DIR);
|
||||
|
||||
$wp_upload_dir = wp_upload_dir();
|
||||
|
||||
/**
|
||||
* Amazon S3 storage has s3://my-bucket/uploads upload path. If we found a scheme in the path we will
|
||||
* skip the realpath check so it won't fail in the future.
|
||||
* @url https://github.com/humanmade/S3-Uploads
|
||||
*/
|
||||
if (!stream_is_local($wp_upload_dir['basedir'])) {
|
||||
$uploadPath = $wp_upload_dir['basedir'];
|
||||
} else {
|
||||
$uploadPath = rtrim(realpath($wp_upload_dir['basedir']), "/\\");
|
||||
if (empty($uploadPath)) {
|
||||
echo 'Error: Your upload path is not valid or does not exist: ' . esc_html($wp_upload_dir['basedir']);
|
||||
$uploadPath = rtrim($wp_upload_dir['basedir'], "/\\");
|
||||
} else {
|
||||
$this->measurePermission($uploadPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (strpos($this->_basepath, $uploadPath) !== 0) {
|
||||
$this->paths[] = $uploadPath;
|
||||
}
|
||||
}
|
||||
|
||||
public function getImagesFolder() {
|
||||
return Platform::getPublicDirectory();
|
||||
}
|
||||
|
||||
public function getWebCachePath() {
|
||||
if (is_multisite()) {
|
||||
return $this->getBasePath() . NEXTEND_RELATIVE_CACHE_WEB . get_current_blog_id();
|
||||
}
|
||||
|
||||
return $this->getBasePath() . NEXTEND_RELATIVE_CACHE_WEB;
|
||||
}
|
||||
|
||||
public function getNotWebCachePath() {
|
||||
if (is_multisite()) {
|
||||
return $this->getBasePath() . NEXTEND_RELATIVE_CACHE_NOTWEB . get_current_blog_id();
|
||||
}
|
||||
|
||||
return $this->getBasePath() . NEXTEND_RELATIVE_CACHE_NOTWEB;
|
||||
}
|
||||
|
||||
public function absoluteURLToPath($url) {
|
||||
$uris = Url::getUris();
|
||||
|
||||
for ($i = count($uris) - 1; $i >= 0; $i--) {
|
||||
$uri = $uris[$i];
|
||||
if (substr($url, 0, strlen($uri)) == $uri) {
|
||||
|
||||
return str_replace($uri, $this->paths[$i], $url);
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function tempnam($filename = '', $dir = '') {
|
||||
return wp_tempnam($filename, $dir);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
|
||||
use Nextend\Framework\Form\ContainerInterface;
|
||||
|
||||
abstract class AbstractFontSource {
|
||||
|
||||
protected $name;
|
||||
|
||||
public abstract function getLabel();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function onFontManagerLoad($force = false) {
|
||||
|
||||
}
|
||||
|
||||
public function onFontManagerLoadBackend() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
abstract public function renderFields($container);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Font\Block\FontManager;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\Js\Js;
|
||||
use Nextend\Framework\Font\FontRenderer;
|
||||
use Nextend\Framework\Font\FontSettings;
|
||||
use Nextend\Framework\Font\ModelFont;
|
||||
use Nextend\Framework\Visual\AbstractBlockVisual;
|
||||
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonApply;
|
||||
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonCancel;
|
||||
|
||||
class BlockFontManager extends AbstractBlockVisual {
|
||||
|
||||
/** @var ModelFont */
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* @return ModelFont
|
||||
*/
|
||||
public function getModel() {
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
public function display() {
|
||||
|
||||
$this->model = new ModelFont($this);
|
||||
|
||||
$this->renderTemplatePart('Index');
|
||||
}
|
||||
|
||||
public function displayTopBar() {
|
||||
|
||||
$buttonCancel = new BlockButtonCancel($this);
|
||||
$buttonCancel->addClass('n2_fullscreen_editor__cancel');
|
||||
$buttonCancel->display();
|
||||
|
||||
$buttonApply = new BlockButtonApply($this);
|
||||
$buttonApply->addClass('n2_fullscreen_editor__save');
|
||||
$buttonApply->display();
|
||||
}
|
||||
|
||||
public function displayContent() {
|
||||
$model = $this->getModel();
|
||||
|
||||
Js::addFirstCode("
|
||||
_N2.CSSRendererFont.defaultFamily = " . json_encode(FontSettings::getDefaultFamily()) . ";
|
||||
_N2.CSSRendererFont.rendererModes = " . json_encode(FontRenderer::$mode) . ";
|
||||
_N2.CSSRendererFont.pre = " . json_encode(FontRenderer::$pre) . ";
|
||||
new _N2.NextendFontManager();
|
||||
");
|
||||
|
||||
$model->renderForm();
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Font\Block\FontManager;
|
||||
|
||||
/**
|
||||
* @var BlockFontManager $this
|
||||
*/
|
||||
?>
|
||||
<div id="n2-lightbox-font" class="n2_fullscreen_editor">
|
||||
<div class="n2_fullscreen_editor__overlay"></div>
|
||||
<div class="n2_fullscreen_editor__window">
|
||||
<div class="n2_fullscreen_editor__nav_bar">
|
||||
<div class="n2_fullscreen_editor__nav_bar_label">
|
||||
<?php n2_e('Font manager'); ?>
|
||||
</div>
|
||||
<div class="n2_fullscreen_editor__nav_bar_actions">
|
||||
<?php $this->displayTopBar(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n2_fullscreen_editor__content">
|
||||
<div class="n2_fullscreen_editor__content_content n2_container_scrollable">
|
||||
<?php $this->displayContent(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
use Nextend\Framework\Controller\Admin\AdminVisualManagerAjaxController;
|
||||
|
||||
class ControllerAjaxFont extends AdminVisualManagerAjaxController {
|
||||
|
||||
protected $type = 'font';
|
||||
|
||||
public function getModel() {
|
||||
|
||||
return new ModelFont($this);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
use Nextend\Framework\Font\Block\FontManager\BlockFontManager;
|
||||
use Nextend\Framework\Pattern\VisualManagerTrait;
|
||||
|
||||
class FontManager {
|
||||
|
||||
use VisualManagerTrait;
|
||||
|
||||
public function display() {
|
||||
|
||||
$fontManagerBlock = new BlockFontManager($this->MVCHelper);
|
||||
$fontManagerBlock->display();
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
|
||||
use Nextend\Framework\Misc\Base64;
|
||||
use Nextend\Framework\Model\Section;
|
||||
|
||||
class FontParser {
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function parse($data) {
|
||||
if (empty($data)) {
|
||||
return '';
|
||||
} else if (is_numeric($data)) {
|
||||
/**
|
||||
* Linked font
|
||||
*/
|
||||
|
||||
$font = Section::getById($data, 'font');
|
||||
|
||||
if (!$font) {
|
||||
/**
|
||||
* Linked font not exists anymore
|
||||
*/
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
if (is_string($font['value'])) {
|
||||
/**
|
||||
* Old format when value stored as Base64
|
||||
*/
|
||||
$decoded = $font['value'];
|
||||
if ($decoded[0] != '{') {
|
||||
$decoded = Base64::decode($decoded);
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value stored as array
|
||||
*/
|
||||
$value = json_encode($font['value']);
|
||||
if ($value == false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
} else if ($data[0] != '{') {
|
||||
return Base64::decode($data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
use Nextend\Framework\Settings;
|
||||
|
||||
class FontRenderer {
|
||||
|
||||
public static $defaultFont = 'Montserrat';
|
||||
|
||||
public static $pre = '';
|
||||
|
||||
/**
|
||||
* @var FontStyle
|
||||
*/
|
||||
public static $style;
|
||||
|
||||
public static $mode;
|
||||
|
||||
public static function setDefaultFont($fontFamily) {
|
||||
self::$defaultFont = $fontFamily;
|
||||
}
|
||||
|
||||
public static function render($font, $mode, $pre = '', $fontSize = false) {
|
||||
self::$pre = $pre;
|
||||
|
||||
if (!empty($font)) {
|
||||
$value = json_decode($font, true);
|
||||
if ($value) {
|
||||
$selector = 'n2-font-' . md5($font) . '-' . $mode;
|
||||
|
||||
return array(
|
||||
$selector . ' ',
|
||||
self::renderFont($mode, $pre, $selector, $value['data'], $fontSize)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function renderFont($mode, $pre, $selector, $tabs, $fontSize) {
|
||||
$search = array(
|
||||
'@pre',
|
||||
'@selector'
|
||||
);
|
||||
$replace = array(
|
||||
$pre,
|
||||
'.' . $selector
|
||||
);
|
||||
$tabs[0] = array_merge(array(
|
||||
'afont' => self::$defaultFont,
|
||||
'color' => '000000ff',
|
||||
'size' => '14||px',
|
||||
'tshadow' => '0|*|0|*|0|*|000000ff',
|
||||
'lineheight' => '1.5',
|
||||
'bold' => 0,
|
||||
'italic' => 0,
|
||||
'underline' => 0,
|
||||
'align' => 'left',
|
||||
'letterspacing' => "normal",
|
||||
'wordspacing' => "normal",
|
||||
'texttransform' => "none",
|
||||
'extra' => ''
|
||||
), $tabs[0]);
|
||||
|
||||
if (self::$mode[$mode]['renderOptions']['combined']) {
|
||||
for ($i = 1; $i < count($tabs); $i++) {
|
||||
$tabs[$i] = array_merge($tabs[$i - 1], $tabs[$i]);
|
||||
if ($tabs[$i]['size'] == $tabs[0]['size']) {
|
||||
$tabs[$i]['size'] = '100||%';
|
||||
} else {
|
||||
$size1 = explode('||', $tabs[0]['size']);
|
||||
$size2 = explode('||', $tabs[$i]['size']);
|
||||
if (isset($size1[1]) && isset($size2[1]) && $size1[1] == 'px' && $size2[1] == 'px') {
|
||||
$tabs[$i]['size'] = round($size2[0] / $size1[0] * 100) . '||%';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($tabs as $k => $tab) {
|
||||
$search[] = '@tab' . $k;
|
||||
FontStyle::$fontSize = $fontSize;
|
||||
$replace[] = self::$style->style($tab);
|
||||
}
|
||||
|
||||
$template = '';
|
||||
foreach (self::$mode[$mode]['selectors'] as $s => $style) {
|
||||
$key = array_search($style, $search);
|
||||
if (is_numeric($key) && !empty($replace[$key])) {
|
||||
$template .= $s . "{" . $style . "}";
|
||||
}
|
||||
}
|
||||
|
||||
return str_replace($search, $replace, $template);
|
||||
}
|
||||
}
|
||||
|
||||
$frontendAccessibility = intval(Settings::get('frontend-accessibility', 1));
|
||||
|
||||
FontRenderer::$mode = array(
|
||||
'0' => array(
|
||||
'id' => '0',
|
||||
'label' => n2_('Text'),
|
||||
'tabs' => array(
|
||||
n2_('Text')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => false
|
||||
),
|
||||
'preview' => '<div class="{fontClassName}">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>',
|
||||
'selectors' => array(
|
||||
'@pre@selector' => '@tab0'
|
||||
)
|
||||
),
|
||||
'simple' => array(
|
||||
'id' => 'simple',
|
||||
'label' => n2_('Text'),
|
||||
'tabs' => array(
|
||||
n2_('Text')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => false
|
||||
),
|
||||
'preview' => '<div class="{fontClassName}">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>',
|
||||
'selectors' => array(
|
||||
'@pre@selector' => '@tab0'
|
||||
)
|
||||
),
|
||||
'hover' => array(
|
||||
'id' => 'hover',
|
||||
'label' => n2_('Hover'),
|
||||
'tabs' => array(
|
||||
n2_('Text'),
|
||||
n2_('Hover')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => false
|
||||
),
|
||||
'preview' => '<div class="{fontClassName}">' . n2_('Heading') . '</div>',
|
||||
'selectors' => $frontendAccessibility ? array(
|
||||
'@pre@selector' => '@tab0',
|
||||
'@pre@selector:HOVER, @pre@selector:ACTIVE, @pre@selector:FOCUS' => '@tab1'
|
||||
) : array(
|
||||
'@pre@selector, @pre@selector:FOCUS' => '@tab0',
|
||||
'@pre@selector:HOVER, @pre@selector:ACTIVE' => '@tab1'
|
||||
)
|
||||
),
|
||||
'link' => array(
|
||||
'id' => 'link',
|
||||
'label' => n2_('Link'),
|
||||
'tabs' => array(
|
||||
n2_('Text'),
|
||||
n2_('Hover')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => false
|
||||
),
|
||||
'preview' => '<div class="{fontClassName}"><a href="#" onclick="return false;">' . n2_('Button') . '</a></div>',
|
||||
'selectors' => $frontendAccessibility ? array(
|
||||
'@pre@selector a' => '@tab0',
|
||||
'@pre@selector a:HOVER, @pre@selector a:ACTIVE, @pre@selector a:FOCUS' => '@tab1'
|
||||
) : array(
|
||||
'@pre@selector a, @pre@selector a:FOCUS' => '@tab0',
|
||||
'@pre@selector a:HOVER, @pre@selector a:ACTIVE' => '@tab1'
|
||||
)
|
||||
),
|
||||
'paragraph' => array(
|
||||
'id' => 'paragraph',
|
||||
'label' => n2_('Paragraph'),
|
||||
'tabs' => array(
|
||||
n2_('Text'),
|
||||
n2_('Link'),
|
||||
n2_('Hover')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => true
|
||||
),
|
||||
'preview' => '<div class="{fontClassName}">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do <a href="#">test link</a> incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in <a href="#">test link</a> velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat <a href="#">test link</a>, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>',
|
||||
'selectors' => array(
|
||||
'@pre@selector' => '@tab0',
|
||||
'@pre@selector a, @pre@selector a:FOCUS' => '@tab1',
|
||||
'@pre@selector a:HOVER, @pre@selector a:ACTIVE' => '@tab2'
|
||||
)
|
||||
),
|
||||
'input' => array(
|
||||
'id' => 'input',
|
||||
'label' => 'Input',
|
||||
'tabs' => array(
|
||||
n2_('Text'),
|
||||
n2_('Hover')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => false
|
||||
),
|
||||
'preview' => '<div class="{fontClassName}">Excepteur sint occaecat</div>',
|
||||
'selectors' => array(
|
||||
'@pre@selector' => '@tab0',
|
||||
'@pre@selector:HOVER, @pre@selector:FOCUS' => '@tab2'
|
||||
)
|
||||
),
|
||||
'dot' => array(
|
||||
'id' => 'dot',
|
||||
'label' => n2_('Dot'),
|
||||
'tabs' => array(
|
||||
n2_('Text'),
|
||||
n2_('Active')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => false
|
||||
),
|
||||
'preview' => '',
|
||||
'selectors' => array(
|
||||
'@pre@selector, @pre@selector:FOCUS' => '@tab0',
|
||||
'@pre@selector.n2-active, @pre@selector:HOVER, @pre@selector:ACTIVE' => '@tab1'
|
||||
)
|
||||
),
|
||||
'list' => array(
|
||||
'id' => 'list',
|
||||
'label' => n2_('List'),
|
||||
'tabs' => array(
|
||||
n2_('Text'),
|
||||
n2_('Link'),
|
||||
n2_('Hover')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => false
|
||||
),
|
||||
'preview' => '',
|
||||
'selectors' => array(
|
||||
'@pre@selector li' => '@tab0',
|
||||
'@pre@selector li a, @pre@selector li a:FOCUS' => '@tab1',
|
||||
'@pre@selector li a:HOVER, @pre@selector li a:ACTIVE' => '@tab2'
|
||||
)
|
||||
),
|
||||
'highlight' => array(
|
||||
'id' => 'highlight',
|
||||
'label' => n2_('Highlight'),
|
||||
'tabs' => array(
|
||||
n2_('Text'),
|
||||
n2_('Highlight'),
|
||||
n2_('Hover')
|
||||
),
|
||||
'renderOptions' => array(
|
||||
'combined' => true
|
||||
),
|
||||
'preview' => '<div class="{fontClassName}">' . n2_('Button') . '</div>',
|
||||
'selectors' => $frontendAccessibility ? array(
|
||||
'@pre@selector' => '@tab0',
|
||||
'@pre@selector .n2-highlighted' => '@tab1',
|
||||
'@pre@selector .n2-highlighted:HOVER, @pre@selector .n2-highlighted:ACTIVE, @pre@selector .n2-highlighted:FOCUS' => '@tab2'
|
||||
) : array(
|
||||
'@pre@selector' => '@tab0',
|
||||
'@pre@selector .n2-highlighted, @pre@selector .n2-highlighted:FOCUS' => '@tab1',
|
||||
'@pre@selector .n2-highlighted:HOVER, @pre@selector .n2-highlighted:ACTIVE' => '@tab2'
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
FontRenderer::$style = new FontStyle();
|
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
|
||||
use Nextend\Framework\Data\Data;
|
||||
use Nextend\Framework\Model\Section;
|
||||
|
||||
class FontSettings {
|
||||
|
||||
/**
|
||||
* @var Data
|
||||
*/
|
||||
private static $data;
|
||||
|
||||
/**
|
||||
* @var Data
|
||||
*/
|
||||
private static $pluginsData;
|
||||
|
||||
public function __construct() {
|
||||
self::load();
|
||||
FontRenderer::setDefaultFont(self::$data->get('default-family'));
|
||||
}
|
||||
|
||||
public static function load() {
|
||||
|
||||
self::$data = new Data(array(
|
||||
'default-family' => n2_x('Roboto,Arial', 'Default font'),
|
||||
'preset-families' => n2_x(implode("\n", array(
|
||||
"Abel",
|
||||
"Arial",
|
||||
"Arimo",
|
||||
"Average",
|
||||
"Bevan",
|
||||
"Bitter",
|
||||
"'Bree Serif'",
|
||||
"Cabin",
|
||||
"Calligraffitti",
|
||||
"Chewy",
|
||||
"Comfortaa",
|
||||
"'Covered By Your Grace'",
|
||||
"'Crafty Girls'",
|
||||
"'Dancing Script'",
|
||||
"'Noto Sans'",
|
||||
"'Noto Serif'",
|
||||
"'Francois One'",
|
||||
"'Fredoka One'",
|
||||
"'Gloria Hallelujah'",
|
||||
"'Happy Monkey'",
|
||||
"'Josefin Slab'",
|
||||
"Lato",
|
||||
"Lobster",
|
||||
"'Luckiest Guy'",
|
||||
"Montserrat",
|
||||
"'Nova Square'",
|
||||
"Nunito",
|
||||
"'Open Sans'",
|
||||
"Oswald",
|
||||
"Oxygen",
|
||||
"Pacifico",
|
||||
"'Permanent Marker'",
|
||||
"'Playfair Display'",
|
||||
"'PT Sans'",
|
||||
"'Poiret One'",
|
||||
"Raleway",
|
||||
"Roboto",
|
||||
"'Rock Salt'",
|
||||
"Quicksand",
|
||||
"Satisfy",
|
||||
"'Squada One'",
|
||||
"'The Girl Next Door'",
|
||||
"'Titillium Web'",
|
||||
"'Varela Round'",
|
||||
"Vollkorn",
|
||||
"'Walter Turncoat'"
|
||||
)), 'Default font family list'),
|
||||
'plugins' => array()
|
||||
));
|
||||
|
||||
foreach (Section::getAll('system', 'fonts') as $data) {
|
||||
self::$data->set($data['referencekey'], $data['value']);
|
||||
}
|
||||
|
||||
self::$pluginsData = new Data(self::$data->get('plugins'), true);
|
||||
}
|
||||
|
||||
public static function store($data) {
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $key => $value) {
|
||||
if (self::$data->has($key)) {
|
||||
self::$data->set($key, $value);
|
||||
Section::set('system', 'fonts', $key, $value, 1, 1);
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
if (count($data)) {
|
||||
self::$pluginsData = new Data($data);
|
||||
Section::set('system', 'fonts', 'plugins', self::$pluginsData->toJSON(), 1, 1);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Data
|
||||
*/
|
||||
public static function getData() {
|
||||
|
||||
return self::$data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Data
|
||||
*/
|
||||
public static function getPluginsData() {
|
||||
|
||||
return self::$pluginsData;
|
||||
}
|
||||
|
||||
public static function getDefaultFamily() {
|
||||
return self::$data->get('default-family');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getPresetFamilies() {
|
||||
return array_filter(explode("\n", self::$data->get('preset-families')));
|
||||
}
|
||||
}
|
||||
|
||||
new FontSettings();
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
|
||||
use Nextend\Framework\Filesystem\Filesystem;
|
||||
|
||||
class FontSources {
|
||||
|
||||
/** @var AbstractFontSource[] */
|
||||
private static $fontSources = array();
|
||||
|
||||
public function __construct() {
|
||||
$dir = dirname(__FILE__) . '/Sources/';
|
||||
foreach (Filesystem::folders($dir) as $folder) {
|
||||
$file = $dir . $folder . '/' . $folder . '.php';
|
||||
if (Filesystem::fileexists($file)) {
|
||||
require_once($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
*/
|
||||
public static function registerSource($class) {
|
||||
|
||||
/** @var AbstractFontSource $source */
|
||||
$source = new $class();
|
||||
|
||||
self::$fontSources[$source->getName()] = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractFontSource[]
|
||||
*/
|
||||
public static function getFontSources() {
|
||||
return self::$fontSources;
|
||||
}
|
||||
|
||||
public static function onFontManagerLoad($force = false) {
|
||||
foreach (self::$fontSources as $source) {
|
||||
$source->onFontManagerLoad($force);
|
||||
}
|
||||
}
|
||||
|
||||
public static function onFontManagerLoadBackend() {
|
||||
foreach (self::$fontSources as $source) {
|
||||
$source->onFontManagerLoadBackend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new FontSources();
|
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
use Nextend\Framework\Pattern\SingletonTrait;
|
||||
use Nextend\Framework\Plugin;
|
||||
|
||||
class FontStorage {
|
||||
|
||||
use SingletonTrait;
|
||||
|
||||
private $sets = array();
|
||||
|
||||
private $fonts = array();
|
||||
|
||||
private $fontsBySet = array();
|
||||
|
||||
private $fontsById = array();
|
||||
|
||||
protected function init() {
|
||||
|
||||
Plugin::addAction('systemfontset', array(
|
||||
$this,
|
||||
'fontSet'
|
||||
));
|
||||
Plugin::addAction('systemfont', array(
|
||||
$this,
|
||||
'fonts'
|
||||
));
|
||||
Plugin::addAction('font', array(
|
||||
$this,
|
||||
'font'
|
||||
));
|
||||
}
|
||||
|
||||
private function load() {
|
||||
static $loaded;
|
||||
if (!$loaded) {
|
||||
Plugin::doAction('fontStorage', array(
|
||||
&$this->sets,
|
||||
&$this->fonts
|
||||
));
|
||||
|
||||
for ($i = 0; $i < count($this->fonts); $i++) {
|
||||
if (!isset($this->fontsBySet[$this->fonts[$i]['referencekey']])) {
|
||||
$this->fontsBySet[$this->fonts[$i]['referencekey']] = array();
|
||||
}
|
||||
$this->fontsBySet[$this->fonts[$i]['referencekey']][] = &$this->fonts[$i];
|
||||
$this->fontsById[$this->fonts[$i]['id']] = &$this->fonts[$i];
|
||||
}
|
||||
$loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function fontSet($referenceKey, &$sets) {
|
||||
|
||||
$this->load();
|
||||
|
||||
for ($i = count($this->sets) - 1; $i >= 0; $i--) {
|
||||
$this->sets[$i]['isSystem'] = 1;
|
||||
$this->sets[$i]['editable'] = 0;
|
||||
array_unshift($sets, $this->sets[$i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function fonts($referenceKey, &$fonts) {
|
||||
|
||||
$this->load();
|
||||
|
||||
if (isset($this->fontsBySet[$referenceKey])) {
|
||||
$_fonts = &$this->fontsBySet[$referenceKey];
|
||||
for ($i = count($_fonts) - 1; $i >= 0; $i--) {
|
||||
$_fonts[$i]['isSystem'] = 1;
|
||||
$_fonts[$i]['editable'] = 0;
|
||||
array_unshift($fonts, $_fonts[$i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function font($id, &$font) {
|
||||
|
||||
$this->load();
|
||||
|
||||
if (isset($this->fontsById[$id])) {
|
||||
$this->fontsById[$id]['isSystem'] = 1;
|
||||
$this->fontsById[$id]['editable'] = 0;
|
||||
$font = $this->fontsById[$id];
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
|
||||
use Nextend\Framework\Parser\Color;
|
||||
use Nextend\Framework\Parser\Common;
|
||||
use Nextend\Framework\Plugin;
|
||||
use Nextend\Framework\Sanitize;
|
||||
|
||||
class FontStyle {
|
||||
|
||||
public static $fontSize = false;
|
||||
|
||||
/**
|
||||
* @param string $tab
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function style($tab) {
|
||||
$style = '';
|
||||
$extra = '';
|
||||
if (isset($tab['extra'])) {
|
||||
$extra = $tab['extra'];
|
||||
unset($tab['extra']);
|
||||
}
|
||||
foreach ($tab as $k => $v) {
|
||||
$style .= $this->parse($k, $v);
|
||||
}
|
||||
$style .= $this->parse('extra', $extra);
|
||||
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $property
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function parse($property, $value) {
|
||||
$fn = 'parse' . $property;
|
||||
|
||||
return $this->$fn($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseColor($v) {
|
||||
$hex = Color::hex82hex($v);
|
||||
if ($hex[1] == 'ff') {
|
||||
return 'color: #' . $hex[0] . ';';
|
||||
}
|
||||
|
||||
$rgba = Color::hex2rgba($v);
|
||||
|
||||
return 'color: RGBA(' . $rgba[0] . ',' . $rgba[1] . ',' . $rgba[2] . ',' . round($rgba[3] / 127, 2) . ');';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseSize($v) {
|
||||
if (self::$fontSize) {
|
||||
$fontSize = Common::parse($v);
|
||||
if ($fontSize[1] == 'px') {
|
||||
return 'font-size:' . ($fontSize[0] / self::$fontSize * 100) . '%;';
|
||||
}
|
||||
}
|
||||
|
||||
return 'font-size:' . Sanitize::esc_css_value(Common::parse($v, '')) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseTshadow($v) {
|
||||
$v = Common::parse($v);
|
||||
$rgba = Color::hex2rgba($v[3]);
|
||||
if ($v[0] == 0 && $v[1] == 0 && $v[2] == 0) return 'text-shadow: none;';
|
||||
|
||||
return 'text-shadow: ' . Sanitize::esc_css_value($v[0]) . 'px ' . Sanitize::esc_css_value($v[1]) . 'px ' . Sanitize::esc_css_value($v[2]) . 'px RGBA(' . $rgba[0] . ',' . $rgba[1] . ',' . $rgba[2] . ',' . round($rgba[3] / 127, 2) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseAfont($v) {
|
||||
return 'font-family: ' . $this->loadFont(Sanitize::esc_css_value($v)) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseLineheight($v) {
|
||||
if ($v == '') return '';
|
||||
|
||||
return 'line-height: ' . Sanitize::esc_css_value($v) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseBold($v) {
|
||||
return $this->parseWeight($v);
|
||||
}
|
||||
|
||||
public function parseWeight($v) {
|
||||
if ($v == '1') return 'font-weight: bold;';
|
||||
if ($v > 1) return 'font-weight: ' . intval($v) . ';';
|
||||
|
||||
return 'font-weight: normal;';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseItalic($v) {
|
||||
if ($v == '1') return 'font-style: italic;';
|
||||
|
||||
return 'font-style: normal;';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseUnderline($v) {
|
||||
if ($v == '1') return 'text-decoration: underline;';
|
||||
|
||||
return 'text-decoration: none;';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $v
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseAlign($v) {
|
||||
return 'text-align: ' . Sanitize::esc_css_value($v) . ';';
|
||||
}
|
||||
|
||||
public function parseLetterSpacing($v) {
|
||||
return 'letter-spacing: ' . Sanitize::esc_css_value($v) . ';';
|
||||
}
|
||||
|
||||
public function parseWordSpacing($v) {
|
||||
return 'word-spacing: ' . Sanitize::esc_css_value($v) . ';';
|
||||
}
|
||||
|
||||
public function parseTextTransform($v) {
|
||||
return 'text-transform: ' . Sanitize::esc_css_value($v) . ';';
|
||||
}
|
||||
|
||||
public function parseExtra($v) {
|
||||
|
||||
return Sanitize::esc_css_string($v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $families
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function loadFont($families) {
|
||||
$families = explode(',', $families);
|
||||
for ($i = 0; $i < count($families); $i++) {
|
||||
if ($families[$i] != "inherit") {
|
||||
$families[$i] = $this->getFamily(trim(trim($families[$i]), '\'"'));
|
||||
}
|
||||
}
|
||||
|
||||
return implode(',', $families);
|
||||
}
|
||||
|
||||
private function getFamily($family) {
|
||||
return "'" . Plugin::applyFilters('fontFamily', $family) . "'";
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Font;
|
||||
|
||||
use Nextend\Framework\Form\Container\ContainerTable;
|
||||
use Nextend\Framework\Form\Element\Button;
|
||||
use Nextend\Framework\Form\Element\Decoration;
|
||||
use Nextend\Framework\Form\Element\MixedField;
|
||||
use Nextend\Framework\Form\Element\Radio\TextAlign;
|
||||
use Nextend\Framework\Form\Element\Select;
|
||||
use Nextend\Framework\Form\Element\Select\FontWeight;
|
||||
use Nextend\Framework\Form\Element\Tab;
|
||||
use Nextend\Framework\Form\Element\Text\Color;
|
||||
use Nextend\Framework\Form\Element\Text\Family;
|
||||
use Nextend\Framework\Form\Element\Text\TextAutoComplete;
|
||||
use Nextend\Framework\Form\Element\Textarea;
|
||||
use Nextend\Framework\Form\Form;
|
||||
use Nextend\Framework\Visual\ModelVisual;
|
||||
|
||||
class ModelFont extends ModelVisual {
|
||||
|
||||
protected $type = 'font';
|
||||
|
||||
public function renderForm() {
|
||||
|
||||
$form = new Form($this, 'n2-font-editor');
|
||||
|
||||
$table = new ContainerTable($form->getContainer(), 'font', n2_('Font settings'));
|
||||
|
||||
$table->setFieldsetPositionEnd();
|
||||
|
||||
new Button($table->getFieldsetLabel(), 'font-clear-tab', false, n2_('Clear tab'));
|
||||
|
||||
new Tab($table->getFieldsetLabel(), 'font-state');
|
||||
|
||||
$row1 = $table->createRow('font-row-1');
|
||||
new Family($row1, 'family', n2_('Family'), 'Arial, Helvetica', array(
|
||||
'style' => 'width:150px;'
|
||||
));
|
||||
new Color($row1, 'color', n2_('Color'), '000000FF', array(
|
||||
'alpha' => true
|
||||
));
|
||||
|
||||
new MixedField\FontSize($row1, 'size', n2_('Size'), '14|*|px');
|
||||
|
||||
new FontWeight($row1, 'weight', n2_('Font weight'), '');
|
||||
new Decoration($row1, 'decoration', n2_('Decoration'));
|
||||
new TextAutoComplete($row1, 'lineheight', n2_('Line height'), '18px', array(
|
||||
'values' => array(
|
||||
'normal',
|
||||
'1',
|
||||
'1.2',
|
||||
'1.5',
|
||||
'1.8',
|
||||
'2'
|
||||
),
|
||||
'style' => 'width:70px;'
|
||||
));
|
||||
new TextAlign($row1, 'textalign', n2_('Text align'), 'inherit');
|
||||
|
||||
$row2 = $table->createRow('font-row-2');
|
||||
|
||||
new TextAutoComplete($row2, 'letterspacing', n2_('Letter spacing'), 'normal', array(
|
||||
'values' => array(
|
||||
'normal',
|
||||
'1px',
|
||||
'2px',
|
||||
'5px',
|
||||
'10px',
|
||||
'15px'
|
||||
),
|
||||
'style' => 'width:50px;'
|
||||
));
|
||||
new TextAutoComplete($row2, 'wordspacing', n2_('Word spacing'), 'normal', array(
|
||||
'values' => array(
|
||||
'normal',
|
||||
'2px',
|
||||
'5px',
|
||||
'10px',
|
||||
'15px'
|
||||
),
|
||||
'style' => 'width:50px;'
|
||||
));
|
||||
new Select($row2, 'texttransform', n2_('Transform'), 'none', array(
|
||||
'options' => array(
|
||||
'none' => n2_('None'),
|
||||
'capitalize' => n2_('Capitalize'),
|
||||
'uppercase' => n2_('Uppercase'),
|
||||
'lowercase' => n2_('Lowercase')
|
||||
)
|
||||
));
|
||||
|
||||
new MixedField\TextShadow($row2, 'tshadow', n2_('Text shadow'), '0|*|0|*|1|*|000000FF');
|
||||
|
||||
new Textarea($row2, 'extracss', 'CSS', '', array(
|
||||
'width' => 200,
|
||||
'height' => 26
|
||||
));
|
||||
|
||||
$previewTable = new ContainerTable($form->getContainer(), 'font-preview', n2_('Preview'));
|
||||
|
||||
$previewTable->setFieldsetPositionEnd();
|
||||
|
||||
new Color($previewTable->getFieldsetLabel(), 'preview-background', false, 'ced3d5');
|
||||
|
||||
$form->render();
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Font\Sources\GoogleFonts;
|
||||
|
||||
use Nextend\Framework\Asset\AssetManager;
|
||||
use Nextend\Framework\Asset\Fonts\Google\Google;
|
||||
use Nextend\Framework\Asset\Js\Js;
|
||||
use Nextend\Framework\Font\AbstractFontSource;
|
||||
use Nextend\Framework\Font\FontSettings;
|
||||
use Nextend\Framework\Font\FontSources;
|
||||
use Nextend\Framework\Form\Container\ContainerRowGroup;
|
||||
use Nextend\Framework\Form\Element\OnOff;
|
||||
use Nextend\Framework\Form\Fieldset\FieldsetRow;
|
||||
use Nextend\Framework\Platform\Platform;
|
||||
use Nextend\Framework\Plugin;
|
||||
|
||||
|
||||
/*
|
||||
jQuery.getJSON('https://www.googleapis.com/webfonts/v1/webfonts?sort=alpha&key=AIzaSyBIzBtder0-ef5a6kX-Ri9IfzVwFu21PGw').done(function(data){
|
||||
var f = [];
|
||||
for(var i = 0; i < data.items.length; i++){
|
||||
f.push(data.items[i].family);
|
||||
}
|
||||
|
||||
var fontString='';
|
||||
f.forEach(function(font){
|
||||
fontString+= font+'\n';
|
||||
});
|
||||
|
||||
console.log(fontString);
|
||||
});
|
||||
*/
|
||||
|
||||
class GoogleFonts extends AbstractFontSource {
|
||||
|
||||
protected $name = 'google';
|
||||
|
||||
private static $fonts = array();
|
||||
|
||||
private static $styles = array();
|
||||
|
||||
public function __construct() {
|
||||
$lines = file(dirname(__FILE__) . '/families.csv', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
for ($i = 0; $i < count($lines); $i++) {
|
||||
self::$fonts[strtolower($lines[$i])] = $lines[$i];
|
||||
}
|
||||
self::$fonts['droid sans'] = 'Noto Sans';
|
||||
self::$fonts['droid sans mono'] = 'Roboto Mono';
|
||||
self::$fonts['droid serif'] = 'Noto Serif';
|
||||
}
|
||||
|
||||
public function getLabel() {
|
||||
return 'Google';
|
||||
}
|
||||
|
||||
public function renderFields($container) {
|
||||
|
||||
$row1 = new FieldsetRow($container, 'fonts-google-1');
|
||||
new OnOff($row1, 'google-enabled', n2_('Frontend'), 1, array(
|
||||
'tipLabel' => n2_('Frontend'),
|
||||
'tipDescription' => n2_('You can load Google Fonts on the frontend.'),
|
||||
'relatedFieldsOn' => array(
|
||||
'fontsgoogle-cache'
|
||||
)
|
||||
));
|
||||
new OnOff($row1, 'google-cache', n2_('Save fonts locally'), 0, array(
|
||||
'tipLabel' => n2_('Save fonts locally'),
|
||||
'tipDescription' => n2_('You can store the used Google Fonts on your server. This way all Google Fonts will load from your own domain.'),
|
||||
'tipLink' => 'https://smartslider.helpscoutdocs.com/article/1787-fonts#google'
|
||||
));
|
||||
new OnOff($row1, 'google-enabled-backend', n2_('Backend'), 1, array(
|
||||
'tipLabel' => n2_('Backend'),
|
||||
'tipDescription' => n2_('You can load Google Fonts in the backend.')
|
||||
));
|
||||
|
||||
$rowGroupStyle = new ContainerRowGroup($container, 'fonts-google-style', n2_('Style'));
|
||||
$rowStyle = $rowGroupStyle->createRow('fonts-google-style');
|
||||
new OnOff($rowStyle, 'google-style-100', '100', 0);
|
||||
new OnOff($rowStyle, 'google-style-100italic', '100 ' . n2_x('Italic', "Font style"), 0);
|
||||
new OnOff($rowStyle, 'google-style-200', '200', 0);
|
||||
new OnOff($rowStyle, 'google-style-200italic', '200 ' . n2_x('Italic', "Font style"), 0);
|
||||
new OnOff($rowStyle, 'google-style-300', '300', 1);
|
||||
new OnOff($rowStyle, 'google-style-300italic', '300 ' . n2_x('Italic', "Font style"), 0);
|
||||
new OnOff($rowStyle, 'google-style-400', n2_('Normal'), 1);
|
||||
new OnOff($rowStyle, 'google-style-400italic', n2_('Normal') . ' ' . n2_x('Italic', "Font style"), 0);
|
||||
new OnOff($rowStyle, 'google-style-500', '500', 0);
|
||||
new OnOff($rowStyle, 'google-style-500italic', '500 ' . n2_x('Italic', "Font style"), 0);
|
||||
new OnOff($rowStyle, 'google-style-600', '600', 0);
|
||||
new OnOff($rowStyle, 'google-style-600italic', '600 ' . n2_x('Italic', "Font style"), 0);
|
||||
new OnOff($rowStyle, 'google-style-700', '700', 0);
|
||||
new OnOff($rowStyle, 'google-style-700italic', '700 ' . n2_x('Italic', "Font style"), 0);
|
||||
new OnOff($rowStyle, 'google-style-800', '800', 0);
|
||||
new OnOff($rowStyle, 'google-style-800italic', '800 ' . n2_x('Italic', "Font style"), 0);
|
||||
new OnOff($rowStyle, 'google-style-900', '900', 0);
|
||||
new OnOff($rowStyle, 'google-style-900italic', '900 ' . n2_x('Italic', "Font style"), 0);
|
||||
}
|
||||
|
||||
public function getPath() {
|
||||
return dirname(__FILE__) . DIRECTORY_SEPARATOR . 'google' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
public function onFontManagerLoad($force = false) {
|
||||
static $loaded;
|
||||
if (!$loaded || $force) {
|
||||
$loaded = true;
|
||||
$parameters = FontSettings::getPluginsData();
|
||||
|
||||
if ((!Platform::isAdmin() && $parameters->get('google-enabled', 1)) || (Platform::isAdmin() && $parameters->get('google-enabled-backend', 1))) {
|
||||
Google::$enabled = 1;
|
||||
|
||||
for ($i = 100; $i < 1000; $i += 100) {
|
||||
$this->addStyle($parameters, $i);
|
||||
$this->addStyle($parameters, $i . 'italic');
|
||||
}
|
||||
if (empty(self::$styles)) {
|
||||
self::$styles[] = '300';
|
||||
self::$styles[] = '400';
|
||||
}
|
||||
|
||||
Plugin::addAction('fontFamily', array(
|
||||
$this,
|
||||
'onFontFamily'
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function onFontManagerLoadBackend() {
|
||||
$parameters = FontSettings::getPluginsData();
|
||||
|
||||
if ($parameters->get('google-enabled-backend', 1)) {
|
||||
Js::addInline('new _N2.NextendFontServiceGoogle("' . implode(',', self::$styles) . '", ' . json_encode(self::$fonts) . ', ' . json_encode(AssetManager::$googleFonts->getLoadedFamilies()) . ');');
|
||||
}
|
||||
}
|
||||
|
||||
function addStyle($parameters, $weight) {
|
||||
if ($parameters->get('google-style-' . $weight, 0)) {
|
||||
self::$styles[] = $weight;
|
||||
}
|
||||
}
|
||||
|
||||
function onFontFamily($family) {
|
||||
$familyLower = strtolower($family);
|
||||
if (isset(self::$fonts[$familyLower])) {
|
||||
foreach (self::$styles as $style) {
|
||||
Google::addFont(self::$fonts[$familyLower], $style);
|
||||
}
|
||||
|
||||
return self::$fonts[$familyLower];
|
||||
}
|
||||
|
||||
return $family;
|
||||
}
|
||||
}
|
||||
|
||||
FontSources::registerSource(GoogleFonts::class);
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form;
|
||||
|
||||
|
||||
abstract class AbstractContainer implements ContainerContainedInterface {
|
||||
|
||||
use TraitContainer;
|
||||
|
||||
/**
|
||||
* @var ContainerContainedInterface
|
||||
*/
|
||||
protected $first, $last;
|
||||
|
||||
protected $controlName = '';
|
||||
|
||||
/**
|
||||
* @var ContainerInterface;
|
||||
*/
|
||||
private $previous, $next;
|
||||
|
||||
public function getPrevious() {
|
||||
return $this->previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainedInterface|null $element
|
||||
*/
|
||||
public function setPrevious($element = null) {
|
||||
$this->previous = $element;
|
||||
}
|
||||
|
||||
public function getNext() {
|
||||
return $this->next;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainedInterface|null $element
|
||||
*/
|
||||
public function setNext($element = null) {
|
||||
$this->next = $element;
|
||||
if ($element) {
|
||||
$element->setPrevious($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove() {
|
||||
$this->getParent()
|
||||
->removeElement($this);
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$this->renderContainer();
|
||||
}
|
||||
|
||||
public function renderContainer() {
|
||||
$element = $this->first;
|
||||
while ($element) {
|
||||
$element->renderContainer();
|
||||
$element = $element->getNext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getControlName() {
|
||||
return $this->controlName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $controlName
|
||||
*/
|
||||
public function setControlName($controlName) {
|
||||
$this->controlName = $controlName;
|
||||
}
|
||||
}
|
@ -0,0 +1,376 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\Js\Js;
|
||||
use Nextend\Framework\Form\Insert\AbstractInsert;
|
||||
use Nextend\Framework\Sanitize;
|
||||
use Nextend\Framework\View\Html;
|
||||
|
||||
abstract class AbstractField implements ContainedInterface {
|
||||
|
||||
/**
|
||||
* @var AbstractField;
|
||||
*/
|
||||
private $previous, $next;
|
||||
|
||||
public function getPrevious() {
|
||||
return $this->previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AbstractField|null $element
|
||||
*/
|
||||
public function setPrevious($element = null) {
|
||||
$this->previous = $element;
|
||||
}
|
||||
|
||||
public function getNext() {
|
||||
return $this->next;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AbstractField|null $element
|
||||
*/
|
||||
public function setNext($element = null) {
|
||||
$this->next = $element;
|
||||
if ($element) {
|
||||
$element->setPrevious($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove() {
|
||||
$this->getParent()
|
||||
->removeElement($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var TraitFieldset
|
||||
*/
|
||||
protected $parent;
|
||||
|
||||
protected $name = '';
|
||||
|
||||
protected $label = '';
|
||||
|
||||
protected $controlName = '';
|
||||
|
||||
protected $defaultValue;
|
||||
|
||||
protected $fieldID;
|
||||
|
||||
private $exposeName = true;
|
||||
|
||||
protected $tip = '';
|
||||
|
||||
protected $tipLabel = '';
|
||||
|
||||
protected $tipDescription = '';
|
||||
|
||||
protected $tipLink = '';
|
||||
|
||||
protected $rowClass = '';
|
||||
|
||||
protected $rowAttributes = array();
|
||||
|
||||
protected $class = '';
|
||||
|
||||
protected $style = '';
|
||||
|
||||
protected $post = '';
|
||||
|
||||
protected $relatedFields = array();
|
||||
|
||||
protected $relatedFieldsOff = array();
|
||||
|
||||
/**
|
||||
* AbstractField constructor.
|
||||
*
|
||||
* @param TraitFieldset|AbstractInsert $insertAt
|
||||
* @param string $name
|
||||
* @param string $label
|
||||
* @param string $default
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function __construct($insertAt, $name = '', $label = '', $default = '', $parameters = array()) {
|
||||
|
||||
$this->name = $name;
|
||||
$this->label = $label;
|
||||
|
||||
if ($insertAt instanceof ContainerInterface) {
|
||||
$this->parent = $insertAt;
|
||||
$this->parent->addElement($this);
|
||||
} else if ($insertAt instanceof AbstractInsert) {
|
||||
$this->parent = $insertAt->insert($this);
|
||||
}
|
||||
|
||||
$this->controlName = $this->parent->getControlName();
|
||||
|
||||
$this->fieldID = $this->generateId($this->controlName . $this->name);
|
||||
|
||||
$this->defaultValue = $default;
|
||||
|
||||
foreach ($parameters as $option => $value) {
|
||||
$option = 'set' . $option;
|
||||
$this->{$option}($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getID() {
|
||||
return $this->fieldID;
|
||||
}
|
||||
|
||||
public function setDefaultValue($defaultValue) {
|
||||
$this->defaultValue = $defaultValue;
|
||||
}
|
||||
|
||||
public function setExposeName($exposeName) {
|
||||
$this->exposeName = $exposeName;
|
||||
}
|
||||
|
||||
public function getPost() {
|
||||
return $this->post;
|
||||
}
|
||||
|
||||
public function setPost($post) {
|
||||
$this->post = $post;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tip
|
||||
*/
|
||||
public function setTip($tip) {
|
||||
$this->tip = $tip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tipLabel
|
||||
*/
|
||||
public function setTipLabel($tipLabel) {
|
||||
$this->tipLabel = $tipLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tipDescription
|
||||
*/
|
||||
public function setTipDescription($tipDescription) {
|
||||
$this->tipDescription = $tipDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tipLink
|
||||
*/
|
||||
public function setTipLink($tipLink) {
|
||||
$this->tipLink = $tipLink;
|
||||
}
|
||||
|
||||
public function setRowClass($rowClass) {
|
||||
$this->rowClass .= $rowClass;
|
||||
}
|
||||
|
||||
public function getRowClass() {
|
||||
return $this->rowClass;
|
||||
}
|
||||
|
||||
public function getClass() {
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function setClass($class) {
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
protected function getFieldName() {
|
||||
if ($this->exposeName) {
|
||||
return $this->controlName . '[' . $this->name . ']';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function render() {
|
||||
|
||||
return array(
|
||||
$this->fetchTooltip(),
|
||||
$this->fetchElement()
|
||||
);
|
||||
}
|
||||
|
||||
public function displayLabel() {
|
||||
echo wp_kses($this->fetchTooltip(), Sanitize::$adminFormTags);
|
||||
}
|
||||
|
||||
public function displayElement() {
|
||||
echo wp_kses($this->fetchElement(), Sanitize::$adminFormTags);
|
||||
}
|
||||
|
||||
protected function fetchTooltip() {
|
||||
|
||||
if ($this->label === false || $this->label === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$attributes = array(
|
||||
'for' => $this->fieldID
|
||||
);
|
||||
|
||||
|
||||
$post = '';
|
||||
if (!empty($this->tipDescription)) {
|
||||
$tipAttributes = array(
|
||||
'class' => 'ssi_16 ssi_16--info',
|
||||
'data-tip-description' => $this->tipDescription
|
||||
);
|
||||
if (!empty($this->tipLabel)) {
|
||||
$tipAttributes['data-tip-label'] = $this->tipLabel;
|
||||
}
|
||||
if (!empty($this->tipLink)) {
|
||||
$tipAttributes['data-tip-link'] = $this->tipLink;
|
||||
}
|
||||
$post .= Html::tag('i', $tipAttributes);
|
||||
}
|
||||
|
||||
return Html::tag('label', $attributes, $this->label) . $post;
|
||||
}
|
||||
|
||||
protected function fetchNoTooltip() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function fetchElement();
|
||||
|
||||
public function getValue() {
|
||||
return $this->getForm()
|
||||
->get($this->name, $this->defaultValue);
|
||||
}
|
||||
|
||||
public function setValue($value) {
|
||||
$this->parent->getForm()
|
||||
->set($this->name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $rowAttributes
|
||||
*/
|
||||
public function setRowAttributes($rowAttributes) {
|
||||
$this->rowAttributes = $rowAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRowAttributes() {
|
||||
return $this->rowAttributes;
|
||||
}
|
||||
|
||||
public function setStyle($style) {
|
||||
$this->style = $style;
|
||||
}
|
||||
|
||||
protected function getStyle() {
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $relatedFields
|
||||
*/
|
||||
public function setRelatedFields($relatedFields) {
|
||||
$this->relatedFields = $relatedFields;
|
||||
}
|
||||
|
||||
public function setRelatedFieldsOff($relatedFieldsOff) {
|
||||
$this->relatedFieldsOff = $relatedFieldsOff;
|
||||
}
|
||||
|
||||
protected function renderRelatedFields() {
|
||||
if (!empty($this->relatedFields) || !empty($this->relatedFieldsOff)) {
|
||||
$options = array(
|
||||
'relatedFieldsOn' => $this->relatedFields,
|
||||
'relatedFieldsOff' => $this->relatedFieldsOff
|
||||
);
|
||||
Js::addInline('new _N2.FormRelatedFields("' . $this->fieldID . '", ' . json_encode($options) . ');');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateId($name) {
|
||||
|
||||
return str_replace(array(
|
||||
'[',
|
||||
']',
|
||||
' '
|
||||
), array(
|
||||
'',
|
||||
'',
|
||||
''
|
||||
), $name);
|
||||
}
|
||||
|
||||
public function getLabelClass() {
|
||||
if ($this->label === false) {
|
||||
return 'n2_field--label-none';
|
||||
} else if ($this->label === '') {
|
||||
return 'n2_field--label-placeholder';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLabel() {
|
||||
return !empty($this->label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Form
|
||||
*/
|
||||
public function getForm() {
|
||||
return $this->parent->getForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getControlName() {
|
||||
return $this->controlName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $controlName
|
||||
*/
|
||||
public function setControlName($controlName) {
|
||||
$this->controlName = $controlName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TraitFieldset
|
||||
*/
|
||||
public function getParent() {
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function getPath() {
|
||||
return $this->parent->getPath() . '/' . $this->name;
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form;
|
||||
|
||||
use Nextend\Framework\Form\Insert\AbstractInsert;
|
||||
|
||||
abstract class AbstractFieldset implements ContainerContainedInterface {
|
||||
|
||||
use TraitFieldset;
|
||||
|
||||
/**
|
||||
* @var ContainedInterface;
|
||||
*/
|
||||
private $previous, $next;
|
||||
|
||||
public function getPrevious() {
|
||||
return $this->previous;
|
||||
}
|
||||
|
||||
public function setPrevious($element = null) {
|
||||
$this->previous = $element;
|
||||
}
|
||||
|
||||
public function getNext() {
|
||||
return $this->next;
|
||||
}
|
||||
|
||||
public function setNext($element = null) {
|
||||
$this->next = $element;
|
||||
if ($element) {
|
||||
$element->setPrevious($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove() {
|
||||
$this->getParent()
|
||||
->removeElement($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $parent;
|
||||
|
||||
protected $name = '';
|
||||
|
||||
protected $label = '';
|
||||
|
||||
protected $controlName = '';
|
||||
|
||||
protected $class = '';
|
||||
|
||||
/**
|
||||
* Container constructor.
|
||||
*
|
||||
* @param ContainerInterface|AbstractInsert $insertAt
|
||||
* @param $name
|
||||
* @param boolean|string $label
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function __construct($insertAt, $name, $label = false, $parameters = array()) {
|
||||
|
||||
$this->name = $name;
|
||||
$this->label = $label;
|
||||
|
||||
if ($insertAt instanceof ContainerInterface) {
|
||||
$this->parent = $insertAt;
|
||||
$this->parent->addElement($this);
|
||||
} else if ($insertAt instanceof AbstractInsert) {
|
||||
$this->parent = $insertAt->insert($this);
|
||||
}
|
||||
|
||||
$this->controlName = $this->parent->getControlName();
|
||||
|
||||
foreach ($parameters as $option => $value) {
|
||||
$option = 'set' . $option;
|
||||
$this->{$option}($value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$this->renderContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AbstractField $element
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function decorateElement($element) {
|
||||
|
||||
ob_start();
|
||||
|
||||
$element->displayElement();
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLabel() {
|
||||
return !empty($this->label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Form
|
||||
*/
|
||||
public function getForm() {
|
||||
return $this->parent->getForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getControlName() {
|
||||
return $this->controlName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $controlName
|
||||
*/
|
||||
public function setControlName($controlName) {
|
||||
$this->controlName = $controlName;
|
||||
}
|
||||
|
||||
public function hasFields() {
|
||||
|
||||
return !empty($this->flattenElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
*/
|
||||
public function setClass($class) {
|
||||
$this->class = $class;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form;
|
||||
|
||||
|
||||
use Nextend\Framework\Pattern\MVCHelperTrait;
|
||||
|
||||
abstract class AbstractFormManager {
|
||||
|
||||
use MVCHelperTrait;
|
||||
|
||||
/**
|
||||
* AbstractFormManager constructor.
|
||||
*
|
||||
* @param MVCHelperTrait $MVCHelper
|
||||
*/
|
||||
public function __construct($MVCHelper) {
|
||||
|
||||
$this->setMVCHelper($MVCHelper);
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Base;
|
||||
|
||||
class PlatformFormBase {
|
||||
|
||||
public function tokenize() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function tokenizeUrl() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function checkToken() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form;
|
||||
|
||||
|
||||
interface ContainedInterface {
|
||||
|
||||
/**
|
||||
* @return ContainedInterface|null
|
||||
*/
|
||||
public function getPrevious();
|
||||
|
||||
/**
|
||||
* @param ContainedInterface|null $element
|
||||
*/
|
||||
public function setPrevious($element = null);
|
||||
|
||||
/**
|
||||
* @return ContainedInterface|null
|
||||
*/
|
||||
public function getNext();
|
||||
|
||||
/**
|
||||
* @param ContainedInterface|null $element
|
||||
*/
|
||||
public function setNext($element = null);
|
||||
|
||||
public function remove();
|
||||
|
||||
/**
|
||||
* @return ContainerInterface
|
||||
*/
|
||||
public function getParent();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPath();
|
||||
|
||||
public function render();
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container;
|
||||
|
||||
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
|
||||
class ContainerAlternative extends ContainerGeneral {
|
||||
|
||||
public function renderContainer() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container;
|
||||
|
||||
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
use Nextend\Framework\Form\Fieldset\FieldsetRow;
|
||||
|
||||
class ContainerRowGroup extends ContainerGeneral {
|
||||
|
||||
public function renderContainer() {
|
||||
echo '<div class="n2_form__table_row_group" data-field="table-row-group-' . esc_attr($this->name) . '">';
|
||||
if ($this->label !== false) {
|
||||
echo '<div class="n2_form__table_row_group_label">';
|
||||
echo esc_html($this->label);
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
echo '<div class="n2_form__table_row_group_rows" data-field="table-row-group-rows-' . esc_attr($this->name) . '">';
|
||||
parent::renderContainer();
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return FieldsetRow
|
||||
*/
|
||||
public function createRow($name) {
|
||||
|
||||
return new FieldsetRow($this, $name);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container;
|
||||
|
||||
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
|
||||
class ContainerSubform extends ContainerGeneral {
|
||||
|
||||
public function renderContainer() {
|
||||
echo '<div id="' . esc_attr($this->getId()) . '" class="n2_form__subform">';
|
||||
parent::renderContainer();
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
public function getId() {
|
||||
return 'n2_form__subform_' . $this->controlName . '_' . $this->name;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container;
|
||||
|
||||
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
|
||||
class ContainerTab extends ContainerGeneral {
|
||||
|
||||
public function renderContainer() {
|
||||
echo '<div class="n2_form__tab" data-related-form="' . esc_attr($this->getForm()
|
||||
->getId()) . '" data-tab="' . esc_attr($this->getId()) . '">';
|
||||
parent::renderContainer();
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
public function getId() {
|
||||
return 'n2_form__tab_' . $this->controlName . '_' . $this->name;
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container;
|
||||
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
use Nextend\Framework\Form\Fieldset\FieldsetRow;
|
||||
use Nextend\Framework\Form\Fieldset\FieldsetTableLabel;
|
||||
|
||||
class ContainerTable extends ContainerGeneral {
|
||||
|
||||
/**
|
||||
* @var FieldsetTableLabel
|
||||
*/
|
||||
protected $fieldsetLabel;
|
||||
|
||||
protected $fieldsetLabelPosition = 'start';
|
||||
|
||||
public function __construct($insertAt, $name, $label = false, $parameters = array()) {
|
||||
parent::__construct($insertAt, $name, $label, $parameters);
|
||||
|
||||
$labelContainer = new ContainerAlternative($this, $name . '-container-label');
|
||||
$this->fieldsetLabel = new FieldsetTableLabel($labelContainer, $name . '-label', false);
|
||||
}
|
||||
|
||||
public function renderContainer() {
|
||||
echo '<div class="n2_form__table" data-field="table-' . esc_attr($this->name) . '">';
|
||||
echo '<div class="n2_form__table_label">';
|
||||
echo '<div class="n2_form__table_label_title">';
|
||||
echo esc_html($this->label);
|
||||
echo '</div>';
|
||||
if ($this->fieldsetLabel->hasFields()) {
|
||||
echo '<div class="n2_form__table_label_fields n2_form__table_label_fields--' . esc_attr($this->fieldsetLabelPosition) . '">';
|
||||
$this->fieldsetLabel->renderContainer();
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</div>';
|
||||
|
||||
if ($this->first) {
|
||||
echo '<div class="n2_form__table_rows" data-field="table-rows-' . esc_attr($this->name) . '">';
|
||||
parent::renderContainer();
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return FieldsetRow
|
||||
*/
|
||||
public function createRow($name) {
|
||||
|
||||
return new FieldsetRow($this, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param string $label
|
||||
*
|
||||
* @return ContainerRowGroup
|
||||
*/
|
||||
public function createRowGroup($name, $label) {
|
||||
|
||||
return new ContainerRowGroup($this, $name, $label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FieldsetTableLabel
|
||||
*/
|
||||
public function getFieldsetLabel() {
|
||||
return $this->fieldsetLabel;
|
||||
}
|
||||
|
||||
public function setFieldsetPositionEnd() {
|
||||
$this->fieldsetLabelPosition = 'end';
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container\LayerWindow;
|
||||
|
||||
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
|
||||
class ContainerAnimation extends ContainerGeneral {
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $label
|
||||
*
|
||||
* @return ContainerAnimationTab
|
||||
*/
|
||||
public function createTab($name, $label) {
|
||||
return new ContainerAnimationTab($this, $name, $label);
|
||||
}
|
||||
|
||||
public function renderContainer() {
|
||||
echo '<div class="n2_container_animation" data-field="animation-' . esc_attr($this->name) . '">';
|
||||
echo '<div class="n2_container_animation__buttons">';
|
||||
|
||||
$element = $this->first;
|
||||
while ($element) {
|
||||
|
||||
if ($element instanceof ContainerAnimationTab) {
|
||||
echo '<div class="n2_container_animation__button" data-related-tab="' . esc_attr($element->getName()) . '">' . esc_html($element->getLabel()) . '</div>';
|
||||
}
|
||||
|
||||
$element = $element->getNext();
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
echo '<div class="n2_container_animation__tabs">';
|
||||
parent::renderContainer();
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container\LayerWindow;
|
||||
|
||||
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
|
||||
class ContainerAnimationTab extends ContainerGeneral {
|
||||
|
||||
public function renderContainer() {
|
||||
echo '<div class="n2_container_animation__tab" data-tab="' . esc_attr($this->name) . '">';
|
||||
parent::renderContainer();
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container\LayerWindow;
|
||||
|
||||
|
||||
use Nextend\Framework\Asset\Js\Js;
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
use Nextend\Framework\Form\ContainerInterface;
|
||||
use Nextend\Framework\Sanitize;
|
||||
use Nextend\Framework\View\Html;
|
||||
|
||||
class ContainerDesign extends ContainerGeneral {
|
||||
|
||||
public function __construct(ContainerInterface $insertAt, $name) {
|
||||
parent::__construct($insertAt, $name);
|
||||
}
|
||||
|
||||
public function renderContainer() {
|
||||
|
||||
$id = 'n2_css_' . $this->name;
|
||||
|
||||
echo wp_kses(Html::openTag('div', array(
|
||||
'id' => $id,
|
||||
'class' => 'n2_ss_design_' . $this->name
|
||||
)), Sanitize::$adminFormTags);
|
||||
|
||||
$element = $this->first;
|
||||
while ($element) {
|
||||
$element->renderContainer();
|
||||
$element = $element->getNext();
|
||||
}
|
||||
|
||||
echo wp_kses(Html::closeTag('div'), Sanitize::$basicTags);
|
||||
|
||||
$options = array(
|
||||
'ajaxUrl' => $this->getForm()
|
||||
->createAjaxUrl('css/index')
|
||||
);
|
||||
|
||||
Js::addInline('new _N2.BasicCSS(' . json_encode($id) . ', ' . json_encode($options) . ');');
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form\Container\LayerWindow;
|
||||
|
||||
|
||||
use Nextend\Framework\Form\ContainerGeneral;
|
||||
use Nextend\Framework\Form\ContainerInterface;
|
||||
|
||||
class ContainerSettings extends ContainerGeneral {
|
||||
|
||||
public function __construct(ContainerInterface $insertAt, $name, $parameters = array()) {
|
||||
parent::__construct($insertAt, $name, false, $parameters);
|
||||
}
|
||||
|
||||
public function renderContainer() {
|
||||
echo '<div class="n2_ss_layer_window__tab_panel" data-panel="' . esc_attr($this->name) . '">';
|
||||
parent::renderContainer();
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Nextend\Framework\Form;
|
||||
|
||||
|
||||
interface ContainerContainedInterface extends ContainerInterface, ContainedInterface {
|
||||
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Nextend\Framework\Form;
|
||||
|
||||
use Nextend\Framework\Form\Insert\AbstractInsert;
|
||||
|
||||
class ContainerGeneral extends AbstractContainer {
|
||||
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $parent;
|
||||
|
||||
protected $name = '';
|
||||
|
||||
protected $label = '';
|
||||
|
||||
protected $class = '';
|
||||
|
||||
/**
|
||||
* Container constructor.
|
||||
*
|
||||
* @param ContainerInterface|AbstractInsert $insertAt
|
||||
* @param string $name
|
||||
* @param boolean|string $label
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function __construct($insertAt, $name, $label = false, $parameters = array()) {
|
||||
|
||||
$this->name = $name;
|
||||
$this->label = $label;
|
||||
|
||||
if ($insertAt instanceof ContainerInterface) {
|
||||
$this->parent = $insertAt;
|
||||
$this->parent->addElement($this);
|
||||
} else if ($insertAt instanceof AbstractInsert) {
|
||||
$this->parent = $insertAt->insert($this);
|
||||
}
|
||||
|
||||
$this->controlName = $this->parent->getControlName();
|
||||
|
||||
foreach ($parameters as $option => $value) {
|
||||
$option = 'set' . $option;
|
||||
$this->{$option}($value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function removeElement($element) {
|
||||
$previous = $element->getPrevious();
|
||||
$next = $element->getNext();
|
||||
|
||||
if ($this->first === $element) {
|
||||
$this->first = $next;
|
||||
}
|
||||
|
||||
if ($this->last === $element) {
|
||||
$this->last = $previous;
|
||||
}
|
||||
|
||||
if ($previous) {
|
||||
$previous->setNext($next);
|
||||
} else {
|
||||
$next->setPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ContainerInterface
|
||||
*/
|
||||
public function getParent() {
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function getPath() {
|
||||
return $this->parent->getPath() . '/' . $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
*/
|
||||
public function setClass($class) {
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLabel() {
|
||||
return !empty($this->label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel() {
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Form
|
||||
*/
|
||||
public function getForm() {
|
||||
return $this->parent->getForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getControlName() {
|
||||
return $this->controlName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $controlName
|
||||
*/
|
||||
public function setControlName($controlName) {
|
||||
$this->controlName = $controlName;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user