Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14757644
D15050.id36348.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
30 KB
Referenced Files
None
Subscribers
None
D15050.id36348.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2314,6 +2314,8 @@
'PhabricatorFileinfoSetupCheck' => 'applications/config/check/PhabricatorFileinfoSetupCheck.php',
'PhabricatorFilesApplication' => 'applications/files/application/PhabricatorFilesApplication.php',
'PhabricatorFilesApplicationStorageEnginePanel' => 'applications/files/applicationpanel/PhabricatorFilesApplicationStorageEnginePanel.php',
+ 'PhabricatorFilesBuiltinFile' => 'applications/files/builtin/PhabricatorFilesBuiltinFile.php',
+ 'PhabricatorFilesComposeIconBuiltinFile' => 'applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php',
'PhabricatorFilesConfigOptions' => 'applications/files/config/PhabricatorFilesConfigOptions.php',
'PhabricatorFilesManagementCatWorkflow' => 'applications/files/management/PhabricatorFilesManagementCatWorkflow.php',
'PhabricatorFilesManagementCompactWorkflow' => 'applications/files/management/PhabricatorFilesManagementCompactWorkflow.php',
@@ -2322,6 +2324,7 @@
'PhabricatorFilesManagementPurgeWorkflow' => 'applications/files/management/PhabricatorFilesManagementPurgeWorkflow.php',
'PhabricatorFilesManagementRebuildWorkflow' => 'applications/files/management/PhabricatorFilesManagementRebuildWorkflow.php',
'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php',
+ 'PhabricatorFilesOnDiskBuiltinFile' => 'applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php',
'PhabricatorFilesOutboundRequestAction' => 'applications/files/action/PhabricatorFilesOutboundRequestAction.php',
'PhabricatorFlag' => 'applications/flag/storage/PhabricatorFlag.php',
'PhabricatorFlagAddFlagHeraldAction' => 'applications/flag/herald/PhabricatorFlagAddFlagHeraldAction.php',
@@ -6610,6 +6613,8 @@
'PhabricatorFileinfoSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorFilesApplication' => 'PhabricatorApplication',
'PhabricatorFilesApplicationStorageEnginePanel' => 'PhabricatorApplicationConfigurationPanel',
+ 'PhabricatorFilesBuiltinFile' => 'Phobject',
+ 'PhabricatorFilesComposeIconBuiltinFile' => 'PhabricatorFilesBuiltinFile',
'PhabricatorFilesConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorFilesManagementCatWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementCompactWorkflow' => 'PhabricatorFilesManagementWorkflow',
@@ -6618,6 +6623,7 @@
'PhabricatorFilesManagementPurgeWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementRebuildWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementWorkflow' => 'PhabricatorManagementWorkflow',
+ 'PhabricatorFilesOnDiskBuiltinFile' => 'PhabricatorFilesBuiltinFile',
'PhabricatorFilesOutboundRequestAction' => 'PhabricatorSystemAction',
'PhabricatorFlag' => array(
'PhabricatorFlagDAO',
diff --git a/src/applications/files/builtin/PhabricatorFilesBuiltinFile.php b/src/applications/files/builtin/PhabricatorFilesBuiltinFile.php
new file mode 100644
--- /dev/null
+++ b/src/applications/files/builtin/PhabricatorFilesBuiltinFile.php
@@ -0,0 +1,9 @@
+<?php
+
+abstract class PhabricatorFilesBuiltinFile extends Phobject {
+
+ abstract public function getBuiltinFileKey();
+ abstract public function getBuiltinDisplayName();
+ abstract public function loadBuiltinFileData();
+
+}
diff --git a/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php b/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php
new file mode 100644
--- /dev/null
+++ b/src/applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php
@@ -0,0 +1,235 @@
+<?php
+
+final class PhabricatorFilesComposeIconBuiltinFile
+ extends PhabricatorFilesBuiltinFile {
+
+ private $icon;
+ private $color;
+
+ public function setIcon($icon) {
+ $this->icon = $icon;
+ return $this;
+ }
+
+ public function getIcon() {
+ return $this->icon;
+ }
+
+ public function setColor($color) {
+ $this->color = $color;
+ return $this;
+ }
+
+ public function getColor() {
+ return $this->color;
+ }
+
+ public function getBuiltinFileKey() {
+ $icon = $this->getIcon();
+ $color = $this->getColor();
+ $desc = "compose(icon={$icon}, color={$color})";
+ $hash = PhabricatorHash::digestToLength($desc, 40);
+ return "builtin:{$hash}";
+ }
+
+ public function getBuiltinDisplayName() {
+ $icon = $this->getIcon();
+ $color = $this->getColor();
+ return "{$icon}-{$color}.png";
+ }
+
+ public function loadBuiltinFileData() {
+ return $this->composeImage($this->getColor(), $this->getIcon());
+ }
+
+ public static function getAllIcons() {
+ $root = dirname(phutil_get_library_root('phabricator'));
+ $root = $root.'/resources/sprite/projects_2x/';
+
+ $quips = self::getIconQuips();
+
+ $map = array();
+ $list = Filesystem::listDirectory($root, $include_hidden = false);
+ foreach ($list as $file) {
+ $short = preg_replace('/\.png$/', '', $file);
+
+ $map[$short] = array(
+ 'path' => $root.$file,
+ 'quip' => idx($quips, $short, $short),
+ );
+ }
+
+ return $map;
+ }
+
+ public static function getAllColors() {
+ $colors = id(new CelerityResourceTransformer())
+ ->getCSSVariableMap();
+
+ $colors = array_select_keys(
+ $colors,
+ array(
+ 'red',
+ 'orange',
+ 'yellow',
+ 'green',
+ 'blue',
+ 'sky',
+ 'indigo',
+ 'violet',
+ 'pink',
+ 'charcoal',
+ 'backdrop',
+ ));
+
+ $quips = self::getColorQuips();
+
+ $map = array();
+ foreach ($colors as $name => $color) {
+ $map[$name] = array(
+ 'color' => $color,
+ 'quip' => idx($quips, $name, $name),
+ );
+ }
+
+ return $map;
+ }
+
+ private function composeImage($color, $icon) {
+ $color_map = self::getAllColors();
+ $color = idx($color_map, $color);
+ if (!$color) {
+ $fallback = 'backdrop';
+ $color = idx($color_map, $fallback);
+ if (!$color) {
+ throw new Exception(
+ pht(
+ 'Fallback compose color ("%s") does not exist!',
+ $fallback));
+ }
+ }
+
+ $color_hex = idx($color, 'color');
+ $color_const = hexdec(trim($color_hex, '#'));
+
+ $icon_map = self::getAllIcons();
+ $icon = idx($icon_map, $icon);
+ if (!$icon) {
+ $fallback = 'fa-umbrella';
+ $icon = idx($icon_map, $fallback);
+ if (!$icon) {
+ throw new Exception(
+ pht(
+ 'Fallback compose icon ("%s") does not exist!',
+ $fallback));
+ }
+ }
+
+ $path = idx($icon, 'path');
+ $data = Filesystem::readFile($path);
+
+ $icon_img = imagecreatefromstring($data);
+
+ $canvas = imagecreatetruecolor(100, 100);
+ imagefill($canvas, 0, 0, $color_const);
+ imagecopy($canvas, $icon_img, 0, 0, 0, 0, 100, 100);
+
+ return PhabricatorImageTransformer::saveImageDataInAnyFormat(
+ $canvas,
+ 'image/png');
+ }
+
+ private static function getIconQuips() {
+ return array(
+ '8ball' => pht('Take a Risk'),
+ 'alien' => pht('Foreign Interface'),
+ 'announce' => pht('Louder is Better'),
+ 'art' => pht('Unique Snowflake'),
+ 'award' => pht('Shooting Star'),
+ 'bacon' => pht('Healthy Vegetables'),
+ 'bandaid' => pht('Durable Infrastructure'),
+ 'beer' => pht('Healthy Vegetable Juice'),
+ 'bomb' => pht('Imminent Success'),
+ 'briefcase' => pht('Adventure Pack'),
+ 'bug' => pht('Costumed Egg'),
+ 'calendar' => pht('Everyone Loves Meetings'),
+ 'cloud' => pht('Water Cycle'),
+ 'coffee' => pht('Half-Whip Nonfat Soy Latte'),
+ 'creditcard' => pht('Expense It'),
+ 'death' => pht('Calcium Promotes Bone Health'),
+ 'desktop' => pht('Magical Portal'),
+ 'dropbox' => pht('Cardboard Box'),
+ 'education' => pht('Debt'),
+ 'experimental' => pht('CAUTION: Dangerous Chemicals'),
+ 'facebook' => pht('Popular Social Network'),
+ 'facility' => pht('Pollution Solves Problems'),
+ 'film' => pht('Actual Physical Film'),
+ 'forked' => pht('You Can\'t Eat Soup'),
+ 'games' => pht('Serious Business'),
+ 'ghost' => pht('Haunted'),
+ 'gift' => pht('Surprise!'),
+ 'globe' => pht('Scanner Sweep'),
+ 'golf' => pht('Business Meeting'),
+ 'heart' => pht('Undergoing a Major Surgery'),
+ 'intergalactic' => pht('Jupiter'),
+ 'lock' => pht('Extremely Secret'),
+ 'mail' => pht('Oragami'),
+ 'martini' => pht('Healthy Olive Drink'),
+ 'medical' => pht('Medic!'),
+ 'mobile' => pht('Cellular Telephone'),
+ 'music' => pht("\xE2\x99\xAB"),
+ 'news' => pht('Actual Physical Newspaper'),
+ 'orgchart' => pht('It\'s Good to be King'),
+ 'peoples' => pht('Angel and Devil'),
+ 'piechart' => pht('Actual Physical Pie'),
+ 'poison' => pht('Healthy Bone Juice'),
+ 'putabirdonit' => pht('Put a Bird On It'),
+ 'radiate' => pht('Radiant Beauty'),
+ 'savings' => pht('Oink Oink'),
+ 'search' => pht('Sleuthing'),
+ 'shield' => pht('Royal Crest'),
+ 'speed' => pht('Slow and Steady'),
+ 'sprint' => pht('Fire Exit'),
+ 'star' => pht('The More You Know'),
+ 'storage' => pht('Stack of Pancakes'),
+ 'tablet' => pht('Cellular Telephone For Giants'),
+ 'travel' => pht('Pretty Clearly an Airplane'),
+ 'twitter' => pht('Bird Stencil'),
+ 'warning' => pht('No Caution Required, Everything Looks Safe'),
+ 'whale' => pht('Friendly Walrus'),
+ 'fa-flask' => pht('Experimental'),
+ 'fa-briefcase' => pht('Briefcase'),
+ 'fa-bug' => pht('Bug'),
+ 'fa-building' => pht('Company'),
+ 'fa-calendar' => pht('Deadline'),
+ 'fa-cloud' => pht('The Cloud'),
+ 'fa-credit-card' => pht('Accounting'),
+ 'fa-envelope' => pht('Communication'),
+ 'fa-flag-checkered' => pht('Goal'),
+ 'fa-folder' => pht('Folder'),
+ 'fa-group' => pht('Team'),
+ 'fa-lock' => pht('Policy'),
+ 'fa-tags' => pht('Tag'),
+ 'fa-trash-o' => pht('Garbage'),
+ 'fa-truck' => pht('Release'),
+ 'fa-umbrella' => pht('An Umbrella'),
+ );
+ }
+
+ private static function getColorQuips() {
+ return array(
+ 'red' => pht('Verbillion'),
+ 'orange' => pht('Navel Orange'),
+ 'yellow' => pht('Prim Goldenrod'),
+ 'green' => pht('Lustrous Verdant'),
+ 'blue' => pht('Tropical Deep'),
+ 'sky' => pht('Wide Open Sky'),
+ 'indigo' => pht('Pleated Khaki'),
+ 'violet' => pht('Aged Merlot'),
+ 'pink' => pht('Easter Bunny'),
+ 'charcoal' => pht('Gemstone'),
+ 'backdrop' => pht('Driven Snow'),
+ );
+ }
+
+}
diff --git a/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php b/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php
new file mode 100644
--- /dev/null
+++ b/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php
@@ -0,0 +1,56 @@
+<?php
+
+final class PhabricatorFilesOnDiskBuiltinFile
+ extends PhabricatorFilesBuiltinFile {
+
+ private $name;
+
+ public function setName($name) {
+ $this->name = $name;
+ return $this;
+ }
+
+ public function getName() {
+ if ($this->name === null) {
+ throw new PhutilInvalidStateException('setName');
+ }
+
+ return $this->name;
+ }
+
+ public function getBuiltinDisplayName() {
+ return $this->getName();
+ }
+
+ public function getBuiltinFileKey() {
+ $name = $this->getName();
+ $desc = "disk(name={$name})";
+ $hash = PhabricatorHash::digestToLength($desc, 40);
+ return "builtin:{$hash}";
+ }
+
+ public function loadBuiltinFileData() {
+ $name = $this->getName();
+
+ $available = $this->getAllBuiltinFiles();
+ if (empty($available[$name])) {
+ throw new Exception(pht('Builtin "%s" does not exist!', $name));
+ }
+
+ return Filesystem::readFile($available[$name]);
+ }
+
+ private function getAllBuiltinFiles() {
+ $root = dirname(phutil_get_library_root('phabricator'));
+ $root = $root.'/resources/builtin/';
+
+ $map = array();
+ $list = Filesystem::listDirectory($root, $include_hidden = false);
+ foreach ($list as $file) {
+ $map[$file] = $root.$file;
+ }
+
+ return $map;
+ }
+
+}
diff --git a/src/applications/files/controller/PhabricatorFileComposeController.php b/src/applications/files/controller/PhabricatorFileComposeController.php
--- a/src/applications/files/controller/PhabricatorFileComposeController.php
+++ b/src/applications/files/controller/PhabricatorFileComposeController.php
@@ -6,21 +6,8 @@
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
- $colors = array(
- 'red' => pht('Verbillion'),
- 'orange' => pht('Navel Orange'),
- 'yellow' => pht('Prim Goldenrod'),
- 'green' => pht('Lustrous Verdant'),
- 'blue' => pht('Tropical Deep'),
- 'sky' => pht('Wide Open Sky'),
- 'indigo' => pht('Pleated Khaki'),
- 'violet' => pht('Aged Merlot'),
- 'pink' => pht('Easter Bunny'),
- 'charcoal' => pht('Gemstone'),
- 'backdrop' => pht('Driven Snow'),
- );
-
- $manifest = PHUIIconView::getSheetManifest(PHUIIconView::SPRITE_PROJECTS);
+ $color_map = PhabricatorFilesComposeIconBuiltinFile::getAllColors();
+ $icon_map = $this->getIconMap();
if ($request->isFormPost()) {
$project_phid = $request->getStr('projectPHID');
@@ -37,36 +24,21 @@
if (!$project) {
return new Aphront404Response();
}
- $icon = $project->getIcon();
- $color = $project->getColor();
- switch ($color) {
- case 'grey':
- $color = 'charcoal';
- break;
- case 'checkered':
- $color = 'backdrop';
- break;
- }
- } else {
- $icon = $request->getStr('icon');
- $color = $request->getStr('color');
}
- if (!isset($colors[$color]) || !isset($manifest['projects-'.$icon])) {
- return new Aphront404Response();
- }
-
- $root = dirname(phutil_get_library_root('phabricator'));
- $icon_file = $root.'/resources/sprite/projects_2x/'.$icon.'.png';
- $icon_data = Filesystem::readFile($icon_file);
+ $icon = $request->getStr('icon');
+ $color = $request->getStr('color');
+ $composer = id(new PhabricatorFilesComposeIconBuiltinFile())
+ ->setIcon($icon)
+ ->setColor($color);
- $data = $this->composeImage($color, $icon_data);
+ $data = $composer->loadBuiltinFileData();
$file = PhabricatorFile::buildFromFileDataOrHash(
$data,
array(
- 'name' => 'project.png',
+ 'name' => $composer->getBuiltinDisplayName(),
'profile' => true,
'canCDN' => true,
));
@@ -97,14 +69,15 @@
}
}
- $value_color = head_key($colors);
- $value_icon = head_key($manifest);
- $value_icon = substr($value_icon, strlen('projects-'));
+ $value_color = head_key($color_map);
+ $value_icon = head_key($icon_map);
require_celerity_resource('people-profile-css');
$buttons = array();
- foreach ($colors as $color => $name) {
+ foreach ($color_map as $color => $info) {
+ $quip = idx($info, 'quip');
+
$buttons[] = javelin_tag(
'button',
array(
@@ -113,116 +86,17 @@
'style' => 'margin: 0 8px 8px 0',
'meta' => array(
'color' => $color,
- 'tip' => $name,
+ 'tip' => $quip,
),
),
id(new PHUIIconView())
->addClass('compose-background-'.$color));
}
- $sort_these_first = array(
- 'projects-fa-briefcase',
- 'projects-fa-tags',
- 'projects-fa-folder',
- 'projects-fa-group',
- 'projects-fa-bug',
- 'projects-fa-trash-o',
- 'projects-fa-calendar',
- 'projects-fa-flag-checkered',
- 'projects-fa-envelope',
- 'projects-fa-truck',
- 'projects-fa-lock',
- 'projects-fa-umbrella',
- 'projects-fa-cloud',
- 'projects-fa-building',
- 'projects-fa-credit-card',
- 'projects-fa-flask',
- );
-
- $manifest = array_select_keys(
- $manifest,
- $sort_these_first)
- + $manifest;
$icons = array();
-
- $icon_quips = array(
- '8ball' => pht('Take a Risk'),
- 'alien' => pht('Foreign Interface'),
- 'announce' => pht('Louder is Better'),
- 'art' => pht('Unique Snowflake'),
- 'award' => pht('Shooting Star'),
- 'bacon' => pht('Healthy Vegetables'),
- 'bandaid' => pht('Durable Infrastructure'),
- 'beer' => pht('Healthy Vegetable Juice'),
- 'bomb' => pht('Imminent Success'),
- 'briefcase' => pht('Adventure Pack'),
- 'bug' => pht('Costumed Egg'),
- 'calendar' => pht('Everyone Loves Meetings'),
- 'cloud' => pht('Water Cycle'),
- 'coffee' => pht('Half-Whip Nonfat Soy Latte'),
- 'creditcard' => pht('Expense It'),
- 'death' => pht('Calcium Promotes Bone Health'),
- 'desktop' => pht('Magical Portal'),
- 'dropbox' => pht('Cardboard Box'),
- 'education' => pht('Debt'),
- 'experimental' => pht('CAUTION: Dangerous Chemicals'),
- 'facebook' => pht('Popular Social Network'),
- 'facility' => pht('Pollution Solves Problems'),
- 'film' => pht('Actual Physical Film'),
- 'forked' => pht('You Can\'t Eat Soup'),
- 'games' => pht('Serious Business'),
- 'ghost' => pht('Haunted'),
- 'gift' => pht('Surprise!'),
- 'globe' => pht('Scanner Sweep'),
- 'golf' => pht('Business Meeting'),
- 'heart' => pht('Undergoing a Major Surgery'),
- 'intergalactic' => pht('Jupiter'),
- 'lock' => pht('Extremely Secret'),
- 'mail' => pht('Oragami'),
- 'martini' => pht('Healthy Olive Drink'),
- 'medical' => pht('Medic!'),
- 'mobile' => pht('Cellular Telephone'),
- 'music' => pht("\xE2\x99\xAB"),
- 'news' => pht('Actual Physical Newspaper'),
- 'orgchart' => pht('It\'s Good to be King'),
- 'peoples' => pht('Angel and Devil'),
- 'piechart' => pht('Actual Physical Pie'),
- 'poison' => pht('Healthy Bone Juice'),
- 'putabirdonit' => pht('Put a Bird On It'),
- 'radiate' => pht('Radiant Beauty'),
- 'savings' => pht('Oink Oink'),
- 'search' => pht('Sleuthing'),
- 'shield' => pht('Royal Crest'),
- 'speed' => pht('Slow and Steady'),
- 'sprint' => pht('Fire Exit'),
- 'star' => pht('The More You Know'),
- 'storage' => pht('Stack of Pancakes'),
- 'tablet' => pht('Cellular Telephone For Giants'),
- 'travel' => pht('Pretty Clearly an Airplane'),
- 'twitter' => pht('Bird Stencil'),
- 'warning' => pht('No Caution Required, Everything Looks Safe'),
- 'whale' => pht('Friendly Walrus'),
- 'fa-flask' => pht('Experimental'),
- 'fa-briefcase' => pht('Briefcase'),
- 'fa-bug' => pht('Bug'),
- 'fa-building' => pht('Company'),
- 'fa-calendar' => pht('Deadline'),
- 'fa-cloud' => pht('The Cloud'),
- 'fa-credit-card' => pht('Accounting'),
- 'fa-envelope' => pht('Communication'),
- 'fa-flag-checkered' => pht('Goal'),
- 'fa-folder' => pht('Folder'),
- 'fa-group' => pht('Team'),
- 'fa-lock' => pht('Policy'),
- 'fa-tags' => pht('Tag'),
- 'fa-trash-o' => pht('Garbage'),
- 'fa-truck' => pht('Release'),
- 'fa-umbrella' => pht('An Umbrella'),
- );
-
- foreach ($manifest as $icon => $spec) {
- $icon = substr($icon, strlen('projects-'));
+ foreach ($icon_map as $icon => $spec) {
+ $quip = idx($spec, 'quip');
$icons[] = javelin_tag(
'button',
@@ -232,7 +106,7 @@
'style' => 'margin: 0 8px 8px 0',
'meta' => array(
'icon' => $icon,
- 'tip' => idx($icon_quips, $icon, $icon),
+ 'tip' => $quip,
),
),
id(new PHUIIconView())
@@ -318,23 +192,31 @@
return id(new AphrontDialogResponse())->setDialog($dialog);
}
- private function composeImage($color, $icon_data) {
- $icon_img = imagecreatefromstring($icon_data);
-
- $map = id(new CelerityResourceTransformer())
- ->getCSSVariableMap();
-
- $color_string = idx($map, $color, '#ff00ff');
- $color_const = hexdec(trim($color_string, '#'));
-
- $canvas = imagecreatetruecolor(100, 100);
- imagefill($canvas, 0, 0, $color_const);
+ private function getIconMap() {
+ $icon_map = PhabricatorFilesComposeIconBuiltinFile::getAllIcons();
+
+ $first = array(
+ 'fa-briefcase',
+ 'fa-tags',
+ 'fa-folder',
+ 'fa-group',
+ 'fa-bug',
+ 'fa-trash-o',
+ 'fa-calendar',
+ 'fa-flag-checkered',
+ 'fa-envelope',
+ 'fa-truck',
+ 'fa-lock',
+ 'fa-umbrella',
+ 'fa-cloud',
+ 'fa-building',
+ 'fa-credit-card',
+ 'fa-flask',
+ );
- imagecopy($canvas, $icon_img, 0, 0, 0, 0, 100, 100);
+ $icon_map = array_select_keys($icon_map, $first) + $icon_map;
- return PhabricatorImageTransformer::saveImageDataInAnyFormat(
- $canvas,
- 'image/png');
+ return $icon_map;
}
}
diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php
--- a/src/applications/files/storage/PhabricatorFile.php
+++ b/src/applications/files/storage/PhabricatorFile.php
@@ -961,16 +961,18 @@
* Builtins are located in `resources/builtin/` and identified by their
* name.
*
- * @param PhabricatorUser Viewing user.
- * @param list<string> List of builtin file names.
- * @return dict<string, PhabricatorFile> Dictionary of named builtins.
+ * @param PhabricatorUser Viewing user.
+ * @param list<PhabricatorFilesBuiltinFile> List of builtin file specs.
+ * @return dict<string, PhabricatorFile> Dictionary of named builtins.
*/
- public static function loadBuiltins(PhabricatorUser $user, array $names) {
+ public static function loadBuiltins(PhabricatorUser $user, array $builtins) {
+ $builtins = mpull($builtins, null, 'getBuiltinFileKey');
+
$specs = array();
- foreach ($names as $name) {
+ foreach ($builtins as $key => $buitin) {
$specs[] = array(
'originalPHID' => PhabricatorPHIDConstants::PHID_VOID,
- 'transform' => 'builtin:'.$name,
+ 'transform' => $key,
);
}
@@ -981,41 +983,34 @@
->withTransforms($specs)
->execute();
- $files = mpull($files, null, 'getName');
-
- $root = dirname(phutil_get_library_root('phabricator'));
- $root = $root.'/resources/builtin/';
+ $results = array();
+ foreach ($files as $file) {
+ $builtin_key = $file->getBuiltinName();
+ if ($builtin_key !== null) {
+ $results[$builtin_key] = $file;
+ }
+ }
$build = array();
- foreach ($names as $name) {
- if (isset($files[$name])) {
+ foreach ($builtins as $key => $builtin) {
+ if (isset($results[$key])) {
continue;
}
- // This is just a sanity check to prevent loading arbitrary files.
- if (basename($name) != $name) {
- throw new Exception(pht("Invalid builtin name '%s'!", $name));
- }
-
- $path = $root.$name;
-
- if (!Filesystem::pathExists($path)) {
- throw new Exception(pht("Builtin '%s' does not exist!", $path));
- }
+ $data = $builtin->loadBuiltinFileData();
- $data = Filesystem::readFile($path);
$params = array(
- 'name' => $name,
+ 'name' => $builtin->getBuiltinDisplayName(),
'ttl' => time() + (60 * 60 * 24 * 7),
'canCDN' => true,
- 'builtin' => $name,
+ 'builtin' => $key,
);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$file = self::newFromFileData($data, $params);
$xform = id(new PhabricatorTransformedFile())
->setOriginalPHID(PhabricatorPHIDConstants::PHID_VOID)
- ->setTransform('builtin:'.$name)
+ ->setTransform($key)
->setTransformedPHID($file->getPHID())
->save();
unset($unguarded);
@@ -1023,10 +1018,10 @@
$file->attachObjectPHIDs(array());
$file->attachObjects(array());
- $files[$name] = $file;
+ $results[$key] = $file;
}
- return $files;
+ return $results;
}
@@ -1038,7 +1033,12 @@
* @return PhabricatorFile Corresponding builtin file.
*/
public static function loadBuiltin(PhabricatorUser $user, $name) {
- return idx(self::loadBuiltins($user, array($name)), $name);
+ $builtin = id(new PhabricatorFilesOnDiskBuiltinFile())
+ ->setName($name);
+
+ $key = $builtin->getBuiltinFileKey();
+
+ return idx(self::loadBuiltins($user, array($builtin)), $key);
}
public function getObjects() {
diff --git a/src/applications/pholio/view/PholioMockImagesView.php b/src/applications/pholio/view/PholioMockImagesView.php
--- a/src/applications/pholio/view/PholioMockImagesView.php
+++ b/src/applications/pholio/view/PholioMockImagesView.php
@@ -68,11 +68,9 @@
// TODO: We could maybe do a better job with tailoring this, which is the
// image shown on the review stage.
- $default_name = 'image-100x100.png';
- $builtins = PhabricatorFile::loadBuiltins(
- $this->getUser(),
- array($default_name));
- $default = $builtins[$default_name];
+ $viewer = $this->getUser();
+
+ $default = PhabricatorFile::loadBuiltin($viewer, 'image-100x100.png');
$engine = id(new PhabricatorMarkupEngine())
->setViewer($this->getUser());
diff --git a/src/applications/project/controller/PhabricatorProjectEditPictureController.php b/src/applications/project/controller/PhabricatorProjectEditPictureController.php
--- a/src/applications/project/controller/PhabricatorProjectEditPictureController.php
+++ b/src/applications/project/controller/PhabricatorProjectEditPictureController.php
@@ -123,7 +123,7 @@
$images[PhabricatorPHIDConstants::PHID_VOID] = array(
'uri' => $default_image->getBestURI(),
- 'tip' => pht('Default Picture'),
+ 'tip' => pht('No Picture'),
);
require_celerity_resource('people-profile-css');
@@ -181,7 +181,11 @@
$form->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Use Picture'))
- ->setValue($buttons));
+ ->setValue(
+ array(
+ $this->renderDefaultForm($project),
+ $buttons,
+ )));
$launch_id = celerity_generate_unique_node_id();
$input_id = celerity_generate_unique_node_id();
@@ -226,38 +230,6 @@
->setLabel(pht('Quick Create'))
->setValue($compose_form));
- $default_button = javelin_tag(
- 'button',
- array(
- 'class' => 'grey',
- ),
- pht('Use Project Icon'));
-
- $default_input = javelin_tag(
- 'input',
- array(
- 'type' => 'hidden',
- 'name' => 'projectPHID',
- 'value' => $project->getPHID(),
- ));
-
- $default_form = phabricator_form(
- $viewer,
- array(
- 'class' => 'profile-image-form',
- 'method' => 'POST',
- 'action' => '/file/compose/',
- ),
- array(
- $default_input,
- $default_button,
- ));
-
- $form->appendChild(
- id(new AphrontFormMarkupControl())
- ->setLabel(pht('Use Default'))
- ->setValue($default_form));
-
$upload_form = id(new AphrontFormView())
->setUser($viewer)
->setEncType('multipart/form-data')
@@ -294,4 +266,69 @@
$upload_box,
));
}
+
+ private function renderDefaultForm(PhabricatorProject $project) {
+ $viewer = $this->getViewer();
+ $compose_color = $project->getDisplayIconComposeColor();
+ $compose_icon = $project->getDisplayIconComposeIcon();
+
+ $default_builtin = id(new PhabricatorFilesComposeIconBuiltinFile())
+ ->setColor($compose_color)
+ ->setIcon($compose_icon);
+
+ $file_builtins = PhabricatorFile::loadBuiltins(
+ $viewer,
+ array($default_builtin));
+
+ $file_builtin = head($file_builtins);
+
+ $default_button = javelin_tag(
+ 'button',
+ array(
+ 'class' => 'grey profile-image-button',
+ 'sigil' => 'has-tooltip',
+ 'meta' => array(
+ 'tip' => pht('Use Icon and Color'),
+ 'size' => 300,
+ ),
+ ),
+ phutil_tag(
+ 'img',
+ array(
+ 'height' => 50,
+ 'width' => 50,
+ 'src' => $file_builtin->getBestURI(),
+ )));
+
+ $inputs = array(
+ 'projectPHID' => $project->getPHID(),
+ 'icon' => $compose_icon,
+ 'color' => $compose_color,
+ );
+
+ foreach ($inputs as $key => $value) {
+ $inputs[$key] = javelin_tag(
+ 'input',
+ array(
+ 'type' => 'hidden',
+ 'name' => $key,
+ 'value' => $value,
+ ));
+ }
+
+ $default_form = phabricator_form(
+ $viewer,
+ array(
+ 'class' => 'profile-image-form',
+ 'method' => 'POST',
+ 'action' => '/file/compose/',
+ ),
+ array(
+ $inputs,
+ $default_button,
+ ));
+
+ return $default_form;
+ }
+
}
diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
--- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
@@ -713,6 +713,10 @@
}
}
+ if ($this->getIsNewObject()) {
+ $this->setDefaultProfilePicture($object);
+ }
+
// TODO: We should dump an informational transaction onto the parent
// project to show that we created the sub-thing.
@@ -886,5 +890,31 @@
return $results;
}
+ private function setDefaultProfilePicture(PhabricatorProject $project) {
+ if ($project->isMilestone()) {
+ return;
+ }
+
+ $compose_color = $project->getDisplayIconComposeColor();
+ $compose_icon = $project->getDisplayIconComposeIcon();
+
+ $builtin = id(new PhabricatorFilesComposeIconBuiltinFile())
+ ->setColor($compose_color)
+ ->setIcon($compose_icon);
+
+ $data = $builtin->loadBuiltinFileData();
+
+ $file = PhabricatorFile::newFromFileData(
+ $data,
+ array(
+ 'name' => $builtin->getBuiltinDisplayName(),
+ 'profile' => true,
+ 'canCDN' => true,
+ ));
+
+ $project
+ ->setProfileImagePHID($file->getPHID())
+ ->save();
+ }
}
diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php
--- a/src/applications/project/storage/PhabricatorProject.php
+++ b/src/applications/project/storage/PhabricatorProject.php
@@ -519,6 +519,23 @@
return $this->getColor();
}
+ public function getDisplayIconComposeIcon() {
+ $icon = $this->getDisplayIconIcon();
+ return $icon;
+ }
+
+ public function getDisplayIconComposeColor() {
+ $color = $this->getDisplayColor();
+
+ $map = array(
+ 'grey' => 'charcoal',
+ 'checkered' => 'backdrop',
+ );
+
+ return idx($map, $color, $color);
+ }
+
+
/* -( PhabricatorSubscribableInterface )----------------------------------- */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 23, 2:25 AM (18 h, 39 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7035332
Default Alt Text
D15050.id36348.diff (30 KB)
Attached To
Mode
D15050: Update project profile image composer for new IconSet code
Attached
Detach File
Event Timeline
Log In to Comment