Page MenuHomePhabricator

D12826.id30824.diff
No OneTemporary

D12826.id30824.diff

diff --git a/resources/sql/autopatches/20150513.user.cache.1.sql b/resources/sql/autopatches/20150513.user.cache.1.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150513.user.cache.1.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_user.user
+ ADD profileImageCache VARCHAR(255) COLLATE {$COLLATE_TEXT};
diff --git a/src/applications/files/transform/PhabricatorFileImageTransform.php b/src/applications/files/transform/PhabricatorFileImageTransform.php
--- a/src/applications/files/transform/PhabricatorFileImageTransform.php
+++ b/src/applications/files/transform/PhabricatorFileImageTransform.php
@@ -141,14 +141,14 @@
$name = 'default.png';
}
- $name = $this->getTransformKey().'-'.$name;
-
- return PhabricatorFile::newFromFileData(
- $data,
- array(
- 'name' => $name,
- 'canCDN' => true,
- ) + $this->getFileProperties());
+ $defaults = array(
+ 'canCDN' => true,
+ 'name' => $this->getTransformKey().'-'.$name,
+ );
+
+ $properties = $this->getFileProperties() + $defaults;
+
+ return PhabricatorFile::newFromFileData($data, $properties);
}
diff --git a/src/applications/files/transform/PhabricatorFileThumbnailTransform.php b/src/applications/files/transform/PhabricatorFileThumbnailTransform.php
--- a/src/applications/files/transform/PhabricatorFileThumbnailTransform.php
+++ b/src/applications/files/transform/PhabricatorFileThumbnailTransform.php
@@ -48,6 +48,7 @@
switch ($this->key) {
case self::TRANSFORM_PROFILE:
$properties['profile'] = true;
+ $properties['name'] = 'profile';
break;
}
return $properties;
@@ -185,8 +186,8 @@
$scale = $scale_y;
}
- $copy_x = $dst_x / $scale_x;
- $copy_y = $dst_y / $scale_x;
+ $copy_x = $dst_x / $scale;
+ $copy_y = $dst_y / $scale;
if (!$scale_up) {
$copy_x = min($src_x, $copy_x);
diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php
--- a/src/applications/people/query/PhabricatorPeopleQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleQuery.php
@@ -148,26 +148,55 @@
}
if ($this->needProfileImage) {
- $user_profile_file_phids = mpull($users, 'getProfileImagePHID');
- $user_profile_file_phids = array_filter($user_profile_file_phids);
- if ($user_profile_file_phids) {
- $files = id(new PhabricatorFileQuery())
- ->setParentQuery($this)
- ->setViewer($this->getViewer())
- ->withPHIDs($user_profile_file_phids)
- ->execute();
- $files = mpull($files, null, 'getPHID');
- } else {
- $files = array();
- }
+ $rebuild = array();
foreach ($users as $user) {
- $image_phid = $user->getProfileImagePHID();
- if (isset($files[$image_phid])) {
- $profile_image_uri = $files[$image_phid]->getBestURI();
+ $image_uri = $user->getProfileImageCache();
+ if ($image_uri) {
+ // This user has a valid cache, so we don't need to fetch any
+ // data or rebuild anything.
+
+ $user->attachProfileImageURI($image_uri);
+ continue;
+ }
+
+ // This user's cache is invalid or missing, so we're going to rebuild
+ // it.
+ $rebuild[] = $user;
+ }
+
+ if ($rebuild) {
+ $file_phids = mpull($rebuild, 'getProfileImagePHID');
+ $file_phids = array_filter($file_phids);
+
+ if ($file_phids) {
+ // NOTE: We're using the omnipotent user here because older profile
+ // images do not have the 'profile' flag, so they may not be visible
+ // to the executing viewer. At some point, we could migrate to add
+ // this flag and then use the real viewer, or just use the real
+ // viewer after enough time has passed to limit the impact of old
+ // data. The consequence of missing here is that we cache a default
+ // image when a real image exists.
+ $files = id(new PhabricatorFileQuery())
+ ->setParentQuery($this)
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($file_phids)
+ ->execute();
+ $files = mpull($files, null, 'getPHID');
} else {
- $profile_image_uri = PhabricatorUser::getDefaultProfileImageURI();
+ $files = array();
+ }
+
+ foreach ($rebuild as $user) {
+ $image_phid = $user->getProfileImagePHID();
+ if (isset($files[$image_phid])) {
+ $image_uri = $files[$image_phid]->getBestURI();
+ } else {
+ $image_uri = PhabricatorUser::getDefaultProfileImageURI();
+ }
+
+ $user->writeProfileImageCache($image_uri);
+ $user->attachProfileImageURI($image_uri);
}
- $user->attachProfileImageURI($profile_image_uri);
}
}
diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php
--- a/src/applications/people/storage/PhabricatorUser.php
+++ b/src/applications/people/storage/PhabricatorUser.php
@@ -1,6 +1,7 @@
<?php
/**
+ * @task image-cache Profile Image Cache
* @task factors Multi-Factor Authentication
* @task handles Managing Handles
*/
@@ -24,6 +25,7 @@
protected $passwordSalt;
protected $passwordHash;
protected $profileImagePHID;
+ protected $profileImageCache;
protected $timezoneIdentifier = '';
protected $consoleEnabled = 0;
@@ -142,6 +144,7 @@
'isApproved' => 'uint32',
'accountSecret' => 'bytes64',
'isEnrolledInMultiFactor' => 'bool',
+ 'profileImageCache' => 'text255?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
@@ -160,6 +163,9 @@
'columns' => array('isApproved'),
),
),
+ self::CONFIG_NO_MUTATE => array(
+ 'profileImageCache' => true,
+ ),
) + parent::getConfiguration();
}
@@ -721,6 +727,72 @@
}
+/* -( Profile Image Cache )------------------------------------------------ */
+
+
+ /**
+ * Get this user's cached profile image URI.
+ *
+ * @return string|null Cached URI, if a URI is cached.
+ * @task image-cache
+ */
+ public function getProfileImageCache() {
+ $version = $this->getProfileImageVersion();
+
+ $parts = explode(',', $this->profileImageCache, 2);
+ if (count($parts) !== 2) {
+ return null;
+ }
+
+ if ($parts[0] !== $version) {
+ return null;
+ }
+
+ return $parts[1];
+ }
+
+
+ /**
+ * Generate a new cache value for this user's profile image.
+ *
+ * @return string New cache value.
+ * @task image-cache
+ */
+ public function writeProfileImageCache($uri) {
+ $version = $this->getProfileImageVersion();
+ $cache = "{$version},{$uri}";
+
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ queryfx(
+ $this->establishConnection('w'),
+ 'UPDATE %T SET profileImageCache = %s WHERE id = %d',
+ $this->getTableName(),
+ $cache,
+ $this->getID());
+ unset($unguarded);
+ }
+
+
+ /**
+ * Get a version identifier for a user's profile image.
+ *
+ * This version will change if the image changes, or if any of the
+ * environment configuration which goes into generating a URI changes.
+ *
+ * @return string Cache version.
+ * @task image-cache
+ */
+ private function getProfileImageVersion() {
+ $parts = array(
+ PhabricatorEnv::getCDNURI('/'),
+ PhabricatorEnv::getEnvConfig('cluster.instance'),
+ $this->getProfileImagePHID(),
+ );
+ $parts = serialize($parts);
+ return PhabricatorHash::digestForIndex($parts);
+ }
+
+
/* -( Multi-Factor Authentication )---------------------------------------- */

File Metadata

Mime Type
text/plain
Expires
Mar 18 2025, 11:05 PM (5 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7710502
Default Alt Text
D12826.id30824.diff (7 KB)

Event Timeline