Phabricator file upload application.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PhabricatorFileController extends PhabricatorController {
|
||||
|
||||
public function buildStandardPageResponse($view, array $data) {
|
||||
$page = new PhabricatorStandardPageView();
|
||||
|
||||
$page->setApplicationName('Files');
|
||||
$page->setBaseURI('/file/');
|
||||
$page->setTitle(idx($data, 'title'));
|
||||
$page->setGlyph("\xE2\x87\xAA");
|
||||
$page->appendChild($view);
|
||||
|
||||
$response = new AphrontWebpageResponse();
|
||||
return $response->setContent($page->render());
|
||||
}
|
||||
|
||||
}
|
||||
16
src/applications/files/controller/base/__init__.php
Normal file
16
src/applications/files/controller/base/__init__.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||
phutil_require_module('phabricator', 'view/page/standard');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFileController.php');
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFileListController extends PhabricatorFileController {
|
||||
|
||||
public function processRequest() {
|
||||
$files = id(new PhabricatorFile())->loadAllWhere(
|
||||
'1 = 1 ORDER BY id DESC LIMIT 100');
|
||||
|
||||
$rows = array();
|
||||
foreach ($files as $file) {
|
||||
$rows[] = array(
|
||||
phutil_escape_html($file->getPHID()),
|
||||
phutil_escape_html($file->getName()),
|
||||
phutil_escape_html($file->getByteSize()),
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'class' => 'small button grey',
|
||||
'href' => '/file/info/'.$file->getPHID().'/',
|
||||
),
|
||||
'Info'),
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'class' => 'small button grey',
|
||||
'href' => '/file/view/'.$file->getPHID().'/',
|
||||
),
|
||||
'View'),
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'class' => 'small button grey',
|
||||
'href' => '/file/download/'.$file->getPHID().'/',
|
||||
),
|
||||
'Download'),
|
||||
);
|
||||
}
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
'PHID',
|
||||
'Name',
|
||||
'Size',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
null,
|
||||
'wide',
|
||||
null,
|
||||
'action',
|
||||
'action',
|
||||
'action',
|
||||
));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->appendChild($table);
|
||||
$panel->setHeader('Files');
|
||||
$panel->setCreateButton('Upload File', '/file/upload/');
|
||||
|
||||
return $this->buildStandardPageResponse($panel, array(
|
||||
'title' => 'Files',
|
||||
'tab' => 'files',
|
||||
));
|
||||
}
|
||||
}
|
||||
18
src/applications/files/controller/list/__init__.php
Normal file
18
src/applications/files/controller/list/__init__.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/files/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFileListController.php');
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFileUploadController extends PhabricatorFileController {
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$request = $this->getRequest();
|
||||
if ($request->isFormPost()) {
|
||||
$file = PhabricatorFile::newFromPHPUpload(
|
||||
idx($_FILES, 'file'),
|
||||
array(
|
||||
'name' => $request->getStr('name'),
|
||||
));
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI('/file/info/'.phutil_escape_uri($file->getPHID()).'/');
|
||||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setAction('/file/upload/');
|
||||
|
||||
$form
|
||||
->setEncType('multipart/form-data')
|
||||
->appendChild(
|
||||
id(new AphrontFormFileControl())
|
||||
->setLabel('File')
|
||||
->setName('file')
|
||||
->setError(true))
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel('Name')
|
||||
->setName('name')
|
||||
->setCaption('Optional file display name.'))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('Upload')
|
||||
->addCancelButton('/file/'));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader('Upload File');
|
||||
|
||||
$panel->appendChild($form);
|
||||
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
array($panel),
|
||||
array(
|
||||
'title' => 'Upload File',
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
20
src/applications/files/controller/upload/__init__.php
Normal file
20
src/applications/files/controller/upload/__init__.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/files/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFileUploadController.php');
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFileViewController extends PhabricatorFileController {
|
||||
|
||||
private $phid;
|
||||
private $view;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->phid = $data['phid'];
|
||||
$this->view = $data['view'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$file = id(new PhabricatorFile())->loadOneWhere(
|
||||
'phid = %s',
|
||||
$this->phid);
|
||||
if (!$file) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
switch ($this->view) {
|
||||
case 'download':
|
||||
case 'view':
|
||||
$data = $file->loadFileData();
|
||||
$response = new AphrontFileResponse();
|
||||
$response->setContent($data);
|
||||
$response->setMimeType($file->getMimeType());
|
||||
if ($this->view == 'download') {
|
||||
$response->setDownload($file->getName());
|
||||
}
|
||||
return $response;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setAction('/file/view/'.$file->getPHID().'/');
|
||||
$form
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel('Name')
|
||||
->setName('name')
|
||||
->setValue($file->getName()))
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel('PHID')
|
||||
->setName('phid')
|
||||
->setValue($file->getPHID()))
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel('Created')
|
||||
->setName('created')
|
||||
->setValue(date('Y-m-d g:i:s A', $file->getDateCreated())))
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel('Mime Type')
|
||||
->setName('mime')
|
||||
->setValue($file->getMimeType()))
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel('Size')
|
||||
->setName('size')
|
||||
->setValue($file->getByteSize().' bytes'))
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel('Engine')
|
||||
->setName('storageEngine')
|
||||
->setValue($file->getStorageEngine()))
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel('Format')
|
||||
->setName('storageFormat')
|
||||
->setValue($file->getStorageFormat()))
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel('Handle')
|
||||
->setName('storageHandle')
|
||||
->setValue($file->getStorageHandle()))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('View File'));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader('File Info - '.$file->getName());
|
||||
|
||||
$panel->appendChild($form);
|
||||
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
array($panel),
|
||||
array(
|
||||
'title' => 'File Info - '.$file->getName(),
|
||||
));
|
||||
}
|
||||
}
|
||||
20
src/applications/files/controller/view/__init__.php
Normal file
20
src/applications/files/controller/view/__init__.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/404');
|
||||
phutil_require_module('phabricator', 'aphront/response/file');
|
||||
phutil_require_module('phabricator', 'applications/files/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFileViewController.php');
|
||||
25
src/applications/files/storage/base/PhabricatorFileDAO.php
Normal file
25
src/applications/files/storage/base/PhabricatorFileDAO.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFileDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'file';
|
||||
}
|
||||
|
||||
}
|
||||
12
src/applications/files/storage/base/__init__.php
Normal file
12
src/applications/files/storage/base/__init__.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/base/storage/lisk');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFileDAO.php');
|
||||
170
src/applications/files/storage/file/PhabricatorFile.php
Normal file
170
src/applications/files/storage/file/PhabricatorFile.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFile extends PhabricatorFileDAO {
|
||||
|
||||
const STORAGE_ENGINE_BLOB = 'blob';
|
||||
|
||||
const STORAGE_FORMAT_RAW = 'raw';
|
||||
|
||||
const PHID_TYPE = 'FILE';
|
||||
|
||||
// TODO: We need to reconcile this with MySQL packet size.
|
||||
const FILE_SIZE_BYTE_LIMIT = 12582912;
|
||||
|
||||
protected $phid;
|
||||
protected $name;
|
||||
protected $mimeType;
|
||||
protected $byteSize;
|
||||
|
||||
protected $storageEngine;
|
||||
protected $storageFormat;
|
||||
protected $storageHandle;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function generatePHID() {
|
||||
return PhabricatorPHID::generateNewPHID(self::PHID_TYPE);
|
||||
}
|
||||
|
||||
public static function newFromPHPUpload($spec, array $params = array()) {
|
||||
if (!$spec) {
|
||||
throw new Exception("No file was uploaded!");
|
||||
}
|
||||
|
||||
$err = idx($spec, 'error');
|
||||
if ($err) {
|
||||
throw new Exception("File upload failed with error '{$err}'.");
|
||||
}
|
||||
|
||||
$tmp_name = idx($spec, 'tmp_name');
|
||||
$is_valid = @is_uploaded_file($tmp_name);
|
||||
if (!$is_valid) {
|
||||
throw new Exception("File is not an uploaded file.");
|
||||
}
|
||||
|
||||
$file_data = Filesystem::readFile($tmp_name);
|
||||
$file_size = idx($spec, 'size');
|
||||
|
||||
if (strlen($file_data) != $file_size) {
|
||||
throw new Exception("File size disagrees with uploaded size.");
|
||||
}
|
||||
|
||||
$file_name = nonempty(
|
||||
idx($params, 'name'),
|
||||
idx($spec, 'name'));
|
||||
$params = array(
|
||||
'name' => $file_name,
|
||||
) + $params;
|
||||
|
||||
return self::newFromFileData($file_data, $params);
|
||||
}
|
||||
|
||||
public static function newFromFileData($data, array $params = array()) {
|
||||
$file_size = strlen($data);
|
||||
|
||||
if ($file_size > self::FILE_SIZE_BYTE_LIMIT) {
|
||||
throw new Exception("File is too large to store.");
|
||||
}
|
||||
|
||||
$file_name = idx($params, 'name');
|
||||
$file_name = self::normalizeFileName($file_name);
|
||||
|
||||
$file = new PhabricatorFile();
|
||||
$file->setName($file_name);
|
||||
$file->setByteSize(strlen($data));
|
||||
|
||||
$blob = new PhabricatorFileStorageBlob();
|
||||
$blob->setData($data);
|
||||
$blob->save();
|
||||
|
||||
// TODO: This stuff is almost certainly YAGNI, but we could imagine having
|
||||
// an alternate disk store and gzipping or encrypting things or something
|
||||
// crazy like that and this isn't toooo much extra code.
|
||||
$file->setStorageEngine(self::STORAGE_ENGINE_BLOB);
|
||||
$file->setStorageFormat(self::STORAGE_FORMAT_RAW);
|
||||
$file->setStorageHandle($blob->getID());
|
||||
|
||||
try {
|
||||
$tmp = new TempFile();
|
||||
Filesystem::writeFile($tmp, $data);
|
||||
list($stdout) = execx('file -b --mime %s', $tmp);
|
||||
$file->setMimeType($stdout);
|
||||
} catch (Exception $ex) {
|
||||
// Be robust here since we don't really care that much about mime types.
|
||||
}
|
||||
|
||||
$file->save();
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
public static function normalizeFileName($file_name) {
|
||||
return preg_replace('/[^a-zA-Z0-9.~_-]/', '_', $file_name);
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
$this->openTransaction();
|
||||
switch ($this->getStorageEngine()) {
|
||||
case self::STORAGE_ENGINE_BLOB:
|
||||
$handle = $this->getStorageHandle();
|
||||
$blob = id(new PhabricatorFileStorageBlob())->load($handle);
|
||||
$blob->delete();
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown storage engine!");
|
||||
}
|
||||
|
||||
$ret = parent::delete();
|
||||
$this->saveTransaction();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function loadFileData() {
|
||||
|
||||
$handle = $this->getStorageHandle();
|
||||
$data = null;
|
||||
|
||||
switch ($this->getStorageEngine()) {
|
||||
case self::STORAGE_ENGINE_BLOB:
|
||||
$blob = id(new PhabricatorFileStorageBlob())->load($handle);
|
||||
if (!$blob) {
|
||||
throw new Exception("Failed to load file blob data.");
|
||||
}
|
||||
$data = $blob->getData();
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown storage engine.");
|
||||
}
|
||||
|
||||
switch ($this->getStorageFormat()) {
|
||||
case self::STORAGE_FORMAT_RAW:
|
||||
$data = $data;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown storage format.");
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
19
src/applications/files/storage/file/__init__.php
Normal file
19
src/applications/files/storage/file/__init__.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/files/storage/base');
|
||||
phutil_require_module('phabricator', 'applications/files/storage/storageblob');
|
||||
phutil_require_module('phabricator', 'applications/phid/storage/phid');
|
||||
|
||||
phutil_require_module('phutil', 'filesystem');
|
||||
phutil_require_module('phutil', 'filesystem/tempfile');
|
||||
phutil_require_module('phutil', 'future/exec');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFile.php');
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFileStorageBlob extends PhabricatorFileDAO {
|
||||
|
||||
protected $data;
|
||||
|
||||
}
|
||||
12
src/applications/files/storage/storageblob/__init__.php
Normal file
12
src/applications/files/storage/storageblob/__init__.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/files/storage/base');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFileStorageBlob.php');
|
||||
Reference in New Issue
Block a user