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

Store width and height metadata of image files

Summary: Also provide a way to update old files metadata.

Test Plan: Create a revision which includes a image file. Check whether the widht, height metadata exists. Run `scripts/files/manage_files.php metadata --all` to update previously uploaded files.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T2101

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

authored by

Mailson Menezes and committed by
epriestley
712e2220 ae0773b7

+212
+5
resources/sql/patches/20130103.filemetadata.sql
··· 1 + ALTER TABLE {$NAMESPACE}_file.file 2 + ADD metadata LONGTEXT COLLATE utf8_bin NOT NULL; 3 + 4 + UPDATE {$NAMESPACE}_file.file 5 + SET metadata = '{}' WHERE metadata = '';
+1
scripts/files/manage_files.php
··· 18 18 new PhabricatorFilesManagementEnginesWorkflow(), 19 19 new PhabricatorFilesManagementMigrateWorkflow(), 20 20 new PhutilHelpArgumentWorkflow(), 21 + new PhabricatorFilesManagementMetadataWorkflow(), 21 22 ); 22 23 23 24 $args->parseWorkflows($workflows);
+2
src/__phutil_library_map__.php
··· 830 830 'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php', 831 831 'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php', 832 832 'PhabricatorFilesManagementEnginesWorkflow' => 'applications/files/management/PhabricatorFilesManagementEnginesWorkflow.php', 833 + 'PhabricatorFilesManagementMetadataWorkflow' => 'applications/files/management/PhabricatorFilesManagementMetadataWorkflow.php', 833 834 'PhabricatorFilesManagementMigrateWorkflow' => 'applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php', 834 835 'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php', 835 836 'PhabricatorFlag' => 'applications/flag/storage/PhabricatorFlag.php', ··· 2177 2178 'PhabricatorFileUploadController' => 'PhabricatorFileController', 2178 2179 'PhabricatorFileUploadException' => 'Exception', 2179 2180 'PhabricatorFilesManagementEnginesWorkflow' => 'PhabricatorFilesManagementWorkflow', 2181 + 'PhabricatorFilesManagementMetadataWorkflow' => 'PhabricatorFilesManagementWorkflow', 2180 2182 'PhabricatorFilesManagementMigrateWorkflow' => 'PhabricatorFilesManagementWorkflow', 2181 2183 'PhabricatorFilesManagementWorkflow' => 'PhutilArgumentWorkflow', 2182 2184 'PhabricatorFlag' => 'PhabricatorFlagDAO',
+11
src/applications/files/controller/PhabricatorFileInfoController.php
··· 125 125 pht('Handle'), 126 126 phutil_escape_html($file->getStorageHandle())); 127 127 128 + $metadata = $file->getMetadata(); 129 + if (!empty($metadata)) { 130 + $view->addSectionHeader(pht('Metadata')); 131 + 132 + foreach ($metadata as $key => $value) { 133 + $view->addProperty( 134 + PhabricatorFile::getMetadataName($key), 135 + phutil_escape_html($value)); 136 + } 137 + } 138 + 128 139 if ($file->isViewableInBrowser()) { 129 140 130 141 // TODO: Clean this up after Pholio (dark backgrounds, standardization,
+131
src/applications/files/management/PhabricatorFilesManagementMetadataWorkflow.php
··· 1 + <?php 2 + 3 + final class PhabricatorFilesManagementMetadataWorkflow 4 + extends PhabricatorFilesManagementWorkflow { 5 + 6 + public function didConstruct() { 7 + $this 8 + ->setName('metadata') 9 + ->setSynopsis('Update metadata of old files.') 10 + ->setArguments( 11 + array( 12 + array( 13 + 'name' => 'all', 14 + 'help' => 'Update all files.', 15 + ), 16 + array( 17 + 'name' => 'names', 18 + 'wildcard' => true, 19 + 'help' => 'Update the given files.', 20 + ), 21 + array( 22 + 'name' => 'dry-run', 23 + 'help' => 'Show what would be updated.', 24 + ), 25 + ) 26 + ); 27 + } 28 + 29 + public function execute(PhutilArgumentParser $args) { 30 + $console = PhutilConsole::getConsole(); 31 + 32 + if ($args->getArg('all')) { 33 + if ($args->getArg('names')) { 34 + throw new PhutilArgumentUsageException( 35 + "Specify either a list of files or `--all`, but not both."); 36 + } 37 + $iterator = new LiskMigrationIterator(new PhabricatorFile()); 38 + } else if ($args->getArg('names')) { 39 + $iterator = array(); 40 + 41 + foreach ($args->getArg('names') as $name) { 42 + $name = trim($name); 43 + 44 + $id = preg_replace('/^F/i', '', $name); 45 + if (ctype_digit($id)) { 46 + $file = id(new PhabricatorFile())->loadOneWhere( 47 + 'id = %d', 48 + $id); 49 + if (!$file) { 50 + throw new PhutilArgumentUsageException( 51 + "No file exists with id '{$name}'."); 52 + } 53 + } else { 54 + $file = id(new PhabricatorFile())->loadOneWhere( 55 + 'phid = %d', 56 + $name); 57 + if (!$file) { 58 + throw new PhutilArgumentUsageException( 59 + "No file exists with PHID '{$name}'."); 60 + } 61 + } 62 + $iterator[] = $file; 63 + } 64 + } else { 65 + throw new PhutilArgumentUsageException( 66 + "Either specify a list of files to update, or use `--all` ". 67 + "to update all files."); 68 + } 69 + 70 + $is_dry_run = $args->getArg('dry-run'); 71 + 72 + $failed = array(); 73 + 74 + foreach ($iterator as $file) { 75 + $fid = 'F'.$file->getID(); 76 + 77 + if (!$file->isViewableImage()) { 78 + $console->writeOut( 79 + "%s: Not an image file.\n", 80 + $fid); 81 + continue; 82 + } 83 + 84 + $metadata = $file->getMetadata(); 85 + $image_width = idx($metadata, PhabricatorFile::METADATA_IMAGE_WIDTH); 86 + $image_height = idx($metadata, PhabricatorFile::METADATA_IMAGE_HEIGHT); 87 + if ($image_width && $image_height) { 88 + $console->writeOut( 89 + "%s: Already updated\n", 90 + $fid); 91 + continue; 92 + } 93 + 94 + if ($is_dry_run) { 95 + $console->writeOut( 96 + "%s: Would update file (dry run)\n", 97 + $fid); 98 + continue; 99 + } 100 + 101 + $console->writeOut( 102 + "%s: Updating metadata... ", 103 + $fid); 104 + 105 + try { 106 + $file->updateDimensions(); 107 + $console->writeOut("done.\n"); 108 + } catch (Exception $ex) { 109 + $console->writeOut("failed!\n"); 110 + $console->writeErr("%s\n", (string)$ex); 111 + $failed[] = $file; 112 + } 113 + } 114 + 115 + if ($failed) { 116 + $console->writeOut("**Failures!**\n"); 117 + $ids = array(); 118 + foreach ($failed as $file) { 119 + $ids[] = 'F'.$file->getID(); 120 + } 121 + $console->writeOut("%s\n", implode(', ', $ids)); 122 + 123 + return 1; 124 + } else { 125 + $console->writeOut("**Success!**\n"); 126 + return 0; 127 + } 128 + 129 + return 0; 130 + } 131 + }
+58
src/applications/files/storage/PhabricatorFile.php
··· 5 5 6 6 const STORAGE_FORMAT_RAW = 'raw'; 7 7 8 + const METADATA_IMAGE_WIDTH = 'width'; 9 + const METADATA_IMAGE_HEIGHT = 'height'; 10 + 8 11 protected $phid; 9 12 protected $name; 10 13 protected $mimeType; ··· 12 15 protected $authorPHID; 13 16 protected $secretKey; 14 17 protected $contentHash; 18 + protected $metadata = array(); 15 19 16 20 protected $storageEngine; 17 21 protected $storageFormat; ··· 20 24 public function getConfiguration() { 21 25 return array( 22 26 self::CONFIG_AUX_PHID => true, 27 + self::CONFIG_SERIALIZATION => array( 28 + 'metadata' => self::SERIALIZATION_JSON, 29 + ), 23 30 ) + parent::getConfiguration(); 24 31 } 25 32 ··· 194 201 $tmp = new TempFile(); 195 202 Filesystem::writeFile($tmp, $data); 196 203 $file->setMimeType(Filesystem::getMimeType($tmp)); 204 + } 205 + 206 + try { 207 + $file->updateDimensions(false); 208 + } catch (Exception $ex) { 209 + // Do nothing 197 210 } 198 211 199 212 $file->save(); ··· 483 496 484 497 public function generateSecretKey() { 485 498 return Filesystem::readRandomCharacters(20); 499 + } 500 + 501 + public function updateDimensions($save = true) { 502 + if (!$this->isViewableImage()) { 503 + throw new Exception( 504 + "This file is not a viewable image."); 505 + } 506 + 507 + if (!function_exists("imagecreatefromstring")) { 508 + throw new Exception( 509 + "Cannot retrieve image information."); 510 + } 511 + 512 + $data = $this->loadFileData(); 513 + 514 + $img = imagecreatefromstring($data); 515 + if ($img === false) { 516 + throw new Exception( 517 + "Error when decoding image."); 518 + } 519 + 520 + $this->metadata[self::METADATA_IMAGE_WIDTH] = imagesx($img); 521 + $this->metadata[self::METADATA_IMAGE_HEIGHT] = imagesy($img); 522 + 523 + if ($save) { 524 + $this->save(); 525 + } 526 + 527 + return $this; 528 + } 529 + 530 + public static function getMetadataName($metadata) { 531 + switch ($metadata) { 532 + case self::METADATA_IMAGE_WIDTH: 533 + $name = pht('Width'); 534 + break; 535 + case self::METADATA_IMAGE_HEIGHT: 536 + $name = pht('Height'); 537 + break; 538 + default: 539 + $name = ucfirst($metadata); 540 + break; 541 + } 542 + 543 + return $name; 486 544 } 487 545 488 546
+4
src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
··· 1081 1081 'name' => 1082 1082 $this->getPatchPath('20130102.metamtareceivedmailmessageidhash.sql'), 1083 1083 ), 1084 + '20130103.filemetadata.sql' => array( 1085 + 'type' => 'sql', 1086 + 'name' => $this->getPatchPath('20130103.filemetadata.sql'), 1087 + ), 1084 1088 ); 1085 1089 } 1086 1090