1<?php 2// force UTF-8 Ø 3$_zp_extra_filetypes = array(); // contains file extensions and the handler class for alternate images 4 5define('WATERMARK_IMAGE', 1); 6define('WATERMARK_THUMB', 2); 7define('WATERMARK_FULL', 4); 8 9/** 10 * Returns a new "image" object based on the file extension 11 * 12 * @param object $album the owner album 13 * @param string $filename the filename 14 * @param bool $quiet set true to supress error messages (used by loadimage) 15 * @return object 16 */ 17function newImage($album, $filename, $quiet = false) { 18 global $_zp_extra_filetypes, $_zp_missing_image; 19 if (is_array($filename)) { 20 $xalbum = newAlbum($filename['folder'], true, true); 21 $filename = $filename['filename']; 22 } else { 23 if ($album->isDynamic()) { 24 $xalbum = NULL; 25 foreach ($album->getImages() as $image) { 26 if ($filename == $image['filename']) { 27 $xalbum = newAlbum($image['folder']); 28 break; 29 } 30 } 31 } else { 32 $xalbum = $album; 33 } 34 } 35 if (!is_object($xalbum) || !$xalbum->exists || !isAlbumClass($xalbum)) { 36 if (!$quiet) { 37 $msg = sprintf(gettext('Bad album object parameter to newImage(%s)'), $filename); 38 trigger_error($msg, E_USER_NOTICE); 39 } 40 return $_zp_missing_image; 41 } 42 if ($object = Gallery::validImageAlt($filename)) { 43 $image = New $object($xalbum, $filename, $quiet); 44 } else { 45 if (Gallery::validImage($filename)) { 46 $image = New Image($xalbum, $filename, $quiet); 47 } else { 48 $image = NULL; 49 } 50 } 51 if ($image) { 52 if ($album && $album->isDynamic()) { 53 $image->albumname = $album->name; 54 $image->albumlink = $album->linkname; 55 $image->albumnamealbum = $album; 56 } 57 zp_apply_filter('image_instantiate', $image); 58 if ($image->exists) { 59 return $image; 60 } else { 61 return $_zp_missing_image; 62 } 63 } 64 65 if (!$quiet) { 66 $msg = sprintf(gettext('Bad filename suffix in newImage(%s)'), $filename); 67 trigger_error($msg, E_USER_NOTICE); 68 } 69 return $_zp_missing_image; 70} 71 72/** 73 * Returns true if the object is a zenphoto 'image' 74 * 75 * @param object $image 76 * @return bool 77 */ 78function isImageClass($image = NULL) { 79 global $_zp_current_image; 80 if (is_null($image)) { 81 if (!in_context(ZP_IMAGE)) 82 return false; 83 $image = $_zp_current_image; 84 } 85 return is_object($image) && ($image->table == 'images'); 86} 87 88/** 89 * Image Class 90 * @package core 91 * @subpackage classes\objects 92 */ 93class Image extends MediaObject { 94 95 public $filename; // true filename of the image. 96 public $exists = true; // Does the image exist? 97 public $webpath; // The full URL path to the original image. 98 public $localpath; // Latin1 full SERVER path to the original image. 99 public $displayname; // $filename with the extension stripped off. 100 public $album; // An album object for the album containing this image. 101 public $albumname; // The name of the album for which this image was instantiated. (MAY NOT be $this->album->name!!!!). 102 public $albumnamealbum; // An album object representing the above; 103 public $albumlink; // "rewrite" verwion of the album name, eg. may not have the .alb 104 public $imagefolder; // The album folder containing the image (May be different from the albumname!!!!) 105 protected $index; // The index of the current image in the album array. 106 protected $sortorder; // The position that this image should be shown in the album 107 public $filemtime; // Last modified time of this image 108 public $sidecars = array(); // keeps the list of suffixes associated with this image 109 public $manage_rights = MANAGE_ALL_ALBUM_RIGHTS; 110 public $manage_some_rights = ALBUM_RIGHTS; 111 public $view_rights = ALL_ALBUMS_RIGHTS; 112 // Plugin handler support 113 public $objectsThumb = NULL; // Thumbnail image for the object 114 public $thumbdimensions = null; 115 protected $is_public = null; 116 117 /** 118 * Constructor for class-image 119 * 120 * Do not call this constructor directly unless you really know what you are doing! 121 * Use instead the function newImage() which will instantiate an object of the 122 * correct class for the file type. 123 * 124 * @param object &$album the owning album 125 * @param sting $filename the filename of the image 126 * @return Image 127 */ 128 129 function __construct($album, $filename, $quiet = false) { 130 global $_zp_current_admin_obj; 131 // $album is an Album object; it should already be created. 132 $msg = false; 133 if (!is_object($album) || !$album->exists) { 134 $msg = gettext('Invalid image instantiation: Album does not exist'); 135 } else { 136 if (!$this->classSetup($album, $filename) || !file_exists($this->localpath) || is_dir($this->localpath)) { 137 $msg = gettext('Invalid image instantiation: file does not exist'); 138 } 139 } 140 if ($msg) { 141 $this->exists = false; 142 if (!$quiet) { 143 trigger_error($msg, E_USER_ERROR); 144 } 145 return; 146 } 147 148 // This is where the magic happens... 149 $album_name = $album->name; 150 $new = $this->instantiate('images', array('filename' => $filename, 'albumid' => $this->album->getID()), 'filename', false, empty($album_name)); 151 if ($new || $this->filemtime != $this->get('mtime')) { 152 if ($new) { 153 $this->setTitle($this->displayname); 154 } 155 $this->updateMetaData(); // extract info from image 156 $this->updateDimensions(); // deal with rotation issues 157 $this->set('mtime', $this->filemtime); 158 $this->save(); 159 if ($new) 160 zp_apply_filter('new_image', $this); 161 } 162 } 163 164 /** 165 * (non-PHPdoc) 166 * @see PersistentObject::setDefaults() 167 */ 168 protected function setDefaults() { 169 global $_zp_gallery; 170 $this->setShow($_zp_gallery->getImagePublish()); 171 $this->set('mtime', $this->filemtime); 172 $this->setLastChange(); 173 $this->updateDimensions(); // deal with rotation issues 174 } 175 176 /** 177 * generic "image" class setup code 178 * Returns true if valid image. 179 * 180 * @param object $album the images' album 181 * @param string $filename of the image 182 * @return bool 183 * 184 */ 185 protected function classSetup(&$album, $filename) { 186 if (TEST_RELEASE) { 187 $bt = debug_backtrace(); 188 $good = false; 189 foreach ($bt as $b) { 190 if ($b['function'] == "newImage") { 191 $good = true; 192 break; 193 } 194 } 195 if (!$good) { 196 zp_error(gettext('An image object was instantiated without using the newImage() function.'), E_USER_WARNING); 197 } 198 } 199 200 global $_zp_current_admin_obj; 201 $fileFS = internalToFilesystem($filename); 202 if ($filename != filesystemToInternal($fileFS)) { // image name spoof attempt 203 return false; 204 } 205 $this->albumnamealbum = $this->album = &$album; 206 if ($album->name == '') { 207 $this->webpath = ALBUM_FOLDER_WEBPATH . $filename; 208 $this->encwebpath = ALBUM_FOLDER_WEBPATH . rawurlencode($filename); 209 $this->localpath = ALBUM_FOLDER_SERVERPATH . internalToFilesystem($filename); 210 } else { 211 $this->webpath = ALBUM_FOLDER_WEBPATH . $album->name . "/" . $filename; 212 $this->encwebpath = ALBUM_FOLDER_WEBPATH . pathurlencode($album->name) . "/" . rawurlencode($filename); 213 $this->localpath = $album->localpath . $fileFS; 214 } 215 $this->imagefolder = $this->albumlink = $this->albumname = $album->name; 216 $this->filename = $filename; 217 $this->displayname = substr($this->filename, 0, strrpos($this->filename, '.')); 218 if (empty($this->displayname)) 219 $this->displayname = $this->filename; 220 $this->comments = null; 221 $this->filemtime = @filemtime($this->localpath); 222 $this->imagetype = strtolower(get_class($this)) . 's'; 223 $date = $this->get('date'); 224 if (empty($date)) { 225 $this->set('date', strftime('%Y-%m-%d %H:%M:%S', $this->filemtime)); 226 } 227 return true; 228 } 229 230 /** 231 * Returns the image filename 232 * 233 * @return string 234 */ 235 function getFileName() { 236 return $this->filename; 237 } 238 239 /** 240 * Returns true if the file has changed since last time we looked 241 * 242 * @return bool 243 */ 244 protected function fileChanged() { 245 $storedmtime = $this->get('mtime'); 246 return (empty($storedmtime) || $this->filemtime > $storedmtime); 247 } 248 249 /** 250 * Returns an array of EXIF data 251 * 252 * @return array 253 */ 254 function getMetaData() { 255 global $_zp_exifvars; 256 $exif = array(); 257 // Put together an array of EXIF data to return 258 foreach ($_zp_exifvars as $field => $exifvar) { 259 // only enabled image metadata 260 if ($_zp_exifvars[$field][5]) { 261 $exif[$field] = $this->get($field); 262 } 263 } 264 return $exif; 265 } 266 267 /** 268 * Parses Exif/IPTC data 269 * 270 */ 271 function updateMetaData() { 272 global $_zp_exifvars, $_zp_gallery; 273 require_once(dirname(__FILE__) . '/exif/exif.php'); 274 $IPTCtags = array( 275 'SKIP' => '2#000', // Record Version Size:64 276 'ObjectType' => '2#003', // Object Type Ref Size:67 277 'ObjectAttr' => '2#004', // Object Attribute Ref Size:67 278 'ObjectName' => '2#005', // Object name Size:64 279 'EditStatus' => '2#007', // Edit Status Size:64 280 'EditorialUpdate' => '2#008', // Editorial Update Size:2 281 'Urgency' => '2#010', // Urgency Size:1 282 'SubRef' => '2#012', // Subject Reference Size:236 283 'Category' => '2#015', // Category Size:3 284 'SuppCategory' => '2#020', // Supplemental category Size:32 285 'FixtureID' => '2#022', // Fixture ID Size:32 286 'Keywords' => '2#025', // Keywords Size:64 287 'ContentLocationCode' => '2#026', // Content Location Code Size:3 288 'ContentLocationName' => '2#027', // Content Location Name Size:64 289 'ReleaseDate' => '2#030', // Release Date Size:8 290 'ReleaseTime' => '2#035', // Release Time Size:11 291 'ExpireDate' => '2#037', // Expiration Date Size:8 292 'ExpireTime' => '2#038', // Expiration Time Size:11 293 'SpecialInstru' => '2#040', // Special Instructions Size:256 294 'ActionAdvised' => '2#042', // Action Advised Size:2 295 'RefService' => '2#045', // Reference Service Size:10 296 'RefDate' => '2#047', // Reference Date Size:8 297 'RefNumber' => '2#050', // Reference Number Size:8 298 'DateCreated' => '2#055', // Date created Size:8 299 'TimeCreated' => '2#060', // Time created Size:11 300 'DigitizeDate' => '2#062', // Digital Creation Date Size:8 301 'DigitizeTime' => '2#063', // Digital Creation Time Size:11 302 'OriginatingProgram' => '2#065', // Originating Program Size:32 303 'ProgramVersion' => '2#070', // Program version Size:10 304 'ObjectCycle' => '2#075', // Object Cycle Size:1 305 'ByLine' => '2#080', // ByLine Size:32 306 'ByLineTitle' => '2#085', // ByLine Title Size:32 307 'City' => '2#090', // City Size:32 308 'SubLocation' => '2#092', // Sublocation Size:32 309 'State' => '2#095', // Province/State Size:32 310 'LocationCode' => '2#100', // Country/Primary Location Code Size:3 311 'LocationName' => '2#101', // Country/Primary Location Name Size:64 312 'TransmissionRef' => '2#103', // Original Transmission Reference Size:32 313 'ImageHeadline' => '2#105', // Image headline Size:256 314 'ImageCredit' => '2#110', // Image credit Size:32 315 'Source' => '2#115', // Source Size:32 316 'Copyright' => '2#116', // Copyright Notice Size:128 317 'Contact' => '2#118', // Contact Size:128 318 'ImageCaption' => '2#120', // Image caption Size:2000 319 'ImageCaptionWriter' => '2#122', // Image caption writer Size:32 320 'ImageType' => '2#130', // Image type Size:2 321 'Orientation' => '2#131', // Image rientation Size:1 322 'LangID' => '2#135', // Language ID Size:3 323 'Subfile' => '8#010' // Subfile Size:2 324 ); 325 $this->set('hasMetadata', 0); 326 $result = array(); 327 if (get_class($this) == 'Image') { 328 $localpath = $this->localpath; 329 } else { 330 $localpath = $this->getThumbImageFile(); 331 } 332 $xdate = false; 333 334 if (!empty($localpath)) { // there is some kind of image to get metadata from 335 $exifraw = read_exif_data_protected($localpath); 336 if (isset($exifraw['ValidEXIFData'])) { 337 $this->set('hasMetadata', 1); 338 foreach ($_zp_exifvars as $field => $exifvar) { 339 $exif = NULL; 340 if ($exifvar[5]) { // enabled field 341 if (isset($exifraw[$exifvar[0]][$exifvar[1]])) { 342 $exif = trim(sanitize($exifraw[$exifvar[0]][$exifvar[1]], 1)); 343 } else if (isset($exifraw[$exifvar[0]]['MakerNote'][$exifvar[1]])) { 344 $exif = trim(sanitize($exifraw[$exifvar[0]]['MakerNote'][$exifvar[1]], 1)); 345 } 346 } 347 $this->set($field, $exif); 348 } 349 } 350 /* check IPTC data */ 351 $iptcdata = zp_imageIPTC($localpath); 352 if (!empty($iptcdata)) { 353 $iptc = iptcparse($iptcdata); 354 if ($iptc) { 355 $this->set('hasMetadata', 1); 356 $characterset = $this->getIPTCTag('1#090', $iptc); 357 if (!$characterset) { 358 $characterset = getOption('IPTC_encoding'); 359 } else if (substr($characterset, 0, 1) == chr(27)) { // IPTC escape encoding 360 $characterset = substr($characterset, 1); 361 if ($characterset == '%G') { 362 $characterset = 'UTF-8'; 363 } else { // we don't know, need to understand the IPTC standard here. In the mean time, default it. 364 $characterset = getOption('IPTC_encoding'); 365 } 366 } else if ($characterset == 'UTF8') { 367 $characterset = 'UTF-8'; 368 } 369 // Extract IPTC fields of interest 370 foreach ($_zp_exifvars as $field => $exifvar) { 371 if ($exifvar[0] == 'IPTC') { 372 if ($exifvar[5]) { // enabled field 373 $datum = $this->getIPTCTag($IPTCtags[$exifvar[1]], $iptc); 374 $this->set($field, $this->prepIPTCString($datum, $characterset)); 375 } else { 376 $this->set($field, NULL); 377 } 378 } 379 } 380 /* iptc keywords (tags) */ 381 if ($_zp_exifvars['IPTCKeywords'][5]) { 382 $datum = $this->getIPTCTagArray($IPTCtags['Keywords'], $iptc); 383 if (is_array($datum)) { 384 $tags = array(); 385 $result['tags'] = array(); 386 foreach ($datum as $item) { 387 $tags[] = $this->prepIPTCString(sanitize($item, 3), $characterset); 388 } 389 $this->setTags($tags); 390 } 391 } 392 } 393 } 394 } 395 /* "import" metadata into Zenphoto fields as makes sense */ 396 zp_apply_filter('image_metadata', $this); 397 398 /* iptc date */ 399 $date = $this->get('IPTCDateCreated'); 400 if (!empty($date)) { 401 if (strlen($date) > 8) { 402 $time = substr($date, 8); 403 } else { 404 /* got date from IPTC, now must get time */ 405 $time = $this->get('IPTCTimeCreated'); 406 } 407 $date = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2); 408 if (!empty($time)) { 409 $date = $date . ' ' . substr($time, 0, 2) . ':' . substr($time, 2, 2) . ':' . substr($time, 4, 2); 410 } 411 } 412 /* EXIF date */ 413 if (empty($date)) { 414 $date = $this->get('EXIFDateTime'); 415 } 416 if (empty($date)) { 417 $date = $this->get('EXIFDateTimeOriginal'); 418 } 419 if (empty($date)) { 420 $date = $this->get('EXIFDateTimeDigitized'); 421 } 422 if (!empty($date)) { 423 $xdate = $date; 424 $this->setDateTime($date); 425 } 426 427 /* iptc title */ 428 $title = $this->get('IPTCObjectName'); 429 if (empty($title)) { 430 $title = $this->get('IPTCImageHeadline'); 431 } 432 //EXIF title [sic] 433 if (empty($title)) { 434 $title = $this->get('EXIFDescription'); 435 } 436 if (!empty($title)) { 437 $this->setTitle($title); 438 } 439 440 /* iptc description */ 441 $desc = $this->get('IPTCImageCaption'); 442 if (!empty($desc)) { 443 if(getOption('IPTC_convert_linebreaks')) { 444 $desc = nl2br($desc); 445 } 446 $this->setDesc($desc); 447 } 448 449 /* iptc location, state, country */ 450 $loc = $this->get('IPTCSubLocation'); 451 if (!empty($loc)) { 452 $this->setLocation($loc); 453 } 454 $city = $this->get('IPTCCity'); 455 if (!empty($city)) { 456 $this->setCity($city); 457 } 458 $state = $this->get('IPTCState'); 459 if (!empty($state)) { 460 $this->setState($state); 461 } 462 $country = $this->get('IPTCLocationName'); 463 if (!empty($country)) { 464 $this->setCountry($country); 465 } 466 467 /* iptc credit */ 468 $credit = $this->get('IPTCByLine'); 469 if (empty($credit)) { 470 $credit = $this->get('IPTCImageCredit'); 471 } 472 if (empty($credit)) { 473 $credit = $this->get('IPTCSource'); 474 } 475 if (!empty($credit)) { 476 $this->setCredit($credit); 477 } 478 479 /* iptc copyright */ 480 $this->setCopyright($this->get('IPTCCopyright')); 481 482 if (empty($xdate)) { 483 $this->setDateTime(strftime('%Y-%m-%d %H:%M:%S', $this->filemtime)); 484 } 485 $alb = $this->album; 486 if (!is_null($alb)) { 487 if (!$this->get('owner')) { 488 $this->setOwner($alb->getOwner()); 489 } 490 $save = false; 491 if (strtotime($alb->getUpdatedDate()) < strtotime(date('Y-m-d H:i:s'))) { 492 $alb->setUpdatedDate(); 493 $alb->setUpdatedDateParents(); 494 $save = true; 495 } 496 if (is_null($albdate = $alb->getDateTime()) || ($_zp_gallery->getAlbumUseImagedate() && strtotime($albdate) < strtotime($this->getDateTime()))) { 497 $alb->setDateTime($this->getDateTime()); // not necessarily the right one, but will do. Can be changed in Admin 498 $save = true; 499 } 500 if ($save) { 501 $alb->save(); 502 } 503 } 504 } 505 506 /** 507 * Fetches a single tag from IPTC data 508 * 509 * @param string $tag the metadata tag sought 510 * @return string 511 */ 512 private function getIPTCTag($tag, $iptc) { 513 if (isset($iptc[$tag])) { 514 $iptcTag = $iptc[$tag]; 515 $r = ""; 516 $ct = count($iptcTag); 517 for ($i = 0; $i < $ct; $i++) { 518 $w = $iptcTag[$i]; 519 if (!empty($r)) { 520 $r .= ", "; 521 } 522 $r .= $w; 523 } 524 return trim($r); 525 } 526 return ''; 527 } 528 529 /** 530 * Fetches the IPTC array for a single tag. 531 * 532 * @param string $tag the metadata tag sought 533 * @return array 534 */ 535 private function getIPTCTagArray($tag, $iptc) { 536 if (array_key_exists($tag, $iptc)) { 537 return $iptc[$tag]; 538 } 539 return NULL; 540 } 541 542 /** 543 * Returns the IPTC data converted into UTF8 544 * 545 * @param string $iptcstring the IPTC data 546 * @param string $characterset the internal encoding of the data 547 * @return string 548 */ 549 private function prepIPTCString($iptcstring, $characterset) { 550 global $_zp_UTF8; 551 // Remove null byte at the end of the string if it exists. 552 if (substr($iptcstring, -1) === 0x0) { 553 $iptcstring = substr($iptcstring, 0, -1); 554 } 555 $outputset = LOCAL_CHARSET; 556 if ($characterset == $outputset) 557 return $iptcstring; 558 $iptcstring = $_zp_UTF8->convert($iptcstring, $characterset, $outputset); 559 return trim(sanitize($iptcstring, 1)); 560 } 561 562 /** 563 * If there is valid GPS data returns key value array with "long" and "lat" keys 564 * otherwise an empty array 565 * 566 * @since ZenphotoCMS 1.5.8 - Moved/adapted from the offical Zenphoto GoogleMap plugin by Stephen Billard (sbillard) & Vincent Bourganel (vincent3569) 567 * 568 * @return array 569 */ 570 function getGeodata() { 571 $gps = array(); 572 if (isImageClass($this)) { 573 $exif = $this->getMetaData(); 574 if ((!empty($exif['EXIFGPSLatitude'])) && (!empty($exif['EXIFGPSLongitude']))) { 575 $lat_c = explode('.', str_replace(',', '.', $exif['EXIFGPSLatitude']) . '.0'); 576 $lat_f = round((float) abs($lat_c[0]) + ($lat_c[1] / pow(10, strlen($lat_c[1]))), 12); 577 if (isset($exif['EXIFGPSLatitudeRef'][0]) && strtoupper($exif['EXIFGPSLatitudeRef'][0]) == 'S') { 578 $lat_f = -$lat_f; 579 } 580 $long_c = explode('.', str_replace(',', '.', $exif['EXIFGPSLongitude']) . '.0'); 581 $long_f = round((float) abs($long_c[0]) + ($long_c[1] / pow(10, strlen($long_c[1]))), 12); 582 if (isset($exif['EXIFGPSLongitudeRef'][0]) && strtoupper($exif['EXIFGPSLongitudeRef'][0]) == 'W') { 583 $long_f = -$long_f; 584 } 585 //in case European comma decimals sneaked in 586 $lat_f = str_replace(',', '.', $lat_f); 587 $long_f = str_replace(',', '.', $long_f); 588 if (($long_f > -180 && $long_f < 180) && ($lat_f > -90 && $lat_f < 90)) { 589 return array( 590 'lat' => $lat_f, 591 'long' => $long_f 592 ); 593 } 594 } 595 return $gps; 596 } 597 } 598 599 /** 600 * Update this object's values for width and height. 601 * 602 */ 603 function updateDimensions() { 604 $discard = NULL; 605 $size = zp_imageDims($this->localpath); 606 $width = $size['width']; 607 $height = $size['height']; 608 if (zp_imageCanRotate()) { 609 // Swap the width and height values if the image should be rotated 610 $splits = preg_split('/!([(0-9)])/', $this->get('EXIFOrientation')); 611 $rotation = $splits[0]; 612 switch ($rotation) { 613 case 5: 614 case 6: 615 case 7: 616 case 8: 617 $width = $size['height']; 618 $height = $size['width']; 619 break; 620 } 621 } 622 $this->set('width', $width); 623 $this->set('height', $height); 624 } 625 626 /** 627 * Returns the width of the image 628 * 629 * @return int 630 */ 631 function getWidth() { 632 $w = $this->get('width'); 633 if (empty($w)) { 634 $this->updateDimensions(); 635 $this->save(); 636 $w = $this->get('width'); 637 } 638 return $w; 639 } 640 641 /** 642 * Returns the height of the image 643 * 644 * @return int 645 */ 646 function getHeight() { 647 $h = $this->get('height'); 648 if (empty($h)) { 649 $this->updateDimensions(); 650 $this->save(); 651 $h = $this->get('height'); 652 } 653 return $h; 654 } 655 656 /** 657 * Returns an array with widht and height the thumb. Here this is just a wrapper for getWidth() and getHeight() 658 * 659 * Child (base) class handlers of non image file formats (e.g. video, textobject) where the actual "image" and the sidecar thumb are not the same 660 * file need to override this and provide the actual dimensions of the thumb using zp_getImageDims($thumbfile). 661 * Otherwise thumb generation may be distorted. 662 * 663 * @since ZephotoCMS 1.5.8 664 * 665 * @return array 666 */ 667 function getThumbDimensions() { 668 if (!is_null($this->thumbdimensions)) { 669 return $this->thumbdimensions; 670 } 671 return $this->thumbdimensions = array( 672 'width' => $this->getWidth(), 673 'height' => $this->getHeight() 674 ); 675 } 676 677 /** 678 * Returns the width of the thumb. Here just the same as getWidth(). 679 * 680 * @see getThumbDimensions() for specific usage 681 * @since ZephotoCMS 1.5.8 682 * 683 * @return int 684 */ 685 function getThumbWidth() { 686 $dims = $this->getThumbDimensions(); 687 return $dims['width']; 688 } 689 690 /** 691 * Returns the height of the image. Here just the same as getHeight(). 692 * 693 * @see getThumbDimensions() for specific usage 694 * @since ZephotoCMS 1.5.8 695 * 696 * @return int 697 */ 698 function getThumbHeight() { 699 $dims = $this->getThumbDimensions(); 700 return $dims['height']; 701 } 702 703 /** 704 * Returns 'is_square', 'is_landscape', 'is_portrait' if the original image's widht and height match. 705 * 706 * @since Zenphoto 1.5.8 707 * 708 * @param string $type 'image' or 'thumb' - the latter may be different on non image "image items" 709 * @return boolean|string 710 */ 711 function getOrientation($type = 'image') { 712 switch ($type) { 713 default: 714 case 'image': 715 $width = $this->getWidth(); 716 $height = $this->getHeight(); 717 break; 718 case 'thumb': 719 $width = $this->getThumbWidth(); 720 $height = $this->getThumbHeight(); 721 break; 722 } 723 if ($width == $height) { 724 return 'is_square'; 725 } else if ($width > $height) { 726 return 'is_landscape'; 727 } else if ($width < $height) { 728 return 'is_portrait'; 729 } 730 return false; 731 } 732 733 /** 734 * Returns true if the image has landscape orientation 735 * 736 * @since Zenphoto 1.5.8 737 * 738 * @param string $type 'image' or 'thumb' - the latter may be different on non image "image items" 739 * @return bool 740 */ 741 function isLandscape($type = 'image') { 742 return $this->getOrientation($type) == 'is_landscape'; 743 } 744 745 /** 746 * Returns true if the image is a square 747 * 748 * @since Zenphoto 1.5.8 749 * 750 * @param string $type 'image' or 'thumb' - the latter may be different on non image "image items" 751 * @return bool 752 */ 753 function isSquare($type = 'image') { 754 return $this->getOrientation($type) == 'is_square'; 755 } 756 757 /** 758 * Returns true if the image has portrait orientation 759 * 760 * @since Zenphoto 1.5.8 761 * 762 * @param string $type 'image' or 'thumb' - the latter may be different on non image "image items" 763 * @return bool 764 */ 765 function isPortrait($type = 'image') { 766 return $this->getOrientation($type) == 'is_portrait'; 767 } 768 769 /** 770 * Returns the album that holds this image 771 * 772 * @return object 773 */ 774 function getAlbum() { 775 return $this->album; 776 } 777 778 /** 779 * Retuns the folder name of the album that holds this image 780 * 781 * @return string 782 */ 783 function getAlbumName() { 784 return $this->albumname; 785 } 786 787 /** 788 * Returns the location field of the image 789 * 790 * @return string 791 */ 792 function getLocation($locale = NULL) { 793 $text = $this->get('location'); 794 if ($locale !== 'all') { 795 $text = get_language_string($text, $locale); 796 } 797 $text = unTagURLs($text); 798 return $text; 799 } 800 801 /** 802 * Stores the location field of the image 803 * 804 * @param string $location text for the location 805 */ 806 function setLocation($location) { 807 $this->set('location', $location); 808 } 809 810 /** 811 * Returns the city field of the image 812 * 813 * @return string 814 */ 815 function getCity($locale = NULL) { 816 $text = $this->get('city'); 817 if ($locale !== 'all') { 818 $text = get_language_string($text, $locale); 819 } 820 $text = unTagURLs($text); 821 return $text; 822 } 823 824 /** 825 * Stores the city field of the image 826 * 827 * @param string $city text for the city 828 */ 829 function setCity($city) { 830 $this->set('city', tagURLs($city)); 831 } 832 833 /** 834 * Returns the state field of the image 835 * 836 * @return string 837 */ 838 function getState($locale = NULL) { 839 $text = $this->get('state'); 840 if ($locale !== 'all') { 841 $text = get_language_string($text, $locale); 842 } 843 $text = unTagURLs($text); 844 return $text; 845 } 846 847 /** 848 * Stores the state field of the image 849 * 850 * @param string $state text for the state 851 */ 852 function setState($state) { 853 $this->set('state', tagURLs($state)); 854 } 855 856 /** 857 * Returns the country field of the image 858 * 859 * @return string 860 */ 861 function getCountry($locale = NULL) { 862 $text = $this->get('country'); 863 if ($locale !== 'all') { 864 $text = get_language_string($text, $locale); 865 } 866 $text = unTagURLs($text); 867 return $text; 868 } 869 870 /** 871 * Stores the country field of the image 872 * 873 * @param string $country text for the country filed 874 */ 875 function setCountry($country) { 876 $this->set('country', tagURLs($country)); 877 } 878 879 /** 880 * Returns the credit field of the image 881 * 882 * @return string 883 */ 884 function getCredit($locale = NULL) { 885 $text = $this->get('credit'); 886 if ($locale !== 'all') { 887 $text = get_language_string($text, $locale); 888 } 889 $text = unTagURLs($text); 890 return $text; 891 } 892 893 /** 894 * Stores the credit field of the image 895 * 896 * @param string $credit text for the credit field 897 */ 898 function setCredit($credit) { 899 $this->set('credit', tagURLs($credit)); 900 } 901 902 /** 903 * Returns the copyright field of the image 904 * 905 * @return string 906 */ 907 function getCopyright($locale = NULL) { 908 $text = $this->get('copyright'); 909 if ($locale !== 'all') { 910 $text = get_language_string($text, $locale); 911 } 912 $text = unTagURLs($text); 913 return $text; 914 } 915 916 /** 917 * Stores the text for the copyright field of the image 918 * 919 * @param string $copyright text for the copyright field 920 */ 921 function setCopyright($copyright) { 922 $this->set('copyright', tagURLs($copyright)); 923 } 924 925 /** 926 * Returns the content of the copyright field if set. 927 * If not it tries the following fallbacks: 928 * 929 * - IPTCCopyright field 930 * - EXIFCopyright field 931 * - "coypright_image_notice" option 932 * - Owner 933 * 934 * @since ZenphotoCMS 1.5.8 935 * 936 * @param string $locale 937 * @return string|null 938 */ 939 function getCopyrightNotice($locale = null) { 940 $copyright = trim($this->getCopyright($locale)); 941 if (!empty($copyright)) { 942 $notice = $copyright; 943 } else { 944 $metadata = $this->getMetaData(); 945 if (isset($metadata['IPTCCopyright']) && !empty($metadata['IPTCCopyright'])) { 946 $notice = $metadata['IPTCCopyright']; 947 } else if (isset($metadata['EXIFCopyright']) && !empty($metadata['EXIFCopyright'])) { 948 $notice = $metadata['EXIFCopyright']; 949 } else if (empty($notice)) { 950 $option = trim(getOption('copyright_image_notice')); 951 if (!empty($option)) { 952 $notice = $option; 953 } 954 } 955 } 956 if (!empty(trim($notice))) { 957 $notice = unTagURLs(get_language_string($notice, $locale)); 958 } 959 return $notice; 960 } 961 962 /** 963 * Gets the general option "copyright_image_rightsholder" respectively "copyright_image_rightsholder_custom" 964 * If set to "none" the following fallbacks are tried. 965 * 966 * - EXIFArtist 967 * - VideoArtist (for multimedia "images") 968 * – IPTCByLine 969 * - the owner (fullname if available) 970 * 971 * @since ZenphotoCMS 1.5.8 972 */ 973 function getCopyrightRightsholder() { 974 $rightsholder = trim(getOption('copyright_image_rightsholder')); 975 if ($rightsholder && $rightsholder != 'none') { 976 if ($rightsholder == 'custom') { 977 $rightsholder = trim(getOption('copyright_image_rightsholder_custom')); 978 } else { 979 $rightsholder = Administrator::getNameByUser($rightsholder); 980 } 981 } else { 982 $metadata = $this->getMetaData(); 983 if (isset($metadata['EXIFArtist']) && !empty($metadata['EXIFArtist'])) { 984 $rightsholder = $metadata['EXIFArtist']; 985 } else if (isset($metadata['VideoArtist']) && !empty($metadata['VideoArtist'])) { 986 $rightsholder = $metadata['VideoArtist']; 987 } else if (isset($metadata['IPTCByLine']) && !empty($metadata['IPTCByLine'])) { 988 $rightsholder = $metadata['IPTCByLine']; 989 } 990 } 991 if (empty($rightsholder)) { 992 $rightsholder = $this->getOwner(true); 993 } 994 return $rightsholder; 995 } 996 997 /** 998 * Gets the image copyright URL 999 * 1000 * @since ZenhphotoCMS 1.5.8 1001 * 1002 * @return string 1003 */ 1004 function getCopyrightURL() { 1005 $url = getOption('copyright_image_url'); 1006 if ($url) { 1007 if ($url == 'custom') { 1008 return getOption('copyright_image_url_custom'); 1009 } else if ($url == 'none') { 1010 return null; 1011 } else { 1012 if (extensionEnabled('zenpage') && ZP_PAGES_ENABLED) { 1013 $pageobj = new ZenpagePage($url); 1014 if ($pageobj->exists) { 1015 return $pageobj->getLink(); 1016 } 1017 } 1018 } 1019 } 1020 } 1021 1022 /** 1023 * Permanently delete this image (permanent: be careful!) 1024 * Returns the result of the unlink operation (whether the delete was successful) 1025 * @param bool $clean whether to remove the database entry. 1026 * @return bool 1027 */ 1028 function remove() { 1029 $result = false; 1030 if (parent::remove()) { 1031 $result = true; 1032 $filestodelete = safe_glob(substr($this->localpath, 0, strrpos($this->localpath, '.')) . '.*'); 1033 foreach ($filestodelete as $file) { 1034 @chmod($file, 0777); 1035 $result = $result && @unlink($file); 1036 } 1037 if ($result) { 1038 $this->setUpdatedDateAlbum(); 1039 query("DELETE FROM " . prefix('obj_to_tag') . "WHERE `type`='images' AND `objectid`=" . $this->id); 1040 query("DELETE FROM " . prefix('comments') . "WHERE `type` ='images' AND `ownerid`=" . $this->id); 1041 $cachepath = SERVERCACHE . '/' . pathurlencode($this->album->name) . '/' . $this->filename; 1042 $cachefilestodelete = safe_glob(substr($cachepath, 0, strrpos($cachepath, '.')) . '_*'); 1043 foreach ($cachefilestodelete as $file) { 1044 @chmod($file, 0777); 1045 @unlink($file); 1046 } 1047 1048 } 1049 } 1050 clearstatcache(); 1051 return $result; 1052 } 1053 1054 /** 1055 * Moves an image to a new album and/or filename (rename). 1056 * Returns 0 on success and error indicator on failure. 1057 * @param Album $newalbum the album to move this file to. Must be a valid Album object. 1058 * @param string $newfilename the new file name of the image in the specified album. 1059 * @return int 1060 */ 1061 function move($newalbum, $newfilename = null) { 1062 if (is_string($newalbum)) 1063 $newalbum = newAlbum($newalbum, false); 1064 if ($newfilename == null) { 1065 $newfilename = $this->filename; 1066 } else { 1067 if (getSuffix($this->filename) != getSuffix($newfilename)) { // that is a no-no 1068 return 6; 1069 } 1070 } 1071 if ($newalbum->getID() == $this->album->getID() && $newfilename == $this->filename) { 1072 // Nothing to do - moving the file to the same place. 1073 return 2; 1074 } 1075 $newpath = $newalbum->localpath . internalToFilesystem($newfilename); 1076 if (file_exists($newpath)) { 1077 // If the file exists, don't overwrite it. 1078 if (!(CASE_INSENSITIVE && strtolower($newpath) == strtolower($this->localpath))) { 1079 return 2; 1080 } 1081 } 1082 $filename = basename($this->localpath); 1083 @chmod($filename, 0777); 1084 $result = @rename($this->localpath, $newpath); 1085 @chmod($filename, FILE_MOD); 1086 $this->localpath = $newpath; 1087 clearstatcache(); 1088 if ($result) { 1089 $filestomove = safe_glob(substr($this->localpath, 0, strrpos($this->localpath, '.')) . '.*'); 1090 foreach ($filestomove as $file) { 1091 if (in_array(strtolower(getSuffix($file)), $this->sidecars)) { 1092 $result = $result && @rename($file, stripSuffix($newpath) . '.' . getSuffix($file)); 1093 } 1094 } 1095 } 1096 if ($result) { 1097 if (parent::move(array('filename' => $newfilename, 'albumid' => $newalbum->getID()))) { 1098 $this->setUpdatedDateAlbum(); 1099 $newalbum->setUpdatedDate(); 1100 $newalbum->save(); 1101 $newalbum->setUpdatedDateParents(); 1102 $this->set('mtime', filemtime($newpath)); 1103 $this->save(); 1104 return 0; 1105 } 1106 } 1107 return 1; 1108 } 1109 1110 /** 1111 * Renames an image to a new filename, keeping it in the same album. Convenience for move($image->album, $newfilename). 1112 * Returns true on success and false on failure. 1113 * @param string $newfilename the new file name of the image file. 1114 * @return bool 1115 */ 1116 function rename($newfilename) { 1117 return $this->move($this->album, $newfilename); 1118 } 1119 1120 /** 1121 * Copies the image to a new album, along with all metadata. 1122 * 1123 * @param string $newalbum the destination album 1124 */ 1125 function copy($newalbum) { 1126 if (is_string($newalbum)) { 1127 $newalbum = newAlbum($newalbum, false); 1128 } 1129 if ($newalbum->getID() == $this->album->getID()) { 1130 // Nothing to do - moving the file to the same place. 1131 return 2; 1132 } 1133 $newpath = $newalbum->localpath . internalToFilesystem($this->filename); 1134 if (file_exists($newpath)) { 1135 // If the file exists, don't overwrite it. 1136 return 2; 1137 } 1138 $filename = basename($this->localpath); 1139 $result = @copy($this->localpath, $newpath); 1140 if ($result) { 1141 $filestocopy = safe_glob(substr($this->localpath, 0, strrpos($this->localpath, '.')) . '.*'); 1142 foreach ($filestocopy as $file) { 1143 if (in_array(strtolower(getSuffix($file)), $this->sidecars)) { 1144 $result = $result && @copy($file, $newalbum->localpath . basename($file)); 1145 } 1146 } 1147 } 1148 if ($result) { 1149 if ($newID = parent::copy(array('filename' => $filename, 'albumid' => $newalbum->getID()))) { 1150 storeTags(readTags($this->getID(), 'images'), $newID, 'images'); 1151 query('UPDATE ' . prefix('images') . ' SET `mtime`=' . filemtime($newpath) . ' WHERE `filename`="' . $filename . '" AND `albumid`=' . $newalbum->getID()); 1152 $newalbum->setUpdatedDate(); 1153 $newalbum->save(); 1154 $newalbum->setUpdatedDateParents(); 1155 return 0; 1156 } 1157 } 1158 return 1; 1159 } 1160 1161 /* * ** Image Methods *** */ 1162 1163 /** 1164 * Returns a path urlencoded image page link for the image 1165 * 1166 * @return string 1167 */ 1168 function getLink() { 1169 if (is_array($this->filename)) { 1170 $albumq = $album = dirname($this->filename['source']); 1171 $image = basename($this->filename['source']); 1172 } else { 1173 $album = $this->albumlink; 1174 $albumq = $this->albumnamealbum->name; 1175 $image = $this->filename; 1176 } 1177 return zp_apply_filter('getLink', rewrite_path(pathurlencode($album) . '/' . urlencode($image) . IM_SUFFIX, '/index.php?album=' . pathurlencode($albumq) . '&image=' . urlencode($image)), $this, NULL); 1178 } 1179 1180 /** 1181 * Returns a path to the original image in the original folder. 1182 * 1183 * @param string $path the "path" to the image. Defaults to the simple WEBPATH 1184 * 1185 * @return string 1186 */ 1187 function getFullImage($path = WEBPATH) { 1188 global $_zp_conf_vars; 1189 if ($path == WEBPATH && $_zp_conf_vars['album_folder_class'] == 'external') { 1190 return false; 1191 } 1192 if (is_array($this->filename)) { 1193 $album = dirname($this->filename['source']); 1194 $image = basename($this->filename['source']); 1195 } else { 1196 $album = $this->imagefolder; 1197 $image = $this->filename; 1198 } 1199 return getAlbumFolder($path) . $album . "/" . $image; 1200 } 1201 1202 /** 1203 * returns URL to the original image 1204 */ 1205 function getFullImageURL() { 1206 return $this->getFullImage(WEBPATH); 1207 } 1208 1209 /** 1210 * Returns a path to a sized version of the image 1211 * 1212 * @param int $size how big an image is wanted 1213 * @return string 1214 */ 1215 function getSizedImage($size) { 1216 $wmt = getWatermarkParam($this, WATERMARK_IMAGE); 1217 $args = getImageParameters(array($size, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, $wmt), $this->album->name); 1218 return getImageURI($args, $this->album->name, $this->filename, $this->filemtime); 1219 } 1220 1221 /** 1222 * Get a custom sized version of this image based on the parameters. 1223 * 1224 * @param int $size size 1225 * @param int $width width 1226 * @param int $height height 1227 * @param int $cropw crop width 1228 * @param int $croph crop height 1229 * @param int $cropx crop x axis 1230 * @param int $cropy crop y axis 1231 * @param bool $thumbStandin set to true to treat as thumbnail 1232 * @param bool $effects set to desired image effect (e.g. 'gray' to force gray scale) 1233 * @return string 1234 */ 1235 function getCustomImage($size, $width, $height, $cropw, $croph, $cropx, $cropy, $thumbStandin = false, $effects = NULL) { 1236 if ($thumbStandin < 0) { 1237 $wmt = '!'; 1238 } else { 1239 if ($thumbStandin) { 1240 $wmt = getWatermarkParam($this, WATERMARK_THUMB); 1241 } else { 1242 $wmt = getWatermarkParam($this, WATERMARK_IMAGE); 1243 } 1244 } 1245 $args = getImageParameters(array($size, $width, $height, $cropw, $croph, $cropx, $cropy, NULL, $thumbStandin, NULL, $thumbStandin, $wmt, NULL, $effects), $this->album->name); 1246 return getImageURI($args, $this->album->name, $this->filename, $this->filemtime); 1247 } 1248 1249 /** 1250 * Returns the default sized image HTML 1251 * 1252 * @return string 1253 */ 1254 function getContent() { 1255 $class = ''; 1256 if (!$this->isPublished()) { 1257 $class .= " not_visible"; 1258 } 1259 $album = $this->getAlbum(); 1260 $pwd = $album->getPassword(); 1261 if (!empty($pwd)) { 1262 $class .= " password_protected"; 1263 } 1264 $size = getOption('image_size'); 1265 $h = $this->getHeight(); 1266 $w = $this->getWidth(); 1267 $side = getOption('image_use_side'); 1268 $us = getOption('image_allow_upscale'); 1269 $dim = $size; 1270 1271 if ($w == 0) { 1272 $hprop = 1; 1273 } else { 1274 $hprop = round(($h / $w) * $dim); 1275 } 1276 if ($h == 0) { 1277 $wprop = 1; 1278 } else { 1279 $wprop = round(($w / $h) * $dim); 1280 } 1281 1282 if (($size && ($side == 'longest' && $h > $w) || ($side == 'height') || ($side == 'shortest' && $h < $w))) { 1283 // Scale the height 1284 $newh = $dim; 1285 $neww = $wprop; 1286 } else { 1287 // Scale the width 1288 $neww = $dim; 1289 $newh = $hprop; 1290 } 1291 if (!$us && $newh >= $h && $neww >= $w) { 1292 $neww = $w; 1293 $newh = $h; 1294 } 1295 $html = '<img src="' . html_encode(pathurlencode($this->getSizedImage($size))) . '" alt="' . html_encode($this->getTitle()) . '"' . 1296 ' width="' . $neww . '" height="' . $newh . '"' . 1297 (($class) ? " class=\"$class\"" : "") . " />"; 1298 $html = zp_apply_filter('standard_image_html', $html, $this); 1299 return $html; 1300 } 1301 1302 /** 1303 * Returns the image file name for the thumbnail image. 1304 * 1305 * @param string $path override path 1306 * 1307 * @return s 1308 */ 1309 function getThumbImageFile() { 1310 return $local = $this->localpath; 1311 } 1312 1313 /** 1314 * Returns an array of cropping parameters. Used as a "helper" function for various 1315 * inherited getThumb() methods 1316 * 1317 * @param string $type the type of thumb (in case it ever matters in the cropping, now it does not.) 1318 */ 1319 function getThumbCropping($ts, $sw, $sh) { 1320 $cy = $this->get('thumbY'); 1321 if (is_null($cy)) { 1322 $custom = $cx = NULL; 1323 $cw = $sw; 1324 $ch = $sh; 1325 } else { 1326 $custom = true; 1327 $cx = $this->get('thumbX'); 1328 $cw = $this->get('thumbW'); 1329 $ch = $this->get('thumbH'); 1330 // upscale to thumb_size proportions 1331 if ($sw == $sh) { // square crop, set the size/width to thumbsize 1332 $sw = $sh = $ts; 1333 } else { 1334 if ($sw > $sh) { 1335 $r = $ts / $sw; 1336 $sw = $ts; 1337 $sh = $sh * $r; 1338 } else { 1339 $r = $ts / $sh; 1340 $sh = $ts; 1341 $sh = $r * $sh; 1342 } 1343 } 1344 } 1345 return array($custom, $cw, $ch, $cx, $cy); 1346 } 1347 1348 /** 1349 * Get a default-sized thumbnail of this image. 1350 * 1351 * @return string 1352 */ 1353 function getThumb($type = 'image') { 1354 $ts = getOption('thumb_size'); 1355 if (getOption('thumb_crop')) { 1356 $sw = getOption('thumb_crop_width'); 1357 $sh = getOption('thumb_crop_height'); 1358 list($custom, $cw, $ch, $cx, $cy) = $this->getThumbCropping($ts, $sw, $sh); 1359 if ($custom) { 1360 $ts = null; 1361 } 1362 } else { 1363 $sw = $sh = $cw = $ch = $cx = $cy = null; 1364 } 1365 return $this->getCustomImage($ts, $sw, $sh, $cw, $ch, $cx, $cy, true); 1366 } 1367 1368 /** 1369 * Get the index of this image in the album, taking sorting into account. 1370 * @param bool $use_realalbum If the image is wihtin a dynamic album this is the index within it, set to true to get the index of the actual physical album the image belongs 1371 * @return int 1372 */ 1373 function getIndex($use_realalbum = false) { 1374 global $_zp_current_search, $_zp_current_album; 1375 $use_realalbum = true; 1376 if ($this->index == NULL) { 1377 if ($use_realalbum) { 1378 $album = $this->getAlbum(); 1379 } else { 1380 $album = $this->albumnamealbum; 1381 } 1382 if (!is_null($_zp_current_search) && !in_context(ZP_ALBUM_LINKED) || $album->isDynamic()) { 1383 if ($album->isDynamic()) { 1384 $images = $album->getImages(); 1385 for ($i = 0; $i < count($images); $i++) { 1386 $image = $images[$i]; 1387 if ($this->filename == $image['filename']) { 1388 $this->index = $i; 1389 break; 1390 } 1391 } 1392 } else { 1393 $this->index = $_zp_current_search->getImageIndex($this->imagefolder, $this->filename); 1394 } 1395 } else { 1396 $images = $this->album->getImages(0); 1397 for ($i = 0; $i < count($images); $i++) { 1398 $image = $images[$i]; 1399 if ($this->filename == $image) { 1400 $this->index = $i; 1401 break; 1402 } 1403 } 1404 } 1405 } 1406 return $this->index; 1407 } 1408 1409 /** 1410 * Returns the next Image. 1411 * 1412 * @return object 1413 */ 1414 function getNextImage() { 1415 global $_zp_current_search; 1416 $index = $this->getIndex(); 1417 if (!is_null($_zp_current_search) && !in_context(ZP_ALBUM_LINKED)) { 1418 $image = $_zp_current_search->getImage($index + 1); 1419 } else { 1420 $album = $this->albumnamealbum; 1421 $image = $album->getImage($index + 1); 1422 } 1423 return $image; 1424 } 1425 1426 /** 1427 * Return the previous Image 1428 * 1429 * @return object 1430 */ 1431 function getPrevImage() { 1432 global $_zp_current_search; 1433 $index = $this->getIndex(); 1434 if (!is_null($_zp_current_search) && !in_context(ZP_ALBUM_LINKED)) { 1435 $image = $_zp_current_search->getImage($index - 1); 1436 } else { 1437 $album = $this->albumnamealbum; 1438 $image = $album->getImage($index - 1); 1439 } 1440 return $image; 1441 } 1442 1443 /** 1444 * Returns the disk size of the image 1445 * 1446 * @return string 1447 */ 1448 function getImageFootprint() { 1449 return filesize($this->localpath); 1450 } 1451 1452 /** 1453 * Returns the custom watermark name 1454 * 1455 * @return string 1456 */ 1457 function getWatermark() { 1458 return $this->get('watermark'); 1459 } 1460 1461 /** 1462 * Set custom watermark 1463 * 1464 * @param string $wm 1465 */ 1466 function setWatermark($wm) { 1467 $this->set('watermark', $wm); 1468 } 1469 1470 /** 1471 * Returns the custom watermark usage 1472 * 1473 * @return bool 1474 */ 1475 function getWMUse() { 1476 return $this->get('watermark_use'); 1477 } 1478 1479 /** 1480 * Sets the custom watermark usage 1481 * 1482 * @param $use 1483 */ 1484 function setWMUse($use) { 1485 $this->set('watermark_use', $use); 1486 } 1487 1488 /** 1489 * Gets the owner of the image 1490 * 1491 * @param bool $fullname Set to true to get the full name (if the owner is a vaild user of the site and has the full name defined) 1492 * @return string 1493 */ 1494 function getOwner($fullname = false) { 1495 $owner = $this->get('owner'); 1496 if (empty($owner)) { 1497 $owner = $this->album->getOwner(); 1498 } 1499 if ($fullname) { 1500 return Zenphoto_Administrator::getNameByUser($owner); 1501 } 1502 return $owner; 1503 } 1504 1505 function setOwner($owner) { 1506 $this->set('owner', $owner); 1507 } 1508 1509 function isMyItem($action) { 1510 $album = $this->album; 1511 return $album->isMyItem($action); 1512 } 1513 1514 /** 1515 * returns true if user is allowed to see the image 1516 */ 1517 function checkAccess(&$hint = NULL, &$show = NULL) { 1518 $album = $this->getAlbum(); 1519 if ($album->isMyItem(LIST_RIGHTS)) { 1520 return $this->isPublished() || $album->albumSubRights() & (MANAGED_OBJECT_RIGHTS_EDIT | MANAGED_OBJECT_RIGHTS_VIEW); 1521 } 1522 return $album->checkforGuest($hint, $show) && $this->isPublished() && $album->isPublished(); 1523 } 1524 1525 /** 1526 * Checks if guest is loggedin for the album 1527 * @param unknown_type $hint 1528 * @param unknown_type $show 1529 */ 1530 function checkforGuest(&$hint = NULL, &$show = NULL) { 1531 if (!parent::checkForGuest()) { 1532 return false; 1533 } 1534 $album = $this->getAlbum(); 1535 return $album->checkforGuest($hint, $show); 1536 } 1537 1538 /** 1539 * 1540 * returns true if there is any protection on the image 1541 */ 1542 function isProtected() { 1543 return $this->checkforGuest() != 'zp_public_access'; 1544 } 1545 1546 /** 1547 * Returns true if this image is published and also its album and all of its parents. 1548 * 1549 * @since Zenphoto 1.5.5 1550 * 1551 * @return bool 1552 */ 1553 function isPublic() { 1554 if (is_null($this->is_public)) { 1555 if (!$this->isPublished()) { 1556 return $this->is_public = false; 1557 } 1558 $album = $this->getAlbum(); 1559 if(!$album->isPublic()) { 1560 return $this->is_public = false; 1561 } 1562 return $this->is_public = true; 1563 } else { 1564 return $this->is_public; 1565 } 1566 } 1567 1568 /** 1569 * Returns the filesize in bytes of the full image 1570 * 1571 * @since ZenphotoCMS 1.5.2 1572 * 1573 * @return int|false 1574 */ 1575 function getFilesize() { 1576 $album = $this->getAlbum(); 1577 $filesize = filesize($this->getFullImage(SERVERPATH)); 1578 return $filesize; 1579 } 1580 1581 /** 1582 * Sets the current date to the images'album and all of its parent albums recursively 1583 * @since Zenphoto 1.5.5 1584 */ 1585 function setUpdatedDateAlbum() { 1586 $album = $this->album; 1587 if($album) { 1588 $album->setUpdatedDate(); 1589 $album->save(); 1590 $album->setUpdatedDateParents(); 1591 } 1592 } 1593 1594} 1595 1596/** 1597 * Transient image class 1598 * @package core 1599 * @subpackage classes\objects 1600 */ 1601class Transientimage extends Image { 1602 1603 /** 1604 * creates a transient image (that is, one that is not stored in the database) 1605 * 1606 * @param string $image the full path to the image 1607 * @return transientimage 1608 */ 1609 function __construct($album, $image) { 1610 if (!is_object($album)) { 1611 $album = new AlbumBase('Transient'); 1612 } 1613 $this->album = $album; 1614 $this->localpath = $image; 1615 $filename = makeSpecialImageName($image); 1616 $this->filename = $filename; 1617 $this->displayname = stripSuffix(basename($image)); 1618 if (empty($this->displayname)) { 1619 $this->displayname = $this->filename['name']; 1620 } 1621 $this->filemtime = @filemtime($this->localpath); 1622 $this->comments = null; 1623 $this->instantiate('images', array('filename' => $filename['name'], 'albumid' => $this->album->getID()), 'filename', true, true); 1624 $this->exists = false; 1625 } 1626 1627} 1628 1629?> 1630