3 * Laconica, the distributed open-source microblogging tool
9 * LICENCE: This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * @author Evan Prodromou <evan@controlyourself.ca>
25 * @author Zach Copley <zach@controlyourself.ca>
26 * @copyright 2008-2009 Control Yourself, Inc.
27 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
28 * @link http://laconi.ca/
31 if (!defined('LACONICA')) {
35 require_once INSTALLDIR.'/lib/accountsettingsaction.php';
40 * We use jCrop plugin for jQuery to crop the image after upload.
44 * @author Evan Prodromou <evan@controlyourself.ca>
45 * @author Zach Copley <zach@controlyourself.ca>
46 * @author Sarven Capadisli <csarven@controlyourself.ca>
47 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
48 * @link http://laconi.ca/
51 class AvatarsettingsAction extends AccountSettingsAction
54 var $imagefile = null;
60 * @return string Title of the page
69 * Instructions for use
71 * @return instructions for use
74 function getInstructions()
76 return _('You can upload your personal avatar.');
80 * Content area of the page
82 * Shows a form for uploading an avatar.
87 function showContent()
89 if ($this->mode == 'crop') {
90 $this->showCropForm();
92 $this->showUploadForm();
96 function showUploadForm()
98 $user = common_current_user();
100 $profile = $user->getProfile();
103 common_log_db_error($user, 'SELECT', __FILE__);
104 $this->serverError(_('User without matching profile'));
108 $original = $profile->getOriginalAvatar();
110 $this->elementStart('form', array('enctype' => 'multipart/form-data',
112 'id' => 'form_settings_avatar',
113 'class' => 'form_settings',
115 common_local_url('avatarsettings')));
116 $this->elementStart('fieldset');
117 $this->element('legend', null, _('Avatar settings'));
118 $this->hidden('token', common_session_token());
120 $this->elementStart('ul', 'form_data');
122 $this->elementStart('li', array('id' => 'avatar_original',
123 'class' => 'avatar_view'));
124 $this->element('h2', null, _("Original"));
125 $this->elementStart('div', array('id'=>'avatar_original_view'));
126 $this->element('img', array('src' => $original->url,
127 'width' => $original->width,
128 'height' => $original->height,
129 'alt' => $user->nickname));
130 $this->elementEnd('div');
131 $this->elementEnd('li');
134 $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
137 $this->elementStart('li', array('id' => 'avatar_preview',
138 'class' => 'avatar_view'));
139 $this->element('h2', null, _("Preview"));
140 $this->elementStart('div', array('id'=>'avatar_preview_view'));
141 $this->element('img', array('src' => $original->url,
142 'width' => AVATAR_PROFILE_SIZE,
143 'height' => AVATAR_PROFILE_SIZE,
144 'alt' => $user->nickname));
145 $this->elementEnd('div');
146 $this->elementEnd('li');
149 $this->elementStart('li', array ('id' => 'settings_attach'));
150 $this->element('input', array('name' => 'avatarfile',
152 'id' => 'avatarfile'));
153 $this->element('input', array('name' => 'MAX_FILE_SIZE',
155 'id' => 'MAX_FILE_SIZE',
156 'value' => MAX_AVATAR_SIZE));
157 $this->elementEnd('li');
158 $this->elementEnd('ul');
160 $this->elementStart('ul', 'form_actions');
161 $this->elementStart('li');
162 $this->submit('upload', _('Upload'));
163 $this->elementEnd('li');
164 $this->elementEnd('ul');
166 $this->elementEnd('fieldset');
167 $this->elementEnd('form');
171 function showCropForm()
173 $user = common_current_user();
175 $profile = $user->getProfile();
178 common_log_db_error($user, 'SELECT', __FILE__);
179 $this->serverError(_('User without matching profile'));
183 $original = $profile->getOriginalAvatar();
185 $this->elementStart('form', array('method' => 'post',
186 'id' => 'form_settings_avatar',
187 'class' => 'form_settings',
189 common_local_url('avatarsettings')));
190 $this->elementStart('fieldset');
191 $this->element('legend', null, _('Avatar settings'));
192 $this->hidden('token', common_session_token());
194 $this->elementStart('ul', 'form_data');
196 $this->elementStart('li',
197 array('id' => 'avatar_original',
198 'class' => 'avatar_view'));
199 $this->element('h2', null, _("Original"));
200 $this->elementStart('div', array('id'=>'avatar_original_view'));
201 $this->element('img', array('src' => common_avatar_url($this->filedata['filename']),
202 'width' => $this->filedata['width'],
203 'height' => $this->filedata['height'],
204 'alt' => $user->nickname));
205 $this->elementEnd('div');
206 $this->elementEnd('li');
208 $this->elementStart('li',
209 array('id' => 'avatar_preview',
210 'class' => 'avatar_view'));
211 $this->element('h2', null, _("Preview"));
212 $this->elementStart('div', array('id'=>'avatar_preview_view'));
213 $this->element('img', array('src' => common_avatar_url($this->filedata['filename']),
214 'width' => AVATAR_PROFILE_SIZE,
215 'height' => AVATAR_PROFILE_SIZE,
216 'alt' => $user->nickname));
217 $this->elementEnd('div');
219 foreach (array('avatar_crop_x', 'avatar_crop_y',
220 'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
221 $this->element('input', array('name' => $crop_info,
223 'id' => $crop_info));
225 $this->submit('crop', _('Crop'));
227 $this->elementEnd('li');
228 $this->elementEnd('ul');
229 $this->elementEnd('fieldset');
230 $this->elementEnd('form');
237 * We mux on the button name to figure out what the user actually wanted.
242 function handlePost()
246 $token = $this->trimmed('token');
247 if (!$token || $token != common_session_token()) {
248 $this->show_form(_('There was a problem with your session token. '.
249 'Try again, please.'));
253 if ($this->arg('upload')) {
254 $this->uploadAvatar();
255 } else if ($this->arg('crop')) {
258 $this->showForm(_('Unexpected form submission.'));
263 * Handle an image upload
265 * Does all the magic for handling an image upload, and crops the
271 function uploadAvatar()
274 $imagefile = ImageFile::fromUpload('avatarfile');
275 } catch (Exception $e) {
276 $this->showForm($e->getMessage());
280 $cur = common_current_user();
282 $filename = common_avatar_filename($cur->id,
283 image_type_to_extension($imagefile->type),
285 'tmp'.common_timestamp());
287 $filepath = common_avatar_path($filename);
289 move_uploaded_file($imagefile->filename, $filepath);
291 $filedata = array('filename' => $filename,
292 'filepath' => $filepath,
293 'width' => $imagefile->width,
294 'height' => $imagefile->height,
295 'type' => $imagefile->type);
297 $_SESSION['FILEDATA'] = $filedata;
299 $this->filedata = $filedata;
301 $this->mode = 'crop';
303 $this->showForm(_('Pick a square area of the image to be your avatar'),
308 * Handle the results of jcrop.
313 function cropAvatar()
315 $user = common_current_user();
317 $profile = $user->getProfile();
319 $x = $this->arg('avatar_crop_x');
320 $y = $this->arg('avatar_crop_y');
321 $w = $this->arg('avatar_crop_w');
322 $h = $this->arg('avatar_crop_h');
324 $filedata = $_SESSION['FILEDATA'];
327 $this->serverError(_('Lost our file data.'));
331 $filepath = common_avatar_path($filedata['filename']);
333 if (!file_exists($filepath)) {
334 $this->serverError(_('Lost our file.'));
338 switch ($filedata['type']) {
340 $image_src = imagecreatefromgif($filepath);
343 $image_src = imagecreatefromjpeg($filepath);
346 $image_src = imagecreatefrompng($filepath);
349 $this->serverError(_('Unknown file type'));
353 common_debug("W = $w, H = $h, X = $x, Y = $y");
355 $image_dest = imagecreatetruecolor($w, $h);
357 $background = imagecolorallocate($image_dest, 0, 0, 0);
358 ImageColorTransparent($image_dest, $background);
359 imagealphablending($image_dest, false);
361 imagecopyresized($image_dest, $image_src, 0, 0, $x, $y, $w, $h, $w, $h);
363 $cur = common_current_user();
365 $filename = common_avatar_filename($cur->id,
366 image_type_to_extension($filedata['type']),
370 $filepath = common_avatar_path($filename);
372 switch ($filedata['type']) {
374 imagegif($image_dest, $filepath);
377 imagejpeg($image_dest, $filepath);
380 imagepng($image_dest, $filepath);
383 $this->serverError(_('Unknown file type'));
387 $user = common_current_user();
389 $profile = $cur->getProfile();
391 if ($profile->setOriginal($filepath)) {
392 @unlink(common_avatar_path($filedata['filename']));
393 unset($_SESSION['FILEDATA']);
394 $this->mode = 'upload';
395 $this->showForm(_('Avatar updated.'), true);
397 $this->showForm(_('Failed updating avatar.'));
402 * Add the jCrop stylesheet
407 function showStylesheets()
409 parent::showStylesheets();
411 common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION);
413 $this->element('link', array('rel' => 'stylesheet',
414 'type' => 'text/css',
415 'href' => $jcropStyle,
416 'media' => 'screen, projection, tv'));
420 * Add the jCrop scripts
425 function showScripts()
427 parent::showScripts();
429 $jcropPack = common_path('js/jcrop/jquery.Jcrop.pack.js');
430 $jcropGo = common_path('js/jcrop/jquery.Jcrop.go.js');
432 $this->element('script', array('type' => 'text/javascript',
433 'src' => $jcropPack));
434 $this->element('script', array('type' => 'text/javascript',