We are no longer offering accounts on this server. Consider https://gitlab.freedesktop.org/ as a place to host projects.

Avatar.php 9.3 KB
Newer Older
Evan Prodromou's avatar
Evan Prodromou committed
1 2 3 4
<?php
/**
 * Table Definition for avatar
 */
5
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
Evan Prodromou's avatar
Evan Prodromou committed
6

7
class Avatar extends Managed_DataObject
Evan Prodromou's avatar
Evan Prodromou committed
8 9 10 11 12 13
{
    ###START_AUTOCODE
    /* the code below is auto generated do not remove the above tag */

    public $__table = 'avatar';                          // table name
    public $profile_id;                      // int(4)  primary_key not_null
14
    public $original;                        // tinyint(1)
Evan Prodromou's avatar
Evan Prodromou committed
15 16 17
    public $width;                           // int(4)  primary_key not_null
    public $height;                          // int(4)  primary_key not_null
    public $mediatype;                       // varchar(32)   not_null
18 19
    public $filename;                        // varchar(191)   not 255 because utf8mb4 takes more space
    public $url;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
Evan Prodromou's avatar
Evan Prodromou committed
20 21
    public $created;                         // datetime()   not_null
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
Evan Prodromou's avatar
Evan Prodromou committed
22 23 24

    /* the code above is auto generated do not remove the tag below */
    ###END_AUTOCODE
25
	
26 27 28 29 30 31 32 33 34
    public static function schemaDef()
    {
        return array(
            'fields' => array(
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
                'original' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'uploaded by user or generated?'),
                'width' => array('type' => 'int', 'not null' => true, 'description' => 'image width'),
                'height' => array('type' => 'int', 'not null' => true, 'description' => 'image height'),
                'mediatype' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'file type'),
35
                'filename' => array('type' => 'varchar', 'length' => 191, 'description' => 'local filename, if local'),
36
                'url' => array('type' => 'text', 'description' => 'avatar location, not indexed - do not use in WHERE statement'),
37 38 39 40 41
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
            ),
            'primary key' => array('profile_id', 'width', 'height'),
            'unique keys' => array(
42
//                'avatar_filename_key' => array('filename'),
43 44 45 46 47 48 49 50 51
            ),
            'foreign keys' => array(
                'avatar_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
            ),
            'indexes' => array(
                'avatar_profile_id_idx' => array('profile_id'),
            ),
        );
    }
52

53
    // We clean up the file, too
54
    function delete($useWhere=false)
55
    {
56
        $filename = $this->filename;
57
        if (file_exists(Avatar::path($filename))) {
58
            @unlink(Avatar::path($filename));
59
        }
60 61

        return parent::delete($useWhere);
62
    }
63

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    /*
     * Deletes all avatars (but may spare the original) from a profile.
     * 
     * @param   Profile $target     The profile we're deleting avatars of.
     * @param   boolean $original   Whether original should be removed or not.
     */
    public static function deleteFromProfile(Profile $target, $original=true) {
        try {
            $avatars = self::getProfileAvatars($target);
            foreach ($avatars as $avatar) {
                if ($avatar->original && !$original) {
                    continue;
                }
                $avatar->delete();
            }
79
        } catch (NoAvatarException $e) {
80
            // There are no avatars to delete, a sort of success.
81
        }
82 83

        return true;
84 85
    }

86 87 88 89 90 91 92
    static protected $_avatars = array();

    /*
     * Get an avatar by profile. Currently can't call newSize with $height
     */
    public static function byProfile(Profile $target, $width=null, $height=null)
    {
93 94
        $width  = intval($width);
        $height = !is_null($height) ? intval($height) : null;
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
        if (is_null($height)) {
            $height = $width;
        }

        $size = "{$width}x{$height}";
        if (!isset(self::$_avatars[$target->id])) {
            self::$_avatars[$target->id] = array();
        } elseif (isset(self::$_avatars[$target->id][$size])){
            return self::$_avatars[$target->id][$size];
        }

        $avatar = null;
        if (Event::handle('StartProfileGetAvatar', array($target, $width, &$avatar))) {
            $avatar = self::pkeyGet(
                array(
                    'profile_id' => $target->id,
                    'width'      => $width,
                    'height'     => $height,
                )
            );
            Event::handle('EndProfileGetAvatar', array($target, $width, &$avatar));
        }

        if (is_null($avatar)) {
            // Obviously we can't find an avatar, so let's resize the original!
            $avatar = Avatar::newSize($target, $width);
        } elseif (!($avatar instanceof Avatar)) {
            throw new NoAvatarException($target, $avatar);
        }

        self::$_avatars[$target->id]["{$avatar->width}x{$avatar->height}"] = $avatar;
        return $avatar;
    }

129
    public static function getUploaded(Profile $target)
