Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/files/conduit/FileAllocateConduitAPIMethod.php
12241 views
1
<?php
2
3
final class FileAllocateConduitAPIMethod
4
extends FileConduitAPIMethod {
5
6
public function getAPIMethodName() {
7
return 'file.allocate';
8
}
9
10
public function getMethodDescription() {
11
return pht('Prepare to upload a file.');
12
}
13
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',
21
);
22
}
23
24
protected function defineReturnType() {
25
return 'map<string, wild>';
26
}
27
28
protected function execute(ConduitAPIRequest $request) {
29
$viewer = $request->getUser();
30
31
$hash = $request->getValue('contentHash');
32
$name = $request->getValue('name');
33
$view_policy = $request->getValue('viewPolicy');
34
$length = $request->getValue('contentLength');
35
36
$properties = array(
37
'name' => $name,
38
'authorPHID' => $viewer->getPHID(),
39
'isExplicitUpload' => true,
40
);
41
42
if ($view_policy !== null) {
43
$properties['viewPolicy'] = $view_policy;
44
}
45
46
$ttl = $request->getValue('deleteAfterEpoch');
47
if ($ttl) {
48
$properties['ttl.absolute'] = $ttl;
49
}
50
51
$file = null;
52
if ($hash !== null) {
53
$file = PhabricatorFile::newFileFromContentHash(
54
$hash,
55
$properties);
56
}
57
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();
66
}
67
68
if ($name !== null && 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();
83
}
84
}
85
86
if ($file) {
87
return array(
88
'upload' => (bool)$file->getIsPartial(),
89
'filePHID' => $file->getPHID(),
90
);
91
}
92
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,
100
);
101
}
102
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;
108
109
if ($hash !== null) {
110
$chunk_properties += array(
111
'chunkedHash' => $chunked_hash,
112
);
113
}
114
115
$chunk_engine = head($chunk_engines);
116
$file = $chunk_engine->allocateChunks($length, $chunk_properties);
117
118
return array(
119
'upload' => true,
120
'filePHID' => $file->getPHID(),
121
);
122
}
123
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.');
133
}
134
135
return array(
136
'upload' => false,
137
'filePHID' => null,
138
'error' => $error,
139
);
140
}
141
142
}
143
144