mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +01:00
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
This commit is contained in:
parent
ae0773b789
commit
712e22208c
7 changed files with 212 additions and 0 deletions
5
resources/sql/patches/20130103.filemetadata.sql
Normal file
5
resources/sql/patches/20130103.filemetadata.sql
Normal file
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE {$NAMESPACE}_file.file
|
||||
ADD metadata LONGTEXT COLLATE utf8_bin NOT NULL;
|
||||
|
||||
UPDATE {$NAMESPACE}_file.file
|
||||
SET metadata = '{}' WHERE metadata = '';
|
|
@ -18,6 +18,7 @@ $workflows = array(
|
|||
new PhabricatorFilesManagementEnginesWorkflow(),
|
||||
new PhabricatorFilesManagementMigrateWorkflow(),
|
||||
new PhutilHelpArgumentWorkflow(),
|
||||
new PhabricatorFilesManagementMetadataWorkflow(),
|
||||
);
|
||||
|
||||
$args->parseWorkflows($workflows);
|
||||
|
|
|
@ -830,6 +830,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php',
|
||||
'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php',
|
||||
'PhabricatorFilesManagementEnginesWorkflow' => 'applications/files/management/PhabricatorFilesManagementEnginesWorkflow.php',
|
||||
'PhabricatorFilesManagementMetadataWorkflow' => 'applications/files/management/PhabricatorFilesManagementMetadataWorkflow.php',
|
||||
'PhabricatorFilesManagementMigrateWorkflow' => 'applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php',
|
||||
'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php',
|
||||
'PhabricatorFlag' => 'applications/flag/storage/PhabricatorFlag.php',
|
||||
|
@ -2177,6 +2178,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFileUploadController' => 'PhabricatorFileController',
|
||||
'PhabricatorFileUploadException' => 'Exception',
|
||||
'PhabricatorFilesManagementEnginesWorkflow' => 'PhabricatorFilesManagementWorkflow',
|
||||
'PhabricatorFilesManagementMetadataWorkflow' => 'PhabricatorFilesManagementWorkflow',
|
||||
'PhabricatorFilesManagementMigrateWorkflow' => 'PhabricatorFilesManagementWorkflow',
|
||||
'PhabricatorFilesManagementWorkflow' => 'PhutilArgumentWorkflow',
|
||||
'PhabricatorFlag' => 'PhabricatorFlagDAO',
|
||||
|
|
|
@ -125,6 +125,17 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
|||
pht('Handle'),
|
||||
phutil_escape_html($file->getStorageHandle()));
|
||||
|
||||
$metadata = $file->getMetadata();
|
||||
if (!empty($metadata)) {
|
||||
$view->addSectionHeader(pht('Metadata'));
|
||||
|
||||
foreach ($metadata as $key => $value) {
|
||||
$view->addProperty(
|
||||
PhabricatorFile::getMetadataName($key),
|
||||
phutil_escape_html($value));
|
||||
}
|
||||
}
|
||||
|
||||
if ($file->isViewableInBrowser()) {
|
||||
|
||||
// TODO: Clean this up after Pholio (dark backgrounds, standardization,
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorFilesManagementMetadataWorkflow
|
||||
extends PhabricatorFilesManagementWorkflow {
|
||||
|
||||
public function didConstruct() {
|
||||
$this
|
||||
->setName('metadata')
|
||||
->setSynopsis('Update metadata of old files.')
|
||||
->setArguments(
|
||||
array(
|
||||
array(
|
||||
'name' => 'all',
|
||||
'help' => 'Update all files.',
|
||||
),
|
||||
array(
|
||||
'name' => 'names',
|
||||
'wildcard' => true,
|
||||
'help' => 'Update the given files.',
|
||||
),
|
||||
array(
|
||||
'name' => 'dry-run',
|
||||
'help' => 'Show what would be updated.',
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function execute(PhutilArgumentParser $args) {
|
||||
$console = PhutilConsole::getConsole();
|
||||
|
||||
if ($args->getArg('all')) {
|
||||
if ($args->getArg('names')) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
"Specify either a list of files or `--all`, but not both.");
|
||||
}
|
||||
$iterator = new LiskMigrationIterator(new PhabricatorFile());
|
||||
} else if ($args->getArg('names')) {
|
||||
$iterator = array();
|
||||
|
||||
foreach ($args->getArg('names') as $name) {
|
||||
$name = trim($name);
|
||||
|
||||
$id = preg_replace('/^F/i', '', $name);
|
||||
if (ctype_digit($id)) {
|
||||
$file = id(new PhabricatorFile())->loadOneWhere(
|
||||
'id = %d',
|
||||
$id);
|
||||
if (!$file) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
"No file exists with id '{$name}'.");
|
||||
}
|
||||
} else {
|
||||
$file = id(new PhabricatorFile())->loadOneWhere(
|
||||
'phid = %d',
|
||||
$name);
|
||||
if (!$file) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
"No file exists with PHID '{$name}'.");
|
||||
}
|
||||
}
|
||||
$iterator[] = $file;
|
||||
}
|
||||
} else {
|
||||
throw new PhutilArgumentUsageException(
|
||||
"Either specify a list of files to update, or use `--all` ".
|
||||
"to update all files.");
|
||||
}
|
||||
|
||||
$is_dry_run = $args->getArg('dry-run');
|
||||
|
||||
$failed = array();
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
$fid = 'F'.$file->getID();
|
||||
|
||||
if (!$file->isViewableImage()) {
|
||||
$console->writeOut(
|
||||
"%s: Not an image file.\n",
|
||||
$fid);
|
||||
continue;
|
||||
}
|
||||
|
||||
$metadata = $file->getMetadata();
|
||||
$image_width = idx($metadata, PhabricatorFile::METADATA_IMAGE_WIDTH);
|
||||
$image_height = idx($metadata, PhabricatorFile::METADATA_IMAGE_HEIGHT);
|
||||
if ($image_width && $image_height) {
|
||||
$console->writeOut(
|
||||
"%s: Already updated\n",
|
||||
$fid);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($is_dry_run) {
|
||||
$console->writeOut(
|
||||
"%s: Would update file (dry run)\n",
|
||||
$fid);
|
||||
continue;
|
||||
}
|
||||
|
||||
$console->writeOut(
|
||||
"%s: Updating metadata... ",
|
||||
$fid);
|
||||
|
||||
try {
|
||||
$file->updateDimensions();
|
||||
$console->writeOut("done.\n");
|
||||
} catch (Exception $ex) {
|
||||
$console->writeOut("failed!\n");
|
||||
$console->writeErr("%s\n", (string)$ex);
|
||||
$failed[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
if ($failed) {
|
||||
$console->writeOut("**Failures!**\n");
|
||||
$ids = array();
|
||||
foreach ($failed as $file) {
|
||||
$ids[] = 'F'.$file->getID();
|
||||
}
|
||||
$console->writeOut("%s\n", implode(', ', $ids));
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
$console->writeOut("**Success!**\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,9 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||
|
||||
const STORAGE_FORMAT_RAW = 'raw';
|
||||
|
||||
const METADATA_IMAGE_WIDTH = 'width';
|
||||
const METADATA_IMAGE_HEIGHT = 'height';
|
||||
|
||||
protected $phid;
|
||||
protected $name;
|
||||
protected $mimeType;
|
||||
|
@ -12,6 +15,7 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||
protected $authorPHID;
|
||||
protected $secretKey;
|
||||
protected $contentHash;
|
||||
protected $metadata = array();
|
||||
|
||||
protected $storageEngine;
|
||||
protected $storageFormat;
|
||||
|
@ -20,6 +24,9 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
'metadata' => self::SERIALIZATION_JSON,
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
|
@ -196,6 +203,12 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||
$file->setMimeType(Filesystem::getMimeType($tmp));
|
||||
}
|
||||
|
||||
try {
|
||||
$file->updateDimensions(false);
|
||||
} catch (Exception $ex) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
$file->save();
|
||||
|
||||
return $file;
|
||||
|
@ -485,6 +498,51 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||
return Filesystem::readRandomCharacters(20);
|
||||
}
|
||||
|
||||
public function updateDimensions($save = true) {
|
||||
if (!$this->isViewableImage()) {
|
||||
throw new Exception(
|
||||
"This file is not a viewable image.");
|
||||
}
|
||||
|
||||
if (!function_exists("imagecreatefromstring")) {
|
||||
throw new Exception(
|
||||
"Cannot retrieve image information.");
|
||||
}
|
||||
|
||||
$data = $this->loadFileData();
|
||||
|
||||
$img = imagecreatefromstring($data);
|
||||
if ($img === false) {
|
||||
throw new Exception(
|
||||
"Error when decoding image.");
|
||||
}
|
||||
|
||||
$this->metadata[self::METADATA_IMAGE_WIDTH] = imagesx($img);
|
||||
$this->metadata[self::METADATA_IMAGE_HEIGHT] = imagesy($img);
|
||||
|
||||
if ($save) {
|
||||
$this->save();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function getMetadataName($metadata) {
|
||||
switch ($metadata) {
|
||||
case self::METADATA_IMAGE_WIDTH:
|
||||
$name = pht('Width');
|
||||
break;
|
||||
case self::METADATA_IMAGE_HEIGHT:
|
||||
$name = pht('Height');
|
||||
break;
|
||||
default:
|
||||
$name = ucfirst($metadata);
|
||||
break;
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
|
||||
|
||||
|
|
|
@ -1081,6 +1081,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
|||
'name' =>
|
||||
$this->getPatchPath('20130102.metamtareceivedmailmessageidhash.sql'),
|
||||
),
|
||||
'20130103.filemetadata.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20130103.filemetadata.sql'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue