Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34307447
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
18 KB
Subscribers
None
View Options
diff --git a/src/applications/people/cache/PhabricatorUserProfileImageCacheType.php b/src/applications/people/cache/PhabricatorUserProfileImageCacheType.php
index b3f944a3e..e2a535cdd 100644
--- a/src/applications/people/cache/PhabricatorUserProfileImageCacheType.php
+++ b/src/applications/people/cache/PhabricatorUserProfileImageCacheType.php
@@ -1,82 +1,120 @@
<?php
final class PhabricatorUserProfileImageCacheType
extends PhabricatorUserCacheType {
const CACHETYPE = 'user.profile';
const KEY_URI = 'user.profile.image.uri.v1';
public function getAutoloadKeys() {
return array(
self::KEY_URI,
);
}
public function canManageKey($key) {
return ($key === self::KEY_URI);
}
public function getDefaultValue() {
return PhabricatorUser::getDefaultProfileImageURI();
}
public function newValueForUsers($key, array $users) {
$viewer = $this->getViewer();
- $file_phids = mpull($users, 'getProfileImagePHID');
- $file_phids = array_filter($file_phids);
+ $file_phids = array();
+ $generate_users = array();
+ foreach ($users as $user) {
+ $user_phid = $user->getPHID();
+ $custom_phid = $user->getProfileImagePHID();
+ $default_phid = $user->getDefaultProfileImagePHID();
+ $version = $user->getDefaultProfileImageVersion();
+
+ if ($custom_phid) {
+ $file_phids[$user_phid] = $custom_phid;
+ continue;
+ }
+ if ($default_phid) {
+ if ($version == PhabricatorFilesComposeAvatarBuiltinFile::VERSION) {
+ $file_phids[$user_phid] = $default_phid;
+ continue;
+ }
+ }
+ $generate_users[] = $user;
+ }
+
+ // Generate Files for anyone without a default
+ foreach ($generate_users as $generate_user) {
+ $generate_user_phid = $generate_user->getPHID();
+ $generate_username = $generate_user->getUsername();
+ $generate_version = PhabricatorFilesComposeAvatarBuiltinFile::VERSION;
+ $generate_file = id(new PhabricatorFilesComposeAvatarBuiltinFile())
+ ->getUserProfileImageFile($generate_username);
+
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ $generate_user->setDefaultProfileImagePHID($generate_file->getPHID());
+ $generate_user->setDefaultProfileImageVersion($generate_version);
+ $generate_user->save();
+ unset($unguarded);
+
+ $file_phids[$generate_user_phid] = $generate_file->getPHID();
+ }
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
$results = array();
foreach ($users as $user) {
$image_phid = $user->getProfileImagePHID();
+ $default_phid = $user->getDefaultProfileImagePHID();
if (isset($files[$image_phid])) {
$image_uri = $files[$image_phid]->getBestURI();
+ } else if (isset($files[$default_phid])) {
+ $image_uri = $files[$default_phid]->getBestURI();
} else {
$image_uri = PhabricatorUser::getDefaultProfileImageURI();
}
$user_phid = $user->getPHID();
$version = $this->getCacheVersion($user);
$results[$user_phid] = "{$version},{$image_uri}";
}
return $results;
}
public function getValueFromStorage($value) {
$parts = explode(',', $value, 2);
return end($parts);
}
public function shouldValidateRawCacheData() {
return true;
}
public function isRawCacheDataValid(PhabricatorUser $user, $key, $data) {
$parts = explode(',', $data, 2);
$version = reset($parts);
return ($version === $this->getCacheVersion($user));
}
private function getCacheVersion(PhabricatorUser $user) {
$parts = array(
PhabricatorEnv::getCDNURI('/'),
PhabricatorEnv::getEnvConfig('cluster.instance'),
$user->getProfileImagePHID(),
);
$parts = serialize($parts);
return PhabricatorHash::digestForIndex($parts);
}
}
diff --git a/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php b/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php
index 153200312..cff833aa5 100644
--- a/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php
@@ -1,313 +1,292 @@
<?php
final class PhabricatorPeopleProfilePictureController
extends PhabricatorPeopleProfileController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$id = $request->getURIData('id');
$user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withIDs(array($id))
->needProfileImage(true)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$user) {
return new Aphront404Response();
}
$this->setUser($user);
$name = $user->getUserName();
$done_uri = '/p/'.$name.'/';
$supported_formats = PhabricatorFile::getTransformableImageFormats();
$e_file = true;
$errors = array();
- // Verify install has GD extension, otherwise default to avatar.png
- $gd = function_exists('imagecreatefromstring');
-
if ($request->isFormPost()) {
$phid = $request->getStr('phid');
$is_default = false;
if ($phid == PhabricatorPHIDConstants::PHID_VOID) {
- // Compose the builtin unique image
- if ($gd) {
- $file = id(new PhabricatorFilesComposeAvatarBuiltinFile())
- ->getUserProfileImageFile($name);
- } else {
- $phid = null;
- $is_default = true;
- }
-
+ $phid = null;
+ $is_default = true;
} else if ($phid) {
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->executeOne();
} else {
if ($request->getFileExists('picture')) {
$file = PhabricatorFile::newFromPHPUpload(
$_FILES['picture'],
array(
'authorPHID' => $viewer->getPHID(),
'canCDN' => true,
));
} else {
$e_file = pht('Required');
$errors[] = pht(
'You must choose a file when uploading a new profile picture.');
}
}
if (!$errors && !$is_default) {
if (!$file->isTransformableImage()) {
$e_file = pht('Not Supported');
$errors[] = pht(
'This server only supports these image formats: %s.',
implode(', ', $supported_formats));
} else {
$xform = PhabricatorFileTransform::getTransformByKey(
PhabricatorFileThumbnailTransform::TRANSFORM_PROFILE);
$xformed = $xform->executeTransform($file);
}
}
if (!$errors) {
if ($is_default) {
$user->setProfileImagePHID(null);
} else {
$user->setProfileImagePHID($xformed->getPHID());
$xformed->attachToObject($user->getPHID());
}
$user->save();
return id(new AphrontRedirectResponse())->setURI($done_uri);
}
}
$title = pht('Edit Profile Picture');
$form = id(new PHUIFormLayoutView())
->setUser($viewer);
- if ($gd) {
- $unique_default = id(new PhabricatorFilesComposeAvatarBuiltinFile())
- ->getUniqueProfileImage($name);
- $default_image = PhabricatorFile::loadBuiltin(
- $viewer, $unique_default['icon']);
- } else {
- $unique_default = null;
+ $default_image = $user->getDefaultProfileImagePHID();
+ if ($default_image) {
+ $default_image = id(new PhabricatorFileQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($default_image))
+ ->executeOne();
+ }
+
+ if (!$default_image) {
$default_image = PhabricatorFile::loadBuiltin($viewer, 'profile.png');
}
$images = array();
$current = $user->getProfileImagePHID();
$has_current = false;
if ($current) {
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($current))
->execute();
if ($files) {
$file = head($files);
if ($file->isTransformableImage()) {
$has_current = true;
$images[$current] = array(
'uri' => $file->getBestURI(),
'tip' => pht('Current Picture'),
);
}
}
}
$builtins = array(
'user1.png',
'user2.png',
'user3.png',
'user4.png',
'user5.png',
'user6.png',
'user7.png',
'user8.png',
'user9.png',
);
foreach ($builtins as $builtin) {
$file = PhabricatorFile::loadBuiltin($viewer, $builtin);
$images[$file->getPHID()] = array(
'uri' => $file->getBestURI(),
'tip' => pht('Builtin Image'),
);
}
// Try to add external account images for any associated external accounts.
$accounts = id(new PhabricatorExternalAccountQuery())
->setViewer($viewer)
->withUserPHIDs(array($user->getPHID()))
->needImages(true)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
foreach ($accounts as $account) {
$file = $account->getProfileImageFile();
if ($account->getProfileImagePHID() != $file->getPHID()) {
// This is a default image, just skip it.
continue;
}
$provider = PhabricatorAuthProvider::getEnabledProviderByKey(
$account->getProviderKey());
if ($provider) {
$tip = pht('Picture From %s', $provider->getProviderName());
} else {
$tip = pht('Picture From External Account');
}
if ($file->isTransformableImage()) {
$images[$file->getPHID()] = array(
'uri' => $file->getBestURI(),
'tip' => $tip,
);
}
}
- $default_style = array();
- if ($unique_default) {
- $border_color = implode(', ', $unique_default['border']);
- $default_style = array(
- 'background-color: '.$unique_default['color'].';',
- 'border: 4px solid rgba('.$border_color.');',
- 'height: 42px;',
- 'width: 42px',
- );
- }
-
$images[PhabricatorPHIDConstants::PHID_VOID] = array(
'uri' => $default_image->getBestURI(),
'tip' => pht('Default Picture'),
- 'style' => implode(' ', $default_style),
);
require_celerity_resource('people-profile-css');
Javelin::initBehavior('phabricator-tooltips', array());
$buttons = array();
foreach ($images as $phid => $spec) {
$style = null;
if (isset($spec['style'])) {
$style = $spec['style'];
}
$button = javelin_tag(
'button',
array(
'class' => 'grey profile-image-button',
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $spec['tip'],
'size' => 300,
),
),
phutil_tag(
'img',
array(
'height' => 50,
'width' => 50,
'src' => $spec['uri'],
- 'style' => $style,
)));
$button = array(
phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => 'phid',
'value' => $phid,
)),
$button,
);
$button = phabricator_form(
$viewer,
array(
'class' => 'profile-image-form',
'method' => 'POST',
),
$button);
$buttons[] = $button;
}
if ($has_current) {
$form->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Current Picture'))
->setValue(array_shift($buttons)));
}
$form->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Use Picture'))
->setValue($buttons));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($title)
->setFormErrors($errors)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$upload_form = id(new AphrontFormView())
->setUser($viewer)
->setEncType('multipart/form-data')
->appendChild(
id(new AphrontFormFileControl())
->setName('picture')
->setLabel(pht('Upload Picture'))
->setError($e_file)
->setCaption(
pht('Supported formats: %s', implode(', ', $supported_formats))))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($done_uri)
->setValue(pht('Upload Picture')));
$upload_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Upload New Picture'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($upload_form);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Edit Profile Picture'));
$crumbs->setBorder(true);
$nav = $this->getProfileMenu();
$nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE);
$header = $this->buildProfileHeader();
$view = id(new PHUITwoColumnView())
->setHeader($header)
->addClass('project-view-home')
->addClass('project-view-people-home')
->setFooter(array(
$form_box,
$upload_box,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setNavigation($nav)
->appendChild($view);
}
}
diff --git a/src/applications/people/management/PhabricatorPeopleProfileImageWorkflow.php b/src/applications/people/management/PhabricatorPeopleProfileImageWorkflow.php
index 1e594017f..358756cec 100644
--- a/src/applications/people/management/PhabricatorPeopleProfileImageWorkflow.php
+++ b/src/applications/people/management/PhabricatorPeopleProfileImageWorkflow.php
@@ -1,81 +1,87 @@
<?php
final class PhabricatorPeopleProfileImageWorkflow
extends PhabricatorPeopleManagementWorkflow {
protected function didConstruct() {
$this
->setName('profileimage')
->setExamples('**profileimage** --users __username__')
->setSynopsis(pht('Generate default profile images.'))
->setArguments(
array(
array(
'name' => 'all',
'help' => pht(
'Generate default profile images for all users.'),
),
array(
'name' => 'force',
'short' => 'f',
'help' => pht(
'Force a default profile image to be replaced.'),
),
array(
'name' => 'users',
'wildcard' => true,
),
));
}
public function execute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole();
$is_force = $args->getArg('force');
$is_all = $args->getArg('all');
$gd = function_exists('imagecreatefromstring');
if (!$gd) {
throw new PhutilArgumentUsageException(
pht(
'GD is not installed for php-cli. Aborting.'));
}
$iterator = $this->buildIterator($args);
if (!$iterator) {
throw new PhutilArgumentUsageException(
pht(
'Either specify a list of users to update, or use `%s` '.
'to update all users.',
'--all'));
}
$version = PhabricatorFilesComposeAvatarBuiltinFile::VERSION;
foreach ($iterator as $user) {
$username = $user->getUsername();
$default_phid = $user->getDefaultProfileImagePHID();
+ $gen_version = $user->getDefaultProfileImageVersion();
- if ($default_phid == null || $is_force) {
+ $generate = false;
+ if ($gen_version != $version) {
+ $generate = true;
+ }
+
+ if ($default_phid == null || $is_force || $generate) {
$file = id(new PhabricatorFilesComposeAvatarBuiltinFile())
->getUserProfileImageFile($username);
$user->setDefaultProfileImagePHID($file->getPHID());
$user->setDefaultProfileImageVersion($version);
$user->save();
$console->writeOut(
"%s\n",
pht(
'Generating profile image for "%s".',
$username));
} else {
$console->writeOut(
"%s\n",
pht(
'Default profile image "%s" already set for "%s".',
$version,
$username));
}
}
}
}
diff --git a/src/applications/people/storage/PhabricatorUserProfile.php b/src/applications/people/storage/PhabricatorUserProfile.php
index edfa24d78..da447410f 100644
--- a/src/applications/people/storage/PhabricatorUserProfile.php
+++ b/src/applications/people/storage/PhabricatorUserProfile.php
@@ -1,46 +1,48 @@
<?php
final class PhabricatorUserProfile extends PhabricatorUserDAO {
protected $userPHID;
protected $title;
protected $blurb;
protected $profileImagePHID;
protected $icon;
public static function initializeNewProfile(PhabricatorUser $user) {
$default_icon = PhabricatorPeopleIconSet::getDefaultIconKey();
return id(new self())
->setUserPHID($user->getPHID())
- ->setIcon($default_icon);
+ ->setIcon($default_icon)
+ ->setTitle('')
+ ->setBlurb('');
}
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
'title' => 'text255',
'blurb' => 'text',
'profileImagePHID' => 'phid?',
'icon' => 'text32',
),
self::CONFIG_KEY_SCHEMA => array(
'userPHID' => array(
'columns' => array('userPHID'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function getDisplayTitle() {
$title = $this->getTitle();
if (strlen($title)) {
return $title;
}
$icon_key = $this->getIcon();
return PhabricatorPeopleIconSet::getIconName($icon_key);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Dec 28, 11:02 PM (1 d, 21 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
df/f6/1be9a5ec37fbb2abf5972b6ce670
Attached To
rPHAB Phabricator
Event Timeline
Log In to Comment