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, $mediumid)
\r
274 global $DIR_MEDIA, $blogid;
\r
276 if ( !self::$itemid || !self::$blogid )
\r
278 self::$blogid = $blogid;
\r
279 self::$itemid = $item->itemid;
\r
280 $this->setData($DIR_MEDIA);
\r
283 $params = array('item', $mediumid);
\r
284 $this->getParsedTag($params);
\r
288 private function getParsedTag($match)
\r
290 global $DIR_MEDIA, $manager;
\r
292 /* receice maximum dimension */
\r
295 if ( array_key_exists(3, $match) )
\r
297 $maxheight = (integer) trim($match[3], ',');
\r
299 if ( array_key_exists(2, $match) )
\r
301 $maxwidth = (integer) trim($match[2], ',');
\r
304 /* ID in tag starts 1 but ID in program starts 0 */
\r
305 $mediumid = $match[1];
\r
308 /* filled tag or blank if failed */
\r
309 $tag = $this->generateParsedTag($maxwidth, $maxheight);
\r
314 private function generateParsedTag($maxwidth, $maxheight)
\r
318 /* check medium has path */
\r
319 $data = &self::$data;
\r
320 if ( !array_key_exists($mediumid, $data) || !$data[$mediumid]['path'] )
\r
325 /* receive an instance of NP_Thumbnail class */
\r
326 $NP_Thumbnail =& $manager->getPlugin('NP_Thumbnail');
\r
328 /* confirm to have maximum dimension */
\r
329 if ( $maxwidth == 0 && $maxheight == 0 )
\r
331 $maxwidth = $NP_Thumbnail->getOption('maxwidth');
\r
332 $maxheight = $NP_Thumbnail->getOption('maxheight');
\r
335 /* receive an instance of MEDIUM class */
\r
336 if ( FALSE === ($medium = new MEDIUM($DIR_MEDIA, $data[$mediumid]['path'], MediaUtils::$prefix)) )
\r
341 /* take the instance having correct resampled dimension */
\r
342 if ( array_key_exists($medium->mime, MediaUtils::$image_mime)
\r
343 && !$medium->setResampledSize($maxwidth, $maxheight) )
\r
348 /* receive template */
\r
349 if ( !array_key_exists($medium->mime, MediaUtils::$image_mime)
\r
350 || $data[$mediumid]['way'] == 'anchor' )
\r
352 $template = $this->getBlogOption(self::$blogid, 'blog_media_template');
\r
354 else if ( $data[$mediumid]['way'] == 'original' )
\r
356 $template = $this->getBlogOption(self::$blogid, 'blog_image_template');
\r
360 $template = $NP_Thumbnail->getBlogOption(self::$blogid, 'thumb_template');
\r
363 /* return filled template */
\r
364 return $NP_Thumbnail->generateTag($template, $medium, $data[$mediumid]['alt']);
\r
367 private function showInterface()
\r
369 global $CONF, $DIR_LIBS, $DIR_MEDIA, $manager;
\r
371 if ( !class_exists('BODYACTIONS', FALSE) )
\r
373 include($DIR_LIBS . 'BODYACTIONS.php');
\r
375 $action = new BODYACTIONS;
\r
377 if ( !$manager->pluginInstalled('NP_Thumbnail') )
\r
381 $NP_Thumbnail = &$manager->getPlugin('NP_Thumbnail');
\r
382 $maxwidth = $NP_Thumbnail->getOption('maxwidth');
\r
383 $maxheight = $NP_Thumbnail->getOption('maxheight');
\r
385 if ( !self::$amount )
\r
390 $data = self::$data;
\r
392 if ( empty($data) )
\r
397 echo "<table frame=\"box\" rules=\"all\" summary=\"Attached Media\">\n";
\r
400 echo "<th>" . _NP_ATTACH_10 . "</th>\n";
\r
401 echo "<th>" . _NP_ATTACH_11 . "</th>\n";
\r
402 echo "<th>" . _NP_ATTACH_12 . "</th>\n";
\r
407 for ( $count = 0; $count < self::$amount; $count++ )
\r
413 echo "<label for=\"alt{$count}\"><%Attach({$id})%></label>\n";
\r
415 if ( $data[$count]['path'] )
\r
418 echo "<input type=\"checkbox\" id=\"delete{$count}\" name=\"delete[{$count}]\" value=\"1\" />\n";
\r
419 echo "<label for=\"delete{$count}\">" . _NP_ATTACH_13 . "</label>\n";
\r
425 if ( !$data[$count]['path'] )
\r
427 echo "<input type=\"file\" id=\"medium{$count}\" name=\"medium[{$count}]\" size=\"1\" /><br />\n";
\r
431 if ( FALSE === ($medium = new MEDIUM($DIR_MEDIA, $data[$count]['path'], MediaUtils::$prefix)) )
\r
436 if ( array_key_exists($medium->mime, MediaUtils::$image_mime)
\r
437 && !$medium->setResampledSize($maxwidth, $maxheight) )
\r
442 if ( array_key_exists($medium->mime, MediaUtils::$image_mime) )
\r
444 $template = $this->getOption('admin_popup_template');
\r
448 $template = $this->getOption('admin_media_template');
\r
451 echo $NP_Thumbnail->generateTag($template, $medium, $data[$count]['alt']) . "<br />\n";
\r
452 echo "<input type=\"hidden\" id=\"path{$count}\" name=\"path[{$count}]\" value=\"{$data[$count]['path']}\" /><br />\n";
\r
454 echo "<input type=\"text\" id=\"alt{$count}\" name=\"alt[{$count}]\" value=\"{$data[$count]['alt']}\" size=\"12\" />\n";
\r
458 if ( $data[$count]['path'] && !array_key_exists($data[$count]['mime'], MediaUtils::$image_mime) )
\r
460 echo "<input type=\"hidden\" name=\"way[{$count}]\" value=\"anchor\" />\n";
\r
461 echo _NP_ATTACH_14 . "\n";
\r
465 $thumbnail_checked = "";
\r
466 $original_checked = "";
\r
467 $anchor_checked = "";
\r
469 if ( $data[$count]['way'] == 'original' )
\r
471 $original_checked = 'checked="checked"';
\r
473 else if ($data[$count]['way'] == 'anchor' )
\r
475 $anchor_checked = 'checked="checked"';
\r
479 $thumbnail_checked = 'checked="checked"';
\r
482 echo "<input type=\"radio\" id=\"way{$count}-anchor\" name=\"way[{$count}]\" value=\"anchor\" {$anchor_checked} />\n";
\r
483 echo "<label for=\"way{$count}-anchor\">" . _NP_ATTACH_15 . "<label><br />\n";
\r
484 echo "<input type=\"radio\" id=\"way{$count}-small\" name=\"way[{$count}]\" value=\"thumbnail\" {$thumbnail_checked} />\n";
\r
485 echo "<label for=\"way{$count}-small\">" . _NP_ATTACH_16 . "<label><br />\n";
\r
486 echo "<input type=\"radio\" id=\"way{$count}-original\" name=\"way[{$count}]\" value=\"original\" {$original_checked} />\n";
\r
487 echo "<label for=\"way{$count}-original\">" . _NP_ATTACH_17 . "<label>\n";
\r
498 private function setData($root)
\r
500 if ( self::$blogid === 0 || !self::$itemid === 0 )
\r
505 self::$amount = $this->getBlogOption(self::$blogid, 'amount');
\r
506 $media = explode(';', $this->getitemOption(self::$itemid, 'media'));
\r
509 for ( $count = 0; $count < self::$amount; $count++ )
\r
511 if ( (self::$itemid != 0) && array_key_exists($count, $media) && !empty($media[$count]) )
\r
513 $medium = explode(':', $media[$count]);
\r
514 $data[$count]['path'] = $medium[0];
\r
515 $data[$count]['alt'] = $medium[1];
\r
516 $data[$count]['way'] = $medium[2];
\r
518 if ( FALSE === ($file = new Medium($root, $data[$count]['path'], MediaUtils::$prefix)) )
\r
520 $data[$count] = array('path' => "", 'alt' => "", 'way' => "");
\r
523 $data[$count]['mime'] = $file->mime;
\r
524 $data[$count]['width'] = $file->width;
\r
525 $data[$count]['height'] = $file->height;
\r
529 $data[$count] = array('path' => "", 'alt' => "", 'way' => "");
\r
533 self::$data = $data;
\r
537 static private function batchRequest($root, $collection)
\r
539 global $CONF, $manager;
\r
544 $deletes = array();
\r
546 if ( array_key_exists('medium', $_FILES) )
\r
548 $media = $_FILES['medium'];
\r
551 if ( array_key_exists('path', $_POST) )
\r
553 $paths = $_POST['path'];
\r
556 if ( array_key_exists('alt', $_POST) )
\r
558 $alts = $_POST['alt'];
\r
561 if ( array_key_exists('way', $_POST) )
\r
563 $ways = $_POST['way'];
\r
566 if ( array_key_exists('delete', $_POST) )
\r
568 $deletes = $_POST['delete'];
\r
571 $data = &self::$data;
\r
573 if ( !$manager->pluginInstalled('NP_Thumbnail') )
\r
578 foreach ( $data as $key => $value )
\r
580 if ( $media && array_key_exists($key, $media['name']) && !empty($media['name'][$key]) )
\r
583 if ( preg_match ("#(\\\\|/|\\n)#", $media['name'][$key]) )
\r
585 $data[$key] = array('path' => "", 'alt' => "", 'way' => "");
\r
589 $medium['name'] = &$media['name'][$key];
\r
590 $medium['size'] = $media['size'][$key];
\r
591 $medium['tmp_name'] = $media['tmp_name'][$key];
\r
592 $medium['error'] = $media['error'][$key];
\r
594 $result = MediaUtils::uploadMedium($root, $collection, $medium, '', $manager);
\r
598 $data[$key]['path'] = "";
\r
599 $data[$key]['alt'] = "{$result} ({$medium['name']})";
\r
600 $data[$key]['way'] = "";
\r
605 $data[$key]['path'] = "{$collection}/{$medium['name']}";
\r
608 else if ( array_key_exists($key, $paths) && !empty($paths[$key]) )
\r
610 if ( FALSE === ($medium = new MEDIUM($root, $paths[$key], MediaUtils::$prefix)) )
\r
612 $data[$key] = array('path' => "", 'alt' => "", 'way' => "");
\r
615 if ( $deletes && array_key_exists($key, $deletes) && $deletes[$key] == 1 )
\r
617 if ( @unlink($root . $paths[$key]) )
\r
619 if ( array_key_exists($medium->mime, MediaUtils::$image_mime) )
\r
621 @ unlink($root . NP_Thumbnail::getThumbPath($medium));
\r
623 $data[$key] = array('path' => "", 'alt' => "", 'way' => "");
\r
629 if ( array_key_exists($key, $alts) && $alts[$key] != $value['alt'] )
\r
631 $data[$key]['alt'] = htmlspecialchars($alts[$key], ENT_QUOTES, _CHARSET);
\r
634 if ( array_key_exists($key, $ways) && $ways[$key] != $value['way'] )
\r
636 if ( !in_array($ways[$key], array('thumbnail', 'original', 'anchor')) )
\r
638 $data[$key]['way'] = 'thumbnail';
\r
642 $data[$key]['way'] = $ways[$key];
\r
649 static private function prepareEnctype()
\r
651 self::$buffer = ob_start();
\r
655 static private function setEnctype()
\r
657 if ( !self::$buffer )
\r
662 $strings = ob_get_contents();
\r
664 $strings = preg_replace('#action="(index.php|bookmarklet.php)"#', '$0 enctype="multipart/form-data"', $strings);
\r