]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - actions/grouplogo.php
These aren't readonly
[quix0rs-gnu-social.git] / actions / grouplogo.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 GrouplogoAction extends Action
52 {
53     var $mode = null;
54     var $imagefile = null;
55     var $filename = null;
56
57     /**
58      * Prepare to run
59      */
60
61     function prepare($args)
62     {
63         parent::prepare($args);
64
65         if (!common_config('inboxes','enabled')) {
66             $this->serverError(_('Inboxes must be enabled for groups to work'));
67             return false;
68         }
69
70         if (!common_logged_in()) {
71             $this->clientError(_('You must be logged in to create a group.'));
72             return false;
73         }
74
75         $nickname_arg = $this->trimmed('nickname');
76         $nickname = common_canonical_nickname($nickname_arg);
77
78         // Permanent redirect on non-canonical nickname
79
80         if ($nickname_arg != $nickname) {
81             $args = array('nickname' => $nickname);
82             common_redirect(common_local_url('editgroup', $args), 301);
83             return false;
84         }
85
86         if (!$nickname) {
87             $this->clientError(_('No nickname'), 404);
88             return false;
89         }
90
91         $groupid = $this->trimmed('groupid');
92
93         if ($groupid) {
94             $this->group = User_group::staticGet('id', $groupid);
95         } else {
96             $this->group = User_group::staticGet('nickname', $nickname);
97         }
98
99         if (!$this->group) {
100             $this->clientError(_('No such group'), 404);
101             return false;
102         }
103
104         $cur = common_current_user();
105
106         if (!$cur->isAdmin($this->group)) {
107             $this->clientError(_('You must be an admin to edit the group'), 403);
108             return false;
109         }
110
111         return true;
112     }
113
114     function handle($args)
115     {
116         parent::handle($args);
117         if ($_SERVER['REQUEST_METHOD'] == 'POST') {
118             $this->handlePost();
119         } else {
120             $this->showForm();
121         }
122     }
123
124     function showForm($msg = null)
125     {
126         $this->msg = $msg;
127         $this->showPage();
128     }
129
130     /**
131      * Title of the page
132      *
133      * @return string Title of the page
134      */
135
136     function title()
137     {
138         return _('Group logo');
139     }
140
141     /**
142      * Instructions for use
143      *
144      * @return instructions for use
145      */
146
147     function getInstructions()
148     {
149         return _('You can upload a logo image for your group.');
150     }
151
152     /**
153      * Content area of the page
154      *
155      * Shows a form for uploading an avatar.
156      *
157      * @return void
158      */
159
160     function showContent()
161     {
162         if ($this->mode == 'crop') {
163             $this->showCropForm();
164         } else {
165             $this->showUploadForm();
166         }
167     }
168
169     function showUploadForm()
170     {
171         $user = common_current_user();
172
173         $profile = $user->getProfile();
174
175         if (!$profile) {
176             common_log_db_error($user, 'SELECT', __FILE__);
177             $this->serverError(_('User without matching profile'));
178             return;
179         }
180
181         $original = $this->group->original_logo;
182
183         $this->elementStart('form', array('enctype' => 'multipart/form-data',
184                                           'method' => 'post',
185                                           'id' => 'form_settings_logo',
186                                           'class' => 'form_settings',
187                                           'action' =>
188                                           common_local_url('grouplogo',
189                                                            array('nickname' => $this->group->nickname))));
190         $this->elementStart('fieldset');
191         $this->element('legend', null, _('Group logo'));
192         $this->hidden('token', common_session_token());
193
194         $this->elementStart('ul', 'form_data');
195         if ($original) {
196             $this->elementStart('li', array('id' => 'avatar_original',
197                                             'class' => 'avatar_view'));
198             $this->element('h2', null, _("Original"));
199             $this->elementStart('div', array('id'=>'avatar_original_view'));
200             $this->element('img', array('src' => $this->group->original_logo,
201                                         'alt' => $this->group->nickname));
202             $this->elementEnd('div');
203             $this->elementEnd('li');
204         }
205
206         if ($this->group->homepage_logo) {
207             $this->elementStart('li', array('id' => 'avatar_preview',
208                                             'class' => 'avatar_view'));
209             $this->element('h2', null, _("Preview"));
210             $this->elementStart('div', array('id'=>'avatar_preview_view'));
211             $this->element('img', array('src' => $this->group->homepage_logo,
212                                         'width' => AVATAR_PROFILE_SIZE,
213                                         'height' => AVATAR_PROFILE_SIZE,
214                                         'alt' => $this->group->nickname));
215             $this->elementEnd('div');
216             $this->elementEnd('li');
217         }
218
219         $this->elementStart('li', array ('id' => 'settings_attach'));
220         $this->element('input', array('name' => 'avatarfile',
221                                       'type' => 'file',
222                                       'id' => 'avatarfile'));
223         $this->element('input', array('name' => 'MAX_FILE_SIZE',
224                                       'type' => 'hidden',
225                                       'id' => 'MAX_FILE_SIZE',
226                                       'value' => MAX_AVATAR_SIZE));
227         $this->elementEnd('li');
228         $this->elementEnd('ul');
229
230         $this->elementStart('ul', 'form_actions');
231         $this->elementStart('li');
232         $this->submit('upload', _('Upload'));
233         $this->elementEnd('li');
234         $this->elementEnd('ul');
235
236         $this->elementEnd('fieldset');
237         $this->elementEnd('form');
238
239     }
240
241     function showCropForm()
242     {
243         $this->elementStart('form', array('method' => 'post',
244                                           'id' => 'form_settings_avatar',
245                                           'class' => 'form_settings',
246                                           'action' =>
247                                           common_local_url('grouplogo',
248                                                            array('nickname' => $this->group->nickname))));
249         $this->elementStart('fieldset');
250         $this->element('legend', null, _('Avatar settings'));
251         $this->hidden('token', common_session_token());
252
253         $this->elementStart('ul', 'form_data');
254
255         $this->elementStart('li',
256                             array('id' => 'avatar_original',
257                                   'class' => 'avatar_view'));
258         $this->element('h2', null, _("Original"));
259         $this->elementStart('div', array('id'=>'avatar_original_view'));
260         $this->element('img', array('src' => common_avatar_url($this->filedata['filename']),
261                                     'width' => $this->filedata['width'],
262                                     'height' => $this->filedata['height'],
263                                     'alt' => $this->group->nickname));
264         $this->elementEnd('div');
265         $this->elementEnd('li');
266
267         $this->elementStart('li',
268                             array('id' => 'avatar_preview',
269                                   'class' => 'avatar_view'));
270         $this->element('h2', null, _("Preview"));
271         $this->elementStart('div', array('id'=>'avatar_preview_view'));
272         $this->element('img', array('src' => common_avatar_url($this->filedata['filename']),
273                                     'width' => AVATAR_PROFILE_SIZE,
274                                     'height' => AVATAR_PROFILE_SIZE,
275                                     'alt' => $this->group->nickname));
276         $this->elementEnd('div');
277
278         foreach (array('avatar_crop_x', 'avatar_crop_y',
279                        'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
280             $this->element('input', array('name' => $crop_info,
281                                           'type' => 'hidden',
282                                           'id' => $crop_info));
283         }
284         $this->submit('crop', _('Crop'));
285
286         $this->elementEnd('li');
287         $this->elementEnd('ul');
288         $this->elementEnd('fieldset');
289         $this->elementEnd('form');
290
291     }
292
293     /**
294      * Handle a post
295      *
296      * We mux on the button name to figure out what the user actually wanted.
297      *
298      * @return void
299      */
300
301     function handlePost()
302     {
303         // CSRF protection
304
305         $token = $this->trimmed('token');
306         if (!$token || $token != common_session_token()) {
307             $this->show_form(_('There was a problem with your session token. '.
308                                'Try again, please.'));
309             return;
310         }
311
312         if ($this->arg('upload')) {
313             $this->uploadAvatar();
314         } else if ($this->arg('crop')) {
315             $this->cropAvatar();
316         } else {
317             $this->showForm(_('Unexpected form submission.'));
318         }
319     }
320
321     /**
322      * Handle an image upload
323      *
324      * Does all the magic for handling an image upload, and crops the
325      * image by default.
326      *
327      * @return void
328      */
329
330     function uploadAvatar()
331     {
332         try {
333             $imagefile = ImageFile::fromUpload('avatarfile');
334         } catch (Exception $e) {
335             $this->showForm($e->getMessage());
336             return;
337         }
338
339         $filename = common_avatar_filename($this->group->id,
340                                            image_type_to_extension($imagefile->type),
341                                            null,
342                                            'group-temp-'.common_timestamp());
343
344         $filepath = common_avatar_path($filename);
345
346         move_uploaded_file($imagefile->filename, $filepath);
347
348         $filedata = array('filename' => $filename,
349                           'filepath' => $filepath,
350                           'width' => $imagefile->width,
351                           'height' => $imagefile->height,
352                           'type' => $imagefile->type);
353
354         $_SESSION['FILEDATA'] = $filedata;
355
356         $this->filedata = $filedata;
357
358         $this->mode = 'crop';
359
360         $this->showForm(_('Pick a square area of the image to be your avatar'),
361                         true);
362     }
363
364     /**
365      * Handle the results of jcrop.
366      *
367      * @return void
368      */
369
370     function cropAvatar()
371     {
372         $user = common_current_user();
373
374         $profile = $user->getProfile();
375
376         $x = $this->arg('avatar_crop_x');
377         $y = $this->arg('avatar_crop_y');
378         $w = $this->arg('avatar_crop_w');
379         $h = $this->arg('avatar_crop_h');
380
381         $filedata = $_SESSION['FILEDATA'];
382
383         if (!$filedata) {
384             $this->serverError(_('Lost our file data.'));
385             return;
386         }
387
388         $filepath = common_avatar_path($filedata['filename']);
389
390         if (!file_exists($filepath)) {
391             $this->serverError(_('Lost our file.'));
392             return;
393         }
394
395         switch ($filedata['type']) {
396         case IMAGETYPE_GIF:
397             $image_src = imagecreatefromgif($filepath);
398             break;
399         case IMAGETYPE_JPEG:
400             $image_src = imagecreatefromjpeg($filepath);
401             break;
402         case IMAGETYPE_PNG:
403             $image_src = imagecreatefrompng($filepath);
404             break;
405          default:
406             $this->serverError(_('Unknown file type'));
407             return;
408         }
409
410         common_debug("W = $w, H = $h, X = $x, Y = $y");
411
412         $image_dest = imagecreatetruecolor($w, $h);
413
414         $background = imagecolorallocate($image_dest, 0, 0, 0);
415         ImageColorTransparent($image_dest, $background);
416         imagealphablending($image_dest, false);
417
418         imagecopyresized($image_dest, $image_src, 0, 0, $x, $y, $w, $h, $w, $h);
419
420         $cur = common_current_user();
421
422         $filename = common_avatar_filename($this->group->id,
423                                            image_type_to_extension($imagefile->type),
424                                            null,
425                                            'group-'.common_timestamp());
426
427         $filepath = common_avatar_path($filename);
428
429         switch ($filedata['type']) {
430         case IMAGETYPE_GIF:
431             imagegif($image_dest, $filepath);
432             break;
433         case IMAGETYPE_JPEG:
434             imagejpeg($image_dest, $filepath);
435             break;
436         case IMAGETYPE_PNG:
437             imagepng($image_dest, $filepath);
438             break;
439          default:
440             $this->serverError(_('Unknown file type'));
441             return;
442         }
443
444         if ($this->group->setOriginal($filename, $filedata['type'])) {
445             @unlink(common_avatar_path($filedata['filename']));
446             unset($_SESSION['FILEDATA']);
447             $this->mode = 'upload';
448             $this->showForm(_('Logo updated.'), true);
449         } else {
450             $this->showForm(_('Failed updating logo.'));
451         }
452     }
453
454     function showPageNotice()
455     {
456         if ($this->msg) {
457             $this->element('div', ($this->success) ? 'success' : 'error',
458                            $this->msg);
459         } else {
460             $inst   = $this->getInstructions();
461             $output = common_markup_to_html($inst);
462
463             $this->elementStart('div', 'instructions');
464             $this->raw($output);
465             $this->elementEnd('div');
466         }
467     }
468
469     /**
470      * Add the jCrop stylesheet
471      *
472      * @return void
473      */
474
475     function showStylesheets()
476     {
477         parent::showStylesheets();
478         $jcropStyle =
479           common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION);
480
481         $this->element('link', array('rel' => 'stylesheet',
482                                      'type' => 'text/css',
483                                      'href' => $jcropStyle,
484                                      'media' => 'screen, projection, tv'));
485     }
486
487     /**
488      * Add the jCrop scripts
489      *
490      * @return void
491      */
492
493     function showScripts()
494     {
495         parent::showScripts();
496
497         $jcropPack = common_path('js/jcrop/jquery.Jcrop.pack.js');
498         $jcropGo   = common_path('js/jcrop/jquery.Jcrop.go.js');
499
500         $this->element('script', array('type' => 'text/javascript',
501                                        'src' => $jcropPack));
502         $this->element('script', array('type' => 'text/javascript',
503                                        'src' => $jcropGo));
504     }
505
506     function showLocalNav()
507     {
508         $nav = new GroupNav($this, $this->group);
509         $nav->show();
510     }
511 }