Select the types of activity you want to include in your feed.
@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
···99final class AphrontRequest {
10101111 // NOTE: These magic request-type parameters are automatically included in
1212- // certain requests (e.g., by phabricator_form(), JX.Request,
1212+ // certain requests (e.g., by phabricator_render_form(), JX.Request,
1313 // JX.Workflow, and ConduitClient) and help us figure out what sort of
1414 // response the client expects.
1515
···1212 public function buildResponseString() {
1313 $failure = new AphrontRequestFailureView();
1414 $failure->setHeader('404 Not Found');
1515- $failure->appendChild(phutil_tag('p', array(), pht(
1616- 'The page you requested was not found.')));
1515+ $failure->appendChild('<p>The page you requested was not found.</p>');
17161817 $view = new PhabricatorStandardPageView();
1918 $view->setTitle('404 Not Found');
+1-1
src/aphront/response/AphrontWebpageResponse.php
···1313 }
14141515 public function buildResponseString() {
1616- return hsprintf('%s', $this->content);
1616+ return $this->content;
1717 }
18181919}
···98989999 $view = new AphrontRequestFailureView();
100100 $view->setHeader(pht('Check Your Email'));
101101- $view->appendChild(phutil_tag('p', array(), pht(
102102- 'An email has been sent with a link you can use to login.')));
101101+ $view->appendChild(
102102+ '<p>'.pht(
103103+ 'An email has been sent with a link you can use to login.'
104104+ ).'</p>');
103105 return $this->buildStandardPageResponse(
104106 $view,
105107 array(
···138140139141 $panel = new AphrontPanelView();
140142 $panel->setWidth(AphrontPanelView::WIDTH_FORM);
141141- $panel->appendChild(phutil_tag('h1', array(), pht(
142142- 'Forgot Password / Email Login')));
143143+ $panel->appendChild('
144144+ <h1>'.pht('Forgot Password / Email Login').'</h1>');
143145 $panel->appendChild($email_auth);
144146 $panel->setNoBackground();
145147
···50505151 $view = new AphrontRequestFailureView();
5252 $view->setHeader(pht('Unable to Login'));
5353- $view->appendChild(phutil_tag('p', array(), pht(
5454- 'The authentication information in the link you clicked is '.
5353+ $view->appendChild(
5454+ '<p>'.pht('The authentication information in the link you clicked is '.
5555 'invalid or out of date. Make sure you are copy-and-pasting the '.
5656 'entire link into your browser. You can try again, or request '.
5757- 'a new email.')));
5858- $view->appendChild(hsprintf(
5757+ 'a new email.').'</p>');
5858+ $view->appendChild(
5959 '<div class="aphront-failure-continue">'.
6060- '<a class="button" href="/login/email/">%s</a>'.
6161- '</div>',
6262- pht('Send Another Email')));
6060+ '<a class="button" href="/login/email/">'.
6161+ pht('Send Another Email').
6262+ '</a>'.
6363+ '</div>');
63646465 return $this->buildStandardPageResponse(
6566 $view,
···1818 $dialog = new AphrontDialogView();
1919 $dialog->setUser($user);
2020 $dialog->setTitle(pht('Really unlink account?'));
2121- $dialog->appendChild(phutil_tag('p', array(), pht(
2222- 'You will not be able to login using this account '.
2323- 'once you unlink it. Continue?')));
2121+ $dialog->appendChild(
2222+ '<p>'.pht('You will not be able to login using this account '.
2323+ 'once you unlink it. Continue?').'</p>');
2424 $dialog->addSubmitButton(pht('Unlink Account'));
2525 $dialog->addCancelButton('/settings/panel/ldap/');
2626
···4646 $dialog = id(new AphrontDialogView())
4747 ->setUser($user)
4848 ->setTitle(pht('Log out of Phabricator?'))
4949- ->appendChild(phutil_tag('p', array(), pht(
5050- 'Are you sure you want to log out?')))
4949+ ->appendChild('<p>'.pht('Are you sure you want to log out?').'</p>')
5150 ->addSubmitButton(pht('Logout'))
5251 ->addCancelButton('/');
5352
···41414242 $error_view = new AphrontRequestFailureView();
4343 $error_view->setHeader(pht('Check Your Email'));
4444- $error_view->appendChild(phutil_tag('p', array(), pht(
4545- 'You must verify your email address to login. You should have a new '.
4444+ $error_view->appendChild(
4545+ '<p>'.
4646+ pht('You must verify your email address to login. You should have a new '.
4647 'email message from Phabricator with verification instructions in your '.
4747- 'inbox (%s).', phutil_tag('strong', array(), $email_address))));
4848- $error_view->appendChild(phutil_tag('p', array(), pht(
4949- 'If you did not receive an email, you can click the button below '.
5050- 'to try sending another one.')));
5151- $error_view->appendChild(hsprintf(
5252- '<div class="aphront-failure-continue">%s</div>',
5353- phabricator_form(
5454- $user,
5555- array(
5656- 'action' => '/login/mustverify/',
5757- 'method' => 'POST',
5858- ),
5959- phutil_tag(
6060- 'button',
4848+ 'inbox (%s).', phutil_tag('strong', array(), $email_address)).
4949+ '</p>');
5050+ $error_view->appendChild(
5151+ '<p>'.
5252+ pht('If you did not receive an email, you can click the button below '.
5353+ 'to try sending another one.').
5454+ '</p>');
5555+ $error_view->appendChild(
5656+ '<div class="aphront-failure-continue">'.
5757+ phabricator_form(
5858+ $user,
6159 array(
6060+ 'action' => '/login/mustverify/',
6161+ 'method' => 'POST',
6262 ),
6363- pht('Send Another Email')))));
6363+ phutil_tag(
6464+ 'button',
6565+ array(
6666+ ),
6767+ pht('Send Another Email'))).
6868+ '</div>');
646965706671 return $this->buildApplicationPage(
···3434 $dialog = new AphrontDialogView();
3535 $dialog->setUser($user);
3636 $dialog->setTitle(pht('Really unlink account?'));
3737- $dialog->appendChild(phutil_tag('p', array(), pht(
3838- 'You will not be able to login using this account '.
3939- 'once you unlink it. Continue?')));
3737+ $dialog->appendChild(
3838+ '<p>'.pht('You will not be able to login using this account '.
3939+ 'once you unlink it. Continue?').'</p>');
4040 $dialog->addSubmitButton(pht('Unlink Account'));
4141 $dialog->addCancelButton($provider->getSettingsPanelURI());
4242
···159159 $item->addClass('hide-unread-count');
160160 }
161161162162- $nav->addCustomBlock($item->render());
162162+ // TODO: [HTML] Clean this up when we clean up HTML stuff in Conpherence.
163163+ $nav->addCustomBlock(phutil_safe_html($item->render()));
163164 }
164165 if (empty($conpherences) || $read) {
165166 $nav->addCustomBlock($this->getNoConpherencesBlock());
···7272 case 'retry':
7373 if ($can_retry) {
7474 $dialog->setTitle('Really retry task?');
7575- $dialog->appendChild(phutil_tag('p', array(), pht(
7676- 'The task will be put back in the queue and executed again.')));
7575+ $dialog->appendChild(
7676+ '<p>The task will be put back in the queue and executed '.
7777+ 'again.</p>');
7778 $dialog->addSubmitButton('Retry Task');
7879 } else {
7980 $dialog->setTitle('Can Not Retry');
8080- $dialog->appendChild(phutil_tag('p', array(), pht(
8181- 'Only archived, unsuccessful tasks can be retried.')));
8181+ $dialog->appendChild(
8282+ '<p>Only archived, unsuccessful tasks can be retried.</p>');
8283 }
8384 break;
8485 case 'cancel':
8586 if ($can_cancel) {
8687 $dialog->setTitle('Really cancel task?');
8787- $dialog->appendChild(phutil_tag('p', array(), pht(
8888- 'The work this task represents will never be performed if you '.
8989- 'cancel it. Are you sure you want to cancel it?')));
8888+ $dialog->appendChild(
8989+ '<p>The work this task represents will never be performed if you '.
9090+ 'cancel it. Are you sure you want to cancel it?</p>');
9091 $dialog->addSubmitButton('Cancel Task');
9192 } else {
9293 $dialog->setTitle('Can Not Cancel');
9393- $dialog->appendChild(phutil_tag('p', array(), pht(
9494- 'Only active tasks can be cancelled.')));
9494+ $dialog->appendChild(
9595+ '<p>Only active tasks can be cancelled.</p>');
9596 }
9697 break;
9798 case 'release':
9899 if ($can_release) {
99100 $dialog->setTitle('Really free task lease?');
100100- $dialog->appendChild(phutil_tag('p', array(), pht(
101101- 'If the process which owns the task lease is still doing work '.
101101+ $dialog->appendChild(
102102+ '<p>If the process which owns the task lease is still doing work '.
102103 'on it, the work may be performed twice. Are you sure you '.
103103- 'want to free the lease?')));
104104+ 'want to free the lease?</p>');
104105 $dialog->addSubmitButton('Free Lease');
105106 } else {
106107 $dialog->setTitle('Can Not Free Lease');
107107- $dialog->appendChild(phutil_tag('p', array(), pht(
108108- 'Only active, leased tasks may have their leases freed.')));
108108+ $dialog->appendChild(
109109+ '<p>Only active, leased tasks may have their leases freed.</p>');
109110 }
110111 break;
111112 default:
···60606161 if (strlen($comment) || $has_inlines) {
6262 $dialog->addSubmitButton(pht('Post as Comment'));
6363- $dialog->appendChild(phutil_tag('br'));
6464- $dialog->appendChild(phutil_tag('p', array(), pht(
6565- 'Do you want to post your feedback anyway, as a normal comment?')));
6363+ $dialog->appendChild('<br />');
6464+ $dialog->appendChild(
6565+ '<p>'.pht('Do you want to post your feedback anyway, as a normal '.
6666+ 'comment?').'</p>');
6667 }
67686869 return id(new AphrontDialogResponse())->setDialog($dialog);
···2525 'href' => PhabricatorEnv::getURI('/D'.$diff->getRevisionID()),
2626 ),
2727 'D'.$diff->getRevisionID());
2828- $top_panel->appendChild(phutil_tag(
2929- 'h1',
3030- array(),
3131- pht('This diff belongs to revision %s', $link)));
2828+ $top_panel->appendChild(
2929+ "<h1>".pht('This diff belongs to revision %s', $link)."</h1>");
3230 } else {
3331 $action_panel = new AphrontPanelView();
3432 $action_panel->setHeader('Preview Diff');
3533 $action_panel->setWidth(AphrontPanelView::WIDTH_WIDE);
3636- $action_panel->appendChild(hsprintf(
3737- '<p class="aphront-panel-instructions">%s</p>',
3838- pht(
3939- 'Review the diff for correctness. When you are satisfied, either '.
4040- '<strong>create a new revision</strong> or <strong>update '.
4141- 'an existing revision</strong>.',
4242- hsprintf(''))));
3434+ $action_panel->appendChild(
3535+ '<p class="aphront-panel-instructions">'.pht('Review the diff for '.
3636+ 'correctness. When you are satisfied, either <strong>create a new '.
3737+ 'revision</strong> or <strong>update an existing revision</strong>.'));
43384439 // TODO: implmenent optgroup support in AphrontFormSelectControl?
4540 $select = array();
···10921092 * indicator of how well tested a change is.
10931093 */
10941094 public function renderModifiedCoverage() {
10951095- $na = phutil_tag('em', array(), '-');
10951095+ $na = '<em>-</em>';
1096109610971097 $coverage = $this->getCoverage();
10981098 if (!$coverage) {
···2424 $dialog = id(new AphrontDialogView())
2525 ->setUser($user)
2626 ->setTitle(pht('Lease Not Active'))
2727- ->appendChild(phutil_tag('p', array(), pht(
2828- 'You can only release "active" leases.')))
2727+ ->appendChild(
2828+ '<p>'.pht('You can only release "active" leases.').'</p>')
2929 ->addCancelButton($lease_uri);
30303131 return id(new AphrontDialogResponse())->setDialog($dialog);
···3535 $dialog = id(new AphrontDialogView())
3636 ->setUser($user)
3737 ->setTitle(pht('Really release lease?'))
3838- ->appendChild(phutil_tag('p', array(), pht(
3939- 'Releasing a lease may cause trouble for the lease holder and '.
4040- 'trigger cleanup of the underlying resource. It can not be '.
4141- 'undone. Continue?')))
3838+ ->appendChild(
3939+ '<p>'.pht(
4040+ 'Releasing a lease may cause trouble for the lease holder and '.
4141+ 'trigger cleanup of the underlying resource. It can not be '.
4242+ 'undone. Continue?').'</p>')
4243 ->addSubmitButton(pht('Release Lease'))
4344 ->addCancelButton($lease_uri);
4445
···2424 $dialog = id(new AphrontDialogView())
2525 ->setUser($user)
2626 ->setTitle(pht('Resource Not Open'))
2727- ->appendChild(phutil_tag('p', array(), pht(
2828- 'You can only close "open" resources.')))
2727+ ->appendChild(
2828+ '<p>'.pht('You can only close "open" resources.').'</p>')
2929 ->addCancelButton($resource_uri);
30303131 return id(new AphrontDialogResponse())->setDialog($dialog);
···3535 $dialog = id(new AphrontDialogView())
3636 ->setUser($user)
3737 ->setTitle(pht('Really close resource?'))
3838- ->appendChild(phutil_tag('p', array(), pht(
3939- 'Closing a resource releases all leases and destroys the '.
4040- 'resource. It can not be undone. Continue?')))
3838+ ->appendChild(
3939+ '<p>'.pht(
4040+ 'Closing a resource releases all leases and destroys the '.
4141+ 'resource. It can not be undone. Continue?').'</p>')
4142 ->addSubmitButton(pht('Close Resource'))
4243 ->addCancelButton($resource_uri);
4344
···2828 $dialog->setUser($user);
29293030 $dialog->setTitle('Excel Export Not Configured');
3131- $dialog->appendChild(hsprintf(
3131+ $dialog->appendChild(
3232 '<p>This system does not have PHPExcel installed. This software '.
3333 'component is required to export tasks to Excel. Have your system '.
3434 'administrator install it from:</p>'.
···3838 '</p>'.
3939 '<br />'.
4040 '<p>Your PHP "include_path" needs to be updated to include the '.
4141- 'PHPExcel Classes/ directory.</p>'));
4141+ 'PHPExcel Classes/ directory.</p>');
42424343 $dialog->addCancelButton('/maniphest/');
4444 return id(new AphrontDialogResponse())->setDialog($dialog);
···5959 $dialog->setUser($user);
60606161 $dialog->setTitle('Export Tasks to Excel');
6262- $dialog->appendChild(phutil_tag('p', array(), pht(
6363- 'Do you want to export the query results to Excel?')));
6262+ $dialog->appendChild(
6363+ '<p>Do you want to export the query results to Excel?</p>');
64646565 $dialog->addCancelButton('/maniphest/');
6666 $dialog->addSubmitButton('Export to Excel');
···143143144144 // display time -- make a nice form for the user to grant the client
145145 // access to the granularity specified by $scope
146146- $title = 'Authorize '.$client->getName().'?';
146146+ $name = phutil_escape_html($client->getName());
147147+ $title = 'Authorize ' . $name . '?';
147148 $panel = new AphrontPanelView();
148149 $panel->setWidth(AphrontPanelView::WIDTH_FORM);
149150 $panel->setHeader($title);
···3737 ->loadOneWhere('phid = %s',
3838 $client_phid);
3939 if ($client) {
4040- $title .= ' for '.$client->getName();
4040+ $client_name = phutil_escape_html($client->getName());
4141+ $title .= ' for '.$client_name;
4142 } else {
4243 // the client does not exist so token is dead already (but
4344 // let's let the user clean this up anyway in that case)
4545+ $client_name = '';
4446 }
45474648 $dialog = new AphrontDialogView();
4749 $dialog->setUser($current_user);
4850 $dialog->setTitle($title);
4949- $dialog->appendChild(phutil_tag('p', array(), pht(
5050- 'Are you sure you want to delete this client authorization?')));
5151+ $dialog->appendChild(
5252+ '<p>Are you sure you want to delete this client authorization?</p>'
5353+ );
5154 $dialog->addSubmitButton();
5255 $dialog->addCancelButton($authorization->getEditURI());
5356 return id(new AphrontDialogResponse())->setDialog($dialog);
···4141 ->appendChild(
4242 pht(
4343 'Really delete the blog "%s"? It will be gone forever.',
4444- $blog->getName()))
4444+ phutil_escape_html($blog->getName())))
4545 ->addSubmitButton(pht('Delete'))
4646 ->addCancelButton($cancel_uri);
4747
···4141 ->appendChild(
4242 pht(
4343 'Really delete the post "%s"? It will be gone forever.',
4444- $post->getTitle()))
4444+ phutil_escape_html($post->getTitle())))
4545 ->addSubmitButton(pht('Delete'))
4646 ->addCancelButton($cancel_uri);
4747
···25252626 $reasons = array();
2727 if (!$post->getBlog()) {
2828- $reasons[] = phutil_tag('p', array(), pht(
2929- 'You can not view the live version of this post because it '.
2828+ $reasons[] =
2929+ '<p>'.pht('You can not view the live version of this post because it '.
3030 'is not associated with a blog. Move the post to a blog in order to '.
3131- 'view it live.'));
3131+ 'view it live.').'</p>';
3232 }
33333434 if ($post->isDraft()) {
3535- $reasons[] = phutil_tag('p', array(), pht(
3636- 'You can not view the live version of this post because it '.
3737- 'is still a draft. Use "Preview/Publish" to publish the post.'));
3535+ $reasons[] =
3636+ '<p>'.pht('You can not view the live version of this post because it '.
3737+ 'is still a draft. Use "Preview/Publish" to publish the post.').'</p>';
3838 }
39394040 if ($reasons) {
···4545 pht(
4646 'The post "%s" will no longer be visible to other users until you '.
4747 'republish it.',
4848- $post->getTitle()))
4848+ phutil_escape_html($post->getTitle())))
4949 ->addSubmitButton(pht('Unpublish'))
5050 ->addCancelButton($cancel_uri);
5151
···123123 }
124124125125 protected function render404Page() {
126126- return hsprintf('<h2>404 Not Found</h2>');
126126+ return '<h2>404 Not Found</h2>';
127127 }
128128129129 final public function getResourceURI($resource) {
···2323 $dialog = new AphrontDialogView();
2424 $dialog->setUser($request->getUser());
2525 $dialog->setTitle('Empty answer');
2626- $dialog->appendChild(phutil_tag('p', array(), pht(
2727- 'Your answer must not be empty.')));
2626+ $dialog->appendChild('<p>Your answer must not be empty.</p>');
2827 $dialog->addCancelButton('/Q'.$question_id);
29283029 return id(new AphrontDialogResponse())->setDialog($dialog);
···3232 $dialog = new AphrontDialogView();
3333 $dialog->setUser($request->getUser());
3434 $dialog->setTitle('Empty comment');
3535- $dialog->appendChild(phutil_tag('p', array(), pht(
3636- 'Your comment must not be empty.')));
3535+ $dialog->appendChild('<p>Your comment must not be empty.</p>');
3736 $dialog->addCancelButton('/Q'.$question_id);
38373938 return id(new AphrontDialogResponse())->setDialog($dialog);
···6262 $dialog = new AphrontDialogView();
6363 $dialog->setUser($user);
6464 $dialog->setTitle(pht('Really leave project?'));
6565- $dialog->appendChild(phutil_tag('p', array(), pht(
6666- 'Your tremendous contributions to this project will be sorely '.
6767- 'missed. Are you sure you want to leave?')));
6565+ $dialog->appendChild(
6666+ '<p>'.
6767+ pht('Your tremendous contributions to this project will be sorely '.
6868+ 'missed. Are you sure you want to leave?').
6969+ '</p>');
6870 $dialog->addCancelButton($project_uri);
6971 $dialog->addSubmitButton(pht('Leave Project'));
7072 break;
···2626 $dialog->setSubmitURI($this->getPanelURI());
2727 $dialog->addSubmitButton('Regenerate');
2828 $dialog->addCancelbutton($this->getPanelURI());
2929- $dialog->appendChild(phutil_tag('p', array(), pht(
3030- 'Really destroy the old certificate? Any established '.
3131- 'sessions will be terminated.')));
2929+ $dialog->appendChild(
3030+ '<p>Really destroy the old certificate? Any established '.
3131+ 'sessions will be terminated.');
32323333 return id(new AphrontDialogResponse())
3434 ->setDialog($dialog);
···103103 }
104104105105 $rows[] = array(
106106- $email->getAddress(),
106106+ phutil_escape_html($email->getAddress()),
107107 $action,
108108 $remove,
109109 );
···191191 ->setUser($user)
192192 ->addHiddenInput('new', 'verify')
193193 ->setTitle('Verification Email Sent')
194194- ->appendChild(phutil_tag('p', array(), pht(
195195- 'A verification email has been sent. Click the link in the '.
196196- 'email to verify your address.')))
194194+ ->appendChild(
195195+ '<p>A verification email has been sent. Click the link in the '.
196196+ 'email to verify your address.</p>')
197197 ->setSubmitURI($uri)
198198 ->addSubmitButton('Done');
199199···264264 ->setUser($user)
265265 ->addHiddenInput('delete', $email_id)
266266 ->setTitle("Really delete address '{$address}'?")
267267- ->appendChild(phutil_tag('p', array(), pht(
268268- 'Are you sure you want to delete this address? You will no '.
269269- 'longer be able to use it to login.')))
267267+ ->appendChild(
268268+ '<p>Are you sure you want to delete this address? You will no '.
269269+ 'longer be able to use it to login.</p>')
270270 ->addSubmitButton('Delete')
271271 ->addCancelButton($uri);
272272
···182182 'href' => $this->getPanelURI('?edit='.$key->getID()),
183183 ),
184184 $key->getName()),
185185- $key->getKeyComment(),
186186- $key->getKeyType(),
185185+ phutil_escape_html($key->getKeyComment()),
186186+ phutil_escape_html($key->getKeyType()),
187187 phabricator_date($key->getDateCreated(), $user),
188188 phabricator_time($key->getDateCreated(), $user),
189189 javelin_tag(
···240240241241 $user = $request->getUser();
242242243243- $name = phutil_tag('strong', array(), $key->getName());
243243+ $name = phutil_escape_html($key->getName());
244244245245 if ($request->isDialogFormPost()) {
246246 $key->delete();
···252252 ->setUser($user)
253253 ->addHiddenInput('delete', $key->getID())
254254 ->setTitle('Really delete SSH Public Key?')
255255- ->appendChild(phutil_tag('p', array(), pht(
256256- 'The key "%s" will be permanently deleted, and you will not longer be '.
257257- 'able to use the corresponding private key to authenticate.',
258258- $name)))
255255+ ->appendChild(
256256+ '<p>The key "<strong>'.$name.'</strong>" will be permanently deleted, '.
257257+ 'and you will not longer be able to use the corresponding private key '.
258258+ 'to authenticate.</p>')
259259 ->addSubmitButton('Delete Public Key')
260260 ->addCancelButton($this->getPanelURI());
261261
···3535 $panel = new AphrontPanelView();
3636 $panel->appendChild($table);
37373838- $panel->appendChild(hsprintf(
3838+ $panel->appendChild(
3939 '<p class="phabricator-ui-example-note">'.
4040 'Use <tt>AphrontPagerView</tt> to render a pager element.'.
4141- '</p>'));
4141+ '</p>');
42424343 $pager = new AphrontPagerView();
4444 $pager->setPageSize($page_size);
···4747 $pager->setURI($request->getRequestURI(), 'offset');
4848 $panel->appendChild($pager);
49495050- $panel->appendChild(hsprintf(
5050+ $panel->appendChild(
5151 '<p class="phabricator-ui-example-note">'.
5252 'You can show more or fewer pages of surrounding context.'.
5353- '</p>'));
5353+ '</p>');
54545555 $many_pages_pager = new AphrontPagerView();
5656 $many_pages_pager->setPageSize($page_size);
···6060 $many_pages_pager->setSurroundingPages(7);
6161 $panel->appendChild($many_pages_pager);
62626363- $panel->appendChild(hsprintf(
6363+ $panel->appendChild(
6464 '<p class="phabricator-ui-example-note">'.
6565 'When it is prohibitively expensive or complex to attain a complete '.
6666 'count of the items, you can select one extra item and set '.
6767 '<tt>hasMorePages(true)</tt> if it exists, creating an inexact pager.'.
6868- '</p>'));
6868+ '</p>');
69697070 $inexact_pager = new AphrontPagerView();
7171 $inexact_pager->setPageSize($page_size);
+14-26
src/docs/developer/rendering_html.diviner
···108108109109If you need to build a list of items with some element in between each of them
110110(like a middot, comma, or vertical bar) you can use
111111-@{function:phutil_implode_html}:
111111+@{function:array_interleave}:
112112113113 // Render links with commas between them.
114114 phutil_tag(
115115 'div',
116116 array(),
117117- phutil_implode_html(', ', $list_of_links));
117117+ array_interleave(', ', $list_of_links));
118118119119= AphrontView Classes =
120120···124124125125 return phutil_tag('div', ...);
126126127127+@{class:AphrontView} subclasses can use `renderHTMLChildren()` and
128128+`renderHTMLView()` to build @{class@libphutil:PhutilSafeHTML} objects from
129129+children or arbitrary lists of components.
130130+131131+@{class:AphrontView} subclasses should avoid `renderChildren()` and
132132+`renderSingleView()` and transition callers to the `HTML` varieties. These older
133133+methods do not return @{class@libphutil:PhutilSafeHTML} objects.
134134+127135= Internationalization: pht() =
128136129137The @{function:pht} function has some special rules. If any input to
···148156you are wrong and the string is not actually safe, you have introduced an XSS
149157vulnerability. Consequently, you should avoid calling this if possible.
150158151151-You can use @{function@libphutil:phutil_escape_html_newlines} to escape HTML
152152-while converting newlines to `<br />`. You should not need to explicitly use
153153-@{function@libphutil:phutil_escape_html} anywhere.
159159+You can use @{function@libphutil:phutil_escape_html} to explicitly escape an
160160+HTML string. You should not normally need to use it.
154161155155-If you need to apply a string function (such as `trim()`) to safe HTML, use
156156-@{method@libphutil:PhutilSafeHTML::applyFunction}.
162162+You can use @{function@libphutil:phutil_escape_html_newlines} to escape HTML
163163+while converting newlines to `<br />`.
157164158165If you need to extract the content of a @{class@libphutil:PhutilSafeHTML}
159166object, you should call `getHTMLContent()`, not cast it to a string. Eventually,
160167we would like to remove the string cast entirely.
161161-162162-Functions @{function@libphutil:phutil_tag} and @{function@libphutil:hsprintf}
163163-are not safe if you pass the user input for the tag or attribute name. All the
164164-following examples are dangerous:
165165-166166- counterexample
167167- phutil_tag($evil);
168168-169169- phutil_tag('span', array($evil => $evil2));
170170-171171- // Use PhutilURI to check if $evil is valid HTTP link.
172172- phutil_tag('a', array('href' => $evil));
173173-174174- phutil_tag('span', array('onmouseover' => $evil));
175175-176176- hsprintf('<%s>%s</%s>', $evil, $evil2, $evil);
177177-178178- // We have a lint rule disallowing this.
179179- hsprintf($evil);
180168181169= Deprecated Functions =
182170
···55 public function buildLinters() {
66 $linters = parent::buildLinters();
7788- foreach ($linters as $linter) {
99- if ($linter instanceof ArcanistPhutilXHPASTLinter) {
1010- $linter->setDeprecatedFunctions(array(
1111- 'phutil_escape_html' =>
1212- 'The phutil_escape_html() function is deprecated. Raw strings '.
1313- 'passed to phutil_tag() or hsprintf() are escaped automatically.',
1414-1515- 'javelin_render_tag' =>
1616- 'The javelin_render_tag() function is deprecated and unsafe. '.
1717- 'Use javelin_tag() instead.',
1818-1919- 'phabricator_render_form' =>
2020- 'The phabricator_render_form() function is deprecated and unsafe. '.
2121- 'Use phabricator_form() instead.',
2222- ));
2323- }
2424- }
2525-268 $paths = $this->getPaths();
2792810 foreach ($paths as $key => $path) {
···13131414 public function apply($text) {
1515 $prefix = $this->getObjectNamePrefix();
1616- return $this->replaceHTML(
1616+ return preg_replace_callback(
1717 "@\B{{$prefix}(\d+)}\B@",
1818 array($this, 'markupObjectHandle'),
1919 $text);
2020 }
21212222- protected function markupObjectHandle($matches) {
2222+ private function markupObjectHandle($matches) {
2323 // TODO: These are single gets but should be okay for now, they're behind
2424 // the cache.
2525 $phid = $this->loadObjectPHID($matches[1]);
···68686969 $layout
7070 ->appendChild($this->renderDataInputs())
7171- ->appendChild($this->renderChildren());
7171+ ->appendChild($this->renderHTMLChildren());
72727373 if (!$this->user) {
7474 throw new Exception('You must pass the user to AphrontFormView.');