]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - actions/avatarsettings.php
change Laconica and Control Yourself to StatusNet in PHP files
[quix0rs-gnu-social.git] / actions / avatarsettings.php
1 <?php
2 /**
3  * StatusNet, 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   StatusNet
24  * @author    Evan Prodromou <evan@controlyourself.ca>
25  * @author    Zach Copley <zach@controlyourself.ca>
26  * @copyright 2008-2009 StatusNet, 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 define('MAX_ORIGINAL', 480);
38
39 /**
40  * Upload an avatar
41  *
42  * We use jCrop plugin for jQuery to crop the image after upload.
43  *
44  * @category Settings
45  * @package  StatusNet
46  * @author   Evan Prodromou <evan@controlyourself.ca>
47  * @author   Zach Copley <zach@controlyourself.ca>
48  * @author   Sarven Capadisli <csarven@controlyourself.ca>
49  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
50  * @link     http://laconi.ca/
51  */
52
53 class AvatarsettingsAction extends AccountSettingsAction
54 {
55     var $mode = null;
56     var $imagefile = null;
57     var $filename = null;
58
59     /**
60      * Title of the page
61      *
62      * @return string Title of the page
63      */
64
65     function title()
66     {
67         return _('Avatar');
68     }
69
70     /**
71      * Instructions for use
72      *
73      * @return instructions for use
74      */
75
76     function getInstructions()
77     {
78         return sprintf(_('You can upload your personal avatar. The maximum file size is %s.'), ImageFile::maxFileSize());
79     }
80
81     /**
82      * Content area of the page
83      *
84      * Shows a form for uploading an avatar.
85      *
86      * @return void
87      */
88
89     function showContent()
90     {
91         if ($this->mode == 'crop') {
92             $this->showCropForm();
93         } else {
94             $this->showUploadForm();
95         }
96     }
97
98     function showUploadForm()
99     {
100         $user = common_current_user();
101
102         $profile = $user->getProfile();
103
104         if (!$profile) {
105             common_log_db_error($user, 'SELECT', __FILE__);
106             $this->serverError(_('User without matching profile'));
107             return;
108         }
109
110         $original = $profile->getOriginalAvatar();
111
112         $this->elementStart('form', array('enctype' => 'multipart/form-data',
113                                           'method' => 'post',
114                                           'id' => 'form_settings_avatar',
115                                           'class' => 'form_settings',
116                                           'action' =>
117                                           common_local_url('avatarsettings')));
118         $this->elementStart('fieldset');
119         $this->element('legend', null, _('Avatar settings'));
120         $this->hidden('token', common_session_token());
121
122         $this->elementStart('ul', 'form_data');
123         if ($original) {
124             $this->elementStart('li', array('id' => 'avatar_original',
125                                             'class' => 'avatar_view'));
126             $this->element('h2', null, _("Original"));
127             $this->elementStart('div', array('id'=>'avatar_original_view'));
128             $this->element('img', array('src' => $original->url,
129                                         'width' => $original->width,
130                                         'height' => $original->height,
131                                         'alt' => $user->nickname));
132             $this->elementEnd('div');
133             $this->elementEnd('li');
134         }
135
136         $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
137
138         if ($avatar) {
139             $this->elementStart('li', array('id' => 'avatar_preview',
140                                             'class' => 'avatar_view'));
141             $this->element('h2', null, _("Preview"));
142             $this->elementStart('div', array('id'=>'avatar_preview_view'));
143             $this->element('img', array('src' => $original->url,
144                                         'width' => AVATAR_PROFILE_SIZE,
145                                         'height' => AVATAR_PROFILE_SIZE,
146                                         'alt' => $user->nickname));
147             $this->elementEnd('div');
148             $this->submit('delete', _('Delete'));
149             $this->elementEnd('li');
150         }
151
152         $this->elementStart('li', array ('id' => 'settings_attach'));
153         $this->element('input', array('name' => 'avatarfile',
154                                       'type' => 'file',
155                                       'id' => 'avatarfile'));
156         $this->element('input', array('name' => 'MAX_FILE_SIZE',
157                                       'type' => 'hidden',
158                                       'id' => 'MAX_FILE_SIZE',
159                                       'value' => ImageFile::maxFileSizeInt()));
160         $this->elementEnd('li');
161         $this->elementEnd('ul');
162
163         $this->elementStart('ul', 'form_actions');
164         $this->elementStart('li');
165         $this->submit('upload', _('Upload'));
166         $this->elementEnd('li');
167         $this->elementEnd('ul');
168
169         $this->elementEnd('fieldset');
170         $this->elementEnd('form');
171
172     }
173
174     function showCropForm()
175     {
176         $user = common_current_user();
177
178         $profile = $user->getProfile();
179
180         if (!$profile) {
181             common_log_db_error($user, 'SELECT', __FILE__);
182             $this->serverError(_('User without matching profile'));
183             return;
184         }
185
186         $original = $profile->getOriginalAvatar();
187
188         $this->elementStart('form', array('method' => 'post',
189                                           'id' => 'form_settings_avatar',
190                                           'class' => 'form_settings',
191                                           'action' =>
192                                           common_local_url('avatarsettings')));
193         $this->elementStart('fieldset');
194         $this->element('legend', null, _('Avatar settings'));
195         $this->hidden('token', common_session_token());
196
197         $this->elementStart('ul', 'form_data');
198
199         $this->elementStart('li',
200                             array('id' => 'avatar_original',
201                                   'class' => 'avatar_view'));
202         $this->element('h2', null, _("Original"));
203         $this->elementStart('div', array('id'=>'avatar_original_view'));
204         $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
205                                     'width' => $this->filedata['width'],
206                                     'height' => $this->filedata['height'],
207                                     'alt' => $user->nickname));
208         $this->elementEnd('div');
209         $this->elementEnd('li');
210
211         $this->elementStart('li',
212                             array('id' => 'avatar_preview',
213                                   'class' => 'avatar_view'));
214         $this->element('h2', null, _("Preview"));
215         $this->elementStart('div', array('id'=>'avatar_preview_view'));
216         $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
217                                     'width' => AVATAR_PROFILE_SIZE,
218                                     'height' => AVATAR_PROFILE_SIZE,
219                                     'alt' => $user->nickname));
220         $this->elementEnd('div');
221
222         foreach (array('avatar_crop_x', 'avatar_crop_y',
223                        'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
224             $this->element('input', array('name' => $crop_info,
225                                           'type' => 'hidden',
226                                           'id' => $crop_info));
227         }
228         $this->submit('crop', _('Crop'));
229
230         $this->elementEnd('li');
231         $this->elementEnd('ul');
232         $this->elementEnd('fieldset');
233         $this->elementEnd('form');
234
235     }
236
237     /**
238      * Handle a post
239      *
240      * We mux on the button name to figure out what the user actually wanted.
241      *
242      * @return void
243      */
244
245     function handlePost()
246     {
247         // CSRF protection
248
249         $token = $this->trimmed('token');
250         if (!$token || $token != common_session_token()) {
251             $this->show_form(_('There was a problem with your session token. '.
252                                'Try again, please.'));
253             return;
254         }
255
256         if ($this->arg('upload')) {
257             $this->uploadAvatar();
258         } else if ($this->arg('crop')) {
259             $this->cropAvatar();
260         } else if ($this->arg('delete')) {
261             $this->deleteAvatar();
262         } else {
263             $this->showForm(_('Unexpected form submission.'));
264         }
265     }
266
267     /**
268      * Handle an image upload
269      *
270      * Does all the magic for handling an image upload, and crops the
271      * image by default.
272      *
273      * @return void
274      */
275
276     function uploadAvatar()
277     {
278         try {
279             $imagefile = ImageFile::fromUpload('avatarfile');
280         } catch (Exception $e) {
281             $this->showForm($e->getMessage());
282             return;
283         }
284
285         $cur = common_current_user();
286
287         $filename = Avatar::filename($cur->id,
288                                      image_type_to_extension($imagefile->type),
289                                      null,
290                                      'tmp'.common_timestamp());
291
292         $filepath = Avatar::path($filename);
293
294         move_uploaded_file($imagefile->filepath, $filepath);
295
296         $filedata = array('filename' => $filename,
297                           'filepath' => $filepath,
298                           'width' => $imagefile->width,
299                           'height' => $imagefile->height,
300                           'type' => $imagefile->type);
301
302         $_SESSION['FILEDATA'] = $filedata;
303
304         $this->filedata = $filedata;
305
306         $this->mode = 'crop';
307
308         $this->showForm(_('Pick a square area of the image to be your avatar'),
309                         true);
310     }
311
312     /**
313      * Handle the results of jcrop.
314      *
315      * @return void
316      */
317
318     function cropAvatar()
319     {
320         $filedata = $_SESSION['FILEDATA'];
321
322         if (!$filedata) {
323             $this->serverError(_('Lost our file data.'));
324             return;
325         }
326
327         $file_d = ($filedata['width'] > $filedata['height'])
328                      ? $filedata['height'] : $filedata['width'];
329
330         $dest_x = $this->arg('avatar_crop_x') ? $this->arg('avatar_crop_x'):0;
331         $dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y'):0;
332         $dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$file_d;
333         $dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$file_d;
334         $size = min($dest_w, $dest_h, MAX_ORIGINAL);
335
336         $user = common_current_user();
337         $profile = $user->getProfile();
338
339         $imagefile = new ImageFile($user->id, $filedata['filepath']);
340         $filename = $imagefile->resize($size, $dest_x, $dest_y, $dest_w, $dest_h);
341
342         if ($profile->setOriginal($filename)) {
343             @unlink($filedata['filepath']);
344             unset($_SESSION['FILEDATA']);
345             $this->mode = 'upload';
346             $this->showForm(_('Avatar updated.'), true);
347             common_broadcast_profile($profile);
348         } else {
349             $this->showForm(_('Failed updating avatar.'));
350         }
351     }
352     
353     /**
354      * Get rid of the current avatar.
355      *
356      * @return void
357      */
358     
359     function deleteAvatar()
360     {
361         $user = common_current_user();
362         $profile = $user->getProfile();
363         
364         $avatar = $profile->getOriginalAvatar();
365         $avatar->delete();
366         $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
367         $avatar->delete();
368         $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
369         $avatar->delete();
370         $avatar = $profile->getAvatar(AVATAR_MINI_SIZE);
371         $avatar->delete();
372
373         $this->showForm(_('Avatar deleted.'), true);
374     }
375
376     /**
377      * Add the jCrop stylesheet
378      *
379      * @return void
380      */
381
382     function showStylesheets()
383     {
384         parent::showStylesheets();
385         $this->cssLink('css/jquery.Jcrop.css','base','screen, projection, tv');
386     }
387
388     /**
389      * Add the jCrop scripts
390      *
391      * @return void
392      */
393
394     function showScripts()
395     {
396         parent::showScripts();
397
398         if ($this->mode == 'crop') {
399             $this->script('js/jcrop/jquery.Jcrop.min.js');
400             $this->script('js/jcrop/jquery.Jcrop.go.js');
401         }
402     }
403 }