self::MAXFILESIZE) {
return self::ERROR_FILETOOBIG;
}
$dimensions = getimagesize($filesArrayElement['tmp_name']);
$width = $dimensions[0];
$height = $dimensions[1];
// Big Enough?
if ($width < self::MINWIDTH || $height < self::MINHEIGHT) {
return self::ERROR_IMAGETOOSMALL;
}
// Too Big?
$area = $width * $height;
if ($area > self::MAXPIXELAREA) {
return self::ERROR_IMAGETOOBIG;
}
return false;
}
/**
* Replaces a user's avatar with the specified image
*
* @param int $userID The user whose avatar is being updated
* @param array $filesArrayElement A member of the $_FILES array containing the new avatar image
* @throws InvalidArgumentException
*/
public static function updateFromUploadedFile($userID, $filesArrayElement)
{
// Validate UserID
if (!(filter_var($userID, FILTER_VALIDATE_INT) > 0)) {
throw new \InvalidArgumentException("User id is invalid: $userID");
}
// Validate File
if (self::errorCheckUploadedFile($filesArrayElement)) {
throw new \InvalidArgumentException("File error check failed. Error check file for more details.");
}
// Remember the previous avatar files so we can delete them once the new avatar files are activated
$oldFiles = query("SELECT smImageName, smImageName64, smImageName128 FROM tig.Users WHERE UserID = " . mysqlescape($userID));
// Allow extra memory for memory-intensive image processing
$oldMemoryLimit = ini_set('memory_limit', self::MEMORYLIMIT);
// Resize the images
$filename32 = self::createLocalFile($filesArrayElement, $userID, 32);
$filename64 = self::createLocalFile($filesArrayElement, $userID, 64);
$filename128 = self::createLocalFile($filesArrayElement, $userID, 128);
// Restore original memory limit now that image processing is done
ini_set('memory_limit', $oldMemoryLimit);
// Looking at "members/avatar/index.html", it doesn't appear that the
// CDN is even used. In case it is in some way I don't realize,
// the avatar images are copied there.
self::createCdnFile($filename32);
self::createCdnFile($filename64);
self::createCdnFile($filename128);
// Activate the new avatars in the database
safe_dbwrite("UPDATE tig.Users
SET smImageName = '$filename32',
smImageName64 = '$filename64',
smImageName128 = '$filename128'
WHERE UserID = " . mysqlescape($userID));
// Activate the new avatars in the $TIGUserInfo cookie - I don't know
// where this info is used but avatarupload.html does this so it's
// included here.
global $TIGUserInfo;
$TIGUserInfo['smImageName'] = $filename32;
$TIGUserInfo['smImageName64'] = $filename64;
$TIGUserInfo['smImageName128'] = $filename128;
setcookie("TIGUserInfo", serialize($TIGUserInfo), "0", "/", ".tigweb.org");
// Delete Obsolete Avatars - If there were previous avatar files and
// their names have changed (meaning the old avatars were not
// simply overwritten), then delete the previous files.
if ($oldFiles['smImageName'] && $filename32 != $oldFiles['smImageName']) {
self::deleteLocalFile($oldFiles['smImageName']);
self::deleteCdnFile($oldFiles['smImageName']);
}
if ($oldFiles['smImageName64'] && $filename64 != $oldFiles['smImageName64']) {
self::deleteLocalFile($oldFiles['smImageName64']);
self::deleteCdnFile($oldFiles['smImageName64']);
}
if ($oldFiles['smImageName128'] && $filename128 != $oldFiles['smImageName128']) {
self::deleteLocalFile($oldFiles['smImageName128']);
self::deleteCdnFile($oldFiles['smImageName128']);
}
// Add "Jeff changed his avatar" to Feeds
add2bb($userID, 75, "{$TIGUserInfo['Username']}|");
}
/**
* Saves a square avatar image file
*
* @param $filesArrayElement A member of $_FILES
* @param int $userID The user the avatar is for. Ex. 654811
* @param int $size The side length of the square avatar image to create. Ex. 32
* @return string The name of the file created
*/
private static function createLocalFile($filesArrayElement, $userID, $size)
{
$extension = pathinfo($filesArrayElement['name'], PATHINFO_EXTENSION);
// Ex. "654811_32.jpg"
$filename = "{$userID}_{$size}.{$extension}";
$imageManipulator = new \Zebra_Image();
$imageManipulator->source_path = $filesArrayElement['tmp_name'];
$imageManipulator->target_path = IMAGEROOT . self::IMAGEFOLDER . $filename;
$imageManipulator->resize($size, $size, ZEBRA_IMAGE_CROP_CENTER);
return $filename;
}
/**
* Permanently erases a avatar file stored on the server
*
* @param string $filename The local avatar file to delete. ex. 654811_32.jpg
*/
private static function deleteLocalFile($filename)
{
$filePath = IMAGEROOT . self::IMAGEFOLDER . $filename;
if (is_file($filePath)) {
unlink($filePath);
}
}
/**
* Copies local avatar images to Cloud Files
*
* @param string $filename The local filename
* @throws InvalidArgumentException
*/
private static function createCdnFile($filename)
{
$filePath = IMAGEROOT . self::IMAGEFOLDER . $filename;
if (!is_file($filePath)) {
throw new \InvalidArgumentException('Source file not found');
}
$container = self::getCloudFilesContainer();
$image = $container->create_object($filename);
$image->load_from_filename(IMAGEROOT . self::IMAGEFOLDER . $filename);
$container->make_public(3600);
}
/**
* Reomves and avatar image from Cloud Files
*
* @param string $filename The local filename
* @throws InvalidArgumentException
*/
private static function deleteCdnFile($filename)
{
$container = self::getCloudFilesContainer();
try {
$container->delete_object($filename);
} catch (NoSuchObjectExceptionException $ex) {
// do nothing - it doesn't matter whether the file was deleted or not there in the beginning
}
}
/**
* Connects to Rackspace Cloud Files to manipulate photos
*
* @return CF_Container Connection to the Rackspace container containing avatars
*/
private static function getCloudFilesContainer()
{
if (!self::$cloudFilesContainer) {
$auth = new \CF_Authentication(self::CDNUSERNAME, self::CDNAPIKEY);
$auth->authenticate();
$connection = new \CF_Connection($auth);
self::$cloudFilesContainer = $connection->get_container(self::CDNCONTAINER);
}
return self::$cloudFilesContainer;
}
}