summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZach Copley <zach@controlyourself.ca>2008-12-25 09:46:01 -0500
committerZach Copley <zach@controlyourself.ca>2008-12-25 09:46:01 -0500
commit5e061d2060702516328a723ad6c9577eb0aa782d (patch)
tree1ed33f138f71806da110d6234f22ecf0a109966e
parent6b51941056a361327e8717ede1194df3abe430a9 (diff)
Some fixups of patches not already migrated to trunk to bring inline with PEAR coding stds
darcs-hash:20081225144601-7b5ce-4846f3d036c36037836d15ed672c10ba33f9f84c.gz
-rw-r--r--_darcs/inventory4
-rw-r--r--_darcs/patches/20081225144601-7b5ce-4846f3d036c36037836d15ed672c10ba33f9f84c.gzbin0 -> 2691 bytes
-rw-r--r--_darcs/pristine/actions/profilesettings.php136
-rw-r--r--_darcs/pristine/classes/Avatar.php75
-rw-r--r--_darcs/pristine/classes/Profile.php42
-rw-r--r--_darcs/pristine/lib/settingsaction.php25
-rw-r--r--_darcs/tentative_inventory127
-rw-r--r--_darcs/tentative_pristine287
-rw-r--r--actions/profilesettings.php136
-rw-r--r--classes/Avatar.php75
-rw-r--r--classes/Profile.php42
-rw-r--r--lib/settingsaction.php25
12 files changed, 682 insertions, 292 deletions
diff --git a/_darcs/inventory b/_darcs/inventory
index da63f8216..22b47336e 100644
--- a/_darcs/inventory
+++ b/_darcs/inventory
@@ -124,4 +124,6 @@ csarven@controlyourself.ca**20081210021607]
[Jcrop CSS updates to original/preview views
csarven@controlyourself.ca**20081210025922]
[Actually crop your avatar when hitting 'crop' button on profile
-Zach Copley <zach@controlyourself.ca>**20081212043018] \ No newline at end of file
+Zach Copley <zach@controlyourself.ca>**20081212043018]
+[Some fixups of patches not already migrated to trunk to bring inline with PEAR coding stds
+Zach Copley <zach@controlyourself.ca>**20081225144601] \ No newline at end of file
diff --git a/_darcs/patches/20081225144601-7b5ce-4846f3d036c36037836d15ed672c10ba33f9f84c.gz b/_darcs/patches/20081225144601-7b5ce-4846f3d036c36037836d15ed672c10ba33f9f84c.gz
new file mode 100644
index 000000000..6a5d9a9db
--- /dev/null
+++ b/_darcs/patches/20081225144601-7b5ce-4846f3d036c36037836d15ed672c10ba33f9f84c.gz
Binary files differ
diff --git a/_darcs/pristine/actions/profilesettings.php b/_darcs/pristine/actions/profilesettings.php
index caec2f93d..d861919b9 100644
--- a/_darcs/pristine/actions/profilesettings.php
+++ b/_darcs/pristine/actions/profilesettings.php
@@ -54,13 +54,17 @@ class ProfilesettingsAction extends SettingsAction
return;
}
- if ($this->arg('save')) {
- $this->save_profile();
- } else if ($this->arg('upload')) {
- $this->upload_avatar();
- } else if ($this->arg('changepass')) {
- $this->change_password();
- }
+ if ($this->arg('save')) {
+ $this->save_profile();
+ } else if ($this->arg('upload')) {
+ $this->upload_avatar();
+ } else if ($this->arg('crop')) {
+ $this->crop_avatar();
+ } else if ($this->arg('changepass')) {
+ $this->change_password();
+ } else {
+ $this->show_form(_('Unexpected form submission.'));
+ }
}
@@ -70,31 +74,30 @@ class ProfilesettingsAction extends SettingsAction
$user = common_current_user();
$profile = $user->getProfile();
- common_element_start('form', array('method' => 'POST',
- 'id' => 'profilesettings',
- 'action' =>
- common_local_url('profilesettings')));
- common_hidden('token', common_session_token());
-
- # too much common patterns here... abstractable?
-
- common_input('nickname', _('Nickname'),
- ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
- _('1-64 lowercase letters or numbers, no punctuation or spaces'));
- common_input('fullname', _('Full name'),
- ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
- common_input('homepage', _('Homepage'),
- ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
- _('URL of your homepage, blog, or profile on another site'));
- common_textarea('bio', _('Bio'),
- ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
- _('Describe yourself and your interests in 140 chars'));
- common_input('location', _('Location'),
- ($this->arg('location')) ? $this->arg('location') : $profile->location,
- _('Where you are, like "City, State (or Region), Country"'));
- common_input('tags', _('Tags'),
- ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
- _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
+ common_element_start('form', array('method' => 'POST',
+ 'id' => 'profilesettings',
+ 'action' => common_local_url('profilesettings')));
+ common_hidden('token', common_session_token());
+
+ # too much common patterns here... abstractable?
+
+ common_input('nickname', _('Nickname'),
+ ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
+ _('1-64 lowercase letters or numbers, no punctuation or spaces'));
+ common_input('fullname', _('Full name'),
+ ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
+ common_input('homepage', _('Homepage'),
+ ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
+ _('URL of your homepage, blog, or profile on another site'));
+ common_textarea('bio', _('Bio'),
+ ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
+ _('Describe yourself and your interests in 140 chars'));
+ common_input('location', _('Location'),
+ ($this->arg('location')) ? $this->arg('location') : $profile->location,
+ _('Where you are, like "City, State (or Region), Country"'));
+ common_input('tags', _('Tags'),
+ ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
+ _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
$language = common_language();
common_dropdown('language', _('Language'), get_nice_language_list(), _('Preferred language'), true, $language);
@@ -112,7 +115,6 @@ class ProfilesettingsAction extends SettingsAction
common_element_end('form');
-
}
function show_avatar_form()
@@ -137,24 +139,40 @@ class ProfilesettingsAction extends SettingsAction
common_local_url('profilesettings')));
common_hidden('token', common_session_token());
- if ($original) {
- common_element('img', array('src' => $original->url,
- 'class' => 'avatar original',
- 'width' => $original->width,
- 'height' => $original->height,
- 'alt' => $user->nickname));
- }
+ if ($original) {
+ common_element_start('div', array('id'=>'avatar_original', 'class'=>'avatar_view'));
+ common_element('h3', null, _("Original:"));
+ common_element_start('div', array('id'=>'avatar_original_view'));
+ common_element('img', array('src' => $original->url,
+ 'class' => 'avatar original',
+ 'width' => $original->width,
+ 'height' => $original->height,
+ 'alt' => $user->nickname));
+ common_element_end('div');
+ common_element_end('div');
+ }
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
- if ($avatar) {
- common_element('img', array('src' => $avatar->url,
- 'class' => 'avatar profile',
- 'width' => AVATAR_PROFILE_SIZE,
- 'height' => AVATAR_PROFILE_SIZE,
- 'alt' => $user->nickname));
- }
-
+ if ($avatar) {
+ common_element_start('div', array('id'=>'avatar_preview', 'class'=>'avatar_view'));
+ common_element('h3', null, _("Preview:"));
+ common_element_start('div', array('id'=>'avatar_preview_view'));
+ common_element('img', array('src' => $original->url,//$avatar->url,
+ 'class' => 'avatar profile',
+ 'width' => AVATAR_PROFILE_SIZE,
+ 'height' => AVATAR_PROFILE_SIZE,
+ 'alt' => $user->nickname));
+ common_element_end('div');
+ common_element_end('div');
+
+ foreach(array('avatar_crop_x', 'avatar_crop_y', 'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
+ common_element('input', array('name' => $crop_info,
+ 'type' => 'hidden',
+ 'id' => $crop_info));
+ }
+ common_submit('crop', _('Crop'));
+ }
common_element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden',
@@ -163,7 +181,6 @@ class ProfilesettingsAction extends SettingsAction
common_element_start('p');
-
common_element('input', array('name' => 'avatarfile',
'type' => 'file',
'id' => 'avatarfile'));
@@ -390,8 +407,25 @@ class ProfilesettingsAction extends SettingsAction
$this->show_form(_('Failed updating avatar.'));
}
- @unlink($_FILES['avatarfile']['tmp_name']);
- }
+ @unlink($_FILES['avatarfile']['tmp_name']);
+ }
+
+ function crop_avatar() {
+
+ $user = common_current_user();
+ $profile = $user->getProfile();
+
+ $x = $this->arg('avatar_crop_x');
+ $y = $this->arg('avatar_crop_y');
+ $w = $this->arg('avatar_crop_w');
+ $h = $this->arg('avatar_crop_h');
+
+ if ($profile->crop_avatars($x, $y, $w, $h)) {
+ $this->show_form(_('Avatar updated.'), true);
+ } else {
+ $this->show_form(_('Failed updating avatar.'));
+ }
+ }
function nickname_exists($nickname)
{
diff --git a/_darcs/pristine/classes/Avatar.php b/_darcs/pristine/classes/Avatar.php
index 4fdb99d35..9ae920647 100644
--- a/_darcs/pristine/classes/Avatar.php
+++ b/_darcs/pristine/classes/Avatar.php
@@ -79,20 +79,63 @@ class Avatar extends Memcached_DataObject
}
}
- function to_image() {
- $filepath = common_avatar_path($this->filename);
- if ($this->mediatype == 'image/gif') {
- return imagecreatefromgif($filepath);
- } else if ($this->mediatype == 'image/jpeg') {
- return imagecreatefromjpeg($filepath);
- } else if ($this->mediatype == 'image/png') {
- return imagecreatefrompng($filepath);
- } else {
- return NULL;
- }
- }
-
- function &pkeyGet($kv) {
- return Memcached_DataObject::pkeyGet('Avatar', $kv);
- }
+ function scale_and_crop($size, $x, $y, $w, $h)
+ {
+
+ $image_s = imagecreatetruecolor($size, $size);
+ $image_a = $this->to_image();
+
+ # Retain alpha channel info if possible for .pngs
+ $background = imagecolorallocate($image_s, 0, 0, 0);
+ ImageColorTransparent($image_s, $background);
+ imagealphablending($image_s, false);
+
+ imagecopyresized($image_s, $image_a, 0, 0, $x, $y, $size, $size, $w, $h);
+
+ $ext = ($this->mediattype == 'image/jpeg') ? ".jpeg" : ".png";
+
+ $filename = common_avatar_filename($this->profile_id, $ext, $size, common_timestamp());
+
+ if ($this->mediatype == 'image/jpeg') {
+ imagejpeg($image_s, common_avatar_path($filename));
+ } else {
+ imagepng($image_s, common_avatar_path($filename));
+ }
+
+ $cropped = DB_DataObject::factory('avatar');
+ $cropped->profile_id = $this->profile_id;
+ $cropped->width = $size;
+ $cropped->height = $size;
+ $cropped->original = false;
+ $cropped->mediatype = ($this->mediattype == 'image/jpeg') ? 'image/jpeg' : 'image/png';
+ $cropped->filename = $filename;
+ $cropped->url = common_avatar_url($filename);
+ $cropped->created = DB_DataObject_Cast::dateTime(); # current time
+
+ if ($cropped->insert()) {
+ return $cropped;
+ } else {
+ return NULL;
+ }
+ }
+
+ function to_image()
+ {
+ $filepath = common_avatar_path($this->filename);
+ if ($this->mediatype == 'image/gif') {
+ return imagecreatefromgif($filepath);
+ } else if ($this->mediatype == 'image/jpeg') {
+ return imagecreatefromjpeg($filepath);
+ } else if ($this->mediatype == 'image/png') {
+ return imagecreatefrompng($filepath);
+ } else {
+ return NULL;
+ }
+ }
+
+ function &pkeyGet($kv)
+ {
+ return Memcached_DataObject::pkeyGet('Avatar', $kv);
+ }
+
}
diff --git a/_darcs/pristine/classes/Profile.php b/_darcs/pristine/classes/Profile.php
index 3b6ac1d7f..31bdf71d5 100644
--- a/_darcs/pristine/classes/Profile.php
+++ b/_darcs/pristine/classes/Profile.php
@@ -121,15 +121,39 @@ class Profile extends Memcached_DataObject
return $avatar;
}
- function delete_avatars() {
- $avatar = new Avatar();
- $avatar->profile_id = $this->id;
- $avatar->find();
- while ($avatar->fetch()) {
- $avatar->delete();
- }
- return true;
- }
+ function crop_avatars($x, $y, $w, $h)
+ {
+
+ $avatar = $this->getOriginalAvatar();
+ $this->delete_avatars(false); # don't delete original
+
+ foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) {
+ # We don't do a scaled one if original is our scaled size
+ if (!($avatar->width == $size && $avatar->height == $size)) {
+ $s = $avatar->scale_and_crop($size, $x, $y, $w, $h);
+ if (!$s) {
+ return NULL;
+ }
+ }
+ }
+ return true;
+ }
+
+ function delete_avatars($original=true)
+ {
+ $avatar = new Avatar();
+ $avatar->profile_id = $this->id;
+ $avatar->find();
+ while ($avatar->fetch()) {
+ if ($avatar->original) {
+ if ($original == false) {
+ continue;
+ }
+ }
+ $avatar->delete();
+ }
+ return true;
+ }
function getBestName()
{
diff --git a/_darcs/pristine/lib/settingsaction.php b/_darcs/pristine/lib/settingsaction.php
index 62de39d45..03bac3a93 100644
--- a/_darcs/pristine/lib/settingsaction.php
+++ b/_darcs/pristine/lib/settingsaction.php
@@ -60,12 +60,25 @@ class SettingsAction extends Action
}
}
- function form_header($title, $msg=NULL, $success=false) {
- common_show_header($title,
- NULL,
- array($msg, $success),
- array($this, 'show_top'));
- }
+ function form_header($title, $msg=NULL, $success=false)
+ {
+ common_show_header($title,
+ array($this, 'show_header'),
+ array($msg, $success),
+ array($this, 'show_top'));
+ }
+
+ function show_header()
+ {
+ common_element('link', array('rel' => 'stylesheet',
+ 'type' => 'text/css',
+ 'href' => common_path('js/jcrop/jquery.Jcrop.css?version='.LACONICA_VERSION),
+ 'media' => 'screen, projection, tv'));
+ common_element('script', array('type' => 'text/javascript',
+ 'src' => common_path('js/jcrop/jquery.Jcrop.pack.js')));
+ common_element('script', array('type' => 'text/javascript',
+ 'src' => common_path('js/jcrop/jquery.Jcrop.go.js')));
+ }
function show_top($arr)
{
diff --git a/_darcs/tentative_inventory b/_darcs/tentative_inventory
deleted file mode 100644
index da63f8216..000000000
--- a/_darcs/tentative_inventory
+++ /dev/null
@@ -1,127 +0,0 @@
-Starting with tag:
-[TAG 0.6.4.1
-Evan Prodromou <evan@controlezvous.ca>**20081220204906]
-[identica badge by Kent Brewster. For more information see:
-Sarven Capadisli <csarven@controlyourself.ca>**20081218003302
- http://kentbrewster.com/identica-badge/
-
- Copy and paste the following wherever you want the badge to show up:
-
- <script type="text/javascript" src="http://identi.ca/js/identica-badge.js">
- {
- "user":"kentbrew",
- "server":"identi.ca",
- "headerText":" and friends"
- }
- </script>
-
- Substitute your own ID in the user parameter.
-
-]
-[more information in subscription notices
-Evan Prodromou <evan@prodromou.name>**20081212171135]
-[first step of phpcs-cleanup of index.php
-Evan Prodromou <evan@prodromou.name>**20081221002332]
-[reformatting for phpcs in lib/util.php
-Evan Prodromou <evan@prodromou.name>**20081221003016]
-[some modifications to assuage phpcs
-Evan Prodromou <evan@prodromou.name>**20081221003955]
-[reformat lib/daemon.php for phpcs
-Evan Prodromou <evan@prodromou.name>**20081221004607]
-[reformat for phpcs
-Evan Prodromou <evan@prodromou.name>**20081221005837]
-[reformat lib/jabber.php for phpcs, including doc comments
-Evan Prodromou <evan@prodromou.name>**20081222173249]
-[reformat lib/language.php for PEAR Coding Standards
-Evan Prodromou <evan@prodromou.name>**20081222193029]
-[bring mailbox.php into line with PEAR Coding Standards (mostly)
-Evan Prodromou <evan@prodromou.name>**20081222195041]
-[bring messaging section (inbox, outbox, mailbox) into PEAR Code Standards compliance
-Evan Prodromou <evan@prodromou.name>**20081222201304
-
- Actually refactored the method names on these classes to come into
- complete compliance with the code standards. Untested; maybe there are
- some bad method names now.
-
-]
-[reformat and document lib/mail.php for phpcs conformance
-Evan Prodromou <evan@prodromou.name>**20081223173330]
-[bring lib/noticelist.php into line with PEAR code standards
-Evan Prodromou <evan@prodromou.name>**20081223190851]
-[incorrect label on notice list file comment
-Evan Prodromou <evan@prodromou.name>**20081223191430]
-[replace all tabs with four spaces
-Evan Prodromou <evan@prodromou.name>**20081223191907
-
- The PEAR coding standards decree: no tabs, but indent by four spaces.
- I've done a global search-and-replace on all tabs, replacing them by
- four spaces. This is a huge change, but it will go a long way to
- getting us towards phpcs-compliance. And that means better code
- readability, and that means more participation.
-
-]
-[replace NULL with null
-Evan Prodromou <evan@prodromou.name>**20081223192129
-
- Another global search-and-replace update. Here, I've replaced the PHP
- keyword 'NULL' with its lowercase version. This is another PEAR code
- standards change.
-
-]
-[change function headers to K&R style
-Evan Prodromou <evan@prodromou.name>**20081223193323
-
- Another huge change, for PEAR code standards compliance. Function
- headers have to be in K&R style (opening brace on its own line),
- instead of having the opening brace on the same line as the function
- and parameters. So, a little perl magic found all the function
- definitions and move the opening brace to the next line (properly
- indented... usually).
-
-]
-[TRUE => true, FALSE => false
-Evan Prodromou <evan@prodromou.name>**20081223194428
-
- More PEAR coding standards global changes. Here, I've changed all
- instances of TRUE to true and FALSE to false.
-
-]
-[move opening brace of class declaration to next line
-Evan Prodromou <evan@prodromou.name>**20081223194923
-
- Another gigantor PEAR coding standards patch. Here, I've moved the
- opening curly bracket on a class statement to the following line.
-
-]
-[Twitter-bridge: fix for Twitter's new strict policy of rejecting HTTP POSTs with invalid "expect" headers
-Zach Copley <zach@controlyourself.ca>**20081225152207]
-[whitespace changes in actions/register.php after global search-and-replace
-Evan Prodromou <evan@prodromou.name>**20081223195722]
-[Laconica-specific extensions for Twitter API
-Evan Prodromou <evan@prodromou.name>**20081230202019]
-[add laconica-specific methods to htaccess.sample
-Evan Prodromou <evan@prodromou.name>**20081230202513]
-[add laconica methods to unauthed ones
-Evan Prodromou <evan@prodromou.name>**20081230203747]
-[implement api/laconica/version method
-Evan Prodromou <evan@prodromou.name>**20081230205939]
-[add some breaks so that switch statement works
-Evan Prodromou <evan@prodromou.name>**20081230210114]
-[implement the api/laconica/config method
-Evan Prodromou <evan@prodromou.name>**20081230211444]
-[better serialization of arrays and booleans in config output
-Evan Prodromou <evan@prodromou.name>**20081230211957]
-[wrapper element for config.xml
-Evan Prodromou <evan@prodromou.name>**20081230212202]
-[trac750 Automatically update linked Facebook users' statuses
-Zach Copley <zach@controlyourself.ca>**20090105010407]
-[trac750 configurable sync flags for Facebook app (noticesync, replysync)
-Zach Copley <zach@controlyourself.ca>**20090105040212]
-[trac750 added some output to the facebook_update.php script
-Zach Copley <zach@controlyourself.ca>**20090105045603]
-[Jcrop v2 (POST cropping to be completed)
-csarven@controlyourself.ca**20081210021607]
-[Jcrop CSS updates to original/preview views
-csarven@controlyourself.ca**20081210025922]
-[Actually crop your avatar when hitting 'crop' button on profile
-Zach Copley <zach@controlyourself.ca>**20081212043018] \ No newline at end of file
diff --git a/_darcs/tentative_pristine b/_darcs/tentative_pristine
index e69de29bb..04a3f84cd 100644
--- a/_darcs/tentative_pristine
+++ b/_darcs/tentative_pristine
@@ -0,0 +1,287 @@
+hunk ./actions/profilesettings.php 57
+- if ($this->arg('save')) {
+- $this->save_profile();
+- } else if ($this->arg('upload')) {
+- $this->upload_avatar();
+- } else if ($this->arg('changepass')) {
+- $this->change_password();
+- }
++ if ($this->arg('save')) {
++ $this->save_profile();
++ } else if ($this->arg('upload')) {
++ $this->upload_avatar();
++ } else if ($this->arg('crop')) {
++ $this->crop_avatar();
++ } else if ($this->arg('changepass')) {
++ $this->change_password();
++ } else {
++ $this->show_form(_('Unexpected form submission.'));
++ }
+hunk ./actions/profilesettings.php 77
+- common_element_start('form', array('method' => 'POST',
+- 'id' => 'profilesettings',
+- 'action' =>
+- common_local_url('profilesettings')));
+- common_hidden('token', common_session_token());
+-
+- # too much common patterns here... abstractable?
+-
+- common_input('nickname', _('Nickname'),
+- ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
+- _('1-64 lowercase letters or numbers, no punctuation or spaces'));
+- common_input('fullname', _('Full name'),
+- ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
+- common_input('homepage', _('Homepage'),
+- ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
+- _('URL of your homepage, blog, or profile on another site'));
+- common_textarea('bio', _('Bio'),
+- ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
+- _('Describe yourself and your interests in 140 chars'));
+- common_input('location', _('Location'),
+- ($this->arg('location')) ? $this->arg('location') : $profile->location,
+- _('Where you are, like "City, State (or Region), Country"'));
+- common_input('tags', _('Tags'),
+- ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
+- _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
++ common_element_start('form', array('method' => 'POST',
++ 'id' => 'profilesettings',
++ 'action' => common_local_url('profilesettings')));
++ common_hidden('token', common_session_token());
++
++ # too much common patterns here... abstractable?
++
++ common_input('nickname', _('Nickname'),
++ ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
++ _('1-64 lowercase letters or numbers, no punctuation or spaces'));
++ common_input('fullname', _('Full name'),
++ ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
++ common_input('homepage', _('Homepage'),
++ ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
++ _('URL of your homepage, blog, or profile on another site'));
++ common_textarea('bio', _('Bio'),
++ ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
++ _('Describe yourself and your interests in 140 chars'));
++ common_input('location', _('Location'),
++ ($this->arg('location')) ? $this->arg('location') : $profile->location,
++ _('Where you are, like "City, State (or Region), Country"'));
++ common_input('tags', _('Tags'),
++ ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
++ _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
+hunk ./actions/profilesettings.php 118
+-
+hunk ./actions/profilesettings.php 142
+- if ($original) {
+- common_element('img', array('src' => $original->url,
+- 'class' => 'avatar original',
+- 'width' => $original->width,
+- 'height' => $original->height,
+- 'alt' => $user->nickname));
+- }
++ if ($original) {
++ common_element_start('div', array('id'=>'avatar_original', 'class'=>'avatar_view'));
++ common_element('h3', null, _("Original:"));
++ common_element_start('div', array('id'=>'avatar_original_view'));
++ common_element('img', array('src' => $original->url,
++ 'class' => 'avatar original',
++ 'width' => $original->width,
++ 'height' => $original->height,
++ 'alt' => $user->nickname));
++ common_element_end('div');
++ common_element_end('div');
++ }
+hunk ./actions/profilesettings.php 157
+- if ($avatar) {
+- common_element('img', array('src' => $avatar->url,
+- 'class' => 'avatar profile',
+- 'width' => AVATAR_PROFILE_SIZE,
+- 'height' => AVATAR_PROFILE_SIZE,
+- 'alt' => $user->nickname));
+- }
++ if ($avatar) {
++ common_element_start('div', array('id'=>'avatar_preview', 'class'=>'avatar_view'));
++ common_element('h3', null, _("Preview:"));
++ common_element_start('div', array('id'=>'avatar_preview_view'));
++ common_element('img', array('src' => $original->url,//$avatar->url,
++ 'class' => 'avatar profile',
++ 'width' => AVATAR_PROFILE_SIZE,
++ 'height' => AVATAR_PROFILE_SIZE,
++ 'alt' => $user->nickname));
++ common_element_end('div');
++ common_element_end('div');
+hunk ./actions/profilesettings.php 169
++ foreach(array('avatar_crop_x', 'avatar_crop_y', 'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
++ common_element('input', array('name' => $crop_info,
++ 'type' => 'hidden',
++ 'id' => $crop_info));
++ }
++ common_submit('crop', _('Crop'));
++ }
+hunk ./actions/profilesettings.php 184
+-
+hunk ./actions/profilesettings.php 410
+- @unlink($_FILES['avatarfile']['tmp_name']);
+- }
++ @unlink($_FILES['avatarfile']['tmp_name']);
++ }
++
++ function crop_avatar() {
++
++ $user = common_current_user();
++ $profile = $user->getProfile();
++
++ $x = $this->arg('avatar_crop_x');
++ $y = $this->arg('avatar_crop_y');
++ $w = $this->arg('avatar_crop_w');
++ $h = $this->arg('avatar_crop_h');
++
++ if ($profile->crop_avatars($x, $y, $w, $h)) {
++ $this->show_form(_('Avatar updated.'), true);
++ } else {
++ $this->show_form(_('Failed updating avatar.'));
++ }
++ }
+hunk ./classes/Avatar.php 82
+- function to_image() {
+- $filepath = common_avatar_path($this->filename);
+- if ($this->mediatype == 'image/gif') {
+- return imagecreatefromgif($filepath);
+- } else if ($this->mediatype == 'image/jpeg') {
+- return imagecreatefromjpeg($filepath);
+- } else if ($this->mediatype == 'image/png') {
+- return imagecreatefrompng($filepath);
+- } else {
+- return NULL;
+- }
+- }
+-
+- function &pkeyGet($kv) {
+- return Memcached_DataObject::pkeyGet('Avatar', $kv);
+- }
++ function scale_and_crop($size, $x, $y, $w, $h)
++ {
++
++ $image_s = imagecreatetruecolor($size, $size);
++ $image_a = $this->to_image();
++
++ # Retain alpha channel info if possible for .pngs
++ $background = imagecolorallocate($image_s, 0, 0, 0);
++ ImageColorTransparent($image_s, $background);
++ imagealphablending($image_s, false);
++
++ imagecopyresized($image_s, $image_a, 0, 0, $x, $y, $size, $size, $w, $h);
++
++ $ext = ($this->mediattype == 'image/jpeg') ? ".jpeg" : ".png";
++
++ $filename = common_avatar_filename($this->profile_id, $ext, $size, common_timestamp());
++
++ if ($this->mediatype == 'image/jpeg') {
++ imagejpeg($image_s, common_avatar_path($filename));
++ } else {
++ imagepng($image_s, common_avatar_path($filename));
++ }
++
++ $cropped = DB_DataObject::factory('avatar');
++ $cropped->profile_id = $this->profile_id;
++ $cropped->width = $size;
++ $cropped->height = $size;
++ $cropped->original = false;
++ $cropped->mediatype = ($this->mediattype == 'image/jpeg') ? 'image/jpeg' : 'image/png';
++ $cropped->filename = $filename;
++ $cropped->url = common_avatar_url($filename);
++ $cropped->created = DB_DataObject_Cast::dateTime(); # current time
++
++ if ($cropped->insert()) {
++ return $cropped;
++ } else {
++ return NULL;
++ }
++ }
++
++ function to_image()
++ {
++ $filepath = common_avatar_path($this->filename);
++ if ($this->mediatype == 'image/gif') {
++ return imagecreatefromgif($filepath);
++ } else if ($this->mediatype == 'image/jpeg') {
++ return imagecreatefromjpeg($filepath);
++ } else if ($this->mediatype == 'image/png') {
++ return imagecreatefrompng($filepath);
++ } else {
++ return NULL;
++ }
++ }
++
++ function &pkeyGet($kv)
++ {
++ return Memcached_DataObject::pkeyGet('Avatar', $kv);
++ }
++
+hunk ./classes/Profile.php 124
+- function delete_avatars() {
+- $avatar = new Avatar();
+- $avatar->profile_id = $this->id;
+- $avatar->find();
+- while ($avatar->fetch()) {
+- $avatar->delete();
+- }
+- return true;
+- }
++ function crop_avatars($x, $y, $w, $h)
++ {
++
++ $avatar = $this->getOriginalAvatar();
++ $this->delete_avatars(false); # don't delete original
++
++ foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) {
++ # We don't do a scaled one if original is our scaled size
++ if (!($avatar->width == $size && $avatar->height == $size)) {
++ $s = $avatar->scale_and_crop($size, $x, $y, $w, $h);
++ if (!$s) {
++ return NULL;
++ }
++ }
++ }
++ return true;
++ }
++
++ function delete_avatars($original=true)
++ {
++ $avatar = new Avatar();
++ $avatar->profile_id = $this->id;
++ $avatar->find();
++ while ($avatar->fetch()) {
++ if ($avatar->original) {
++ if ($original == false) {
++ continue;
++ }
++ }
++ $avatar->delete();
++ }
++ return true;
++ }
+hunk ./lib/settingsaction.php 63
+- function form_header($title, $msg=NULL, $success=false) {
+- common_show_header($title,
+- NULL,
+- array($msg, $success),
+- array($this, 'show_top'));
+- }
++ function form_header($title, $msg=NULL, $success=false)
++ {
++ common_show_header($title,
++ array($this, 'show_header'),
++ array($msg, $success),
++ array($this, 'show_top'));
++ }
++
++ function show_header()
++ {
++ common_element('link', array('rel' => 'stylesheet',
++ 'type' => 'text/css',
++ 'href' => common_path('js/jcrop/jquery.Jcrop.css?version='.LACONICA_VERSION),
++ 'media' => 'screen, projection, tv'));
++ common_element('script', array('type' => 'text/javascript',
++ 'src' => common_path('js/jcrop/jquery.Jcrop.pack.js')));
++ common_element('script', array('type' => 'text/javascript',
++ 'src' => common_path('js/jcrop/jquery.Jcrop.go.js')));
++ }
diff --git a/actions/profilesettings.php b/actions/profilesettings.php
index caec2f93d..d861919b9 100644
--- a/actions/profilesettings.php
+++ b/actions/profilesettings.php
@@ -54,13 +54,17 @@ class ProfilesettingsAction extends SettingsAction
return;
}
- if ($this->arg('save')) {
- $this->save_profile();
- } else if ($this->arg('upload')) {
- $this->upload_avatar();
- } else if ($this->arg('changepass')) {
- $this->change_password();
- }
+ if ($this->arg('save')) {
+ $this->save_profile();
+ } else if ($this->arg('upload')) {
+ $this->upload_avatar();
+ } else if ($this->arg('crop')) {
+ $this->crop_avatar();
+ } else if ($this->arg('changepass')) {
+ $this->change_password();
+ } else {
+ $this->show_form(_('Unexpected form submission.'));
+ }
}
@@ -70,31 +74,30 @@ class ProfilesettingsAction extends SettingsAction
$user = common_current_user();
$profile = $user->getProfile();
- common_element_start('form', array('method' => 'POST',
- 'id' => 'profilesettings',
- 'action' =>
- common_local_url('profilesettings')));
- common_hidden('token', common_session_token());
-
- # too much common patterns here... abstractable?
-
- common_input('nickname', _('Nickname'),
- ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
- _('1-64 lowercase letters or numbers, no punctuation or spaces'));
- common_input('fullname', _('Full name'),
- ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
- common_input('homepage', _('Homepage'),
- ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
- _('URL of your homepage, blog, or profile on another site'));
- common_textarea('bio', _('Bio'),
- ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
- _('Describe yourself and your interests in 140 chars'));
- common_input('location', _('Location'),
- ($this->arg('location')) ? $this->arg('location') : $profile->location,
- _('Where you are, like "City, State (or Region), Country"'));
- common_input('tags', _('Tags'),
- ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
- _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
+ common_element_start('form', array('method' => 'POST',
+ 'id' => 'profilesettings',
+ 'action' => common_local_url('profilesettings')));
+ common_hidden('token', common_session_token());
+
+ # too much common patterns here... abstractable?
+
+ common_input('nickname', _('Nickname'),
+ ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
+ _('1-64 lowercase letters or numbers, no punctuation or spaces'));
+ common_input('fullname', _('Full name'),
+ ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
+ common_input('homepage', _('Homepage'),
+ ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
+ _('URL of your homepage, blog, or profile on another site'));
+ common_textarea('bio', _('Bio'),
+ ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
+ _('Describe yourself and your interests in 140 chars'));
+ common_input('location', _('Location'),
+ ($this->arg('location')) ? $this->arg('location') : $profile->location,
+ _('Where you are, like "City, State (or Region), Country"'));
+ common_input('tags', _('Tags'),
+ ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
+ _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
$language = common_language();
common_dropdown('language', _('Language'), get_nice_language_list(), _('Preferred language'), true, $language);
@@ -112,7 +115,6 @@ class ProfilesettingsAction extends SettingsAction
common_element_end('form');
-
}
function show_avatar_form()
@@ -137,24 +139,40 @@ class ProfilesettingsAction extends SettingsAction
common_local_url('profilesettings')));
common_hidden('token', common_session_token());
- if ($original) {
- common_element('img', array('src' => $original->url,
- 'class' => 'avatar original',
- 'width' => $original->width,
- 'height' => $original->height,
- 'alt' => $user->nickname));
- }
+ if ($original) {
+ common_element_start('div', array('id'=>'avatar_original', 'class'=>'avatar_view'));
+ common_element('h3', null, _("Original:"));
+ common_element_start('div', array('id'=>'avatar_original_view'));
+ common_element('img', array('src' => $original->url,
+ 'class' => 'avatar original',
+ 'width' => $original->width,
+ 'height' => $original->height,
+ 'alt' => $user->nickname));
+ common_element_end('div');
+ common_element_end('div');
+ }
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
- if ($avatar) {
- common_element('img', array('src' => $avatar->url,
- 'class' => 'avatar profile',
- 'width' => AVATAR_PROFILE_SIZE,
- 'height' => AVATAR_PROFILE_SIZE,
- 'alt' => $user->nickname));
- }
-
+ if ($avatar) {
+ common_element_start('div', array('id'=>'avatar_preview', 'class'=>'avatar_view'));
+ common_element('h3', null, _("Preview:"));
+ common_element_start('div', array('id'=>'avatar_preview_view'));
+ common_element('img', array('src' => $original->url,//$avatar->url,
+ 'class' => 'avatar profile',
+ 'width' => AVATAR_PROFILE_SIZE,
+ 'height' => AVATAR_PROFILE_SIZE,
+ 'alt' => $user->nickname));
+ common_element_end('div');
+ common_element_end('div');
+
+ foreach(array('avatar_crop_x', 'avatar_crop_y', 'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
+ common_element('input', array('name' => $crop_info,
+ 'type' => 'hidden',
+ 'id' => $crop_info));
+ }
+ common_submit('crop', _('Crop'));
+ }
common_element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden',
@@ -163,7 +181,6 @@ class ProfilesettingsAction extends SettingsAction
common_element_start('p');
-
common_element('input', array('name' => 'avatarfile',
'type' => 'file',
'id' => 'avatarfile'));
@@ -390,8 +407,25 @@ class ProfilesettingsAction extends SettingsAction
$this->show_form(_('Failed updating avatar.'));
}
- @unlink($_FILES['avatarfile']['tmp_name']);
- }
+ @unlink($_FILES['avatarfile']['tmp_name']);
+ }
+
+ function crop_avatar() {
+
+ $user = common_current_user();
+ $profile = $user->getProfile();
+
+ $x = $this->arg('avatar_crop_x');
+ $y = $this->arg('avatar_crop_y');
+ $w = $this->arg('avatar_crop_w');
+ $h = $this->arg('avatar_crop_h');
+
+ if ($profile->crop_avatars($x, $y, $w, $h)) {
+ $this->show_form(_('Avatar updated.'), true);
+ } else {
+ $this->show_form(_('Failed updating avatar.'));
+ }
+ }
function nickname_exists($nickname)
{
diff --git a/classes/Avatar.php b/classes/Avatar.php
index 4fdb99d35..9ae920647 100644
--- a/classes/Avatar.php
+++ b/classes/Avatar.php
@@ -79,20 +79,63 @@ class Avatar extends Memcached_DataObject
}
}
- function to_image() {
- $filepath = common_avatar_path($this->filename);
- if ($this->mediatype == 'image/gif') {
- return imagecreatefromgif($filepath);
- } else if ($this->mediatype == 'image/jpeg') {
- return imagecreatefromjpeg($filepath);
- } else if ($this->mediatype == 'image/png') {
- return imagecreatefrompng($filepath);
- } else {
- return NULL;
- }
- }
-
- function &pkeyGet($kv) {
- return Memcached_DataObject::pkeyGet('Avatar', $kv);
- }
+ function scale_and_crop($size, $x, $y, $w, $h)
+ {
+
+ $image_s = imagecreatetruecolor($size, $size);
+ $image_a = $this->to_image();
+
+ # Retain alpha channel info if possible for .pngs
+ $background = imagecolorallocate($image_s, 0, 0, 0);
+ ImageColorTransparent($image_s, $background);
+ imagealphablending($image_s, false);
+
+ imagecopyresized($image_s, $image_a, 0, 0, $x, $y, $size, $size, $w, $h);
+
+ $ext = ($this->mediattype == 'image/jpeg') ? ".jpeg" : ".png";
+
+ $filename = common_avatar_filename($this->profile_id, $ext, $size, common_timestamp());
+
+ if ($this->mediatype == 'image/jpeg') {
+ imagejpeg($image_s, common_avatar_path($filename));
+ } else {
+ imagepng($image_s, common_avatar_path($filename));
+ }
+
+ $cropped = DB_DataObject::factory('avatar');
+ $cropped->profile_id = $this->profile_id;
+ $cropped->width = $size;
+ $cropped->height = $size;
+ $cropped->original = false;
+ $cropped->mediatype = ($this->mediattype == 'image/jpeg') ? 'image/jpeg' : 'image/png';
+ $cropped->filename = $filename;
+ $cropped->url = common_avatar_url($filename);
+ $cropped->created = DB_DataObject_Cast::dateTime(); # current time
+
+ if ($cropped->insert()) {
+ return $cropped;
+ } else {
+ return NULL;
+ }
+ }
+
+ function to_image()
+ {
+ $filepath = common_avatar_path($this->filename);
+ if ($this->mediatype == 'image/gif') {
+ return imagecreatefromgif($filepath);
+ } else if ($this->mediatype == 'image/jpeg') {
+ return imagecreatefromjpeg($filepath);
+ } else if ($this->mediatype == 'image/png') {
+ return imagecreatefrompng($filepath);
+ } else {
+ return NULL;
+ }
+ }
+
+ function &pkeyGet($kv)
+ {
+ return Memcached_DataObject::pkeyGet('Avatar', $kv);
+ }
+
}
diff --git a/classes/Profile.php b/classes/Profile.php
index 3b6ac1d7f..31bdf71d5 100644
--- a/classes/Profile.php
+++ b/classes/Profile.php
@@ -121,15 +121,39 @@ class Profile extends Memcached_DataObject
return $avatar;
}
- function delete_avatars() {
- $avatar = new Avatar();
- $avatar->profile_id = $this->id;
- $avatar->find();
- while ($avatar->fetch()) {
- $avatar->delete();
- }
- return true;
- }
+ function crop_avatars($x, $y, $w, $h)
+ {
+
+ $avatar = $this->getOriginalAvatar();
+ $this->delete_avatars(false); # don't delete original
+
+ foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) {
+ # We don't do a scaled one if original is our scaled size
+ if (!($avatar->width == $size && $avatar->height == $size)) {
+ $s = $avatar->scale_and_crop($size, $x, $y, $w, $h);
+ if (!$s) {
+ return NULL;
+ }
+ }
+ }
+ return true;
+ }
+
+ function delete_avatars($original=true)
+ {
+ $avatar = new Avatar();
+ $avatar->profile_id = $this->id;
+ $avatar->find();
+ while ($avatar->fetch()) {
+ if ($avatar->original) {
+ if ($original == false) {
+ continue;
+ }
+ }
+ $avatar->delete();
+ }
+ return true;
+ }
function getBestName()
{
diff --git a/lib/settingsaction.php b/lib/settingsaction.php
index 62de39d45..03bac3a93 100644
--- a/lib/settingsaction.php
+++ b/lib/settingsaction.php
@@ -60,12 +60,25 @@ class SettingsAction extends Action
}
}
- function form_header($title, $msg=NULL, $success=false) {
- common_show_header($title,
- NULL,
- array($msg, $success),
- array($this, 'show_top'));
- }
+ function form_header($title, $msg=NULL, $success=false)
+ {
+ common_show_header($title,
+ array($this, 'show_header'),
+ array($msg, $success),
+ array($this, 'show_top'));
+ }
+
+ function show_header()
+ {
+ common_element('link', array('rel' => 'stylesheet',
+ 'type' => 'text/css',
+ 'href' => common_path('js/jcrop/jquery.Jcrop.css?version='.LACONICA_VERSION),
+ 'media' => 'screen, projection, tv'));
+ common_element('script', array('type' => 'text/javascript',
+ 'src' => common_path('js/jcrop/jquery.Jcrop.pack.js')));
+ common_element('script', array('type' => 'text/javascript',
+ 'src' => common_path('js/jcrop/jquery.Jcrop.go.js')));
+ }
function show_top($arr)
{