OSDN Git Service

b73f4566cb0cc62a4866f2fd569bd6da56814818
[nucleus-jp/nucleus-plugins.git] / NP_Thumbnail / NP_Thumbnail.php
1 <?php
2 /**
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
8  * 
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.
13  */
14
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
21         
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'); }
31         
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>');
38                 return;
39         }
40         
41         /*
42          * plugin options are purged automatically when uninstalled.
43          */
44         public function uninstall() {
45                 global $DIR_MEDIA;
46                 MediaUtils::purgeDir($DIR_MEDIA . self::$thumbdir);
47                 return;
48         }
49         
50         public function init() {
51                 global $DIR_MEDIA;
52                 
53                 if (!class_exists('Medium', FALSE)) {
54                         include(MediaUtils::$lib_path . '/Medium.php');
55                 }
56                 
57                 $language = preg_replace('#[/|\\\\]#', '', getLanguageName());
58                 
59                 if (!defined('_NP_THUMBNAIL_01')) {
60                         if (file_exists($this->getDirectory() . $language.'.php')) {
61                                 include($this->getDirectory() . $language.'.php');
62                         } else {
63                                 include($this->getDirectory() . 'english.php');
64                         }
65                 }
66                 return;
67         }
68         
69 /*
70  * for translation
71  */
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']);
78                                         }
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']);
83                                                         }
84                                                 }
85                                         }
86                                 }
87                         }
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']);
92                                 }
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']);
97                                                         }
98                                                 }
99                                 }
100                         }
101                 }
102                 return;
103         }
104         
105 /*
106  * for translation
107  */
108         static private function t ($text, $array=array()){
109                 if (is_array($array)) {
110                         $search = array();
111                         $replace = array();
112                         
113                         foreach ($array as $key => $value){
114                                 if (is_array($value)) {
115                                         continue;
116                                 }
117                                 $search[] = '<%'.preg_replace('/[^a-zA-Z0-9_]+/','',$key).'%>';
118                                 $replace[] = $value;
119                         }
120                 }
121                 return htmlspecialchars (str_replace($search, $replace, $text), ENT_QUOTES, _CHARSET);
122         }
123         
124         public function event_QuickMenu ($data) {
125                 global $CONF;
126                 if($this->getOption('save_thumb') !== 'no') {
127                         array_push(
128                                 $data['options'],
129                                 array (
130                                         'title'   => 'NP_Thumbnail',
131                                         'url'     => "{$CONF['ActionURL']}?action=plugin&name={$this->getname()}&type=admin",
132                                         'tooltip' => _NP_THUMBNAIL_09));
133                 }
134                 return;
135         }
136         
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;
147                 }
148                 return;
149         }
150         
151         public function doAction ($type) {
152                 global $DIR_MEDIA, $member;
153                 
154                 $type = (string) $type;
155                 
156                 $path = '';
157                 $maxwidth = '';
158                 $maxheight = '';
159                 
160                 if (array_key_exists('path', $_GET)) {
161                         $path = (string)  $_GET['path'];
162                 }
163                 if (array_key_exists('width', $_GET)) {
164                         $maxwidth = (integer) $_GET['width'];
165                 }
166                 if (array_key_exists('height', $_GET)) {
167                         $maxheight = (integer) $_GET['height'];
168                 }
169                 
170                 if (in_array($type, array('admin', 'clear', 'sync')) && $member->isAdmin()) {
171                         $this->showAdmin($type);
172                         exit;
173                 }
174                 
175                 if (self::$buffering) {
176                         ob_end_clean();
177                 }
178                 
179                 if ($maxwidth <= 0 || $maxwidth > 1000 || $maxheight <= 0 || $maxheight > 1000 ) {
180                         MediaUtils::error ($this->t(_NP_THUMBNAIL_10, array($maxwidth, $maxheight)));
181                         return;
182                 }
183                 
184                 if (FALSE === ($medium = new Medium($DIR_MEDIA, $path, MediaUtils::$prefix))) {
185                         MediaUtils::error ($this->t(_NP_THUMBNAIL_11, array($path)));
186                         return;
187                 }
188                 
189                 if (FALSE === $medium->setResampledSize($maxwidth, $maxheight)) {
190                         MediaUtils::error ($this->t(_NP_THUMBNAIL_10, array($maxwidth, $maxheight)));
191                         return;
192                 }
193                 
194                 MediaUtils::responseResampledImage($medium);
195                 return;
196         }
197         
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;
203                 
204                 if ($this->getBlogOption(MediaUtils::$blogid, 'force_thumb') == 'yes') {
205                         echo $this->getParsedTag(array('', '', $path, 0, 0, $alt), $maxwidth, $maxheight);
206                 }
207                 return;
208         }
209         
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);
215                 
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);
219                 }
220                 return;
221         }
222         
223         public function event_PostMediaUpload ($data) {
224                 global $DIR_MEDIA;
225                 if ($this->getOption('save_thumb') == 'no') {
226                         return;
227                 }
228                 
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');
234                 
235                 if (!MediaUtils::checkDir ($root . '/' . self::$thumbdir)) {
236                         return;
237                 }
238                 
239                 if (FALSE === ($medium = new Medium($root, "{$path}/{$filename}", MediaUtils::$prefix))) {
240                         return;
241                 }
242                 
243                 if (!array_key_exists($medium->mime, MediaUtils::$image_mime)) {
244                         return;
245                 }
246                 
247                 if (FALSE === $medium->setResampledSize($maxwidth, $maxheight)) {
248                         return;
249                 }
250                 
251                 $target = $this->getThumbPath($medium);
252                 
253                 if ($this->getOption('save_thumb') == 'filesystem') {
254                         if (!file_exists("{$root}/{$target}")
255                                 && !MediaUtils::storeResampledImage ($DIR_MEDIA, $target, $medium)) {
256                                 return;
257                         }
258                 }
259                 
260                 return;
261         }
262         
263         public function getParsedTag ($match, $maxwidth=0, $maxheight=0) {
264                 global $DIR_MEDIA, $member;
265                 
266                 list($code, $tag, $path, $width, $height, $alt) = $match;
267                 
268                 if (!preg_match("#^.+?/.+$#", $path) && self::$authorid) {
269                         $path = self::$authorid . '/' . $path;
270                 }
271                 
272                 if (FALSE === ($medium = new Medium($DIR_MEDIA, $path, MediaUtils::$prefix))) {
273                         return $this->t('NP_Thumbnail: 指定したメディアファイルを読み込めませんでした。', array($path));
274                 }
275                 
276                 if (!array_key_exists($medium->mime, MediaUtils::$image_mime)) {
277                         return $this->t(_NP_THUMBNAIL_12, array($path));
278                 }
279                 
280                 if ($tag == 'Thumbnail') {
281                         $maxwidth  = (integer) $width;
282                         $maxheight = (integer) $height;
283                 }
284                 
285                 if (($maxwidth == 0) && ($maxheight == 0)) {
286                         $maxwidth  = (integer) $this->getOption('maxwidth');
287                         $maxheight = (integer) $this->getOption('maxheight');
288                 }
289                 
290                 if ($maxwidth < 0 || $maxwidth > 1000 || $maxheight < 0 || $maxheight > 1000) {
291                         return $this->t(_NP_THUMBNAIL_10, array($path));
292                 }
293                 
294                 if (FALSE === $medium->setResampledSize($maxwidth, $maxheight)) {
295                         return $this->t('NP_Thumbnail: サムネイルのサイズが不正です。', array($path));
296                 }
297                 
298                 if (!$alt) {
299                         $alt =& $path;
300                 }
301                 
302                 return $this->generateTag($this->getBlogOption(MediaUtils::$blogid, 'thumb_template'), $medium, $alt);
303         }
304         
305         public function generateTag($template, $medium, $alt) {
306                 global $DIR_LIBS;
307                 
308                 if (!class_exists('BODYACTIONS', FALSE)) {
309                         include($DIR_LIBS . 'BODYACTIONS.php');
310                 }
311                 $action = new BODYACTIONS;
312                 
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));
317                         }
318                         if (!file_exists("{$medium->root}/{$this->getThumbPath($medium)}")) {
319                                 MediaUtils::storeResampledImage ($medium->root, $this->getThumbPath($medium), $medium);
320                         }
321                 }
322                 
323                 ob_start();
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)
330                         );
331                         foreach ($replacements as $target => $replacement) {
332                                 $action->template['POPUP_CODE'] = str_replace ($target, $replacement, $action->template['POPUP_CODE']);
333                         }
334                         $action->createPopupCode ("{$medium->path}/{$medium->name}", $medium->width, $medium->height, $alt);
335                 } else {
336                         $action->template['MEDIA_CODE'] = $template;
337                         $action->createMediaCode("{$medium->path}/{$medium->name}", $alt);
338                 }
339                 $tag = ob_get_contents();
340                 ob_get_clean();
341                 
342                 return preg_replace('#href="(.*?)imagetext(.*?)"#', 'href="$1imagetext$2&amp;blogid='.MediaUtils::$blogid . '"', $tag);
343         }
344         
345         private function showAdmin ($type) {
346                 global $CONF, $DIR_LIBS, $DIR_MEDIA, $manager;
347                 
348                 $type = (string) $type;
349                 
350                 if (!class_exists ('PLUGINADMIN', FALSE)) {
351                         include ($DIR_LIBS . 'PLUGINADMIN.php');
352                 }
353                 
354                 $oPluginAdmin = new PluginAdmin('Thumbnail');
355                 $oPluginAdmin->start();
356                 
357                 echo "<h2>NP_Thumbnail</h2>\n";
358                 
359                 if($this->getOption('save_thumb') === 'no') {
360                         echo '<p>' . $this->t(_NP_THUMBNAIL_14) . "</p>\n";
361                         $oPluginAdmin->end();
362                         return;
363                 }
364                 
365                 if ($type == 'clear') {
366                         if ($this->getOption('save_thumb') == 'filesystem') {
367                                 $logs = MediaUtils::purgeDir($DIR_MEDIA, self::$thumbdir . '/');
368                         }
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);
374                         }
375                 } else {
376                         $logs = array ();
377                 }
378                 
379                 $media = MediaUtils::getMediaList($DIR_MEDIA);
380                 $elected = array();
381                 $rejected = array();
382                 
383                 foreach ($media as $medium) {
384                         if (!array_key_exists($medium->mime, MediaUtils::$image_mime)) {
385                                 continue;
386                         }
387                         if (file_exists ($DIR_MEDIA . $this->getThumbPath($medium))) {
388                                 $rejected[] = &$medium;
389                                 continue;
390                         } else {
391                                 $elected[] = &$medium;
392                                 continue;
393                         }
394                 }
395                 
396                 $total_media = count ($media);
397                 $total_elected = count ($elected);
398                 $total_rejected = count ($rejected);
399                 $total_candidates = count ($rejected) + $total_elected;
400                 
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";
404                 
405                 /*
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.
410                  */
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";
415                                 echo "<p>\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";
421                                         } else {
422                                                 echo "<option value=\"{$blogid}\">{$bshortname}</option>\n";
423                                         }
424                                 }
425                                 echo "</select>\n";
426                                 echo "<input type=\"hidden\" id=\"admin\" name=\"type\" value=\"admin\">\n";
427                                 echo "</p>\n";
428                                 echo "</form>\n";
429                         }
430                 }
431                 
432                 echo "<form method=\"post\" action=\"{$CONF['ActionURL']}?action=plugin&name=Thumbnail\" enctype=\"application/x-www-form-urlencoded\">\n";
433                 echo "<ul>\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";
437                 echo "</ul>\n";
438                 echo "<p>\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";
442                 echo "</p>\n";
443                 
444                 if ($logs) {
445                         echo "<h3>" . $this->t(_NP_THUMBNAIL_21) . "</h3>\n";
446                         echo "<ul>\n";
447                         
448                         foreach ($logs as $log) {
449                                 echo "<li>{$log}</li>\n";
450                         }
451                         echo "</ul>\n";
452                 }
453                 echo "</form>\n";
454                 
455                 $oPluginAdmin->end();
456                 return;
457         }
458         
459         public function syncFilesystem ($root, $dest, $maxwidth, $maxheight) {
460                 $logs = array ();
461                 
462                 $root = rtrim($root, '/');
463                 if(!$root || !file_exists($root)) {
464                         return FALSE;
465                 }
466                 
467                 if (!MediaUtils::checkDir(rtrim($root, '/') . '/' . trim($dest, '/'))) {
468                         return FALSE;
469                 }
470                 
471                 $media = MediaUtils::getMediaList($root);
472                 $targets = array();
473                 $count = 1;
474                 
475                 foreach ($media as $medium) {
476                         if ($count > self::$max_sync) {
477                                 break;
478                         }
479                         
480                         if (!array_key_exists ($medium->mime, MediaUtils::$image_mime)) {
481                                 continue;
482                         }
483                         
484                         if (FALSE === $medium->setResampledSize($maxwidth, $maxheight)) {
485                                 continue;
486                         }
487                         
488                         $destination = $this->getThumbPath($medium);
489                         
490                         if (!file_exists (rtrim($root, '/') . '/' . $destination)) {
491                                 if (!MediaUtils::storeResampledImage ($root, $destination, $medium)) {
492                                         $logs[] = "Fail: {$medium->name}";
493                                 } else {
494                                         $logs[] = "Success: {$medium->name}";
495                                 }
496                                 $count++;
497                         }
498                 }
499                 return $logs;
500         }
501         
502         public function getThumbPath($medium) {
503                 if ('Medium' !== get_class($medium)) {
504                         return FALSE;
505                 }
506                 return self::$thumbdir . '/' . $medium->getHashedName(MediaUtils::$algorism) . MediaUtils::$image_mime[$medium->mime];
507         }
508         
509         public function getThumbURL($medium) {
510                 global $CONF, $DIR_MEDIA;
511                 
512                 if ('Medium' !== get_class($medium)) {
513                         return FALSE;
514                 }
515                 
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&amp;name={$this->getName()}&amp;path={$medium->path}/{$medium->name}&amp;width={$medium->resampledwidth}&amp;height={$medium->resampledheight}&amp;blogid=" . MediaUtils::$blogid;
521                 } else if (file_exists($DIR_MEDIA . $this->getThumbPath($medium))) {
522                         $url = "{$CONF['MediaURL']}{$this->getThumbPath($medium)}";
523                 } else {
524                         $url = FALSE;
525                 }
526                 return $url;
527         }
528 }
529