Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 09e6f6c6de..a94dc510f5 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,138 +1,158 @@
<?php
/**
* This file is automatically generated. Use 'phutil_mapper.php' to rebuild it.
* @generated
*/
phutil_register_library_map(array(
'class' =>
array(
'Aphront404Response' => 'aphront/response/404',
'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration',
'AphrontController' => 'aphront/controller',
'AphrontDatabaseConnection' => 'storage/connection/base',
'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration',
'AphrontDefaultApplicationController' => 'aphront/default/controller',
'AphrontDialogResponse' => 'aphront/response/dialog',
'AphrontDialogView' => 'view/dialog',
'AphrontErrorView' => 'view/form/error',
+ 'AphrontFileResponse' => 'aphront/response/file',
'AphrontFormControl' => 'view/form/control/base',
+ 'AphrontFormFileControl' => 'view/form/control/file',
'AphrontFormSelectControl' => 'view/form/control/select',
+ 'AphrontFormStaticControl' => 'view/form/control/static',
'AphrontFormSubmitControl' => 'view/form/control/submit',
'AphrontFormTextAreaControl' => 'view/form/control/textarea',
'AphrontFormTextControl' => 'view/form/control/text',
'AphrontFormView' => 'view/form/base',
'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql',
'AphrontNullView' => 'view/null',
'AphrontPageView' => 'view/page/base',
'AphrontPanelView' => 'view/layout/panel',
'AphrontQueryConnectionException' => 'storage/exception/connection',
'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost',
'AphrontQueryCountException' => 'storage/exception/count',
'AphrontQueryException' => 'storage/exception/base',
'AphrontQueryObjectMissingException' => 'storage/exception/objectmissing',
'AphrontQueryParameterException' => 'storage/exception/parameter',
'AphrontQueryRecoverableException' => 'storage/exception/recoverable',
'AphrontRedirectResponse' => 'aphront/response/redirect',
'AphrontRequest' => 'aphront/request',
'AphrontResponse' => 'aphront/response/base',
'AphrontTableView' => 'view/control/table',
'AphrontURIMapper' => 'aphront/mapper',
'AphrontView' => 'view/base',
'AphrontWebpageResponse' => 'aphront/response/webpage',
'DifferentialAction' => 'applications/review/constants/action',
'DifferentialChangeType' => 'applications/review/constants/changetype',
'DifferentialLintStatus' => 'applications/review/constants/lintstatus',
'DifferentialRevisionStatus' => 'applications/review/constants/revisionstatus',
'DifferentialUnitStatus' => 'applications/review/constants/unitstatus',
'LiskDAO' => 'storage/lisk/dao',
'PhabricatorController' => 'applications/base/controller/base',
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit',
'PhabricatorDirectoryCategoryListController' => 'applications/directory/controller/categorylist',
'PhabricatorDirectoryController' => 'applications/directory/controller/base',
'PhabricatorDirectoryDAO' => 'applications/directory/storage/base',
'PhabricatorDirectoryItem' => 'applications/directory/storage/item',
'PhabricatorDirectoryItemDeleteController' => 'applications/directory/controller/itemdelete',
'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit',
'PhabricatorDirectoryItemListController' => 'applications/directory/controller/itemlist',
'PhabricatorDirectoryMainController' => 'applications/directory/controller/main',
+ 'PhabricatorFile' => 'applications/files/storage/file',
+ 'PhabricatorFileController' => 'applications/files/controller/base',
+ 'PhabricatorFileDAO' => 'applications/files/storage/base',
+ 'PhabricatorFileListController' => 'applications/files/controller/list',
+ 'PhabricatorFileStorageBlob' => 'applications/files/storage/storageblob',
+ 'PhabricatorFileUploadController' => 'applications/files/controller/upload',
+ 'PhabricatorFileViewController' => 'applications/files/controller/view',
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
'PhabricatorPHID' => 'applications/phid/storage/phid',
'PhabricatorPHIDAllocateController' => 'applications/phid/controller/allocate',
'PhabricatorPHIDController' => 'applications/phid/controller/base',
'PhabricatorPHIDDAO' => 'applications/phid/storage/base',
'PhabricatorPHIDListController' => 'applications/phid/controller/list',
'PhabricatorPHIDType' => 'applications/phid/storage/type',
'PhabricatorPHIDTypeEditController' => 'applications/phid/controller/typeedit',
'PhabricatorPHIDTypeListController' => 'applications/phid/controller/typelist',
'PhabricatorStandardPageView' => 'view/page/standard',
),
'function' =>
array(
'_qsprintf_check_scalar_type' => 'storage/qsprintf',
'_qsprintf_check_type' => 'storage/qsprintf',
'qsprintf' => 'storage/qsprintf',
'queryfx' => 'storage/queryfx',
'queryfx_all' => 'storage/queryfx',
'queryfx_one' => 'storage/queryfx',
'vqsprintf' => 'storage/qsprintf',
'vqueryfx' => 'storage/queryfx',
'xsprintf_query' => 'storage/qsprintf',
),
'requires_class' =>
array(
'Aphront404Response' => 'AphrontResponse',
'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration',
'AphrontDefaultApplicationController' => 'AphrontController',
'AphrontDialogResponse' => 'AphrontResponse',
'AphrontDialogView' => 'AphrontView',
'AphrontErrorView' => 'AphrontView',
+ 'AphrontFileResponse' => 'AphrontResponse',
'AphrontFormControl' => 'AphrontView',
+ 'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormSelectControl' => 'AphrontFormControl',
+ 'AphrontFormStaticControl' => 'AphrontFormControl',
'AphrontFormSubmitControl' => 'AphrontFormControl',
'AphrontFormTextAreaControl' => 'AphrontFormControl',
'AphrontFormTextControl' => 'AphrontFormControl',
'AphrontFormView' => 'AphrontView',
'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontNullView' => 'AphrontView',
'AphrontPageView' => 'AphrontView',
'AphrontPanelView' => 'AphrontView',
'AphrontQueryConnectionException' => 'AphrontQueryException',
'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException',
'AphrontQueryCountException' => 'AphrontQueryException',
'AphrontQueryObjectMissingException' => 'AphrontQueryException',
'AphrontQueryParameterException' => 'AphrontQueryException',
'AphrontQueryRecoverableException' => 'AphrontQueryException',
'AphrontRedirectResponse' => 'AphrontResponse',
'AphrontTableView' => 'AphrontView',
'AphrontWebpageResponse' => 'AphrontResponse',
'PhabricatorController' => 'AphrontController',
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryCategoryListController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryController' => 'PhabricatorController',
'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO',
'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryItemListController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController',
+ 'PhabricatorFile' => 'PhabricatorFileDAO',
+ 'PhabricatorFileController' => 'PhabricatorController',
+ 'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
+ 'PhabricatorFileListController' => 'PhabricatorFileController',
+ 'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO',
+ 'PhabricatorFileUploadController' => 'PhabricatorFileController',
+ 'PhabricatorFileViewController' => 'PhabricatorFileController',
'PhabricatorLiskDAO' => 'LiskDAO',
'PhabricatorPHID' => 'PhabricatorPHIDDAO',
'PhabricatorPHIDAllocateController' => 'PhabricatorPHIDController',
'PhabricatorPHIDController' => 'PhabricatorController',
'PhabricatorPHIDDAO' => 'PhabricatorLiskDAO',
'PhabricatorPHIDListController' => 'PhabricatorPHIDController',
'PhabricatorPHIDType' => 'PhabricatorPHIDDAO',
'PhabricatorPHIDTypeEditController' => 'PhabricatorPHIDController',
'PhabricatorPHIDTypeListController' => 'PhabricatorPHIDController',
'PhabricatorStandardPageView' => 'AphrontPageView',
),
'requires_interface' =>
array(
),
));
diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
index 4765cf56e6..0939448591 100644
--- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
+++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
@@ -1,109 +1,116 @@
<?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.
*/
/**
* @group aphront
*/
class AphrontDefaultApplicationConfiguration
extends AphrontApplicationConfiguration {
public function getApplicationName() {
return 'aphront-default';
}
public function getURIMap() {
return array(
'/repository/' => array(
'$' => 'RepositoryListController',
'new/$' => 'RepositoryEditController',
'edit/(?<id>\d+)/$' => 'RepositoryEditController',
'delete/(?<id>\d+)/$' => 'RepositoryDeleteController',
),
'/' => array(
'$' => 'PhabricatorDirectoryMainController',
),
'/directory/' => array(
'item/$'
=> 'PhabricatorDirectoryItemListController',
'item/edit/(?:(?<id>\d+)/)?$'
=> 'PhabricatorDirectoryItemEditController',
'item/delete/(?<id>\d+)/'
=> 'PhabricatorDirectoryItemDeleteController',
'category/$'
=> 'PhabricatorDirectoryCategoryListController',
'category/edit/(?:(?<id>\d+)/)?$'
=> 'PhabricatorDirectoryCategoryEditController',
'category/delete/(?<id>\d+)/'
=> 'PhabricatorDirectoryCategoryDeleteController',
),
+ '/file/' => array(
+ '$' => 'PhabricatorFileListController',
+ 'upload/$' => 'PhabricatorFileUploadController',
+ '(?<view>info)/(?<phid>[^/]+)/' => 'PhabricatorFileViewController',
+ '(?<view>view)/(?<phid>[^/]+)/' => 'PhabricatorFileViewController',
+ '(?<view>download)/(?<phid>[^/]+)/' => 'PhabricatorFileViewController',
+ ),
'/phid/' => array(
'$' => 'PhabricatorPHIDListController',
'type/$' => 'PhabricatorPHIDTypeListController',
'type/edit/(?:(?<id>\d+)/)?$' => 'PhabricatorPHIDTypeEditController',
'new/$' => 'PhabricatorPHIDAllocateController',
),
'.*' => 'AphrontDefaultApplicationController',
);
}
public function buildRequest() {
$request = new AphrontRequest($this->getHost(), $this->getPath());
$request->setRequestData($_GET + $_POST);
return $request;
}
public function handleException(Exception $ex) {
$class = phutil_escape_html(get_class($ex));
$message = phutil_escape_html($ex->getMessage());
$content =
'<div class="aphront-unhandled-exception">'.
'<h1>Unhandled Exception "'.$class.'": '.$message.'</h1>'.
'<code>'.phutil_escape_html((string)$ex).'</code>'.
'</div>';
$view = new PhabricatorStandardPageView();
$view->appendChild($content);
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
return $response;
}
public function willSendResponse(AphrontResponse $response) {
$request = $this->getRequest();
if ($response instanceof AphrontDialogResponse) {
if (!$request->isAjax()) {
$view = new PhabricatorStandardPageView();
$view->appendChild(
'<div style="padding: 2em 0;">'.
$response->buildResponseString().
'</div>');
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
return $response;
}
}
return $response;
}
}
diff --git a/src/aphront/response/file/AphrontFileResponse.php b/src/aphront/response/file/AphrontFileResponse.php
new file mode 100644
index 0000000000..0e60435951
--- /dev/null
+++ b/src/aphront/response/file/AphrontFileResponse.php
@@ -0,0 +1,70 @@
+<?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.
+ */
+
+/**
+ * @group aphront
+ */
+class AphrontFileResponse extends AphrontResponse {
+
+ private $content;
+ private $mimeType;
+ private $download;
+
+ public function setDownload($download) {
+ $this->download = $download;
+ return $this;
+ }
+
+ public function getDownload() {
+ return $this->download;
+ }
+
+ public function setMimeType($mime_type) {
+ $this->mimeType = $mime_type;
+ return $this;
+ }
+
+ public function getMimeType() {
+ return $this->mimeType;
+ }
+
+ public function setContent($content) {
+ $this->content = $content;
+ return $this;
+ }
+
+ public function buildResponseString() {
+ return $this->content;
+ }
+
+ public function getHeaders() {
+ $headers = array(
+ array('Content-Type', $this->getMimeType()),
+ );
+
+ if ($this->getDownload()) {
+ $headers[] = array(
+ 'Content-Disposition',
+ 'attachment; filename='.$this->getDownload(),
+ );
+ }
+
+ return $headers;
+ }
+
+}
diff --git a/src/applications/files/controller/base/PhabricatorFileController.php b/src/applications/files/controller/base/PhabricatorFileController.php
new file mode 100644
index 0000000000..6ef76df91b
--- /dev/null
+++ b/src/applications/files/controller/base/PhabricatorFileController.php
@@ -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());
+ }
+
+}
diff --git a/src/applications/files/controller/base/__init__.php b/src/applications/files/controller/base/__init__.php
new file mode 100644
index 0000000000..16685a0b26
--- /dev/null
+++ b/src/applications/files/controller/base/__init__.php
@@ -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');
diff --git a/src/applications/files/controller/list/PhabricatorFileListController.php b/src/applications/files/controller/list/PhabricatorFileListController.php
new file mode 100644
index 0000000000..ac2edab897
--- /dev/null
+++ b/src/applications/files/controller/list/PhabricatorFileListController.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',
+ ));
+ }
+}
diff --git a/src/applications/files/controller/list/__init__.php b/src/applications/files/controller/list/__init__.php
new file mode 100644
index 0000000000..91678ceb0e
--- /dev/null
+++ b/src/applications/files/controller/list/__init__.php
@@ -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');
diff --git a/src/applications/files/controller/upload/PhabricatorFileUploadController.php b/src/applications/files/controller/upload/PhabricatorFileUploadController.php
new file mode 100644
index 0000000000..12d6f83a81
--- /dev/null
+++ b/src/applications/files/controller/upload/PhabricatorFileUploadController.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',
+ ));
+ }
+
+}
diff --git a/src/applications/files/controller/upload/__init__.php b/src/applications/files/controller/upload/__init__.php
new file mode 100644
index 0000000000..63a11bf54e
--- /dev/null
+++ b/src/applications/files/controller/upload/__init__.php
@@ -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');
diff --git a/src/applications/files/controller/view/PhabricatorFileViewController.php b/src/applications/files/controller/view/PhabricatorFileViewController.php
new file mode 100644
index 0000000000..361a7cb98b
--- /dev/null
+++ b/src/applications/files/controller/view/PhabricatorFileViewController.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(),
+ ));
+ }
+}
diff --git a/src/applications/files/controller/view/__init__.php b/src/applications/files/controller/view/__init__.php
new file mode 100644
index 0000000000..ed0b9e9534
--- /dev/null
+++ b/src/applications/files/controller/view/__init__.php
@@ -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');
diff --git a/src/applications/files/storage/base/PhabricatorFileDAO.php b/src/applications/files/storage/base/PhabricatorFileDAO.php
new file mode 100644
index 0000000000..a2c580d8c8
--- /dev/null
+++ b/src/applications/files/storage/base/PhabricatorFileDAO.php
@@ -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';
+ }
+
+}
diff --git a/src/applications/files/storage/base/__init__.php b/src/applications/files/storage/base/__init__.php
new file mode 100644
index 0000000000..a1568eb4f0
--- /dev/null
+++ b/src/applications/files/storage/base/__init__.php
@@ -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');
diff --git a/src/applications/files/storage/file/PhabricatorFile.php b/src/applications/files/storage/file/PhabricatorFile.php
new file mode 100644
index 0000000000..37929f2509
--- /dev/null
+++ b/src/applications/files/storage/file/PhabricatorFile.php
@@ -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;
+ }
+
+}
diff --git a/src/applications/files/storage/file/__init__.php b/src/applications/files/storage/file/__init__.php
new file mode 100644
index 0000000000..26394989c8
--- /dev/null
+++ b/src/applications/files/storage/file/__init__.php
@@ -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');
diff --git a/src/applications/files/storage/storageblob/PhabricatorFileStorageBlob.php b/src/applications/files/storage/storageblob/PhabricatorFileStorageBlob.php
new file mode 100644
index 0000000000..14b3745e4f
--- /dev/null
+++ b/src/applications/files/storage/storageblob/PhabricatorFileStorageBlob.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;
+
+}
diff --git a/src/applications/files/storage/storageblob/__init__.php b/src/applications/files/storage/storageblob/__init__.php
new file mode 100644
index 0000000000..1f3fade7b3
--- /dev/null
+++ b/src/applications/files/storage/storageblob/__init__.php
@@ -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');
diff --git a/src/applications/phid/storage/phid/PhabricatorPHID.php b/src/applications/phid/storage/phid/PhabricatorPHID.php
index 70f018ad4f..6289311f6a 100644
--- a/src/applications/phid/storage/phid/PhabricatorPHID.php
+++ b/src/applications/phid/storage/phid/PhabricatorPHID.php
@@ -1,56 +1,57 @@
<?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 PhabricatorPHID extends PhabricatorPHIDDAO {
protected $phid;
protected $phidType;
protected $ownerPHID;
protected $parentPHID;
public static function generateNewPHID($type, array $config = array()) {
$owner = idx($config, 'owner');
$parent = idx($config, 'parent');
if (!$type) {
throw new Exception("Can not generate PHID with no type.");
}
$urandom = @fopen('/dev/urandom', 'r');
if (!$urandom) {
throw new Exception("Failed to open /dev/urandom!");
}
- $entropy = fread($urandom, 16);
- if (strlen($entropy) != 16) {
+ $entropy = fread($urandom, 20);
+ if (strlen($entropy) != 20) {
throw new Exception("Failed to read from /dev/urandom!");
}
$uniq = sha1($entropy);
- $phid = 'PHID-'.$type.'-X-'.$uniq;
+ $uniq = substr($uniq, 0, 20);
+ $phid = 'PHID-'.$type.'-'.$uniq;
$phid_rec = new PhabricatorPHID();
$phid_rec->setPHIDType($type);
$phid_rec->setOwnerPHID($owner);
$phid_rec->setParentPHID($parent);
$phid_rec->setPHID($phid);
$phid_rec->save();
return $phid;
}
}
diff --git a/src/view/form/base/AphrontFormView.php b/src/view/form/base/AphrontFormView.php
index bb03038d86..5cf93d98f4 100755
--- a/src/view/form/base/AphrontFormView.php
+++ b/src/view/form/base/AphrontFormView.php
@@ -1,65 +1,72 @@
<?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.
*/
final class AphrontFormView extends AphrontView {
private $action;
private $method = 'POST';
private $header;
private $data = array();
+ private $encType;
public function setAction($action) {
$this->action = $action;
return $this;
}
public function setMethod($method) {
$this->method = $method;
return $this;
}
+ public function setEncType($enc_type) {
+ $this->encType = $enc_type;
+ return $this;
+ }
+
public function render() {
return phutil_render_tag(
'form',
array(
- 'action' => $this->action,
- 'method' => $this->method,
- 'class' => 'aphront-form-view',
+ 'action' => $this->action,
+ 'method' => $this->method,
+ 'class' => 'aphront-form-view',
+ 'enctype' => $this->encType,
),
$this->renderDataInputs().
$this->renderChildren());
}
private function renderDataInputs() {
$data = $this->data + array(
'__form__' => 1,
);
$inputs = array();
foreach ($data as $key => $value) {
$inputs[] = phutil_render_tag(
'input',
array(
'type' => 'hidden',
'name' => $key,
'value' => $value,
));
}
return implode("\n", $inputs);
}
}
diff --git a/src/view/form/control/submit/AphrontFormSubmitControl.php b/src/view/form/control/file/AphrontFormFileControl.php
similarity index 60%
copy from src/view/form/control/submit/AphrontFormSubmitControl.php
copy to src/view/form/control/file/AphrontFormFileControl.php
index 7742a20ae0..9c83ceaaf9 100755
--- a/src/view/form/control/submit/AphrontFormSubmitControl.php
+++ b/src/view/form/control/file/AphrontFormFileControl.php
@@ -1,49 +1,35 @@
<?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 AphrontFormSubmitControl extends AphrontFormControl {
-
- protected $cancelButton;
-
- public function addCancelButton($href, $label = 'Cancel') {
- $this->cancelButton = phutil_render_tag(
- 'a',
- array(
- 'href' => $href,
- 'class' => 'button grey',
- ),
- phutil_escape_html($label));
- return $this;
- }
+class AphrontFormFileControl extends AphrontFormControl {
protected function getCustomControlClass() {
- return 'aphront-form-control-submit';
+ return 'aphront-form-file-text';
}
protected function renderInput() {
return phutil_render_tag(
- 'button',
+ 'input',
array(
- 'name' => '__submit__',
+ 'type' => 'file',
+ 'name' => $this->getName(),
'disabled' => $this->getDisabled() ? 'disabled' : null,
- ),
- phutil_escape_html($this->getValue())).
- $this->cancelButton;
+ ));
}
}
diff --git a/src/view/form/control/file/__init__.php b/src/view/form/control/file/__init__.php
new file mode 100644
index 0000000000..ccabdcbaa2
--- /dev/null
+++ b/src/view/form/control/file/__init__.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'view/form/control/base');
+
+phutil_require_module('phutil', 'markup');
+
+
+phutil_require_source('AphrontFormFileControl.php');
diff --git a/src/view/form/control/submit/AphrontFormSubmitControl.php b/src/view/form/control/static/AphrontFormStaticControl.php
similarity index 52%
copy from src/view/form/control/submit/AphrontFormSubmitControl.php
copy to src/view/form/control/static/AphrontFormStaticControl.php
index 7742a20ae0..0f011e0248 100755
--- a/src/view/form/control/submit/AphrontFormSubmitControl.php
+++ b/src/view/form/control/static/AphrontFormStaticControl.php
@@ -1,49 +1,29 @@
<?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 AphrontFormSubmitControl extends AphrontFormControl {
-
- protected $cancelButton;
-
- public function addCancelButton($href, $label = 'Cancel') {
- $this->cancelButton = phutil_render_tag(
- 'a',
- array(
- 'href' => $href,
- 'class' => 'button grey',
- ),
- phutil_escape_html($label));
- return $this;
- }
+class AphrontFormStaticControl extends AphrontFormControl {
protected function getCustomControlClass() {
- return 'aphront-form-control-submit';
+ return 'aphront-form-control-static';
}
protected function renderInput() {
- return phutil_render_tag(
- 'button',
- array(
- 'name' => '__submit__',
- 'disabled' => $this->getDisabled() ? 'disabled' : null,
- ),
- phutil_escape_html($this->getValue())).
- $this->cancelButton;
+ return phutil_escape_html($this->getValue());
}
}
diff --git a/src/view/form/control/static/__init__.php b/src/view/form/control/static/__init__.php
new file mode 100644
index 0000000000..97d6bb9b42
--- /dev/null
+++ b/src/view/form/control/static/__init__.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'view/form/control/base');
+
+phutil_require_module('phutil', 'markup');
+
+
+phutil_require_source('AphrontFormStaticControl.php');
diff --git a/src/view/form/control/submit/AphrontFormSubmitControl.php b/src/view/form/control/submit/AphrontFormSubmitControl.php
index 7742a20ae0..3cf8c59823 100755
--- a/src/view/form/control/submit/AphrontFormSubmitControl.php
+++ b/src/view/form/control/submit/AphrontFormSubmitControl.php
@@ -1,49 +1,52 @@
<?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 AphrontFormSubmitControl extends AphrontFormControl {
protected $cancelButton;
public function addCancelButton($href, $label = 'Cancel') {
$this->cancelButton = phutil_render_tag(
'a',
array(
'href' => $href,
'class' => 'button grey',
),
phutil_escape_html($label));
return $this;
}
protected function getCustomControlClass() {
return 'aphront-form-control-submit';
}
protected function renderInput() {
- return phutil_render_tag(
- 'button',
- array(
- 'name' => '__submit__',
- 'disabled' => $this->getDisabled() ? 'disabled' : null,
- ),
- phutil_escape_html($this->getValue())).
- $this->cancelButton;
+ $submit_button = null;
+ if ($this->getValue()) {
+ $submit_button = phutil_render_tag(
+ 'button',
+ array(
+ 'name' => '__submit__',
+ 'disabled' => $this->getDisabled() ? 'disabled' : null,
+ ),
+ phutil_escape_html($this->getValue()));
+ }
+ return $submit_button.$this->cancelButton;
}
}
diff --git a/webroot/rsrc/css/base.css b/webroot/rsrc/css/base.css
index 4e49a892d3..f305a544c2 100644
--- a/webroot/rsrc/css/base.css
+++ b/webroot/rsrc/css/base.css
@@ -1,536 +1,534 @@
html {
overflow-y: scroll;
}
body, div, dl, dt, dd, ul, ol, li,
h1, h2, h3, h4, h5, h6,
pre, form, fieldset,
p, blockquote, th, td, button {
margin: 0;
padding: 0;
outline: 0;
border: 0;
}
html {
padding-bottom: 16em;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset, img {
border: 0;
}
address, caption, cite, code, dfn, th, var {
font-style: normal;
font-weight: normal;
}
ol, ul {
list-style: none;
}
caption, th {
text-align: left;
}
td, th {
vertical-align: top;
}
h1, h2, h3, h4, h5, h6 {
font-size: 100%;
font-weight: bold;
}
body {
font: 13px/1.231 'lucida grande', tahoma, verdana, arial, sans-serif;
background: #ACACAC;
direction: ltr;
text-align: left;
unicode-bidi: embed;
*font-size: small;
}
select, input, button, textarea, button {
font: 99% 'lucida grande', tahoma, verdana, arial, clean, sans-serif;
}
table {
font-size: inherit;
font: 100%;
}
h1 {
font-size: 16px;
}
h2 {
font-size: 14px;
}
a {
-moz-outline-style: none;
text-decoration: none;
cursor: pointer;
}
a:visited {
color: #3b5998;
}
a:link {
color: #3b5998;
}
a:hover {
text-decoration: underline;
}
img {
display: block;
}
/******************************************************************************/
/* Buttons */
/******************************************************************************/
button,
a.button,
a.button:visited,
input.inputsubmit {
background: #5e77aa url('/rsrc/image/sprite.png') 0 0 repeat-x;
border: 1px solid #29447e;
border-bottom-color: #1a356e;
color: #fff;
cursor: pointer;
font-weight: bold;
text-align: center;
white-space: nowrap;
display: inline-block;
font-size: 13px;
overflow: visible;
padding: 2px 8px 3px 8px;
line-height: 18px;
vertical-align: baseline;
width: auto;
box-shadow: 0px 1px 0px rgba(0,0,0,.12);
-moz-box-shadow: 0px 1px 0px rgba(0,0,0,.12);
-webkit-box-shadow: 0px 1px 0px rgba(0,0,0,.12);
}
button {
*padding: 2px 4px 1px 8px;
_padding-right: 6px;
}
a.button,
a.button:visited {
*padding: 3px 8px 4px;
}
/* Buttons with images (full size only) */
button.icon,
a.icon,
a.icon:visited {
padding-left: 0;
position: relative;
text-indent: 29px;
}
/* Fix for IE7 within table cells ? */
td button {
*width: 100%;
*padding-right: 8px;
}
button:active,
a.button:active {
background-color: #4f6aa3;
background-position: 0 -100px;
border-bottom-color: #29447e;
}
button.green,
a.green,
a.green:visited {
background-color: #6da952;
background-position: 0 -50px;
border: 1px solid #3b6e22;
border-bottom-color: #2c5a15;
}
button.green:active,
a.green:active {
background-color: #5e9d43;
background-position: 0 -150px;
border-bottom-color: #3b6e22;
}
button.grey,
input.inputaux,
a.grey,
a.grey:visited,
a.button.disabled,
button.disabled {
background-color: #e4e5e5;
background-position: 0 -250px;
border: 1px solid #999;
border-bottom-color: #888;
color: #333;
box-shadow: 0px 1px 0px rgba(0,0,0,.07);
-moz-box-shadow: 0px 1px 0px rgba(0,0,0,.07);
-webkit-box-shadow: 0px 1px 0px rgba(0,0,0,.07);
}
a.disabled,
button.disabled {
filter:alpha(opacity=50);
-moz-opacity:0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
}
button.grey:active,
a.grey:active,
button.grey_active {
background-color: #dddddd;
background-position: 0 -200px;
border-bottom-color: #999;
}
button:active::-moz-focus-inner,
button:focus::-moz-focus-inner {
border-color: #405071;
}
button.green:active::-moz-focus-inner,
button.green:focus::-moz-focus-inner {
border-color: #4c713b;
}
button.grey:active::-moz-focus-inner,
button.grey:focus::-moz-focus-inner {
border-color: #666;
}
a.button:hover {
text-decoration: none;
}
button.small,
a.small,
a.small:visited {
padding: 2px 7px;
height: auto;
font-size: 11px;
line-height: 16px;
}
/******************************************************************************/
/* Aphront */
/******************************************************************************/
.aphront-standard-page {
background: #ffffff;
border-bottom: 1px solid #888888;
font-size: 14px;
-webkit-box-shadow: 0 0 6px #000;
-mox-box-shadow: 0 0 6px #000;
box-shadow: 0 0 6px #000;
}
.aphront-standard-header {
background: #003366;
color: white;
padding: 1em 1em 0.5em 1em;
overflow: hidden;
position: relative;
}
.aphront-standard-header a {
color: white;
}
.aphront-standard-header .aphront-head-tabs {
padding: 0 1em;
font-size: 13px;
font-weight: bold;
}
.aphront-standard-header .aphront-head-tabs a {
border-bottom: 3px solid transparent;
padding: 0.5em 0.75em;
position: relative;
bottom: 2px;
}
.aphront-standard-header .aphront-head-tabs a.aphront-selected-tab {
border-bottom-color: #cccccc;
}
.aphront-standard-header .aphront-head-appname {
padding: 0 1em;
text-transform: uppercase;
}
.aphront-directory-list {
margin: 1em 3% 8em;
}
.aphront-directory-category h1 {
border-bottom: 1px solid #cccccc;
margin-bottom: .5em;
padding-bottom: .1em;
}
.aphront-directory-list h2 {
font-size: 14px;
font-weight: bold;
padding: 0;
margin: 0;
}
.aphront-directory-list p {
color: #444444;
font-size: 12px;
padding: .05em .5em .5em;
}
.aphront-directory-category {
padding: 10px;
width: 300px;
float: left;
}
.aphront-directory-group {
padding: 0 .5em 3em;
}
.aphront-panel-view {
background: #f3f3f3;
border: 1px solid #c0c0c0;
border-width: 1px 0 0;
padding: 1em 2em;
margin: 1em 2em;
}
.aphront-panel-view h1 {
font-size: 14px;
font-weight: bold;
padding: 2px 0 8px;
}
.aphront-panel-view a.create-button {
float: right;
}
.aphront-panel-width-form {
width: 720px;
margin-right: auto;
margin-left: auto;
}
.aphront-table-view {
width: 100%;
border-collapse: collapse;
background: #fdfdfd;
border: 1px solid #003366;
}
.aphront-table-view tr.alt {
background: #efefef;
}
.aphront-table-view th {
font-size: 12px;
font-weight: bold;
padding: 4px 8px;
background: #003366;
color: white;
white-space: nowrap;
}
.aphront-table-view td.header {
padding: 4px 8px;
background: #3b5998;
color: white;
white-space: nowrap;
text-align: right;
}
.aphront-table-view td {
vertical-align: top;
padding: 4px 8px;
font-size: 11px;
white-space: nowrap;
}
.aphront-table-view td.action {
padding-top: 1px;
padding-bottom: 1px;
}
.aphront-table-view td.larger {
font-size: 14px;
}
.aphront-table-view td.pri {
font-weight: bold;
}
.aphront-table-view td.wide {
white-space: normal;
width: 100%;
}
.aphront-table-view td.right {
text-align: right;
}
.aphront-table-view td.mono {
font-family: "Monaco", monospace;
font-size: 10px;
}
.aphront-table-view tr.no-data td {
padding: 1em;
text-align: center;
color: #888888;
font-style: italic;
}
/******************************************************************************/
/* forms */
/******************************************************************************/
.aphront-form-view {
background: #e7e7e7;
border: 1px solid #c4c4c4;
padding: 1em;
}
.aphront-form-view label {
padding-top: 4px;
width: 14%;
float: left;
text-align: right;
font-weight: bold;
font-size: 13px;
color: #666666;
}
.aphront-form-input {
margin-left: 15%;
margin-right: 25%;
width: 60%;
}
.aphront-form-error {
width: 23%;
float: right;
color: #aa0000;
font-weight: bold;
padding-top: 4px;
}
.aphront-form-input input,
.aphront-form-input textarea {
font-size: 12px;
width: 100%;
}
.aphront-form-input textarea {
height: 12em;
}
.aphront-form-control {
padding: 4px;
}
.aphront-form-control-submit button,
.aphront-form-control-submit a.button {
float: right;
margin: 1em 0 0em 2%;
}
.aphront-form-view .aphront-form-caption {
font-size: 11px;
color: #444444;
text-align: right;
clear: both;
margin-right: 25%;
margin-left: 15%;
- margin-top: 3px;
- margin-bottom: 6px;
}
.aphront-error-view {
width: 720px;
margin: 1em auto;
border: 1px solid #aa0000;
padding: 1em;
background: #f9b9bc;
}
/******************************************************************************/
/* dialog */
/******************************************************************************/
.aphront-dialog-view {
width: 480px;
padding: 8px;
background: #666;
margin: auto;
}
.aphront-dialog-head {
background: #003366;
border: none;
font-size: 15px;
padding: 5px 12px 6px;
color: #ffffff;
}
.aphront-dialog-body {
background: #ffffff;
padding: 16px 12px;
border: none;
overflow: hidden;
}
.aphront-dialog-tail {
border: none;
background: #ededed;
padding: 0.5em;
text-align: right;
}
.aphront-dialog-tail button,
.aphront-dialog-tail a.button {
float: right;
margin-left: .5em;
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 29, 6:04 AM (2 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
188105
Default Alt Text
(57 KB)

Event Timeline