@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
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix JSON encoding of PhutilSafeHTML for browser consumption

Summary:
If you run this code:

json_encode(array('tag' => phutil_tag('div', array())));

...you get this result, because json_encode() does not call toString() on objects:

{"tag":{}}

Instead, convert such objects to their underlying strings. Javelin has support for JX.HTML and for implicit conversion (which is kind of sketchy for other reasons) but it's sort of complicated (only happens on Ajax, not behaviors) and messy (not metadata-based), so ignore it for now.

We'll need to do something similar for serialization to the database. My plan there is just to throw on any objects. The only time we put HTML in the database is cache-related and those tiny number of callsites can manually handle it.

Test Plan: Various ajax things now receive the correct data.

Reviewers: vrana

Reviewed By: vrana

CC: aran

Maniphest Tasks: T2432

Differential Revision: https://secure.phabricator.com/D4684

+31 -3
+11
externals/javelinjs/src/lib/DOM.js
··· 87 87 JX.install('HTML', { 88 88 89 89 construct : function(str) { 90 + if (str instanceof JX.HTML) { 91 + this._content = str._content; 92 + return; 93 + } 94 + 90 95 if (__DEV__) { 96 + if ((typeof str !== 'string') && (!str || !str.match)) { 97 + JX.$E( 98 + 'new JX.HTML(<empty?>): ' + 99 + 'call initializes an HTML object with an empty value.'); 100 + } 101 + 91 102 var tags = ['legend', 'thead', 'tbody', 'tfoot', 'column', 'colgroup', 92 103 'caption', 'tr', 'th', 'td', 'option']; 93 104 var evil_stuff = new RegExp('^\\s*<(' + tags.join('|') + ')\\b', 'i');
+15 -1
src/aphront/response/AphrontResponse.php
··· 54 54 return $this; 55 55 } 56 56 57 - protected function encodeJSONForHTTPResponse(array $object) { 57 + public static function processValueForJSONEncoding(&$value, $key) { 58 + if ($value instanceof PhutilSafeHTML) { 59 + // TODO: Javelin supports implicity conversion of '__html' objects to 60 + // JX.HTML, but only for Ajax responses, not behaviors. Just leave things 61 + // as they are for now (where behaviors treat responses as HTML or plain 62 + // text at their discretion). 63 + $value = $value->getHTMLContent(); 64 + } 65 + } 66 + 67 + public static function encodeJSONForHTTPResponse(array $object) { 68 + 69 + array_walk_recursive( 70 + $object, 71 + array('AphrontResponse', 'processValueForJSONEncoding')); 58 72 59 73 $response = json_encode($object); 60 74
+5 -2
src/infrastructure/celerity/CelerityStaticResourceResponse.php
··· 128 128 public function renderHTMLFooter() { 129 129 $data = array(); 130 130 if ($this->metadata) { 131 - $json_metadata = json_encode($this->metadata); 131 + $json_metadata = AphrontResponse::encodeJSONForHTTPResponse( 132 + $this->metadata); 132 133 $this->metadata = array(); 133 134 } else { 134 135 $json_metadata = '{}'; ··· 164 165 if (!$group) { 165 166 continue; 166 167 } 167 - $onload[] = 'JX.initBehaviors('.json_encode($group).')'; 168 + $group_json = AphrontResponse::encodeJSONForHTTPResponse( 169 + $group); 170 + $onload[] = 'JX.initBehaviors('.$group_json.')'; 168 171 } 169 172 } 170 173