Вход Регистрация
Файл: library/XenForo/Model/Avatar.php
Строк: 364
<?php

/**
 * Model for avatars.
 *
 * @package XenForo_Avatar
 */
class XenForo_Model_Avatar extends XenForo_Model
{
    
/**
     * List of available avatar sizes. The largest must go first.
     * Avatars of each size code (directory name) will be no bigger
     * than the given pixel amount.
     *
     * @var array Format: [code] => max pixels
     */
    
protected static $_sizes = array(
        
'l' => 192,
        
'm' => 96,
        
's' => 48
    
);

    public static 
$imageQuality = 85;

    
/**
     * Processes an avatar upload for a user.
     *
     * @param XenForo_Upload $upload The uploaded avatar.
     * @param integer $userId User ID avatar belongs to
     * @param array|false $permissions User's permissions. False to skip permission checks
     *
     * @return array Changed avatar fields
     */
    
public function uploadAvatar(XenForo_Upload $upload, $userId, $permissions)
    {
        if (!
$userId)
        {
            throw new 
XenForo_Exception('Missing user ID.');
        }

        if (
$permissions !== false && !is_array($permissions))
        {
            throw new 
XenForo_Exception('Invalid permission set.');
        }

        
$largestDimension = $this->getSizeFromCode('l');

        if (!
$upload->isValid())
        {
            throw new 
XenForo_Exception($upload->getErrors(), true);
        }

        if (!
$upload->isImage())
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('uploaded_file_is_not_valid_image'), true);
        };

        
$imageType = $upload->getImageInfoField('type');
        if (!
in_array($imageType, array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG)))
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('uploaded_file_is_not_valid_image'), true);
        }

        
$baseTempFile = $upload->getTempFile();

        
$width = $upload->getImageInfoField('width');
        
$height = $upload->getImageInfoField('height');

        return 
$this->applyAvatar($userId, $baseTempFile, $imageType, $width, $height, $permissions);
    }

    
/**
     * Applies the avatar file to the specified user.
     *
     * @param integer $userId
     * @param string $fileName
     * @param constant|false $imageType Type of image (IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG)
     * @param integer|false $width
     * @param integer|false $height
     * @param array|false $permissions
     *
     * @return array
     */
    
public function applyAvatar($userId, $fileName, $imageType = false, $width = false, $height = false, $permissions = false)
    {
        if (!
$imageType || !$width || !$height)
        {
            
$imageInfo = getimagesize($fileName);
            if (!
$imageInfo)
            {
                throw new 
XenForo_Exception('Non-image passed in to applyAvatar');
            }
            
$width = $imageInfo[0];
            
$height = $imageInfo[1];
            
$imageType = $imageInfo[2];
        }

        if (!
in_array($imageType, array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG)))
        {
            throw new 
XenForo_Exception('Invalid image type passed in to applyAvatar');
        }

        if (!
XenForo_Image_Abstract::canResize($width, $height))
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('uploaded_image_is_too_big'), true);
        }

        
// require 2:1 aspect ratio or squarer
        
if ($width > 2 * $height || $height > 2 * $width)
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('please_provide_an_image_whose_longer_side_is_no_more_than_twice_length'), true);
        }

        
$outputFiles = array();
        
$outputType = $imageType;

        
reset(self::$_sizes);
        list(
$sizeCode, $maxDimensions) = each(self::$_sizes);

        
$shortSide = ($width > $height ? $height : $width);

        if (
$shortSide > $maxDimensions)
        {
            
$newTempFile = tempnam(XenForo_Helper_File::getTempDir(), 'xf');
            
$image = XenForo_Image_Abstract::createFromFile($fileName, $imageType);
            if (!
$image)
            {
                throw new 
XenForo_Exception(new XenForo_Phrase('image_could_be_processed_try_another_contact_owner'), true);
            }
            
$image->thumbnailFixedShorterSide($maxDimensions);
            
$image->output($outputType, $newTempFile, self::$imageQuality);

            
$width = $image->getWidth();
            
$height = $image->getHeight();

            
$outputFiles[$sizeCode] = $newTempFile;
        }
        else
        {
            
$outputFiles[$sizeCode] = $fileName;
        }

        if (
is_array($permissions))
        {
            
$maxFileSize = XenForo_Permission::hasPermission($permissions, 'avatar', 'maxFileSize');
            if (
$maxFileSize != -1 && filesize($outputFiles[$sizeCode]) > $maxFileSize)
            {
                foreach (
$outputFiles AS $tempFile)
                {
                    if (
$tempFile != $fileName)
                    {
                        @
unlink($tempFile);
                    }
                }

                throw new 
XenForo_Exception(new XenForo_Phrase('your_avatar_file_size_large_smaller_x', array(
                    
'size' => XenForo_Locale::numberFormat($maxFileSize, 'size')
                )), 
true);
            }
        }

        
