]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - actions/avatarsettings.php
Merge branch '0.7.x' of git@gitorious.org:laconica/dev into 0.7.x
[quix0rs-gnu-social.git] / actions / avatarsettings.php
1 <?php
2 /**
3  * Laconica, the distributed open-source microblogging tool
4  *
5  * Upload an avatar
6  *
7  * PHP version 5
8  *
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.
13  *
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.
18  *
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/>.
21  *
22  * @category  Settings
23  * @package   Laconica
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/
29  */
30
31 if (!defined('LACONICA')) {
32     exit(1);
33 }
34
35 require_once INSTALLDIR.'/lib/accountsettingsaction.php';
36
37 /**
38  * Upload an avatar
39  *
40  * We use jCrop plugin for jQuery to crop the image after upload.
41  *
42  * @category Settings
43  * @package  Laconica
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/
49  */
50
51 class AvatarsettingsAction extends AccountSettingsAction
52 {
53     var $mode = null;
54     var $imagefile = null;
55     var $filename = null;
56
57     /**
58      * Title of the page
59      *
60      * @return string Title of the page
61      */
62
63     function title()
64     {
65         return _('Avatar');
66     }
67
68     /**
69      * Instructions for use
70      *
71      * @return instructions for use
72      */
73
74     function getInstructions()
75     {
76         return _('You can upload your personal avatar.');
77     }
78
79     /**
80      * Content area of the page
81      *
82      * Shows a form for uploading an avatar.
83      *
84      * @return void
85      */
86
87     function showContent()
88     {
89         if ($this->mode == 'crop') {
90             $this->showCropForm();
91         } else {
92             $this->showUploadForm();
93         }
94     }
95
96     function showUploadForm()
97     {
98         $user = common_current_user();
99
100         $profile = $user->getProfile();
101
102         if (!$profile) {
103             common_log_db_error($user, 'SELECT', __FILE__);
104             $this->serverError(_('User without matching profile'));
105             return;
106         }
107
108         $original = $profile->getOriginalAvatar();
109
110         $this->elementStart('form', array('enctype' => 'multipart/form-data',
111                                           'method' => 'post',
112                                           'id' => 'form_settings_avatar',
113                                           'class' => 'form_settings',
114                                           'action' =>
115                                           common_local_url('avatarsettings')));
116         $this->elementStart('fieldset');
117         $this->element('legend', null, _('Avatar settings'));
118         $this->hidden('token', common_session_token());
119
120         $this->elementStart('ul', 'form_data');
121         if ($original) {
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');
132         }
133
134         $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
135
136         if ($avatar) {
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');
147         }
148
149         $this->elementStart('li', array ('id' => 'settings_attach'));
150         $this->element('input', array('name' => 'avatarfile',
151                                       'type' => 'file',
152                                       'id' => 'avatarfile'));
153         $this->element('input', array('name' => 'MAX_FILE_SIZE',
154                                       'type' => 'hidden',
155                                       'id' => 'MAX_FILE_SIZE',
156                                       'value' => MAX_AVATAR_SIZE));
157         $this->elementEnd('li');
158         $this->elementEnd('ul');
159
160         $this->elementStart('ul', 'form_actions');
161         $this->elementStart('li');
162         $this->submit('upload', _('Upload'));
163         $this->elementEnd('li');
164         $this->elementEnd('ul');
165
166         $this->elementEnd('fieldset');
167         $this->elementEnd('form');
168
169     }
170
171     function showCropForm()
172     {
173         $user = common_current_user();
174
175         $profile = $user->getProfile();
176
177         if (!$profile) {
178             common_log_db_error($user, 'SELECT', __FILE__);
179             $this->serverError(_('User without matching profile'));
180             return;
181         }
182
183         $original = $profile->getOriginalAvatar();
184
185         $this->elementStart('form', array('method' => 'post',
186                                           'id' => 'form_settings_avatar',
187                                           'class' => 'form_settings',
188                                           'action' =>
189                                           common_local_url('avatarsettings')));
190         $this->elementStart('fieldset');
191         $this->element('legend', null, _('Avatar settings'));
192         $this->hidden('token', common_session_token());
193
194         $this->elementStart('ul', 'form_data');
195
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');
207
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');
218
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,
222                                           'type' => 'hidden',
223                                           'id' => $crop_info));
224         }
225         $this->submit('crop', _('Crop'));
226
227         $this->elementEnd('li');
228         $this->elementEnd('ul');
229         $this->elementEnd('fieldset');
230         $this->elementEnd('form');
231
232     }
233
234     /**
235      * Handle a post
236      *
237      * We mux on the button name to figure out what the user actually wanted.
238      *
239      * @return void
240      */
241
242     function handlePost()
243     {
244         // CSRF protection
245
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.'));
250             return;
251         }
252
253         if ($this->arg('upload')) {
254             $this->uploadAvatar();
255         } else if ($this->arg('crop')) {
256             $this->cropAvatar();
257         } else {
258             $this->showForm(_('Unexpected form submission.'));
259         }
260     }
261
262     /**
263      * Handle an image upload
264      *
265      * Does all the magic for handling an image upload, and crops the
266      * image by default.
267      *
268      * @return void
269      */
270
271     function uploadAvatar()
272     {
273         try {
274             $imagefile = ImageFile::fromUpload('avatarfile');
275         } catch (Exception $e) {
276             $this->showForm($e->getMessage());
277             return;
278         }
279
280         $cur = common_current_user();
281
282         $filename = common_avatar_filename($cur->id,
283                                            image_type_to_extension($imagefile->type),
284                                            null,
285                                            'tmp'.common_timestamp());
286
287         $filepath = common_avatar_path($filename);
288
289         move_uploaded_file($imagefile->filename, $filepath);
290
291         $filedata = array('filename' => $filename,
292                           'filepath' => $filepath,
293                           'width' => $imagefile->width,
294                           'height' => $imagefile->height,
295                           'type' => $imagefile->type);
296
297         $_SESSION['FILEDATA'] = $filedata;
298
299         $this->filedata = $filedata;
300
301         $this->mode = 'crop';
302
303         $this->showForm(_('Pick a square area of the image to be your avatar'),
304                         true);
305     }
306
307     /**
308      * Handle the results of jcrop.
309      *
310      * @return void
311      */
312
313     function cropAvatar()
314     {
315         $user = common_current_user();
316
317         $profile = $user->getProfile();
318
319         $filedata = $_SESSION['FILEDATA'];
320
321         if (!$filedata) {
322             $this->serverError(_('Lost our file data.'));
323             return;
324         }
325
326         $x = $this->arg('avatar_crop_x');
327         $y = $this->arg('avatar_crop_y');
328         $w = ($this->arg('avatar_crop_w')) ? $this->arg('avatar_crop_w') : $filedata['width'];
329         $h = ($this->arg('avatar_crop_h')) ? $this->arg('avatar_crop_h') : $filedata['height'];
330
331         $filepath = common_avatar_path($filedata['filename']);
332
333         if (!file_exists($filepath)) {
334             $this->serverError(_('Lost our file.'));
335             return;
336         }
337
338         switch ($filedata['type']) {
339         case IMAGETYPE_GIF:
340             $image_src = imagecreatefromgif($filepath);
341             break;
342         case IMAGETYPE_JPEG:
343             $image_src = imagecreatefromjpeg($filepath);
344             break;
345         case IMAGETYPE_PNG:
346             $image_src = imagecreatefrompng($filepath);
347             break;
348          default:
349             $this->serverError(_('Unknown file type'));
350             return;
351         }
352
353         common_debug("W = $w, H = $h, X = $x, Y = $y");
354
355         $image_dest = imagecreatetruecolor($w, $h);
356
357         $background = imagecolorallocate($image_dest, 0, 0, 0);
358         ImageColorTransparent($image_dest, $background);
359         imagealphablending($image_dest, false);
360
361         imagecopyresized($image_dest, $image_src, 0, 0, $x, $y, $w, $h, $w, $h);
362
363         $cur = common_current_user();
364
365         $filename = common_avatar_filename($cur->id,
366                                            image_type_to_extension($filedata['type']),
367                                            null,
368                                            common_timestamp());
369
370         $filepath = common_avatar_path($filename);
371
372         switch ($filedata['type']) {
373         case IMAGETYPE_GIF:
374             imagegif($image_dest, $filepath);
375             break;
376         case IMAGETYPE_JPEG:
377             imagejpeg($image_dest, $filepath);
378             break;
379         case IMAGETYPE_PNG:
380             imagepng($image_dest, $filepath);
381             break;
382          default:
383             $this->serverError(_('Unknown file type'));
384             return;
385         }
386
387         $user = common_current_user();
388
389         $profile = $cur->getProfile();
390
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);
396         } else {
397             $this->showForm(_('Failed updating avatar.'));
398         }
399     }
400
401     /**
402      * Add the jCrop stylesheet
403      *
404      * @return void
405      */
406
407     function showStylesheets()
408     {
409         parent::showStylesheets();
410         $jcropStyle =
411           common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION);
412
413         $this->element('link', array('rel' => 'stylesheet',
414                                      'type' => 'text/css',
415                                      'href' => $jcropStyle,
416                                      'media' => 'screen, projection, tv'));
417     }
418
419     /**
420      * Add the jCrop scripts
421      *
422      * @return void
423      */
424
425     function showScripts()
426     {
427         parent::showScripts();
428
429         $jcropPack = common_path('js/jcrop/jquery.Jcrop.pack.js');
430         $jcropGo   = common_path('js/jcrop/jquery.Jcrop.go.js');
431
432         $this->element('script', array('type' => 'text/javascript',
433                                        'src' => $jcropPack));
434         $this->element('script', array('type' => 'text/javascript',
435                                        'src' => $jcropGo));
436     }
437 }