@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorFileComposeController
4 extends PhabricatorFileController {
5
6 public function handleRequest(AphrontRequest $request) {
7 $viewer = $request->getViewer();
8
9 $color_map = PhabricatorFilesComposeIconBuiltinFile::getAllColors();
10 $icon_map = $this->getIconMap();
11
12 if ($request->isFormPost()) {
13 $project_phid = $request->getStr('projectPHID');
14 if ($project_phid) {
15 $project = id(new PhabricatorProjectQuery())
16 ->setViewer($viewer)
17 ->withPHIDs(array($project_phid))
18 ->requireCapabilities(
19 array(
20 PhabricatorPolicyCapability::CAN_VIEW,
21 PhabricatorPolicyCapability::CAN_EDIT,
22 ))
23 ->executeOne();
24 if (!$project) {
25 return new Aphront404Response();
26 }
27 }
28
29 $icon = $request->getStr('icon');
30 $color = $request->getStr('color');
31
32 $composer = id(new PhabricatorFilesComposeIconBuiltinFile())
33 ->setIcon($icon)
34 ->setColor($color);
35
36 $data = $composer->loadBuiltinFileData();
37
38 $file = PhabricatorFile::newFromFileData(
39 $data,
40 array(
41 'name' => $composer->getBuiltinDisplayName(),
42 'profile' => true,
43 'canCDN' => true,
44 ));
45
46 if ($project_phid) {
47 $edit_uri = '/project/manage/'.$project->getID().'/';
48
49 $xactions = array();
50 $xactions[] = id(new PhabricatorProjectTransaction())
51 ->setTransactionType(
52 PhabricatorProjectImageTransaction::TRANSACTIONTYPE)
53 ->setNewValue($file->getPHID());
54
55 $editor = id(new PhabricatorProjectTransactionEditor())
56 ->setActor($viewer)
57 ->setContentSourceFromRequest($request)
58 ->setContinueOnMissingFields(true)
59 ->setContinueOnNoEffect(true);
60
61 $editor->applyTransactions($project, $xactions);
62
63 return id(new AphrontRedirectResponse())->setURI($edit_uri);
64 } else {
65 $content = array(
66 'phid' => $file->getPHID(),
67 );
68
69 return id(new AphrontAjaxResponse())->setContent($content);
70 }
71 }
72
73 $value_color = head_key($color_map);
74 $value_icon = head_key($icon_map);
75
76 require_celerity_resource('people-profile-css');
77
78 $buttons = array();
79 foreach ($color_map as $color => $info) {
80 $quip = idx($info, 'quip');
81
82 $buttons[] = javelin_tag(
83 'button',
84 array(
85 'class' => 'button-grey profile-image-button',
86 'sigil' => 'has-tooltip compose-select-color',
87 'style' => 'margin: 0 8px 8px 0',
88 'meta' => array(
89 'color' => $color,
90 'tip' => $quip,
91 ),
92 ),
93 id(new PHUIIconView())
94 ->addClass('compose-background-'.$color));
95 }
96
97
98 $icons = array();
99 foreach ($icon_map as $icon => $spec) {
100 $quip = idx($spec, 'quip');
101
102 $icons[] = javelin_tag(
103 'button',
104 array(
105 'class' => 'button-grey profile-image-button',
106 'sigil' => 'has-tooltip compose-select-icon',
107 'style' => 'margin: 0 8px 8px 0',
108 'meta' => array(
109 'icon' => $icon,
110 'tip' => $quip,
111 ),
112 ),
113 id(new PHUIIconView())
114 ->setIcon($icon)
115 ->addClass('compose-icon-bg'));
116 }
117
118 $dialog_id = celerity_generate_unique_node_id();
119 $color_input_id = celerity_generate_unique_node_id();
120 $icon_input_id = celerity_generate_unique_node_id();
121 $preview_id = celerity_generate_unique_node_id();
122
123 $preview = id(new PHUIIconView())
124 ->setID($preview_id)
125 ->addClass('compose-background-'.$value_color)
126 ->setIcon($value_icon)
127 ->addClass('compose-icon-bg');
128
129 $color_input = javelin_tag(
130 'input',
131 array(
132 'type' => 'hidden',
133 'name' => 'color',
134 'value' => $value_color,
135 'id' => $color_input_id,
136 ));
137
138 $icon_input = javelin_tag(
139 'input',
140 array(
141 'type' => 'hidden',
142 'name' => 'icon',
143 'value' => $value_icon,
144 'id' => $icon_input_id,
145 ));
146
147 Javelin::initBehavior('phabricator-tooltips');
148 Javelin::initBehavior(
149 'icon-composer',
150 array(
151 'dialogID' => $dialog_id,
152 'colorInputID' => $color_input_id,
153 'iconInputID' => $icon_input_id,
154 'previewID' => $preview_id,
155 'defaultColor' => $value_color,
156 'defaultIcon' => $value_icon,
157 ));
158
159 return $this->newDialog()
160 ->setFormID($dialog_id)
161 ->setClass('compose-dialog')
162 ->setTitle(pht('Compose Image'))
163 ->appendChild(
164 phutil_tag(
165 'div',
166 array(
167 'class' => 'compose-header',
168 ),
169 pht('Choose Background Color')))
170 ->appendChild($buttons)
171 ->appendChild(
172 phutil_tag(
173 'div',
174 array(
175 'class' => 'compose-header',
176 ),
177 pht('Choose Icon')))
178 ->appendChild($icons)
179 ->appendChild(
180 phutil_tag(
181 'div',
182 array(
183 'class' => 'compose-header',
184 ),
185 pht('Preview')))
186 ->appendChild($preview)
187 ->appendChild($color_input)
188 ->appendChild($icon_input)
189 ->addCancelButton('/')
190 ->addSubmitButton(pht('Save Image'));
191 }
192
193 private function getIconMap() {
194 $icon_map = PhabricatorFilesComposeIconBuiltinFile::getAllIcons();
195
196 $first = array(
197 'fa-briefcase',
198 'fa-tags',
199 'fa-folder',
200 'fa-group',
201 'fa-bug',
202 'fa-trash-o',
203 'fa-calendar',
204 'fa-flag-checkered',
205 'fa-envelope',
206 'fa-truck',
207 'fa-lock',
208 'fa-umbrella',
209 'fa-cloud',
210 'fa-building',
211 'fa-credit-card',
212 'fa-flask',
213 );
214
215 $icon_map = array_select_keys($icon_map, $first) + $icon_map;
216
217 return $icon_map;
218 }
219
220}