3 * StatusNet, 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@status.net>
25 * @author Zach Copley <zach@status.net>
26 * @copyright 2008-2011 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://status.net/
31 if (!defined('GNUSOCIAL')) {
38 * We use jCrop plugin for jQuery to crop the image after upload.
42 * @author Evan Prodromou <evan@status.net>
43 * @author Zach Copley <zach@status.net>
44 * @author Sarven Capadisli <csarven@status.net>
45 * @author Alexei Sorokin <sor.alexei@meowr.ru>
46 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
47 * @link http://status.net/
49 class GrouplogoAction extends GroupAction
52 public $imagefile = null;
53 public $filename = null;
54 public $message = null;
55 public $success = null;
56 protected $canPost = true;
61 * @return string Title of the page
63 public function title()
65 // TRANS: Title for group logo settings page.
66 return _('Group logo');
70 * Content area of the page
72 * Shows a form for uploading an avatar.
76 public function showContent()
78 if ($this->mode == 'crop') {
79 $this->showCropForm();
81 $this->showUploadForm();
85 public function showCropForm()
87 $this->elementStart('form', array('method' => 'post',
88 'id' => 'form_settings_avatar',
89 'class' => 'form_settings',
93 array('nickname' => $this->group->nickname)
95 $this->elementStart('fieldset');
96 // TRANS: Legend for group logo settings fieldset.
97 $this->element('legend', null, _('Avatar settings'));
98 $this->hidden('token', common_session_token());
100 $this->elementStart('ul', 'form_data');
104 array('id' => 'avatar_original',
105 'class' => 'avatar_view')
107 // TRANS: Header for originally uploaded file before a crop on the group logo page.
108 $this->element('h2', null, _('Original'));
109 $this->elementStart('div', array('id' => 'avatar_original_view'));
110 $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
111 'width' => $this->filedata['width'],
112 'height' => $this->filedata['height'],
113 'alt' => $this->group->nickname));
114 $this->elementEnd('div');
115 $this->elementEnd('li');
119 array('id' => 'avatar_preview',
120 'class' => 'avatar_view')
122 // TRANS: Header for the cropped group logo on the group logo page.
123 $this->element('h2', null, _('Preview'));
124 $this->elementStart('div', array('id' => 'avatar_preview_view'));
125 $this->element('img', array('src' => Avatar::url($this->filedata['filename']),
126 'width' => AVATAR_PROFILE_SIZE,
127 'height' => AVATAR_PROFILE_SIZE,
128 'alt' => $this->group->nickname));
129 $this->elementEnd('div');
131 foreach (array('avatar_crop_x', 'avatar_crop_y',
132 'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
133 $this->element('input', array('name' => $crop_info,
135 'id' => $crop_info));
138 // TRANS: Button text for cropping an uploaded group logo.
139 $this->submit('crop', _('Crop'));
141 $this->elementEnd('li');
142 $this->elementEnd('ul');
143 $this->elementEnd('fieldset');
144 $this->elementEnd('form');
147 public function showUploadForm()
149 $user = common_current_user();
151 $profile = $user->getProfile();
154 common_log_db_error($user, 'SELECT', __FILE__);
155 // TRANS: Error message displayed when referring to a user without a profile.
156 $this->serverError(_('User has no profile.'));
159 $original = $this->group->original_logo;
161 $this->elementStart('form', array('enctype' => 'multipart/form-data',
163 'id' => 'form_settings_avatar',
164 'class' => 'form_settings',
168 array('nickname' => $this->group->nickname)
170 $this->elementStart('fieldset');
171 // TRANS: Group logo form legend.
172 $this->element('legend', null, _('Group logo'));
173 $this->hidden('token', common_session_token());
175 $this->elementStart('ul', 'form_data');
177 $this->elementStart('li', array('id' => 'avatar_original',
178 'class' => 'avatar_view'));
179 // TRANS: Uploaded original file in group logo form.
180 $this->element('h2', null, _('Original'));
181 $this->elementStart('div', array('id' => 'avatar_original_view'));
182 $this->element('img', array('src' => $this->group->original_logo,
183 'alt' => $this->group->nickname));
184 $this->elementEnd('div');
185 $this->elementEnd('li');
188 if ($this->group->homepage_logo) {
189 $this->elementStart('li', array('id' => 'avatar_preview',
190 'class' => 'avatar_view'));
191 // TRANS: Header for preview of to be displayed group logo.
192 $this->element('h2', null, _('Preview'));
193 $this->elementStart('div', array('id' => 'avatar_preview_view'));
194 $this->element('img', array('src' => $this->group->homepage_logo,
195 'width' => AVATAR_PROFILE_SIZE,
196 'height' => AVATAR_PROFILE_SIZE,
197 'alt' => $this->group->nickname));
198 $this->elementEnd('div');
199 if (!empty($this->group->homepage_logo)) {
200 // TRANS: Button on group logo upload page to delete current group logo.
201 $this->submit('delete', _('Delete'));
203 $this->elementEnd('li');
206 $this->elementStart('li', array('id' => 'settings_attach'));
207 $this->element('input', array('name' => 'MAX_FILE_SIZE',
209 'id' => 'MAX_FILE_SIZE',
210 'value' => ImageFile::maxFileSizeInt()));
211 $this->element('input', array('name' => 'avatarfile',
213 'id' => 'avatarfile'));
214 $this->elementEnd('li');
215 $this->elementEnd('ul');
217 $this->elementStart('ul', 'form_actions');
218 $this->elementStart('li');
219 // TRANS: Submit button for uploading a group logo.
220 $this->submit('upload', _('Upload'));
221 $this->elementEnd('li');
222 $this->elementEnd('ul');
224 $this->elementEnd('fieldset');
225 $this->elementEnd('form');
228 public function showPageNoticeBlock()
230 parent::showPageNoticeBlock();
232 if ($this->message) {
235 ($this->success) ? 'success' : 'error',
239 $inst = $this->getInstructions();
240 $output = common_markup_to_html($inst);
242 $this->elementStart('div', 'instructions');
244 $this->elementEnd('div');
249 * Instructions for use
251 * @return string instructions for use
253 public function getInstructions()
255 // TRANS: Instructions for group logo page.
256 // TRANS: %s is the maximum file size for that site.
257 return sprintf(_('You can upload a logo image for your group. The maximum file size is %s.'), ImageFile::maxFileSize());
261 * Add the jCrop stylesheet
265 public function showStylesheets()
267 parent::showStylesheets();
268 $this->cssLink('js/extlib/jquery-jcrop/css/jcrop.css', 'base', 'screen, projection, tv');
272 * Add the jCrop scripts
276 public function showScripts()
278 parent::showScripts();
280 if ($this->mode == 'crop') {
281 $this->script('extlib/jquery-jcrop/jcrop.js');
282 $this->script('jcrop.go.js');
285 $this->autofocus('avatarfile');
292 * @throws ClientException
293 * @throws NicknameException
295 protected function prepare(array $args = [])
297 parent::prepare($args);
299 if (!common_logged_in()) {
300 // TRANS: Client error displayed when trying to create a group while not logged in.
301 $this->clientError(_('You must be logged in to create a group.'));
304 $nickname_arg = $this->trimmed('nickname');
305 $nickname = common_canonical_nickname($nickname_arg);
307 // Permanent redirect on non-canonical nickname
309 if ($nickname_arg != $nickname) {
310 $args = array('nickname' => $nickname);
311 common_redirect(common_local_url('grouplogo', $args), 301);
315 // TRANS: Client error displayed when trying to change group logo settings without providing a nickname.
316 $this->clientError(_('No nickname.'), 404);
319 $groupid = $this->trimmed('groupid');
322 $this->group = User_group::getKV('id', $groupid);
324 $local = Local_group::getKV('nickname', $nickname);
326 $this->group = User_group::getKV('id', $local->group_id);
331 // TRANS: Client error displayed when trying to update logo settings for a non-existing group.
332 $this->clientError(_('No such group.'), 404);
335 $cur = common_current_user();
337 if (!$cur->isAdmin($this->group)) {
338 // TRANS: Client error displayed when trying to change group logo settings while not being a group admin.
339 $this->clientError(_('You must be an admin to edit the group.'), 403);
348 * We mux on the button name to figure out what the user actually wanted.
351 * @throws ClientException
352 * @throws NoResultException
353 * @throws UnsupportedMediaException
354 * @throws UseFileAsThumbnailException
356 protected function handlePost()
358 parent::handlePost();
360 if ($this->arg('upload')) {
362 } elseif ($this->arg('crop')) {
364 } elseif ($this->arg('delete')) {
367 // TRANS: Form validation error message when an unsupported argument is used.
368 $this->setMessage(_('Unexpected form submission.'), true);
373 * Handle an image upload
375 * Does all the magic for handling an image upload, and crops the
380 public function uploadLogo()
383 $imagefile = ImageFile::fromUpload('avatarfile');
384 } catch (Exception $e) {
385 $this->setMessage($e->getMessage(), true);
389 $type = $imagefile->preferredType();
390 $filename = Avatar::filename(
392 image_type_to_extension($type),
394 'group-temp-' . common_timestamp()
397 $filepath = Avatar::path($filename);
399 $imagefile->copyTo($filepath);
401 $filedata = array('filename' => $filename,
402 'filepath' => $filepath,
403 'width' => $imagefile->width,
404 'height' => $imagefile->height,
407 $_SESSION['FILEDATA'] = $filedata;
409 $this->filedata = $filedata;
411 $this->mode = 'crop';
413 // TRANS: Form instructions on the group logo page.
414 $this->setMessage(_('Pick a square area of the image to be the logo.'));
417 public function setMessage($msg, $error = false)
419 $this->message = $msg;
420 $this->success = !$error;
424 * Handle the results of jcrop.
427 * @throws NoResultException
428 * @throws UnsupportedMediaException
429 * @throws UseFileAsThumbnailException
431 public function cropLogo()
433 $filedata = $_SESSION['FILEDATA'];
436 // TRANS: Server error displayed trying to crop an uploaded group logo that is no longer present.
437 $this->serverError(_('Lost our file data.'));
440 // If image is not being cropped assume pos & dimentions of original
441 $dest_x = $this->arg('avatar_crop_x') ? $this->arg('avatar_crop_x') : 0;
442 $dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y') : 0;
443 $dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w') : $filedata['width'];
444 $dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h') : $filedata['height'];
445 $size = min($dest_w, $dest_h, common_config('avatar', 'maxsize'));
446 $box = array('width' => $size, 'height' => $size,
447 'x' => $dest_x, 'y' => $dest_y,
448 'w' => $dest_w, 'h' => $dest_h);
450 $profile = $this->group->getProfile();
452 $imagefile = new ImageFile(null, $filedata['filepath']);
453 $filename = Avatar::filename(
455 image_type_to_extension($imagefile->preferredType()),
460 $imagefile->resizeTo(Avatar::path($filename), $box);
462 if ($profile->setOriginal($filename)) {
463 @unlink($filedata['filepath']);
464 unset($_SESSION['FILEDATA']);
465 $this->mode = 'upload';
466 // TRANS: Form success message after updating a group logo.
467 $this->setMessage(_('Logo updated.'));
469 // TRANS: Form failure message after failing to update a group logo.
470 $this->setMessage(_('Failed updating logo.'), true);
475 * Get rid of the current group logo.
479 public function deleteLogo()
481 $orig = clone($this->group);
482 Avatar::deleteFromProfile($this->group->getProfile());
483 @unlink(Avatar::path(basename($this->group->original_logo)));
484 @unlink(Avatar::path(basename($this->group->homepage_logo)));
485 @unlink(Avatar::path(basename($this->group->stream_logo)));
486 @unlink(Avatar::path(basename($this->group->mini_logo)));
487 $this->group->original_logo = User_group::defaultLogo(AVATAR_PROFILE_SIZE);
488 $this->group->homepage_logo = User_group::defaultLogo(AVATAR_PROFILE_SIZE);
489 $this->group->stream_logo = User_group::defaultLogo(AVATAR_STREAM_SIZE);
490 $this->group->mini_logo = User_group::defaultLogo(AVATAR_MINI_SIZE);
491 $this->group->update($orig);
493 // TRANS: Success message for deleting the group logo.
494 $this->setMessage(_('Logo deleted.'));