%PDF- %PDF-
| Direktori : /home/lightco1/public_html/plugins/content/sigplus/ |
| Current File : /home/lightco1/public_html/plugins/content/sigplus/sigplus.php |
<?php
/**
* @file
* @brief sigplus Image Gallery Plus plug-in for Joomla
* @author Levente Hunyadi
* @version 1.5.0
* @remarks Copyright (C) 2009-2014 Levente Hunyadi
* @remarks Licensed under GNU/GPLv3, see http://www.gnu.org/licenses/gpl-3.0.html
* @see http://hunyadi.info.hu/projects/sigplus
*/
/*
* sigplus Image Gallery Plus plug-in for Joomla
* Copyright 2009-2014 Levente Hunyadi
*
* sigplus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sigplus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
if (!defined('SIGPLUS_VERSION_PLUGIN')) {
define('SIGPLUS_VERSION_PLUGIN', '1.5.0');
}
require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'fields'.DIRECTORY_SEPARATOR.'constants.php';
if (!defined('SIGPLUS_DEBUG')) {
/**
* Triggers debug mode.
* In debug mode, the extension uses uncompressed versions of scripts rather than the bandwidth-saving minified versions.
*/
define('SIGPLUS_DEBUG', false);
}
if (!defined('SIGPLUS_LOGGING')) {
/**
* Triggers logging mode.
* In logging mode, the extension prints verbose status messages to the output.
*/
define('SIGPLUS_LOGGING', false);
}
// import library dependencies
jimport('joomla.event.plugin');
require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'core'.DIRECTORY_SEPARATOR.'core.php';
/**
* sigplus Image Gallery Plus plug-in.
*/
class plgContentSigPlusNovo extends JPlugin {
/** Activation tag used to produce galleries with the plug-in. */
private $tag_gallery = 'gallery';
/** Activation tag used to produce a lightbox-powered link with the plug-in. */
private $tag_lightbox = 'lightbox';
/** Core service object. */
private $core;
public function __construct(&$subject, $params) {
parent::__construct($subject, $params);
// set activation tag if well-formed
$tag_gallery = $this->getParameterValue('tag_gallery', $this->tag_gallery);
if (is_string($tag_gallery) && ctype_alnum($tag_gallery)) {
$this->tag_gallery = $tag_gallery;
}
$tag_lightbox = $this->getParameterValue('tag_lightbox', $this->tag_lightbox);
if (is_string($tag_lightbox) && ctype_alnum($tag_lightbox)) {
$this->tag_lightbox = $tag_lightbox;
}
}
private function getParameterValue($name, $default) {
if ($this->params instanceof stdClass) {
if (isset($this->params->$name)) {
return $this->params->$name;
}
} else if ($this->params instanceof JRegistry) { // Joomla 2.5 and earlier
$paramvalue = $this->params->get($name);
if (isset($paramvalue)) {
return $paramvalue;
}
}
return $default;
}
/**
* Fired before article contents are to be processed by the plug-in.
* @param $article The article that is being rendered by the view.
* @param $params An associative array of relevant parameters.
* @param $limitstart An integer that determines the "page" of the content that is to be generated.
* @param
*/
public function onContentAfterTitle($context, &$article, &$params, $limitstart) {
}
/**
* Parses the article for occurrences of the activation tag. Replacements are not saved.
* Fired immediately after content has been saved.
* @param {string} $context The context of the content passed to the plug-in.
* @param $article The content object.
* @param {bool} $isNew True if the content has just been created.
*/
public function onContentAfterSave($context, $article, $isNew) {
return true;
}
/**
* Fired when content are to be processed by the plug-in.
* Recommended usage syntax:
* a) POSIX fully portable file names
* Folder name characters are in [A-Za-z0-9._-])
* Regular expression: [/\w.-]+
* Example: {gallery rows=1 cols=1} /sigplus/birds/ {/gallery}
* b) URL-encoded absolute URLs
* Regular expression: (?:[0-9A-Za-z!"$&\'()*+,.:;=@_-]|%[0-9A-Za-z]{2})+
* Example: {gallery} http://example.com/image.jpg {/gallery}
*/
public function onContentPrepare($context, &$article, &$params, $limitstart) {
if ($context === 'com_finder.indexer') {
// skip plug-in activation when the content is being indexed
} elseif (($context === 'com_content.category' || $context === 'com_content.featured') && isset($article->introtext)) {
$this->parseContent($article->text, $article->introtext); // only introductory text is visible, do not make replacements elsewhere
} else {
$this->parseContent($article->text); // replacements take effect
}
}
private function parseContent(&$text, $introtext = null) {
if (isset($introtext) && strpos($introtext, '{'.$this->tag_gallery) === false && strpos($introtext, '{'.$this->tag_lightbox) === false) {
return false; // short-circuit plugin activation, no replacements made
}
if (strpos($text, '{'.$this->tag_gallery) === false && strpos($text, '{'.$this->tag_lightbox) === false) {
return false; // short-circuit plugin activation, no replacements made
}
if (SigPlusNovoTimer::shortcircuit()) {
return false; // short-circuit plugin activation, allotted execution time expired, error message already printed
}
// load language file for internationalized labels and error messages
$lang = JFactory::getLanguage();
$lang->load('plg_content_sigplus', JPATH_ADMINISTRATOR);
if (!isset($this->core)) {
$this->core = false;
try {
// create configuration parameter objects
$configuration = new SigPlusNovoConfigurationParameters();
$configuration->service = new SigPlusNovoServiceParameters();
$configuration->service->setParameters($this->params);
$configuration->gallery = new SigPlusNovoGalleryParameters();
$configuration->gallery->setParameters($this->params);
if (SIGPLUS_LOGGING || $configuration->service->debug_server == 'verbose') {
SigPlusNovoLogging::setService(new SigPlusNovoHTMLLogging());
} else {
SigPlusNovoLogging::setService(new SigPlusNovoNoLogging());
}
$this->core = new SigPlusNovoCore($configuration);
} catch (Exception $e) {
$app = JFactory::getApplication();
$app->enqueueMessage($e->getMessage(), 'error');
}
}
if ($this->core !== false) {
if (SIGPLUS_LOGGING) {
SigPlusNovoLogging::appendStatus(JText::_('SIGPLUS_STATUS_LOGGING'));
}
$gallerycount = 0;
// pattern for key/value parameter list
$param_pattern = '(?:[^{/}]+|/(?!\})|\{\$[^{/}]+\})*'; // characters other than curly braces, or variable substitutions in the style "{$variable}"
// find compact {gallery/} tags and emit code
$tag_gallery = preg_quote($this->tag_gallery, '#');
$pattern = '#\{'.$tag_gallery.'\b('.$param_pattern.')/\}#msSu';
$gallerycount += $this->getGalleryReplacementAll($text, $pattern);
// find {gallery}...{/gallery} tags and emit code
$tag_gallery = preg_quote($this->tag_gallery, '#');
$pattern = '#\{'.$tag_gallery.'\b('.$param_pattern.')\}(.+?)\{/'.$tag_gallery.'\}#msSu';
$gallerycount += $this->getGalleryReplacementAll($text, $pattern);
// find {lightbox}...{/lightbox} tags wrapping HTML and emit code
$tag_lightbox = preg_quote($this->tag_lightbox, '#');
$pattern = '#\{'.$tag_lightbox.'\b([^{}]*)(?<!/)\}(.+?)\{/'.$tag_lightbox.'\}#msSu';
$text = preg_replace_callback($pattern, function ($match) {
return $this->getLightboxReplacement($match);
}, $text, -1, $lightboxcount);
// find compact {lightbox/} tags and emit code
$pattern = '#\{'.$tag_lightbox.'\b([^{}]*)/\}#msSu';
$text = preg_replace_callback($pattern, function ($match) {
return $this->getSelectorReplacement($match);
}, $text);
// employ safety measure for excessively large galleries
if (strlen($text) > 80000) { // there is a risk of exhausting the backtrack limit and producing the "white screen of death"
ini_set('pcre.backtrack_limit', 1000000); // try to raise backtrack limit
SigPlusNovoLogging::appendStatus('Generated HTML code is excessively large, consider splitting galleries. Regular expression matching backtrack limit has been increased.');
}
$log = SigPlusNovoLogging::fetch();
if ($log) {
$text = $log.$text;
}
return $gallerycount + $lightboxcount > 0;
}
return false;
}
/**
* Replaces all occurrences of a gallery activation tag.
* @param {string} $text Article (content item) text.
* @param {string} $pattern Replacement regular expression pattern.
*/
private function getGalleryReplacementAll(&$text, $pattern) {
$count = 0;
$offset = 0;
while (preg_match($pattern, $text, $match, PREG_OFFSET_CAPTURE, $offset)) {
if (SigPlusNovoTimer::shortcircuit()) {
return $count; // short-circuit plugin activation, allotted execution time expired, error message already printed
}
$count++;
$start = $match[0][1];
$end = $start + strlen($match[0][0]);
try {
$innertext = isset($match[2]) ? $match[2][0] : null; // text in between start and end tags (unless omitted)
$paramtext = $match[1][0];
$body = $this->getGalleryReplacementSingle($innertext, $paramtext);
$text = substr($text, 0, $start).$body.substr($text, $end);
$offset = $start + strlen($body);
} catch (Exception $e) {
$app = JFactory::getApplication();
switch ($this->core->verbosityLevel()) {
case 'none':
// display no message, hide activation tag completely
$text = substr($text, 0, $start).substr($text, $end);
$offset = $start;
break;
case 'laconic':
if ($e instanceof SigPlusNovoTimeoutException) { // display a timeout message
$message = JText::_('SIGPLUS_EXCEPTION_MESSAGE_TIMEOUT');
} else { // display a very general, uninformative message
$message = JText::_('SIGPLUS_EXCEPTION_MESSAGE');
}
// hide activation tag completely
$text = substr($text, 0, $start).substr($text, $end);
$offset = $start;
// show error message
$app->enqueueMessage($message, 'error');
break;
case 'verbose':
default:
// display a specific, informative message
$message = $e->getMessage();
// leave activation tag as it appears
$offset = $end;
// show error message
$app->enqueueMessage($message, 'error');
}
}
}
return $count;
}
/**
* Replaces a single occurrence of a gallery activation tag.
* @param {string} $sourcetext A string that identifies the image source.
* @param {string} $paramtext A string that stores parameter key/value pairs.
*/
private function getGalleryReplacementSingle($sourcetext, $paramtext) {
// the activation code {gallery key=value}myfolder{/gallery} translates into a source and a parameter string
$paramtext = self::strip_html($paramtext);
$this->core->setParameterString($paramtext);
// update parameters if a module is specified that acts as a base for gallery parameters
// pushes a new set of parameters on the parameter stack
$inherits = $this->setInheritedParameters($paramtext);
// get special-purpose parameter "source"
$params = $this->core->getParameters();
// set image source
$source = null;
if (isset($sourcetext)) {
$source = html_entity_decode($sourcetext, ENT_QUOTES, 'utf-8');
}
if ($params->source) {
$source = $params->source;
}
if (is_url_http($source)) {
$source = safe_url_encode($source);
}
try {
if (is_absolute_path($source)) { // do not permit an absolute path enclosed in activation tags
throw new SigPlusNovoImageSourceException($source);
}
// download image
try {
if ($this->core->downloadImage($source)) { // an image has been requested for download
jexit(); // do not produce a page
}
} catch (SigPlusNovoImageDownloadAccessException $e) { // signal download errors but do not stop page processing
$app = JFactory::getApplication();
$app->enqueueMessage($e->getMessage(), 'error');
}
// generate image gallery
$body = $this->core->getGalleryHTML($source, $id);
$this->core->addStyles($id);
$this->core->addScripts($id);
$this->core->resetParameters();
if ($inherits) { // pops the extra set of parameters from the parameter stack
$this->core->resetParameters();
}
return $body;
} catch (Exception $e) {
$this->core->resetParameters();
if ($inherits) { // pops the extra set of parameters from the parameter stack
$this->core->resetParameters();
}
throw $e;
}
}
/**
* Generates image thumbnails with alternate text, title and lightbox pop-up activation on mouse click.
* This method is to be called as a regular expression replace callback.
* Any error messages are printed to screen.
* @param $match A regular expression match.
*/
private function getGalleryReplacement($match) {
try {
$body = $this->getGalleryReplacementSingle($match[2], $match[1]);
} catch (Exception $e) {
$body = $match[0]; // no replacements
$app = JFactory::getApplication();
$app->enqueueMessage($e->getMessage(), 'error');
}
return $body;
}
/**
* Replaces a single occurrence of a lightbox activation tag.
*/
private function getLightboxReplacement($match) {
// extract parameter string
$params = SigPlusNovoConfigurationBase::string_to_array(self::strip_html($match[1]));
// extract or create identifier
if (!isset($params['id'])) {
$params['id'] = $this->core->getUniqueGalleryId();
}
if (isset($params['href']) || isset($params['link'])) {
$this->core->setParameterArray($params);
// build anchor components
if (isset($params['link'])) { // create link to gallery on the same page
$this->core->addLightboxLinkScript($params['id'], $params['link']);
unset($params['link']);
$params['href'] = 'javascript:void(0);'; // artificial link target
} elseif (isset($params['href'])) { // create link to (external) image
if (!is_url_http($params['href'])) { // make relative URLs absolute
$params['href'] = JURI::base(false).$params['href'];
}
$params['href'] = safe_url_encode($params['href']);
// add lightbox scripts to page header
$selector = '#'.$params['id']; // build selector from the identifier of the anchor that links to a resource
$this->core->addLightboxScripts($selector);
}
$this->core->resetParameters();
// generate anchor HTML
$anchor = '<a';
foreach (array('id','href','rel','class','style','title') as $attr) {
if (isset($params[$attr])) {
$anchor .= ' '.$attr.'="'.$params[$attr].'"';
}
}
$anchor .= '>'.$match[2].'</a>';
return $anchor;
} else {
return $match[2]; // do not change text for unsupported combination of parameters
}
}
private function getSelectorReplacement($match) {
$replacement = $match[0]; // no replacements
// extract parameter string
$params = SigPlusNovoConfigurationBase::string_to_array(self::strip_html($match[1]));
// apply lightbox to all items that satisfy the CSS selector
if (isset($params['selector'])) {
// add lightbox scripts to page header
$this->core->setParameterArray($params);
try {
$this->core->addLightboxScripts($params['selector']);
$this->core->resetParameters();
} catch (Exception $e) {
$this->core->resetParameters();
throw $e;
}
$replacement = '';
}
return $replacement;
}
/**
* Sets plug-in parameters inherited from a module.
*
* Parameters of a module may in this way act as a template for plug-in parameters. Plug-in parameters override
* the parameter values inherited from the base module.
*/
private function setInheritedParameters($params) {
// get current parameters
$curparams = $this->core->getParameters();
if (!isset($curparams->base_module)) {
return false;
}
// import parameters from module
$module = JModuleHelper::getModule('mod_sigplus', $curparams->base_module);
if (empty($module)) {
return false;
}
// pop parameters recently pushed to parameter stack
$this->core->resetParameters();
// process parameters from module that acts as base source for parameters
$baseparams = json_decode($module->params);
unset($baseparams->source); // ignore parameter "source" not meaningful in this context
// push base parameters to parameter stack
$this->core->setParameterObject($baseparams);
// (re-)push activation code parameters to parameter stack
$this->core->setParameterString($params);
$curparams = $this->core->getParameters();
return true;
}
private static function strip_html($html) {
$text = html_entity_decode($html, ENT_QUOTES, 'utf-8'); // translate HTML entities to regular characters
$text = str_replace("\xc2\xa0", ' ', $text); // translate non-breaking space to regular space
$text = strip_tags($text); // remove HTML tags
return $text;
}
public function onExtensionAfterSave($context, $table, $isNew) {
if (!isset($table) ||
!isset($table->type) || $table->type !== 'plugin' ||
!isset($table->folder) || $table->folder !== 'content' ||
!isset($table->element) || $table->element !== 'sigplus')
{ // function invoked in the context of an unrelated extension
return;
}
// previous extension configuration that is being overwritten
$old_params = new SigPlusNovoServiceParameters();
$old_params->setParameters($this->params);
if (!empty($this->params['settings'])) {
$old_params->setString($this->params['settings']);
}
// new extension configuration that has been persisted
$params = json_decode($table->params, true);
$new_params = new SigPlusNovoServiceParameters();
if ($params) {
$new_params->setArray($params);
if (!empty($params['settings'])) {
$new_params->setString($params['settings']);
}
}
$clean_database = false;
// check if there has been a change in metadata extraction strategy
if ($old_params->metadata_filter != $new_params->metadata_filter) {
$clean_database = true;
}
// check if instructed to clean database on every save
if ($new_params->clean_database) {
$clean_database = true;
}
if ($clean_database) {
require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'core'.DIRECTORY_SEPARATOR.'setup.php';
SigPlusNovoDatabaseSetup::update();
SigPlusNovoDatabaseSetup::populate();
}
}
}
if (!file_exists(JPATH_ROOT.DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR.'content'.DIRECTORY_SEPARATOR.'sigplus'.DIRECTORY_SEPARATOR.'js')) { // available in 1.4.x only
/**
* Compatibility layer for using sigplus Novo as a next version of sigplus.
*/
class plgContentSIGPlus extends plgContentSigPlusNovo {
}
}