SPTImage.php
Go to the documentation of this file.
00001 <?PHP 00002 # 00003 # FILE: SPTImage.php 00004 # 00005 # METHODS PROVIDED: 00006 # SPTImage($ImageIdOrFileNameOrImageObj, 00007 # $MaxPreviewWidth = NULL, $MaxPreviewHeight = NULL, 00008 # $MaxThumbnailWidth = NULL, $MaxThumbnailHeight = NULL) 00009 # - object constructor 00010 # Delete() 00011 # - delete image and associated files and data 00012 # AltText($NewValue = NULL) 00013 # - get/set alt text attribute 00014 # Id() 00015 # Url() 00016 # PreviewUrl() 00017 # ThumbnailUrl() 00018 # Format() 00019 # Height() 00020 # Width() 00021 # PreviewHeight() 00022 # PreviewWidth() 00023 # ThumbnailHeight() 00024 # ThumbnailWidth() 00025 # - get attributes 00026 # 00027 # AUTHOR: Edward Almasy 00028 # 00029 # Part of CWIS 00030 # Copyright 2002-2011 Internet Scout Project 00031 # http://scout.wisc.edu 00032 # 00033 00034 class SPTImage { 00035 00036 # ---- PUBLIC INTERFACE -------------------------------------------------- 00037 00043 const IMAGE_PATH = "ImageStorage/"; 00044 const PREVIEW_PATH = "ImageStorage/Previews/"; 00045 const THUMBNAIL_PATH = "ImageStorage/Thumbnails/"; 00046 00047 # object constructor 00048 function SPTImage($ImageIdOrFileNameOrImageObj, 00049 $MaxPreviewWidth = NULL, $MaxPreviewHeight = NULL, 00050 $MaxThumbnailWidth = NULL, $MaxThumbnailHeight = NULL) 00051 { 00052 # clear error status (0 = AI_OKAY) 00053 $this->ErrorStatus = 0; 00054 00055 # trigger the Image class file to be autoloaded since some parts of this 00056 # class (SPTImage) use constants defined in it but don't construct Image 00057 # objects 00058 new Image(NULL); 00059 00060 # create and save a database handle for our use 00061 $this->DB = new SPTDatabase(); 00062 00063 # if image object was passed in 00064 if (is_object($ImageIdOrFileNameOrImageObj) 00065 && method_exists($ImageIdOrFileNameOrImageObj, "SPTImage")) 00066 { 00067 # create copy of image passed in 00068 $this->CreateCopyOfImage($ImageIdOrFileNameOrImageObj); 00069 } 00070 # else if image ID was passed in 00071 elseif (($ImageIdOrFileNameOrImageObj > 0) 00072 && preg_match("/[0-9]+/", $ImageIdOrFileNameOrImageObj)) 00073 { 00074 # load info on existing image 00075 $this->LoadImageInfo($ImageIdOrFileNameOrImageObj); 00076 } 00077 # else assume that value passed in is file name 00078 else 00079 { 00080 # create new image from named file 00081 $this->CreateNewImage($ImageIdOrFileNameOrImageObj, 00082 $MaxPreviewWidth, $MaxPreviewHeight, 00083 $MaxThumbnailWidth, $MaxThumbnailHeight); 00084 } 00085 } 00086 00087 # get attributes 00088 function Id() { return $this->Id; } 00089 function Url() { return $this->FileName; } 00090 function PreviewUrl() { return $this->PreviewFileName; } 00091 function ThumbnailUrl() { return $this->ThumbnailFileName; } 00092 function Format() { return $this->Format; } 00093 function Height() { return $this->Height; } 00094 function Width() { return $this->Width; } 00095 function PreviewHeight() { return $this->PreviewHeight; } 00096 function PreviewWidth() { return $this->PreviewWidth; } 00097 function ThumbnailHeight() { return $this->ThumbnailHeight; } 00098 function ThumbnailWidth() { return $this->ThumbnailWidth; } 00099 function ImageStorageDirectory() { return self::IMAGE_PATH; } 00100 function PreviewStorageDirectory() { return self::PREVIEW_PATH; } 00101 function ThumbnailStorageDirectory() { return self::THUMBNAIL_PATH; } 00102 function GetLink() { return $this->FileName; } 00103 00104 # get/set attributes 00105 function AltText($NewValue = NULL) 00106 { 00107 # if new value supplied and new value differs from existing value 00108 if (($NewValue !== NULL) && ($NewValue != $this->AltText)) 00109 { 00110 # save new value to database 00111 $this->DB->Query("UPDATE Images SET" 00112 ." AltText = '".addslashes($NewValue)."'" 00113 ." WHERE ImageId = ".$this->Id); 00114 00115 # save new value locally 00116 $this->AltText = $NewValue; 00117 } 00118 00119 # return attribute value to caller 00120 return $this->AltText; 00121 } 00122 00123 # delete image and associated files and data 00124 function Delete() 00125 { 00126 # delete base image file 00127 if (file_exists($this->FileName)) { unlink($this->FileName); } 00128 00129 # delete preview image file 00130 if (file_exists($this->PreviewFileName)) { unlink($this->PreviewFileName); } 00131 00132 # delete thumbnail image file 00133 if (file_exists($this->ThumbnailFileName)) { unlink($this->ThumbnailFileName); } 00134 00135 # delete image info record in database 00136 $this->DB->Query("DELETE FROM Images WHERE ImageId = ".$this->Id); 00137 } 00138 00139 # return error status set by the constructor 00140 function Status() 00141 { 00142 return $this->ErrorStatus; 00143 } 00144 00145 # check to make sure image storage directories are available 00146 # (returns array of error codes or NULL if no errors found) 00147 static function CheckDirectories() 00148 { 00149 # determine paths 00150 $ImagePath = self::IMAGE_PATH; 00151 $PreviewPath = self::PREVIEW_PATH; 00152 $ThumbnailPath = self::THUMBNAIL_PATH; 00153 00154 # assume everything will be okay 00155 $ErrorsFound = NULL; 00156 00157 # check base image directory 00158 if (!is_dir($ImagePath) || !is_writable($ImagePath)) 00159 { 00160 if (!is_dir($ImagePath)) 00161 { 00162 @mkdir($ImagePath, 0755); 00163 } 00164 else 00165 { 00166 @chmod($ImagePath, 0755); 00167 } 00168 if (!is_dir($ImagePath)) 00169 { 00170 $ErrorsFound[] = "Image Storage Directory Not Found"; 00171 } 00172 elseif (!is_writable($ImagePath)) 00173 { 00174 $ErrorsFound[] = "Image Storage Directory Not Writable"; 00175 } 00176 } 00177 00178 # check preview directory 00179 if (!is_dir($PreviewPath) || !is_writable($PreviewPath)) 00180 { 00181 if (!is_dir($PreviewPath)) 00182 { 00183 @mkdir($PreviewPath, 0755); 00184 } 00185 else 00186 { 00187 @chmod($PreviewPath, 0755); 00188 } 00189 if (!is_dir($PreviewPath)) 00190 { 00191 $ErrorsFound[] = "Preview Storage Directory Not Found"; 00192 } 00193 elseif (!is_writable($PreviewPath)) 00194 { 00195 $ErrorsFound[] = "Preview Storage Directory Not Writable"; 00196 } 00197 } 00198 00199 # check thumbnail directory 00200 if (!is_dir($ThumbnailPath) || !is_writable($ThumbnailPath)) 00201 { 00202 if (!is_dir($ThumbnailPath)) 00203 { 00204 @mkdir($ThumbnailPath, 0755); 00205 } 00206 else 00207 { 00208 @chmod($ThumbnailPath, 0755); 00209 } 00210 if (!is_dir($ThumbnailPath)) 00211 { 00212 $ErrorsFound[] = "Thumbnail Storage Directory Not Found"; 00213 } 00214 elseif (!is_writable($ThumbnailPath)) 00215 { 00216 $ErrorsFound[] = "Thumbnail Storage Directory Not Writable"; 00217 } 00218 } 00219 00220 # return any errors found to caller 00221 return $ErrorsFound; 00222 } 00223 00224 00225 # ---- PRIVATE INTERFACE ------------------------------------------------- 00226 00227 var $Id; 00228 var $FileName; 00229 var $PreviewFileName; 00230 var $ThumbnailFileName; 00231 var $Format; 00232 var $AltText; 00233 var $Url; 00234 var $PreviewUrl; 00235 var $ThumbnailUrl; 00236 var $Height; 00237 var $Width; 00238 var $PreviewHeight; 00239 var $PreviewWidth; 00240 var $ThumbnailHeight; 00241 var $ThumbnailWidth; 00242 var $DB; 00243 var $ErrorStatus; 00244 00245 function CreateNewImage($FileName, $MaxPreviewWidth, $MaxPreviewHeight, 00246 $MaxThumbnailWidth, $MaxThumbnailHeight) 00247 { 00248 # if file does not exist or is not readable 00249 if (!is_readable($FileName)) 00250 { 00251 # set error status 00252 $this->ErrorStatus = AI_FILEUNREADABLE; 00253 } 00254 else 00255 { 00256 # if image is invalid or unsupported type 00257 $SrcImage = new Image($FileName); 00258 if ($SrcImage->Status() != AI_OKAY) 00259 { 00260 # set error status 00261 $this->ErrorStatus = $SrcImage->Status(); 00262 } 00263 else 00264 { 00265 # retrieve image type 00266 $this->Format = $SrcImage->Type(); 00267 00268 # generate new image ID 00269 $this->Id = $this->GenerateNewImageId(); 00270 00271 # generate and set file names 00272 $this->SetFileNames(); 00273 00274 # if our image file name differs from file name passed in 00275 if (realpath($this->FileName) != realpath($FileName)) 00276 { 00277 # create image file 00278 $SrcImage->SaveAs($this->FileName); 00279 00280 # if create failed set error status and bail out 00281 if ($SrcImage->Status() != AI_OKAY) 00282 { 00283 echo "create failed<br>"; 00284 echo "Status: ".$SrcImage->Status()."<br>"; 00285 echo "Failed Command: ".$SrcImage->FailedExternalCommand()."<br>"; 00286 echo "Missing External Executables: "; 00287 print_r(Image::MissingExternalExecutables()); 00288 echo "<br>"; 00289 $this->ErrorStatus = $SrcImage->Status(); 00290 return; 00291 } 00292 } 00293 00294 # retrieve image width and height 00295 $this->Height = $SrcImage->YSize(); 00296 $this->Width = $SrcImage->XSize(); 00297 00298 # generate preview image and calculate width and height 00299 $MaxPreviewWidth = min($MaxPreviewWidth, $this->Width); 00300 $MaxPreviewHeight = min($MaxPreviewHeight, $this->Height); 00301 $SrcImage->ScaleTo($MaxPreviewWidth, $MaxPreviewHeight, TRUE); 00302 $SrcImage->SaveAs($this->PreviewFileName, IMGTYPE_JPEG); 00303 if ($SrcImage->Status() != AI_OKAY) 00304 { 00305 echo "preview save as failed<br>"; 00306 $this->ErrorStatus = $SrcImage->Status(); 00307 return; 00308 } 00309 if (($this->Width * $MaxPreviewHeight) 00310 > ($this->Height * $MaxPreviewWidth)) 00311 { 00312 $this->PreviewWidth = $MaxPreviewWidth; 00313 $this->PreviewHeight = 00314 ($MaxPreviewWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00315 } 00316 else 00317 { 00318 $this->PreviewWidth = 00319 ($MaxPreviewHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00320 $this->PreviewHeight = $MaxPreviewHeight; 00321 } 00322 00323 # generate thumbnail image and calculate width and height 00324 $MaxThumbnailWidth = min($MaxThumbnailWidth, $this->Width); 00325 $MaxThumbnailHeight = min($MaxThumbnailHeight, $this->Height); 00326 $SrcImage->ScaleTo($MaxThumbnailWidth, $MaxThumbnailHeight, TRUE); 00327 $SrcImage->SaveAs($this->ThumbnailFileName, IMGTYPE_JPEG); 00328 if ($SrcImage->Status() != AI_OKAY) 00329 { 00330 echo "thumbnail SaveAs failed.<br>"; 00331 $this->ErrorStatus = $SrcImage->Status(); 00332 return; 00333 } 00334 if (($this->Width * $MaxThumbnailHeight) 00335 > ($this->Height * $MaxThumbnailWidth)) 00336 { 00337 $this->ThumbnailWidth = $MaxThumbnailWidth; 00338 $this->ThumbnailHeight = 00339 ($MaxThumbnailWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00340 } 00341 else 00342 { 00343 $this->ThumbnailWidth = ($MaxThumbnailHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00344 $this->ThumbnailHeight = $MaxThumbnailHeight; 00345 } 00346 00347 # save image attributes to database 00348 $this->SaveImageInfo(); 00349 } 00350 } 00351 } 00352 00353 function LoadImageInfo($ImageId) 00354 { 00355 # save image ID 00356 $this->Id = $ImageId; 00357 00358 # load image record from database 00359 $this->DB->Query("SELECT * FROM Images WHERE ImageId = ".$ImageId); 00360 00361 # if the ID is invalid 00362 if (!$this->DB->NumRowsSelected()) 00363 { 00364 $this->ErrorStatus = AI_INTERNALERROR; 00365 return; 00366 } 00367 00368 $Record = $this->DB->FetchRow(); 00369 00370 # load in values from record 00371 $this->Format = $Record["Format"]; 00372 $this->AltText = $Record["AltText"]; 00373 $this->Height = $Record["Height"]; 00374 $this->Width = $Record["Width"]; 00375 $this->PreviewHeight = $Record["PreviewHeight"]; 00376 $this->PreviewWidth = $Record["PreviewWidth"]; 00377 $this->ThumbnailHeight = $Record["ThumbnailHeight"]; 00378 $this->ThumbnailWidth = $Record["ThumbnailWidth"]; 00379 00380 # generate file names 00381 $this->SetFileNames(); 00382 } 00383 00384 function CreateCopyOfImage($SrcImage) 00385 { 00386 $Image = new Image($SrcImage->Url()); 00387 if ($Image->Status() != AI_OKAY) 00388 { 00389 # set error status 00390 $this->ErrorStatus = $Image->Status(); 00391 return; 00392 } 00393 00394 # generate new image ID 00395 $this->Id = $this->GenerateNewImageId(); 00396 00397 # generate file names 00398 $this->SetFileNames(); 00399 00400 # copy attributes from source image 00401 $this->Format = $SrcImage->Format(); 00402 $this->AltText = $SrcImage->AltText(); 00403 $this->Width = $SrcImage->Width(); 00404 $this->Height = $SrcImage->Height(); 00405 $this->PreviewWidth = $SrcImage->PreviewWidth(); 00406 $this->PreviewHeight = $SrcImage->PreviewHeight(); 00407 $this->ThumbnailWidth = $SrcImage->ThumbnailWidth(); 00408 $this->ThumbnailHeight = $SrcImage->ThumbnailHeight(); 00409 00410 # copy source image files 00411 copy($SrcImage->Url(), $this->FileName); 00412 copy($SrcImage->PreviewUrl(), $this->PreviewFileName); 00413 copy($SrcImage->ThumbnailUrl(), $this->ThumbnailFileName); 00414 00415 # save image attributes to database 00416 $this->SaveImageInfo(); 00417 } 00418 00419 # generate and save image, preview, and thumnail file names 00420 # (requires image ID and format to be set beforehand) 00421 function SetFileNames() 00422 { 00423 if (Image::Extension($this->Format)) 00424 { 00425 $FileExtension = Image::Extension($this->Format); 00426 } 00427 else 00428 { 00429 $FileExtension = ""; 00430 } 00431 00432 $this->FileName = self::IMAGE_PATH . "Img--" 00433 .sprintf("%08d.", $this->Id).$FileExtension; 00434 $this->PreviewFileName = self::PREVIEW_PATH . "Preview--" 00435 .sprintf("%08d.", $this->Id).$FileExtension; 00436 $this->ThumbnailFileName = self::THUMBNAIL_PATH . "Thumb--" 00437 .sprintf("%08d.", $this->Id).$FileExtension; 00438 } 00439 00440 # retrieve next image ID 00441 function GenerateNewImageId() 00442 { 00443 # look up highest image ID in database 00444 $CurrentHighestId = $this->DB->Query("SELECT ImageId FROM Images" 00445 ." ORDER BY ImageId DESC LIMIT 1", 00446 "ImageId"); 00447 00448 # return next highest ID or 1 if no ID yet used 00449 return ($CurrentHighestId > 0) ? ($CurrentHighestId + 1) : 1; 00450 } 00451 00452 # store image attributes to database 00453 function SaveImageInfo() 00454 { 00455 # look for existing image record with matching ID 00456 $RecordCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount FROM Images" 00457 ." WHERE ImageId = ".$this->Id, 00458 "RecordCount"); 00459 00460 # if matching ID found 00461 if ($RecordCount > 0) 00462 { 00463 # update existing image record 00464 $this->DB->Query("UPDATE Images SET" 00465 ." Format = '" .$this->Format."'," 00466 ." AltText = '" .addslashes($this->AltText)."'," 00467 ." Height = '" .$this->Height."'," 00468 ." Width = '" .$this->Width."'," 00469 ." PreviewHeight = '" .$this->PreviewHeight."'," 00470 ." PreviewWidth = '" .$this->PreviewWidth."'," 00471 ." ThumbnailHeight = '".$this->ThumbnailHeight."'," 00472 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'" 00473 ." WHERE ImageId = ".$this->Id); 00474 } 00475 else 00476 { 00477 # add new image record 00478 $this->DB->Query("INSERT INTO Images SET" 00479 ." ImageId = '" .$this->Id."'," 00480 ." Format = '" .$this->Format."'," 00481 ." AltText = '" .addslashes($this->AltText)."'," 00482 ." Height = '" .$this->Height."'," 00483 ." Width = '" .$this->Width."'," 00484 ." PreviewHeight = '" .$this->PreviewHeight."'," 00485 ." PreviewWidth = '" .$this->PreviewWidth."'," 00486 ." ThumbnailHeight = '".$this->ThumbnailHeight."'," 00487 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'"); 00488 } 00489 } 00490 }