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

PhabricatorMemeEngine HA HA HA HA

Summary:
Depends on D19198. Ref T13101. Ref T5258. Pull compositing logic out of the `Controller`.

This is moving toward fixing memes in email.

Test Plan: Used new and old memes. Used API memes.

Maniphest Tasks: T13101, T5258

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

+201 -115
+2
src/__phutil_library_map__.php
··· 3295 3295 'PhabricatorMarkupInterface' => 'infrastructure/markup/PhabricatorMarkupInterface.php', 3296 3296 'PhabricatorMarkupOneOff' => 'infrastructure/markup/PhabricatorMarkupOneOff.php', 3297 3297 'PhabricatorMarkupPreviewController' => 'infrastructure/markup/PhabricatorMarkupPreviewController.php', 3298 + 'PhabricatorMemeEngine' => 'applications/macro/engine/PhabricatorMemeEngine.php', 3298 3299 'PhabricatorMemeRemarkupRule' => 'applications/macro/markup/PhabricatorMemeRemarkupRule.php', 3299 3300 'PhabricatorMentionRemarkupRule' => 'applications/people/markup/PhabricatorMentionRemarkupRule.php', 3300 3301 'PhabricatorMentionableInterface' => 'applications/transactions/interface/PhabricatorMentionableInterface.php', ··· 8893 8894 'PhabricatorMarkupInterface', 8894 8895 ), 8895 8896 'PhabricatorMarkupPreviewController' => 'PhabricatorController', 8897 + 'PhabricatorMemeEngine' => 'Phobject', 8896 8898 'PhabricatorMemeRemarkupRule' => 'PhutilRemarkupRule', 8897 8899 'PhabricatorMentionRemarkupRule' => 'PhutilRemarkupRule', 8898 8900 'PhabricatorMercurialGraphStream' => 'PhabricatorRepositoryGraphStream',
+7 -14
src/applications/macro/conduit/MacroCreateMemeConduitAPIMethod.php
··· 35 35 protected function execute(ConduitAPIRequest $request) { 36 36 $user = $request->getUser(); 37 37 38 - $macro_name = $request->getValue('macroName'); 39 - $upper_text = $request->getValue('upperText'); 40 - $lower_text = $request->getValue('lowerText'); 41 - 42 - $uri = PhabricatorMacroMemeController::generateMacro( 43 - $user, 44 - $macro_name, 45 - $upper_text, 46 - $lower_text); 47 - 48 - if (!$uri) { 49 - throw new ConduitException('ERR-NOT-FOUND'); 50 - } 38 + $file = id(new PhabricatorMemeEngine()) 39 + ->setViewer($user) 40 + ->setTemplate($request->getValue('macroName')) 41 + ->setAboveText($request->getValue('upperText')) 42 + ->setBelowText($request->getValue('lowerText')) 43 + ->newAsset(); 51 44 52 45 return array( 53 - 'uri' => $uri, 46 + 'uri' => $file->getViewURI(), 54 47 ); 55 48 } 56 49
+7 -93
src/applications/macro/controller/PhabricatorMacroMemeController.php
··· 13 13 $lower_text = $request->getStr('lowertext'); 14 14 $viewer = $request->getViewer(); 15 15 16 - $uri = self::generateMacro( 17 - $viewer, 18 - $macro_name, 19 - $upper_text, 20 - $lower_text); 16 + $file = id(new PhabricatorMemeEngine()) 17 + ->setViewer($viewer) 18 + ->setTemplate($macro_name) 19 + ->setAboveText($request->getStr('above')) 20 + ->setBelowText($request->getStr('below')) 21 + ->newAsset(); 21 22 22 23 $content = array( 23 - 'imageURI' => $uri, 24 + 'imageURI' => $file->getViewURI(), 24 25 ); 25 26 26 27 return id(new AphrontAjaxResponse())->setContent($content); 27 28 } 28 29 29 - public static function generateMacro( 30 - PhabricatorUser $viewer, 31 - $macro_name, 32 - $upper_text, 33 - $lower_text) { 34 - 35 - $macro = id(new PhabricatorMacroQuery()) 36 - ->setViewer($viewer) 37 - ->withNames(array($macro_name)) 38 - ->needFiles(true) 39 - ->executeOne(); 40 - if (!$macro) { 41 - return false; 42 - } 43 - $file = $macro->getFile(); 44 - 45 - $upper_text = phutil_utf8_strtoupper($upper_text); 46 - $lower_text = phutil_utf8_strtoupper($lower_text); 47 - 48 - $hash = PhabricatorHash::digestForIndex( 49 - phutil_json_encode( 50 - array( 51 - 'kind' => 'meme', 52 - 'upper' => $upper_text, 53 - 'lower' => $lower_text, 54 - ))); 55 - 56 - $xfile = self::loadTransformedFile($viewer, $file->getPHID(), $hash); 57 - if ($xfile) { 58 - return $xfile->getViewURI(); 59 - } 60 - 61 - $transformer = new PhabricatorImageTransformer(); 62 - 63 - $new_file = $transformer->executeMemeTransform( 64 - $file, 65 - $upper_text, 66 - $lower_text); 67 - 68 - $xfile = id(new PhabricatorTransformedFile()) 69 - ->setOriginalPHID($file->getPHID()) 70 - ->setTransformedPHID($new_file->getPHID()) 71 - ->setTransform($hash); 72 - 73 - try { 74 - $caught = null; 75 - 76 - $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); 77 - try { 78 - $xfile->save(); 79 - } catch (Exception $ex) { 80 - $caught = $ex; 81 - } 82 - unset($unguarded); 83 - 84 - if ($caught) { 85 - throw $caught; 86 - } 87 - 88 - return $new_file->getViewURI(); 89 - } catch (AphrontDuplicateKeyQueryException $ex) { 90 - $xfile = self::loadTransformedFile($viewer, $file->getPHID(), $hash); 91 - if (!$xfile) { 92 - throw $ex; 93 - } 94 - return $xfile->getViewURI(); 95 - } 96 - } 97 - 98 - private static function loadTransformedFile( 99 - PhabricatorUser $viewer, 100 - $file_phid, 101 - $hash) { 102 - 103 - $xform = id(new PhabricatorTransformedFile())->loadOneWhere( 104 - 'originalPHID = %s AND transform = %s', 105 - $file_phid, 106 - $hash); 107 - if (!$xform) { 108 - return null; 109 - } 110 - 111 - return id(new PhabricatorFileQuery()) 112 - ->setViewer($viewer) 113 - ->withPHIDs(array($xform->getTransformedPHID())) 114 - ->executeOne(); 115 - } 116 30 }
+163
src/applications/macro/engine/PhabricatorMemeEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorMemeEngine extends Phobject { 4 + 5 + private $viewer; 6 + private $template; 7 + private $aboveText; 8 + private $belowText; 9 + 10 + private $templateFile; 11 + 12 + public function setViewer(PhabricatorUser $viewer) { 13 + $this->viewer = $viewer; 14 + return $this; 15 + } 16 + 17 + public function getViewer() { 18 + return $this->viewer; 19 + } 20 + 21 + public function setTemplate($template) { 22 + $this->template = $template; 23 + return $this; 24 + } 25 + 26 + public function getTemplate() { 27 + return $this->template; 28 + } 29 + 30 + public function setAboveText($above_text) { 31 + $this->aboveText = $above_text; 32 + return $this; 33 + } 34 + 35 + public function getAboveText() { 36 + return $this->aboveText; 37 + } 38 + 39 + public function setBelowText($below_text) { 40 + $this->belowText = $below_text; 41 + return $this; 42 + } 43 + 44 + public function getBelowText() { 45 + return $this->belowText; 46 + } 47 + 48 + public function getGenerateURI() { 49 + return id(new PhutilURI('/macro/meme/')) 50 + ->alter('macro', $this->getTemplate()) 51 + ->alter('above', $this->getAboveText()) 52 + ->alter('below', $this->getBelowText()); 53 + } 54 + 55 + public function newAsset() { 56 + $cache = $this->loadCachedFile(); 57 + if ($cache) { 58 + return $cache; 59 + } 60 + 61 + $template = $this->loadTemplateFile(); 62 + if (!$template) { 63 + throw new Exception( 64 + pht( 65 + 'Template "%s" is not a valid template.', 66 + $template)); 67 + } 68 + 69 + $hash = $this->newTransformHash(); 70 + 71 + $transformer = new PhabricatorImageTransformer(); 72 + $asset = $transformer->executeMemeTransform( 73 + $template, 74 + $this->getAboveText(), 75 + $this->getBelowText()); 76 + 77 + $xfile = id(new PhabricatorTransformedFile()) 78 + ->setOriginalPHID($template->getPHID()) 79 + ->setTransformedPHID($asset->getPHID()) 80 + ->setTransform($hash); 81 + 82 + try { 83 + $caught = null; 84 + 85 + $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); 86 + try { 87 + $xfile->save(); 88 + } catch (Exception $ex) { 89 + $caught = $ex; 90 + } 91 + unset($unguarded); 92 + 93 + if ($caught) { 94 + throw $caught; 95 + } 96 + 97 + return $asset; 98 + } catch (AphrontDuplicateKeyQueryException $ex) { 99 + $xfile = $this->loadCachedFile(); 100 + if (!$xfile) { 101 + throw $ex; 102 + } 103 + return $xfile; 104 + } 105 + } 106 + 107 + private function newTransformHash() { 108 + $properties = array( 109 + 'kind' => 'meme', 110 + 'above' => phutil_utf8_strtoupper($this->getAboveText()), 111 + 'below' => phutil_utf8_strtoupper($this->getBelowText()), 112 + ); 113 + 114 + $properties = phutil_json_encode($properties); 115 + 116 + return PhabricatorHash::digestForIndex($properties); 117 + } 118 + 119 + public function loadCachedFile() { 120 + $viewer = $this->getViewer(); 121 + 122 + $template_file = $this->loadTemplateFile(); 123 + if (!$template_file) { 124 + return null; 125 + } 126 + 127 + $hash = $this->newTransformHash(); 128 + 129 + $xform = id(new PhabricatorTransformedFile())->loadOneWhere( 130 + 'originalPHID = %s AND transform = %s', 131 + $template_file->getPHID(), 132 + $hash); 133 + if (!$xform) { 134 + return null; 135 + } 136 + 137 + return id(new PhabricatorFileQuery()) 138 + ->setViewer($viewer) 139 + ->withPHIDs(array($xform->getTransformedPHID())) 140 + ->executeOne(); 141 + } 142 + 143 + private function loadTemplateFile() { 144 + if ($this->templateFile === null) { 145 + $viewer = $this->getViewer(); 146 + $template = $this->getTemplate(); 147 + 148 + $macro = id(new PhabricatorMacroQuery()) 149 + ->setViewer($viewer) 150 + ->withNames(array($template)) 151 + ->needFiles(true) 152 + ->executeOne(); 153 + if (!$macro) { 154 + return null; 155 + } 156 + 157 + $this->templateFile = $macro->getFile(); 158 + } 159 + 160 + return $this->templateFile; 161 + } 162 + 163 + }
+22 -8
src/applications/macro/markup/PhabricatorMemeRemarkupRule.php
··· 29 29 $parser = new PhutilSimpleOptions(); 30 30 $options = $parser->parse($matches[1]) + $options; 31 31 32 - $uri = id(new PhutilURI('/macro/meme/')) 33 - ->alter('macro', $options['src']) 34 - ->alter('uppertext', $options['above']) 35 - ->alter('lowertext', $options['below']); 32 + $engine = id(new PhabricatorMemeEngine()) 33 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 34 + ->setTemplate($options['src']) 35 + ->setAboveText($options['above']) 36 + ->setBelowText($options['below']); 37 + 38 + $asset = $engine->loadCachedFile(); 39 + $uri = $engine->getGenerateURI(); 36 40 37 41 if ($this->getEngine()->isHTMLMailMode()) { 38 42 $uri = PhabricatorEnv::getProductionURI($uri); ··· 50 54 $options['above'], 51 55 $options['below']); 52 56 53 - $img = id(new PHUIRemarkupImageView()) 54 - ->setURI($uri) 55 - ->addClass('phabricator-remarkup-macro') 56 - ->setAlt($alt_text); 57 + if ($asset) { 58 + $img = $this->newTag( 59 + 'img', 60 + array( 61 + 'src' => $asset->getViewURI(), 62 + 'class' => 'phabricator-remarkup-macro', 63 + 'alt' => $alt_text, 64 + )); 65 + } else { 66 + $img = id(new PHUIRemarkupImageView()) 67 + ->setURI($uri) 68 + ->addClass('phabricator-remarkup-macro') 69 + ->setAlt($alt_text); 70 + } 57 71 } 58 72 59 73 return $this->getEngine()->storeText($img);