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