Remove all "FileHasObject" edge reads and writes
[phabricator.git] / src / applications / files / conduit / FileAllocateConduitAPIMethod.php
blobc831eb2afee0393d64f6edacc008a7f5adb1812b
1 <?php
3 final class FileAllocateConduitAPIMethod
4 extends FileConduitAPIMethod {
6 public function getAPIMethodName() {
7 return 'file.allocate';
10 public function getMethodDescription() {
11 return pht('Prepare to upload a file.');
14 protected function defineParamTypes() {
15 return array(
16 'name' => 'string',
17 'contentLength' => 'int',
18 'contentHash' => 'optional string',
19 'viewPolicy' => 'optional string',
20 'deleteAfterEpoch' => 'optional int',
24 protected function defineReturnType() {
25 return 'map<string, wild>';
28 protected function execute(ConduitAPIRequest $request) {
29 $viewer = $request->getUser();
31 $hash = $request->getValue('contentHash');
32 $name = $request->getValue('name');
33 $view_policy = $request->getValue('viewPolicy');
34 $length = $request->getValue('contentLength');
36 $properties = array(
37 'name' => $name,
38 'authorPHID' => $viewer->getPHID(),
39 'isExplicitUpload' => true,
42 if ($view_policy !== null) {
43 $properties['viewPolicy'] = $view_policy;
46 $ttl = $request->getValue('deleteAfterEpoch');
47 if ($ttl) {
48 $properties['ttl.absolute'] = $ttl;
51 $file = null;
52 if ($hash !== null) {
53 $file = PhabricatorFile::newFileFromContentHash(
54 $hash,
55 $properties);
58 if ($hash !== null && !$file) {
59 $chunked_hash = PhabricatorChunkedFileStorageEngine::getChunkedHash(
60 $viewer,
61 $hash);
62 $file = id(new PhabricatorFileQuery())
63 ->setViewer($viewer)
64 ->withContentHashes(array($chunked_hash))
65 ->executeOne();
68 if (strlen($name) && !$hash && !$file) {
69 if ($length > PhabricatorFileStorageEngine::getChunkThreshold()) {
70 // If we don't have a hash, but this file is large enough to store in
71 // chunks and thus may be resumable, try to find a partially uploaded
72 // file by the same author with the same name and same length. This
73 // allows us to resume uploads in Javascript where we can't efficiently
74 // compute file hashes.
75 $file = id(new PhabricatorFileQuery())
76 ->setViewer($viewer)
77 ->withAuthorPHIDs(array($viewer->getPHID()))
78 ->withNames(array($name))
79 ->withLengthBetween($length, $length)
80 ->withIsPartial(true)
81 ->setLimit(1)
82 ->executeOne();
86 if ($file) {
87 return array(
88 'upload' => (bool)$file->getIsPartial(),
89 'filePHID' => $file->getPHID(),
93 // If there are any non-chunk engines which this file can fit into,
94 // just tell the client to upload the file.
95 $engines = PhabricatorFileStorageEngine::loadStorageEngines($length);
96 if ($engines) {
97 return array(
98 'upload' => true,
99 'filePHID' => null,
103 // Otherwise, this is a large file and we want to perform a chunked
104 // upload if we have a chunk engine available.
105 $chunk_engines = PhabricatorFileStorageEngine::loadWritableChunkEngines();
106 if ($chunk_engines) {
107 $chunk_properties = $properties;
109 if ($hash !== null) {
110 $chunk_properties += array(
111 'chunkedHash' => $chunked_hash,
115 $chunk_engine = head($chunk_engines);
116 $file = $chunk_engine->allocateChunks($length, $chunk_properties);
118 return array(
119 'upload' => true,
120 'filePHID' => $file->getPHID(),
124 // None of the storage engines can accept this file.
125 if (PhabricatorFileStorageEngine::loadWritableEngines()) {
126 $error = pht(
127 'Unable to upload file: this file is too large for any '.
128 'configured storage engine.');
129 } else {
130 $error = pht(
131 'Unable to upload file: the server is not configured with any '.
132 'writable storage engines.');
135 return array(
136 'upload' => false,
137 'filePHID' => null,
138 'error' => $error,