$crop = array(
            
'x' => array('m' => 0),
            
'y' => array('m' => 0),
        );

        while (list(
$sizeCode, $maxDimensions) = each(self::$_sizes))
        {
            
$newTempFile = tempnam(XenForo_Helper_File::getTempDir(), 'xf');
            
$image = XenForo_Image_Abstract::createFromFile($fileName, $imageType);
            if (!
$image)
            {
                continue;
            }

            
$image->thumbnailFixedShorterSide($maxDimensions);

            if (
$image->getOrientation() != XenForo_Image_Abstract::ORIENTATION_SQUARE)
            {
                
$crop['x'][$sizeCode] = floor(($image->getWidth() - $maxDimensions) / 2);
                
$crop['y'][$sizeCode] = floor(($image->getHeight() - $maxDimensions) / 2);
                
$image->crop($crop['x'][$sizeCode], $crop['y'][$sizeCode], $maxDimensions, $maxDimensions);
            }

            
$image->output($outputType, $newTempFile, self::$imageQuality);
            unset(
$image);

            
$outputFiles[$sizeCode] = $newTempFile;
        }

        if (
count($outputFiles) != count(self::$_sizes))
        {
            foreach (
$outputFiles AS $tempFile)
            {
                if (
$tempFile != $fileName)
                {
                    @
unlink($tempFile);
                }
            }
            throw new 
XenForo_Exception(new XenForo_Phrase('image_could_be_processed_try_another_contact_owner'), true);
        }

        
// done in 2 loops as multiple items may point to same file
        
foreach ($outputFiles AS $sizeCode => $tempFile)
        {
            
$this->_writeAvatar($userId, $sizeCode, $tempFile);
        }
        foreach (
$outputFiles AS $tempFile)
        {
            if (
$tempFile != $fileName)
            {
                @
unlink($tempFile);
            }
        }

        
$dwData = array(
            
'avatar_date' => XenForo_Application::$time,
            
'avatar_width' => $width,
            
'avatar_height' => $height,
            
'avatar_crop_x' => $crop['x']['m'],
            
'avatar_crop_y' => $crop['y']['m'],
            
'gravatar' => '',
        );

        
$dw = XenForo_DataWriter::create('XenForo_DataWriter_User');
        
$dw->setExistingData($userId);
        
$dw->bulkSet($dwData);
        
$dw->save();

        return 
$dwData;
    }

    
/**
     * Re-crops an existing avatar with a square, starting at the specified coordinates
     *
     * @param integer $userId
     * @param integer $x
     * @param integer $y
     *
     * @return array Changed avatar fields
     */
    
public function recropAvatar($userId, $x, $y)
    {
        
$sizeList = self::$_sizes;

        
// get rid of the first entry in the sizes array
        
list($largeSizeCode, $largeMaxDimensions) = each($sizeList);

        
$outputFiles = array();

        
$avatarFile = $this->getAvatarFilePath($userId, $largeSizeCode);
        
$imageInfo = getimagesize($avatarFile);
        if (!
$imageInfo)
        {
            throw new 
XenForo_Exception('Non-image passed in to recropAvatar');
        }
        
$imageType = $imageInfo[2];

        
// now loop through the rest
        
while (list($sizeCode, $maxDimensions) = each($sizeList))
        {
            
$image = XenForo_Image_Abstract::createFromFile($avatarFile, $imageType);
            
$image->thumbnailFixedShorterSide($maxDimensions);

            if (
$image->getOrientation() != XenForo_Image_Abstract::ORIENTATION_SQUARE)
            {
                
$ratio = $maxDimensions / $sizeList['m'];

                
$xCrop = floor($ratio * $x);
                
$yCrop = floor($ratio * $y);

                if (
$image->getWidth() > $maxDimensions && $image->getWidth() - $xCrop < $maxDimensions)
                {
                    
$xCrop = $image->getWidth() - $maxDimensions;
                }
                if (
$image->getHeight() > $maxDimensions && $image->getHeight() - $yCrop < $maxDimensions)
                {
                    
$yCrop = $image->getHeight() - $maxDimensions;
                }

                
$image->crop($xCrop, $yCrop, $maxDimensions, $maxDimensions);
            }

            
$newTempFile = tempnam(XenForo_Helper_File::getTempDir(), 'xf');

            
$image->output($imageType, $newTempFile, self::$imageQuality);
            unset(
$image);

            
$outputFiles[$sizeCode] = $newTempFile;
        }

        foreach (
$outputFiles AS $sizeCode => $tempFile)
        {
            
$this->_writeAvatar($userId, $sizeCode, $tempFile);
        }
        foreach (
$outputFiles AS $tempFile)
        {
            @
unlink($tempFile);
        }

        
$dwData = array(
            
'avatar_date' => XenForo_Application::$time,
            
'avatar_crop_x' => $x,
            
'avatar_crop_y' => $y,
            
'gravatar' => '',
        );

        
$dw = XenForo_DataWriter::create('XenForo_DataWriter_User');
        
$dw->setExistingData($userId);
        
$dw->bulkSet($dwData);
        
$dw->save();

        return 
$dwData;
    }

    
