/** * Generates image previews with alternate text, title and lightbox pop-up activation on mouse click. * @param string $body Data associated with the gallery. * @param string $paramstring A whitespace-separated list of name="value" parameter values. */ private function getImageGalleryHtml($body, $params = array()) { // set gallery parameters $this->curparams = clone $this->defparams; // parameters set in back-end if (is_array($params)) { $this->curparams->setArray($params); } else { $paramstring = htmlspecialchars_decode((string) $params); $this->curparams->setString($paramstring); // parameters set inline } if (!isset($body)) { // path is set via parameter with compact activation syntax $body = $this->curparams->path; } $engineservices = SIGPlusEngineServices::instance(); // generate link to an existing gallery if ($this->curparams->link !== false) { $lightbox = $engineservices->getLightboxEngine($this->curparams->lightbox); // get selected lightbox engine if any or use default if ($lightbox && ($linkscript = $lightbox->getLinkScript($this->curparams->link, $this->curparams->index)) !== false) { return '<a href="javascript:void(' . htmlspecialchars($linkscript) . ')">' . $body . '</a>'; } else { // engine does not support programmatic activation return $body; } } // set gallery folders $imageref = $body; // a relative path to an image folder or an image, or an absolute URL to an image to display if ($isremote = is_remote_path($imageref)) { $imageurl = $imageref; $iswebalbum = (bool) preg_match('"^https?://picasaweb.google.com/data/feed/(?:api|base)/user/([^/?#]+)/albumid/([^/?#]+)"', $imageurl); // test for Picasa galleries $imagehashbase = $imageurl; } else { $imageref = trim($imageref, '/'); // remove leading and trailing backslash // verify validity of relative path $imagepath = $this->imageservices->getImagePath($imageref); if (!file_exists($imagepath)) { throw new SIGPlusImageGalleryFolderException($imageref); } $imagehashbase = $imagepath; // base in computing hash for content caching } // set gallery identifier if ($this->curparams->id) { // use user-supplied identifier $galleryid = $this->curparams->id; } else { // automatically generate identifier for thumbnail gallery $galleryid = 'sigplus_' . md5($imagehashbase); } $galleryid = $this->getUniqueGalleryId($galleryid); // force meaningful settings for single-image view (disable slider and activate flow layout) if ($this->curparams->layout != 'hidden' && ($isremote && !$iswebalbum || isset($imagepath) && is_file($imagepath))) { $this->curparams->layout = 'flow'; $this->curparams->rows = false; $this->curparams->cols = false; $this->curparams->slider = false; } // substitute proper left or right alignment depending on whether language is LTR or RTL $language = JFactory::getLanguage(); $this->curparams->alignment = str_replace(array('after', 'before'), $language->isRTL() ? array('left', 'right') : array('right', 'left'), $this->curparams->alignment); // get selected slider engine if any, or use default $slider = $engineservices->getSliderEngine($this->curparams->slider); if (!$slider) { $this->curparams->progressive = false; // progressive loading is not supported unless a slider is enabled } // *** cannot update $this->curparams, which is used in content caching, beyond this point *** // // initialize logging if (SIGPLUS_LOGGING) { $logging = SIGPlusLogging::instance(); if ($isremote) { $logging->append('Generating gallery "' . $galleryid . '" from URL: <kbd>' . $imageurl . '</kbd>'); } else { $logging->append('Generating gallery "' . $galleryid . '" from file/directory: <kbd>' . $imagepath . '</kbd>'); } $logging->appendblock('Local parameters for "' . $galleryid . '" are:', print_r($this->curparams, true)); } // verify if content is available in cache folder if (!SIGPLUS_CONTENT_CACHING || $engineservices->debug || $this->curparams->hasRandom()) { $cachekey = false; // galleries that involve a random element cannot be cached } elseif (($cachekey = $this->imageservices->getCachedContent($imagehashbase, $this->curparams)) !== false) { if (SIGPLUS_LOGGING) { $logging->append('Retrieving cached content with key <kbd>' . $cachekey . '</kbd>.'); } } // generate gallery HTML code or setup script if ($cachekey === false) { // save default title and description, which might be overridden in labels file, affecting hash key used in caching $deftitle = $this->curparams->deftitle; $defdescription = $this->curparams->defdescription; if ($isremote) { // access images remote domain if ($iswebalbum) { $htmlorscript = $this->getPicasaImageGallery($imageurl, $galleryid); } else { $extension = strtolower(pathinfo(parse_url($imageurl, PHP_URL_PATH), PATHINFO_EXTENSION)); switch ($extension) { case 'gif': case 'jpg': case 'jpeg': case 'png': // plug-in syntax {gallery}http://example.com/image.jpg{/gallery} $labels = array(new SIGPlusImageLabel($imageurl, false, false)); // artificial single-entry labels file $htmlorscript = $this->getUserDefinedRemoteImageGallery($labels, $galleryid); break; default: // plug-in syntax {gallery}http://example.com{/gallery} throw new SIGPlusNotSupportedException(); $labels = $this->imageservices->getLabels($imageurl, $this->curparams->labels, $this->curparams->deftitle, $this->curparams->defdescription); switch ($this->curparams->sortcriterion) { case SIGPLUS_SORT_RANDOMLABELS: shuffle($labels); // fall through // fall through case SIGPLUS_SORT_LABELS_OR_FILENAME: case SIGPLUS_SORT_LABELS_OR_MTIME: $htmlorscript = $this->getUserDefinedRemoteImageGallery($labels, $galleryid); } } } } else { if (is_file($imagepath)) { // syntax {gallery}folder/subfolder/file.jpg{/gallery} $htmlorscript = $this->getUnlabeledImageGallery(dirname($imagepath), array(basename($imagepath)), $galleryid); } else { // syntax {gallery}folder/subfolder{/gallery} // fetch image labels switch ($this->curparams->labels) { case 'filename': $labels = $this->imageservices->getLabelsFromFilenames($imagepath); break; default: $labels = $this->imageservices->getLabels($imagepath, $this->curparams->labels, $this->curparams->deftitle, $this->curparams->defdescription); } switch ($this->curparams->sortcriterion) { case SIGPLUS_SORT_LABELS_OR_FILENAME: if (empty($labels)) { // there is no labels file to use $files = $this->imageservices->getListing($imagepath, SIGPLUS_FILENAME, $this->curparams->sortorder, $this->curparams->depth); $htmlorscript = $this->getUnlabeledImageGallery($imagepath, $files, $galleryid); } else { $htmlorscript = $this->getUserDefinedImageGallery($imagepath, $labels, $galleryid); } break; case SIGPLUS_SORT_LABELS_OR_MTIME: if (empty($labels)) { $files = $this->imageservices->getListing($imagepath, SIGPLUS_MTIME, $this->curparams->sortorder, $this->curparams->depth); $htmlorscript = $this->getUnlabeledImageGallery($imagepath, $files, $galleryid); } else { $htmlorscript = $this->getUserDefinedImageGallery($imagepath, $labels, $galleryid); } break; case SIGPLUS_SORT_MTIME: $files = $this->imageservices->getListing($imagepath, SIGPLUS_MTIME, $this->curparams->sortorder, $this->curparams->depth); $htmlorscript = $this->getLabeledImageGallery($imagepath, $files, $labels, $galleryid); break; case SIGPLUS_SORT_RANDOM: $files = $this->imageservices->getListing($imagepath, SIGPLUS_RANDOM, $this->curparams->sortorder, $this->curparams->depth); $htmlorscript = $this->getLabeledImageGallery($imagepath, $files, $labels, $galleryid); break; case SIGPLUS_SORT_RANDOMLABELS: if (empty($labels)) { // there is no labels file to use $files = $this->imageservices->getListing($imagepath, SIGPLUS_RANDOM, $this->curparams->sortorder, $this->curparams->depth); $htmlorscript = $this->getUnlabeledImageGallery($imagepath, $files, $galleryid); } else { shuffle($labels); $htmlorscript = $this->getUserDefinedImageGallery($imagepath, $labels, $galleryid); } break; default: // case SIGPLUS_SORT_FILENAME: $files = $this->imageservices->getListing($imagepath, SIGPLUS_FILENAME, $this->curparams->sortorder, $this->curparams->depth); $htmlorscript = $this->getLabeledImageGallery($imagepath, $files, $labels, $galleryid); break; } } } if (!empty($htmlorscript)) { switch ($this->curparams->linkage) { case 'inline': $cachedata = ($slider !== false ? '<ul style="visibility:hidden;">' : '<ul>') . implode($htmlorscript) . '</ul>'; break; case 'head': // put generated content in HTML head (does not allow HTML body with bloating size, which would cause preg_replace in System - SEF to fail) $cachedata = $this->getGalleryScript($galleryid, $htmlorscript); break; case 'external': $cachedata = '__jQuery__(function () { ' . $this->getGalleryScript($galleryid, $htmlorscript) . ' });'; break; } } else { $cachedata = false; } // restore default title and description, which might have been overridden in labels file $this->curparams->deftitle = $deftitle; $this->curparams->defdescription = $defdescription; if (SIGPLUS_CONTENT_CACHING && !$this->curparams->hasRandom()) { // save generated content for future re-use in a temporary file in the cache folder $this->imageservices->cleanCachedContent(); $cachekey = $this->imageservices->saveCachedContent($imagehashbase, $this->curparams, $cachedata); if (SIGPLUS_LOGGING) { if ($cachekey !== false) { $logging->append('Saved cached content with key <kbd>' . $cachekey . '</kbd>.'); } else { $logging->append('Failed to persist content in cache folder.'); } } } } elseif ($this->curparams->linkage != 'external') { // retrieve content from cache but no need to fetch content for linking external .js file $cachefile = $this->imageservices->getCachedContentPath($cachekey, $this->curparams->linkage == 'inline' ? '.html' : '.js'); if (filesize($cachefile) > 0) { $cachedata = file_get_contents($cachefile); } else { $cachedata = false; // empty gallery } } else { $cachedata = true; } if ($cachedata === false) { // no content $html = JText::_('SIGPLUS_EMPTY'); } else { switch ($this->curparams->linkage) { case 'inline': $html = $cachedata; // content produced as HTML only in inline linkage mode break; case 'head': $this->addGalleryScript(); // add gallery population script $engineservices->addOnReadyScript($cachedata); // add gallery data $html = ''; // no content produced in HTML except for placeholder break; case 'external': $this->addGalleryScript(); if ($cachekey !== false) { // include reference to generated script in external .js file $document = JFactory::getDocument(); $document->addScript($this->imageservices->getCachedContentUrl($cachekey, '.js')); } else { // add script to document head as a fall-back if could not save to external .js file in cache folder $engineservices->addOnReadyScript($cachedata); } $html = ''; break; } } // set image gallery alignment (left, center or right) and style $gallerystyle = 'sigplus-gallery'; switch ($this->curparams->alignment) { case 'left': case 'left-clear': case 'left-float': $gallerystyle .= ' sigplus-left'; break; case 'center': $gallerystyle .= ' sigplus-center'; break; case 'right': case 'right-clear': case 'right-float': $gallerystyle .= ' sigplus-right'; break; } switch ($this->curparams->alignment) { case 'left': case 'left-float': case 'right': case 'right-float': $gallerystyle .= ' sigplus-float'; break; case 'left-clear': case 'right-clear': $gallerystyle .= ' sigplus-clear'; break; } switch ($this->curparams->imagecaptions) { case 'above': $gallerystyle .= ' sigplus-captionsabove'; break; case 'below': $gallerystyle .= ' sigplus-captionsbelow'; break; } // output image gallery or gallery placeholder $div_attrs = array('id' => $galleryid, 'class' => $gallerystyle); if ($this->curparams->layout == 'hidden') { $div_attrs['style'] = 'display:none !important;'; } $html = make_html('div', $div_attrs, $html); // add style and script declarations $this->addStylesAndScripts($galleryid); $this->curparams = false; return $html; }
/** * Fired when contents 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} */ function onContentPrepare($context, &$article, &$params, $limitstart) { // skip plug-in activation when the content is being indexed if ($context === 'com_finder.indexer') { return; } if (strpos($article->text, '{' . $this->activationtag) === false) { return; /* short-circuit plugin activation */ } // reset low-level lightbox-only mode $this->lowlevel = false; if (SIGPLUS_LOGGING) { $logging = SIGPlusLogging::instance(); $logging->append('<strong>sigplus is currently running in logging mode</strong>. This should be turned off in a production environment by setting the constant SIGPLUS_LOGGING in <kbd>sigplus.php</kbd> to <kbd>false</kbd>, in which case this message will also disappear.'); } // load language file for internationalized labels and error messages $lang = JFactory::getLanguage(); $lang->load('plg_content_sigplus', JPATH_ADMINISTRATOR); try { // on-demand instantiation if (!isset($this->core)) { $this->core = new SIGPlusCore($this->configuration); } // find gallery tags and emit code $activationtag = preg_quote($this->activationtag, '#'); $article->text = preg_replace_callback('#[{]' . $activationtag . '([^{}]*)(?<!/)[}]\\s*((?:[^{]+|[{](?!/' . $activationtag . '))+)\\s*[{]/' . $activationtag . '[}]#', array($this, 'getGalleryRegexReplacementExpanded'), $article->text, -1); $article->text = preg_replace_callback('#[{]' . $activationtag . '([^{}]*)/[}]#', array($this, 'getGalleryRegexReplacementCollapsed'), $article->text, -1); $this->core->addGalleryEngines($this->lowlevel); } catch (Exception $e) { $app = JFactory::getApplication(); $app->enqueueMessage($e->getMessage(), 'error'); $article->text = $e->getMessage() . $article->text; } if (SIGPLUS_LOGGING) { $article->text = $logging->fetch() . $article->text; } }