3 * Thumbnail plugin for Nucleus CMS
4 * Version 3.9.6 (4.0 RC2) for PHP5
5 * Written By Mocchi, Apr. 04, 2011
6 * Original code was written by jirochou, May 23, 2004 and maintained by nakahara21
7 * This plugin depends on NP_MediaUtils
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 3
12 * of the License, or (at your option) any later version.
15 class NP_Thumbnail extends NucleusPlugin {
16 private static $thumbdir = '.thumb';
17 private static $max_sync = 10;
18 private static $authorid = 0;
19 private static $buffering = FALSE;
20 private static $table_name = 'plugin_thumbnail'; // not implemented
22 public function getName() { return 'Thumbnail'; }
23 public function getAuthor() { return 'Mocchi, nakahara21, jirochou'; }
24 public function getURL() { return 'http://japan.nucleuscms.org/wiki/plugins:thumbnail'; }
25 public function getVersion() { return '3.9.6 (4.0 RC2)'; }
26 public function getDescription() { return _NP_THUMBNAIL_01; }
27 public function getPluginDep() { return array('NP_MediaUtils');}
28 public function getMinNucleusVersion() {return 340;}
29 public function supportsFeature($feature) { return in_array ($feature, array('SqlTablePrefix', 'SqlApi'));}
30 public function getEventList() { return array('QuickMenu', 'PrePluginOptionsEdit', 'PostAuthentication', 'PreItem', 'PostMediaUpload'); }
32 public function install () {
33 $this->createOption('maxwidth', '_NP_THUMBNAIL_02', 'text', '100', 'datatype=numerical');
34 $this->createOption('maxheight', '_NP_THUMBNAIL_03', 'text', '100', 'datatype=numerical');
35 $this->createOption('save_thumb', '_NP_THUMBNAIL_04', 'select', 'filesystem', '_NP_THUMBNAIL_05|no|_NP_THUMBNAIL_06|filesystem');
36 $this->createBlogOption('force_thumb', '_NP_THUMBNAIL_07', 'yesno', 'yes');
37 $this->createBlogOption('thumb_template', '_NP_THUMBNAIL_08', 'textarea', '<a href="<%rawpopuplink%>" title="<%popuptext%>" onclick="<%popupcode%>"><img src="<%thumb_url%>" width="<%thumb_width%>" height="<%thumb_height%>" alt="<%popuptext%>" /></a>');
42 * plugin options are purged automatically when uninstalled.
44 public function uninstall() {
46 MediaUtils::purgeDir($DIR_MEDIA . self::$thumbdir);
50 public function init() {
53 if (!class_exists('Medium', FALSE)) {
54 include(MediaUtils::$lib_path . '/Medium.php');
57 $language = preg_replace('#[/|\\\\]#', '', getLanguageName());
59 if (!defined('_NP_THUMBNAIL_01')) {
60 if (file_exists($this->getDirectory() . $language.'.php')) {
61 include($this->getDirectory() . $language.'.php');
63 include($this->getDirectory() . 'english.php');
72 public function event_PrePluginOptionsEdit ($data) {
73 if ($data['context'] != 'global') {
74 foreach($data['options'] as $key => $option) {
75 if ($option['pid'] == $this->getID()) {
76 if (defined($option['description'])) {
77 $data['options'][$key]['description'] = constant($option['description']);
79 if ($option['type'] == 'select') {
80 foreach (explode('|', $option['typeinfo']) as $option) {
81 if (defined($option)) {
82 $data['options'][$key]['typeinfo'] = str_replace($option, constant($option), $data['options'][$key]['typeinfo']);
88 } else if ($data['plugid'] == $this->getID()) {
89 foreach($data['options'] as $key => $option){
90 if (defined($option['description'])) {
91 $data['options'][$key]['description'] = constant($option['description']);
93 if ($option['type'] == 'select') {
94 foreach (explode('|', $option['typeinfo']) as $option) {
95 if (defined($option)) {
96 $data['options'][$key]['typeinfo'] = str_replace($option, constant($option), $data['options'][$key]['typeinfo']);
108 static private function t ($text, $array=array()){
109 if (is_array($array)) {
113 foreach ($array as $key => $value){
114 if (is_array($value)) {
117 $search[] = '<%'.preg_replace('/[^a-zA-Z0-9_]+/','',$key).'%>';
121 return htmlspecialchars (str_replace($search, $replace, $text), ENT_QUOTES, _CHARSET);
124 public function event_QuickMenu ($data) {
126 if($this->getOption('save_thumb') !== 'no') {
130 'title' => 'NP_Thumbnail',
131 'url' => "{$CONF['ActionURL']}?action=plugin&name={$this->getname()}&type=admin",
132 'tooltip' => _NP_THUMBNAIL_09));
137 public function event_PostAuthentication ($data) {
138 if (array_key_exists('action', $_REQUEST)
139 && array_key_exists('name', $_REQUEST)
140 && array_key_exists('type', $_REQUEST)
141 && array_key_exists('width', $_REQUEST)
142 && array_key_exists('height', $_REQUEST)
143 && $_REQUEST['action'] === 'plugin'
144 && $_REQUEST['name'] === $this->getName()
145 && $_REQUEST['type'] !== '') {
146 self::$buffering = ob_start;
151 public function doAction ($type) {
152 global $DIR_MEDIA, $member;
154 $type = (string) $type;
160 if (array_key_exists('path', $_GET)) {
161 $path = (string) $_GET['path'];
163 if (array_key_exists('width', $_GET)) {
164 $maxwidth = (integer) $_GET['width'];
166 if (array_key_exists('height', $_GET)) {
167 $maxheight = (integer) $_GET['height'];
170 if (in_array($type, array('admin', 'clear', 'sync')) && $member->isAdmin()) {
171 $this->showAdmin($type);
175 if (self::$buffering) {
179 if ($maxwidth <= 0 || $maxwidth > 1000 || $maxheight <= 0 || $maxheight > 1000 ) {
180 MediaUtils::error ($this->t(_NP_THUMBNAIL_10, array($maxwidth, $maxheight)));
184 if (FALSE === ($medium = new Medium($DIR_MEDIA, $path, MediaUtils::$prefix))) {
185 MediaUtils::error ($this->t(_NP_THUMBNAIL_11, array($path)));
189 if (FALSE === $medium->setResampledSize($maxwidth, $maxheight)) {
190 MediaUtils::error ($this->t(_NP_THUMBNAIL_10, array($maxwidth, $maxheight)));
194 MediaUtils::responseResampledImage($medium);
198 public function doSkinVar ($skinType, $path, $maxwidth=0, $maxheight=0, $alt) {
199 $path = (string) $path;
200 $maxwidth = (integer) $maxwidth;
201 $maxheight = (integer) $maxheight;
202 $alt = (string) $alt;
204 if ($this->getBlogOption(MediaUtils::$blogid, 'force_thumb') == 'yes') {
205 echo $this->getParsedTag(array('', '', $path, 0, 0, $alt), $maxwidth, $maxheight);
210 public function event_PreItem($data) {
211 $item =& $data["item"];
212 self::$authorid = $item->authorid;
213 $item->body = preg_replace_callback("#<\%(Thumbnail)\((.*?)\|(.*?)\|(.*?)\|(.*?)\)%\>#", array(&$this, 'getParsedTag'), $item->body);
214 $item->more = preg_replace_callback("#<\%(Thumbnail)\((.*?)\|(.*?)\|(.*?)\|(.*?)\)%\>#", array(&$this, 'getParsedTag'), $item->more);
216 if ($this->getBlogOption(MediaUtils::$blogid, 'force_thumb') == 'yes') {
217 $item->body = preg_replace_callback("#<\%(popup)\((.*?)\|(.*?)\|(.*?)\|(.*?)\)%\>#", array(&$this, 'getParsedTag'), $item->body);
218 $item->more = preg_replace_callback("#<\%(popup)\((.*?)\|(.*?)\|(.*?)\|(.*?)\)%\>#", array(&$this, 'getParsedTag'), $item->more);
223 public function event_PostMediaUpload ($data) {
225 if ($this->getOption('save_thumb') == 'no') {
229 $root = rtrim($DIR_MEDIA, '/');
230 $path = trim($data['collection'], '/');
231 $filename = trim($data['filename'], '/');
232 $maxwidth = $this->getOption('maxwidth');
233 $maxheight = $this->getOption('maxheight');
235 if (!MediaUtils::checkDir ($root . '/' . self::$thumbdir)) {
239 if (FALSE === ($medium = new Medium($root, "{$path}/{$filename}", MediaUtils::$prefix))) {
243 if (!array_key_exists($medium->mime, MediaUtils::$image_mime)) {
247 if (FALSE === $medium->setResampledSize($maxwidth, $maxheight)) {
251 $target = $this->getThumbPath($medium);
253 if ($this->getOption('save_thumb') == 'filesystem') {
254 if (!file_exists("{$root}/{$target}")
255 && !MediaUtils::storeResampledImage ($DIR_MEDIA, $target, $medium)) {
263 public function getParsedTag ($match, $maxwidth=0, $maxheight=0) {
264 global $DIR_MEDIA, $member;
266 list($code, $tag, $path, $width, $height, $alt) = $match;
268 if (!preg_match("#^.+?/.+$#", $path) && self::$authorid) {
269 $path = self::$authorid . '/' . $path;
272 if (FALSE === ($medium = new Medium($DIR_MEDIA, $path, MediaUtils::$prefix))) {
273 return $this->t('NP_Thumbnail: 指定したメディアファイルを読み込めませんでした。', array($path));
276 if (!array_key_exists($medium->mime, MediaUtils::$image_mime)) {
277 return $this->t(_NP_THUMBNAIL_12, array($path));
280 if ($tag == 'Thumbnail') {
281 $maxwidth = (integer) $width;
282 $maxheight = (integer) $height;
285 if (($maxwidth == 0) && ($maxheight == 0)) {
286 $maxwidth = (integer) $this->getOption('maxwidth');
287 $maxheight = (integer) $this->getOption('maxheight');
290 if ($maxwidth < 0 || $maxwidth > 1000 || $maxheight < 0 || $maxheight > 1000) {
291 return $this->t(_NP_THUMBNAIL_10, array($path));
294 if (FALSE === $medium->setResampledSize($maxwidth, $maxheight)) {
295 return $this->t('NP_Thumbnail: サムネイルのサイズが不正です。', array($path));
302 return $this->generateTag($this->getBlogOption(MediaUtils::$blogid, 'thumb_template'), $medium, $alt);
305 public function generateTag($template, $medium, $alt) {
308 if (!class_exists('BODYACTIONS', FALSE)) {
309 include($DIR_LIBS . 'BODYACTIONS.php');
311 $action = new BODYACTIONS;
313 if (array_key_exists($medium->mime, MediaUtils::$image_mime)
314 && $this->getOption('save_thumb') == 'filesystem') {
315 if (!MediaUtils::checkDir ($medium->root . '/' . self::$thumbdir)) {
316 return $this->t(_NP_THUMBNAIL_13, array(self::$thumbdir));
318 if (!file_exists("{$medium->root}/{$this->getThumbPath($medium)}")) {
319 MediaUtils::storeResampledImage ($medium->root, $this->getThumbPath($medium), $medium);
324 if (array_key_exists($medium->mime, MediaUtils::$image_mime) && $this->getThumbURL($medium)) {
325 $action->template['POPUP_CODE'] = $template;
326 $replacements = array(
327 '<%thumb_width%>' => $medium->resampledwidth,
328 '<%thumb_height%>' => $medium->resampledheight,
329 '<%thumb_url%>' => $this->getThumbURL($medium)
331 foreach ($replacements as $target => $replacement) {
332 $action->template['POPUP_CODE'] = str_replace ($target, $replacement, $action->template['POPUP_CODE']);
334 $action->createPopupCode ("{$medium->path}/{$medium->name}", $medium->width, $medium->height, $alt);
336 $action->template['MEDIA_CODE'] = $template;
337 $action->createMediaCode("{$medium->path}/{$medium->name}", $alt);
339 $tag = ob_get_contents();
342 return preg_replace('#href="(.*?)imagetext(.*?)"#', 'href="$1imagetext$2&blogid='.MediaUtils::$blogid . '"', $tag);
345 private function showAdmin ($type) {
346 global $CONF, $DIR_LIBS, $DIR_MEDIA, $manager;
348 $type = (string) $type;
350 if (!class_exists ('PLUGINADMIN', FALSE)) {
351 include ($DIR_LIBS . 'PLUGINADMIN.php');
354 $oPluginAdmin = new PluginAdmin('Thumbnail');
355 $oPluginAdmin->start();
357 echo "<h2>NP_Thumbnail</h2>\n";
359 if($this->getOption('save_thumb') === 'no') {
360 echo '<p>' . $this->t(_NP_THUMBNAIL_14) . "</p>\n";
361 $oPluginAdmin->end();
365 if ($type == 'clear') {
366 if ($this->getOption('save_thumb') == 'filesystem') {
367 $logs = MediaUtils::purgeDir($DIR_MEDIA, self::$thumbdir . '/');
369 } else if ($type == 'sync') {
370 $maxwidth = $this->getOption('maxwidth');
371 $maxheight = $this->getOption('maxheight');
372 if ($this->getOption('save_thumb') == 'filesystem') {
373 $logs = $this->syncFilesystem ($DIR_MEDIA, self::$thumbdir, $maxwidth, $maxheight);
379 $media = MediaUtils::getMediaList($DIR_MEDIA);
383 foreach ($media as $medium) {
384 if (!array_key_exists($medium->mime, MediaUtils::$image_mime)) {
387 if (file_exists ($DIR_MEDIA . $this->getThumbPath($medium))) {
388 $rejected[] = &$medium;
391 $elected[] = &$medium;
396 $total_media = count ($media);
397 $total_elected = count ($elected);
398 $total_rejected = count ($rejected);
399 $total_candidates = count ($rejected) + $total_elected;
401 echo "<p>" . $this->t(_NP_THUMBNAIL_15, array(self::$thumbdir)) . "<br />\n";
402 echo $this->t(_NP_THUMBNAIL_16, array(self::$max_sync)) . "<br />\n";
403 echo $this->t(_NP_THUMBNAIL_17) . "</p>\n";
406 * NOTICE: NP_Improvededia with eachblogdir option rewrite
407 * global variables of "DIR_MEDIA" and "$CONF['MediaURL']"
408 * in its initializing process.
409 * Here are based on its rewriting system.
411 if ($manager->pluginInstalled('NP_ImprovedMedia')) {
412 $NP_ImprovedMedia =& $manager->getPlugin('NP_ImprovedMedia');
413 if ($NP_ImprovedMedia->getOption('IM_EACHBLOGDIR') == 'yes') {
414 echo "<form method=\"post\" action=\"{$CONF['ActionURL']}?action=plugin&name=Thumbnail\" enctype=\"application/x-www-form-urlencoded\">\n";
416 echo "<label for=\"blogid\">サムネイル作成対象のウェブログ</label>\n";
417 echo "<select name=\"blogid\" id=\"blogid\"onchange=\"return form.submit()\">\n";
418 foreach(MediaUtils::$blogs as $blogid => $bshortname) {
419 if ($blogid == MediaUtils::$blogid) {
420 echo "<option value=\"{$blogid}\" selected=\"selected\">{$bshortname}</option>\n";
422 echo "<option value=\"{$blogid}\">{$bshortname}</option>\n";
426 echo "<input type=\"hidden\" id=\"admin\" name=\"type\" value=\"admin\">\n";
432 echo "<form method=\"post\" action=\"{$CONF['ActionURL']}?action=plugin&name=Thumbnail\" enctype=\"application/x-www-form-urlencoded\">\n";
434 echo "<li>" . $this->t(_NP_THUMBNAIL_18, array($total_media)) . "</li>\n";
435 echo "<li>" . $this->t(_NP_THUMBNAIL_19, array($total_candidates)) . "</li>\n";
436 echo "<li>" . $this->t(_NP_THUMBNAIL_20, array($total_rejected)) . "</li>\n";
439 echo '<input type="hidden" name="blogid" value="' . MediaUtils::$blogid . '">' . "\n";
440 echo "<input type=\"submit\" id=\"sync\" name=\"type\" value=\"sync\">\n";
441 echo "<input type=\"submit\" id=\"clear\" name=\"type\" value=\"clear\">\n";
445 echo "<h3>" . $this->t(_NP_THUMBNAIL_21) . "</h3>\n";
448 foreach ($logs as $log) {
449 echo "<li>{$log}</li>\n";
455 $oPluginAdmin->end();
459 public function syncFilesystem ($root, $dest, $maxwidth, $maxheight) {
462 $root = rtrim($root, '/');
463 if(!$root || !file_exists($root)) {
467 if (!MediaUtils::checkDir(rtrim($root, '/') . '/' . trim($dest, '/'))) {
471 $media = MediaUtils::getMediaList($root);
475 foreach ($media as $medium) {
476 if ($count > self::$max_sync) {
480 if (!array_key_exists ($medium->mime, MediaUtils::$image_mime)) {
484 if (FALSE === $medium->setResampledSize($maxwidth, $maxheight)) {
488 $destination = $this->getThumbPath($medium);
490 if (!file_exists (rtrim($root, '/') . '/' . $destination)) {
491 if (!MediaUtils::storeResampledImage ($root, $destination, $medium)) {
492 $logs[] = "Fail: {$medium->name}";
494 $logs[] = "Success: {$medium->name}";
502 public function getThumbPath($medium) {
503 if ('Medium' !== get_class($medium)) {
506 return self::$thumbdir . '/' . $medium->getHashedName(MediaUtils::$algorism) . MediaUtils::$image_mime[$medium->mime];
509 public function getThumbURL($medium) {
510 global $CONF, $DIR_MEDIA;
512 if ('Medium' !== get_class($medium)) {
516 if (($medium->width < $medium->resampledwidth && $medium->height < $medium->resampledheight)
517 || ($medium->width <= $this->getOption('maxwidth') && $medium->height <= $this->getOption('maxheight'))) {
518 $url = "{$CONF['MediaURL']}{$medium->path}/{$medium->name}";
519 } else if ($medium->resampledwidth > $this->getOption('maxwidth') && $medium->resampledheight > $this->getOption('maxheight')) {
520 $url = "{$CONF['ActionURL']}?action=plugin&name={$this->getName()}&path={$medium->path}/{$medium->name}&width={$medium->resampledwidth}&height={$medium->resampledheight}&blogid=" . MediaUtils::$blogid;
521 } else if (file_exists($DIR_MEDIA . $this->getThumbPath($medium))) {
522 $url = "{$CONF['MediaURL']}{$this->getThumbPath($medium)}";