/**
     * Writes out an avatar.
     *
     * @param integer $userId
     * @param string $size Size code
     * @param string $tempFile Temporary avatar file. Will be moved.
     *
     * @return boolean
     */
    
protected function _writeAvatar($userId, $size, $tempFile)
    {
        if (!
in_array($size, array_keys(self::$_sizes)))
        {
            throw new 
XenForo_Exception('Invalid avatar size.');
        }

        
$filePath = $this->getAvatarFilePath($userId, $size);
        
$directory = dirname($filePath);

        if (
XenForo_Helper_File::createDirectory($directory, true) && is_writable($directory))
        {
            if (
file_exists($filePath))
            {
                @
unlink($filePath);
            }

            return 
XenForo_Helper_File::safeRename($tempFile, $filePath);
        }
        else
        {
            return 
false;
        }
    }

    
/**
     * Get the file path to an avatar.
     *
     * @param integer $userId
     * @param string $size Size code
     * @param string External data directory path (optional)
     *
     * @return string
     */
    
public function getAvatarFilePath($userId, $size, $externalDataPath = null)
    {
        if (
$externalDataPath === null)
        {
            
$externalDataPath = XenForo_Helper_File::getExternalDataPath();
        }
        
        return 
sprintf('%s/avatars/%s/%d/%d.jpg',
            
$externalDataPath,
            
$size,
            
floor($userId / 1000),
            
$userId
        
);
    }

    
/**
     * Deletes a user's avatar.
     *
     * @param integer $userId
     * @param boolean $updateUser
     *
     * @return array Changed avatar fields
     */
    
public function deleteAvatar($userId, $updateUser = true)
    {
        foreach (
array_keys(self::$_sizes) AS $size)
        {
            
$filePath = $this->getAvatarFilePath($userId, $size);
            if (
file_exists($filePath) && is_writable($filePath))
            {
                @
unlink($filePath);
            }
        }

        
$dwData = array(
            
'avatar_date' => 0,
            
'avatar_width' => 0,
            
'avatar_height' => 0,
            
'avatar_crop_x' => 0,
            
'avatar_crop_y' => 0,
            
'gravatar' => '',
        );

        if (
$updateUser)
        {
            
$dw = XenForo_DataWriter::create('XenForo_DataWriter_User', XenForo_DataWriter::ERROR_SILENT);
            
$dw->setExistingData($userId);
            
$dw->bulkSet($dwData);
            
$dw->save();
        }

        return 
$dwData;
    }

    
/**
     * Returns the _sizes array, defining what avatar sizes are available.
     *
     * @return array
     */
    
public static function getSizes()
    {
        return 
self::$_sizes;
    }

    
/**
     * Returns the maximum size (in pixels) of an avatar corresponding to the size code specified
     *
     * @param string $sizeCode (s,m,l)
     *
     * @return integer
     */
    
public static function getSizeFromCode($sizeCode)
    {
        return 
self::$_sizes[strtolower($sizeCode)];
    }

    
/**
     * Checks whether a Gravatar exists for a given email address
     *
     * @param string $email
     *
     * @return string|boolean Gravatar URL on success
     */
    
public static function gravatarExists($email, &$errorText = '', $size = 1, &$gravatarUrl = '')
    {
        if (!
XenForo_Helper_Email::isEmailValid($email))
        {
            
$errorText = new XenForo_Phrase('gravatars_require_valid_email_addresses');
            return 
false;
        }

        try
        {
            
$client = XenForo_Helper_Http::getClient(self::_getGravatarUrl($email, 1, 404), array(
                
'maxredirects' => 0,
                
'timeout' => 5
            
));

            if (
$client->request('HEAD')->getStatus() !== 200)
            {
                
$errorText = new XenForo_Phrase('no_gravatar_found_for_specified_email_address');
                return 
false;
            }
        }
        catch (
Exception $e)
        {
            if (
strpos($e->getMessage(), 'Read timed out') === false)
            {
                
// don't log timeouts - they're most likely on Gravatar's side
                
XenForo_Error::logException($e, false);
            }
            
$errorText = new XenForo_Phrase('there_was_problem_communicating_with_gravatar');
            return 
false;
        }

        
$gravatarUrl = self::_getGravatarUrl($email, $size, false);
        return 
true;
    }

    
/**
     * Builds a basic Gravatar URL for the given parameters

     * @param string $email
     * @param integer $size
     * @param mixed $default
     *
     * @return string
     */
    
public static function _getGravatarUrl($email, $size, $default = false)
    {
        
$md5 = md5(strtolower(trim($email)));

        if (!empty(
$default))
        {
            
$default = '&d=' . urlencode($default);
        }

        return (
XenForo_Application::$secure ? 'https://secure' : 'http://www')
            . 
".gravatar.com/avatar/{$md5}?s={$size}{$default}";
    }
}
Онлайн: 1
Реклама