Remove product literal strings in "pht()", part 5
[phabricator.git] / src / applications / files / engine / PhabricatorS3FileStorageEngine.php
blob443a5a9ddc61d5d58448a81686ea1465e37f991b
1 <?php
3 /**
4 * Amazon S3 file storage engine. This engine scales well but is relatively
5 * high-latency since data has to be pulled off S3.
7 * @task internal Internals
8 */
9 final class PhabricatorS3FileStorageEngine
10 extends PhabricatorFileStorageEngine {
13 /* -( Engine Metadata )---------------------------------------------------- */
16 /**
17 * This engine identifies as `amazon-s3`.
19 public function getEngineIdentifier() {
20 return 'amazon-s3';
23 public function getEnginePriority() {
24 return 100;
27 public function canWriteFiles() {
28 $bucket = PhabricatorEnv::getEnvConfig('storage.s3.bucket');
29 $access_key = PhabricatorEnv::getEnvConfig('amazon-s3.access-key');
30 $secret_key = PhabricatorEnv::getEnvConfig('amazon-s3.secret-key');
31 $endpoint = PhabricatorEnv::getEnvConfig('amazon-s3.endpoint');
32 $region = PhabricatorEnv::getEnvConfig('amazon-s3.region');
34 return (strlen($bucket) &&
35 strlen($access_key) &&
36 strlen($secret_key) &&
37 strlen($endpoint) &&
38 strlen($region));
42 /* -( Managing File Data )------------------------------------------------- */
45 /**
46 * Writes file data into Amazon S3.
48 public function writeFile($data, array $params) {
49 $s3 = $this->newS3API();
51 // Generate a random name for this file. We add some directories to it
52 // (e.g. 'abcdef123456' becomes 'ab/cd/ef123456') to make large numbers of
53 // files more browsable with web/debugging tools like the S3 administration
54 // tool.
55 $seed = Filesystem::readRandomCharacters(20);
56 $parts = array();
57 $parts[] = 'phabricator';
59 $instance_name = PhabricatorEnv::getEnvConfig('cluster.instance');
60 if (strlen($instance_name)) {
61 $parts[] = $instance_name;
64 $parts[] = substr($seed, 0, 2);
65 $parts[] = substr($seed, 2, 2);
66 $parts[] = substr($seed, 4);
68 $name = implode('/', $parts);
70 AphrontWriteGuard::willWrite();
71 $profiler = PhutilServiceProfiler::getInstance();
72 $call_id = $profiler->beginServiceCall(
73 array(
74 'type' => 's3',
75 'method' => 'putObject',
76 ));
78 $s3
79 ->setParametersForPutObject($name, $data)
80 ->resolve();
82 $profiler->endServiceCall($call_id, array());
84 return $name;
88 /**
89 * Load a stored blob from Amazon S3.
91 public function readFile($handle) {
92 $s3 = $this->newS3API();
94 $profiler = PhutilServiceProfiler::getInstance();
95 $call_id = $profiler->beginServiceCall(
96 array(
97 'type' => 's3',
98 'method' => 'getObject',
99 ));
101 $result = $s3
102 ->setParametersForGetObject($handle)
103 ->resolve();
105 $profiler->endServiceCall($call_id, array());
107 return $result;
112 * Delete a blob from Amazon S3.
114 public function deleteFile($handle) {
115 $s3 = $this->newS3API();
117 AphrontWriteGuard::willWrite();
118 $profiler = PhutilServiceProfiler::getInstance();
119 $call_id = $profiler->beginServiceCall(
120 array(
121 'type' => 's3',
122 'method' => 'deleteObject',
126 ->setParametersForDeleteObject($handle)
127 ->resolve();
129 $profiler->endServiceCall($call_id, array());
133 /* -( Internals )---------------------------------------------------------- */
137 * Retrieve the S3 bucket name.
139 * @task internal
141 private function getBucketName() {
142 $bucket = PhabricatorEnv::getEnvConfig('storage.s3.bucket');
143 if (!$bucket) {
144 throw new PhabricatorFileStorageConfigurationException(
145 pht(
146 "No '%s' specified!",
147 'storage.s3.bucket'));
149 return $bucket;
153 * Create a new S3 API object.
155 * @task internal
157 private function newS3API() {
158 $access_key = PhabricatorEnv::getEnvConfig('amazon-s3.access-key');
159 $secret_key = PhabricatorEnv::getEnvConfig('amazon-s3.secret-key');
160 $region = PhabricatorEnv::getEnvConfig('amazon-s3.region');
161 $endpoint = PhabricatorEnv::getEnvConfig('amazon-s3.endpoint');
163 return id(new PhutilAWSS3Future())
164 ->setAccessKey($access_key)
165 ->setSecretKey(new PhutilOpaqueEnvelope($secret_key))
166 ->setRegion($region)
167 ->setEndpoint($endpoint)
168 ->setBucket($this->getBucketName());