| Current Path : /home/digilove/www/41423/ |
| Current File : /home/digilove/www/41423/Application.tar |
AdministratorApplication.php 0000644 00000031406 15234470622 0012272 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Application;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Input\Input;
use Joomla\Registry\Registry;
/**
* Joomla! Administrator Application class
*
* @since 3.2
*/
class AdministratorApplication extends CMSApplication
{
/**
* Class constructor.
*
* @param Input $input An optional argument to provide dependency injection for the application's
* input object. If the argument is a \JInput object that object will become
* the application's input object, otherwise a default input object is created.
* @param Registry $config An optional argument to provide dependency injection for the application's
* config object. If the argument is a Registry object that object will become
* the application's config object, otherwise a default config object is created.
* @param \JApplicationWebClient $client An optional argument to provide dependency injection for the application's
* client object. If the argument is a \JApplicationWebClient object that object will become
* the application's client object, otherwise a default client object is created.
*
* @since 3.2
*/
public function __construct(Input $input = null, Registry $config = null, \JApplicationWebClient $client = null)
{
// Register the application name
$this->_name = 'administrator';
// Register the client ID
$this->_clientId = 1;
// Execute the parent constructor
parent::__construct($input, $config, $client);
// Set the root in the URI based on the application name
\JUri::root(null, rtrim(dirname(\JUri::base(true)), '/\\'));
}
/**
* Dispatch the application
*
* @param string $component The component which is being rendered.
*
* @return void
*
* @since 3.2
*/
public function dispatch($component = null)
{
if ($component === null)
{
$component = \JAdministratorHelper::findOption();
}
// Load the document to the API
$this->loadDocument();
// Set up the params
$document = \JFactory::getDocument();
// Register the document object with \JFactory
\JFactory::$document = $document;
switch ($document->getType())
{
case 'html':
$document->setMetaData('keywords', $this->get('MetaKeys'));
// Get the template
$template = $this->getTemplate(true);
// Store the template and its params to the config
$this->set('theme', $template->template);
$this->set('themeParams', $template->params);
break;
default:
break;
}
$document->setTitle($this->get('sitename') . ' - ' . \JText::_('JADMINISTRATION'));
$document->setDescription($this->get('MetaDesc'));
$document->setGenerator('Joomla! - Open Source Content Management');
$contents = ComponentHelper::renderComponent($component);
$document->setBuffer($contents, 'component');
// Trigger the onAfterDispatch event.
\JPluginHelper::importPlugin('system');
$this->triggerEvent('onAfterDispatch');
}
/**
* Method to run the Web application routines.
*
* @return void
*
* @since 3.2
*/
protected function doExecute()
{
// Get the language from the (login) form or user state
$login_lang = ($this->input->get('option') == 'com_login') ? $this->input->get('lang') : '';
$options = array('language' => $login_lang ?: $this->getUserState('application.lang'));
// Initialise the application
$this->initialiseApp($options);
// Test for magic quotes
if (PHP_VERSION_ID < 50400 && get_magic_quotes_gpc())
{
$lang = $this->getLanguage();
if ($lang->hasKey('JERROR_MAGIC_QUOTES'))
{
$this->enqueueMessage(\JText::_('JERROR_MAGIC_QUOTES'), 'error');
}
else
{
$this->enqueueMessage('Your host needs to disable magic_quotes_gpc to run this version of Joomla!', 'error');
}
}
// Mark afterInitialise in the profiler.
JDEBUG ? $this->profiler->mark('afterInitialise') : null;
// Route the application
$this->route();
// Mark afterRoute in the profiler.
JDEBUG ? $this->profiler->mark('afterRoute') : null;
/*
* Check if the user is required to reset their password
*
* Before $this->route(); "option" and "view" can't be safely read using:
* $this->input->getCmd('option'); or $this->input->getCmd('view');
* ex: due of the sef urls
*/
$this->checkUserRequireReset('com_admin', 'profile', 'edit', 'com_admin/profile.save,com_admin/profile.apply,com_login/logout');
// Dispatch the application
$this->dispatch();
// Mark afterDispatch in the profiler.
JDEBUG ? $this->profiler->mark('afterDispatch') : null;
}
/**
* Return a reference to the \JRouter object.
*
* @param string $name The name of the application.
* @param array $options An optional associative array of configuration settings.
*
* @return \JRouter
*
* @since 3.2
*/
public static function getRouter($name = 'administrator', array $options = array())
{
return parent::getRouter($name, $options);
}
/**
* Gets the name of the current template.
*
* @param boolean $params True to return the template parameters
*
* @return string The name of the template.
*
* @since 3.2
* @throws \InvalidArgumentException
*/
public function getTemplate($params = false)
{
if (is_object($this->template))
{
if ($params)
{
return $this->template;
}
return $this->template->template;
}
$admin_style = \JFactory::getUser()->getParam('admin_style');
// Load the template name from the database
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('template, s.params')
->from('#__template_styles as s')
->join('LEFT', '#__extensions as e ON e.type=' . $db->quote('template') . ' AND e.element=s.template AND e.client_id=s.client_id');
if ($admin_style)
{
$query->where('s.client_id = 1 AND id = ' . (int) $admin_style . ' AND e.enabled = 1', 'OR');
}
$query->where('s.client_id = 1 AND home = ' . $db->quote('1'), 'OR')
->order('home');
$db->setQuery($query);
$template = $db->loadObject();
$template->template = \JFilterInput::getInstance()->clean($template->template, 'cmd');
$template->params = new Registry($template->params);
if (!file_exists(JPATH_THEMES . '/' . $template->template . '/index.php'))
{
$this->enqueueMessage(\JText::_('JERROR_ALERTNOTEMPLATE'), 'error');
$template->params = new Registry;
$template->template = 'isis';
}
// Cache the result
$this->template = $template;
if (!file_exists(JPATH_THEMES . '/' . $template->template . '/index.php'))
{
throw new \InvalidArgumentException(\JText::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $template->template));
}
if ($params)
{
return $template;
}
return $template->template;
}
/**
* Initialise the application.
*
* @param array $options An optional associative array of configuration settings.
*
* @return void
*
* @since 3.2
*/
protected function initialiseApp($options = array())
{
$user = \JFactory::getUser();
// If the user is a guest we populate it with the guest user group.
if ($user->guest)
{
$guestUsergroup = ComponentHelper::getParams('com_users')->get('guest_usergroup', 1);
$user->groups = array($guestUsergroup);
}
// If a language was specified it has priority, otherwise use user or default language settings
if (empty($options['language']))
{
$lang = $user->getParam('admin_language');
// Make sure that the user's language exists
if ($lang && \JLanguageHelper::exists($lang))
{
$options['language'] = $lang;
}
else
{
$params = ComponentHelper::getParams('com_languages');
$options['language'] = $params->get('administrator', $this->get('language', 'en-GB'));
}
}
// One last check to make sure we have something
if (!\JLanguageHelper::exists($options['language']))
{
$lang = $this->get('language', 'en-GB');
if (\JLanguageHelper::exists($lang))
{
$options['language'] = $lang;
}
else
{
// As a last ditch fail to english
$options['language'] = 'en-GB';
}
}
// Finish initialisation
parent::initialiseApp($options);
}
/**
* Login authentication function
*
* @param array $credentials Array('username' => string, 'password' => string)
* @param array $options Array('remember' => boolean)
*
* @return boolean True on success.
*
* @since 3.2
*/
public function login($credentials, $options = array())
{
// The minimum group
$options['group'] = 'Public Backend';
// Make sure users are not auto-registered
$options['autoregister'] = false;
// Set the application login entry point
if (!array_key_exists('entry_url', $options))
{
$options['entry_url'] = \JUri::base() . 'index.php?option=com_users&task=login';
}
// Set the access control action to check.
$options['action'] = 'core.login.admin';
$result = parent::login($credentials, $options);
if (!($result instanceof \Exception))
{
$lang = $this->input->getCmd('lang');
$lang = preg_replace('/[^A-Z-]/i', '', $lang);
if ($lang)
{
$this->setUserState('application.lang', $lang);
}
static::purgeMessages();
}
return $result;
}
/**
* Purge the jos_messages table of old messages
*
* @return void
*
* @since 3.2
*/
public static function purgeMessages()
{
$user = \JFactory::getUser();
$userid = $user->get('id');
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__messages_cfg'))
->where($db->quoteName('user_id') . ' = ' . (int) $userid, 'AND')
->where($db->quoteName('cfg_name') . ' = ' . $db->quote('auto_purge'), 'AND');
$db->setQuery($query);
$config = $db->loadObject();
// Check if auto_purge value set
if (is_object($config) && $config->cfg_name === 'auto_purge')
{
$purge = $config->cfg_value;
}
else
{
// If no value set, default is 7 days
$purge = 7;
}
// If purge value is not 0, then allow purging of old messages
if ($purge > 0)
{
// Purge old messages at day set in message configuration
$past = \JFactory::getDate(time() - $purge * 86400);
$pastStamp = $past->toSql();
$query->clear()
->delete($db->quoteName('#__messages'))
->where($db->quoteName('date_time') . ' < ' . $db->quote($pastStamp), 'AND')
->where($db->quoteName('user_id_to') . ' = ' . (int) $userid, 'AND');
$db->setQuery($query);
$db->execute();
}
}
/**
* Rendering is the process of pushing the document buffers into the template
* placeholders, retrieving data from the document and pushing it into
* the application response buffer.
*
* @return void
*
* @since 3.2
*/
protected function render()
{
// Get the \JInput object
$input = $this->input;
$component = $input->getCmd('option', 'com_login');
$file = $input->getCmd('tmpl', 'index');
if ($component === 'com_login')
{
$file = 'login';
}
$this->set('themeFile', $file . '.php');
// Safety check for when configuration.php root_user is in use.
$rootUser = $this->get('root_user');
if (property_exists('\JConfig', 'root_user'))
{
if (\JFactory::getUser()->get('username') === $rootUser || \JFactory::getUser()->id === (string) $rootUser)
{
$this->enqueueMessage(
\JText::sprintf(
'JWARNING_REMOVE_ROOT_USER',
'index.php?option=com_config&task=config.removeroot&' . \JSession::getFormToken() . '=1'
),
'error'
);
}
// Show this message to superusers too
elseif (\JFactory::getUser()->authorise('core.admin'))
{
$this->enqueueMessage(
\JText::sprintf(
'JWARNING_REMOVE_ROOT_USER_ADMIN',
$rootUser,
'index.php?option=com_config&task=config.removeroot&' . \JSession::getFormToken() . '=1'
),
'error'
);
}
}
parent::render();
}
/**
* Route the application.
*
* Routing is the process of examining the request environment to determine which
* component should receive the request. The component optional parameters
* are then set in the request object to be processed when the application is being
* dispatched.
*
* @return void
*
* @since 3.2
*/
protected function route()
{
$uri = \JUri::getInstance();
if ($this->get('force_ssl') >= 1 && strtolower($uri->getScheme()) !== 'https')
{
// Forward to https
$uri->setScheme('https');
$this->redirect((string) $uri, 301);
}
// Trigger the onAfterRoute event.
\JPluginHelper::importPlugin('system');
$this->triggerEvent('onAfterRoute');
}
}
ApplicationHelper.php 0000644 00000014206 15234470622 0010670 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Application;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
/**
* Application helper functions
*
* @since 1.5
*/
class ApplicationHelper
{
/**
* Client information array
*
* @var array
* @since 1.6
*/
protected static $_clients = array();
/**
* Return the name of the request component [main component]
*
* @param string $default The default option
*
* @return string Option (e.g. com_something)
*
* @since 1.6
*/
public static function getComponentName($default = null)
{
static $option;
if ($option)
{
return $option;
}
$input = \JFactory::getApplication()->input;
$option = strtolower($input->get('option'));
if (empty($option))
{
$option = $default;
}
$input->set('option', $option);
return $option;
}
/**
* Provides a secure hash based on a seed
*
* @param string $seed Seed string.
*
* @return string A secure hash
*
* @since 3.2
*/
public static function getHash($seed)
{
return md5(\JFactory::getConfig()->get('secret') . $seed);
}
/**
* This method transliterates a string into a URL
* safe string or returns a URL safe UTF-8 string
* based on the global configuration
*
* @param string $string String to process
* @param string $language Language to transliterate to if unicode slugs are disabled
*
* @return string Processed string
*
* @since 3.2
*/
public static function stringURLSafe($string, $language = '')
{
if (\JFactory::getConfig()->get('unicodeslugs') == 1)
{
$output = \JFilterOutput::stringURLUnicodeSlug($string);
}
else
{
if ($language === '*' || $language === '')
{
$languageParams = ComponentHelper::getParams('com_languages');
$language = $languageParams->get('site');
}
$output = \JFilterOutput::stringURLSafe($string, $language);
}
return $output;
}
/**
* Gets information on a specific client id. This method will be useful in
* future versions when we start mapping applications in the database.
*
* This method will return a client information array if called
* with no arguments which can be used to add custom application information.
*
* @param integer $id A client identifier
* @param boolean $byName If True, find the client by its name
*
* @return mixed Object describing the client or false if not known
*
* @since 1.5
*/
public static function getClientInfo($id = null, $byName = false)
{
// Only create the array if it is empty
if (empty(self::$_clients))
{
$obj = new \stdClass;
// Site Client
$obj->id = 0;
$obj->name = 'site';
$obj->path = JPATH_SITE;
self::$_clients[0] = clone $obj;
// Administrator Client
$obj->id = 1;
$obj->name = 'administrator';
$obj->path = JPATH_ADMINISTRATOR;
self::$_clients[1] = clone $obj;
// Installation Client
$obj->id = 2;
$obj->name = 'installation';
$obj->path = JPATH_INSTALLATION;
self::$_clients[2] = clone $obj;
}
// If no client id has been passed return the whole array
if ($id === null)
{
return self::$_clients;
}
// Are we looking for client information by id or by name?
if (!$byName)
{
if (isset(self::$_clients[$id]))
{
return self::$_clients[$id];
}
}
else
{
foreach (self::$_clients as $client)
{
if ($client->name == strtolower($id))
{
return $client;
}
}
}
return;
}
/**
* Adds information for a client.
*
* @param mixed $client A client identifier either an array or object
*
* @return boolean True if the information is added. False on error
*
* @since 1.6
*/
public static function addClientInfo($client)
{
if (is_array($client))
{
$client = (object) $client;
}
if (!is_object($client))
{
return false;
}
$info = self::getClientInfo();
if (!isset($client->id))
{
$client->id = count($info);
}
self::$_clients[$client->id] = clone $client;
return true;
}
/**
* Parse a XML install manifest file.
*
* XML Root tag should be 'install' except for languages which use meta file.
*
* @param string $path Full path to XML file.
*
* @return array XML metadata.
*
* @since 1.5
* @deprecated 4.0 Use \JInstaller::parseXMLInstallFile instead.
*/
public static function parseXMLInstallFile($path)
{
\JLog::add('ApplicationHelper::parseXMLInstallFile is deprecated. Use \JInstaller::parseXMLInstallFile instead.', \JLog::WARNING, 'deprecated');
return \JInstaller::parseXMLInstallFile($path);
}
/**
* Parse a XML language meta file.
*
* XML Root tag for languages which is meta file.
*
* @param string $path Full path to XML file.
*
* @return array XML metadata.
*
* @since 1.5
* @deprecated 4.0 Use \JInstaller::parseXMLInstallFile instead.
*/
public static function parseXMLLangMetaFile($path)
{
\JLog::add('ApplicationHelper::parseXMLLangMetaFile is deprecated. Use \JInstaller::parseXMLInstallFile instead.', \JLog::WARNING, 'deprecated');
// Check if meta file exists.
if (!file_exists($path))
{
return false;
}
// Read the file to see if it's a valid component XML file
$xml = simplexml_load_file($path);
if (!$xml)
{
return false;
}
/*
* Check for a valid XML root tag.
*
* Should be 'metafile'.
*/
if ($xml->getName() !== 'metafile')
{
unset($xml);
return false;
}
$data = array();
$data['name'] = (string) $xml->name;
$data['type'] = $xml->attributes()->type;
$data['creationDate'] = ((string) $xml->creationDate) ?: \JText::_('JLIB_UNKNOWN');
$data['author'] = ((string) $xml->author) ?: \JText::_('JLIB_UNKNOWN');
$data['copyright'] = (string) $xml->copyright;
$data['authorEmail'] = (string) $xml->authorEmail;
$data['authorUrl'] = (string) $xml->authorUrl;
$data['version'] = (string) $xml->version;
$data['description'] = (string) $xml->description;
$data['group'] = (string) $xml->group;
return $data;
}
}
BaseApplication.php 0000644 00000011166 15234470622 0010325 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Application;
defined('JPATH_PLATFORM') or die;
use Joomla\Application\AbstractApplication;
use Joomla\CMS\Input\Input;
use Joomla\Registry\Registry;
/**
* Joomla Platform Base Application Class
*
* @property-read \JInput $input The application input object
*
* @since 3.0.0
*/
abstract class BaseApplication extends AbstractApplication
{
/**
* The application dispatcher object.
*
* @var \JEventDispatcher
* @since 3.0.0
*/
protected $dispatcher;
/**
* The application identity object.
*
* @var \JUser
* @since 3.0.0
*/
protected $identity;
/**
* Class constructor.
*
* @param Input $input An optional argument to provide dependency injection for the application's
* input object. If the argument is a \JInput object that object will become
* the application's input object, otherwise a default input object is created.
* @param Registry $config An optional argument to provide dependency injection for the application's
* config object. If the argument is a Registry object that object will become
* the application's config object, otherwise a default config object is created.
*
* @since 3.0.0
*/
public function __construct(Input $input = null, Registry $config = null)
{
$this->input = $input instanceof Input ? $input : new Input;
$this->config = $config instanceof Registry ? $config : new Registry;
$this->initialise();
}
/**
* Get the application identity.
*
* @return mixed A \JUser object or null.
*
* @since 3.0.0
*/
public function getIdentity()
{
return $this->identity;
}
/**
* Registers a handler to a particular event group.
*
* @param string $event The event name.
* @param callable $handler The handler, a function or an instance of an event object.
*
* @return BaseApplication The application to allow chaining.
*
* @since 3.0.0
*/
public function registerEvent($event, $handler)
{
if ($this->dispatcher instanceof \JEventDispatcher)
{
$this->dispatcher->register($event, $handler);
}
return $this;
}
/**
* Calls all handlers associated with an event group.
*
* @param string $event The event name.
* @param array $args An array of arguments (optional).
*
* @return array An array of results from each function call, or null if no dispatcher is defined.
*
* @since 3.0.0
*/
public function triggerEvent($event, array $args = null)
{
if ($this->dispatcher instanceof \JEventDispatcher)
{
return $this->dispatcher->trigger($event, $args);
}
return;
}
/**
* Allows the application to load a custom or default dispatcher.
*
* The logic and options for creating this object are adequately generic for default cases
* but for many applications it will make sense to override this method and create event
* dispatchers, if required, based on more specific needs.
*
* @param \JEventDispatcher $dispatcher An optional dispatcher object. If omitted, the factory dispatcher is created.
*
* @return BaseApplication This method is chainable.
*
* @since 3.0.0
*/
public function loadDispatcher(\JEventDispatcher $dispatcher = null)
{
$this->dispatcher = ($dispatcher === null) ? \JEventDispatcher::getInstance() : $dispatcher;
return $this;
}
/**
* Allows the application to load a custom or default identity.
*
* The logic and options for creating this object are adequately generic for default cases
* but for many applications it will make sense to override this method and create an identity,
* if required, based on more specific needs.
*
* @param \JUser $identity An optional identity object. If omitted, the factory user is created.
*
* @return BaseApplication This method is chainable.
*
* @since 3.0.0
*/
public function loadIdentity(\JUser $identity = null)
{
$this->identity = ($identity === null) ? \JFactory::getUser() : $identity;
return $this;
}
/**
* Method to run the application routines. Most likely you will want to instantiate a controller
* and execute it, or perform some sort of task directly.
*
* @return void
*
* @since 3.4 (CMS)
* @deprecated 4.0 The default concrete implementation of doExecute() will be removed, subclasses will need to provide their own implementation.
*/
protected function doExecute()
{
return;
}
}
CMSApplication.php 0000644 00000100361 15234470622 0010071 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Application;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Input\Input;
use Joomla\CMS\Session\MetadataManager;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
/**
* Joomla! CMS Application class
*
* @since 3.2
*/
class CMSApplication extends WebApplication
{
/**
* Array of options for the \JDocument object
*
* @var array
* @since 3.2
*/
protected $docOptions = array();
/**
* Application instances container.
*
* @var CMSApplication[]
* @since 3.2
*/
protected static $instances = array();
/**
* The scope of the application.
*
* @var string
* @since 3.2
*/
public $scope = null;
/**
* The client identifier.
*
* @var integer
* @since 3.2
* @deprecated 4.0 Will be renamed $clientId
*/
protected $_clientId = null;
/**
* The application message queue.
*
* @var array
* @since 3.2
* @deprecated 4.0 Will be renamed $messageQueue
*/
protected $_messageQueue = array();
/**
* The name of the application.
*
* @var array
* @since 3.2
* @deprecated 4.0 Will be renamed $name
*/
protected $_name = null;
/**
* The profiler instance
*
* @var \JProfiler
* @since 3.2
*/
protected $profiler = null;
/**
* Currently active template
*
* @var object
* @since 3.2
*/
protected $template = null;
/**
* Class constructor.
*
* @param Input $input An optional argument to provide dependency injection for the application's
* input object. If the argument is a \JInput object that object will become
* the application's input object, otherwise a default input object is created.
* @param Registry $config An optional argument to provide dependency injection for the application's
* config object. If the argument is a Registry object that object will become
* the application's config object, otherwise a default config object is created.
* @param \JApplicationWebClient $client An optional argument to provide dependency injection for the application's
* client object. If the argument is a \JApplicationWebClient object that object will become
* the application's client object, otherwise a default client object is created.
*
* @since 3.2
*/
public function __construct(Input $input = null, Registry $config = null, \JApplicationWebClient $client = null)
{
parent::__construct($input, $config, $client);
// Load and set the dispatcher
$this->loadDispatcher();
// If JDEBUG is defined, load the profiler instance
if (defined('JDEBUG') && JDEBUG)
{
$this->profiler = \JProfiler::getInstance('Application');
}
// Enable sessions by default.
if ($this->config->get('session') === null)
{
$this->config->set('session', true);
}
// Set the session default name.
if ($this->config->get('session_name') === null)
{
$this->config->set('session_name', $this->getName());
}
// Create the session if a session name is passed.
if ($this->config->get('session') !== false)
{
$this->loadSession();
}
}
/**
* Checks the user session.
*
* If the session record doesn't exist, initialise it.
* If session is new, create session variables
*
* @return void
*
* @since 3.2
* @throws \RuntimeException
*/
public function checkSession()
{
$metadataManager = new MetadataManager($this, \JFactory::getDbo());
$metadataManager->createRecordIfNonExisting(\JFactory::getSession(), \JFactory::getUser());
}
/**
* Enqueue a system message.
*
* @param string $msg The message to enqueue.
* @param string $type The message type. Default is message.
*
* @return void
*
* @since 3.2
*/
public function enqueueMessage($msg, $type = 'message')
{
// Don't add empty messages.
if (trim($msg) === '')
{
return;
}
$inputFilter = InputFilter::getInstance(array(), array(), 1, 1);
// Build the message array and apply the HTML InputFilter with the default blacklist to the message
$message = array(
'message' => $inputFilter->clean($msg, 'html'),
'type' => $inputFilter->clean(strtolower($type), 'cmd')
);
// For empty queue, if messages exists in the session, enqueue them first.
$messages = $this->getMessageQueue();
if (!in_array($message, $this->_messageQueue))
{
// Enqueue the message.
$this->_messageQueue[] = $message;
}
}
/**
* Execute the application.
*
* @return void
*
* @since 3.2
*/
public function execute()
{
$input = $this->input;
// Get invalid input variables
$invalidInputVariables = array_filter(
array('option', 'view', 'format', 'lang', 'Itemid', 'template', 'templateStyle', 'task'),
function($systemVariable) use ($input) {
return $input->exists($systemVariable) && is_array($input->getRaw($systemVariable));
}
);
// Unset invalid system variables
foreach ($invalidInputVariables as $systemVariable)
{
$input->set($systemVariable, null);
}
// Abort when there are invalid variables
if ($invalidInputVariables)
{
throw new \RuntimeException('Invalid input, aborting application.');
}
// Perform application routines.
$this->doExecute();
// If we have an application document object, render it.
if ($this->document instanceof \JDocument)
{
// Render the application output.
$this->render();
}
// If gzip compression is enabled in configuration and the server is compliant, compress the output.
if ($this->get('gzip') && !ini_get('zlib.output_compression') && ini_get('output_handler') !== 'ob_gzhandler')
{
$this->compress();
// Trigger the onAfterCompress event.
$this->triggerEvent('onAfterCompress');
}
// Send the application response.
$this->respond();
// Trigger the onAfterRespond event.
$this->triggerEvent('onAfterRespond');
}
/**
* Check if the user is required to reset their password.
*
* If the user is required to reset their password will be redirected to the page that manage the password reset.
*
* @param string $option The option that manage the password reset
* @param string $view The view that manage the password reset
* @param string $layout The layout of the view that manage the password reset
* @param string $tasks Permitted tasks
*
* @return void
*/
protected function checkUserRequireReset($option, $view, $layout, $tasks)
{
if (\JFactory::getUser()->get('requireReset', 0))
{
$redirect = false;
/*
* By default user profile edit page is used.
* That page allows you to change more than just the password and might not be the desired behavior.
* This allows a developer to override the page that manage the password reset.
* (can be configured using the file: configuration.php, or if extended, through the global configuration form)
*/
$name = $this->getName();
if ($this->get($name . '_reset_password_override', 0))
{
$option = $this->get($name . '_reset_password_option', '');
$view = $this->get($name . '_reset_password_view', '');
$layout = $this->get($name . '_reset_password_layout', '');
$tasks = $this->get($name . '_reset_password_tasks', '');
}
$task = $this->input->getCmd('task', '');
// Check task or option/view/layout
if (!empty($task))
{
$tasks = explode(',', $tasks);
// Check full task version "option/task"
if (array_search($this->input->getCmd('option', '') . '/' . $task, $tasks) === false)
{
// Check short task version, must be on the same option of the view
if ($this->input->getCmd('option', '') !== $option || array_search($task, $tasks) === false)
{
// Not permitted task
$redirect = true;
}
}
}
else
{
if ($this->input->getCmd('option', '') !== $option || $this->input->getCmd('view', '') !== $view
|| $this->input->getCmd('layout', '') !== $layout)
{
// Requested a different option/view/layout
$redirect = true;
}
}
if ($redirect)
{
// Redirect to the profile edit page
$this->enqueueMessage(\JText::_('JGLOBAL_PASSWORD_RESET_REQUIRED'), 'notice');
$this->redirect(\JRoute::_('index.php?option=' . $option . '&view=' . $view . '&layout=' . $layout, false));
}
}
}
/**
* Gets a configuration value.
*
* @param string $varname The name of the value to get.
* @param string $default Default value to return
*
* @return mixed The user state.
*
* @since 3.2
* @deprecated 5.0 Use get() instead
*/
public function getCfg($varname, $default = null)
{
try
{
\JLog::add(
sprintf('%s() is deprecated and will be removed in 5.0. Use JFactory->getApplication()->get() instead.', __METHOD__),
\JLog::WARNING,
'deprecated'
);
}
catch (RuntimeException $exception)
{
// Informational log only
}
return $this->get($varname, $default);
}
/**
* Gets the client id of the current running application.
*
* @return integer A client identifier.
*
* @since 3.2
*/
public function getClientId()
{
return $this->_clientId;
}
/**
* Returns a reference to the global CMSApplication object, only creating it if it doesn't already exist.
*
* This method must be invoked as: $web = CMSApplication::getInstance();
*
* @param string $name The name (optional) of the CMSApplication class to instantiate.
*
* @return CMSApplication
*
* @since 3.2
* @throws \RuntimeException
*/
public static function getInstance($name = null)
{
if (empty(static::$instances[$name]))
{
// Create a CMSApplication object.
$classname = '\JApplication' . ucfirst($name);
if (!class_exists($classname))
{
throw new \RuntimeException(\JText::sprintf('JLIB_APPLICATION_ERROR_APPLICATION_LOAD', $name), 500);
}
static::$instances[$name] = new $classname;
}
return static::$instances[$name];
}
/**
* Returns the application \JMenu object.
*
* @param string $name The name of the application/client.
* @param array $options An optional associative array of configuration settings.
*
* @return \JMenu|null
*
* @since 3.2
*/
public function getMenu($name = null, $options = array())
{
if (!isset($name))
{
$name = $this->getName();
}
// Inject this application object into the \JMenu tree if one isn't already specified
if (!isset($options['app']))
{
$options['app'] = $this;
}
try
{
$menu = \JMenu::getInstance($name, $options);
}
catch (\Exception $e)
{
return;
}
return $menu;
}
/**
* Get the system message queue.
*
* @param boolean $clear Clear the messages currently attached to the application object
*
* @return array The system message queue.
*
* @since 3.2
*/
public function getMessageQueue($clear = false)
{
// For empty queue, if messages exists in the session, enqueue them.
if (!$this->_messageQueue)
{
$session = \JFactory::getSession();
$sessionQueue = $session->get('application.queue', array());
if ($sessionQueue)
{
$this->_messageQueue = $sessionQueue;
$session->set('application.queue', array());
}
}
$messageQueue = $this->_messageQueue;
if ($clear)
{
$this->_messageQueue = array();
}
return $messageQueue;
}
/**
* Gets the name of the current running application.
*
* @return string The name of the application.
*
* @since 3.2
*/
public function getName()
{
return $this->_name;
}
/**
* Returns the application \JPathway object.
*
* @param string $name The name of the application.
* @param array $options An optional associative array of configuration settings.
*
* @return \JPathway|null
*
* @since 3.2
*/
public function getPathway($name = null, $options = array())
{
if (!isset($name))
{
$name = $this->getName();
}
else
{
// Name should not be used
$this->getLogger()->warning(
'Name attribute is deprecated, in the future fetch the pathway '
. 'through the respective application.',
array('category' => 'deprecated')
);
}
try
{
$pathway = \JPathway::getInstance($name, $options);
}
catch (\Exception $e)
{
return;
}
return $pathway;
}
/**
* Returns the application \JRouter object.
*
* @param string $name The name of the application.
* @param array $options An optional associative array of configuration settings.
*
* @return \JRouter|null
*
* @since 3.2
*/
public static function getRouter($name = null, array $options = array())
{
if (!isset($name))
{
$app = \JFactory::getApplication();
$name = $app->getName();
}
$options['mode'] = \JFactory::getConfig()->get('sef');
try
{
$router = \JRouter::getInstance($name, $options);
}
catch (\Exception $e)
{
return;
}
return $router;
}
/**
* Gets the name of the current template.
*
* @param boolean $params An optional associative array of configuration settings
*
* @return mixed System is the fallback.
*
* @since 3.2
*/
public function getTemplate($params = false)
{
$template = new \stdClass;
$template->template = 'system';
$template->params = new Registry;
if ($params)
{
return $template;
}
return $template->template;
}
/**
* Gets a user state.
*
* @param string $key The path of the state.
* @param mixed $default Optional default value, returned if the internal value is null.
*
* @return mixed The user state or null.
*
* @since 3.2
*/
public function getUserState($key, $default = null)
{
$session = \JFactory::getSession();
$registry = $session->get('registry');
if ($registry !== null)
{
return $registry->get($key, $default);
}
return $default;
}
/**
* Gets the value of a user state variable.
*
* @param string $key The key of the user state variable.
* @param string $request The name of the variable passed in a request.
* @param string $default The default value for the variable if not found. Optional.
* @param string $type Filter for the variable, for valid values see {@link \JFilterInput::clean()}. Optional.
*
* @return mixed The request user state.
*
* @since 3.2
*/
public function getUserStateFromRequest($key, $request, $default = null, $type = 'none')
{
$cur_state = $this->getUserState($key, $default);
$new_state = $this->input->get($request, null, $type);
if ($new_state === null)
{
return $cur_state;
}
// Save the new value only if it was set in this request.
$this->setUserState($key, $new_state);
return $new_state;
}
/**
* Initialise the application.
*
* @param array $options An optional associative array of configuration settings.
*
* @return void
*
* @since 3.2
*/
protected function initialiseApp($options = array())
{
// Set the configuration in the API.
$this->config = \JFactory::getConfig();
// Check that we were given a language in the array (since by default may be blank).
if (isset($options['language']))
{
$this->set('language', $options['language']);
}
// Build our language object
$lang = \JLanguage::getInstance($this->get('language'), $this->get('debug_lang'));
// Load the language to the API
$this->loadLanguage($lang);
// Register the language object with \JFactory
\JFactory::$language = $this->getLanguage();
// Load the library language files
$this->loadLibraryLanguage();
// Set user specific editor.
$user = \JFactory::getUser();
$editor = $user->getParam('editor', $this->get('editor'));
if (!\JPluginHelper::isEnabled('editors', $editor))
{
$editor = $this->get('editor');
if (!\JPluginHelper::isEnabled('editors', $editor))
{
$editor = 'none';
}
}
$this->set('editor', $editor);
// Trigger the onAfterInitialise event.
\JPluginHelper::importPlugin('system');
$this->triggerEvent('onAfterInitialise');
}
/**
* Is admin interface?
*
* @return boolean True if this application is administrator.
*
* @since 3.2
* @deprecated 4.0 Use isClient('administrator') instead.
*/
public function isAdmin()
{
try
{
\JLog::add(
sprintf("%s() is deprecated and will be removed in 4.0. Use JFactory->getApplication()->isClient('administrator') instead.", __METHOD__),
\JLog::WARNING,
'deprecated'
);
}
catch (\RuntimeException $exception)
{
// Informational log only
}
return $this->isClient('administrator');
}
/**
* Is site interface?
*
* @return boolean True if this application is site.
*
* @since 3.2
* @deprecated 4.0 Use isClient('site') instead.
*/
public function isSite()
{
try
{
\JLog::add(
sprintf("%s() is deprecated and will be removed in 4.0. Use JFactory->getApplication()->isClient('site') instead.", __METHOD__),
\JLog::WARNING,
'deprecated'
);
}
catch (\RuntimeException $exception)
{
// Informational log only
}
return $this->isClient('site');
}
/**
* Checks if HTTPS is forced in the client configuration.
*
* @param integer $clientId An optional client id (defaults to current application client).
*
* @return boolean True if is forced for the client, false otherwise.
*
* @since 3.7.3
*/
public function isHttpsForced($clientId = null)
{
$clientId = (int) ($clientId !== null ? $clientId : $this->getClientId());
$forceSsl = (int) $this->get('force_ssl');
if ($clientId === 0 && $forceSsl === 2)
{
return true;
}
if ($clientId === 1 && $forceSsl >= 1)
{
return true;
}
return false;
}
/**
* Check the client interface by name.
*
* @param string $identifier String identifier for the application interface
*
* @return boolean True if this application is of the given type client interface.
*
* @since 3.7.0
*/
public function isClient($identifier)
{
return $this->getName() === $identifier;
}
/**
* Load the library language files for the application
*
* @return void
*
* @since 3.6.3
*/
protected function loadLibraryLanguage()
{
$this->getLanguage()->load('lib_joomla', JPATH_ADMINISTRATOR);
}
/**
* Allows the application to load a custom or default session.
*
* The logic and options for creating this object are adequately generic for default cases
* but for many applications it will make sense to override this method and create a session,
* if required, based on more specific needs.
*
* @param \JSession $session An optional session object. If omitted, the session is created.
*
* @return CMSApplication This method is chainable.
*
* @since 3.2
*/
public function loadSession(\JSession $session = null)
{
if ($session !== null)
{
$this->session = $session;
return $this;
}
$this->registerEvent('onAfterSessionStart', array($this, 'afterSessionStart'));
/*
* Note: The below code CANNOT change from instantiating a session via \JFactory until there is a proper dependency injection container supported
* by the application. The current default behaviours result in this method being called each time an application class is instantiated.
* https://github.com/joomla/joomla-cms/issues/12108 explains why things will crash and burn if you ever attempt to make this change
* without a proper dependency injection container.
*/
$session = \JFactory::getSession(
array(
'name' => \JApplicationHelper::getHash($this->get('session_name', get_class($this))),
'expire' => $this->get('lifetime') ? $this->get('lifetime') * 60 : 900,
'force_ssl' => $this->isHttpsForced(),
)
);
$session->initialise($this->input, $this->dispatcher);
// Get the session handler from the configuration.
$handler = $this->get('session_handler', 'none');
/*
* Check for extra session metadata when:
*
* 1) The database handler is in use and the session is new
* 2) The database handler is not in use and the time is an even numbered second or the session is new
*/
if (($handler !== 'database' && (time() % 2 || $session->isNew())) || ($handler === 'database' && $session->isNew()))
{
$this->checkSession();
}
// Set the session object.
$this->session = $session;
return $this;
}
/**
* Login authentication function.
*
* Username and encoded password are passed the onUserLogin event which
* is responsible for the user validation. A successful validation updates
* the current session record with the user's details.
*
* Username and encoded password are sent as credentials (along with other
* possibilities) to each observer (authentication plugin) for user
* validation. Successful validation will update the current session with
* the user details.
*
* @param array $credentials Array('username' => string, 'password' => string)
* @param array $options Array('remember' => boolean)
*
* @return boolean|\JException True on success, false if failed or silent handling is configured, or a \JException object on authentication error.
*
* @since 3.2
*/
public function login($credentials, $options = array())
{
// Get the global \JAuthentication object.
$authenticate = \JAuthentication::getInstance();
$response = $authenticate->authenticate($credentials, $options);
// Import the user plugin group.
\JPluginHelper::importPlugin('user');
if ($response->status === \JAuthentication::STATUS_SUCCESS)
{
/*
* Validate that the user should be able to login (different to being authenticated).
* This permits authentication plugins blocking the user.
*/
$authorisations = $authenticate->authorise($response, $options);
$denied_states = \JAuthentication::STATUS_EXPIRED | \JAuthentication::STATUS_DENIED;
foreach ($authorisations as $authorisation)
{
if ((int) $authorisation->status & $denied_states)
{
// Trigger onUserAuthorisationFailure Event.
$this->triggerEvent('onUserAuthorisationFailure', array((array) $authorisation));
// If silent is set, just return false.
if (isset($options['silent']) && $options['silent'])
{
return false;
}
// Return the error.
switch ($authorisation->status)
{
case \JAuthentication::STATUS_EXPIRED:
return \JError::raiseWarning('102002', \JText::_('JLIB_LOGIN_EXPIRED'));
case \JAuthentication::STATUS_DENIED:
return \JError::raiseWarning('102003', \JText::_('JLIB_LOGIN_DENIED'));
default:
return \JError::raiseWarning('102004', \JText::_('JLIB_LOGIN_AUTHORISATION'));
}
}
}
// OK, the credentials are authenticated and user is authorised. Let's fire the onLogin event.
$results = $this->triggerEvent('onUserLogin', array((array) $response, $options));
/*
* If any of the user plugins did not successfully complete the login routine
* then the whole method fails.
*
* Any errors raised should be done in the plugin as this provides the ability
* to provide much more information about why the routine may have failed.
*/
$user = \JFactory::getUser();
if ($response->type === 'Cookie')
{
$user->set('cookieLogin', true);
}
if (in_array(false, $results, true) == false)
{
$options['user'] = $user;
$options['responseType'] = $response->type;
// The user is successfully logged in. Run the after login events
$this->triggerEvent('onUserAfterLogin', array($options));
return true;
}
}
// Trigger onUserLoginFailure Event.
$this->triggerEvent('onUserLoginFailure', array((array) $response));
// If silent is set, just return false.
if (isset($options['silent']) && $options['silent'])
{
return false;
}
// If status is success, any error will have been raised by the user plugin
if ($response->status !== \JAuthentication::STATUS_SUCCESS)
{
$this->getLogger()->warning($response->error_message, array('category' => 'jerror'));
}
return false;
}
/**
* Logout authentication function.
*
* Passed the current user information to the onUserLogout event and reverts the current
* session record back to 'anonymous' parameters.
* If any of the authentication plugins did not successfully complete
* the logout routine then the whole method fails. Any errors raised
* should be done in the plugin as this provides the ability to give
* much more information about why the routine may have failed.
*
* @param integer $userid The user to load - Can be an integer or string - If string, it is converted to ID automatically
* @param array $options Array('clientid' => array of client id's)
*
* @return boolean True on success
*
* @since 3.2
*/
public function logout($userid = null, $options = array())
{
// Get a user object from the \JApplication.
$user = \JFactory::getUser($userid);
// Build the credentials array.
$parameters['username'] = $user->get('username');
$parameters['id'] = $user->get('id');
// Set clientid in the options array if it hasn't been set already and shared sessions are not enabled.
if (!$this->get('shared_session', '0') && !isset($options['clientid']))
{
$options['clientid'] = $this->getClientId();
}
// Import the user plugin group.
\JPluginHelper::importPlugin('user');
// OK, the credentials are built. Lets fire the onLogout event.
$results = $this->triggerEvent('onUserLogout', array($parameters, $options));
// Check if any of the plugins failed. If none did, success.
if (!in_array(false, $results, true))
{
$options['username'] = $user->get('username');
$this->triggerEvent('onUserAfterLogout', array($options));
return true;
}
// Trigger onUserLoginFailure Event.
$this->triggerEvent('onUserLogoutFailure', array($parameters));
return false;
}
/**
* Redirect to another URL.
*
* If the headers have not been sent the redirect will be accomplished using a "301 Moved Permanently"
* or "303 See Other" code in the header pointing to the new location. If the headers have already been
* sent this will be accomplished using a JavaScript statement.
*
* @param string $url The URL to redirect to. Can only be http/https URL
* @param integer $status The HTTP 1.1 status code to be provided. 303 is assumed by default.
*
* @return void
*
* @since 3.2
*/
public function redirect($url, $status = 303)
{
// Handle B/C by checking if a message was passed to the method, will be removed at 4.0
if (func_num_args() > 1)
{
$args = func_get_args();
/*
* Do some checks on the $args array, values below correspond to legacy redirect() method
*
* $args[0] = $url
* $args[1] = Message to enqueue
* $args[2] = Message type
* $args[3] = $status (previously moved)
*/
if (isset($args[1]) && !empty($args[1]) && (!is_bool($args[1]) && !is_int($args[1])))
{
$this->getLogger()->warning(
'Passing a message and message type to ' . __METHOD__ . '() is deprecated. '
. 'Please set your message via ' . __CLASS__ . '::enqueueMessage() prior to calling ' . __CLASS__
. '::redirect().',
array('category' => 'deprecated')
);
$message = $args[1];
// Set the message type if present
if (isset($args[2]) && !empty($args[2]))
{
$type = $args[2];
}
else
{
$type = 'message';
}
// Enqueue the message
$this->enqueueMessage($message, $type);
// Reset the $moved variable
$status = isset($args[3]) ? (boolean) $args[3] : false;
}
}
// Persist messages if they exist.
if ($this->_messageQueue)
{
$session = \JFactory::getSession();
$session->set('application.queue', $this->_messageQueue);
}
// Hand over processing to the parent now
parent::redirect($url, $status);
}
/**
* Rendering is the process of pushing the document buffers into the template
* placeholders, retrieving data from the document and pushing it into
* the application response buffer.
*
* @return void
*
* @since 3.2
*/
protected function render()
{
// Setup the document options.
$this->docOptions['template'] = $this->get('theme');
$this->docOptions['file'] = $this->get('themeFile', 'index.php');
$this->docOptions['params'] = $this->get('themeParams');
if ($this->get('themes.base'))
{
$this->docOptions['directory'] = $this->get('themes.base');
}
// Fall back to constants.
else
{
$this->docOptions['directory'] = defined('JPATH_THEMES') ? JPATH_THEMES : (defined('JPATH_BASE') ? JPATH_BASE : __DIR__) . '/themes';
}
// Parse the document.
$this->document->parse($this->docOptions);
// Trigger the onBeforeRender event.
\JPluginHelper::importPlugin('system');
$this->triggerEvent('onBeforeRender');
$caching = false;
if ($this->isClient('site') && $this->get('caching') && $this->get('caching', 2) == 2 && !\JFactory::getUser()->get('id'))
{
$caching = true;
}
// Render the document.
$data = $this->document->render($caching, $this->docOptions);
// Set the application output data.
$this->setBody($data);
// Trigger the onAfterRender event.
$this->triggerEvent('onAfterRender');
// Mark afterRender in the profiler.
JDEBUG ? $this->profiler->mark('afterRender') : null;
}
/**
* Route the application.
*
* Routing is the process of examining the request environment to determine which
* component should receive the request. The component optional parameters
* are then set in the request object to be processed when the application is being
* dispatched.
*
* @return void
*
* @since 3.2
*/
protected function route()
{
// Get the full request URI.
$uri = clone \JUri::getInstance();
$router = static::getRouter();
$result = $router->parse($uri);
$active = $this->getMenu()->getActive();
if ($active !== null
&& $active->type === 'alias'
&& $active->params->get('alias_redirect')
&& in_array($this->input->getMethod(), array('GET', 'HEAD'), true))
{
$item = $this->getMenu()->getItem($active->params->get('aliasoptions'));
if ($item !== null)
{
$oldUri = clone \JUri::getInstance();
if ($oldUri->getVar('Itemid') == $active->id)
{
$oldUri->setVar('Itemid', $item->id);
}
$base = \JUri::base(true);
$oldPath = StringHelper::strtolower(substr($oldUri->getPath(), strlen($base) + 1));
$activePathPrefix = StringHelper::strtolower($active->route);
$position = strpos($oldPath, $activePathPrefix);
if ($position !== false)
{
$oldUri->setPath($base . '/' . substr_replace($oldPath, $item->route, $position, strlen($activePathPrefix)));
$this->setHeader('Expires', 'Wed, 17 Aug 2005 00:00:00 GMT', true);
$this->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT', true);
$this->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', false);
$this->setHeader('Pragma', 'no-cache');
$this->sendHeaders();
$this->redirect((string) $oldUri, 301);
}
}
}
foreach ($result as $key => $value)
{
$this->input->def($key, $value);
}
// Trigger the onAfterRoute event.
\JPluginHelper::importPlugin('system');
$this->triggerEvent('onAfterRoute');
}
/**
* Sets the value of a user state variable.
*
* @param string $key The path of the state.
* @param mixed $value The value of the variable.
*
* @return mixed The previous state, if one existed.
*
* @since 3.2
*/
public function setUserState($key, $value)
{
$session = \JFactory::getSession();
$registry = $session->get('registry');
if ($registry !== null)
{
return $registry->set($key, $value);
}
return;
}
/**
* Sends all headers prior to returning the string
*
* @param boolean $compress If true, compress the data
*
* @return string
*
* @since 3.2
*/
public function toString($compress = false)
{
// Don't compress something if the server is going to do it anyway. Waste of time.
if ($compress && !ini_get('zlib.output_compression') && ini_get('output_handler') !== 'ob_gzhandler')
{
$this->compress();
}
if ($this->allowCache() === false)
{
$this->setHeader('Cache-Control', 'no-cache', false);
// HTTP 1.0
$this->setHeader('Pragma', 'no-cache');
}
$this->sendHeaders();
return $this->getBody();
}
}
CliApplication.php 0000644 00000016444 15234470622 0010166 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Application;
defined('JPATH_PLATFORM') or die;
use Joomla\Application\Cli\CliOutput;
use Joomla\CMS\Input\Cli;
use Joomla\CMS\Input\Input;
use Joomla\Registry\Registry;
/**
* Base class for a Joomla! command line application.
*
* @since 2.5.0
* @note As of 4.0 this class will be abstract
*/
class CliApplication extends BaseApplication
{
/**
* @var CliOutput The output type.
* @since 3.3
*/
protected $output;
/**
* @var CliApplication The application instance.
* @since 1.7.0
*/
protected static $instance;
/**
* Class constructor.
*
* @param Cli $input An optional argument to provide dependency injection for the application's
* input object. If the argument is a \JInputCli object that object will become
* the application's input object, otherwise a default input object is created.
* @param Registry $config An optional argument to provide dependency injection for the application's
* config object. If the argument is a Registry object that object will become
* the application's config object, otherwise a default config object is created.
* @param \JEventDispatcher $dispatcher An optional argument to provide dependency injection for the application's
* event dispatcher. If the argument is a \JEventDispatcher object that object will become
* the application's event dispatcher, if it is null then the default event dispatcher
* will be created based on the application's loadDispatcher() method.
*
* @see BaseApplication::loadDispatcher()
* @since 1.7.0
*/
public function __construct(Cli $input = null, Registry $config = null, \JEventDispatcher $dispatcher = null)
{
// Close the application if we are not executed from the command line.
if (!defined('STDOUT') || !defined('STDIN') || !isset($_SERVER['argv']))
{
$this->close();
}
// If an input object is given use it.
if ($input instanceof Input)
{
$this->input = $input;
}
// Create the input based on the application logic.
else
{
if (class_exists('\\Joomla\\CMS\\Input\\Cli'))
{
$this->input = new Cli;
}
}
// If a config object is given use it.
if ($config instanceof Registry)
{
$this->config = $config;
}
// Instantiate a new configuration object.
else
{
$this->config = new Registry;
}
$this->loadDispatcher($dispatcher);
// Load the configuration object.
$this->loadConfiguration($this->fetchConfigurationData());
// Set the execution datetime and timestamp;
$this->set('execution.datetime', gmdate('Y-m-d H:i:s'));
$this->set('execution.timestamp', time());
// Set the current directory.
$this->set('cwd', getcwd());
}
/**
* Returns a reference to the global CliApplication object, only creating it if it doesn't already exist.
*
* This method must be invoked as: $cli = CliApplication::getInstance();
*
* @param string $name The name (optional) of the JApplicationCli class to instantiate.
*
* @return CliApplication
*
* @since 1.7.0
*/
public static function getInstance($name = null)
{
// Only create the object if it doesn't exist.
if (empty(self::$instance))
{
if (class_exists($name) && (is_subclass_of($name, '\\Joomla\\CMS\\Application\\CliApplication')))
{
self::$instance = new $name;
}
else
{
self::$instance = new CliApplication;
}
}
return self::$instance;
}
/**
* Execute the application.
*
* @return void
*
* @since 1.7.0
*/
public function execute()
{
// Trigger the onBeforeExecute event.
$this->triggerEvent('onBeforeExecute');
// Perform application routines.
$this->doExecute();
// Trigger the onAfterExecute event.
$this->triggerEvent('onAfterExecute');
}
/**
* Load an object or array into the application configuration object.
*
* @param mixed $data Either an array or object to be loaded into the configuration object.
*
* @return CliApplication Instance of $this to allow chaining.
*
* @since 1.7.0
*/
public function loadConfiguration($data)
{
// Load the data into the configuration object.
if (is_array($data))
{
$this->config->loadArray($data);
}
elseif (is_object($data))
{
$this->config->loadObject($data);
}
return $this;
}
/**
* Write a string to standard output.
*
* @param string $text The text to display.
* @param boolean $nl True (default) to append a new line at the end of the output string.
*
* @return CliApplication Instance of $this to allow chaining.
*
* @codeCoverageIgnore
* @since 1.7.0
*/
public function out($text = '', $nl = true)
{
$output = $this->getOutput();
$output->out($text, $nl);
return $this;
}
/**
* Get an output object.
*
* @return CliOutput
*
* @since 3.3
*/
public function getOutput()
{
if (!$this->output)
{
// In 4.0, this will convert to throwing an exception and you will expected to
// initialize this in the constructor. Until then set a default.
$default = new \Joomla\Application\Cli\Output\Xml;
$this->setOutput($default);
}
return $this->output;
}
/**
* Set an output object.
*
* @param CliOutput $output CliOutput object
*
* @return CliApplication Instance of $this to allow chaining.
*
* @since 3.3
*/
public function setOutput(CliOutput $output)
{
$this->output = $output;
return $this;
}
/**
* Get a value from standard input.
*
* @return string The input string from standard input.
*
* @codeCoverageIgnore
* @since 1.7.0
*/
public function in()
{
return rtrim(fread(STDIN, 8192), "\n");
}
/**
* Method to load a PHP configuration class file based on convention and return the instantiated data object. You
* will extend this method in child classes to provide configuration data from whatever data source is relevant
* for your specific application.
*
* @param string $file The path and filename of the configuration file. If not provided, configuration.php
* in JPATH_CONFIGURATION will be used.
* @param string $class The class name to instantiate.
*
* @return mixed Either an array or object to be loaded into the configuration object.
*
* @since 1.7.0
*/
protected function fetchConfigurationData($file = '', $class = '\JConfig')
{
// Instantiate variables.
$config = array();
if (empty($file))
{
$file = JPATH_CONFIGURATION . '/configuration.php';
// Applications can choose not to have any configuration data by not implementing this method and not having a config file.
if (!file_exists($file))
{
$file = '';
}
}
if (!empty($file))
{
\JLoader::register($class, $file);
if (class_exists($class))
{
$config = new $class;
}
else
{
throw new \RuntimeException('Configuration class does not exist.');
}
}
return $config;
}
}
DaemonApplication.php 0000644 00000061013 15234470622 0010652 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Application;
defined('JPATH_PLATFORM') or die;
jimport('joomla.filesystem.folder');
use Joomla\Registry\Registry;
/**
* Class to turn CliApplication applications into daemons. It requires CLI and PCNTL support built into PHP.
*
* @link https://www.php.net/manual/en/book.pcntl.php
* @link https://www.php.net/manual/en/features.commandline.php
* @since 1.7.0
*/
class DaemonApplication extends CliApplication
{
/**
* @var array The available POSIX signals to be caught by default.
* @link https://www.php.net/manual/pcntl.constants.php
* @since 1.7.0
*/
protected static $signals = array(
'SIGHUP',
'SIGINT',
'SIGQUIT',
'SIGILL',
'SIGTRAP',
'SIGABRT',
'SIGIOT',
'SIGBUS',
'SIGFPE',
'SIGUSR1',
'SIGSEGV',
'SIGUSR2',
'SIGPIPE',
'SIGALRM',
'SIGTERM',
'SIGSTKFLT',
'SIGCLD',
'SIGCHLD',
'SIGCONT',
'SIGTSTP',
'SIGTTIN',
'SIGTTOU',
'SIGURG',
'SIGXCPU',
'SIGXFSZ',
'SIGVTALRM',
'SIGPROF',
'SIGWINCH',
'SIGPOLL',
'SIGIO',
'SIGPWR',
'SIGSYS',
'SIGBABY',
'SIG_BLOCK',
'SIG_UNBLOCK',
'SIG_SETMASK',
);
/**
* @var boolean True if the daemon is in the process of exiting.
* @since 1.7.0
*/
protected $exiting = false;
/**
* @var integer The parent process id.
* @since 3.0.0
*/
protected $parentId = 0;
/**
* @var integer The process id of the daemon.
* @since 1.7.0
*/
protected $processId = 0;
/**
* @var boolean True if the daemon is currently running.
* @since 1.7.0
*/
protected $running = false;
/**
* Class constructor.
*
* @param \JInputCli $input An optional argument to provide dependency injection for the application's
* input object. If the argument is a \JInputCli object that object will become
* the application's input object, otherwise a default input object is created.
* @param Registry $config An optional argument to provide dependency injection for the application's
* config object. If the argument is a Registry object that object will become
* the application's config object, otherwise a default config object is created.
* @param \JEventDispatcher $dispatcher An optional argument to provide dependency injection for the application's
* event dispatcher. If the argument is a \JEventDispatcher object that object will become
* the application's event dispatcher, if it is null then the default event dispatcher
* will be created based on the application's loadDispatcher() method.
*
* @since 1.7.0
* @throws \RuntimeException
*/
public function __construct(\JInputCli $input = null, Registry $config = null, \JEventDispatcher $dispatcher = null)
{
// Verify that the process control extension for PHP is available.
if (!defined('SIGHUP'))
{
\JLog::add('The PCNTL extension for PHP is not available.', \JLog::ERROR);
throw new \RuntimeException('The PCNTL extension for PHP is not available.');
}
// Verify that POSIX support for PHP is available.
if (!function_exists('posix_getpid'))
{
\JLog::add('The POSIX extension for PHP is not available.', \JLog::ERROR);
throw new \RuntimeException('The POSIX extension for PHP is not available.');
}
// Call the parent constructor.
parent::__construct($input, $config, $dispatcher);
// Set some system limits.
@set_time_limit($this->config->get('max_execution_time', 0));
if ($this->config->get('max_memory_limit') !== null)
{
ini_set('memory_limit', $this->config->get('max_memory_limit', '256M'));
}
// Flush content immediately.
ob_implicit_flush();
}
/**
* Method to handle POSIX signals.
*
* @param integer $signal The received POSIX signal.
*
* @return void
*
* @since 1.7.0
* @see pcntl_signal()
* @throws \RuntimeException
*/
public static function signal($signal)
{
// Log all signals sent to the daemon.
\JLog::add('Received signal: ' . $signal, \JLog::DEBUG);
// Let's make sure we have an application instance.
if (!is_subclass_of(static::$instance, 'CliApplication'))
{
\JLog::add('Cannot find the application instance.', \JLog::EMERGENCY);
throw new \RuntimeException('Cannot find the application instance.');
}
// Fire the onReceiveSignal event.
static::$instance->triggerEvent('onReceiveSignal', array($signal));
switch ($signal)
{
case SIGINT:
case SIGTERM:
// Handle shutdown tasks
if (static::$instance->running && static::$instance->isActive())
{
static::$instance->shutdown();
}
else
{
static::$instance->close();
}
break;
case SIGHUP:
// Handle restart tasks
if (static::$instance->running && static::$instance->isActive())
{
static::$instance->shutdown(true);
}
else
{
static::$instance->close();
}
break;
case SIGCHLD:
// A child process has died
while (static::$instance->pcntlWait($signal, WNOHANG || WUNTRACED) > 0)
{
usleep(1000);
}
break;
case SIGCLD:
while (static::$instance->pcntlWait($signal, WNOHANG) > 0)
{
$signal = static::$instance->pcntlChildExitStatus($signal);
}
break;
default:
break;
}
}
/**
* Check to see if the daemon is active. This does not assume that $this daemon is active, but
* only if an instance of the application is active as a daemon.
*
* @return boolean True if daemon is active.
*
* @since 1.7.0
*/
public function isActive()
{
// Get the process id file location for the application.
$pidFile = $this->config->get('application_pid_file');
// If the process id file doesn't exist then the daemon is obviously not running.
if (!is_file($pidFile))
{
return false;
}
// Read the contents of the process id file as an integer.
$fp = fopen($pidFile, 'r');
$pid = fread($fp, filesize($pidFile));
$pid = (int) $pid;
fclose($fp);
// Check to make sure that the process id exists as a positive integer.
if (!$pid)
{
return false;
}
// Check to make sure the process is active by pinging it and ensure it responds.
if (!posix_kill($pid, 0))
{
// No response so remove the process id file and log the situation.
@ unlink($pidFile);
\JLog::add('The process found based on PID file was unresponsive.', \JLog::WARNING);
return false;
}
return true;
}
/**
* Load an object or array into the application configuration object.
*
* @param mixed $data Either an array or object to be loaded into the configuration object.
*
* @return DaemonApplication Instance of $this to allow chaining.
*
* @since 1.7.0
*/
public function loadConfiguration($data)
{
// Execute the parent load method.
parent::loadConfiguration($data);
/*
* Setup some application metadata options. This is useful if we ever want to write out startup scripts
* or just have some sort of information available to share about things.
*/
// The application author name. This string is used in generating startup scripts and has
// a maximum of 50 characters.
$tmp = (string) $this->config->get('author_name', 'Joomla Platform');
$this->config->set('author_name', (strlen($tmp) > 50) ? substr($tmp, 0, 50) : $tmp);
// The application author email. This string is used in generating startup scripts.
$tmp = (string) $this->config->get('author_email', 'admin@joomla.org');
$this->config->set('author_email', filter_var($tmp, FILTER_VALIDATE_EMAIL));
// The application name. This string is used in generating startup scripts.
$tmp = (string) $this->config->get('application_name', 'DaemonApplication');
$this->config->set('application_name', (string) preg_replace('/[^A-Z0-9_-]/i', '', $tmp));
// The application description. This string is used in generating startup scripts.
$tmp = (string) $this->config->get('application_description', 'A generic Joomla Platform application.');
$this->config->set('application_description', filter_var($tmp, FILTER_SANITIZE_STRING));
/*
* Setup the application path options. This defines the default executable name, executable directory,
* and also the path to the daemon process id file.
*/
// The application executable daemon. This string is used in generating startup scripts.
$tmp = (string) $this->config->get('application_executable', basename($this->input->executable));
$this->config->set('application_executable', $tmp);
// The home directory of the daemon.
$tmp = (string) $this->config->get('application_directory', dirname($this->input->executable));
$this->config->set('application_directory', $tmp);
// The pid file location. This defaults to a path inside the /tmp directory.
$name = $this->config->get('application_name');
$tmp = (string) $this->config->get('application_pid_file', strtolower('/tmp/' . $name . '/' . $name . '.pid'));
$this->config->set('application_pid_file', $tmp);
/*
* Setup the application identity options. It is important to remember if the default of 0 is set for
* either UID or GID then changing that setting will not be attempted as there is no real way to "change"
* the identity of a process from some user to root.
*/
// The user id under which to run the daemon.
$tmp = (int) $this->config->get('application_uid', 0);
$options = array('options' => array('min_range' => 0, 'max_range' => 65000));
$this->config->set('application_uid', filter_var($tmp, FILTER_VALIDATE_INT, $options));
// The group id under which to run the daemon.
$tmp = (int) $this->config->get('application_gid', 0);
$options = array('options' => array('min_range' => 0, 'max_range' => 65000));
$this->config->set('application_gid', filter_var($tmp, FILTER_VALIDATE_INT, $options));
// Option to kill the daemon if it cannot switch to the chosen identity.
$tmp = (bool) $this->config->get('application_require_identity', 1);
$this->config->set('application_require_identity', $tmp);
/*
* Setup the application runtime options. By default our execution time limit is infinite obviously
* because a daemon should be constantly running unless told otherwise. The default limit for memory
* usage is 256M, which admittedly is a little high, but remember it is a "limit" and PHP's memory
* management leaves a bit to be desired :-)
*/
// The maximum execution time of the application in seconds. Zero is infinite.
$tmp = $this->config->get('max_execution_time');
if ($tmp !== null)
{
$this->config->set('max_execution_time', (int) $tmp);
}
// The maximum amount of memory the application can use.
$tmp = $this->config->get('max_memory_limit', '256M');
if ($tmp !== null)
{
$this->config->set('max_memory_limit', (string) $tmp);
}
return $this;
}
/**
* Execute the daemon.
*
* @return void
*
* @since 1.7.0
*/
public function execute()
{
// Trigger the onBeforeExecute event.
$this->triggerEvent('onBeforeExecute');
// Enable basic garbage collection.
gc_enable();
\JLog::add('Starting ' . $this->name, \JLog::INFO);
// Set off the process for becoming a daemon.
if ($this->daemonize())
{
// Declare ticks to start signal monitoring. When you declare ticks, PCNTL will monitor
// incoming signals after each tick and call the relevant signal handler automatically.
declare (ticks = 1);
// Start the main execution loop.
while (true)
{
// Perform basic garbage collection.
$this->gc();
// Don't completely overload the CPU.
usleep(1000);
// Execute the main application logic.
$this->doExecute();
}
}
// We were not able to daemonize the application so log the failure and die gracefully.
else
{
\JLog::add('Starting ' . $this->name . ' failed', \JLog::INFO);
}
// Trigger the onAfterExecute event.
$this->triggerEvent('onAfterExecute');
}
/**
* Restart daemon process.
*
* @return void
*
* @since 1.7.0
*/
public function restart()
{
\JLog::add('Stopping ' . $this->name, \JLog::INFO);
$this->shutdown(true);
}
/**
* Stop daemon process.
*
* @return void
*
* @since 1.7.0
*/
public function stop()
{
\JLog::add('Stopping ' . $this->name, \JLog::INFO);
$this->shutdown();
}
/**
* Method to change the identity of the daemon process and resources.
*
* @return boolean True if identity successfully changed
*
* @since 1.7.0
* @see posix_setuid()
*/
protected function changeIdentity()
{
// Get the group and user ids to set for the daemon.
$uid = (int) $this->config->get('application_uid', 0);
$gid = (int) $this->config->get('application_gid', 0);
// Get the application process id file path.
$file = $this->config->get('application_pid_file');
// Change the user id for the process id file if necessary.
if ($uid && (fileowner($file) != $uid) && (!@ chown($file, $uid)))
{
\JLog::add('Unable to change user ownership of the process id file.', \JLog::ERROR);
return false;
}
// Change the group id for the process id file if necessary.
if ($gid && (filegroup($file) != $gid) && (!@ chgrp($file, $gid)))
{
\JLog::add('Unable to change group ownership of the process id file.', \JLog::ERROR);
return false;
}
// Set the correct home directory for the process.
if ($uid && ($info = posix_getpwuid($uid)) && is_dir($info['dir']))
{
system('export HOME="' . $info['dir'] . '"');
}
// Change the user id for the process necessary.
if ($uid && (posix_getuid($file) != $uid) && (!@ posix_setuid($uid)))
{
\JLog::add('Unable to change user ownership of the proccess.', \JLog::ERROR);
return false;
}
// Change the group id for the process necessary.
if ($gid && (posix_getgid($file) != $gid) && (!@ posix_setgid($gid)))
{
\JLog::add('Unable to change group ownership of the proccess.', \JLog::ERROR);
return false;
}
// Get the user and group information based on uid and gid.
$user = posix_getpwuid($uid);
$group = posix_getgrgid($gid);
\JLog::add('Changed daemon identity to ' . $user['name'] . ':' . $group['name'], \JLog::INFO);
return true;
}
/**
* Method to put the application into the background.
*
* @return boolean
*
* @since 1.7.0
* @throws \RuntimeException
*/
protected function daemonize()
{
// Is there already an active daemon running?
if ($this->isActive())
{
\JLog::add($this->name . ' daemon is still running. Exiting the application.', \JLog::EMERGENCY);
return false;
}
// Reset Process Information
$this->safeMode = !!@ ini_get('safe_mode');
$this->processId = 0;
$this->running = false;
// Detach process!
try
{
// Check if we should run in the foreground.
if (!$this->input->get('f'))
{
// Detach from the terminal.
$this->detach();
}
else
{
// Setup running values.
$this->exiting = false;
$this->running = true;
// Set the process id.
$this->processId = (int) posix_getpid();
$this->parentId = $this->processId;
}
}
catch (\RuntimeException $e)
{
\JLog::add('Unable to fork.', \JLog::EMERGENCY);
return false;
}
// Verify the process id is valid.
if ($this->processId < 1)
{
\JLog::add('The process id is invalid; the fork failed.', \JLog::EMERGENCY);
return false;
}
// Clear the umask.
@ umask(0);
// Write out the process id file for concurrency management.
if (!$this->writeProcessIdFile())
{
\JLog::add('Unable to write the pid file at: ' . $this->config->get('application_pid_file'), \JLog::EMERGENCY);
return false;
}
// Attempt to change the identity of user running the process.
if (!$this->changeIdentity())
{
// If the identity change was required then we need to return false.
if ($this->config->get('application_require_identity'))
{
\JLog::add('Unable to change process owner.', \JLog::CRITICAL);
return false;
}
else
{
\JLog::add('Unable to change process owner.', \JLog::WARNING);
}
}
// Setup the signal handlers for the daemon.
if (!$this->setupSignalHandlers())
{
return false;
}
// Change the current working directory to the application working directory.
@ chdir($this->config->get('application_directory'));
return true;
}
/**
* This is truly where the magic happens. This is where we fork the process and kill the parent
* process, which is essentially what turns the application into a daemon.
*
* @return void
*
* @since 3.0.0
* @throws \RuntimeException
*/
protected function detach()
{
\JLog::add('Detaching the ' . $this->name . ' daemon.', \JLog::DEBUG);
// Attempt to fork the process.
$pid = $this->fork();
// If the pid is positive then we successfully forked, and can close this application.
if ($pid)
{
// Add the log entry for debugging purposes and exit gracefully.
\JLog::add('Ending ' . $this->name . ' parent process', \JLog::DEBUG);
$this->close();
}
// We are in the forked child process.
else
{
// Setup some protected values.
$this->exiting = false;
$this->running = true;
// Set the parent to self.
$this->parentId = $this->processId;
}
}
/**
* Method to fork the process.
*
* @return integer The child process id to the parent process, zero to the child process.
*
* @since 1.7.0
* @throws \RuntimeException
*/
protected function fork()
{
// Attempt to fork the process.
$pid = $this->pcntlFork();
// If the fork failed, throw an exception.
if ($pid === -1)
{
throw new \RuntimeException('The process could not be forked.');
}
// Update the process id for the child.
elseif ($pid === 0)
{
$this->processId = (int) posix_getpid();
}
// Log the fork in the parent.
else
{
// Log the fork.
\JLog::add('Process forked ' . $pid, \JLog::DEBUG);
}
// Trigger the onFork event.
$this->postFork();
return $pid;
}
/**
* Method to perform basic garbage collection and memory management in the sense of clearing the
* stat cache. We will probably call this method pretty regularly in our main loop.
*
* @return void
*
* @since 1.7.0
*/
protected function gc()
{
// Perform generic garbage collection.
gc_collect_cycles();
// Clear the stat cache so it doesn't blow up memory.
clearstatcache();
}
/**
* Method to attach the DaemonApplication signal handler to the known signals. Applications
* can override these handlers by using the pcntl_signal() function and attaching a different
* callback method.
*
* @return boolean
*
* @since 1.7.0
* @see pcntl_signal()
*/
protected function setupSignalHandlers()
{
// We add the error suppression for the loop because on some platforms some constants are not defined.
foreach (self::$signals as $signal)
{
// Ignore signals that are not defined.
if (!defined($signal) || !is_int(constant($signal)) || (constant($signal) === 0))
{
// Define the signal to avoid notices.
\JLog::add('Signal "' . $signal . '" not defined. Defining it as null.', \JLog::DEBUG);
define($signal, null);
// Don't listen for signal.
continue;
}
// Attach the signal handler for the signal.
if (!$this->pcntlSignal(constant($signal), array('DaemonApplication', 'signal')))
{
\JLog::add(sprintf('Unable to reroute signal handler: %s', $signal), \JLog::EMERGENCY);
return false;
}
}
return true;
}
/**
* Method to shut down the daemon and optionally restart it.
*
* @param boolean $restart True to restart the daemon on exit.
*
* @return void
*
* @since 1.7.0
*/
protected function shutdown($restart = false)
{
// If we are already exiting, chill.
if ($this->exiting)
{
return;
}
// If not, now we are.
else
{
$this->exiting = true;
}
// If we aren't already daemonized then just kill the application.
if (!$this->running && !$this->isActive())
{
\JLog::add('Process was not daemonized yet, just halting current process', \JLog::INFO);
$this->close();
}
// Only read the pid for the parent file.
if ($this->parentId == $this->processId)
{
// Read the contents of the process id file as an integer.
$fp = fopen($this->config->get('application_pid_file'), 'r');
$pid = fread($fp, filesize($this->config->get('application_pid_file')));
$pid = (int) $pid;
fclose($fp);
// Remove the process id file.
@ unlink($this->config->get('application_pid_file'));
// If we are supposed to restart the daemon we need to execute the same command.
if ($restart)
{
$this->close(exec(implode(' ', $GLOBALS['argv']) . ' > /dev/null &'));
}
// If we are not supposed to restart the daemon let's just kill -9.
else
{
passthru('kill -9 ' . $pid);
$this->close();
}
}
}
/**
* Method to write the process id file out to disk.
*
* @return boolean
*
* @since 1.7.0
*/
protected function writeProcessIdFile()
{
// Verify the process id is valid.
if ($this->processId < 1)
{
\JLog::add('The process id is invalid.', \JLog::EMERGENCY);
return false;
}
// Get the application process id file path.
$file = $this->config->get('application_pid_file');
if (empty($file))
{
\JLog::add('The process id file path is empty.', \JLog::ERROR);
return false;
}
// Make sure that the folder where we are writing the process id file exists.
$folder = dirname($file);
if (!is_dir($folder) && !\JFolder::create($folder))
{
\JLog::add('Unable to create directory: ' . $folder, \JLog::ERROR);
return false;
}
// Write the process id file out to disk.
if (!file_put_contents($file, $this->processId))
{
\JLog::add('Unable to write proccess id file: ' . $file, \JLog::ERROR);
return false;
}
// Make sure the permissions for the proccess id file are accurate.
if (!chmod($file, 0644))
{
\JLog::add('Unable to adjust permissions for the proccess id file: ' . $file, \JLog::ERROR);
return false;
}
return true;
}
/**
* Method to handle post-fork triggering of the onFork event.
*
* @return void
*
* @since 3.0.0
*/
protected function postFork()
{
// Trigger the onFork event.
$this->triggerEvent('onFork');
}
/**
* Method to return the exit code of a terminated child process.
*
* @param integer $status The status parameter is the status parameter supplied to a successful call to pcntl_waitpid().
*
* @return integer The child process exit code.
*
* @see pcntl_wexitstatus()
* @since 1.7.3
*/
protected function pcntlChildExitStatus($status)
{
return pcntl_wexitstatus($status);
}
/**
* Method to return the exit code of a terminated child process.
*
* @return integer On success, the PID of the child process is returned in the parent's thread
* of execution, and a 0 is returned in the child's thread of execution. On
* failure, a -1 will be returned in the parent's context, no child process
* will be created, and a PHP error is raised.
*
* @see pcntl_fork()
* @since 1.7.3
*/
protected function pcntlFork()
{
return pcntl_fork();
}
/**
* Method to install a signal handler.
*
* @param integer $signal The signal number.
* @param callable $handler The signal handler which may be the name of a user created function,
* or method, or either of the two global constants SIG_IGN or SIG_DFL.
* @param boolean $restart Specifies whether system call restarting should be used when this
* signal arrives.
*
* @return boolean True on success.
*
* @see pcntl_signal()
* @since 1.7.3
*/
protected function pcntlSignal($signal, $handler, $restart = true)
{
return pcntl_signal($signal, $handler, $restart);
}
/**
* Method to wait on or return the status of a forked child.
*
* @param integer &$status Status information.
* @param integer $options If wait3 is available on your system (mostly BSD-style systems),
* you can provide the optional options parameter.
*
* @return integer The process ID of the child which exited, -1 on error or zero if WNOHANG
* was provided as an option (on wait3-available systems) and no child was available.
*
* @see pcntl_wait()
* @since 1.7.3
*/
protected function pcntlWait(&$status, $options = 0)
{
return pcntl_wait($status, $options);
}
}
SiteApplication.php 0000644 00000052430 15234470622 0010356 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Application;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Input\Input;
use Joomla\Registry\Registry;
/**
* Joomla! Site Application class
*
* @since 3.2
*/
final class SiteApplication extends CMSApplication
{
/**
* Option to filter by language
*
* @var boolean
* @since 3.2
* @deprecated 4.0 Will be renamed $language_filter
*/
protected $_language_filter = false;
/**
* Option to detect language by the browser
*
* @var boolean
* @since 3.2
* @deprecated 4.0 Will be renamed $detect_browser
*/
protected $_detect_browser = false;
/**
* Class constructor.
*
* @param Input $input An optional argument to provide dependency injection for the application's
* input object. If the argument is a \JInput object that object will become
* the application's input object, otherwise a default input object is created.
* @param Registry $config An optional argument to provide dependency injection for the application's
* config object. If the argument is a Registry object that object will become
* the application's config object, otherwise a default config object is created.
* @param \JApplicationWebClient $client An optional argument to provide dependency injection for the application's
* client object. If the argument is a \JApplicationWebClient object that object will become
* the application's client object, otherwise a default client object is created.
*
* @since 3.2
*/
public function __construct(Input $input = null, Registry $config = null, \JApplicationWebClient $client = null)
{
// Register the application name
$this->_name = 'site';
// Register the client ID
$this->_clientId = 0;
// Execute the parent constructor
parent::__construct($input, $config, $client);
}
/**
* Check if the user can access the application
*
* @param integer $itemid The item ID to check authorisation for
*
* @return void
*
* @since 3.2
*
* @throws \Exception When you are not authorised to view the home page menu item
*/
protected function authorise($itemid)
{
$menus = $this->getMenu();
$user = \JFactory::getUser();
if (!$menus->authorise($itemid))
{
if ($user->get('id') == 0)
{
// Set the data
$this->setUserState('users.login.form.data', array('return' => \JUri::getInstance()->toString()));
$url = \JRoute::_('index.php?option=com_users&view=login', false);
$this->enqueueMessage(\JText::_('JGLOBAL_YOU_MUST_LOGIN_FIRST'), 'error');
$this->redirect($url);
}
else
{
// Get the home page menu item
$home_item = $menus->getDefault($this->getLanguage()->getTag());
// If we are already in the homepage raise an exception
if ($menus->getActive()->id == $home_item->id)
{
throw new \Exception(\JText::_('JERROR_ALERTNOAUTHOR'), 403);
}
// Otherwise redirect to the homepage and show an error
$this->enqueueMessage(\JText::_('JERROR_ALERTNOAUTHOR'), 'error');
$this->redirect(\JRoute::_('index.php?Itemid=' . $home_item->id, false));
}
}
}
/**
* Dispatch the application
*
* @param string $component The component which is being rendered.
*
* @return void
*
* @since 3.2
*/
public function dispatch($component = null)
{
// Get the component if not set.
if (!$component)
{
$component = $this->input->getCmd('option', null);
}
// Load the document to the API
$this->loadDocument();
// Set up the params
$document = $this->getDocument();
$router = static::getRouter();
$params = $this->getParams();
// Register the document object with \JFactory
\JFactory::$document = $document;
switch ($document->getType())
{
case 'html':
// Get language
$lang_code = $this->getLanguage()->getTag();
$languages = \JLanguageHelper::getLanguages('lang_code');
// Set metadata
if (isset($languages[$lang_code]) && $languages[$lang_code]->metakey)
{
$document->setMetaData('keywords', $languages[$lang_code]->metakey);
}
else
{
$document->setMetaData('keywords', $this->get('MetaKeys'));
}
$document->setMetaData('rights', $this->get('MetaRights'));
if ($router->getMode() == JROUTER_MODE_SEF)
{
$document->setBase(htmlspecialchars(\JUri::current()));
}
// Get the template
$template = $this->getTemplate(true);
// Store the template and its params to the config
$this->set('theme', $template->template);
$this->set('themeParams', $template->params);
break;
case 'feed':
$document->setBase(htmlspecialchars(\JUri::current()));
break;
}
$document->setTitle($params->get('page_title'));
$document->setDescription($params->get('page_description'));
// Add version number or not based on global configuration
if ($this->get('MetaVersion', 0))
{
$document->setGenerator('Joomla! - Open Source Content Management - Version ' . JVERSION);
}
else
{
$document->setGenerator('Joomla! - Open Source Content Management');
}
$contents = ComponentHelper::renderComponent($component);
$document->setBuffer($contents, 'component');
// Trigger the onAfterDispatch event.
\JPluginHelper::importPlugin('system');
$this->triggerEvent('onAfterDispatch');
}
/**
* Method to run the Web application routines.
*
* @return void
*
* @since 3.2
*/
protected function doExecute()
{
// Initialise the application
$this->initialiseApp();
// Mark afterInitialise in the profiler.
JDEBUG ? $this->profiler->mark('afterInitialise') : null;
// Route the application
$this->route();
// Mark afterRoute in the profiler.
JDEBUG ? $this->profiler->mark('afterRoute') : null;
/*
* Check if the user is required to reset their password
*
* Before $this->route(); "option" and "view" can't be safely read using:
* $this->input->getCmd('option'); or $this->input->getCmd('view');
* ex: due of the sef urls
*/
$this->checkUserRequireReset('com_users', 'profile', 'edit', 'com_users/profile.save,com_users/profile.apply,com_users/user.logout');
// Dispatch the application
$this->dispatch();
// Mark afterDispatch in the profiler.
JDEBUG ? $this->profiler->mark('afterDispatch') : null;
}
/**
* Return the current state of the detect browser option.
*
* @return boolean
*
* @since 3.2
*/
public function getDetectBrowser()
{
return $this->_detect_browser;
}
/**
* Return the current state of the language filter.
*
* @return boolean
*
* @since 3.2
*/
public function getLanguageFilter()
{
return $this->_language_filter;
}
/**
* Return a reference to the \JMenu object.
*
* @param string $name The name of the application/client.
* @param array $options An optional associative array of configuration settings.
*
* @return \JMenu \JMenu object.
*
* @since 3.2
*/
public function getMenu($name = 'site', $options = array())
{
return parent::getMenu($name, $options);
}
/**
* Get the application parameters
*
* @param string $option The component option
*
* @return Registry The parameters object
*
* @since 3.2
* @deprecated 4.0 Use getParams() instead
*/
public function getPageParameters($option = null)
{
return $this->getParams($option);
}
/**
* Get the application parameters
*
* @param string $option The component option
*
* @return Registry The parameters object
*
* @since 3.2
*/
public function getParams($option = null)
{
static $params = array();
$hash = '__default';
if (!empty($option))
{
$hash = $option;
}
if (!isset($params[$hash]))
{
// Get component parameters
if (!$option)
{
$option = $this->input->getCmd('option', null);
}
// Get new instance of component global parameters
$params[$hash] = clone ComponentHelper::getParams($option);
// Get menu parameters
$menus = $this->getMenu();
$menu = $menus->getActive();
// Get language
$lang_code = $this->getLanguage()->getTag();
$languages = \JLanguageHelper::getLanguages('lang_code');
$title = $this->get('sitename');
if (isset($languages[$lang_code]) && $languages[$lang_code]->metadesc)
{
$description = $languages[$lang_code]->metadesc;
}
else
{
$description = $this->get('MetaDesc');
}
$rights = $this->get('MetaRights');
$robots = $this->get('robots');
// Retrieve com_menu global settings
$temp = clone ComponentHelper::getParams('com_menus');
// Lets cascade the parameters if we have menu item parameters
if (is_object($menu))
{
// Get show_page_heading from com_menu global settings
$params[$hash]->def('show_page_heading', $temp->get('show_page_heading'));
$params[$hash]->merge($menu->params);
$title = $menu->title;
}
else
{
// Merge com_menu global settings
$params[$hash]->merge($temp);
// If supplied, use page title
$title = $temp->get('page_title', $title);
}
$params[$hash]->def('page_title', $title);
$params[$hash]->def('page_description', $description);
$params[$hash]->def('page_rights', $rights);
$params[$hash]->def('robots', $robots);
}
return $params[$hash];
}
/**
* Return a reference to the \JPathway object.
*
* @param string $name The name of the application.
* @param array $options An optional associative array of configuration settings.
*
* @return \JPathway A \JPathway object
*
* @since 3.2
*/
public function getPathway($name = 'site', $options = array())
{
return parent::getPathway($name, $options);
}
/**
* Return a reference to the \JRouter object.
*
* @param string $name The name of the application.
* @param array $options An optional associative array of configuration settings.
*
* @return \JRouter
*
* @since 3.2
*/
public static function getRouter($name = 'site', array $options = array())
{
return parent::getRouter($name, $options);
}
/**
* Gets the name of the current template.
*
* @param boolean $params True to return the template parameters
*
* @return string The name of the template.
*
* @since 3.2
* @throws \InvalidArgumentException
*/
public function getTemplate($params = false)
{
if (is_object($this->template))
{
if (!file_exists(JPATH_THEMES . '/' . $this->template->template . '/index.php'))
{
throw new \InvalidArgumentException(\JText::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $this->template->template));
}
if ($params)
{
return $this->template;
}
return $this->template->template;
}
// Get the id of the active menu item
$menu = $this->getMenu();
$item = $menu->getActive();
if (!$item)
{
$item = $menu->getItem($this->input->getInt('Itemid', null));
}
$id = 0;
if (is_object($item))
{
// Valid item retrieved
$id = $item->template_style_id;
}
$tid = $this->input->getUint('templateStyle', 0);
if (is_numeric($tid) && (int) $tid > 0)
{
$id = (int) $tid;
}
$cache = \JFactory::getCache('com_templates', '');
if ($this->_language_filter)
{
$tag = $this->getLanguage()->getTag();
}
else
{
$tag = '';
}
$cacheId = 'templates0' . $tag;
if ($cache->contains($cacheId))
{
$templates = $cache->get($cacheId);
}
else
{
// Load styles
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('id, home, template, s.params')
->from('#__template_styles as s')
->where('s.client_id = 0')
->where('e.enabled = 1')
->join('LEFT', '#__extensions as e ON e.element=s.template AND e.type=' . $db->quote('template') . ' AND e.client_id=s.client_id');
$db->setQuery($query);
$templates = $db->loadObjectList('id');
foreach ($templates as &$template)
{
// Create home element
if ($template->home == 1 && !isset($template_home) || $this->_language_filter && $template->home == $tag)
{
$template_home = clone $template;
}
$template->params = new Registry($template->params);
}
// Unset the $template reference to the last $templates[n] item cycled in the foreach above to avoid editing it later
unset($template);
// Add home element, after loop to avoid double execution
if (isset($template_home))
{
$template_home->params = new Registry($template_home->params);
$templates[0] = $template_home;
}
$cache->store($templates, $cacheId);
}
if (isset($templates[$id]))
{
$template = $templates[$id];
}
else
{
$template = $templates[0];
}
// Allows for overriding the active template from the request
$template_override = $this->input->getCmd('template', '');
// Only set template override if it is a valid template (= it exists and is enabled)
if (!empty($template_override))
{
if (file_exists(JPATH_THEMES . '/' . $template_override . '/index.php'))
{
foreach ($templates as $tmpl)
{
if ($tmpl->template === $template_override)
{
$template = $tmpl;
break;
}
}
}
}
// Need to filter the default value as well
$template->template = \JFilterInput::getInstance()->clean($template->template, 'cmd');
// Fallback template
if (!file_exists(JPATH_THEMES . '/' . $template->template . '/index.php'))
{
$this->enqueueMessage(\JText::_('JERROR_ALERTNOTEMPLATE'), 'error');
// Try to find data for 'beez3' template
$original_tmpl = $template->template;
foreach ($templates as $tmpl)
{
if ($tmpl->template === 'beez3')
{
$template = $tmpl;
break;
}
}
// Check, the data were found and if template really exists
if (!file_exists(JPATH_THEMES . '/' . $template->template . '/index.php'))
{
throw new \InvalidArgumentException(\JText::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $original_tmpl));
}
}
// Cache the result
$this->template = $template;
if ($params)
{
return $template;
}
return $template->template;
}
/**
* Initialise the application.
*
* @param array $options An optional associative array of configuration settings.
*
* @return void
*
* @since 3.2
*/
protected function initialiseApp($options = array())
{
$user = \JFactory::getUser();
// If the user is a guest we populate it with the guest user group.
if ($user->guest)
{
$guestUsergroup = ComponentHelper::getParams('com_users')->get('guest_usergroup', 1);
$user->groups = array($guestUsergroup);
}
/*
* If a language was specified it has priority, otherwise use user or default language settings
* Check this only if the languagefilter plugin is enabled
*
* @TODO - Remove the hardcoded dependency to the languagefilter plugin
*/
if (\JPluginHelper::isEnabled('system', 'languagefilter'))
{
$plugin = \JPluginHelper::getPlugin('system', 'languagefilter');
$pluginParams = new Registry($plugin->params);
$this->setLanguageFilter(true);
$this->setDetectBrowser($pluginParams->get('detect_browser', '1') == '1');
}
if (empty($options['language']))
{
// Detect the specified language
$lang = $this->input->getString('language', null);
// Make sure that the user's language exists
if ($lang && \JLanguageHelper::exists($lang))
{
$options['language'] = $lang;
}
}
if (empty($options['language']) && $this->getLanguageFilter())
{
// Detect cookie language
$lang = $this->input->cookie->get(md5($this->get('secret') . 'language'), null, 'string');
// Make sure that the user's language exists
if ($lang && \JLanguageHelper::exists($lang))
{
$options['language'] = $lang;
}
}
if (empty($options['language']))
{
// Detect user language
$lang = $user->getParam('language');
// Make sure that the user's language exists
if ($lang && \JLanguageHelper::exists($lang))
{
$options['language'] = $lang;
}
}
if (empty($options['language']) && $this->getDetectBrowser())
{
// Detect browser language
$lang = \JLanguageHelper::detectLanguage();
// Make sure that the user's language exists
if ($lang && \JLanguageHelper::exists($lang))
{
$options['language'] = $lang;
}
}
if (empty($options['language']))
{
// Detect default language
$params = ComponentHelper::getParams('com_languages');
$options['language'] = $params->get('site', $this->get('language', 'en-GB'));
}
// One last check to make sure we have something
if (!\JLanguageHelper::exists($options['language']))
{
$lang = $this->config->get('language', 'en-GB');
if (\JLanguageHelper::exists($lang))
{
$options['language'] = $lang;
}
else
{
// As a last ditch fail to english
$options['language'] = 'en-GB';
}
}
// Finish initialisation
parent::initialiseApp($options);
}
/**
* Load the library language files for the application
*
* @return void
*
* @since 3.6.3
*/
protected function loadLibraryLanguage()
{
/*
* Try the lib_joomla file in the current language (without allowing the loading of the file in the default language)
* Fallback to the default language if necessary
*/
$this->getLanguage()->load('lib_joomla', JPATH_SITE, null, false, true)
|| $this->getLanguage()->load('lib_joomla', JPATH_ADMINISTRATOR, null, false, true);
}
/**
* Login authentication function
*
* @param array $credentials Array('username' => string, 'password' => string)
* @param array $options Array('remember' => boolean)
*
* @return boolean True on success.
*
* @since 3.2
*/
public function login($credentials, $options = array())
{
// Set the application login entry point
if (!array_key_exists('entry_url', $options))
{
$options['entry_url'] = \JUri::base() . 'index.php?option=com_users&task=user.login';
}
// Set the access control action to check.
$options['action'] = 'core.login.site';
return parent::login($credentials, $options);
}
/**
* Rendering is the process of pushing the document buffers into the template
* placeholders, retrieving data from the document and pushing it into
* the application response buffer.
*
* @return void
*
* @since 3.2
*/
protected function render()
{
switch ($this->document->getType())
{
case 'feed':
// No special processing for feeds
break;
case 'html':
default:
$template = $this->getTemplate(true);
$file = $this->input->get('tmpl', 'index');
if ($file === 'offline' && !$this->get('offline'))
{
$this->set('themeFile', 'index.php');
}
if ($this->get('offline') && !\JFactory::getUser()->authorise('core.login.offline'))
{
$this->setUserState('users.login.form.data', array('return' => \JUri::getInstance()->toString()));
$this->set('themeFile', 'offline.php');
$this->setHeader('Status', '503 Service Temporarily Unavailable', 'true');
}
if (!is_dir(JPATH_THEMES . '/' . $template->template) && !$this->get('offline'))
{
$this->set('themeFile', 'component.php');
}
// Ensure themeFile is set by now
if ($this->get('themeFile') == '')
{
$this->set('themeFile', $file . '.php');
}
break;
}
parent::render();
}
/**
* Route the application.
*
* Routing is the process of examining the request environment to determine which
* component should receive the request. The component optional parameters
* are then set in the request object to be processed when the application is being
* dispatched.
*
* @return void
*
* @since 3.2
*/
protected function route()
{
// Execute the parent method
parent::route();
$Itemid = $this->input->getInt('Itemid', null);
$this->authorise($Itemid);
}
/**
* Set the current state of the detect browser option.
*
* @param boolean $state The new state of the detect browser option
*
* @return boolean The previous state
*
* @since 3.2
*/
public function setDetectBrowser($state = false)
{
$old = $this->_detect_browser;
$this->_detect_browser = $state;
return $old;
}
/**
* Set the current state of the language filter.
*
* @param boolean $state The new state of the language filter
*
* @return boolean The previous state
*
* @since 3.2
*/
public function setLanguageFilter($state = false)
{
$old = $this->_language_filter;
$this->_language_filter = $state;
return $old;
}
/**
* Overrides the default template that would be used
*
* @param string $template The template name
* @param mixed $styleParams The template style parameters
*
* @return void
*
* @since 3.2
*/
public function setTemplate($template, $styleParams = null)
{
if (is_dir(JPATH_THEMES . '/' . $template))
{
$this->template = new \stdClass;
$this->template->template = $template;
if ($styleParams instanceof Registry)
{
$this->template->params = $styleParams;
}
else
{
$this->template->params = new Registry($styleParams);
}
// Store the template and its params to the config
$this->set('theme', $this->template->template);
$this->set('themeParams', $this->template->params);
}
}
}
WebApplication.php 0000644 00000112577 15234470622 0010200 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Application;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Input\Input;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
/**
* Base class for a Joomla! Web application.
*
* @since 2.5.0
* @note As of 4.0 this class will be abstract
*/
class WebApplication extends BaseApplication
{
/**
* @var string Character encoding string.
* @since 1.7.3
*/
public $charSet = 'utf-8';
/**
* @var string Response mime type.
* @since 1.7.3
*/
public $mimeType = 'text/html';
/**
* @var \JDate The body modified date for response headers.
* @since 1.7.3
*/
public $modifiedDate;
/**
* @var \JApplicationWebClient The application client object.
* @since 1.7.3
*/
public $client;
/**
* @var \JDocument The application document object.
* @since 1.7.3
*/
protected $document;
/**
* @var \JLanguage The application language object.
* @since 1.7.3
*/
protected $language;
/**
* @var \JSession The application session object.
* @since 1.7.3
*/
protected $session;
/**
* @var object The application response object.
* @since 1.7.3
*/
protected $response;
/**
* @var WebApplication The application instance.
* @since 1.7.3
*/
protected static $instance;
/**
* A map of integer HTTP 1.1 response codes to the full HTTP Status for the headers.
*
* @var object
* @since 3.4
* @link http://tools.ietf.org/pdf/rfc7231.pdf
*/
private $responseMap = array(
100 => 'HTTP/1.1 100 Continue',
101 => 'HTTP/1.1 101 Switching Protocols',
102 => 'HTTP/1.1 102 Processing',
200 => 'HTTP/1.1 200 OK',
201 => 'HTTP/1.1 201 Created',
202 => 'HTTP/1.1 202 Accepted',
203 => 'HTTP/1.1 203 Non-Authoritative Information',
204 => 'HTTP/1.1 204 No Content',
205 => 'HTTP/1.1 205 Reset Content',
206 => 'HTTP/1.1 206 Partial Content',
207 => 'HTTP/1.1 207 Multi-Status',
208 => 'HTTP/1.1 208 Already Reported',
226 => 'HTTP/1.1 226 IM Used',
300 => 'HTTP/1.1 300 Multiple Choices',
301 => 'HTTP/1.1 301 Moved Permanently',
302 => 'HTTP/1.1 302 Found',
303 => 'HTTP/1.1 303 See other',
304 => 'HTTP/1.1 304 Not Modified',
305 => 'HTTP/1.1 305 Use Proxy',
306 => 'HTTP/1.1 306 (Unused)',
307 => 'HTTP/1.1 307 Temporary Redirect',
308 => 'HTTP/1.1 308 Permanent Redirect',
400 => 'HTTP/1.1 400 Bad Request',
401 => 'HTTP/1.1 401 Unauthorized',
402 => 'HTTP/1.1 402 Payment Required',
403 => 'HTTP/1.1 403 Forbidden',
404 => 'HTTP/1.1 404 Not Found',
405 => 'HTTP/1.1 405 Method Not Allowed',
406 => 'HTTP/1.1 406 Not Acceptable',
407 => 'HTTP/1.1 407 Proxy Authentication Required',
408 => 'HTTP/1.1 408 Request Timeout',
409 => 'HTTP/1.1 409 Conflict',
410 => 'HTTP/1.1 410 Gone',
411 => 'HTTP/1.1 411 Length Required',
412 => 'HTTP/1.1 412 Precondition Failed',
413 => 'HTTP/1.1 413 Payload Too Large',
414 => 'HTTP/1.1 414 URI Too Long',
415 => 'HTTP/1.1 415 Unsupported Media Type',
416 => 'HTTP/1.1 416 Range Not Satisfiable',
417 => 'HTTP/1.1 417 Expectation Failed',
418 => 'HTTP/1.1 418 I\'m a teapot',
421 => 'HTTP/1.1 421 Misdirected Request',
422 => 'HTTP/1.1 422 Unprocessable Entity',
423 => 'HTTP/1.1 423 Locked',
424 => 'HTTP/1.1 424 Failed Dependency',
426 => 'HTTP/1.1 426 Upgrade Required',
428 => 'HTTP/1.1 428 Precondition Required',
429 => 'HTTP/1.1 429 Too Many Requests',
431 => 'HTTP/1.1 431 Request Header Fields Too Large',
451 => 'HTTP/1.1 451 Unavailable For Legal Reasons',
500 => 'HTTP/1.1 500 Internal Server Error',
501 => 'HTTP/1.1 501 Not Implemented',
502 => 'HTTP/1.1 502 Bad Gateway',
503 => 'HTTP/1.1 503 Service Unavailable',
504 => 'HTTP/1.1 504 Gateway Timeout',
505 => 'HTTP/1.1 505 HTTP Version Not Supported',
506 => 'HTTP/1.1 506 Variant Also Negotiates',
507 => 'HTTP/1.1 507 Insufficient Storage',
508 => 'HTTP/1.1 508 Loop Detected',
510 => 'HTTP/1.1 510 Not Extended',
511 => 'HTTP/1.1 511 Network Authentication Required',
);
/**
* A map of HTTP Response headers which may only send a single value, all others
* are considered to allow multiple
*
* @var object
* @since 3.5.2
* @link https://tools.ietf.org/html/rfc7230
*/
private $singleValueResponseHeaders = array(
'status', // This is not a valid header name, but the representation used by Joomla to identify the HTTP Response Code
'content-length',
'host',
'content-type',
'content-location',
'date',
'location',
'retry-after',
'server',
'mime-version',
'last-modified',
'etag',
'accept-ranges',
'content-range',
'age',
'expires',
'clear-site-data',
'pragma',
'strict-transport-security',
'content-security-policy',
'content-security-policy-report-only',
'x-frame-options',
'x-xss-protection',
'x-content-type-options',
'referrer-policy',
'expect-ct',
'feature-policy', // @deprecated - see: https://scotthelme.co.uk/goodbye-feature-policy-and-hello-permissions-policy/
'permissions-policy',
);
/**
* Class constructor.
*
* @param Input $input An optional argument to provide dependency injection for the application's
* input object. If the argument is a \JInput object that object will become
* the application's input object, otherwise a default input object is created.
* @param Registry $config An optional argument to provide dependency injection for the application's
* config object. If the argument is a Registry object that object will become
* the application's config object, otherwise a default config object is created.
* @param \JApplicationWebClient $client An optional argument to provide dependency injection for the application's
* client object. If the argument is a \JApplicationWebClient object that object will become
* the application's client object, otherwise a default client object is created.
*
* @since 1.7.3
*/
public function __construct(Input $input = null, Registry $config = null, \JApplicationWebClient $client = null)
{
// If an input object is given use it.
if ($input instanceof Input)
{
$this->input = $input;
}
// Create the input based on the application logic.
else
{
$this->input = new Input;
}
// If a config object is given use it.
if ($config instanceof Registry)
{
$this->config = $config;
}
// Instantiate a new configuration object.
else
{
$this->config = new Registry;
}
// If a client object is given use it.
if ($client instanceof \JApplicationWebClient)
{
$this->client = $client;
}
// Instantiate a new web client object.
else
{
$this->client = new \JApplicationWebClient;
}
// Load the configuration object.
$this->loadConfiguration($this->fetchConfigurationData());
// Set the execution datetime and timestamp;
$this->set('execution.datetime', gmdate('Y-m-d H:i:s'));
$this->set('execution.timestamp', time());
// Setup the response object.
$this->response = new \stdClass;
$this->response->cachable = false;
$this->response->headers = array();
$this->response->body = array();
// Set the system URIs.
$this->loadSystemUris();
}
/**
* Returns a reference to the global WebApplication object, only creating it if it doesn't already exist.
*
* This method must be invoked as: $web = WebApplication::getInstance();
*
* @param string $name The name (optional) of the JApplicationWeb class to instantiate.
*
* @return WebApplication
*
* @since 1.7.3
*/
public static function getInstance($name = null)
{
// Only create the object if it doesn't exist.
if (empty(self::$instance))
{
if (class_exists($name) && (is_subclass_of($name, '\\Joomla\\CMS\\Application\\WebApplication')))
{
self::$instance = new $name;
}
else
{
self::$instance = new WebApplication;
}
}
return self::$instance;
}
/**
* Initialise the application.
*
* @param mixed $session An optional argument to provide dependency injection for the application's
* session object. If the argument is a \JSession object that object will become
* the application's session object, if it is false then there will be no session
* object, and if it is null then the default session object will be created based
* on the application's loadSession() method.
* @param mixed $document An optional argument to provide dependency injection for the application's
* document object. If the argument is a \JDocument object that object will become
* the application's document object, if it is false then there will be no document
* object, and if it is null then the default document object will be created based
* on the application's loadDocument() method.
* @param mixed $language An optional argument to provide dependency injection for the application's
* language object. If the argument is a \JLanguage object that object will become
* the application's language object, if it is false then there will be no language
* object, and if it is null then the default language object will be created based
* on the application's loadLanguage() method.
* @param mixed $dispatcher An optional argument to provide dependency injection for the application's
* event dispatcher. If the argument is a \JEventDispatcher object that object will become
* the application's event dispatcher, if it is null then the default event dispatcher
* will be created based on the application's loadDispatcher() method.
*
* @return WebApplication Instance of $this to allow chaining.
*
* @deprecated 4.0
* @see WebApplication::loadSession()
* @see WebApplication::loadDocument()
* @see WebApplication::loadLanguage()
* @see WebApplication::loadDispatcher()
* @since 1.7.3
*/
public function initialise($session = null, $document = null, $language = null, $dispatcher = null)
{
// Create the session based on the application logic.
if ($session !== false)
{
$this->loadSession($session);
}
// Create the document based on the application logic.
if ($document !== false)
{
$this->loadDocument($document);
}
// Create the language based on the application logic.
if ($language !== false)
{
$this->loadLanguage($language);
}
$this->loadDispatcher($dispatcher);
return $this;
}
/**
* Execute the application.
*
* @return void
*
* @since 1.7.3
*/
public function execute()
{
// Trigger the onBeforeExecute event.
$this->triggerEvent('onBeforeExecute');
// Perform application routines.
$this->doExecute();
// Trigger the onAfterExecute event.
$this->triggerEvent('onAfterExecute');
// If we have an application document object, render it.
if ($this->document instanceof \JDocument)
{
// Trigger the onBeforeRender event.
$this->triggerEvent('onBeforeRender');
// Render the application output.
$this->render();
// Trigger the onAfterRender event.
$this->triggerEvent('onAfterRender');
}
// If gzip compression is enabled in configuration and the server is compliant, compress the output.
if ($this->get('gzip') && !ini_get('zlib.output_compression') && (ini_get('output_handler') != 'ob_gzhandler'))
{
$this->compress();
}
// Trigger the onBeforeRespond event.
$this->triggerEvent('onBeforeRespond');
// Send the application response.
$this->respond();
// Trigger the onAfterRespond event.
$this->triggerEvent('onAfterRespond');
}
/**
* Rendering is the process of pushing the document buffers into the template
* placeholders, retrieving data from the document and pushing it into
* the application response buffer.
*
* @return void
*
* @since 1.7.3
*/
protected function render()
{
// Setup the document options.
$options = array(
'template' => $this->get('theme'),
'file' => $this->get('themeFile', 'index.php'),
'params' => $this->get('themeParams'),
);
if ($this->get('themes.base'))
{
$options['directory'] = $this->get('themes.base');
}
// Fall back to constants.
else
{
$options['directory'] = defined('JPATH_THEMES') ? JPATH_THEMES : (defined('JPATH_BASE') ? JPATH_BASE : __DIR__) . '/themes';
}
// Parse the document.
$this->document->parse($options);
// Render the document.
$data = $this->document->render($this->get('cache_enabled'), $options);
// Set the application output data.
$this->setBody($data);
}
/**
* Checks the accept encoding of the browser and compresses the data before
* sending it to the client if possible.
*
* @return void
*
* @since 1.7.3
*/
protected function compress()
{
// Supported compression encodings.
$supported = array(
'x-gzip' => 'gz',
'gzip' => 'gz',
'deflate' => 'deflate',
);
// Get the supported encoding.
$encodings = array_intersect($this->client->encodings, array_keys($supported));
// If no supported encoding is detected do nothing and return.
if (empty($encodings))
{
return;
}
// Verify that headers have not yet been sent, and that our connection is still alive.
if ($this->checkHeadersSent() || !$this->checkConnectionAlive())
{
return;
}
// Iterate through the encodings and attempt to compress the data using any found supported encodings.
foreach ($encodings as $encoding)
{
if (($supported[$encoding] == 'gz') || ($supported[$encoding] == 'deflate'))
{
// Verify that the server supports gzip compression before we attempt to gzip encode the data.
if (!extension_loaded('zlib') || ini_get('zlib.output_compression'))
{
continue;
}
// Attempt to gzip encode the data with an optimal level 4.
$data = $this->getBody();
$gzdata = gzencode($data, 4, ($supported[$encoding] == 'gz') ? FORCE_GZIP : FORCE_DEFLATE);
// If there was a problem encoding the data just try the next encoding scheme.
if ($gzdata === false)
{
continue;
}
// Set the encoding headers.
$this->setHeader('Content-Encoding', $encoding);
$this->setHeader('Vary', 'Accept-Encoding');
// Header will be removed at 4.0
if ($this->get('MetaVersion'))
{
$this->setHeader('X-Content-Encoded-By', 'Joomla');
}
// Replace the output with the encoded data.
$this->setBody($gzdata);
// Compression complete, let's break out of the loop.
break;
}
}
}
/**
* Method to send the application response to the client. All headers will be sent prior to the main
* application output data.
*
* @return void
*
* @since 1.7.3
*/
protected function respond()
{
// Send the content-type header.
$this->setHeader('Content-Type', $this->mimeType . '; charset=' . $this->charSet);
// If the response is set to uncachable, we need to set some appropriate headers so browsers don't cache the response.
if (!$this->response->cachable)
{
// Expires in the past.
$this->setHeader('Expires', 'Wed, 17 Aug 2005 00:00:00 GMT', true);
// Always modified.
$this->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT', true);
$this->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', false);
// HTTP 1.0
$this->setHeader('Pragma', 'no-cache');
}
else
{
// Expires.
$this->setHeader('Expires', gmdate('D, d M Y H:i:s', time() + 900) . ' GMT');
// Last modified.
if ($this->modifiedDate instanceof \JDate)
{
$this->setHeader('Last-Modified', $this->modifiedDate->format('D, d M Y H:i:s', false, false) . ' GMT');
}
}
$this->sendHeaders();
echo $this->getBody();
}
/**
* Redirect to another URL.
*
* If the headers have not been sent the redirect will be accomplished using a "301 Moved Permanently"
* or "303 See Other" code in the header pointing to the new location. If the headers have already been
* sent this will be accomplished using a JavaScript statement.
*
* @param string $url The URL to redirect to. Can only be http/https URL.
* @param integer $status The HTTP 1.1 status code to be provided. 303 is assumed by default.
*
* @return void
*
* @since 1.7.3
*/
public function redirect($url, $status = 303)
{
// Check for relative internal links.
if (preg_match('#^index\.php#', $url))
{
// We changed this from "$this->get('uri.base.full') . $url" due to the inability to run the system tests with the original code
$url = \JUri::base() . $url;
}
// Perform a basic sanity check to make sure we don't have any CRLF garbage.
$url = preg_split("/[\r\n]/", $url);
$url = $url[0];
/*
* Here we need to check and see if the URL is relative or absolute. Essentially, do we need to
* prepend the URL with our base URL for a proper redirect. The rudimentary way we are looking
* at this is to simply check whether or not the URL string has a valid scheme or not.
*/
if (!preg_match('#^[a-z]+\://#i', $url))
{
// Get a \JUri instance for the requested URI.
$uri = \JUri::getInstance($this->get('uri.request'));
// Get a base URL to prepend from the requested URI.
$prefix = $uri->toString(array('scheme', 'user', 'pass', 'host', 'port'));
// We just need the prefix since we have a path relative to the root.
if ($url[0] == '/')
{
$url = $prefix . $url;
}
// It's relative to where we are now, so lets add that.
else
{
$parts = explode('/', $uri->toString(array('path')));
array_pop($parts);
$path = implode('/', $parts) . '/';
$url = $prefix . $path . $url;
}
}
// If the headers have already been sent we need to send the redirect statement via JavaScript.
if ($this->checkHeadersSent())
{
echo "<script>document.location.href=" . json_encode(str_replace("'", ''', $url)) . ";</script>\n";
}
else
{
// We have to use a JavaScript redirect here because MSIE doesn't play nice with utf-8 URLs.
if (($this->client->engine == \JApplicationWebClient::TRIDENT) && !StringHelper::is_ascii($url))
{
$html = '<html><head>';
$html .= '<meta http-equiv="content-type" content="text/html; charset=' . $this->charSet . '" />';
$html .= '<script>document.location.href=' . json_encode(str_replace("'", ''', $url)) . ';</script>';
$html .= '</head><body></body></html>';
echo $html;
}
else
{
// Check if we have a boolean for the status variable for compatibility with old $move parameter
// @deprecated 4.0
if (is_bool($status))
{
$status = $status ? 301 : 303;
}
// Now check if we have an integer status code that maps to a valid redirect. If we don't then set a 303
// @deprecated 4.0 From 4.0 if no valid status code is given an InvalidArgumentException will be thrown
if (!is_int($status) || !$this->isRedirectState($status))
{
$status = 303;
}
// All other cases use the more efficient HTTP header for redirection.
$this->setHeader('Status', $status, true);
$this->setHeader('Location', $url, true);
}
}
// Trigger the onBeforeRespond event.
$this->triggerEvent('onBeforeRespond');
// Set appropriate headers
$this->respond();
// Trigger the onAfterRespond event.
$this->triggerEvent('onAfterRespond');
// Close the application after the redirect.
$this->close();
}
/**
* Checks if a state is a redirect state
*
* @param integer $state The HTTP 1.1 status code.
*
* @return boolean
*
* @since 3.8.0
*/
protected function isRedirectState($state)
{
$state = (int) $state;
return ($state > 299 && $state < 400);
}
/**
* Load an object or array into the application configuration object.
*
* @param mixed $data Either an array or object to be loaded into the configuration object.
*
* @return WebApplication Instance of $this to allow chaining.
*
* @since 1.7.3
*/
public function loadConfiguration($data)
{
// Load the data into the configuration object.
if (is_array($data))
{
$this->config->loadArray($data);
}
elseif (is_object($data))
{
$this->config->loadObject($data);
}
return $this;
}
/**
* Set/get cachable state for the response. If $allow is set, sets the cachable state of the
* response. Always returns the current state.
*
* @param boolean $allow True to allow browser caching.
*
* @return boolean
*
* @since 1.7.3
*/
public function allowCache($allow = null)
{
if ($allow !== null)
{
$this->response->cachable = (bool) $allow;
}
return $this->response->cachable;
}
/**
* Method to set a response header. If the replace flag is set then all headers
* with the given name will be replaced by the new one. The headers are stored
* in an internal array to be sent when the site is sent to the browser.
*
* @param string $name The name of the header to set.
* @param string $value The value of the header to set.
* @param boolean $replace True to replace any headers with the same name.
*
* @return WebApplication Instance of $this to allow chaining.
*
* @since 1.7.3
*/
public function setHeader($name, $value, $replace = false)
{
// Sanitize the input values.
$name = (string) $name;
$value = (string) $value;
// Create an array of duplicate header names
$keys = false;
if ($this->response->headers)
{
$names = array();
foreach ($this->response->headers as $key => $header)
{
$names[$key] = $header['name'];
}
// Find existing headers by name
$keys = array_keys($names, $name);
}
// Remove if $replace is true and there are duplicate names
if ($replace && $keys)
{
$this->response->headers = array_diff_key($this->response->headers, array_flip($keys));
}
/*
* If no keys found, safe to insert (!$keys)
* If ($keys && $replace) it's a replacement and previous have been deleted
* If ($keys && !in_array...) it's a multiple value header
*/
$single = in_array(strtolower($name), $this->singleValueResponseHeaders);
if ($value && (!$keys || ($keys && ($replace || !$single))))
{
// Add the header to the internal array.
$this->response->headers[] = array('name' => $name, 'value' => $value);
}
return $this;
}
/**
* Method to get the array of response headers to be sent when the response is sent
* to the client.
*
* @return array *
*
* @since 1.7.3
*/
public function getHeaders()
{
return $this->response->headers;
}
/**
* Method to clear any set response headers.
*
* @return WebApplication Instance of $this to allow chaining.
*
* @since 1.7.3
*/
public function clearHeaders()
{
$this->response->headers = array();
return $this;
}
/**
* Send the response headers.
*
* @return WebApplication Instance of $this to allow chaining.
*
* @since 1.7.3
*/
public function sendHeaders()
{
if (!$this->checkHeadersSent())
{
// Creating an array of headers, making arrays of headers with multiple values
$val = array();
foreach ($this->response->headers as $header)
{
if ('status' == strtolower($header['name']))
{
// 'status' headers indicate an HTTP status, and need to be handled slightly differently
$status = $this->getHttpStatusValue($header['value']);
$this->header($status, true, (int) $header['value']);
}
else
{
$val[$header['name']] = !isset($val[$header['name']]) ? $header['value'] : implode(', ', array($val[$header['name']], $header['value']));
$this->header($header['name'] . ': ' . $val[$header['name']], true);
}
}
}
return $this;
}
/**
* Check if a given value can be successfully mapped to a valid http status value
*
* @param string $value The given status as int or string
*
* @return string
*
* @since 3.8.0
*/
protected function getHttpStatusValue($value)
{
$code = (int) $value;
if (array_key_exists($code, $this->responseMap))
{
return $this->responseMap[$code];
}
return 'HTTP/1.1 ' . $code;
}
/**
* Set body content. If body content already defined, this will replace it.
*
* @param string $content The content to set as the response body.
*
* @return WebApplication Instance of $this to allow chaining.
*
* @since 1.7.3
*/
public function setBody($content)
{
$this->response->body = array((string) $content);
return $this;
}
/**
* Prepend content to the body content
*
* @param string $content The content to prepend to the response body.
*
* @return WebApplication Instance of $this to allow chaining.
*
* @since 1.7.3
*/
public function prependBody($content)
{
array_unshift($this->response->body, (string) $content);
return $this;
}
/**
* Append content to the body content
*
* @param string $content The content to append to the response body.
*
* @return WebApplication Instance of $this to allow chaining.
*
* @since 1.7.3
*/
public function appendBody($content)
{
$this->response->body[] = (string) $content;
return $this;
}
/**
* Return the body content
*
* @param boolean $asArray True to return the body as an array of strings.
*
* @return mixed The response body either as an array or concatenated string.
*
* @since 1.7.3
*/
public function getBody($asArray = false)
{
return $asArray ? $this->response->body : implode((array) $this->response->body);
}
/**
* Method to get the application document object.
*
* @return \JDocument The document object
*
* @since 1.7.3
*/
public function getDocument()
{
return $this->document;
}
/**
* Method to get the application language object.
*
* @return \JLanguage The language object
*
* @since 1.7.3
*/
public function getLanguage()
{
return $this->language;
}
/**
* Method to get the application session object.
*
* @return \JSession The session object
*
* @since 1.7.3
*/
public function getSession()
{
return $this->session;
}
/**
* Method to check the current client connection status to ensure that it is alive. We are
* wrapping this to isolate the connection_status() function from our code base for testing reasons.
*
* @return boolean True if the connection is valid and normal.
*
* @see connection_status()
* @since 1.7.3
*/
protected function checkConnectionAlive()
{
return connection_status() === CONNECTION_NORMAL;
}
/**
* Method to check to see if headers have already been sent. We are wrapping this to isolate the
* headers_sent() function from our code base for testing reasons.
*
* @return boolean True if the headers have already been sent.
*
* @see headers_sent()
* @since 1.7.3
*/
protected function checkHeadersSent()
{
return headers_sent();
}
/**
* Method to detect the requested URI from server environment variables.
*
* @return string The requested URI
*
* @since 1.7.3
*/
protected function detectRequestUri()
{
// First we need to detect the URI scheme.
if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off'))
{
$scheme = 'https://';
}
else
{
$scheme = 'http://';
}
/*
* There are some differences in the way that Apache and IIS populate server environment variables. To
* properly detect the requested URI we need to adjust our algorithm based on whether or not we are getting
* information from Apache or IIS.
*/
// Define variable to return
$uri = '';
// If PHP_SELF and REQUEST_URI are both populated then we will assume "Apache Mode".
if (!empty($_SERVER['PHP_SELF']) && !empty($_SERVER['REQUEST_URI']))
{
// The URI is built from the HTTP_HOST and REQUEST_URI environment variables in an Apache environment.
$uri = $scheme . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}
// If not in "Apache Mode" we will assume that we are in an IIS environment and proceed.
elseif (isset($_SERVER['HTTP_HOST']))
{
// IIS uses the SCRIPT_NAME variable instead of a REQUEST_URI variable... thanks, MS
$uri = $scheme . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'];
// If the QUERY_STRING variable exists append it to the URI string.
if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']))
{
$uri .= '?' . $_SERVER['QUERY_STRING'];
}
}
return trim($uri);
}
/**
* Method to load a PHP configuration class file based on convention and return the instantiated data object. You
* will extend this method in child classes to provide configuration data from whatever data source is relevant
* for your specific application.
*
* @param string $file The path and filename of the configuration file. If not provided, configuration.php
* in JPATH_CONFIGURATION will be used.
* @param string $class The class name to instantiate.
*
* @return mixed Either an array or object to be loaded into the configuration object.
*
* @since 1.7.3
* @throws \RuntimeException
*/
protected function fetchConfigurationData($file = '', $class = '\JConfig')
{
// Instantiate variables.
$config = array();
if (empty($file))
{
$file = JPATH_CONFIGURATION . '/configuration.php';
// Applications can choose not to have any configuration data
// by not implementing this method and not having a config file.
if (!file_exists($file))
{
$file = '';
}
}
if (!empty($file))
{
\JLoader::register($class, $file);
if (class_exists($class))
{
$config = new $class;
}
else
{
throw new \RuntimeException('Configuration class does not exist.');
}
}
return $config;
}
/**
* Flush the media version to refresh versionable assets
*
* @return void
*
* @since 3.2
*/
public function flushAssets()
{
$version = new \JVersion;
$version->refreshMediaVersion();
}
/**
* Method to send a header to the client. We are wrapping this to isolate the header() function
* from our code base for testing reasons.
*
* @param string $string The header string.
* @param boolean $replace The optional replace parameter indicates whether the header should
* replace a previous similar header, or add a second header of the same type.
* @param integer $code Forces the HTTP response code to the specified value. Note that
* this parameter only has an effect if the string is not empty.
*
* @return void
*
* @see header()
* @since 1.7.3
*/
protected function header($string, $replace = true, $code = null)
{
$string = str_replace(chr(0), '', $string);
if ($code === null)
{
$code = 0;
}
header($string, $replace, $code);
}
/**
* Determine if we are using a secure (SSL) connection.
*
* @return boolean True if using SSL, false if not.
*
* @since 3.0.1
*/
public function isSSLConnection()
{
return (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) || getenv('SSL_PROTOCOL_VERSION');
}
/**
* Allows the application to load a custom or default document.
*
* The logic and options for creating this object are adequately generic for default cases
* but for many applications it will make sense to override this method and create a document,
* if required, based on more specific needs.
*
* @param \JDocument $document An optional document object. If omitted, the factory document is created.
*
* @return WebApplication This method is chainable.
*
* @since 1.7.3
*/
public function loadDocument(\JDocument $document = null)
{
$this->document = ($document === null) ? \JFactory::getDocument() : $document;
return $this;
}
/**
* Allows the application to load a custom or default language.
*
* The logic and options for creating this object are adequately generic for default cases
* but for many applications it will make sense to override this method and create a language,
* if required, based on more specific needs.
*
* @param \JLanguage $language An optional language object. If omitted, the factory language is created.
*
* @return WebApplication This method is chainable.
*
* @since 1.7.3
*/
public function loadLanguage(\JLanguage $language = null)
{
$this->language = ($language === null) ? \JFactory::getLanguage() : $language;
return $this;
}
/**
* Allows the application to load a custom or default session.
*
* The logic and options for creating this object are adequately generic for default cases
* but for many applications it will make sense to override this method and create a session,
* if required, based on more specific needs.
*
* @param \JSession $session An optional session object. If omitted, the session is created.
*
* @return WebApplication This method is chainable.
*
* @since 1.7.3
*/
public function loadSession(\JSession $session = null)
{
if ($session !== null)
{
$this->session = $session;
return $this;
}
// Generate a session name.
$name = md5($this->get('secret') . $this->get('session_name', get_class($this)));
// Calculate the session lifetime.
$lifetime = (($this->get('sess_lifetime')) ? $this->get('sess_lifetime') * 60 : 900);
// Get the session handler from the configuration.
$handler = $this->get('sess_handler', 'none');
// Initialize the options for \JSession.
$options = array(
'name' => $name,
'expire' => $lifetime,
'force_ssl' => $this->get('force_ssl'),
);
$this->registerEvent('onAfterSessionStart', array($this, 'afterSessionStart'));
// Instantiate the session object.
$session = \JSession::getInstance($handler, $options);
$session->initialise($this->input, $this->dispatcher);
if ($session->getState() == 'expired')
{
$session->restart();
}
else
{
$session->start();
}
// Set the session object.
$this->session = $session;
return $this;
}
/**
* After the session has been started we need to populate it with some default values.
*
* @return void
*
* @since 3.0.1
*/
public function afterSessionStart()
{
$session = \JFactory::getSession();
if ($session->isNew())
{
$session->set('registry', new Registry);
$session->set('user', new \JUser);
}
}
/**
* Method to load the system URI strings for the application.
*
* @param string $requestUri An optional request URI to use instead of detecting one from the
* server environment variables.
*
* @return void
*
* @since 1.7.3
*/
protected function loadSystemUris($requestUri = null)
{
// Set the request URI.
if (!empty($requestUri))
{
$this->set('uri.request', $requestUri);
}
else
{
$this->set('uri.request', $this->detectRequestUri());
}
// Check to see if an explicit base URI has been set.
$siteUri = trim($this->get('site_uri', ''));
if ($siteUri != '')
{
$uri = \JUri::getInstance($siteUri);
$path = $uri->toString(array('path'));
}
// No explicit base URI was set so we need to detect it.
else
{
// Start with the requested URI.
$uri = \JUri::getInstance($this->get('uri.request'));
// If we are working from a CGI SAPI with the 'cgi.fix_pathinfo' directive disabled we use PHP_SELF.
if (strpos(php_sapi_name(), 'cgi') !== false && !ini_get('cgi.fix_pathinfo') && !empty($_SERVER['REQUEST_URI']))
{
// We aren't expecting PATH_INFO within PHP_SELF so this should work.
$path = dirname($_SERVER['PHP_SELF']);
}
// Pretty much everything else should be handled with SCRIPT_NAME.
else
{
$path = dirname($_SERVER['SCRIPT_NAME']);
}
}
$host = $uri->toString(array('scheme', 'user', 'pass', 'host', 'port'));
// Check if the path includes "index.php".
if (strpos($path, 'index.php') !== false)
{
// Remove the index.php portion of the path.
$path = substr_replace($path, '', strpos($path, 'index.php'), 9);
}
$path = rtrim($path, '/\\');
// Set the base URI both as just a path and as the full URI.
$this->set('uri.base.full', $host . $path . '/');
$this->set('uri.base.host', $host);
$this->set('uri.base.path', $path . '/');
// Set the extended (non-base) part of the request URI as the route.
if (stripos($this->get('uri.request'), $this->get('uri.base.full')) === 0)
{
$this->set('uri.route', substr_replace($this->get('uri.request'), '', 0, strlen($this->get('uri.base.full'))));
}
// Get an explicitly set media URI is present.
$mediaURI = trim($this->get('media_uri', ''));
if ($mediaURI)
{
if (strpos($mediaURI, '://') !== false)
{
$this->set('uri.media.full', $mediaURI);
$this->set('uri.media.path', $mediaURI);
}
else
{
// Normalise slashes.
$mediaURI = trim($mediaURI, '/\\');
$mediaURI = !empty($mediaURI) ? '/' . $mediaURI . '/' : '/';
$this->set('uri.media.full', $this->get('uri.base.host') . $mediaURI);
$this->set('uri.media.path', $mediaURI);
}
}
// No explicit media URI was set, build it dynamically from the base uri.
else
{
$this->set('uri.media.full', $this->get('uri.base.full') . 'media/');
$this->set('uri.media.path', $this->get('uri.base.path') . 'media/');
}
}
}
ApplicationSmartSlider3.php 0000644 00000002532 15235664602 0011770 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application;
use Exception;
use Nextend\Framework\Application\AbstractApplication;
use Nextend\Framework\Asset\Js\Js;
use Nextend\Framework\Platform\Platform;
use Nextend\SmartSlider3\Application\Admin\ApplicationTypeAdmin;
use Nextend\SmartSlider3\Application\Frontend\ApplicationTypeFrontend;
class ApplicationSmartSlider3 extends AbstractApplication {
protected $key = 'ss3';
/** @var ApplicationTypeAdmin */
protected $applicationTypeAdmin;
/** @var ApplicationTypeFrontend */
protected $applicationTypeFrontend;
/**
* @throws Exception
*/
protected function init() {
parent::init();
$this->applicationTypeAdmin = new ApplicationTypeAdmin($this);
$this->applicationTypeFrontend = new ApplicationTypeFrontend($this);
}
/**
* @return ApplicationTypeAdmin
*/
public function getApplicationTypeAdmin() {
return $this->applicationTypeAdmin;
}
/**
* @return ApplicationTypeFrontend
*/
public function getApplicationTypeFrontend() {
return $this->applicationTypeFrontend;
}
public function enqueueAssets() {
if (Platform::isAdmin()) {
Js::addGlobalInline('window.N2SSPRO=' . N2SSPRO . ';');
}
}
} Model/ModelGenerator.php 0000644 00000047671 15235664602 0011254 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Model;
use Exception;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Database\Database;
use Nextend\Framework\Form\Container\ContainerTable;
use Nextend\Framework\Form\ContainerInterface;
use Nextend\Framework\Form\Element\Button\ButtonRecordViewer;
use Nextend\Framework\Form\Element\Text\Number;
use Nextend\Framework\Misc\Base64;
use Nextend\Framework\Model\AbstractModelTable;
use Nextend\SmartSlider3\Generator\AbstractGeneratorGroup;
use Nextend\SmartSlider3\Generator\GeneratorFactory;
use Nextend\SmartSlider3\SlideBuilder\BuilderComponentCol;
use Nextend\SmartSlider3\SlideBuilder\BuilderComponentLayer;
use Nextend\SmartSlider3\SlideBuilder\BuilderComponentRow;
use Nextend\SmartSlider3\SlideBuilder\BuilderComponentSlide;
class ModelGenerator extends AbstractModelTable {
protected function createConnectorTable() {
return Database::getTable('nextend2_smartslider3_generators');
}
private static function getLayout($type) {
$slideBuilder = new BuilderComponentSlide();
switch ($type) {
case 'image':
$slideBuilder->set(array(
'title' => "{title}",
'thumbnail' => "{thumbnail}",
'backgroundImage' => "{image}",
'background-type' => 'image'
));
break;
case 'image_extended':
$slideBuilder->set(array(
'title' => "{title}",
'thumbnail' => "{thumbnail}",
'backgroundImage' => "{image}",
'background-type' => 'image'
));
$slideBuilder->content->set(array(
'verticalalign' => 'flex-end',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px'
));
$row = new BuilderComponentRow($slideBuilder->content);
$row->set(array(
'bgcolor' => '00000080',
));
$col = new BuilderComponentCol($row, '1');
$col->set(array(
'desktopportraitinneralign' => "left"
));
$heading = new BuilderComponentLayer($col, 'heading');
$heading->set(array(
'desktopportraitselfalign' => 'inherit'
));
$heading->item->set(array(
'heading' => '{title/1}',
));
break;
case 'article':
$slideBuilder->set(array(
'title' => "{title}",
'description' => '{description}',
'href' => '{url}',
'thumbnail' => "{thumbnail}",
'backgroundImage' => "{image}",
'background-type' => 'image'
));
$slideBuilder->content->set(array(
'verticalalign' => 'flex-end',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
));
$row = new BuilderComponentRow($slideBuilder->content);
$row->set(array(
'bgcolor' => '00000080',
));
$col = new BuilderComponentCol($row, '1');
$col->set(array(
'desktopportraitinneralign' => "left",
));
$heading = new BuilderComponentLayer($col, 'heading');
$heading->set(array(
'desktopportraitselfalign' => 'inherit'
));
$heading->item->set(array(
'heading' => '{title}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"36||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}')
));
break;
case 'product':
$slideBuilder->set(array(
'title' => "{title}",
'description' => '{description}',
'href' => '{url}',
'thumbnail' => "{thumbnail}",
'backgroundImage' => "{image}",
'background-type' => 'image'
));
$slideBuilder->content->set(array(
'verticalalign' => 'flex-end',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
));
$row = new BuilderComponentRow($slideBuilder->content);
$row->set(array(
'bgcolor' => '00000080',
));
$col = new BuilderComponentCol($row, '1/2');
$col->set(array(
'desktopportraitinneralign' => "left",
));
$heading = new BuilderComponentLayer($col, 'heading');
$heading->set(array(
'desktopportraitselfalign' => 'inherit'
));
$heading->item->set(array(
'heading' => '{title}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"36||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}'),
));
$col2 = new BuilderComponentCol($row, '1/2');
$col2->set(array(
'desktopportraitinneralign' => "right",
));
$text = new BuilderComponentLayer($col2, 'text');
$text->set(array(
'desktopportraitselfalign' => 'inherit'
));
$text->item->set(array(
'content' => '{price}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"36||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}'),
));
break;
case 'event':
$slideBuilder->set(array(
'title' => "{title}",
'description' => '{description}',
'href' => '{url}',
'thumbnail' => "{thumbnail}",
'backgroundImage' => "{image}",
'background-type' => 'image'
));
$slideBuilder->content->set(array(
'verticalalign' => 'flex-end',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
));
$row = new BuilderComponentRow($slideBuilder->content);
$row->set(array(
'bgcolor' => '00000080',
));
$col = new BuilderComponentCol($row, '1/2');
$col->set(array(
'desktopportraitinneralign' => "left",
));
$heading = new BuilderComponentLayer($col, 'heading');
$heading->set(array(
'desktopportraitselfalign' => 'inherit'
));
$heading->item->set(array(
'heading' => '{title}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"36||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}'),
));
$col2 = new BuilderComponentCol($row, '1/2');
$col2->set(array(
'desktopportraitinneralign' => "right",
));
$heading = new BuilderComponentLayer($col2, 'heading');
$heading->set(array(
'desktopportraitselfalign' => 'inherit'
));
$heading->item->set(array(
'heading' => '{start_date}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"36||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}'),
));
break;
case 'youtube':
$slideBuilder->set(array(
'title' => "{title}",
'description' => '{description}',
'thumbnail' => "{thumbnail}",
'backgroundColor' => "ffffff00",
'background-type' => 'color',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
));
$youtube = new BuilderComponentLayer($slideBuilder->content, 'youtube');
$youtube->item->set(array(
"youtubeurl" => "{video_url}",
));
break;
case 'vimeo':
$slideBuilder->set(array(
'title' => "{title}",
'description' => '{description}',
'thumbnail' => "{image200x150/1}",
'backgroundColor' => "ffffff00",
'background-type' => 'color',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
));
$vimeo = new BuilderComponentLayer($slideBuilder->content, 'vimeo');
$vimeo->item->set(array(
"vimeourl" => "{url}",
'image' => '{image}'
));
break;
case 'video_mp4':
$slideBuilder->set(array(
'title' => "{name}",
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
));
$video = new BuilderComponentLayer($slideBuilder->content, 'video');
$video->item->set(array(
"video_mp4" => "{video}",
));
break;
case 'social_post':
$slideBuilder->set(array(
'title' => "{title}",
'description' => '{description}',
'href' => '{url}',
'thumbnail' => "{author_image}",
'backgroundColor' => "ffffff00",
'background-type' => 'color',
));
$slideBuilder->content->set(array(
'verticalalign' => 'center',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
'desktopportraitmargin' => '0|*|0|*|0|*|0|*|px'
));
$row = new BuilderComponentRow($slideBuilder->content);
$row->set(array(
'bgcolor' => '00000080',
'desktopportraitpadding' => '10|*|10|*|10|*|10|*|px',
'desktopportraitmargin' => '0|*|0|*|0|*|0|*|px'
));
$col = new BuilderComponentCol($row, '1');
$col->set(array(
'desktopportraitinneralign' => "left",
'desktopportraitmargin' => '0|*|0|*|0|*|0|*|px',
'desktopportraitpadding' => '10|*|10|*|10|*|10|*|px'
));
$heading = new BuilderComponentLayer($col, 'heading');
$heading->set(array(
'desktopportraitmargin' => '0|*|0|*|0|*|0|*|px',
'desktopportraitselfalign' => 'inherit'
));
$heading->item->set(array(
'heading' => '{message}',
));
$image = new BuilderComponentLayer($col, 'image');
$image->set(array(
'desktopportraitmargin' => '0|*|0|*|0|*|0|*|px',
'desktopportraitselfalign' => 'inherit'
));
$image->item->set(array(
'image' => '{author_image}',
));
$button = new BuilderComponentLayer($col, 'button');
$button->set(array(
'desktopportraitmargin' => '0|*|0|*|0|*|0|*|px',
'desktopportraitselfalign' => 'inherit'
));
$button->item->set(array(
'content' => '{url_label}',
));
break;
case 'text':
$slideBuilder->set(array(
'title' => "{title}"
));
$slideBuilder->content->set(array(
'verticalalign' => 'flex-end',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
));
$row = new BuilderComponentRow($slideBuilder->content);
$row->set(array(
'bgcolor' => '00000080',
));
$col = new BuilderComponentCol($row, '1');
$col->set(array(
'desktopportraitinneralign' => "left",
));
$heading = new BuilderComponentLayer($col, 'heading');
$heading->set(array(
'desktopportraitselfalign' => 'inherit'
));
$heading->item->set(array(
'heading' => '{title}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"36||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}')
));
break;
case 'text_generator':
$slideBuilder->set(array(
'title' => "{variable1}"
));
$slideBuilder->content->set(array(
'verticalalign' => 'flex-end',
'desktopportraitpadding' => '0|*|0|*|0|*|0|*|px',
));
$row = new BuilderComponentRow($slideBuilder->content);
$row->set(array(
'bgcolor' => '00000080',
));
$col = new BuilderComponentCol($row, '1');
$col->set(array(
'desktopportraitinneralign' => "left",
));
$heading = new BuilderComponentLayer($col, 'heading');
$heading->set(array(
'desktopportraitselfalign' => 'inherit'
));
$heading->item->set(array(
'heading' => '{variable1}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"36||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}')
));
break;
default:
return $slideBuilder->set(array(
'title' => "title",
'description' => '',
'backgroundColor' => "ffffff00",
'background-type' => 'color',
));
}
return $slideBuilder->getData();
}
public function createGenerator($sliderId, $params) {
$data = new Data($params);
unset($params['type']);
unset($params['group']);
unset($params['record-slides']);
try {
$generatorId = $this->_create($data->get('type'), $data->get('group'), json_encode($params));
$source = $this->getGeneratorGroup($data->get('group'))
->getSource($data->get('type'));
$slideData = self::getLayout($source->getLayout());
$slideData['record-slides'] = intval($data->get('record-slides', 5));
$slidesModel = new ModelSlides($this);
$slideId = $slidesModel->createSlideWithGenerator($sliderId, $generatorId, $slideData);
return array(
'slideId' => $slideId,
'generatorId' => $generatorId
);
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
/**
* @param ContainerInterface $container
*/
public function renderFields($container) {
$settings = new ContainerTable($container, 'generator', n2_('Generator settings'));
$generatorRow = $settings->createRow('generator-row');
new Number($generatorRow, 'record-slides', n2_('Slides'), 5, array(
'unit' => n2_x('slides', 'Unit'),
'wide' => 3,
));
new Number($generatorRow, 'cache-expiration', n2_('Cache expiration'), 24, array(
'wide' => 3,
'unit' => n2_('Hours')
));
new Number($generatorRow, 'record-start', n2_('Start index'), 1, array(
'wide' => 3
));
new Number($generatorRow, 'record-group', n2_('Group result'), 1, array(
'wide' => 3
));
new ButtonRecordViewer($generatorRow, 'record-viewer');
}
/**
* @param $type
*
* @return AbstractGeneratorGroup
*/
public function getGeneratorGroup($type) {
return GeneratorFactory::getGenerator($type);
}
public function get($id) {
return Database::queryRow("SELECT * FROM " . $this->getTableName() . " WHERE id = :id", array(
":id" => $id
));
}
public function import($generator) {
$this->table->insert(array(
'type' => $generator['type'],
'group' => $generator['group'],
'params' => $generator['params']
));
return $this->table->insertId();
}
private function _create($type, $group, $params) {
$this->table->insert(array(
'type' => $type,
'group' => $group,
'params' => $params
));
return $this->table->insertId();
}
public function save($generatorId, $params) {
$this->table->update(array(
'params' => json_encode($params)
), array('id' => $generatorId));
return $generatorId;
}
public function delete($id) {
$this->table->deleteByAttributes(array(
"id" => intval($id)
));
}
public function duplicate($id) {
$generatorRow = $this->get($id);
$generatorId = $this->_create($generatorRow['type'], $generatorRow['group'], $generatorRow['params']);
return $generatorId;
}
public function getSliderId($generatorId) {
$slidesModal = new ModelSlides($this);
$slideData = Database::queryRow("SELECT slider FROM " . $slidesModal->getTableName() . " WHERE generator_id = :id", array(
":id" => $generatorId
));
return $slideData['slider'];
}
} Model/ModelLicense.php 0000644 00000006322 15235664602 0010674 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Model;
use Nextend\Framework\Model\StorageSectionManager;
use Nextend\Framework\Notification\Notification;
use Nextend\Framework\Pattern\SingletonTrait;
use Nextend\SmartSlider3\SmartSlider3Info;
/**
* Class ModelLicense
*
* @package Nextend\SmartSlider3\Application\Model
*
*/
class ModelLicense {
use SingletonTrait;
private $key;
public function __construct() {
if (defined('SMART_SLIDER_LICENSE')) {
$this->key = SMART_SLIDER_LICENSE;
} else {
$this->key = StorageSectionManager::getStorage('smartslider')
->get('license', 'key');
}
}
public function hasKey() {
return true;//mhehm
return !empty($this->key);
}
public function maybeActiveLazy() {
$lastActive = StorageSectionManager::getStorage('smartslider')
->get('license', 'isActive');
return $lastActive > 0;
}
public function maybeActive() {
$lastActive = StorageSectionManager::getStorage('smartslider')
->get('license', 'isActive');
if ($lastActive && $lastActive > strtotime("-1 week")) {
return true;
}
return false;
}
public function getKey() {
return '73879A3c9cb691cc8b796c4d63d53802a8b2570e36f34781a044981349bfdf7dd5fece1e1ce6ed34bc3a96e1814582a7ecf9';//mhehm
return $this->key;
}
public function setKey($licenseKey) {
StorageSectionManager::getStorage('smartslider')
->set('license', 'key', $licenseKey);
StorageSectionManager::getStorage('smartslider')
->set('license', 'isActive', time());
if ($licenseKey == '') {
StorageSectionManager::getStorage('smartslider')
->set('license', 'isActive', '0');
}
$this->key = $licenseKey;
}
public function checkKey($license, $action = 'licensecheck') {
$result = SmartSlider3Info::api(array(
'action' => $action,
'license' => $license
));
if ($result === false) {
return 'CONNECTION_ERROR';
}
return $result['status'];
}
public function isActive($cacheAccepted = true) {
if ($cacheAccepted && $this->maybeActive()) {
return 'OK';
}
$status = $this->checkKey($this->key);
if ($this->hasKey() && $status == 'OK') {
StorageSectionManager::getStorage('smartslider')
->set('license', 'isActive', time());
return $status;
}
StorageSectionManager::getStorage('smartslider')
->set('license', 'isActive', '0');
return $status;
}
public function deAuthorize() {
if ($this->hasKey()) {
$this->setKey('');
Notification::notice(n2_('Smart Slider 3 deactivated on this site!'));
return 'OK';
}
return false;
}
} Model/ModelSettings.php 0000644 00000002445 15235664602 0011114 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Model;
use Nextend\Framework\Model\AbstractModel;
use Nextend\Framework\Model\Section;
use Nextend\Framework\Request\Request;
use Nextend\SmartSlider3\Application\Helper\HelperSliderChanged;
use Nextend\SmartSlider3\Settings;
class ModelSettings extends AbstractModel {
public function save() {
$namespace = Request::$REQUEST->getCmd('namespace', 'default');
$settings = Request::$REQUEST->getVar('settings');
if ($namespace && $settings) {
if ($namespace == 'default') $namespace = 'settings';
if ($namespace == 'font' && Request::$REQUEST->getInt('sliderid')) {
$namespace .= Request::$REQUEST->getInt('sliderid');
$helper = new HelperSliderChanged($this);
$helper->setSliderChanged(Request::$REQUEST->getInt('sliderid'), 1);
}
Settings::store($namespace, json_encode($settings));
}
return true;
}
public function saveDefaults($defaults) {
if (!empty($defaults)) {
foreach ($defaults as $referenceKey => $value) {
Section::set('smartslider', 'default', $referenceKey, $value);
}
}
return true;
}
} Model/ModelSliders.php 0000644 00000066611 15235664602 0010726 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Model;
use Exception;
use Nextend\Framework\Cache\AbstractCache;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Database\Database;
use Nextend\Framework\Misc\Str;
use Nextend\Framework\Model\AbstractModelTable;
use Nextend\Framework\Notification\Notification;
use Nextend\Framework\Platform\Platform;
use Nextend\SmartSlider3\Application\Helper\HelperSliderChanged;
use Nextend\SmartSlider3\Slider\Admin\AdminSlider;
use Nextend\SmartSlider3\Slider\Slider;
use Nextend\SmartSlider3\SmartSlider3Info;
class ModelSliders extends AbstractModelTable {
/**
* @var ModelSlidersXRef
*/
private $xref;
private $sliderTitleLength = 200;
protected function createConnectorTable() {
$this->xref = new ModelSlidersXRef($this);
return Database::getTable('nextend2_smartslider3_sliders');
}
public function get($id) {
return Database::queryRow("SELECT * FROM " . $this->getTableName() . " WHERE id = :id", array(
":id" => $id
));
}
public function getByAlias($alias) {
return Database::queryRow("SELECT id FROM " . $this->getTableName() . " WHERE alias = :alias", array(
":alias" => $alias
));
}
public function getWithThumbnail($id) {
$slidesModel = new ModelSlides($this);
return Database::queryRow("SELECT sliders.*,xref.group_id, IF(sliders.thumbnail != '',sliders.thumbnail,(SELECT slides.thumbnail from " . $slidesModel->getTableName() . " AS slides WHERE slides.slider = sliders.id AND slides.published = 1 AND slides.generator_id = 0 AND slides.thumbnail NOT LIKE '' ORDER BY slides.first DESC, slides.ordering ASC LIMIT 1)) AS thumbnail,
IF(sliders.type != 'group',
(SELECT count(*) FROM " . $slidesModel->getTableName() . " AS slides2 WHERE slides2.slider = sliders.id GROUP BY slides2.slider),
(SELECT count(*) FROM " . $this->xref->getTableName() . " AS xref2 WHERE xref2.group_id = sliders.id GROUP BY xref2.group_id)
) AS slides
FROM " . $this->getTableName() . " AS sliders
LEFT JOIN " . $this->xref->getTableName() . " AS xref ON xref.slider_id = sliders.id
WHERE sliders.id = :id", array(
":id" => $id
));
}
public function invalidateCache() {
Database::query("DELETE FROM `" . Database::parsePrefix('#__nextend2_section_storage') . "` WHERE `application` LIKE 'cache'");
Database::query("DELETE FROM `" . Database::parsePrefix('#__nextend2_section_storage') . "` WHERE `application` LIKE 'smartslider' AND `section` LIKE 'sliderChanged';");
}
public function refreshCache($sliderid) {
AbstractCache::clearGroup(Slider::getCacheId($sliderid));
AbstractCache::clearGroup(AdminSlider::getCacheId($sliderid));
$this->markChanged($sliderid);
}
public function getSlidersCount($status = '*', $witGroup = false) {
$wheres = array();
$join = "";
if ($status !== '*') {
$wheres[] = " WHERE _sliders.slider_status LIKE " . Database::quote($status);
}
if ($witGroup) {
$join = "LEFT JOIN " . $this->xref->getTableName() . " AS xref ON xref.slider_id = _sliders.id ";
$wheres[] = "(xref.group_id IS NULL OR xref.group_id = 0)";
}
$data = Database::queryRow("SELECT COUNT(*) AS sliders FROM " . $this->getTableName() . " as _sliders " . $join . " " . implode(' AND ', $wheres));
if (!empty($data)) {
return intval($data['sliders']);
}
return 0;
}
/**
* @return mixed
*/
public function getAll($groupID = '*', $status = '*', $orderBy = 'ordering', $orderByDirection = 'ASC', $page = null, $limit = 'all') {
$slidesModel = new ModelSlides($this);
if (empty($orderBy)) {
$orderBy = 'ordering';
}
if (empty($orderByDirection)) {
$orderByDirection = 'ASC';
}
$_orderby = $orderBy . ' ' . $orderByDirection;
$limitQuery = "";
$wheres = array();
if ($groupID !== '*') {
if ($groupID == 0) {
$wheres[] = "(xref.group_id IS NULL OR xref.group_id = 0)";
if ($page !== null && $limit != 'all') {
$first = intval($page) * intval($limit);
$limitQuery = "LIMIT " . $first . "," . intval($limit);
}
} else {
if ($orderBy == 'ordering') {
$_orderby = 'xref.' . $orderBy . ' ' . $orderByDirection;
}
$wheres[] = "xref.group_id = '" . $groupID . "'";
}
}
if ($status !== '*') {
$wheres[] = "sliders.slider_status LIKE " . Database::quote($status);
}
$sliders = Database::queryAll("
SELECT sliders.*,
IF(sliders.thumbnail != '',
sliders.thumbnail,
IF(sliders.type != 'group',
(SELECT slides.thumbnail FROM " . $slidesModel->getTableName() . " AS slides WHERE slides.slider = sliders.id AND slides.published = 1 AND slides.generator_id = 0 AND slides.thumbnail NOT LIKE '' ORDER BY slides.first DESC, slides.ordering ASC LIMIT 1),
''
)
) AS thumbnail,
IF(sliders.type != 'group',
(SELECT count(*) FROM " . $slidesModel->getTableName() . " AS slides2 WHERE slides2.slider = sliders.id GROUP BY slides2.slider),
(SELECT count(*) FROM " . $this->xref->getTableName() . " AS xref2 LEFT JOIN " . $this->getTableName() . " AS sliders2 ON sliders2.id = xref2.slider_id WHERE xref2.group_id = sliders.id AND sliders2.slider_status LIKE 'published' GROUP BY xref2.group_id)
) AS slides
FROM " . $this->getTableName() . " AS sliders
LEFT JOIN " . $this->xref->getTableName() . " AS xref ON xref.slider_id = sliders.id
WHERE " . implode(' AND ', $wheres) . "
ORDER BY " . $_orderby . " " . $limitQuery);
return $sliders;
}
public function _getAll() {
return Database::queryAll("SELECT sliders.* FROM " . $this->getTableName() . " AS sliders");
}
public function getSearchResults($keyword = "") {
$slidesModel = new ModelSlides($this);
$wheres = array();
$orderByExtra = "";
$id = intval($keyword);
if ($id > 0) {
$wheres[] = "sliders.id LIKE '%" . $id . "%'";
$orderByExtra = "(sliders.id = '" . $id . "') DESC, ";
}
$wheres[] = "sliders.alias LIKE " . Database::quote('%' . $keyword . '%') . " OR sliders.title LIKE " . Database::quote('%' . $keyword . '%');
return Database::queryAll("SELECT sliders.*,
xref.group_id,
IF(sliders.thumbnail != '',
sliders.thumbnail,
IF(sliders.type != 'group',
(SELECT slides.thumbnail FROM " . $slidesModel->getTableName() . " AS slides WHERE slides.slider = sliders.id AND slides.published = 1 AND slides.generator_id = 0 AND slides.thumbnail NOT LIKE '' ORDER BY slides.first DESC, slides.ordering ASC LIMIT 1),
''
)
) AS thumbnail,
IF(sliders.type != 'group',
(SELECT count(*) FROM " . $slidesModel->getTableName() . " AS slides2 WHERE slides2.slider = sliders.id GROUP BY slides2.slider),
(SELECT count(*) FROM " . $this->xref->getTableName() . " AS xref2 LEFT JOIN " . $this->getTableName() . " AS sliders2 ON sliders2.id = xref2.slider_id WHERE xref2.group_id = sliders.id AND sliders2.slider_status LIKE 'published' GROUP BY xref2.group_id)
) AS slides
FROM " . $this->getTableName() . " AS sliders
LEFT JOIN " . $this->xref->getTableName() . " AS xref ON xref.slider_id = sliders.id
WHERE
(
xref.group_id IS NULL
OR xref.group_id = 0
OR (SELECT _sliders.slider_status FROM " . $this->getTableName() . " AS _sliders WHERE _sliders.id = xref.group_id ) LIKE 'published'
)
AND sliders.slider_status LIKE 'published'
AND (" . implode(' OR ', $wheres) . ")
GROUP BY sliders.id
ORDER BY " . $orderByExtra . "sliders.title ASC");
}
public function getGroups($status = '*') {
$wheres = array(
"type LIKE 'group'"
);
if ($status !== '*') {
$wheres[] = "slider_status LIKE " . Database::quote($status);
}
return Database::queryAll("SELECT id, title FROM " . $this->getTableName() . " WHERE " . implode(' AND ', $wheres) . " ORDER BY title ASC");
}
public function getFallbackUsage($sliderIDs) {
$wheres = array();
foreach ($sliderIDs as $id) {
$wheres[] = 'params LIKE \'%"fallback-slider":"' . $id . '"%\'';
}
return Database::queryAll("SELECT id FROM " . $this->getTableName() . " as sliders WHERE " . implode(" OR ", $wheres));
}
public function import($slider, $groupID = 0) {
try {
$this->table->insert(array(
'title' => $slider['title'],
'type' => $slider['type'],
'thumbnail' => empty($slider['thumbnail']) ? '' : $slider['thumbnail'],
'params' => $slider['params']->toJSON(),
'time' => date('Y-m-d H:i:s', Platform::getTimestamp()),
'ordering' => -1
));
$sliderID = $this->table->insertId();
if (isset($slider['alias'])) {
$this->updateAlias($sliderID, $slider['alias']);
}
$this->xref->add($groupID, $sliderID);
$this->reindexOrdering();
SmartSlider3Info::sliderChanged();
return $sliderID;
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
public function replace($slider, $groupID) {
if (isset($slider['id']) && $slider['id'] > 0) {
$groups = $this->xref->getGroups($slider['id']);
$this->deletePermanently($slider['id']);
try {
$this->table->insert(array(
'id' => $slider['id'],
'title' => $slider['title'],
'type' => $slider['type'],
'thumbnail' => empty($slider['thumbnail']) ? '' : $slider['thumbnail'],
'params' => $slider['params']->toJSON(),
'time' => date('Y-m-d H:i:s', Platform::getTimestamp())
));
$sliderID = $this->table->insertId();
if (isset($slider['alias'])) {
$this->updateAlias($sliderID, $slider['alias']);
}
if ($groupID) {
$this->xref->add($groupID, $sliderID);
}
if (!empty($groups)) {
foreach ($groups as $group) {
if ($groupID != $group['group_id']) {
$this->xref->add($group['group_id'], $sliderID);
}
}
}
SmartSlider3Info::sliderChanged();
return $sliderID;
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
return $this->import($slider);
}
/**
* @param $sliderId
* @param $params Data
*/
public function importUpdate($sliderId, $params) {
$this->table->update(array(
'params' => $params->toJson()
), array(
"id" => $sliderId
));
}
public function create($slider, $groupID = 0) {
if (!isset($slider['version'])) {
$slider['version'] = SmartSlider3Info::$version;
}
if (!isset($slider['title'])) return false;
if ($slider['title'] == '') $slider['title'] = n2_('New slider');
if (Str::strlen($slider['title']) > $this->sliderTitleLength) {
$slider['title'] = Str::substr($slider['title'], 0, $this->sliderTitleLength);
}
$title = $slider['title'];
unset($slider['title']);
$type = $slider['type'];
unset($slider['type']);
$thumbnail = '';
if (!empty($slider['thumbnail'])) {
$thumbnail = $slider['thumbnail'];
unset($slider['thumbnail']);
}
try {
$this->table->insert(array(
'title' => $title,
'type' => $type,
'params' => json_encode($slider),
'thumbnail' => $thumbnail,
'time' => date('Y-m-d H:i:s', Platform::getTimestamp()),
'ordering' => -1
));
$sliderID = $this->table->insertId();
$this->xref->add($groupID, $sliderID);
$this->reindexOrdering();
SmartSlider3Info::sliderChanged();
return $sliderID;
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
public function saveSimple($id, $title, $params) {
if ($id <= 0) return false;
$params['version'] = SmartSlider3Info::$version;
if (empty($title)) $title = n2_('New slider');
if (Str::strlen($title) > $this->sliderTitleLength) {
$title = Str::substr($title, 0, $this->sliderTitleLength);
}
$this->table->update(array(
'title' => $title,
'params' => json_encode($params)
), array(
"id" => $id
));
}
public function save($id, $slider) {
$slider['version'] = SmartSlider3Info::$version;
if (!isset($slider['title']) || $id <= 0) return false;
$response = array(
'changedFields' => array()
);
if ($slider['title'] == '') $slider['title'] = n2_('New slider');
$title = $slider['title'];
unset($slider['title']);
if (Str::strlen($title) > $this->sliderTitleLength) {
$title = Str::substr($title, 0, $this->sliderTitleLength);
}
$alias = $slider['alias'];
unset($slider['alias']);
$type = $slider['type'];
unset($slider['type']);
$thumbnail = '';
if (!empty($slider['thumbnail'])) {
$thumbnail = $slider['thumbnail'];
unset($slider['thumbnail']);
}
$this->table->update(array(
'title' => $title,
'type' => $type,
'params' => json_encode($slider),
'thumbnail' => $thumbnail
), array(
"id" => $id
));
$aliasResult = $this->updateAlias($id, $alias);
if ($aliasResult !== false) {
if ($aliasResult['oldAlias'] !== $aliasResult['newAlias']) {
if ($aliasResult['newAlias'] === null) {
Notification::notice(n2_('Alias removed'));
$response['changedFields']['slideralias'] = '';
} else if ($aliasResult['newAlias'] === '') {
Notification::error(n2_('Alias must contain one or more letters'));
$response['changedFields']['slideralias'] = '';
} else {
Notification::notice(sprintf(n2_('Alias updated to: %s'), $aliasResult['newAlias']));
$response['changedFields']['slideralias'] = $aliasResult['newAlias'];
}
}
}
$this->markChanged($id);
SmartSlider3Info::sliderChanged();
return $response;
}
public function updateAlias($sliderID, $alias) {
$isNull = false;
if (empty($alias)) {
$isNull = true;
} else {
$alias = strtolower($alias);
$alias = preg_replace('/&.+?;/', '', $alias); // kill entities
$alias = str_replace('.', '-', $alias);
$alias = preg_replace('/[^%a-z0-9 _-]/', '', $alias);
$alias = preg_replace('/\s+/', '-', $alias);
$alias = preg_replace('|-+|', '-', $alias);
$alias = preg_replace('|^-*|', '', $alias);
if (empty($alias)) {
$isNull = true;
}
}
$slider = $this->get($sliderID);
if ($isNull) {
if ($slider['alias'] == 'null') {
} else {
Database::query('UPDATE ' . $this->table->getTableName() . ' SET `alias` = NULL WHERE id = ' . intval($sliderID));
return array(
'oldAlias' => $slider['alias'],
'newAlias' => null
);
}
} else {
if (!is_numeric($alias)) {
if ($slider['alias'] == $alias) {
return array(
'oldAlias' => $slider['alias'],
'newAlias' => $alias
);
} else {
$_alias = $alias;
for ($i = 2; $i < 12; $i++) {
$sliderWithAlias = $this->getByAlias($_alias);
if (!$sliderWithAlias) {
$this->table->update(array(
'alias' => $_alias
), array(
"id" => $sliderID
));
return array(
'oldAlias' => $slider['alias'],
'newAlias' => $_alias
);
break;
} else {
$_alias = $alias . $i;
}
}
}
}
return array(
'oldAlias' => $slider['alias'],
'newAlias' => ''
);
}
return false;
}
public function setTitle($id, $title) {
if (Str::strlen($title) > $this->sliderTitleLength) {
$title = Str::substr($title, 0, $this->sliderTitleLength);
}
$this->table->update(array(
'title' => $title
), array(
"id" => $id
));
$this->markChanged($id);
return $id;
}
public function setThumbnail($id, $thumbnail) {
$this->table->update(array(
'thumbnail' => $thumbnail
), array(
"id" => $id
));
$this->markChanged($id);
return $id;
}
public function changeSliderType($sliderID, $targetSliderType) {
$this->table->update(array(
'type' => $targetSliderType
), array(
"id" => $sliderID
));
$this->markChanged($sliderID);
}
/**
* @param $sliderID
* @param $groupID
*
* @return string
*/
public function trash($sliderID, $groupID) {
$relatedGroups = $this->xref->getGroups($sliderID);
if (count($relatedGroups) > 1) {
/**
* Delete the connection between the slider and the group
*/
$this->xref->deleteXref($groupID, $sliderID);
return 'unlink';
}
$this->table->update(array(
'slider_status' => 'trash'
), array(
"id" => $sliderID
));
$helper = new HelperSliderChanged($this);
$helper->setSliderChanged($sliderID, 1);
$helper->setSliderChanged($groupID, 1);
$slider = $this->get($sliderID);
if ($slider['type'] == 'group') {
$subSliders = $this->xref->getSliders($sliderID, 'published');
foreach ($subSliders as $subSlider) {
if (!$this->xref->isSliderAvailableInAnyGroups($subSlider['slider_id'])) {
$helper->setSliderChanged($subSlider['slider_id'], 1);
}
}
}
return 'trash';
}
public function restore($id) {
$changedSliders = array();
$helper = new HelperSliderChanged($this);
$slider = $this->get($id);
if ($slider['type'] == 'group') {
$subSliders = $this->xref->getSliders($id, 'published');
foreach ($subSliders as $subSlider) {
if (!$this->xref->isSliderAvailableInAnyGroups($subSlider['slider_id'])) {
$changedSliders[] = $subSlider['slider_id'];
}
}
} else {
$relatedGroups = $this->xref->getGroups($id);
if ($relatedGroups && isset($relatedGroups[0]['group_id']) && $relatedGroups[0]['group_id'] > 0) {
//if a slider was trashed, then it can only be restored to one group
$helper->setSliderChanged($relatedGroups[0]['group_id'], 1);
}
}
$this->table->update(array(
'slider_status' => 'published'
), array(
"id" => $id
));
if (!empty($changedSliders)) {
foreach ($changedSliders as $sliderID) {
$helper->setSliderChanged($sliderID, 1);
}
}
}
/**
* @param $id
*
* @return array the IDs of the deleted sliders.
*/
public function deletePermanently($id) {
$slidesModel = new ModelSlides($this);
$slidesModel->deleteBySlider($id);
$deletedSliders = $this->xref->deleteGroup($id);
$deletedSliders[] = $id;
$this->xref->deleteSlider($id);
$this->table->deleteByPk($id);
AbstractCache::clearGroup(Slider::getCacheId($id));
AbstractCache::clearGroup(AdminSlider::getCacheId($id));
$this->markChanged($id);
$this->reindexOrdering();
SmartSlider3Info::sliderChanged();
return $deletedSliders;
}
public function trashOrDelete($id, $groupID) {
$relatedGroups = $this->xref->getGroups($id);
if (count($relatedGroups) > 1) {
/**
* Delete the connection between the slider and the group
*/
$this->xref->deleteXref($groupID, $id);
return 'unlink';
} else {
$this->deletePermanently($id);
return 'delete';
}
}
public function deleteSlides($id) {
$slidesModel = new ModelSlides($this);
$slidesModel->deleteBySlider($id);
$this->markChanged($id);
}
public function duplicate($id, $withGroup = true) {
$slider = $this->get($id);
unset($slider['id']);
$slider['title'] .= ' - ' . n2_('Copy');
if (Str::strlen($slider['title']) > $this->sliderTitleLength) {
$slider['title'] = Str::substr($slider['title'], 0, $this->sliderTitleLength);
}
$slider['time'] = date('Y-m-d H:i:s', Platform::getTimestamp());
/**
* Remove alias to prevent override
*/
$slider['alias'] = '';
try {
$this->table->insert($slider);
$newSliderId = $this->table->insertId();
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
if (!$newSliderId) {
return false;
}
if ($slider['type'] == 'group') {
$subSliders = $this->xref->getSliders($id, 'published');
foreach ($subSliders as $subSlider) {
$newSubSliderID = $this->duplicate($subSlider['slider_id'], false);
$this->xref->add($newSliderId, $newSubSliderID);
}
} else {
$slidesModel = new ModelSlides($this);
foreach ($slidesModel->getAll($id) as $slide) {
$slidesModel->copyTo($slide['id'], true, $newSliderId);
}
if ($withGroup) {
$groups = $this->xref->getGroups($id);
foreach ($groups as $group) {
$this->xref->add($group['group_id'], $newSliderId);
}
}
}
$this->reindexOrdering();
SmartSlider3Info::sliderChanged();
return $newSliderId;
}
public function markChanged($sliderid) {
$helper = new HelperSliderChanged($this);
$helper->setSliderChanged($sliderid, 1);
}
public function order($groupID, $ids, $isReverse = false, $orders = array()) {
if (is_array($ids) && count($ids) > 0) {
if ($isReverse) {
$ids = array_reverse($ids);
}
$groupID = intval($groupID);
if ($groupID <= 0) {
$groupID = false;
}
if (!empty($orders)) {
asort($orders);
$orders = array_values($orders);
}
$i = 0;
foreach ($ids as $id) {
$id = intval($id);
if ($id > 0) {
if (!$groupID) {
if (!empty($orders)) {
$order = intval($orders[$i]);
} else {
$order = $i;
}
$this->table->update(array(
'ordering' => $order,
), array(
"id" => $id
));
} else {
$this->xref->table->update(array(
'ordering' => $i,
), array(
"slider_id" => $id,
"group_id" => $groupID
));
}
$i++;
}
}
return $i;
}
return false;
}
public function reindexOrdering() {
$sliders = $this->getAll(0);
foreach ($sliders as $idx => $slider) {
$this->table->update(array(
'ordering' => $idx
), array(
"id" => $slider['id']
));
}
}
protected function getMaximalOrderValue() {
$query = "SELECT MAX(ordering) AS ordering FROM " . $this->getTableName() . "";
$result = Database::queryRow($query);
if (isset($result['ordering'])) return $result['ordering'] + 1;
return 0;
}
} Model/ModelSlidersXRef.php 0000644 00000013656 15235664602 0011514 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Model;
use Exception;
use Nextend\Framework\Database\Database;
use Nextend\Framework\Model\AbstractModelTable;
use Nextend\SmartSlider3\Application\Helper\HelperSliderChanged;
use Nextend\SmartSlider3\SmartSlider3Info;
class ModelSlidersXRef extends AbstractModelTable {
protected function createConnectorTable() {
return Database::getTable('nextend2_smartslider3_sliders_xref');
}
public function add($groupID, $sliderID) {
try {
$this->table->insert(array(
'group_id' => $groupID,
'slider_id' => $sliderID,
'ordering' => $this->getMaximalOrderValue($groupID)
));
$helper = new HelperSliderChanged($this);
$helper->setSliderChanged($sliderID, 1);
$helper->setSliderChanged($groupID, 1);
SmartSlider3Info::sliderChanged();
return true;
} catch (Exception $e) {
return false;
}
}
/**
* @param int $groupID
*
* @return array the IDs of the deleted child sliders.
*/
public function deleteGroup($groupID) {
$sliders = $this->getSliders($groupID);
$deletedSliders = array();
$slidersModel = new ModelSliders($this);
foreach ($sliders as $slider) {
$relatedGroups = $this->getGroups($slider['slider_id']);
if (count($relatedGroups) == 1) {
if ($slidersModel->trashOrDelete($slider['slider_id'], $groupID) == 'delete') {
$deletedSliders[] = $slider['slider_id'];
}
}
}
$this->table->deleteByAttributes(array(
'group_id' => $groupID
));
SmartSlider3Info::sliderChanged();
return $deletedSliders;
}
public function deleteSlider($sliderID) {
$helper = new HelperSliderChanged($this);
$helper->setSliderChanged($sliderID, 1);
SmartSlider3Info::sliderChanged();
return $this->table->deleteByAttributes(array(
'slider_id' => $sliderID
));
}
public function deleteXref($groupID, $sliderID) {
$helper = new HelperSliderChanged($this);
$helper->setSliderChanged($sliderID, 1);
$helper->setSliderChanged($groupID, 1);
SmartSlider3Info::sliderChanged();
return $this->table->deleteByAttributes(array(
'group_id' => $groupID,
'slider_id' => $sliderID
));
}
public function getSliders($groupID, $status = '*') {
if ($status !== '*') {
$slidersModel = new ModelSliders($this);
return Database::queryAll("
SELECT xref.slider_id
FROM " . $this->getTableName() . " AS xref
LEFT JOIN " . $slidersModel->getTableName() . " AS sliders ON sliders.id = xref.slider_id
WHERE xref.group_id = '" . $groupID . "' AND sliders.slider_status LIKE " . Database::quote($status) . "
ORDER BY xref.ordering ASC");
}
return Database::queryAll("
SELECT slider_id
FROM " . $this->getTableName() . "
WHERE group_id = '" . $groupID . "'
ORDER BY ordering ASC");
}
public function getGroupsIDs($sliderID) {
$ids = array();
$result = Database::queryAll("
SELECT group_id
FROM " . $this->getTableName() . "
WHERE slider_id = '" . $sliderID . "'
ORDER BY ordering ASC");
foreach ($result as $row) {
$ids[] = $row['group_id'];
}
return $ids;
}
public function getGroups($sliderID, $status = '*') {
$slidersModel = new ModelSliders($this);
$wheres = array("xref.slider_id = '" . $sliderID . "'");
if ($status !== '*') {
$wheres[] = "sliders.slider_status LIKE '" . $status . "'";
}
$result = Database::queryAll("
SELECT xref.group_id, sliders.title
FROM " . $this->getTableName() . " AS xref
LEFT JOIN " . $slidersModel->getTableName() . " AS sliders ON sliders.id = xref.group_id
WHERE " . implode(' AND ', $wheres) . "
ORDER BY xref.group_id ASC");
if (!empty($result)) {
return $result;
}
return array(
array(
"group_id" => 0,
"title" => n2_('Dashboard')
)
);
}
protected function getMaximalOrderValue($groupID) {
$query = "SELECT MAX(ordering) AS ordering FROM " . $this->getTableName() . " WHERE group_id = '" . intval($groupID) . "'";
$result = Database::queryRow($query);
if (isset($result['ordering'])) return $result['ordering'] + 1;
return 0;
}
/**
* @param $sliderID
*
* @return bool
*/
public function isSliderAvailableInAnyGroups($sliderID) {
$allRelatedGroups = $this->getGroups($sliderID);
$slidersModel = new ModelSliders($this);
foreach ($allRelatedGroups as $group) {
if ($group['group_id'] != 0) {
/*
* It is a group
*/
$sliderRow = $slidersModel->get($group['group_id']);
if (isset($sliderRow['slider_status']) && $sliderRow['slider_status'] === 'published') {
return true;
}
} else {
/*
* It is a slider
*/
$sliderRow = $slidersModel->get($sliderID);
if (isset($sliderRow['slider_status']) && $sliderRow['slider_status'] === 'published') {
return true;
}
}
}
return false;
}
} Model/ModelSlides.php 0000644 00000056335 15235664602 0010546 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Model;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Database\Database;
use Nextend\Framework\Misc\Base64;
use Nextend\Framework\Misc\Str;
use Nextend\Framework\Model\AbstractModelTable;
use Nextend\Framework\Request\Request;
use Nextend\SmartSlider3\Application\Helper\HelperSliderChanged;
use Nextend\SmartSlider3\Renderable\Component\AbstractComponent;
use Nextend\SmartSlider3\Renderable\Component\ComponentCol;
use Nextend\SmartSlider3\Renderable\Component\ComponentContent;
use Nextend\SmartSlider3\Renderable\Component\ComponentLayer;
use Nextend\SmartSlider3\Renderable\Component\ComponentRow;
use Nextend\SmartSlider3\SlideBuilder\BuilderComponentLayer;
use Nextend\SmartSlider3\SlideBuilder\BuilderComponentSlide;
use Nextend\SmartSlider3\Slider\Slide;
use Nextend\SmartSlider3\Slider\Slider;
use Nextend\SmartSlider3\SmartSlider3Info;
use Nextend\SmartSlider3Pro\Renderable\Component\ComponentGroup;
class ModelSlides extends AbstractModelTable {
protected function createConnectorTable() {
return Database::getTable('nextend2_smartslider3_slides');
}
public function get($id) {
return $this->table->findByPk($id);
}
public function getAll($sliderid = 0, $where = '') {
return Database::queryAll('SELECT * FROM ' . $this->getTableName() . ' WHERE slider = ' . $sliderid . ' ' . $where . ' ORDER BY ordering', false, "assoc", null);
}
public function createQuickImage($image, $sliderId) {
$parameters = array(
'background-type' => 'image',
'backgroundImage' => $image['image']
);
if (!empty($image['alt'])) {
$parameters['backgroundAlt'] = $image['alt'];
}
$slideID = $this->create($sliderId, $image['title'], array(), $image['image'], $parameters, array(
'description' => $image['description']
));
$this->markChanged($sliderId);
return $slideID;
}
public function createQuickEmptySlide($sliderId) {
$parameters = array(
'background-type' => 'color'
);
$slideID = $this->create($sliderId, 'Slide', array(), '', $parameters);
$this->markChanged($sliderId);
return $slideID;
}
public function createQuickStaticOverlay($sliderId) {
$parameters = array(
'static-slide' => 1
);
$slideID = $this->create($sliderId, n2_('Static overlay'), array(), '', $parameters);
$this->markChanged($sliderId);
return $slideID;
}
public function createQuickPost($post, $sliderId) {
$data = new Data($post);
$title = $this->removeFourByteChars($data->get('title'));
$description = $this->removeFourByteChars($data->get('description'));
$slideBuilder = new BuilderComponentSlide(array(
'title' => $title,
'description' => $description,
'thumbnail' => $data->get('image'),
'background-type' => 'image',
'backgroundImage' => $data->get('image'),
'backgroundImageOpacity' => 20,
'backgroundColor' => '000000FF'
));
$slideBuilder->content->set(array(
'desktopportraitpadding' => '10|*|100|*|10|*|100|*|px',
'mobileportraitpadding' => '10|*|10|*|10|*|10|*|px'
));
if ($title) {
$heading = new BuilderComponentLayer($slideBuilder->content, 'heading');
$heading->item->set(array(
'heading' => '{name/slide}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"48||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}'),
));
}
if ($description) {
$text = new BuilderComponentLayer($slideBuilder->content, 'text');
$text->set(array(
'desktopportraitmargin' => '0|*|0|*|20|*|0|*|px',
));
$text->item->set(array(
'content' => '{description/slide}',
'font' => Base64::encode('{"data":[{"extra":"","color":"ffffffff","size":"18||px","tshadow":"0|*|0|*|0|*|000000ff","afont":"Roboto,Arial","lineheight":"1.5","bold":0,"italic":0,"underline":0,"align":"inherit","letterspacing":"normal","wordspacing":"normal","texttransform":"none"},{"extra":""}]}'),
));
}
$link = $data->get('link');
if (!empty($link)) {
$buttonLayer = new BuilderComponentLayer($slideBuilder->content, 'button');
$buttonLayer->item->set(array(
'content' => n2_('Read more'),
'link' => $link . '|*|_self'
));
}
$row = $this->convertSlideDataToDatabaseRow($slideBuilder->getData(), $sliderId);
$slideID = $this->create($row['slider'], $row['title'], $row['slide'], $row['thumbnail'], $row['params'], array(
'description' => $row['description'],
'published' => $row['published'],
'publish_up' => $row['publish_up'],
'publish_down' => $row['publish_down']
));
$this->markChanged($sliderId);
return $slideID;
}
public function createSimpleEditAdd($postData, $sliderId) {
$data = new Data($postData);
$title = $data->get('title', '');
$description = $data->get('description', '');
$slideBuilder = new BuilderComponentSlide(array(
'title' => $title,
'description' => $description,
'thumbnailType' => $data->get('thumbnailType', ''),
'thumbnail' => $data->get('backgroundImage', ''),
'background-type' => 'image',
'backgroundImage' => $data->get('backgroundImage', ''),
'backgroundImageOpacity' => 100,
'backgroundColor' => '000000FF',
'href' => $data->get('href', ''),
'href-target' => $data->get('href-target', '')
));
$slideBuilder->content->set(array(
'desktopportraitpadding' => '10|*|100|*|10|*|100|*|px',
'mobileportraitpadding' => '10|*|10|*|10|*|10|*|px'
));
$videoUrl = $data->get('video', '');
if (!empty($videoUrl)) {
preg_match('/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/', $videoUrl, $matches);
if (!empty($matches)) {
/**
* YouTube
*/
$thumbnail = 'https://i.ytimg.com/vi/' . $matches[2] . '/hqdefault.jpg';
$slideBuilder->set('thumbnail', $thumbnail);
$youtubeLayer = new BuilderComponentLayer($slideBuilder->content, 'youtube');
$youtubeLayer->item->set(array(
'code' => $matches[2],
'youtubeurl' => $videoUrl,
'image' => $thumbnail
));
} else {
preg_match('/https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/', $videoUrl, $matches);
if (!empty($matches)) {
/**
* Vimeo
*/
$vimeoLayer = new BuilderComponentLayer($slideBuilder->content, 'vimeo');
$vimeoLayer->item->set(array(
'vimeourl' => $videoUrl
));
} else {
/**
* MP4
*/
$mp4Layer = new BuilderComponentLayer($slideBuilder->content, 'video');
$mp4Layer->item->set(array(
'video_mp4' => $videoUrl
));
}
}
}
/*
if ($title) {
$heading = new BuilderComponentLayer($slideBuilder->content, 'heading');
$heading->item->set(array(
'heading' => '{name/slide}'
));
}
*/
$row = $this->convertSlideDataToDatabaseRow($slideBuilder->getData(), $sliderId);
$slideID = $this->create($row['slider'], $row['title'], $row['slide'], $row['thumbnail'], $row['params'], array(
'description' => $row['description'],
'published' => $row['published'],
'publish_up' => $row['publish_up'],
'publish_down' => $row['publish_down']
));
$this->markChanged($sliderId);
return $slideID;
}
public function import($row, $sliderId) {
if (!$row['params']->has('version')) {
/**
* We must set the missing empty version to allow upgrade of the old slides
*/
$row['params']->set('version', '');
}
return $this->create($sliderId, $row['title'], $row['slide'], $row['thumbnail'], $row['params']->toArray(), array(
'description' => $row['description'],
'published' => $row['published'],
'publish_up' => $row['publish_up'],
'publish_down' => $row['publish_down'],
'first' => $row['first'],
'ordering' => $row['ordering'],
'generator_id' => $row['generator_id']
));
}
private function create($sliderID, $title, $layers, $thumbnail, $params = array(), $optional = array()) {
if (!isset($optional['ordering'])) {
$optional['ordering'] = $this->getNextOrdering($sliderID);
}
if (!isset($params['version'])) {
$params['version'] = SmartSlider3Info::$version;
}
$data = array_merge(array(
'description' => '',
'first' => 0,
'published' => 1,
'publish_up' => '1970-01-01 00:00:00',
'publish_down' => '1970-01-01 00:00:00',
'generator_id' => 0
), $optional, array(
'title' => $title,
'slide' => json_encode($layers, JSON_UNESCAPED_SLASHES),
'thumbnail' => $thumbnail,
'params' => json_encode($params, JSON_UNESCAPED_SLASHES),
'slider' => $sliderID
));
$this->table->insert($data);
return $this->table->insertId();
}
/**
* @param $sliderId
* @param int $generatorID
* @param $slide
*
* @return bool
*/
public function createSlideWithGenerator($sliderId, $generatorID, $slide) {
$row = $this->convertSlideDataToDatabaseRow($slide, $sliderId);
$slideId = $this->create($row['slider'], $row['title'], $row['slide'], $row['thumbnail'], $row['params'], array(
'description' => $row['description'],
'published' => $row['published'],
'publish_up' => $row['publish_up'],
'publish_down' => $row['publish_down'],
'generator_id' => $generatorID
));
$this->markChanged($sliderId);
return $slideId;
}
/**
* @param int $slideID
* @param string $slide
* @param string $guides
*
* @return bool
*/
public function save($slideID, $slide, $guides) {
$slideData = json_decode(Base64::decode($slide), true);
$slideData['guides'] = $guides;
$row = $this->convertSlideDataToDatabaseRow($slideData);
$this->table->update(array(
'title' => $row['title'],
'slide' => json_encode($row['slide'], JSON_UNESCAPED_SLASHES),
'description' => $row['description'],
'thumbnail' => $row['thumbnail'],
'published' => $row['published'],
'publish_up' => $row['publish_up'],
'publish_down' => $row['publish_down'],
'params' => json_encode($row['params'], JSON_UNESCAPED_SLASHES)
), array('id' => $slideID));
$this->markChanged(Request::$REQUEST->getInt('sliderid'));
return true;
}
public function saveSimple($slideID, $title, $description, $params) {
$this->table->update(array(
'title' => $title,
'description' => $description,
'params' => json_encode($params, JSON_UNESCAPED_SLASHES)
), array('id' => $slideID));
}
/**
* Updates the params field of the slide;
*
* @param $id
* @param $params
*/
public function updateSlideParams($id, $params) {
$this->table->update(array(
'params' => json_encode($params)
), array('id' => $id));
}
public function delete($id) {
$slide = $this->get($id);
if ($slide['generator_id'] > 0) {
$slidesWithSameGenerator = $this->getAll($slide['slider'], 'AND generator_id = ' . intval($slide['generator_id']));
if (count($slidesWithSameGenerator) == 1) {
$generatorModel = new ModelGenerator($this);
$generatorModel->delete($slide['generator_id']);
}
}
$this->table->deleteByAttributes(array(
"id" => intval($id)
));
$this->markChanged($slide['slider']);
}
/**
* @param int $id
* @param bool $maintainOrdering
* @param bool|int $targetSliderId
*
* @return int The new slide ID;
*/
public function copyTo($id, $maintainOrdering = false, $targetSliderId = false) {
$row = $this->get($id);
unset($row['id']);
$row['first'] = 0;
if ($targetSliderId === false || $row['slider'] == $targetSliderId) {
/**
* Copy the slide to the same slider
*/
$this->shiftSlideOrdering($row['slider'], $row['ordering']);
} else {
/**
* Copy the slide to another slider
*/
$row['slider'] = $targetSliderId;
if (!$maintainOrdering) {
$row['ordering'] = 0;
}
}
if (!empty($row['generator_id'])) {
$generatorModel = new ModelGenerator($this);
$row['generator_id'] = $generatorModel->duplicate($row['generator_id']);
}
$row['slide'] = json_encode(AbstractComponent::translateUniqueIdentifier(json_decode($row['slide'], true)), JSON_UNESCAPED_SLASHES);
$this->table->insert($row);
$id = $this->table->insertId();
$this->markChanged($row['slider']);
return $id;
}
public function setTitle($id, $title) {
$slide = $this->get($id);
$this->table->update(array(
"title" => $title
), array(
"id" => $id
));
$this->markChanged($slide['slider']);
}
public function first($id) {
$slide = $this->get($id);
$this->table->update(array(
"first" => 0
), array(
"slider" => $slide['slider']
));
$this->table->update(array(
"first" => 1
), array(
"id" => $id
));
$this->markChanged($slide['slider']);
}
public function publish($id) {
$this->markChanged(Request::$REQUEST->getInt('sliderid'));
return $this->table->update(array(
"published" => 1
), array("id" => intval($id)));
}
public function unPublish($id) {
$this->table->update(array(
"published" => 0
), array(
"id" => intval($id)
));
$this->markChanged(Request::$REQUEST->getInt('sliderid'));
}
public function convertToSlide($id) {
$slide = $this->get($id);
$data = new Data($slide['params'], true);
$data->set('static-slide', 0);
$this->table->update(array(
"params" => $data->toJSON()
), array(
"id" => intval($id)
));
$this->markChanged($slide['slider']);
}
public function deleteBySlider($sliderid) {
$slides = $this->getAll($sliderid);
foreach ($slides as $slide) {
$this->delete($slide['id']);
}
$this->markChanged($sliderid);
}
/**
* @param $sliderid
* @param $ids
*
* @return bool|int
*/
public function order($sliderid, $ids) {
if (is_array($ids) && count($ids) > 0) {
$i = 0;
foreach ($ids as $id) {
$id = intval($id);
if ($id > 0) {
$this->table->update(array(
'ordering' => $i + 1,
), array(
"id" => $id,
"slider" => $sliderid
));
$i++;
}
}
$this->markChanged($sliderid);
return $i;
}
return false;
}
private function markChanged($sliderid) {
$helper = new HelperSliderChanged($this);
$helper->setSliderChanged($sliderid, 1);
}
public function convertDynamicSlideToSlides($slideId) {
$slideData = $this->get($slideId);
if ($slideData['generator_id'] > 0) {
$sliderObj = new Slider($this, $slideData['slider'], array(), true);
$rootSlide = new Slide($sliderObj, $slideData);
$rootSlide->initGenerator(array());
$slides = $rootSlide->expandSlide();
$this->shiftSlideOrdering($slideData['slider'], $slideData['ordering'], count($slides));
$firstUsed = false;
$i = 1;
foreach ($slides as $slide) {
$row = $slide->getRow();
$row['title'] = Str::substr($row['title'], 0, 200);
$row['description'] = Str::substr($row['description'], 0, 2000);
// set the proper ordering
$row['ordering'] += $i;
if ($row['first']) {
// Make sure to mark only one slide as start slide
if ($firstUsed) {
$row['first'] = 0;
} else {
$firstUsed = true;
}
}
$this->table->insert($row);
$i++;
}
Database::query("UPDATE {$this->getTableName()} SET published = 0, first = 0 WHERE id = :id", array(
":id" => $slideData['id']
));
return count($slides);
} else {
return false;
}
}
public static function prepareSample(&$layers) {
for ($i = 0; $i < count($layers); $i++) {
if (isset($layers[$i]['type'])) {
switch ($layers[$i]['type']) {
case 'content':
ComponentContent::prepareSample($layers[$i]);
break;
case 'row':
ComponentRow::prepareSample($layers[$i]);
break;
case 'col':
ComponentCol::prepareSample($layers[$i]);
break;
default:
ComponentLayer::prepareSample($layers[$i]);
}
} else {
ComponentLayer::prepareSample($layers[$i]);
}
}
}
public function convertSlideDataToDatabaseRow($slideData, $sliderID = false) {
$slideData['version'] = SmartSlider3Info::$version;
$publish_up = '1970-01-01 00:00:00';
if (isset($slideData['publish_up'])) {
if ($slideData['publish_up'] != '0000-00-00 00:00:00') {
$publish_up = date('Y-m-d H:i:s', strtotime($slideData['publish_up']));
} else {
$publish_up = '1970-01-01 00:00:00';
}
}
$publish_down = '1970-01-01 00:00:00';
if (isset($slideData['publish_down'])) {
if ($slideData['publish_down'] != '0000-00-00 00:00:00') {
$publish_down = date('Y-m-d H:i:s', strtotime($slideData['publish_down']));
} else {
$publish_down = '1970-01-01 00:00:00';
}
}
$row = array(
'title' => $slideData['title'],
'slide' => '',
'description' => $slideData['description'],
'thumbnail' => $slideData['thumbnail'],
'published' => (isset($slideData['published']) ? $slideData['published'] : 1),
'publish_up' => $publish_up,
'publish_down' => $publish_down
);
if ($sliderID !== false) {
$row['slider'] = $sliderID;
}
$row['slide'] = $slideData['layers'];
if (isset($slideData['first'])) {
$row['first'] = intval($slideData['first']);
}
if (isset($slideData['generator_id']) && $slideData['generator_id'] > 0) {
$row['generator_id'] = intval($slideData['generator_id']);
}
unset($slideData['title']);
unset($slideData['layers']);
unset($slideData['description']);
unset($slideData['thumbnail']);
unset($slideData['published']);
unset($slideData['first']);
unset($slideData['publish_up']);
unset($slideData['publish_down']);
unset($slideData['ordering']);
unset($slideData['generator_id']);
$row['params'] = $slideData;
return $row;
}
private function removeFourByteChars($text) {
return preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $text);
}
/**
* @param int $sliderID
*
* @return int
*/
private function getNextOrdering($sliderID) {
$query = "SELECT MAX(ordering) AS ordering FROM " . $this->getTableName() . " WHERE slider = :id";
$result = Database::queryRow($query, array(
":id" => intval($sliderID)
));
if (isset($result['ordering'])) {
return $result['ordering'] + 1;
}
return 1;
}
/**
* @param int $sliderID
* @param int $offset
* @param int $slidesCount
*/
private function shiftSlideOrdering($sliderID, $offset, $slidesCount = 1) {
// Shift the afterwards slides with the slides count
Database::query("UPDATE {$this->getTableName()} SET ordering = ordering + " . $slidesCount . " WHERE slider = :sliderid AND ordering > :ordering", array(
":sliderid" => intval($sliderID),
":ordering" => intval($offset)
), '');
}
} Helper/HelperSliderChanged.php 0000644 00000004321 15235664602 0012341 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Helper;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Model\ApplicationSection;
use Nextend\Framework\Model\StorageSectionManager;
use Nextend\Framework\Pattern\MVCHelperTrait;
use Nextend\SmartSlider3\Application\Model\ModelSliders;
use Nextend\SmartSlider3\Application\Model\ModelSlidersXRef;
use WP_Post;
class HelperSliderChanged {
use MVCHelperTrait;
/** @var ApplicationSection */
protected $storage;
/**
* HelperSliderChanged constructor.
*
* @param MVCHelperTrait $MVCHelper
*/
public function __construct($MVCHelper) {
$this->setMVCHelper($MVCHelper);
$this->storage = StorageSectionManager::getStorage('smartslider');
}
public function isSliderChanged($sliderId, $value = 1) {
return intval($this->storage->get('sliderChanged', $sliderId, $value));
}
public function setGroupChanged($sliderId, $value = 1) {
$xref = new ModelSlidersXRef($this);
$groupIDs = array();
foreach ($xref->getGroups($sliderId) as $row) {
if ($row['group_id'] > 0) {
$this->storage->set('sliderChanged', $row['group_id'], $value);
}
$groupIDs[] = $row['group_id'];
}
return $groupIDs;
}
public function setSliderChanged($sliderId, $value = 1, &$changedSliders = array()) {
$this->storage->set('sliderChanged', $sliderId, $value);
$changedSliders[] = $sliderId;
$xref = new ModelSlidersXRef($this);
$sliderModel = new ModelSliders($this);
array_merge($changedSliders, $this->setGroupChanged($sliderId));
foreach ($xref->getGroups($sliderId) as $group) {
$changedSliders[] = $group['group_id'];
}
$fallbackSliders = $sliderModel->getFallbackUsage($changedSliders);
if (!empty($fallbackSliders)) {
foreach ($fallbackSliders as $slider) {
if (!in_array($slider['id'], $changedSliders)) {
$this->setSliderChanged($slider['id'], 1, $changedSliders);
}
}
}
}
} Frontend/ApplicationTypeFrontend.php 0000644 00000002005 15235664602 0013647 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Frontend;
use Nextend\Framework\Application\AbstractApplicationType;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\SmartSlider3\Application\Frontend\Slider\ControllerPreRenderSlider;
use Nextend\SmartSlider3\Application\Frontend\Slider\ControllerSlider;
class ApplicationTypeFrontend extends AbstractApplicationType {
protected $key = 'frontend';
public function __construct($application) {
ResourceTranslator::createResource('$system$', self::getAssetsPath(), self::getAssetsUri());
parent::__construct($application);
}
protected function getControllerSlider() {
return new ControllerSlider($this);
}
protected function getControllerPreRenderSlider() {
return new ControllerPreRenderSlider($this);
}
protected function getDefaultController($controllerName, $ajax = false) {
// TODO: Implement getDefaultController() method.
}
} Frontend/Slider/ControllerPreRenderSlider.php 0000644 00000001560 15235664602 0015366 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Frontend\Slider;
use Nextend\Framework\Asset\Css\Css;
use Nextend\Framework\Controller\AbstractController;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\Framework\Request\Request;
class ControllerPreRenderSlider extends AbstractController {
public function actionIframe() {
$sliderIDorAlias = Request::$GET->getVar('sliderid') !== null ? Request::$GET->getVar('sliderid') : false;
if (empty($sliderIDorAlias)) {
echo 'Slider ID or alias is empty.';
} else {
Css::addStaticGroup(ResourceTranslator::toPath('$ss3-frontend$/dist/normalize.min.css'), 'normalize');
$view = new ViewIframe($this);
$view->setSliderIDorAlias($sliderIDorAlias);
$view->display();
}
}
} Frontend/Slider/ControllerSlider.php 0000644 00000000626 15235664602 0013561 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Frontend\Slider;
use Nextend\Framework\Controller\AbstractController;
class ControllerSlider extends AbstractController {
public function actionDisplay($sliderID, $usage) {
$view = new ViewDisplay($this);
$view->setSliderIDorAlias($sliderID);
$view->setUsage($usage);
$view->display();
}
} Frontend/Slider/ViewDisplay.php 0000644 00000002636 15235664602 0012536 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Frontend\Slider;
use Nextend\Framework\View\AbstractView;
use Nextend\SmartSlider3\SliderManager\SliderManager;
class ViewDisplay extends AbstractView {
/** @var string|integer */
protected $sliderIDorAlias;
/** @var string */
protected $usage;
public function display() {
$this->getApplicationType()
->enqueueAssets();
$locale = setlocale(LC_NUMERIC, 0);
setlocale(LC_NUMERIC, "C");
$sliderManager = new SliderManager($this, $this->sliderIDorAlias, false);
$sliderManager->setUsage($this->usage);
// PHPCS - Content already escaped
echo $sliderManager->render(true); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
setlocale(LC_NUMERIC, $locale);
}
/**
* @return string|integer
*/
public function getSliderIDorAlias() {
return $this->sliderIDorAlias;
}
/**
* @param string|integer $sliderIDorAlias
*/
public function setSliderIDorAlias($sliderIDorAlias) {
$this->sliderIDorAlias = $sliderIDorAlias;
}
/**
* @return string
*/
public function getUsage() {
return $this->usage;
}
/**
* @param string $usage
*/
public function setUsage($usage) {
$this->usage = $usage;
}
} Frontend/Slider/ViewIframe.php 0000644 00000003543 15235664602 0012332 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Frontend\Slider;
use Nextend\Framework\View\AbstractView;
use Nextend\SmartSlider3\SliderManager\SliderManager;
class ViewIframe extends AbstractView {
/** @var string|integer */
protected $sliderIDorAlias;
/**
* @var integer
*/
protected $sliderID;
protected $isGroup = false;
protected $sliderHTML = '';
public function display() {
$this->getApplicationType()
->enqueueAssets();
$locale = setlocale(LC_NUMERIC, 0);
setlocale(LC_NUMERIC, "C");
$sliderManager = new SliderManager($this, $this->sliderIDorAlias, false);
$sliderManager->setUsage('iframe');
$this->sliderHTML = $sliderManager->render(true);
$slider = $sliderManager->getSlider();
if ($slider) {
$this->sliderID = $slider->sliderId;
$this->isGroup = $slider->isGroup();
}
setlocale(LC_NUMERIC, $locale);
// PHPCS - Content already escaped
echo $this->render('Iframe'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* @return string|integer
*/
public function getSliderIDorAlias() {
return $this->sliderIDorAlias;
}
/**
* @param string|integer $sliderIDorAlias
*/
public function setSliderIDorAlias($sliderIDorAlias) {
$this->sliderIDorAlias = $sliderIDorAlias;
}
/**
* @return string already escaped
*/
public function getSliderHTML() {
return $this->sliderHTML;
}
/**
* @return int
*/
public function getSliderID() {
return $this->sliderID;
}
/**
* @return bool
*/
public function isGroup() {
return $this->isGroup;
}
} Frontend/Slider/Template/Iframe.php 0000644 00000016426 15235664602 0013256 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Frontend\Slider;
use Nextend\Framework\Asset\AssetManager;
use Nextend\Framework\Request\Request;
use Nextend\SmartSlider3\Settings;
use Nextend\WordPress\OutputBuffer;
/**
* @var ViewIframe $this
*/
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex">
<title>Slider</title>
<style>
html, body {
overflow: hidden;
}
body * {
background-attachment: scroll !important;
}
</style>
<?php
/**
* In page builder -> editors, we must force sliders to be visible on every device.
*/
if (Request::$GET->getInt('iseditor')):
?>
<script>
window.ssOverrideHideOn = {
desktopLandscape: 0,
desktopPortrait: 0,
tabletLandscape: 0,
tabletPortrait: 0,
mobileLandscape: 0,
mobilePortrait: 0
};
</script>
<?php
endif;
?>
<?php
$handlers = ob_list_handlers();
if (!in_array(OutputBuffer::class . '::outputCallback', $handlers)) {
if (class_exists('\\Nextend\\Framework\\Asset\\AssetManager', false)) {
// PHPCS - Content already escaped
echo AssetManager::getCSS(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// PHPCS - Content already escaped
echo AssetManager::getJs(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
$externals = esc_attr(Settings::get('external-css-files'));
if (!empty($externals)) {
$externals = explode("\n", $externals);
foreach ($externals as $external) {
echo "<link rel='stylesheet' href='" . esc_url($external) . "' type='text/css' media='all' />";
}
}
?>
</head>
<body>
<?php
// PHPCS - Content already escaped
echo $this->getSliderHTML(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
<script>
_N2.r('windowLoad', function () {
if (window.n2ss) {
var body = document.body,
options = {
forceFullWidth: 0,
fullPage: 0,
focusOffsetTop: '',
focusOffsetBottom: '',
margin: 0,
height: 0
},
setOption = function (name, value) {
if (options[name] != value) {
options[name] = value;
parent.postMessage({
key: 'option',
name: name,
value: value
}, "*");
}
},
sliders = [],
promise = new Promise(function (resolve) {
var checkSliders = function () {
if (Object.keys(n2ss.sliders).length) {
initSliders();
} else {
setTimeout(checkSliders, 16);
}
},
initSliders = function () {
var promises = [];
for (var k in n2ss.sliders) {
promises.push(new Promise(function (resolve) {
n2ss.ready(k, (function (slider) {
sliders.push(slider);
resolve();
}).bind(this));
}));
}
Promise.all(promises).then(resolve);
};
checkSliders();
});
promise.then(function () {
if (sliders.length === 1) {
var sliderElement = sliders[0].sliderElement,
marginElement = sliderElement.closest('.n2-ss-margin');
if (marginElement) {
var cs = window.getComputedStyle(marginElement);
setOption('margin', [cs.marginTop, cs.marginRight, cs.marginBottom, cs.marginLeft].join(' '));
marginElement.style.margin = '0';
}
}
for (var i = 0; i < sliders.length; i++) {
var slider = sliders[i];
slider.stages.done('ResizeFirst', (function (slider) {
if (slider.sliderElement.closest('ss3-force-full-width')) {
setOption('forceFullWidth', true);
}
if (slider.responsive.parameters.type === 'fullpage') {
setOption('fullPage', true);
}
if (sliders.length === 1) {
setOption('focusOffsetTop', slider.responsive.parameters.focus.offsetTop);
setOption('focusOffsetBottom', slider.responsive.parameters.focus.offsetBottom);
}
}).bind(this, slider));
slider.stages.done('HasDimension', function () {
document.querySelectorAll('a:not([target="_parent"]):not([target="_blank"])').forEach(function (a) {
a.target = '_parent';
});
});
}
var observer = new ResizeObserver((function (entries) {
setOption('height', entries[0].contentRect.height);
}).bind(this));
observer.observe(body);
});
var interval = setInterval(function () {
parent.postMessage({key: 'ready'}, "*");
}, 40);
window.addEventListener("message", function (e) {
var data = e.data;
switch (data["key"]) {
case "ackReady":
window.n2Height = data.windowInnerHeight;
window.n2OffsetTop = 0;
window.n2OffsetBottom = 0;
clearInterval(interval);
document.body.style.setProperty('--target-height', window.n2Height + 'px');
break;
case 'fullpage':
window.n2Height = data.height;
window.n2OffsetTop = data.offsetTop;
window.n2OffsetBottom = data.offsetBottom;
document.body.style.setProperty('--target-height', window.n2Height + 'px');
window.dispatchEvent(new Event('resize'));
break;
}
});
n2const.setLocation = function (l) {
parent.postMessage({
key: 'setLocation',
location: l
}, "*");
};
}
});
</script>
</body>
</html>
Admin/AbstractControllerAdmin.php 0000644 00000004552 15235664602 0013104 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin;
use Nextend\Framework\Asset\Js\Js;
use Nextend\Framework\Controller\Admin\AbstractAdminController;
use Nextend\Framework\Model\StorageSectionManager;
use Nextend\Framework\Platform\Platform;
use Nextend\Framework\Request\Request;
use Nextend\SmartSlider3\Application\Model\ModelSlidersXRef;
use Nextend\SmartSlider3\SmartSlider3Info;
abstract class AbstractControllerAdmin extends AbstractAdminController {
use TraitAdminUrl;
public function initialize() {
parent::initialize();
Js::addFirstCode('window.ss2lang = {};');
require_once dirname(__FILE__) . '/JavaScriptTranslation.php';
}
public function loadSliderManager() {
$groupID = Request::$REQUEST->getInt('sliderid', 0);
$storage = StorageSectionManager::getStorage('smartslider');
$options = array(
'userEmail' => Platform::getUserEmail(),
'skipNewsletter' => intval($storage->get('free', 'subscribeOnImport')) || intval($storage->get('free', 'dismissNewsletterSampleSliders')),
'exportAllUrl' => $this->getUrlDashboardExportAll($groupID),
'ajaxUrl' => $this->getAjaxUrlSlidesCreate(),
'previewUrl' => $this->getUrlPreviewIndex(0),
'importUrl' => $this->getUrlImport($groupID),
'paginationUrl' => $this->getUrlPaginator()
);
Js::addInline("new _N2.ManageSliders('" . $groupID . "', " . json_encode($options) . ", " . json_encode(SmartSlider3Info::shouldSkipLicenseModal()) . ");");
}
public function redirectToSliders() {
$this->redirect($this->getUrlDashboard());
}
/**
* @param int $sliderID
*
* @return bool
*/
protected function getGroupData($sliderID) {
$groupID = Request::$REQUEST->getInt('groupID');
$xref = new ModelSlidersXRef($this);
$groups = $xref->getGroups($sliderID, 'published');
$currentGroup = false;
foreach ($groups as $group) {
if ($group['group_id'] == $groupID) {
$currentGroup = $group;
break;
}
}
if ($currentGroup === false) {
$currentGroup = $groups[0];
}
return $currentGroup;
}
} Admin/ApplicationTypeAdmin.php 0000644 00000014117 15235664602 0012400 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin;
use Exception;
use Nextend\Framework\Application\AbstractApplicationType;
use Nextend\Framework\Asset\Css\Css;
use Nextend\Framework\Asset\Js\Js;
use Nextend\Framework\Browse\ControllerAjaxBrowse;
use Nextend\Framework\Content\ControllerAjaxContent;
use Nextend\Framework\Font\ControllerAjaxFont;
use Nextend\Framework\Image\ControllerAjaxImage;
use Nextend\Framework\Image\Image;
use Nextend\Framework\Platform\Platform;
use Nextend\Framework\Router\Router;
use Nextend\Framework\Style\ControllerAjaxStyle;
use Nextend\SmartSlider3\Application\Admin\Generator\ControllerAjaxGenerator;
use Nextend\SmartSlider3\Application\Admin\Generator\ControllerGenerator;
use Nextend\SmartSlider3\Application\Admin\GoPro\ControllerGoPro;
use Nextend\SmartSlider3\Application\Admin\Help\ControllerHelp;
use Nextend\SmartSlider3\Application\Admin\Layout\AbstractLayoutMenu;
use Nextend\SmartSlider3\Application\Admin\Preview\ControllerPreview;
use Nextend\SmartSlider3\Application\Admin\Settings\ControllerAjaxSettings;
use Nextend\SmartSlider3\Application\Admin\Settings\ControllerSettings;
use Nextend\SmartSlider3\Application\Admin\Slider\ControllerAjaxSlider;
use Nextend\SmartSlider3\Application\Admin\Slider\ControllerSlider;
use Nextend\SmartSlider3\Application\Admin\Sliders\ControllerAjaxSliders;
use Nextend\SmartSlider3\Application\Admin\Sliders\ControllerSliders;
use Nextend\SmartSlider3\Application\Admin\Slides\ControllerAjaxSlides;
use Nextend\SmartSlider3\Application\Admin\Slides\ControllerSlides;
use Nextend\SmartSlider3\Application\Admin\Update\ControllerUpdate;
use Nextend\SmartSlider3\Application\Admin\Visuals\ControllerAjaxCss;
use Nextend\SmartSlider3\BackgroundAnimation\ControllerAjaxBackgroundAnimation;
use Nextend\SmartSlider3\Platform\Joomla\JoomlaShim;
use Nextend\SmartSlider3\Platform\SmartSlider3Platform;
use Nextend\SmartSlider3\SmartSlider3Info;
class ApplicationTypeAdmin extends AbstractApplicationType {
use TraitAdminUrl;
protected $key = 'admin';
protected function createRouter() {
$this->router = new Router(SmartSlider3Platform::getAdminUrl(), SmartSlider3Platform::getAdminAjaxUrl(), SmartSlider3Platform::getNetworkAdminUrl());
}
public function setLayout($layout) {
parent::setLayout($layout);
if ($this->layout instanceof AbstractLayoutMenu) {
$this->layout->addBreadcrumb(n2_('Dashboard'), 'ssi_16 ssi_16--dashboard', $this->getUrlDashboard());
}
Js::addGlobalInline("window.N2SS3VERSION='" . SmartSlider3Info::$version . "';");
}
protected function getControllerSliders() {
return new ControllerSliders($this);
}
protected function getControllerAjaxSliders() {
return new ControllerAjaxSliders($this);
}
protected function getControllerSlider() {
return new ControllerSlider($this);
}
protected function getControllerAjaxSlider() {
return new ControllerAjaxSlider($this);
}
protected function getControllerSlides() {
return new ControllerSlides($this);
}
protected function getControllerAjaxSlides() {
return new ControllerAjaxSlides($this);
}
protected function getControllerGenerator() {
return new ControllerGenerator($this);
}
protected function getControllerAjaxGenerator() {
return new ControllerAjaxGenerator($this);
}
protected function getControllerPreview() {
return new ControllerPreview($this);
}
protected function getControllerSettings() {
return new ControllerSettings($this);
}
protected function getControllerAjaxSettings() {
return new ControllerAjaxSettings($this);
}
protected function getControllerHelp() {
return new ControllerHelp($this);
}
protected function getControllerGoPro() {
return new ControllerGoPro($this);
}
protected function getControllerAjaxBackgroundAnimation() {
return new ControllerAjaxBackgroundAnimation($this);
}
protected function getControllerAjaxFont() {
return new ControllerAjaxFont($this);
}
protected function getControllerAjaxStyle() {
return new ControllerAjaxStyle($this);
}
protected function getControllerAjaxCss() {
return new ControllerAjaxCss($this);
}
protected function getControllerAjaxImage() {
return new ControllerAjaxImage($this);
}
protected function getControllerAjaxContent() {
return new ControllerAjaxContent($this);
}
protected function getControllerUpdate() {
return new ControllerUpdate($this);
}
protected function getControllerAjaxBrowse() {
return new ControllerAjaxBrowse($this);
}
protected function getDefaultController($controllerName, $ajax = false) {
if ($controllerName !== 'sliders') {
return $this->getControllerSliders();
}
throw new Exception('Missing default controller for application type.');
}
public function enqueueAssets() {
Js::addInline('_N2.AjaxHelper.addAdminUrl(' . json_encode($this->getKey()) . ', ' . json_encode($this->createAjaxUrl('/')) . ');');
JS::addInline('_N2.BrowserCompatibility(' . json_encode($this->getUrlHelpBrowserIncompatible()) . ');');
parent::enqueueAssets();
if (Platform::isAdmin()) {
Js::addGlobalInline('window.N2SS3C="' . SmartSlider3Info::$campaign . '";');
}
Js::addGlobalInline('window.N2Joomla4=' . JoomlaShim::$isJoomla4 . ';');
Image::enqueueHelper();
static $once;
if ($once != null) {
return;
}
$once = true;
$path = self::getAssetsPath();
Css::addStaticGroup($path . '/dist/smartslider-admin.min.css', 'smartslider-admin');
Js::addStaticGroup($path . '/dist/smartslider-backend.min.js', 'smartslider-backend');
}
} Admin/JavaScriptTranslation.php 0000644 00000014153 15235664602 0012607 0 ustar 00 <?php
\Nextend\Framework\Localization\Localization::addJS(array("%s or newer required for this feature.","Above %s pixels.","Action","Activate","Activate Smart Slider 3 Pro","Activation is required to unlock all features!","Add animation","Add keyframe","Add Layer","Add post","Adjust","Advanced","Align (Absolute)","All","All layers, all devices","All layers, current device","An event you use to trigger layer animation(s) with","Animated heading","Animation","Animation tab","Are you sure?","Area","Arrows","Audio","Auto","Autoplay duration","Backward","Before After","Below %s pixels.","Between %s and %s pixels.","Block","bottom","Bottom","Boxed","Button","Cancel","Caption","Carousel","Center","Change group","Change slider type","Changing your slider type is irreversible. After changing your slider type, %syou will lose all slider type related settings%s.","Child layers","Choose folder","Choose images","Circle counter","Clean HTML","Clear device specific settings","Clear guides","Close","Column","Content","Content List - One Per Line","Content tab","Convert","Convert to slide","Copy","Copy slide to","Countdown","Counter","Create","Create a New Project","Create group","Create new project","Current layer, all devices","Current layer, current device","Current path","Dashboard","Data","Days","Delete","Delete permanently","delete these slides","delete this slide","delete this slider","Deleted.","Desktop","Direction","Disabled","Done","Drop files here","Duplicate","Edit","Edit generator","Edit Slider","Editor settings","Empty","empty the trash","Enabled","Event name","Examples","Filter","Find image","Find link","Forward","Full page","Full width","General","Go Pro","Go to slide","Go to slide ID","Got it","Group","Group created","Group name","Groups","Guide settings","Heading","Height","Hide on","Highlighted heading","Hours","HTML","Icon","Icon not found","Icons","Iframe","Image","Image area","Image box","Image field can not be empty!","Input","Insert","Insert a slider into your content","Insert group","Join more than 120,000 subscribers and get access to the latest slider templates, tips, tutorials and other exclusive contents directly to your inbox.","Join The Smart Slider 3 Community","Joomla module","Keyboard shortcuts","Keyframe","Landscape","Laptop","Large desktop","Large mobile","Large tablet","Layer","Layer Animation - Basic","Layer Animation - Reveal","Layer design options affect every device. If you need to make responsive adjustments, look for the options with the device icon.","Layer List","Layer(s)","Layout","left","Left","Lightbox","List","Load style","Loop","Loops %s and returns to starting slide.","Loops %s and stops before starting slide.","Margin","Max width","Middle","Minutes","Mobile","Move (Absolute)","Move to trash","My project","Name","Next slide","No","No file selected.","None","Notice","Numeric keys","Off","On","Oops, Something Went Wrong","Open docs","Open/Close","or import your own files","Orientation","Outer %s","Overwrite preset","Padding","Parent","Parent directory","Paste","Pick the align point of the child layer!","Pick the align point of the parent layer!","Pick the parent layer!","Play animations","Please fill the name field!","Please select a Post first!","Portrait","Posts","Preset","Preset deleted.","Preset saved.","Preview","Previous slide","Pro","Progress bar","Project type","Publish","Records","Redo","Register Smart Slider 3 Pro on this domain to enable auto update, slider templates and slide library.","Remove animations","Remove HTML","Remove line breaks","Remove links","Rename","Reset style to default","Respect words","Result","right","Right","Round to 5px","Row","Ruler","Save","Save as","Save as New","Save style as new preset","Saved.","Scroll to","Scroll to alias","Scrolls to the bottom of the page.","Scrolls to the top of the page.","Search","Search keyword","Seconds","Select","Select image","Select Slider","Select the slider you want to insert.","Set","Set as first","Settings","Show/Hide in editor","Showcase","Simple","Size","Skip","Slide","Slide event","Slide height","Slide ID","Slide index","slide index: 2 %s direction: backward","slide index: 5 %s direction: forward","Slide title","Slide width","Slider","Slider alias","Slider alias set at Slider settings > General","Slider type","Smart Slider 3 activated!","Smart snap","Special Zero","Split by Chars","Start a new project from scratch and build exactly what you’ve imagined. You can easily customize every pixels and create anything with layers.","Start with a Template","Start with a template and make it your own with the innovative drag and drop interface. You can choose from hundreds of premade templates.","Static","Strict","Style tab","Subscribe","Success","Switches %s slide(s).","Switches to the %s. slide.","Switches to the fifth slide as if the next arrow was pressed","Switches to the second slide as if the previous arrow was pressed","Switches to the slide with the #2 ID as if the previous arrow was pressed","Switches to the slide with the #5 ID as if the next arrow was pressed","Tablet","Text","Text animation in","Text animation out","The changes you made will be lost if you navigate away from this page.","The deletion is irreversible, and it's not possible to recover %s.","The image is empty","Theme","There is no layer available to be parent of the current layer!","This block is not available in the free version. %s","This section requires activated Pro version.","This slide is hidden on the following devices: %s","Timeline","Titles - One Per Line","top","Top","Top and bottom","Transition","Undo","Unexpected response","Unpublish","Up","Upgrade to Pro","URL","Use default selector","Use Joomla selector","Use our powerful visual editor, or simply import one of our existing template.","Video","View","What do you want to create today?","Width","You can use any jQuery selector to scroll to a specific element on the page. Example: \"#pricing\" scrolls to the element with the id of \"pricing\".","You can use presets to save style settings for later use. Clicking on any preset will load its styling to your current layer, and the previous style settings will be lost.","You have not created any presets for this layer yet.","You're about to %s. ")); Admin/TraitAdminUrl.php 0000644 00000040502 15235664602 0011036 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin;
use Joomla\CMS\Uri\Uri;
use Nextend\Framework\Pattern\MVCHelperTrait;
trait TraitAdminUrl {
/** @var MVCHelperTrait */
protected $MVCHelper;
public function getUrlGettingStarted() {
return $this->createUrl(array(
"sliders/gettingstarted"
));
}
public function getUrlGettingStartedDontShow() {
return $this->createUrl(array(
"sliders/gettingStartedDontShow"
));
}
public function getUrlDashboard() {
return $this->createUrl(array(
"sliders/index"
));
}
public function getUrlPaginator() {
return $this->createAjaxUrl(array(
'sliders/pagination',
));
}
public function getUrlDashboardOrderBy($orderBy, $direction, $page = null, $limit = null) {
$args = array();
$args[$orderBy] = $direction;
$args['pageIndex'] = $page;
$args['limit'] = $limit;
return $this->createAjaxUrl(array(
'sliders/orderby',
$args
), true);
}
public function getUrlDashboardExportAll($groupID) {
return $this->createUrl(array(
"sliders/exportAll",
array(
'currentGroupID' => $groupID,
'sliders' => array()
)
), true);
}
public function getAjaxUrlHideReview() {
return $this->createAjaxUrl(array(
'sliders/HideReview'
));
}
public function getUrlHidePromoUpgrade() {
return $this->createUrl(array(
'sliders/hidePromoUpgrade'
), true);
}
/**
* @return string
*/
public function getUrlTrash() {
return $this->createUrl(array(
"sliders/trash"
));
}
/**
* @return string
*/
public function getUrlImport($groupID = 0) {
return $this->createUrl(array(
"sliders/import",
array(
'groupID' => $groupID
)
));
}
/**
* @return string
*/
public function getAjaxUrlImport($groupID = 0) {
return $this->createAjaxUrl(array(
"sliders/import",
array(
'groupID' => $groupID
)
));
}
/**
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getUrlSliderEdit($sliderID, $groupID = 0) {
return $this->createUrl(array(
"slider/edit",
array(
'sliderid' => $sliderID,
'groupID' => $groupID
)
));
}
public function getAjaxUrlSliderEdit($sliderID) {
return $this->createAjaxUrl(array(
"slider/edit",
array(
'sliderid' => $sliderID
)
));
}
/**
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getUrlSliderSimpleEdit($sliderID, $groupID = 0) {
return $this->createUrl(array(
"slider/simpleedit",
array(
'sliderid' => $sliderID,
'groupID' => $groupID
)
));
}
/**
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getUrlSliderSimpleEditAddSlide($sliderID, $groupID = 0) {
return $this->createUrl(array(
"slider/simpleeditaddslide",
array(
'sliderid' => $sliderID,
'groupID' => $groupID
)
));
}
/**
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getUrlSliderMoveToTrash($sliderID, $groupID) {
return $this->createUrl(array(
'slider/trash',
array(
'sliderid' => $sliderID,
'groupID' => $groupID
)
), true);
}
/**
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getUrlSliderDuplicate($sliderID, $groupID) {
return $this->createUrl(array(
'slider/duplicate',
array(
'sliderid' => $sliderID,
'groupID' => $groupID
)
), true);
}
/**
* @param int $sliderID
*
* @return string
*/
public function getUrlSliderExport($sliderID) {
return $this->createUrl(array(
'slider/export',
array(
'sliderid' => $sliderID
)
), true);
}
/**
* @param int $sliderID
*
* @return string
*/
public function getUrlSliderExportHtml($sliderID) {
return $this->createUrl(array(
'slider/exporthtml',
array(
'sliderid' => $sliderID
)
), true);
}
/**
* @param int $sliderID
*
* @return string
*/
public function getUrlSliderClearCache($sliderID) {
return $this->createUrl(array(
'slider/clearcache',
array(
'sliderid' => $sliderID
)
), true);
}
/**
* @param int $sliderID
*
* @return string
*/
public function getUrlPreviewIndex($sliderID) {
return $this->createUrl(array(
"preview/index",
array(
'sliderid' => $sliderID
)
), true);
}
public function getUrlPreviewFull($sliderID) {
return $this->createUrl(array(
"preview/full",
array(
'sliderid' => $sliderID
)
), true);
}
/**
* @param int $sliderID
* @param bool|string $slideID
*
* @return string
*/
public function getUrlPreviewSlider($sliderID, $slideID = false) {
$args = array(
'sliderid' => $sliderID
);
if ($slideID) {
$args['slideId'] = $slideID;
}
return $this->createUrl(array(
"preview/slider",
$args
), true);
}
/**
* @param int $generatorID
*
* @return string
*/
public function getUrlPreviewGenerator($generatorID) {
return $this->createUrl(array(
"preview/generator",
array(
'generator_id' => $generatorID
)
), true);
}
public function getUrlSlidesUniversal($sliderID, $groupID) {
return $this->createUrl(array(
"slides/index",
array(
'groupID' => $groupID,
'sliderid' => $sliderID
)
));
}
public function getAjaxUrlSlidesUniversal($sliderID, $groupID) {
return $this->createAjaxUrl(array(
"slides/index",
array(
'groupID' => $groupID,
'sliderid' => $sliderID
)
));
}
public function getAjaxUrlSlidesCreate() {
return $this->createAjaxUrl(array(
"slider/create"
));
}
public function getUrlSlideEdit($slideID, $sliderID, $groupID) {
return $this->createUrl(array(
"slides/edit",
array(
'groupID' => $groupID,
'sliderid' => $sliderID,
'slideid' => $slideID
)
));
}
public function getUrlSlidePublish($slideID, $sliderID, $groupID) {
return $this->createUrl(array(
"slides/publish",
array(
'groupID' => $groupID,
'sliderid' => $sliderID,
'slideid' => $slideID
)
), true);
}
public function getUrlSlideUnPublish($slideID, $sliderID, $groupID) {
return $this->createUrl(array(
"slides/unpublish",
array(
'groupID' => $groupID,
'sliderid' => $sliderID,
'slideid' => $slideID
)
), true);
}
public function getUrlGeneratorCreate($sliderID, $groupID) {
return $this->createUrl(array(
"generator/create",
array(
'sliderid' => $sliderID,
'groupID' => $groupID
)
));
}
/**
* @param string $generatorGroupName
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getUrlGeneratorCheckConfiguration($generatorGroupName, $sliderID, $groupID) {
return $this->createUrl(array(
"generator/checkConfiguration",
array(
'sliderid' => $sliderID,
'groupID' => $groupID,
'group' => $generatorGroupName
)
));
}
/**
* @param string $generatorGroupName
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getAjaxUrlGeneratorCheckConfiguration($generatorGroupName, $sliderID, $groupID) {
return $this->createAjaxUrl(array(
"generator/checkConfiguration",
array(
'sliderid' => $sliderID,
'groupID' => $groupID,
'group' => $generatorGroupName
)
));
}
/**
* @param string $generatorGroupName
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getUrlGeneratorCreateStep2($generatorGroupName, $sliderID, $groupID) {
return $this->createUrl(array(
"generator/createStep2",
array(
'sliderid' => $sliderID,
'groupID' => $groupID,
'group' => $generatorGroupName
)
));
}
/**
* @param string $generatorGroupName
* @param string $generatorTypeName
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getUrlGeneratorCreateSettings($generatorGroupName, $generatorTypeName, $sliderID, $groupID) {
return $this->createUrl(array(
"generator/createSettings",
array(
'sliderid' => $sliderID,
'groupID' => $groupID,
'group' => $generatorGroupName,
'type' => $generatorTypeName
)
));
}
/**
* @param string $generatorGroupName
* @param string $generatorTypeName
* @param int $sliderID
* @param int $groupID
*
* @return string
*/
public function getAjaxUrlGeneratorCreateSettings($generatorGroupName, $generatorTypeName, $sliderID, $groupID) {
return $this->createAjaxUrl(array(
"generator/createSettings",
array(
'sliderid' => $sliderID,
'groupID' => $groupID,
'group' => $generatorGroupName,
'type' => $generatorTypeName
)
));
}
public function getUrlGeneratorEdit($generatorID, $groupID) {
return $this->createUrl(array(
"generator/edit",
array(
'generator_id' => $generatorID,
'groupID' => $groupID
)
));
}
public function getAjaxUrlGeneratorEdit($generatorID, $groupID) {
return $this->createAjaxUrl(array(
"generator/edit",
array(
'generator_id' => $generatorID,
'groupID' => $groupID
)
));
}
/**
*
* @return string
*/
public function getUrlSettingsDefault() {
return $this->createUrl(array(
'settings/default'
));
}
/**
*
* @return string
*/
public function getAjaxUrlSettingsDefault() {
return $this->createAjaxUrl(array(
'settings/default'
));
}
/**
*
* @return string
*/
public function getUrlSettingsClearCache() {
return $this->createUrl(array(
'settings/clearcache',
));
}
/**
*
* @return string
*/
public function getAjaxUrlSettingsClearCache() {
return $this->createAjaxUrl(array(
'settings/clearcache',
));
}
/**
*
* @return string
*/
public function getUrlSettingsFramework() {
return $this->createUrl(array(
'settings/framework'
));
}
/**
*
* @return string
*/
public function getAjaxUrlSettingsFramework() {
return $this->createAjaxUrl(array(
'settings/framework'
));
}
/**
*
* @return string
*/
public function getUrlSettingsFonts() {
return $this->createUrl(array(
'settings/fonts'
));
}
/**
*
* @return string
*/
public function getAjaxUrlSettingsFonts() {
return $this->createAjaxUrl(array(
'settings/fonts'
));
}
/**
*
* @return string
*/
public function getUrlSettingsItemDefaults() {
return $this->createUrl(array(
'settings/itemDefaults'
));
}
/**
*
* @return string
*/
public function getAjaxUrlSettingsItemDefaults() {
return $this->createAjaxUrl(array(
'settings/itemDefaults'
));
}
/**
* @param string $generatorName
*
* @return string
*/
public function getUrlSettingsGenerator($generatorName) {
return $this->createUrl(array(
'settings/generatorconfigure',
array(
'group' => $generatorName
)
));
}
public function getAjaxUrlSettingsGenerator($generatorName) {
return $this->createAjaxUrl(array(
'settings/generatorconfigure',
array(
'group' => $generatorName
)
));
}
/**
*
* @return string
*/
public function getUrlHelp() {
return $this->createUrl(array(
'help/index'
));
}
/**
*
* @return string
*/
public function getUrlHelpBrowserIncompatible() {
return $this->createUrl(array(
'help/browserincompatible'
));
}
/**
*
* @return string
*/
public function getUrlHelpTestApi() {
return $this->createUrl(array(
'help/testApi'
));
}
/**
*
* @return string
*/
public function getUrlHelpRepairDatabase() {
$currentUrl = Uri::getInstance();
$currentUrl->setVar('repairss3', 1);
return $currentUrl;
}
public function getUrlUpdateDownload() {
return $this->createUrl(array(
'update/update'
), true);
}
public function getUrlDeauthorizeLicense() {
return $this->createUrl(array('license/deauthorize'), true);
}
public function getAjaxUrlLicenseAdd() {
return $this->createAjaxUrl(array(
'license/add'
));
}
public function getAjaxUrlImage() {
return $this->createAjaxUrl(array(
'image/index'
));
}
public function getAjaxUrlBrowse() {
return $this->createAjaxUrl(array(
'browse/index'
));
}
public function getAjaxUrlContentSearchContent() {
return $this->createAjaxUrl(array(
'content/searchcontent'
));
}
public function getAjaxUrlSubscribed() {
return $this->createAjaxUrl(array(
'settings/subscribed'
));
}
} Admin/Visuals/ControllerAjaxCss.php 0000644 00000005541 15235664602 0013351 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Visuals;
use Nextend\Framework\Controller\Admin\AdminAjaxController;
use Nextend\Framework\Notification\Notification;
use Nextend\Framework\Request\Request;
use Nextend\Framework\Style\ModelCss;
class ControllerAjaxCss extends AdminAjaxController {
public function getModel() {
return new ModelCss($this);
}
public function actionLoadVisuals() {
$this->validateToken();
$type = Request::$REQUEST->getCmd('type');
$this->validateVariable(!empty($type), 'type');
$model = $this->getModel();
$visuals = $model->getVisuals($type);
if (is_array($visuals)) {
$this->response->respond(array(
'visuals' => $visuals
));
}
Notification::error(n2_('Unexpected error'));
$this->response->error();
}
public function actionAddVisual() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$type = Request::$REQUEST->getCmd('type');
$this->validateVariable(!empty($type), 'type');
$model = $this->getModel();
if (($visual = $model->addVisual($type, 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');
$type = Request::$REQUEST->getCmd('type');
$this->validateVariable(!empty($type), 'type');
$visualId = Request::$REQUEST->getInt('visualId');
$this->validateVariable($visualId > 0, 'visual');
$model = $this->getModel();
if (($visual = $model->deleteVisual($type, $visualId))) {
$this->response->respond(array(
'visual' => $visual
));
}
Notification::error(n2_('Not editable'));
$this->response->error();
}
public function actionChangeVisual() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$type = Request::$REQUEST->getCmd('type');
$this->validateVariable(!empty($type), 'type');
$visualId = Request::$REQUEST->getInt('visualId');
$this->validateVariable($visualId > 0, 'visual');
$model = $this->getModel();
if (($visual = $model->changeVisual($type, $visualId, Request::$REQUEST->getVar('value')))) {
$this->response->respond(array(
'visual' => $visual
));
}
Notification::error(n2_('Unexpected error'));
$this->response->error();
}
} Admin/Update/ControllerUpdate.php 0000644 00000000761 15235664602 0013032 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Update;
use Joomla\CMS\Router\Route;
use Nextend\SmartSlider3\Application\Admin\AbstractControllerAdmin;
class ControllerUpdate extends AbstractControllerAdmin {
public function actionUpdate() {
if ($this->validateToken()) {
header('LOCATION: ' . Route::_('index.php?option=com_installer&view=update', false));
exit;
}
$this->redirectToSliders();
}
} Admin/Slides/ControllerAjaxSlides.php 0000644 00000027420 15235664602 0013641 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Slides;
use Nextend\Framework\Controller\Admin\AdminAjaxController;
use Nextend\Framework\Filesystem\Filesystem;
use Nextend\Framework\Misc\Base64;
use Nextend\Framework\Notification\Notification;
use Nextend\Framework\Request\Request;
use Nextend\SmartSlider3\Application\Admin\TraitAdminUrl;
use Nextend\SmartSlider3\Application\Model\ModelSliders;
use Nextend\SmartSlider3\Application\Model\ModelSlides;
use Nextend\SmartSlider3\Settings;
use Nextend\SmartSlider3\Slider\Feature\Optimize;
use Nextend\SmartSlider3\Slider\Slide;
use Nextend\SmartSlider3\Slider\Slider;
class ControllerAjaxSlides extends AdminAjaxController {
use TraitAdminUrl;
public function actionEdit() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$groupID = Request::$REQUEST->getInt('groupID', 0);
$this->validateVariable($groupID >= 0, 'groupID');
$slidersModel = new ModelSliders($this);
$sliderId = Request::$REQUEST->getInt('sliderid');
$slider = $slidersModel->get($sliderId);
$this->validateDatabase($slider);
$slidesModel = new ModelSlides($this);
$this->validateDatabase($slidesModel->get(Request::$REQUEST->getInt('slideid')));
$response = array();
$file = Request::$FILES->getVar('slide');
if (Settings::get('slide-as-file', 0) && $file !== null) {
$slide = Filesystem::readFile($file['tmp_name']);
} else {
$slide = Request::$REQUEST->getVar('slide');
}
$guides = Request::$REQUEST->getVar('guides');
if ($slidesModel->save(Request::$REQUEST->getInt('slideid'), $slide, $guides)) {
Notification::success(n2_('Slide saved.'));
if (Request::$REQUEST->getInt('generatorStatic') == 1) {
$slideCount = $slidesModel->convertDynamicSlideToSlides(Request::$REQUEST->getInt('slideid'));
if ($slideCount) {
Notification::success(sprintf(n2_('%d static slides generated.'), $slideCount));
$this->response->redirect($this->getUrlSliderEdit($sliderId, $groupID));
}
}
}
$this->response->respond($response);
}
public function actionRename() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$slideID = Request::$REQUEST->getInt('slideid');
$this->validateVariable($slideID > 0, 'Slide');
$title = Request::$REQUEST->getVar('title');
$slidersModel = new ModelSlides($this);
$slidersModel->setTitle($slideID, $title);
Notification::success(n2_('Slide renamed.'));
$this->response->respond();
}
public function actionFirst() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$slideId = Request::$REQUEST->getInt('id');
$this->validateVariable($slideId > 0, 'Slide id');
$slidesModel = new ModelSlides($this);
$slidesModel->first($slideId);
Notification::success(n2_('First slide changed.'));
$this->response->respond();
}
public function actionConvertToSlide() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$slideId = Request::$REQUEST->getInt('slideid');
$this->validateVariable($slideId > 0, 'Slide id');
$slidesModel = new ModelSlides($this);
$slidesModel->convertToSlide($slideId);
Notification::success(n2_('Static overlay converted to slide.'));
$this->response->respond();
}
public function actionPublish() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$ids = array_map('intval', array_filter((array)Request::$REQUEST->getVar('slides'), 'is_numeric'));
$this->validateVariable(count($ids), 'Slides');
$slidesModel = new ModelSlides($this);
foreach ($ids as $id) {
if ($id > 0) {
$slidesModel->publish($id);
}
}
Notification::success(n2_('Slide published.'));
$this->response->respond();
}
public function actionUnPublish() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$ids = array_map('intval', array_filter((array)Request::$REQUEST->getVar('slides'), 'is_numeric'));
$this->validateVariable(count($ids), 'Slides');
$slidesModel = new ModelSlides($this);
foreach ($ids as $id) {
if ($id > 0) {
$slidesModel->unPublish($id);
}
}
Notification::success(n2_('Slide unpublished.'));
$this->response->respond();
}
public function actionOrder() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$sliderid = Request::$REQUEST->getInt('sliderid');
$this->validateVariable($sliderid > 0, 'Slider');
$slidesModel = new ModelSlides($this);
$result = $slidesModel->order($sliderid, Request::$REQUEST->getVar('slideorder'));
$this->validateDatabase($result);
Notification::success(n2_('Slide order saved.'));
$this->response->respond();
}
public function actionCopy() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$groupID = Request::$REQUEST->getInt('targetGroupID', 0);
$this->validateVariable($groupID >= 0, 'targetGroupID');
$slideId = Request::$REQUEST->getInt('slideid');
$this->validateVariable($slideId > 0, 'Slide');
$sliderID = Request::$REQUEST->getInt('targetSliderID');
$this->validateVariable($sliderID > 0, 'Slider ID');
$slidesModel = new ModelSlides($this);
$newSlideId = $slidesModel->copyTo($slideId, false, $sliderID);
$slide = $slidesModel->get($newSlideId);
$this->validateDatabase($slide);
Notification::success(n2_('Slide(s) copied.'));
$this->response->redirect($this->getUrlSliderEdit($sliderID, $groupID));
}
public function actionCopySlides() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$groupID = Request::$REQUEST->getInt('targetGroupID', 0);
$this->validateVariable($groupID >= 0, 'targetGroupID');
$ids = array_map('intval', array_filter((array)Request::$REQUEST->getVar('slides'), 'is_numeric'));
$this->validateVariable(count($ids), 'Slides');
$sliderID = Request::$REQUEST->getInt('targetSliderID');
$this->validateVariable($sliderID > 0, 'Slider ID');
$slidesModel = new ModelSlides($this);
foreach ($ids as $id) {
$slidesModel->copyTo($id, false, $sliderID);
}
Notification::success(n2_('Slide(s) copied.'));
$this->response->redirect($this->getUrlSliderEdit($sliderID, $groupID));
}
public function actionDuplicate() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$groupID = Request::$REQUEST->getInt('groupID');
$this->validateVariable($groupID >= 0, 'groupID');
$slideId = Request::$REQUEST->getInt('slideid');
$this->validateVariable($slideId > 0, 'Slide');
$slidesModel = new ModelSlides($this);
$newSlideId = $slidesModel->copyTo($slideId);
$slide = $slidesModel->get($newSlideId);
$this->validateDatabase($slide);
Notification::success(n2_('Slide duplicated.'));
$sliderObj = new Slider($this, $slide['slider'], array(), true);
$sliderObj->initSlider();
$optimize = new Optimize($sliderObj);
$slideObj = new Slide($sliderObj, $slide);
$slideObj->initGenerator();
$slideObj->fillSample();
$view = new ViewAjaxSlideBox($this);
$view->setGroupID($groupID);
$view->setSlider($sliderObj);
$view->setSlide($slideObj);
$view->setOptimize($optimize);
$this->response->respond($view->display());
}
public function actionDelete() {
$this->validateToken();
$this->validatePermission('smartslider_delete');
$ids = array_map('intval', array_filter((array)Request::$REQUEST->getVar('slides'), 'is_numeric'));
$this->validateVariable(count($ids), 'Slide');
$slidesModel = new ModelSlides($this);
foreach ($ids as $id) {
if ($id > 0) {
$slidesModel->delete($id);
}
}
Notification::success(n2_('Slide deleted.'));
$this->response->respond();
}
public function actionCreate() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$type = Request::$REQUEST->getVar('type');
$groupID = Request::$REQUEST->getInt('groupID');
$this->validateVariable($groupID >= 0, 'groupID');
$sliderId = Request::$REQUEST->getInt('sliderid');
$this->validateVariable($sliderId > 0, 'Slider');
$slidesModel = new ModelSlides($this);
$createdSlidesID = array();
switch ($type) {
case 'image':
$images = json_decode(Base64::decode(Request::$REQUEST->getVar('images')), true);
$this->validateVariable(count($images), 'Images');
foreach ($images as $image) {
$createdSlidesID[] = $slidesModel->createQuickImage($image, $sliderId);
}
break;
case 'empty-slide':
$createdSlidesID[] = $slidesModel->createQuickEmptySlide($sliderId);
break;
case 'video':
$video = json_decode(urldecode(Base64::decode(Request::$REQUEST->getVar('video'))), true);
$this->validateVariable($video, 'Video');
$createdSlidesID[] = $slidesModel->createQuickVideo($video, $sliderId);
break;
case 'post':
$post = Request::$REQUEST->getVar('post');
$this->validateVariable($post, 'Post');
$createdSlidesID[] = $slidesModel->createQuickPost($post, $sliderId);
break;
case 'static-overlay':
$createdSlidesID[] = $slidesModel->createQuickStaticOverlay($sliderId);
break;
}
if (!empty($createdSlidesID)) {
$sliderObj = new Slider($this, $sliderId, array());
$sliderObj->initSlider();
$optimize = new Optimize($sliderObj);
$responseBody = '';
foreach ($createdSlidesID as $slideID) {
$slide = $slidesModel->get($slideID);
$slideObj = new Slide($sliderObj, $slide);
$slideObj->initGenerator();
$slideObj->fillSample();
$view = new ViewAjaxSlideBox($this);
$view->setGroupID($groupID);
$view->setSlider($sliderObj);
$view->setSlide($slideObj);
$view->setOptimize($optimize);
$responseBody .= $view->display();
}
if (count($createdSlidesID) > 1) {
Notification::success(n2_('Slides created.'));
} else {
Notification::success(n2_('Slide created.'));
}
$this->response->respond($responseBody);
} else {
Notification::error(n2_('Failed to create slides.'));
$this->response->respond();
}
}
} Admin/Slides/ControllerSlides.php 0000644 00000006107 15235664602 0013034 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Slides;
use Nextend\Framework\Notification\Notification;
use Nextend\Framework\Request\Request;
use Nextend\SmartSlider3\Application\Admin\AbstractControllerAdmin;
use Nextend\SmartSlider3\Application\Model\ModelSliders;
use Nextend\SmartSlider3\Application\Model\ModelSlides;
use Nextend\SmartSlider3\SmartSlider3Info;
class ControllerSlides extends AbstractControllerAdmin {
public function initialize() {
parent::initialize();
SmartSlider3Info::$forceDesktop = true;
SmartSlider3Info::$forceAllDevices = true;
}
public function actionEdit() {
if ($this->validatePermission('smartslider_edit')) {
$slidersModel = new ModelSliders($this);
$sliderID = Request::$REQUEST->getInt('sliderid');
$slider = $slidersModel->get($sliderID);
if ($this->validateDatabase($slider, false)) {
$slidesModel = new ModelSlides($this);
$slideID = Request::$REQUEST->getInt('slideid');
$slide = $slidesModel->get($slideID);
if ($slide) {
$groupData = $this->getGroupData($sliderID);
$view = new ViewSlidesEdit($this);
$view->setGroupData($groupData['group_id'], $groupData['title']);
$view->setSlider($slider);
$view->setSlide($slide);
$view->display();
} else {
$this->redirect($this->getUrlDashboard());
}
} else {
$this->redirect($this->getUrlDashboard());
}
}
}
public function actionDelete() {
if ($this->validateToken() && $this->validatePermission('smartslider_delete')) {
if ($slideId = Request::$REQUEST->getInt('slideid')) {
$slidesModel = new ModelSlides($this);
$slidesModel->delete($slideId);
}
$sliderId = Request::$REQUEST->getInt("sliderid");
if ($sliderId) {
$groupData = $this->getGroupData($sliderId);
$this->redirect($this->getUrlSliderEdit($sliderId, $groupData['group_id']));
}
$this->redirect($this->getUrlDashboard());
}
}
public function actionDuplicate() {
if ($this->validateToken() && $this->validatePermission('smartslider_edit')) {
if ($slideId = Request::$REQUEST->getInt('slideid')) {
$slidesModel = new ModelSlides($this);
$newSlideId = $slidesModel->copyTo($slideId);
Notification::success(n2_('Slide duplicated.'));
$sliderID = Request::$REQUEST->getInt("sliderid");
$groupData = $this->getGroupData($sliderID);
$this->redirect($this->getUrlSlideEdit($newSlideId, $sliderID, $groupData['group_id']));
}
$this->redirect($this->getUrlDashboard());
}
}
} Admin/Slides/ViewAjaxSlideBox.php 0000644 00000003566 15235664602 0012723 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Slides;
use Nextend\Framework\View\AbstractViewAjax;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Slide\SlideBox\BlockSlideBox;
use Nextend\SmartSlider3\Slider\Feature\Optimize;
use Nextend\SmartSlider3\Slider\Slide;
use Nextend\SmartSlider3\Slider\Slider;
class ViewAjaxSlideBox extends AbstractViewAjax {
protected $groupID = 0;
/** @var Slider */
protected $slider;
/** @var Slide */
protected $slide;
/** @var Optimize */
protected $optimize;
public function display() {
return $this->render('AjaxSlideBox');
}
public function renderSlideBlock() {
$blockSlideBox = new BlockSlideBox($this);
$blockSlideBox->setGroupID($this->groupID);
$blockSlideBox->setSlider($this->slider);
$blockSlideBox->setSlide($this->slide);
$blockSlideBox->setOptimize($this->optimize);
$blockSlideBox->display();
}
/**
* @param int $groupID
*/
public function setGroupID($groupID) {
$this->groupID = $groupID;
}
/**
* @return Slider
*/
public function getSlider() {
return $this->slider;
}
/**
* @param Slider $slider
*/
public function setSlider($slider) {
$this->slider = $slider;
}
/**
* @return Slide
*/
public function getSlide() {
return $this->slide;
}
/**
* @param Slide $slide
*/
public function setSlide($slide) {
$this->slide = $slide;
}
/**
* @return Optimize
*/
public function getOptimize() {
return $this->optimize;
}
/**
* @param Optimize $optimize
*/
public function setOptimize($optimize) {
$this->optimize = $optimize;
}
} Admin/Slides/ViewSlidesEdit.php 0000644 00000022725 15235664602 0012435 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Slides;
use Nextend\Framework\Request\Request;
use Nextend\Framework\Sanitize;
use Nextend\Framework\View\AbstractView;
use Nextend\SmartSlider3\Application\Admin\FormManager\FormManagerSlide;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Core\Header\BlockHeader;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Core\TopBarGroup\BlockTopBarGroup;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButton;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonBack;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonPlainIcon;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonSave;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonSpacer;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Slide\AddLayer\BlockAddLayer;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Slide\EditorOverlay\BlockEditorOverlay;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Slide\LayerWindow\BlockLayerWindow;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Slide\SlideManager\BlockSlideManager;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Slider\DeviceZoom\BlockDeviceZoom;
use Nextend\SmartSlider3\Application\Admin\Layout\LayoutEditor;
use Nextend\SmartSlider3\Application\Admin\TraitAdminUrl;
use Nextend\SmartSlider3\Application\Model\ModelSlides;
use Nextend\SmartSlider3\Slider\Admin\AdminSlider;
use Nextend\SmartSlider3\Slider\Slider;
class ViewSlidesEdit extends AbstractView {
use TraitAdminUrl;
/** @var LayoutEditor */
protected $layout;
/**
* @var BlockEditorOverlay
*/
protected $editorOverlay;
/** @var ModelSlides */
protected $model;
/**
* @var Slider
*/
protected $frontendSlider;
/**
* @var string contains already escaped data
*/
protected $renderedSlider;
protected $groupID = 0;
protected $groupTitle = '';
protected $slider;
protected $slide = false;
/**
* @var BlockHeader
*/
protected $blockHeader;
/**
* @var FormManagerSlide
*/
protected $formManager;
public function __construct($controller) {
parent::__construct($controller);
$this->model = new ModelSlides($this);
}
public function display() {
$locale = setlocale(LC_NUMERIC, 0);
setlocale(LC_NUMERIC, "C");
$this->layout = new LayoutEditor($this);
$this->editorOverlay = new BlockEditorOverlay($this);
$this->layout->setEditorOverlay($this->editorOverlay);
$this->frontendSlider = new AdminSlider($this->MVCHelper, Request::$GET->getInt('sliderid'), array(
'disableResponsive' => true
));
$this->frontendSlider->setEditedSlideID($this->getSlideID());
$this->frontendSlider->initSlider();
$this->frontendSlider->initSlides();
/**
* Layer window should be rendered before the slider render as layers items might add CSS and JS codes to it.
*/
$layerWindowBlock = new BlockLayerWindow($this);
$layerWindowBlock->setRenderableAdminSlider($this->frontendSlider);
$this->editorOverlay->setContentLayerWindow($layerWindowBlock->toHTML());
$this->frontendSlider->initAll();
$this->frontendSlider->addScript('new _N2.DeviceChanger(this);');
$this->renderedSlider = $this->frontendSlider->render();
$this->formManager = new FormManagerSlide($this, $this->groupID, $this->frontendSlider, $this->slide);
$this->layout->addBreadcrumb(n2_('Dashboard'), 'ssi_16 ssi_16--dashboard', $this->getUrlDashboard());
if ($this->groupID) {
$this->layout->addBreadcrumb(Sanitize::esc_html($this->groupTitle), 'ssi_16 ssi_16--folderclosed', $this->getUrlSliderEdit($this->groupID));
}
$this->layout->addBreadcrumb(Sanitize::esc_html($this->slider['title']), 'ssi_16 ssi_16--image', $this->getUrlSliderEdit($this->slider['id'], $this->groupID));
$this->addActiveBreadcrumb();
if (!empty($this->slide['generator_id'])) {
$this->layout->addBreadcrumb(n2_('Generator'), 'ssi_16 ssi_16--cog', $this->getUrlGeneratorEdit($this->slide['generator_id'], $this->groupID));
}
$slideManager = new BlockSlideManager($this);
$slideManager->setGroupID($this->groupID);
$slideManager->setSliderID($this->slider['id']);
$slideManager->setBreadcrumbOpener(true);
$this->editorOverlay->setSlideManager($slideManager);
$this->renderTopBar();
$blockAddLayer = new BlockAddLayer($this);
$blockAddLayer->setSliderType($this->frontendSlider->data->get('type'));
$this->editorOverlay->setBlockAddLayer($blockAddLayer);
$this->layout->addContent($this->render('Edit'));
$this->renderLayout();
setlocale(LC_NUMERIC, $locale);
}
protected function renderLayout() {
$this->layout->render();
}
protected function addActiveBreadcrumb() {
$breadCrumb = $this->layout->addBreadcrumb(n2_('Slides') . '<i class="ssi_16 ssi_16--selectarrow"></i>', 'ssi_16 ssi_16--slides', '#');
$breadCrumb->addClass('n2_nav_bar__breadcrumb_button_slides');
$breadCrumb->setIsActive(true);
}
private function renderTopBar() {
$topBar = $this->editorOverlay->getTopBar();
$buttonSave = new BlockButtonSave($this);
$buttonSave->addClass('n2_button--inactive');
$buttonSave->addClass('n2_slide_settings_save');
$topBar->addPrimaryBlock($buttonSave);
$buttonBack = new BlockButtonBack($this);
$buttonBack->setUrl($this->getUrlSliderEdit($this->getSliderID(), $this->groupID));
$buttonBack->addClass('n2_slide_settings_back');
$topBar->addPrimaryBlock($buttonBack);
if ($this->slide && $this->slide['generator_id'] > 0) {
$buttonStaticSave = new BlockButton($this);
$buttonStaticSave->setLabel(n2_('Static save'));
$buttonStaticSave->addClass('n2_slide_generator_static_save');
$topBar->addPrimaryBlock($buttonStaticSave);
}
$narrowGroup = new BlockTopBarGroup($this);
$narrowGroup->setNarrow();
$buttonRedo = new BlockButtonPlainIcon($this);
$buttonRedo->addClass('n2_top_bar_button_icon');
$buttonRedo->addClass('n2_ss_history_action');
$buttonRedo->addClass('n2_ss_history_action--redo');
$buttonRedo->setIcon('ssi_24 ssi_24--redo');
$buttonRedo->addAttribute('data-n2tip', n2_('Redo'));
$buttonRedo->addAttribute('data-n2tipv', -20);
$narrowGroup->addBlock($buttonRedo);
$buttonUndo = new BlockButtonPlainIcon($this);
$buttonUndo->addClass('n2_top_bar_button_icon');
$buttonUndo->addClass('n2_ss_history_action');
$buttonUndo->addClass('n2_ss_history_action--undo');
$buttonUndo->setIcon('ssi_24 ssi_24--undo');
$buttonUndo->addAttribute('data-n2tip', n2_('Undo'));
$buttonUndo->addAttribute('data-n2tipv', -20);
$narrowGroup->addBlock($buttonUndo);
$topBar->addPrimaryBlock($narrowGroup);
$spacer = new BlockButtonSpacer($this);
$spacer->setIsVisible(true);
$topBar->addPrimaryBlock($spacer);
$deviceZoom = new BlockDeviceZoom($this);
$topBar->addPrimaryBlock($deviceZoom);
$buttonPreview = new BlockButtonPlainIcon($this);
$buttonPreview->addAttribute('id', 'n2-ss-preview');
$buttonPreview->addClass('n2_top_bar_button_icon');
$buttonPreview->addClass('n2_top_bar_main__preview');
$buttonPreview->setIcon('ssi_24 ssi_24--preview');
$buttonPreview->addAttribute('data-n2tip', n2_('Preview'));
$buttonPreview->setUrl($this->getUrlPreviewIndex($this->getSliderID()));
$topBar->addPrimaryBlock($buttonPreview);
}
public function getModel() {
return $this->model;
}
/**
* @param int $groupID
* @param string $groupTitle
*/
public function setGroupData($groupID, $groupTitle) {
$this->groupID = $groupID;
$this->groupTitle = $groupTitle;
}
public function getSliderID() {
return $this->slider['id'];
}
/**
* @param array $slider
*/
public function setSlider($slider) {
$this->slider = $slider;
}
/**
* @param array $slide
*/
public function setSlide($slide) {
$this->slide = $slide;
}
public function getSlideID() {
return $this->slide['id'];
}
public function getAjaxUrl() {
if ($this->slide) {
return $this->createAjaxUrl(array(
'slides/edit',
array(
'groupID' => $this->groupID,
'sliderid' => $this->getSliderID(),
'slideid' => $this->getSlideID()
)
));
}
return $this->createAjaxUrl(array(
'slides/create',
array(
'groupID' => $this->groupID,
'sliderid' => $this->getSliderID(),
'slideid' => $this->getSlideID()
)
));
}
} Admin/Slides/Template/AjaxSlideBox.php 0000644 00000000215 15235664602 0013627 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Slides;
/**
* @var $this ViewAjaxSlideBox
*/
$this->renderSlideBlock(); Admin/Slides/Template/Edit.php 0000644 00000006567 15235664602 0012217 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Slides;
use Nextend\Framework\Asset\Js\Js;
use Nextend\Framework\Platform\Platform;
use Nextend\Framework\Request\Request;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Application\Model\ModelLicense;
use Nextend\SmartSlider3\Settings;
use Nextend\SmartSlider3\SmartSlider3Info;
use Nextend\SmartSlider3Pro\LayerAnimation\LayerAnimationStorage;
/**
* @var $this ViewSlidesEdit
*/
JS::addGlobalInline('document.documentElement.classList.add("n2_html--application-only");');
Js::addGlobalInline("window.ss3LayerAnimationPresets=" . LayerAnimationStorage::getInstance()
->getData() . ";");
$externals = esc_attr(Settings::get('external-css-files'));
if (!empty($externals)) {
$externals = explode("\n", $externals);
foreach ($externals as $external) {
echo "<link rel='stylesheet' href='" . esc_url($external) . "' type='text/css' media='all'>";
}
}
$slider = $this->frontendSlider;
$renderedSlider = $this->renderedSlider;
?>
<form id="n2-ss-form-slide-edit" action="#" method="post">
<?php
$this->formManager->render();
?>
</form>
<div id='n2-ss-slide-canvas-container' class='n2_slide_editor_slider'>
<div class="n2_slide_editor_slider__editor" style="width: <?php esc_attr($slider->features->responsive->sizes['desktopPortrait']['width']); ?>px">
<div class="n2_slide_editor_slider__editor_inner">
<?php
// PHPCS - Content already escaped
echo $renderedSlider; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</div>
</div>
</div>
<?php
$fillMode = $slider->params->get('backgroundMode', 'fill');
if ($fillMode == 'fixed' || $fillMode == 'tile') {
$fillMode = 'fill';
}
$options = array(
'isUploadDisabled' => defined('N2_IMAGE_UPLOAD_DISABLE'),
'slideBackgroundMode' => $fillMode,
'settingsGoProUrl' => SmartSlider3Info::getProUrlPricing(array(
'utm_source' => 'go-pro-button-editor-settings',
'utm_medium' => 'smartslider-' . Platform::getName() . '-' . SmartSlider3Info::$plan,
'utm_campaign' => SmartSlider3Info::$campaign
))
);
if (!defined('N2_IMAGE_UPLOAD_DISABLE')) {
$options['uploadUrl'] = $this->createAjaxUrl(array('browse/upload'));
$options['uploadDir'] = 'slider' . $slider->sliderId;
}
if (ModelLicense::getInstance()
->maybeActiveLazy()) {
$options['sectionLibraryFree'] = false;
$options['sectionLibraryUrl'] = 'https://smartslider3.com/slides/v2/pro2e4G2dR';
} else {
$options['sectionLibraryUrl'] = 'https://smartslider3.com/slides/v2/free';
}
JS::addInline('new _N2.SlideEdit(' . json_encode(array(
'ajaxUrl' => $this->getAjaxUrl(),
'slideAsFile' => intval(Settings::get('slide-as-file', 0)),
'nextendAction' => Request::$GET->getCmd('nextendaction'),
'previewInNewWindow' => !!Settings::get('preview-new-window', 0),
'previewUrl' => $this->getUrlPreviewSlider($slider->data->get('id'), $this->getSlideID()),
'sliderElementID' => $slider->elementId,
'slideEditorOptions' => $options
)) . ');');
Admin/Sliders/ControllerAjaxSliders.php 0000644 00000027454 15235664602 0014214 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Sliders;
use Nextend\Framework\Controller\Admin\AdminAjaxController;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Filesystem\Filesystem;
use Nextend\Framework\Misc\HttpClient;
use Nextend\Framework\Model\StorageSectionManager;
use Nextend\Framework\Notification\Notification;
use Nextend\Framework\Platform\Platform;
use Nextend\Framework\Request\Request;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\SmartSlider3\Application\Admin\TraitAdminUrl;
use Nextend\SmartSlider3\Application\Model\ModelSliders;
use Nextend\SmartSlider3\BackupSlider\ImportSlider;
use Nextend\SmartSlider3\Settings;
use RuntimeException;
class ControllerAjaxSliders extends AdminAjaxController {
use TraitAdminUrl;
public function actionList() {
$this->validateToken();
$parentID = Request::$REQUEST->getInt('parentID');
$this->validateVariable($parentID >= 0, 'parentID');
if ($parentID > 0) {
$orderBy = 'ordering';
$orderByDirection = 'ASC';
} else {
$orderBy = Settings::get('slidersOrder2', 'ordering');
$orderByDirection = Settings::get('slidersOrder2Direction', 'ASC');
}
$slidersModel = new ModelSliders($this);
$sliders = $slidersModel->getAll($parentID, 'published', $orderBy, $orderByDirection);
$data = array();
foreach ($sliders as $slider) {
$data[] = array(
'id' => $slider['id'],
'alias' => $slider['alias'],
'title' => $slider['title'],
'thumbnail' => $this->getSliderThumbnail($slider),
'isGroup' => $slider['type'] == 'group',
'childrenCount' => $slider['slides'] > 0 ? $slider['slides'] : 0
);
}
$this->response->respond($data);
}
private function getSliderThumbnail($slider) {
$thumbnail = $slider['thumbnail'];
if (empty($thumbnail)) {
return '';
} else {
return ResourceTranslator::toUrl($thumbnail);
}
}
public function actionOrder() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
$slidersModel = new ModelSliders($this);
$result = $slidersModel->order(Request::$REQUEST->getVar('groupID', 0), Request::$REQUEST->getVar('sliderorder'), Request::$REQUEST->getInt('isReversed', 1), Request::$REQUEST->getVar('orders', array()));
$this->validateDatabase($result);
Notification::success(n2_('Slider order saved.'));
$this->response->respond();
}
public function actionTrash() {
$this->validateToken();
$this->validatePermission('smartslider_delete');
$groupID = Request::$REQUEST->getInt('groupID', 0);
$this->validateVariable($groupID >= 0, 'groupID');
$ids = array_map('intval', array_filter((array)Request::$REQUEST->getVar('sliders'), 'is_numeric'));
$this->validateVariable(count($ids), 'Slider');
$slidersModel = new ModelSliders($this);
$isTrash = false;
$isUnlink = false;
foreach ($ids as $id) {
if ($id > 0) {
$mode = $slidersModel->trash($id, $groupID);
switch ($mode) {
case 'trash':
$isTrash = true;
break;
case 'unlink':
$isUnlink = true;
break;
}
}
}
if ($isTrash) {
Notification::success(n2_('Slider(s) moved to the trash.'));
}
if ($isUnlink) {
Notification::success(n2_('Slider(s) removed from the group.'));
}
$this->response->respond();
}
public function actionEmptyTrash() {
$this->validateToken();
$this->validatePermission('smartslider_delete');
$slidersModel = new ModelSliders($this);
$slidersInTrash = $slidersModel->getAll('*', 'trash');
foreach ($slidersInTrash as $slider) {
$slidersModel->deletePermanently($slider['id']);
}
Notification::success(n2_('Slider(s) deleted permanently from the trash.'));
$this->response->respond();
}
public function actionHideReview() {
$this->validateToken();
$this->validatePermission('smartslider_config');
StorageSectionManager::getStorage('smartslider')
->set('free', 'review', 1);
$this->response->respond();
}
public function actionSearch() {
$this->validateToken();
$this->validatePermission('smartslider_config');
$slidersModel = new ModelSliders($this);
$keyword = Request::$REQUEST->getVar('keyword', '');
$sliders = array();
$url = parse_url($keyword);
$baseUrl = parse_url(Platform::getSiteUrl());
if (isset($url['host']) && $url['host'] === $baseUrl['host']) {
$content = HttpClient::get($keyword);
preg_match_all('/data-ssid="(?<id>[0-9]+)/', $content, $matches);
foreach ($matches['id'] as $sliderID) {
if ($_slider = $slidersModel->getWithThumbnail($sliderID)) {
array_push($sliders, $_slider);
}
}
}
$sliders = array_merge($sliders, $slidersModel->getSearchResults($keyword));
$result = array();
if (!empty($sliders)) {
foreach ($sliders as $slider) {
$result[] = array(
'id' => $slider['id'],
'alias' => $slider['alias'],
'title' => $slider['title'],
'thumbnail' => $this->getSliderThumbnail($slider),
'isGroup' => $slider['type'] == 'group',
'childrenCount' => $slider['slides'] > 0 ? $slider['slides'] : 0,
'editUrl' => $this->getUrlSliderEdit($slider['id'], $slider['group_id']),
'order' => $slider['ordering']
);
}
}
$this->response->respond($result);
}
public function actionPagination() {
$this->validateToken();
$this->validatePermission('smartslider_config');
$slidersModel = new ModelSliders($this);
$pageIndex = Request::$REQUEST->getInt('pageIndex', 0);
$limit = Request::$REQUEST->getVar('limit', 20);
$orderBy = Request::$REQUEST->getCmd('orderBy', 'ordering');
$orderDirection = Request::$REQUEST->getCmd('orderDirection', 'ASC');
Settings::set('limit', $limit);
Settings::set('slidersOrder2', $orderBy);
Settings::set('slidersOrder2Direction', $orderDirection);
if ($pageIndex < 0) {
$pageIndex = 0;
}
$sliderCount = $slidersModel->getSlidersCount('published', true);
$result = array();
$sliders = $slidersModel->getAll(0, 'published', $orderBy, $orderDirection, $pageIndex, $limit);
//if last page is empty
if (empty($sliders) && $sliderCount) {
$lastPageIndex = intval(ceil(($sliderCount - $limit) / $limit));
$sliders = $slidersModel->getAll(0, 'published', $orderBy, $orderDirection, $lastPageIndex, $limit);
$result['pageIndex'] = $lastPageIndex;
}
if (!empty($sliders)) {
foreach ($sliders as $slider) {
$result['sliders'][] = array(
'id' => $slider['id'],
'alias' => $slider['alias'],
'title' => $slider['title'],
'thumbnail' => $this->getSliderThumbnail($slider),
'isGroup' => $slider['type'] == 'group',
'childrenCount' => $slider['slides'] > 0 ? $slider['slides'] : 0,
'editUrl' => $this->getUrlSliderEdit($slider['id'], 0),
'order' => $slider['ordering']
);
}
$result['slidersPerPage'] = count($sliders);
}
$result['sliderCount'] = $sliderCount;
$this->response->respond($result);
}
protected function actionImport() {
$this->validateToken();
$this->validatePermission('smartslider_edit');
if (empty($_FILES) && empty($_POST)) {
Notification::error(sprintf(n2_('Your server has an upload file limit at %s, so if you have bigger export file, please use the local import file method.'), @ini_get('post_max_size')));
$this->response->respond();
} else if (!empty($_POST)) {
$data = new Data(Request::$REQUEST->getVar('slider'));
$restore = $data->get('restore', 0);
$file = '';
$slider = Request::$FILES->getVar('slider');
if ($slider['tmp_name']['import-file'] !== null) {
switch ($slider['error']['import-file']) {
case UPLOAD_ERR_OK:
case UPLOAD_ERR_NO_FILE:
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
throw new RuntimeException('Exceeded filesize limit.');
default:
throw new RuntimeException('Unknown errors.');
}
$file = $slider['tmp_name']['import-file'];
}
if (empty($file)) {
$_file = $data->get('local-import-file');
if (!empty($_file)) {
$file = Platform::getPublicDirectory() . '/' . $_file;
}
}
if (Filesystem::fileexists($file)) {
$import = new ImportSlider($this);
if ($restore) {
$import->enableReplace();
}
$groupID = Request::$REQUEST->getVar('groupID', 0);
$sliderId = $import->import($file, $groupID, $data->get('image-mode', 'clone'), 0);
if ($sliderId !== false) {
Notification::success(n2_('Slider imported.'));
if ($data->get('delete')) {
@unlink($file);
}
$this->response->redirect($this->getUrlSliderEdit($sliderId, $groupID));
} else {
$extension = pathinfo($slider['name']['import-file'], PATHINFO_EXTENSION);
if (strpos($slider['name']['import-file'], 'sliders_unzip_to_import') !== false) {
Notification::error(sprintf(n2_('You have to unzip your %1$s file to find the importable *.ss3 files!'), $slider['name']['import-file']));
$this->response->error();
} else if ($extension != 'ss3') {
Notification::error(n2_('Only *.ss3 files can be uploaded!'));
$this->response->error();
} else {
Notification::error(n2_('Import error!'));
$this->response->error();
}
$this->response->redirect($this->getUrlImport());
}
} else {
Notification::error(n2_('The imported file is not readable!'));
$this->response->error();
}
}
}
} Admin/Sliders/ControllerSliders.php 0000644 00000006730 15235664602 0013402 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Sliders;
use Nextend\Framework\Misc\Zip\Creator;
use Nextend\Framework\Model\StorageSectionManager;
use Nextend\Framework\PageFlow;
use Nextend\Framework\Request\Request;
use Nextend\SmartSlider3\Application\Admin\AbstractControllerAdmin;
use Nextend\SmartSlider3\Application\Admin\Sliders\Pro\ViewSlidersActivate;
use Nextend\SmartSlider3\Application\Model\ModelLicense;
use Nextend\SmartSlider3\Application\Model\ModelSliders;
use Nextend\SmartSlider3\BackupSlider\ExportSlider;
use Nextend\SmartSlider3\Settings;
class ControllerSliders extends AbstractControllerAdmin {
protected function actionGettingStarted() {
if (!StorageSectionManager::getStorage('smartslider')
->get('tutorial', 'GettingStarted')) {
$view = new ViewSlidersGettingStarted($this);
$view->display();
} else {
$modelLicense = ModelLicense::getInstance();
if (!$modelLicense->hasKey()) {
$view = new ViewSlidersActivate($this);
$view->display();
} else {
$this->redirectToSliders();
}
}
}
protected function actionGettingStartedDontShow() {
StorageSectionManager::getStorage('smartslider')
->set('tutorial', 'GettingStarted', 1);
$this->redirectToSliders();
}
protected function actionIndex() {
$this->loadSliderManager();
$view = new ViewSlidersIndex($this);
$view->setPaginationIndex(max(0, intval(Request::$REQUEST->getInt('pageIndex', 0)) - 1)); /*-1 needs because beautified query string*/
$view->display();
}
protected function actionTrash() {
$view = new ViewSlidersTrash($this);
$view->display();
}
protected function actionExportAll() {
$slidersModel = new ModelSliders($this);
$groupID = (Request::$REQUEST->getVar('inSearch', false)) ? '*' : Request::$REQUEST->getInt('currentGroupID', 0);
$sliders = $slidersModel->getAll($groupID, 'published');
$ids = Request::$REQUEST->getVar('sliders');
$files = array();
$saveAsFile = count($ids) == 1 ? false : true;
foreach ($sliders as $slider) {
if (!empty($ids) && !in_array($slider['id'], $ids)) {
continue;
}
$export = new ExportSlider($this, $slider['id']);
$files[] = $export->create($saveAsFile);
}
$zip = new Creator();
foreach ($files as $file) {
$zip->addFile(file_get_contents($file), basename($file));
unlink($file);
}
PageFlow::cleanOutputBuffers();
header('Content-disposition: attachment; filename=sliders_unzip_to_import.zip');
header('Content-type: application/zip');
// PHPCS - Contains binary zip data, so nothing to escape.
echo $zip->file(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
PageFlow::exitApplication();
}
protected function actionImport() {
if ($this->validatePermission('smartslider_edit')) {
$groupID = Request::$REQUEST->getVar('groupID', 0);
$view = new ViewSlidersImport($this);
$view->setGroupID($groupID);
$view->display();
}
}
} Admin/Sliders/ViewSlidersGettingStarted.php 0000644 00000001020 15235664602 0015025 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Sliders;
use Nextend\Framework\View\AbstractView;
use Nextend\SmartSlider3\Application\Admin\Layout\LayoutDefault;
use Nextend\SmartSlider3\Application\Admin\TraitAdminUrl;
class ViewSlidersGettingStarted extends AbstractView {
use TraitAdminUrl;
public function display() {
$this->layout = new LayoutDefault($this);
$this->layout->addContent($this->render('GettingStarted'));
$this->layout->render();
}
} Admin/Sliders/ViewSlidersImport.php 0000644 00000012251 15235664602 0013357 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Sliders;
use Nextend\Framework\Form\Container\ContainerTable;
use Nextend\Framework\Form\Element\Grouping;
use Nextend\Framework\Form\Element\Message\Notice;
use Nextend\Framework\Form\Element\OnOff;
use Nextend\Framework\Form\Element\Select;
use Nextend\Framework\Form\Element\Select\SelectFile;
use Nextend\Framework\Form\Element\Token;
use Nextend\Framework\Form\Element\Upload;
use Nextend\Framework\Form\Form;
use Nextend\Framework\Platform\Platform;
use Nextend\Framework\View\AbstractView;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Core\TopBarMain\BlockTopBarMain;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonBack;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonImport;
use Nextend\SmartSlider3\Application\Admin\Layout\LayoutDefault;
use Nextend\SmartSlider3\Application\Admin\TraitAdminUrl;
class ViewSlidersImport extends AbstractView {
use TraitAdminUrl;
/**
* @var LayoutDefault
*/
protected $layout;
/**
* @var int
*/
protected $groupID;
public function display() {
$this->layout = new LayoutDefault($this);
$this->layout->addBreadcrumb(n2_('Import project'), '', $this->getUrlImport());
$this->displayTopBar();
$this->displayHeader();
$this->layout->render();
}
protected function displayTopBar() {
$topBar = new BlockTopBarMain($this);
$buttonImport = new BlockButtonImport($this);
$buttonImport->addClass('n2_button--inactive');
$buttonImport->addClass('n2_slider_import');
$topBar->addPrimaryBlock($buttonImport);
$buttonBack = new BlockButtonBack($this);
$buttonBack->setUrl($this->getUrlDashboard());
$buttonBack->addClass('n2_slider_import_back');
$topBar->addPrimaryBlock($buttonBack);
$this->layout->setTopBar($topBar->toHTML());
}
protected function displayHeader() {
$this->layout->addContent($this->render('Import'));
}
public function renderForm() {
$form = new Form($this, 'slider');
new Token($form->getFieldsetHidden());
$settings = new ContainerTable($form->getContainer(), 'import-slider', n2_('Import project'));
$row1 = $settings->createRow('import-row-1');
$instructions = n2_('You can upload *.ss3 files which were exported by Smart Slider 3.') . '<br>';
new Notice($row1, 'instructions', n2_('Instruction'), $instructions);
$row2 = $settings->createRow('import-row-2');
new OnOff($row2, 'upload_or_local', n2_('Local import'), 0, array(
'relatedFieldsOff' => array(
'sliderupload-grouping'
),
'relatedFieldsOn' => array(
'sliderlocal-import-grouping'
)
));
$uploadGrouping = new Grouping($row2, 'upload-grouping');
new Upload($uploadGrouping, 'import-file', n2_('Upload file'));
new Notice($uploadGrouping, 'instructions', '', sprintf(n2_('Your server\'s upload filesize limitation is %s, so if your file is bigger, use the local import.'), @ini_get('post_max_size')));
$localImportGrouping = new Grouping($row2, 'local-import-grouping');
new SelectFile($localImportGrouping, 'local-import-file', n2_('File'), '', 'ss3');
new Notice($localImportGrouping, 'instructions', '', sprintf(n2_('Files with %1$s.ss3%2$s extension are listed from: %3$s'), '<i>', '</i>', Platform::getPublicDirectory()));
new OnOff($localImportGrouping, 'delete', n2_('Delete file'), 0, array(
'tipLabel' => n2_('Delete file'),
'tipDescription' => n2_('Removes the selected .ss3 file from your sever after the import.'),
));
$row3 = $settings->createRow('import-row-3');
new OnOff($row3, 'restore', n2_('Restore slider'), 0, array(
'tipLabel' => n2_('Restore'),
'tipDescription' => n2_('The imported slider will have the same ID as the original export has. If you have a slider with the same ID, it will be overwritten.'),
'tipLink' => 'https://smartslider.helpscoutdocs.com/article/1728-export-import-slider#import'
));
new Select($row3, 'image-mode', n2_('Image mode'), 'clone', array(
'options' => array(
'clone' => n2_('Clone'),
'update' => n2_('Old site url'),
'original' => n2_('Original')
),
'tipLabel' => n2_('Image mode'),
'tipDescription' => n2_('You can choose how the slide images are loaded.'),
'tipLink' => 'https://smartslider.helpscoutdocs.com/article/1728-export-import-slider#image-mode'
));
$form->render();
}
/**
* @return int
*/
public function getGroupID() {
return $this->groupID;
}
/**
* @param int $groupID
*/
public function setGroupID($groupID) {
$this->groupID = $groupID;
}
} Admin/Sliders/ViewSlidersIndex.php 0000644 00000003576 15235664602 0013166 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Sliders;
use Nextend\Framework\View\AbstractView;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Core\Banner\BlockBannerActivate;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Dashboard\DashboardInfo\BlockDashboardInfo;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Dashboard\DashboardManager\BlockDashboardManager;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Slider\SliderManager\BlockSliderManager;
use Nextend\SmartSlider3\Application\Admin\Layout\LayoutDefault;
use Nextend\SmartSlider3\Application\Model\ModelLicense;
class ViewSlidersIndex extends AbstractView {
/**
* @var LayoutDefault
*/
protected $layout;
protected $paginationIndex = 0;
public function display() {
$this->layout = new LayoutDefault($this);
$dashboardInfo = new BlockDashboardInfo($this);
$this->layout->addHeaderMenuItem($dashboardInfo->toHTML());
$this->displayHeader();
$this->displaySliderManager();
$dashboardManager = new BlockDashboardManager($this);
$this->layout->addContentBlock($dashboardManager);
$this->layout->render();
}
public function setPaginationIndex($index) {
$this->paginationIndex = $index;
}
protected function displayHeader() {
$model = ModelLicense::getInstance();
if (!$model->hasKey()) {
ob_start();
$banner = new BlockBannerActivate($this);
$banner->display();
$this->layout->addContent(ob_get_clean());
}
}
protected function displaySliderManager() {
$sliderManager = new BlockSliderManager($this);
$sliderManager->setPaginationIndex($this->paginationIndex);
$this->layout->addContentBlock($sliderManager);
}
} Admin/Sliders/ViewSlidersTrash.php 0000644 00000003414 15235664602 0013167 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Sliders;
use Nextend\Framework\View\AbstractView;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Core\TopBarMain\BlockTopBarMain;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButton;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Forms\Button\BlockButtonBack;
use Nextend\SmartSlider3\Application\Admin\Layout\Block\Slider\SliderTrash\BlockSliderTrash;
use Nextend\SmartSlider3\Application\Admin\Layout\LayoutDefault;
use Nextend\SmartSlider3\Application\Admin\TraitAdminUrl;
class ViewSlidersTrash extends AbstractView {
use TraitAdminUrl;
public function display() {
$this->layout = new LayoutDefault($this);
$this->layout->addBreadcrumb(n2_('Trash'), 'ssi_16 ssi_16--delete', $this->getUrlTrash());
$topBar = new BlockTopBarMain($this);
$buttonEmptyTrash = new BlockButton($this);
$buttonEmptyTrash->setLabel(n2_('Empty trash'));
$buttonEmptyTrash->setBig();
$buttonEmptyTrash->setRed();
$buttonEmptyTrash->addClass('n2_slider_empty_trash');
$buttonEmptyTrash->addClass('n2_button--inactive');
$topBar->addPrimaryBlock($buttonEmptyTrash);
$buttonBack = new BlockButtonBack($this);
$buttonBack->setUrl($this->getUrlDashboard());
$buttonBack->addClass('n2_slider_settings_back');
$topBar->addPrimaryBlock($buttonBack);
$this->layout->setTopBar($topBar->toHTML());
$this->displaySliderTrash();
$this->layout->render();
}
protected function displaySliderTrash() {
$sliderManager = new BlockSliderTrash($this);
$this->layout->addContentBlock($sliderManager);
}
} Admin/Sliders/Template/GettingStarted.php 0000644 00000002344 15235664602 0014431 0 ustar 00 <?php
namespace Nextend\SmartSlider3\Application\Admin\Sliders;
/**
* @var $this ViewSlidersGettingStarted
*/
?>
<div class="n2_getting_started">
<div class="n2_getting_started__heading">
<?php n2_e('Welcome to Smart Slider 3'); ?>
</div>
<div class="n2_getting_started__subheading">
<?php n2_e('To help you get started, we\'ve put together a super tutorial video that shows you the basic settings.'); ?>
</div>
<div class="n2_getting_started__video">
<div class="n2_getting_started__video_placeholder"></div>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/3PPtkRU7D74?rel=0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<div class="n2_getting_started__buttons">
<div class="n2_getting_started__button_dont_show">
<a href="<?php echo esc_url($this->getUrlGettingStartedDontShow()); ?>"><?php n2_e('Don\'t show again'); ?></a>
</div>
<div class="n2_getting_started__button_dashboard">
<a href="<?php echo esc_url($this->getUrlDashboard()); ?>"><?php n2_e('Go to dashboard'); ?></a>
</div>
</div>
</div>