3 * Attach plugin for Nucleus CMS
\r
4 * Version 1.0.0 for PHP5
\r
5 * Written By Mocchi, Oct. 20, 2012
\r
6 * Original code was written by NKJG and yamamoto, May 02, 2009
\r
7 * This plugin depends on NP_Thumbnail and NP_MediaUtils
\r
9 * This program is free software; you can redistribute it and/or
\r
10 * modify it under the terms of the GNU General Public License
\r
11 * as published by the Free Software Foundation; either version 3
\r
12 * of the License, or (at your option) any later version.
\r
15 // TODO (hard) If itemOption is set as "hidden", PrePluginOptionsUpdate event is not generated, related Nucleus CMS library problem.
\r
16 // TODO (hard) There are no ways to show the error message even if upload processing is failed.
\r
17 // TODO (medium) all of the plugin options are purged when uninstalling plugins.
\r
19 class NP_Attach extends NucleusPlugin
\r
21 static private $buffer = false;
\r
22 static private $blogid = 0;
\r
23 static private $itemid = 0;
\r
24 static private $amount = 0;
\r
25 static private $data = array();
\r
27 public function getName() { return 'Attach'; }
\r
28 public function getAuthor() { return 'Mocchi, yamamoto, NKJG'; }
\r
29 public function getURL() { return 'http://japan.nucleuscms.org/wiki/plugins:attach'; }
\r
30 public function getVersion() { return '1.0.0'; }
\r
31 public function getDescription() { return _NP_ATTACH_01; }
\r
32 public function getPluginDep() { return array('NP_MediaUtils', 'NP_Thumbnail');}
\r
33 public function getMinNucleusVersion() {return 340;}
\r
34 public function supportsFeature($feature) { return in_array($feature, array('SqlTablePrefix', 'SqlApi'));}
\r
35 public function getEventList()
\r
38 'PrePluginOptionsEdit',
\r
40 'BookmarkletExtraHead',
\r
46 'PrePluginOptionsUpdate',
\r
47 'AddItemFormExtras',
\r
48 'EditItemFormExtras');
\r
51 public function install()
\r
53 $this->createOption('maxwidth', '_NP_ATTACH_02', 'text', '90', 'datatype=numerical');
\r
54 $this->createOption('maxheight', '_NP_ATTACH_03', 'text', '90', 'datatype=numerical');
\r
55 $this->createOption('admin_popup_template', '_NP_ATTACH_04', 'textarea', '<a href="<%rawpopuplink%>" title="<%popuptext%>" onclick="<%popupcode%>"><img src="<%thumb_url%>" width="<%thumb_width%>" height="<%thumb_height%>" alt="<%popuptext%>" /></a>');
\r
56 $this->createOption('admin_media_template', '_NP_ATTACH_05', 'textarea', '<a href="<%link%>" title="<%text%>"><%text%></a>');
\r
57 $this->createBlogOption('amount', '_NP_ATTACH_06', 'text', '3');
\r
58 $this->createBlogOption('blog_image_template', '_NP_ATTACH_07', 'textarea', '<img src="<%link%>" width="<%width%>" height="<%height%>" alt="<%text%>" />');
\r
59 $this->createBlogOption('blog_media_template', '_NP_ATTACH_08', 'textarea', '<a href="<%link%>" title="<%text%>"><%text%></a>');
\r
60 $this->createItemOption('media', '_NP_ATTACH_09', 'text', '');
\r
64 public function uninstall()
\r
69 public function init()
\r
74 if ( class_exists('i18n', FALSE) )
\r
76 $locale = i18n::get_current_locale() . '.' . i18n::get_current_charset() . '.php';
\r
81 $language = preg_replace('#[/|\\\\]#', '', getLanguageName());
\r
82 if ( $language == 'japanese-euc' )
\r
84 $locale = 'ja_Jpan_JP.EUC-JP.php';
\r
86 else if ( $language = 'japanese-utf8' )
\r
88 $locale = 'ja_Jpan_JP.UTF-8.php';
\r
92 if ( !$locale || !file_exists($this->getDirectory() . $locale) )
\r
94 include($this->getDirectory() . 'en_Latn_US.ISO-8859-1.php');
\r
98 include($this->getDirectory() . $locale);
\r
107 public function event_PrePluginOptionsEdit(&$data)
\r
109 /* Old version do not support natively */
\r
110 if ( getNucleusVersion() < 400 )
\r
112 if ( $data['context'] != 'global' )
\r
114 foreach ( $data['options'] as $key => $option )
\r
116 if ( $option['pid'] == $this->getID() )
\r
118 if ( defined($option['description']) )
\r
120 $data['options'][$key]['description'] = constant($option['description']);
\r
122 if ( $option['type'] == 'select' )
\r
124 foreach ( explode('|', $option['typeinfo']) as $option )
\r
126 if ( defined($option) )
\r
128 $data['options'][$key]['typeinfo'] = str_replace($option, constant($option), $data['options'][$key]['typeinfo']);
\r
135 else if ($data['plugid'] == $this->getID() )
\r
137 foreach ( $data['options'] as $key => $option )
\r
139 if ( defined($option['description']) )
\r
141 $data['options'][$key]['description'] = constant($option['description']);
\r
143 if ( $option['type'] == 'select' )
\r
145 foreach ( explode('|', $option['typeinfo']) as $option )
\r
147 if ( defined($option) )
\r
149 $data['options'][$key]['typeinfo'] = str_replace($option, constant($option), $data['options'][$key]['typeinfo']);
\r
161 * Change enctype attribute of form element as 'multipart/form-data'
\r
164 public function event_AdminPrePageHead(&$data)
\r
166 if ( !in_array ($data['action'], array('createitem', 'itemedit')) )
\r
168 self::prepareEnctype();
\r
173 public function event_BookmarkletExtraHead(&$data)
\r
175 self::prepareEnctype();
\r
179 public function event_AddItemFormExtras(&$data)
\r
182 $blog = $data['blog'];
\r
183 self::$blogid = $blog->blogid;
\r
185 self::setEnctype();
\r
186 $this->setData($DIR_MEDIA);
\r
187 $this->showInterface();
\r
191 public function event_EditItemFormExtras(&$data)
\r
194 $blog = $data['blog'];
\r
195 self::$blogid = $blog->blogid;
\r
196 self::$itemid = $data['itemid'];
\r
197 self::setEnctype();
\r
198 $this->setData($DIR_MEDIA);
\r
199 $this->showInterface();
\r
204 * Process upload and update plugin item option
\r
206 public function event_PreAddItem(&$data)
\r
208 self::$blogid = $data['blog']->blogid;
\r
212 public function event_PreUpdateItem(&$data)
\r
214 self::$blogid = $data['blog']->blogid;
\r
218 public function event_PostAddItem(&$data)
\r
220 self::$itemid = $data['itemid'];
\r
224 public function event_PostUpdateItem(&$data)
\r
226 self::$itemid = $data['itemid'];
\r
230 public function event_PrePluginOptionsUpdate(&$data)
\r
232 global $DIR_MEDIA, $member;
\r
234 if ( $data['plugid'] != $this->getID() || $data['optionname'] != 'media' )
\r
239 $this->setData($DIR_MEDIA);
\r
240 self::batchRequest($DIR_MEDIA, $member->getID());
\r
243 foreach ( self::$data as $datum )
\r
245 if ( !$datum['path'] )
\r
249 $value .= "{$datum['path']}:{$datum['alt']}:{$datum['way']};";
\r
252 $data['value'] = $value;
\r
257 * Show media in item
\r
259 public function event_PreItem(&$data)
\r
263 self::$blogid =& $data['blog']->blogid;
\r
264 self::$itemid =& $data["item"]->itemid;
\r
265 $this->setData($DIR_MEDIA);
\r
267 $data["item"]->body = preg_replace_callback("#<\%Attach\((.+?)(,.+?)?(,.+?)?\)%\>#", array($this, 'getParsedTag'), $data["item"]->body);
\r
268 $data["item"]->more = preg_replace_callback("#<\%Attach\((.+?)(,.+?)?(,.+?)?\)%\>#", array($this, 'getParsedTag'), $data["item"]->more);
\r
272 public function doTemplateVar(&$item)
\r
274 global $DIR_MEDIA, $blogid;
\r
276 /* receive an argument, with prevention of E_STRICT*/
\r
277 $args = func_get_args();
\r
278 if ( !array_key_exists(0, $args) )
\r
284 $mediumid = $args[0];
\r
287 if ( !self::$itemid || !self::$blogid )
\r
289 self::$blogid = $blogid;
\r
290 self::$itemid = $item->itemid;
\r
291 $this->setData($DIR_MEDIA);
\r
294 $params = array('item', $mediumid);
\r
295 $this->getParsedTag($params);
\r
299 private function getParsedTag($match)
\r
301 global $DIR_MEDIA, $manager;
\r
303 /* receice maximum dimension */
\r
306 if ( array_key_exists(3, $match) )
\r
308 $maxheight = (integer) trim($match[3], ',');
\r
310 if ( array_key_exists(2, $match) )
\r
312 $maxwidth = (integer) trim($match[2], ',');
\r
315 /* ID in tag starts 1 but ID in program starts 0 */
\r
316 $mediumid = $match[1];
\r
319 /* filled tag or blank if failed */
\r
320 $tag = $this->generateParsedTag($maxwidth, $maxheight);
\r
325 private function generateParsedTag($maxwidth, $maxheight)
\r
327 global $manager, $DIR_MEDIA;
\r
329 /* check medium has path */
\r
330 $data = &self::$data;
\r
331 if ( !array_key_exists($mediumid, $data) || !$data[$mediumid]['path'] )
\r
336 /* receive an instance of NP_Thumbnail class */
\r
337 $NP_Thumbnail =& $manager->getPlugin('NP_Thumbnail');
\r
339 /* confirm to have maximum dimension */
\r
340 if ( $maxwidth == 0 && $maxheight == 0 )
\r
342 $maxwidth = $NP_Thumbnail->getOption('maxwidth');
\r
343 $maxheight = $NP_Thumbnail->getOption('maxheight');
\r
346 /* receive an instance of MEDIUM class */
\r
347 if ( FALSE === ($medium = new MEDIUM($DIR_MEDIA, $data[$mediumid]['path'], MediaUtils::$prefix)) )
\r
352 /* take the instance having correct resampled dimension */
\r
353 if ( array_key_exists($medium->mime, MediaUtils::$image_mime)
\r
354 && !$medium->setResampledSize($maxwidth, $maxheight) )
\r
359 /* receive template */
\r
360 if ( !array_key_exists($medium->mime, MediaUtils::$image_mime)
\r
361 || $data[$mediumid]['way'] == 'anchor' )
\r
363 $template = $this->getBlogOption(self::$blogid, 'blog_media_template');
\r
365 else if ( $data[$mediumid]['way'] == 'original' )
\r
367 $template = $this->getBlogOption(self::$blogid, 'blog_image_template');
\r
371 $template = $NP_Thumbnail->getBlogOption(self::$blogid, 'thumb_template');
\r
374 /* return filled template */
\r
375 return $NP_Thumbnail->generateTag($template, $medium, $data[$mediumid]['alt']);
\r
378 private function showInterface()
\r
380 global $CONF, $DIR_LIBS, $DIR_MEDIA, $manager;
\r
382 if ( !class_exists('BODYACTIONS', FALSE) )
\r
384 include($DIR_LIBS . 'BODYACTIONS.php');
\r
386 $action = new BODYACTIONS;
\r
388 if ( !$manager->pluginInstalled('NP_Thumbnail') )
\r
392 $NP_Thumbnail = &$manager->getPlugin('NP_Thumbnail');
\r
393 $maxwidth = $NP_Thumbnail->getOption('maxwidth');
\r
394 $maxheight = $NP_Thumbnail->getOption('maxheight');
\r
396 if ( !self::$amount )
\r
401 $data = self::$data;
\r
403 if ( empty($data) )
\r
408 echo "<table frame=\"box\" rules=\"all\" summary=\"Attached Media\">\n";
\r
411 echo "<th>" . _NP_ATTACH_10 . "</th>\n";
\r
412 echo "<th>" . _NP_ATTACH_11 . "</th>\n";
\r
413 echo "<th>" . _NP_ATTACH_12 . "</th>\n";
\r
418 for ( $count = 0; $count < self::$amount; $count++ )
\r
424 echo "<label for=\"alt{$count}\"><%Attach({$id})%></label>\n";
\r
426 if ( $data[$count]['path'] )
\r
429 echo "<input type=\"checkbox\" id=\"delete{$count}\" name=\"delete[{$count}]\" value=\"1\" />\n";
\r
430 echo "<label for=\"delete{$count}\">" . _NP_ATTACH_13 . "</label>\n";
\r
436 if ( !$data[$count]['path'] )
\r
438 echo "<input type=\"file\" id=\"medium{$count}\" name=\"medium[{$count}]\" size=\"1\" /><br />\n";
\r
442 if ( FALSE === ($medium = new MEDIUM($DIR_MEDIA, $data[$count]['path'], MediaUtils::$prefix)) )
\r
447 if ( array_key_exists($medium->mime, MediaUtils::$image_mime)
\r
448 && !$medium->setResampledSize($maxwidth, $maxheight) )
\r
453 if ( array_key_exists($medium->mime, MediaUtils::$image_mime) )
\r
455 $template = $this->getOption('admin_popup_template');
\r
459 $template = $this->getOption('admin_media_template');
\r
462 echo $NP_Thumbnail->generateTag($template, $medium, $data[$count]['alt']) . "<br />\n";
\r
463 echo "<input type=\"hidden\" id=\"path{$count}\" name=\"path[{$count}]\" value=\"{$data[$count]['path']}\" /><br />\n";
\r
465 echo "<input type=\"text\" id=\"alt{$count}\" name=\"alt[{$count}]\" value=\"{$data[$count]['alt']}\" size=\"12\" />\n";
\r
469 if ( $data[$count]['path'] && !array_key_exists($data[$count]['mime'], MediaUtils::$image_mime) )
\r
471 echo "<input type=\"hidden\" name=\"way[{$count}]\" value=\"anchor\" />\n";
\r
472 echo _NP_ATTACH_14 . "\n";
\r
476 $thumbnail_checked = "";
\r
477 $original_checked = "";
\r
478 $anchor_checked = "";
\r
480 if ( $data[$count]['way'] == 'original' )
\r
482 $original_checked = 'checked="checked"';
\r
484 else if ($data[$count]['way'] == 'anchor' )
\r
486 $anchor_checked = 'checked="checked"';
\r
490 $thumbnail_checked = 'checked="checked"';
\r
493 echo "<input type=\"radio\" id=\"way{$count}-anchor\" name=\"way[{$count}]\" value=\"anchor\" {$anchor_checked} />\n";
\r
494 echo "<label for=\"way{$count}-anchor\">" . _NP_ATTACH_15 . "<label><br />\n";
\r
495 echo "<input type=\"radio\" id=\"way{$count}-small\" name=\"way[{$count}]\" value=\"thumbnail\" {$thumbnail_checked} />\n";
\r
496 echo "<label for=\"way{$count}-small\">" . _NP_ATTACH_16 . "<label><br />\n";
\r
497 echo "<input type=\"radio\" id=\"way{$count}-original\" name=\"way[{$count}]\" value=\"original\" {$original_checked} />\n";
\r
498 echo "<label for=\"way{$count}-original\">" . _NP_ATTACH_17 . "<label>\n";
\r
509 private function setData($root)
\r
511 if ( self::$blogid === 0 || !self::$itemid === 0 )
\r
516 self::$amount = $this->getBlogOption(self::$blogid, 'amount');
\r
517 $media = explode(';', $this->getitemOption(self::$itemid, 'media'));
\r
520 for ( $count = 0; $count < self::$amount; $count++ )
\r
522 if ( (self::$itemid != 0) && array_key_exists($count, $media) && !empty($media[$count]) )
\r
524 $medium = explode(':', $media[$count]);
\r
525 $data[$count]['path'] = $medium[0];
\r
526 $data[$count]['alt'] = $medium[1];
\r
527 $data[$count]['way'] = $medium[2];
\r
529 if ( FALSE === ($file = new Medium($root, $data[$count]['path'], MediaUtils::$prefix)) )
\r
531 $data[$count] = array('path' => "", 'alt' => "", 'way' => "");
\r
534 $data[$count]['mime'] = $file->mime;
\r
535 $data[$count]['width'] = $file->width;
\r
536 $data[$count]['height'] = $file->height;
\r
540 $data[$count] = array('path' => "", 'alt' => "", 'way' => "");
\r
544 self::$data = $data;
\r
548 static private function batchRequest($root, $collection)
\r
550 global $CONF, $manager;
\r
555 $deletes = array();
\r
557 if ( array_key_exists('medium', $_FILES) )
\r
559 $media = $_FILES['medium'];
\r
562 if ( array_key_exists('path', $_POST) )
\r
564 $paths = $_POST['path'];
\r
567 if ( array_key_exists('alt', $_POST) )
\r
569 $alts = $_POST['alt'];
\r
572 if ( array_key_exists('way', $_POST) )
\r
574 $ways = $_POST['way'];
\r
577 if ( array_key_exists('delete', $_POST) )
\r
579 $deletes = $_POST['delete'];
\r
582 $data = &self::$data;
\r
584 if ( !$manager->pluginInstalled('NP_Thumbnail') )
\r
589 foreach ( $data as $key => $value )
\r
591 if ( $media && array_key_exists($key, $media['name']) && !empty($media['name'][$key]) )
\r
594 if ( preg_match ("#(\\\\|/|\\n)#", $media['name'][$key]) )
\r
596 $data[$key] = array('path' => "", 'alt' => "", 'way' => "");
\r
600 $medium['name'] = &$media['name'][$key];
\r
601 $medium['size'] = $media['size'][$key];
\r
602 $medium['tmp_name'] = $media['tmp_name'][$key];
\r
603 $medium['error'] = $media['error'][$key];
\r
605 $result = MediaUtils::uploadMedium($root, $collection, $medium, '', $manager);
\r
609 $data[$key]['path'] = "";
\r
610 $data[$key]['alt'] = "{$result} ({$medium['name']})";
\r
611 $data[$key]['way'] = "";
\r
616 $data[$key]['path'] = "{$collection}/{$medium['name']}";
\r
619 else if ( array_key_exists($key, $paths) && !empty($paths[$key]) )
\r
621 if ( FALSE === ($medium = new MEDIUM($root, $paths[$key], MediaUtils::$prefix)) )
\r
623 $data[$key] = array('path' => "", 'alt' => "", 'way' => "");
\r
626 if ( $deletes && array_key_exists($key, $deletes) && $deletes[$key] == 1 )
\r
628 if ( @unlink($root . $paths[$key]) )
\r
630 if ( array_key_exists($medium->mime, MediaUtils::$image_mime) )
\r
632 @ unlink($root . NP_Thumbnail::getThumbPath($medium));
\r
634 $data[$key] = array('path' => "", 'alt' => "", 'way' => "");
\r
640 if ( array_key_exists($key, $alts) && $alts[$key] != $value['alt'] )
\r
642 $data[$key]['alt'] = htmlspecialchars($alts[$key], ENT_QUOTES, _CHARSET);
\r
645 if ( array_key_exists($key, $ways) && $ways[$key] != $value['way'] )
\r
647 if ( !in_array($ways[$key], array('thumbnail', 'original', 'anchor')) )
\r
649 $data[$key]['way'] = 'thumbnail';
\r
653 $data[$key]['way'] = $ways[$key];
\r
660 static private function prepareEnctype()
\r
662 self::$buffer = ob_start();
\r
666 static private function setEnctype()
\r
668 if ( !self::$buffer )
\r
673 $strings = ob_get_contents();
\r
675 $strings = preg_replace('#action="(index.php|bookmarklet.php)"#', '$0 enctype="multipart/form-data"', $strings);
\r