1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +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:
Mailson Menezes 2013-01-07 09:43:35 -08:00 committed by epriestley
parent ae0773b789
commit 712e22208c
7 changed files with 212 additions and 0 deletions

View 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 = '';

View file

@ -18,6 +18,7 @@ $workflows = array(
new PhabricatorFilesManagementEnginesWorkflow(),
new PhabricatorFilesManagementMigrateWorkflow(),
new PhutilHelpArgumentWorkflow(),
new PhabricatorFilesManagementMetadataWorkflow(),
);
$args->parseWorkflows($workflows);

View file

@ -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',

View file

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

View file

@ -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;
}
}

View file

@ -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 )-------------------------- */

View file

@ -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'),
),
);
}