130 131 132 133 134
    {
        $avatar = new Avatar();
        $avatar->profile_id = $target->id;
        $avatar->original = true;
        if (!$avatar->find(true)) {
135
            throw new NoAvatarException($target, $avatar);
136
        }
137 138 139 140
        if (!file_exists(Avatar::path($avatar->filename))) {
            // The delete call may be odd for, say, unmounted filesystems
            // that cause a file to currently not exist, but actually it does...
            $avatar->delete();
141
            throw new NoAvatarException($target, $avatar);
142
        }
143
        return $avatar;
144 145
    }

146 147 148
    public static function getProfileAvatars(Profile $target) {
        $avatar = new Avatar();
        $avatar->profile_id = $target->id;
149
        if (!$avatar->find()) {
150
            throw new NoAvatarException($target, $avatar);
151
        }
152 153 154
        return $avatar->fetchAll();
    }

155 156 157
    /**
     * Where should the avatar go for this user?
     */
158 159 160 161 162 163 164 165 166 167 168
    static function filename($id, $extension, $size=null, $extra=null)
    {
        if ($size) {
            return $id . '-' . $size . (($extra) ? ('-' . $extra) : '') . $extension;
        } else {
            return $id . '-original' . (($extra) ? ('-' . $extra) : '') . $extension;
        }
    }

    static function path($filename)
    {
Evan Prodromou's avatar
Evan Prodromou committed
169 170 171 172 173 174 175
        $dir = common_config('avatar', 'dir');

        if ($dir[strlen($dir)-1] != '/') {
            $dir .= '/';
        }

        return $dir . $filename;
176 177 178 179
    }

    static function url($filename)
    {
Evan Prodromou's avatar
Evan Prodromou committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
        $path = common_config('avatar', 'path');

        if ($path[strlen($path)-1] != '/') {
            $path .= '/';
        }

        if ($path[0] != '/') {
            $path = '/'.$path;
        }

        $server = common_config('avatar', 'server');

        if (empty($server)) {
            $server = common_config('site', 'server');
        }
Zach Copley's avatar
Zach Copley committed
195

196 197 198 199 200 201 202 203 204 205 206 207
        $ssl = common_config('avatar', 'ssl');

        if (is_null($ssl)) { // null -> guess
            if (common_config('site', 'ssl') == 'always' &&
                !common_config('avatar', 'server')) {
                $ssl = true;
            } else {
                $ssl = false;
            }
        }

        $protocol = ($ssl) ? 'https' : 'http';
Evan Prodromou's avatar
Evan Prodromou committed
208

209
        return $protocol.'://'.$server.$path.$filename;
210 211 212 213 214
    }

    function displayUrl()
    {
        $server = common_config('avatar', 'server');
215
        if ($server && !empty($this->filename)) {
Evan Prodromou's avatar
Evan Prodromou committed
216
            return Avatar::url($this->filename);
217 218 219 220 221
        } else {
            return $this->url;
        }
    }

222 223 224 225 226 227 228 229
    static function urlByProfile(Profile $target, $width=null, $height=null) {
        try {
            return self::byProfile($target,  $width, $height)->displayUrl();
        } catch (Exception $e) {
            return self::defaultImage($width);
        }
    }

Evan Prodromou's avatar
Evan Prodromou committed
230
    static function defaultImage($size)
231 232 233 234
    {
        static $sizenames = array(AVATAR_PROFILE_SIZE => 'profile',
                                  AVATAR_STREAM_SIZE => 'stream',
                                  AVATAR_MINI_SIZE => 'mini');
235
        return Theme::path('default-avatar-'.$sizenames[$size].'.png');
236
    }
237

238
    static function newSize(Profile $target, $width) {
239
        $width = intval($width);
240
        if ($width < 1 || $width > common_config('avatar', 'maxsize')) {
241
            // TRANS: An error message when avatar size is unreasonable
242
            throw new Exception(_m('Avatar size too large'));
243 244
        }

245
        $original = Avatar::getUploaded($target);
246

247
        $imagefile = new ImageFile(null, Avatar::path($original->filename));
248
        $filename = $imagefile->resize($width);
249 250 251

        $scaled = clone($original);
        $scaled->original = false;
252 253
        $scaled->width = $width;
        $scaled->height = $width;
254
        $scaled->url = Avatar::url($filename);
255 256
        $scaled->filename = $filename;
        $scaled->created = common_sql_now();
257 258 259 260 261 262 263 264 265

        if (!$scaled->insert()) {
            // TRANS: An error message when unable to insert avatar data into the db
            throw new Exception(_m('Could not insert new avatar data to database'));
        }

        // Return the new avatar object
        return $scaled;
    }
Evan Prodromou's avatar
Evan Prodromou committed
266
}