2 // vim: tabstop=2:shiftwidth=2
5 * NP_TrimImage ($Revision: 1.11 $)
6 * by nakahara21 ( http://nakahara21.com/ )
7 * by hsur ( http://blog.cles.jp/np_cles/ )
8 * $Id: NP_TrimImage.php,v 1.11 2008-05-02 17:23:20 hsur Exp $
10 * Based on NP_TrimImage 1.0 by nakahara21
11 * http://nakahara21.com/?itemid=512
15 * Copyright (C) 2004-2006 nakahara21 All rights reserved.
16 * Copyright (C) 2006-2008 cles All rights reserved.
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 * In addition, as a special exception, mamio and cles gives
33 * permission to link the code of this program with those files in the PEAR
34 * library that are licensed under the PHP License (or with modified versions
35 * of those files that use the same license as those files), and distribute
36 * linked combinations including the two. You must obey the GNU General Public
37 * License in all respects for all of the code used other than those files in
38 * the PEAR library that are licensed under the PHP License. If you modify
39 * this file, you may extend this exception to your version of the file,
40 * but you are not obligated to do so. If you do not wish to do so, delete
41 * this exception statement from your version.
45 // 0.2: $archive, $blogid and $catid suppot ($exmode=all ready)
47 // 0.3: add strtolower
48 // Initialize $this->exquery
49 // 0.5: use createGlobalItemLink
50 // sql_table support :-P
51 // 0.6: parameter supports blogid and catid
52 // 0.7: supports templatevar
55 // 0.9: doTemplateVar calls DB data for other PreItem Plugin
56 // 0.9: change '&' to '&'
57 // 1.1: NP_Paint support.
59 // 2.0: use phpThumb() (http://phpthumb.sourceforge.net)
61 // add alt/title attribute
63 // 2.2: support <img /> tag.
64 // doTemplateVar() bug fix.
65 // Add ENT_QUOTES to htmlspecialchars()
66 // Add ExtractImageMode
67 // 2.2.1: update phpThumb() 1.7.7 .
69 // 2.2.2: update enableLeftTop.patch
70 // 2.3.0: add itemcat mode
72 define('NP_TRIMIMAGE_FORCE_PASSTHRU', true); //passthru(standard)
73 //define('NP_TRIMIMAGE_FORCE_PASSTHRU', false); //redirect(advanced)
75 define('NP_TRIMIMAGE_CACHE_MAXAGE', 86400 * 30); // 30days
76 define('NP_TRIMIMAGE_PREFER_IMAGEMAGICK', false);
78 require_once(dirname(__FILE__).'/sharedlibs/sharedlibs.php');
79 require_once('phpthumb/phpthumb.functions.php');
80 require_once('phpthumb/phpthumb.class.php');
82 class NP_TrimImage extends NucleusPlugin {
87 function getAuthor() {
88 return 'nakahara21 + hsur';
92 return 'http://blog.cles.jp/np_cles/category/31/subcatid/15';
95 function getVersion() {
99 function supportsFeature($what) {
101 case 'SqlTablePrefix' :
108 function getDescription() {
109 return 'Trim image in items, and embed these images.';
112 function getEventList() {
113 return array ('PostAddItem', 'PostUpdateItem', 'PostDeleteItem',);
116 function event_PostAddItem(& $data) {
117 $this->_clearCache();
119 function event_PostUpdateItem(& $data) {
120 $this->_clearCache();
122 function event_PostDeleteItem(& $data) {
123 $this->_clearCache();
125 function _clearCache() {
127 $phpThumb = new phpThumb();
128 foreach ($this->phpThumbParams as $paramKey => $paramValue) {
129 $phpThumb->setParameter($paramKey, $paramValue);
131 $phpThumb->setParameter('config_cache_maxage', 1);
132 $phpThumb->CleanUpCacheDirectory();
139 $this->fileex = array ('.gif', '.jpg', '.png');
140 $cacheDir = $DIR_MEDIA.'phpthumb/';
141 $cacheDir = (is_dir($cacheDir) && @ is_writable($cacheDir)) ? $cacheDir : null;
143 $this->phpThumbParams = array(
144 'config_document_root' => $DIR_MEDIA,
145 'config_cache_directory' => $cacheDir,
146 'config_cache_disable_warning' => true,
147 'config_cache_directory_depth' => 0,
148 'config_cache_maxage' => NP_TRIMIMAGE_CACHE_MAXAGE,
149 'config_cache_maxsize' => 10 * 1024 * 1024, // 10MB
150 'config_cache_maxfiles' => 1000,
151 'config_cache_source_filemtime_ignore_local' => true,
152 'config_cache_cache_default_only_suffix' => '',
153 'config_cache_prefix' => 'phpThumb_cache',
154 'config_cache_force_passthru' => NP_TRIMIMAGE_FORCE_PASSTHRU,
155 'config_max_source_pixels' => 3871488, //4Mpx
156 'config_output_format' => 'jpg',
157 'config_disable_debug' => true,
158 'config_prefer_imagemagick' => NP_TRIMIMAGE_PREFER_IMAGEMAGICK,
162 function getCategoryIDFromItemID($itemid) {
163 return quickQuery('SELECT icat as result FROM ' . sql_table('item') . ' WHERE inumber=' . intval($itemid) );
166 function doSkinVar($skinType, $amount = 10, $wsize = 80, $hsize = 80, $point = 0, $random = 0, $exmode = '', $titlemode = '', $includeImg = 'true') {
167 global $CONF, $manager, $blog;
171 $b = & $manager->getBlog($CONF['DefaultBlog']);
174 if (!is_numeric($amount))
176 if (!is_numeric($hsize))
178 if (!is_numeric($wsize))
180 $point = ($point == 'lefttop') ? true : false;
181 $includeImg = ( $includeImg == 'true' ) ? true : false;
188 $year = $month = $day = '';
189 sscanf($archive, '%d-%d-%d', $year, $month, $day);
191 $timestamp_start = mktime(0, 0, 0, $month, 1, $year);
192 $timestamp_end = mktime(0, 0, 0, $month +1, 1, $year); // also works when $month==12
194 $timestamp_start = mktime(0, 0, 0, $month, $day, $year);
195 $timestamp_end = mktime(0, 0, 0, $month, $day +1, $year);
197 $this->exquery .= ' and itime >= ' . mysqldate($timestamp_start)
198 .' and itime < ' . mysqldate($timestamp_end);
202 if ($exmode == '' || $exmode == 'itemcat') {
203 global $catid, $itemid;
205 $this->exquery .= ' and icat = '.intval($catid);
206 elseif( $exmode == 'itemcat' && $itemid )
207 $this->exquery .= ' and icat = '.intval( $this->getCategoryIDFromItemID($itemid) );
209 $this->exquery .= ' and iblog = '.intval($b->getID());
210 } elseif ($exmode == 'all') {
213 $spbid = $spcid = array ();
214 $spid_array = explode('/', $exmode);
215 foreach ($spid_array as $spid) {
216 $type = substr($spid, 0, 1);
217 $type_id = intval(substr($spid, 1));
218 if( (!$type) || (!$type_id) ) continue;
230 $this->exquery .= ' and iblog IN ('.implode(',', $spbid).') ';
233 $this->exquery .= ' and icat IN ('.implode(',', $spcid).') ';
238 $filelist = array ();
239 $this->imglists = array ();
240 $this->imgfilename = array ();
241 $random = $random ? true : false;
242 if (!($filelist = $this->listup($amount, $random, $includeImg))) {
243 //echo 'No images here.';
247 $amount = min($amount, count($filelist));
249 for ($i = 0; $i < $amount; $i ++) {
250 $itemlink = $this->createGlobalItemLink($filelist[$i][1], ''); // why not createItemLink ?
251 // $itemlink = $this->createItemLink($filelist[$i][1]);
252 echo '<a href="'.$itemlink.'">';
255 if (!$this->phpThumbParams['config_cache_force_passthru']) {
256 $src = $this->createImage($filelist[$i][0], $wsize, $hsize, $point, true);
259 $src = htmlspecialchars($CONF['ActionURL'], ENT_QUOTES)
260 .'?action=plugin&name=TrimImage&type=draw'.'&p='
261 .$filelist[$i][0].'&wsize='.$wsize.'&hsize='.$hsize
262 . ($point ? '&pnt=lefttop' : '');
265 if($titlemode == 'item')
266 $title = ($filelist[$i][4]) ? $filelist[$i][4] : $filelist[$i][2];
268 $title = ($filelist[$i][2]) ? $filelist[$i][2] : $filelist[$i][4];
270 echo '<img src="'.$src.'" '
271 . ( $wsize ? 'width="'.$wsize.'"' : '' )
272 . ( $hsize ? 'height="'.$hsize.'"' : '' )
273 . 'alt="'.htmlspecialchars($title, ENT_QUOTES)
274 . '" title="'.htmlspecialchars($title, ENT_QUOTES).'"/>';
280 function listup($amount = 10, $random = false, $includeImg = true) {
281 global $CONF, $manager, $blog;
285 $b = & $manager->getBlog($CONF['DefaultBlog']);
288 $query = 'SELECT inumber as itemid, ititle as title, ibody as body, iauthor, itime, imore as more,';
289 $query .= ' icat as catid, iclosed as closed';
290 $query .= ' FROM '.sql_table('item');
291 $query .= ' WHERE idraft = 0';
292 $query .= ' and itime <= '.mysqldate($b->getCorrectTime()); // don't show future items!
293 $query .= $this->exquery;
294 $query .= ' ORDER BY itime DESC LIMIT '.intval($amount * 10);
296 $res = sql_query($query);
298 if (!mysql_num_rows($res))
301 while ($it = mysql_fetch_object($res)) {
302 $txt = $it->body.$it->more;
303 if (preg_match_all("/<%(image|popup|paint)\((.*?)\)%>/s", $txt, $imgpnt))
304 @ array_walk($imgpnt[2], array (& $this, "exarray"), array ($it->itemid, $it->iauthor, $it->title));
306 if ($includeImg && preg_match_all("/<img (.*?)>/s", $txt, $imgtmp)){
307 foreach($imgtmp[1] as $tmp){
308 $this->exarray($tmp, null, array($it->itemid, $it->iauthor, $it->title), true);
312 if (count($this->imglists) >= $amount)
315 mysql_free_result($res);
318 shuffle($this->imglists);
319 $this->imglists = array_slice($this->imglists, 0, $amount);
320 return $this->imglists;
323 function exarray($imginfo, $key, $params, $isImg = false) {
326 if( preg_match_all('/(src|width|height|alt|title)=\"(.*?)\"/i', $imginfo, $matches) ) {
329 foreach( $matches[1] as $type ){
330 $param[$type] = $matches[2][$index];
333 if( $param['src'] && ( strpos($param['src'], $CONF['MediaURL']) === 0 ) ){
334 $imginfo = substr( $param['src'], strlen($CONF['MediaURL']) )
335 . '|' . $param['width']
336 . '|' . $param['height']
337 . '|' . ( $param['title'] ? $param['tiltle'] : $param['alt']);
344 list ($url, $w, $h, $alt, $ext) = explode("|", $imginfo, 5);
345 if (!in_array(strtolower(strrchr($url, ".")), $this->fileex))
347 if (in_array($url, $this->imgfilename))
349 $this->imgfilename[] = $url;
350 if (!strstr($url, '/')) {
351 $url = $params[1].'/'.$url;
353 $this->imglists[] = array ($url, $params[0], $alt, $ext, $params[2]);
356 function doTemplateVar(& $item, $wsize = 80, $hsize = 80, $point = 0, $maxAmount = 0, $titlemode = '', $includeImg = 'true') {
358 if (!is_numeric($hsize))
360 if (!is_numeric($wsize))
362 $point = ($point == 'lefttop') ? true : false;
363 $includeImg = ( $includeImg == 'true' ) ? true : false;
365 $filelist = array ();
366 $this->imglists = array ();
367 $this->imgfilename = array ();
368 //$txt = $item->body.$item->more;
370 $q = 'SELECT ibody as body, imore as more, ititle as title FROM '.sql_table('item').' WHERE inumber='.intval($item->itemid);
372 while ($d = mysql_fetch_object($r)) {
373 $txt .= $d->body.$d->more;
376 if (preg_match_all("/<%(image|popup|paint)\((.*?)\)%>/s", $txt, $imgpnt))
377 @ array_walk($imgpnt[2], array (& $this, "exarray"), array ($item->itemid, $item->authorid, $item->title));
379 if ($includeImg && preg_match_all("/<img (.*?)>/s", $txt, $imgtmp)){
380 foreach($imgtmp[1] as $tmp){
381 $this->exarray($tmp, null, array ($item->itemid, $item->authorid, $item->title), true);
385 $filelist = $this->imglists;
387 $amount = count($filelist);
389 $amount = min($maxAmount, count($filelist));
392 $img_tag = '<img src="'.htmlspecialchars($CONF['ActionURL'], ENT_QUOTES).'?action=plugin&name=TrimImage';
393 $img_tag .= '&type=draw&p=non&wsize='.$wsize.'&hsize='.$hsize.$exq;
394 $img_tag .= '" width="'.$wsize.'" height="'.$hsize.'" />';
397 for ($i = 0; $i < $amount; $i ++) {
399 if (!$this->phpThumbParams['config_cache_force_passthru']) {
400 $src = $this->createImage($filelist[$i][0], $wsize, $hsize, $point, true);
403 $src = htmlspecialchars($CONF['ActionURL'], ENT_QUOTES).'?action=plugin&name=TrimImage&type=draw'.'&p='.$filelist[$i][0].'&wsize='.$wsize.'&hsize='.$hsize. ($point ? '&pnt=lefttop' : '');
406 if($titlemode == 'item')
407 $title = ($filelist[$i][4]) ? $filelist[$i][4] : $filelist[$i][2];
409 $title = ($filelist[$i][2]) ? $filelist[$i][2] : $filelist[$i][4];
411 echo '<img src="'.$src.'" '
412 . ( $wsize ? 'width="'.$wsize.'"' : '' )
413 . ( $hsize ? 'height="'.$hsize.'"' : '' )
414 . 'alt="'.htmlspecialchars($title, ENT_QUOTES)
415 . '" title="'.htmlspecialchars($title, ENT_QUOTES).'"/>';
420 function doAction($type) {
421 $w = is_numeric(requestVar('wsize')) ? requestVar('wsize') : 80;
422 $h = is_numeric(requestVar('hsize')) ? requestVar('hsize') : 80;
423 $isLefttop = (requestVar('pnt') == 'lefttop') ? true : false;
427 $this->createImage(requestVar('p'), $w, $h, $isLefttop);
430 return 'No such action';
435 function createImage($p, $w, $h, $isLefttop, $cacheCheckOnly = false) {
436 $phpThumb = new phpThumb();
437 foreach ($this->phpThumbParams as $paramKey => $paramValue) {
438 $phpThumb->setParameter($paramKey, $paramValue);
441 if($h) $phpThumb->setParameter('h', intval($h));
442 if($w) $phpThumb->setParameter('w', intval($w));
445 $bghexcolor = 'FFFFFF';
446 if ($phpThumb->gdimg_source = phpthumb_functions::ImageCreateFunction($phpThumb->w, $phpThumb->h)) {
447 $phpThumb->setParameter('is_alpha', true);
448 ImageAlphaBlending($phpThumb->gdimg_source, false);
449 ImageSaveAlpha($phpThumb->gdimg_source, true);
450 $new_background_color = phpthumb_functions::ImageHexColorAllocate($phpThumb->gdimg_source, $bghexcolor, false, 127);
451 ImageFilledRectangle($phpThumb->gdimg_source, 0, 0, $phpThumb->w, $phpThumb->h, $new_background_color);
454 $phpThumb->setParameter('src', '/'.$p);
456 $phpThumb->setParameter('zc', $isLefttop ? 2 : 1);
458 $phpThumb->setParameter('aoe', 1);
462 $phpThumb->cache_filename = null;
463 $phpThumb->CalculateThumbnailDimensions();
464 $phpThumb->SetCacheFilename();
465 if (file_exists($phpThumb->cache_filename)) {
466 $nModified = filemtime($phpThumb->cache_filename);
467 if (time() - $nModified < NP_TRIMIMAGE_CACHE_MAXAGE) {
469 preg_match('/^'.preg_quote($this->phpThumbParams['config_document_root'], '/').'(.*)$/', $phpThumb->cache_filename, $matches);
470 $fileUrl = $CONF['MediaURL'].$matches[1];
474 header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT');
475 if (@ serverVar('HTTP_IF_MODIFIED_SINCE')
476 && ($nModified == strtotime(serverVar('HTTP_IF_MODIFIED_SINCE')))
477 && @ serverVar('SERVER_PROTOCOL')
479 header(serverVar('SERVER_PROTOCOL').' 304 Not Modified');
482 if ($getimagesize = @ GetImageSize($phpThumb->cache_filename)) {
483 header('Content-Type: '.phpthumb_functions :: ImageTypeToMIMEtype($getimagesize[2]));
485 elseif (eregi('\.ico$', $phpThumb->cache_filename)) {
486 header('Content-Type: image/x-icon');
488 if ($this->phpThumbParams['config_cache_force_passthru']) {
489 @ readfile($phpThumb->cache_filename);
491 header('Location: '.$fileUrl);
496 if ($cacheCheckOnly) {
502 $phpThumb->GenerateThumbnail();
506 $phpThumb->CleanUpCacheDirectory();
507 $phpThumb->RenderToFile($phpThumb->cache_filename);
508 @ chmod($phpThumb->cache_filename, 0666);
511 $phpThumb->OutputThumbnail();
517 global $member, $manager;
518 if (!$member->isLoggedIn())
520 return $member->isAdmin();
523 function createGlobalItemLink($itemid, $extra = '') {
524 global $CONF, $manager;
525 $itemid = intval($itemid);
526 if ($CONF['URLMode'] == 'pathinfo') {
527 $link = $CONF['ItemURL'].'/item/'.$itemid;
529 $blogid = getBlogIDFromItemID($itemid);
530 $b_tmp = & $manager->getBlog($blogid);
531 $blogurl = $b_tmp->getURL();
533 $blogurl = $CONF['IndexURL'];
535 if (substr($blogurl, -4) != '.php') {
536 if (substr($blogurl, -1) != '/')
538 $blogurl .= 'index.php';
540 $link = $blogurl.'?itemid='.$itemid;
542 return addLinkParams($link, $extra);