mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-30 02:32:42 +01:00
(stable) Promote 2015 Week 43
This commit is contained in:
commit
9520a6b0ed
54 changed files with 780 additions and 369 deletions
|
@ -373,6 +373,7 @@ return array(
|
||||||
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
|
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
|
||||||
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
|
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
|
||||||
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781',
|
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781',
|
||||||
|
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef',
|
||||||
'rsrc/js/application/files/behavior-icon-composer.js' => '8ef9ab58',
|
'rsrc/js/application/files/behavior-icon-composer.js' => '8ef9ab58',
|
||||||
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
|
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
|
||||||
'rsrc/js/application/herald/HeraldRuleEditor.js' => '91a6031b',
|
'rsrc/js/application/herald/HeraldRuleEditor.js' => '91a6031b',
|
||||||
|
@ -576,6 +577,7 @@ return array(
|
||||||
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
||||||
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
|
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
|
||||||
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
||||||
|
'javelin-behavior-drydock-live-operation-status' => '901935ef',
|
||||||
'javelin-behavior-durable-column' => 'c72aa091',
|
'javelin-behavior-durable-column' => 'c72aa091',
|
||||||
'javelin-behavior-error-log' => '6882e80a',
|
'javelin-behavior-error-log' => '6882e80a',
|
||||||
'javelin-behavior-event-all-day' => '38dcf3c8',
|
'javelin-behavior-event-all-day' => '38dcf3c8',
|
||||||
|
@ -1518,6 +1520,11 @@ return array(
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
),
|
),
|
||||||
|
'901935ef' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-request',
|
||||||
|
),
|
||||||
'91a6031b' => array(
|
'91a6031b' => array(
|
||||||
'multirow-row-manager',
|
'multirow-row-manager',
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
|
|
|
@ -885,6 +885,8 @@ phutil_register_library_map(array(
|
||||||
'DrydockRepositoryOperationPHIDType' => 'applications/drydock/phid/DrydockRepositoryOperationPHIDType.php',
|
'DrydockRepositoryOperationPHIDType' => 'applications/drydock/phid/DrydockRepositoryOperationPHIDType.php',
|
||||||
'DrydockRepositoryOperationQuery' => 'applications/drydock/query/DrydockRepositoryOperationQuery.php',
|
'DrydockRepositoryOperationQuery' => 'applications/drydock/query/DrydockRepositoryOperationQuery.php',
|
||||||
'DrydockRepositoryOperationSearchEngine' => 'applications/drydock/query/DrydockRepositoryOperationSearchEngine.php',
|
'DrydockRepositoryOperationSearchEngine' => 'applications/drydock/query/DrydockRepositoryOperationSearchEngine.php',
|
||||||
|
'DrydockRepositoryOperationStatusController' => 'applications/drydock/controller/DrydockRepositoryOperationStatusController.php',
|
||||||
|
'DrydockRepositoryOperationStatusView' => 'applications/drydock/view/DrydockRepositoryOperationStatusView.php',
|
||||||
'DrydockRepositoryOperationType' => 'applications/drydock/operation/DrydockRepositoryOperationType.php',
|
'DrydockRepositoryOperationType' => 'applications/drydock/operation/DrydockRepositoryOperationType.php',
|
||||||
'DrydockRepositoryOperationUpdateWorker' => 'applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php',
|
'DrydockRepositoryOperationUpdateWorker' => 'applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php',
|
||||||
'DrydockRepositoryOperationViewController' => 'applications/drydock/controller/DrydockRepositoryOperationViewController.php',
|
'DrydockRepositoryOperationViewController' => 'applications/drydock/controller/DrydockRepositoryOperationViewController.php',
|
||||||
|
@ -2552,6 +2554,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPasteRemarkupRule' => 'applications/paste/remarkup/PhabricatorPasteRemarkupRule.php',
|
'PhabricatorPasteRemarkupRule' => 'applications/paste/remarkup/PhabricatorPasteRemarkupRule.php',
|
||||||
'PhabricatorPasteSchemaSpec' => 'applications/paste/storage/PhabricatorPasteSchemaSpec.php',
|
'PhabricatorPasteSchemaSpec' => 'applications/paste/storage/PhabricatorPasteSchemaSpec.php',
|
||||||
'PhabricatorPasteSearchEngine' => 'applications/paste/query/PhabricatorPasteSearchEngine.php',
|
'PhabricatorPasteSearchEngine' => 'applications/paste/query/PhabricatorPasteSearchEngine.php',
|
||||||
|
'PhabricatorPasteSnippet' => 'applications/paste/snippet/PhabricatorPasteSnippet.php',
|
||||||
'PhabricatorPasteTestDataGenerator' => 'applications/paste/lipsum/PhabricatorPasteTestDataGenerator.php',
|
'PhabricatorPasteTestDataGenerator' => 'applications/paste/lipsum/PhabricatorPasteTestDataGenerator.php',
|
||||||
'PhabricatorPasteTransaction' => 'applications/paste/storage/PhabricatorPasteTransaction.php',
|
'PhabricatorPasteTransaction' => 'applications/paste/storage/PhabricatorPasteTransaction.php',
|
||||||
'PhabricatorPasteTransactionComment' => 'applications/paste/storage/PhabricatorPasteTransactionComment.php',
|
'PhabricatorPasteTransactionComment' => 'applications/paste/storage/PhabricatorPasteTransactionComment.php',
|
||||||
|
@ -4671,6 +4674,8 @@ phutil_register_library_map(array(
|
||||||
'DrydockRepositoryOperationPHIDType' => 'PhabricatorPHIDType',
|
'DrydockRepositoryOperationPHIDType' => 'PhabricatorPHIDType',
|
||||||
'DrydockRepositoryOperationQuery' => 'DrydockQuery',
|
'DrydockRepositoryOperationQuery' => 'DrydockQuery',
|
||||||
'DrydockRepositoryOperationSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'DrydockRepositoryOperationSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'DrydockRepositoryOperationStatusController' => 'DrydockController',
|
||||||
|
'DrydockRepositoryOperationStatusView' => 'AphrontView',
|
||||||
'DrydockRepositoryOperationType' => 'Phobject',
|
'DrydockRepositoryOperationType' => 'Phobject',
|
||||||
'DrydockRepositoryOperationUpdateWorker' => 'DrydockWorker',
|
'DrydockRepositoryOperationUpdateWorker' => 'DrydockWorker',
|
||||||
'DrydockRepositoryOperationViewController' => 'DrydockController',
|
'DrydockRepositoryOperationViewController' => 'DrydockController',
|
||||||
|
@ -6633,6 +6638,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPasteRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
'PhabricatorPasteRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||||
'PhabricatorPasteSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
'PhabricatorPasteSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||||
'PhabricatorPasteSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'PhabricatorPasteSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'PhabricatorPasteSnippet' => 'Phobject',
|
||||||
'PhabricatorPasteTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
'PhabricatorPasteTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
||||||
'PhabricatorPasteTransaction' => 'PhabricatorApplicationTransaction',
|
'PhabricatorPasteTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
'PhabricatorPasteTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
'PhabricatorPasteTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||||
|
|
|
@ -113,6 +113,27 @@ final class PhabricatorAuthLoginController
|
||||||
$provider->getProviderName()));
|
$provider->getProviderName()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// If the user already has a linked account of this type, prevent them
|
||||||
|
// from linking a second account. This can happen if they swap logins
|
||||||
|
// and then refresh the account link. See T6707. We will eventually
|
||||||
|
// allow this after T2549.
|
||||||
|
$existing_accounts = id(new PhabricatorExternalAccountQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withUserPHIDs(array($viewer->getPHID()))
|
||||||
|
->withAccountTypes(array($account->getAccountType()))
|
||||||
|
->execute();
|
||||||
|
if ($existing_accounts) {
|
||||||
|
return $this->renderError(
|
||||||
|
pht(
|
||||||
|
'Your Phabricator account is already connected to an external '.
|
||||||
|
'account on this provider ("%s"), but you are currently logged '.
|
||||||
|
'in to the provider with a different account. Log out of the '.
|
||||||
|
'external service, then log back in with the correct account '.
|
||||||
|
'before refreshing the account link.',
|
||||||
|
$provider->getProviderName()));
|
||||||
|
}
|
||||||
|
|
||||||
if ($provider->shouldAllowAccountLink()) {
|
if ($provider->shouldAllowAccountLink()) {
|
||||||
return $this->processLinkUser($account);
|
return $this->processLinkUser($account);
|
||||||
} else {
|
} else {
|
||||||
|
|
36
src/applications/cache/PhabricatorCaches.php
vendored
36
src/applications/cache/PhabricatorCaches.php
vendored
|
@ -206,40 +206,12 @@ final class PhabricatorCaches extends Phobject {
|
||||||
// otherwise (we desire this property to give the cache the best hit rate
|
// otherwise (we desire this property to give the cache the best hit rate
|
||||||
// we can).
|
// we can).
|
||||||
|
|
||||||
// In some setups, the parent PID is more stable and longer-lived that the
|
// Unfortunately, we don't have a very good strategy for minimizing the
|
||||||
// PID (e.g., under apache, our PID will be a worker while the ppid will
|
// churn rate of the cache. We previously tried to use the parent process
|
||||||
// be the main httpd process). If we're confident we're running under such
|
// PID in some cases, but this was not reliable. See T9599 for one case of
|
||||||
// a setup, we can try to use the PPID as the basis for our cache instead
|
// this.
|
||||||
// of our own PID.
|
|
||||||
$use_ppid = false;
|
|
||||||
|
|
||||||
switch (php_sapi_name()) {
|
|
||||||
case 'cli-server':
|
|
||||||
// This is the PHP5.4+ built-in webserver. We should use the pid
|
|
||||||
// (the server), not the ppid (probably a shell or something).
|
|
||||||
$use_ppid = false;
|
|
||||||
break;
|
|
||||||
case 'fpm-fcgi':
|
|
||||||
// We should be safe to use PPID here.
|
|
||||||
$use_ppid = true;
|
|
||||||
break;
|
|
||||||
case 'apache2handler':
|
|
||||||
// We're definitely safe to use the PPID.
|
|
||||||
$use_ppid = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pid_basis = getmypid();
|
$pid_basis = getmypid();
|
||||||
if ($use_ppid) {
|
|
||||||
if (function_exists('posix_getppid')) {
|
|
||||||
$parent_pid = posix_getppid();
|
|
||||||
// On most systems, normal processes can never have PIDs lower than 100,
|
|
||||||
// so something likely went wrong if we we get one of these.
|
|
||||||
if ($parent_pid > 100) {
|
|
||||||
$pid_basis = $parent_pid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If possible, we also want to know when the process launched, so we can
|
// If possible, we also want to know when the process launched, so we can
|
||||||
// drop the cache if a process restarts but gets the same PID an earlier
|
// drop the cache if a process restarts but gets the same PID an earlier
|
||||||
|
|
|
@ -63,7 +63,9 @@ final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec {
|
||||||
private function initNoneSpec() {
|
private function initNoneSpec() {
|
||||||
if (version_compare(phpversion(), '5.5', '>=')) {
|
if (version_compare(phpversion(), '5.5', '>=')) {
|
||||||
$message = pht(
|
$message = pht(
|
||||||
'Installing the "APCu" PHP extension will improve performance.');
|
'Installing the "APCu" PHP extension will improve performance. '.
|
||||||
|
'This extension is strongly recommended. Without it, Phabricator '.
|
||||||
|
'must rely on a very inefficient disk-based cache.');
|
||||||
|
|
||||||
$this
|
$this
|
||||||
->newIssue('extension.apcu')
|
->newIssue('extension.apcu')
|
||||||
|
|
|
@ -7,18 +7,9 @@ final class PhabricatorConduitAPIController
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private $method;
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$method = $request->getURIData('method');
|
||||||
public function willProcessRequest(array $data) {
|
|
||||||
$this->method = $data['method'];
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$time_start = microtime(true);
|
$time_start = microtime(true);
|
||||||
$request = $this->getRequest();
|
|
||||||
|
|
||||||
$method = $this->method;
|
|
||||||
|
|
||||||
$api_request = null;
|
$api_request = null;
|
||||||
$method_implementation = null;
|
$method_implementation = null;
|
||||||
|
@ -55,7 +46,7 @@ final class PhabricatorConduitAPIController
|
||||||
$conduit_username = '-';
|
$conduit_username = '-';
|
||||||
if ($call->shouldRequireAuthentication()) {
|
if ($call->shouldRequireAuthentication()) {
|
||||||
$metadata['scope'] = $call->getRequiredScope();
|
$metadata['scope'] = $call->getRequiredScope();
|
||||||
$auth_error = $this->authenticateUser($api_request, $metadata);
|
$auth_error = $this->authenticateUser($api_request, $metadata, $method);
|
||||||
// If we've explicitly authenticated the user here and either done
|
// If we've explicitly authenticated the user here and either done
|
||||||
// CSRF validation or are using a non-web authentication mechanism.
|
// CSRF validation or are using a non-web authentication mechanism.
|
||||||
$allow_unguarded_writes = true;
|
$allow_unguarded_writes = true;
|
||||||
|
@ -169,7 +160,8 @@ final class PhabricatorConduitAPIController
|
||||||
*/
|
*/
|
||||||
private function authenticateUser(
|
private function authenticateUser(
|
||||||
ConduitAPIRequest $api_request,
|
ConduitAPIRequest $api_request,
|
||||||
array $metadata) {
|
array $metadata,
|
||||||
|
$method) {
|
||||||
|
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
|
|
||||||
|
@ -207,7 +199,7 @@ final class PhabricatorConduitAPIController
|
||||||
unset($protocol_data['scope']);
|
unset($protocol_data['scope']);
|
||||||
|
|
||||||
ConduitClient::verifySignature(
|
ConduitClient::verifySignature(
|
||||||
$this->method,
|
$method,
|
||||||
$api_request->getAllParameters(),
|
$api_request->getAllParameters(),
|
||||||
$protocol_data,
|
$protocol_data,
|
||||||
$ssl_public_key);
|
$ssl_public_key);
|
||||||
|
|
|
@ -3,19 +3,13 @@
|
||||||
final class PhabricatorConduitListController
|
final class PhabricatorConduitListController
|
||||||
extends PhabricatorConduitController {
|
extends PhabricatorConduitController {
|
||||||
|
|
||||||
private $queryKey;
|
|
||||||
|
|
||||||
public function shouldAllowPublic() {
|
public function shouldAllowPublic() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$this->queryKey = idx($data, 'queryKey');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$controller = id(new PhabricatorApplicationSearchController())
|
$controller = id(new PhabricatorApplicationSearchController())
|
||||||
->setQueryKey($this->queryKey)
|
->setQueryKey($request->getURIData('queryKey'))
|
||||||
->setSearchEngine(new PhabricatorConduitSearchEngine())
|
->setSearchEngine(new PhabricatorConduitSearchEngine())
|
||||||
->setNavigation($this->buildSideNavView());
|
->setNavigation($this->buildSideNavView());
|
||||||
return $this->delegateToController($controller);
|
return $this->delegateToController($controller);
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
final class PhabricatorConduitLogController
|
final class PhabricatorConduitLogController
|
||||||
extends PhabricatorConduitController {
|
extends PhabricatorConduitController {
|
||||||
|
|
||||||
public function processRequest() {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$request = $this->getRequest();
|
$viewer = $request->getViewer();
|
||||||
$viewer = $request->getUser();
|
|
||||||
|
|
||||||
$conn_table = new PhabricatorConduitConnectionLog();
|
$conn_table = new PhabricatorConduitConnectionLog();
|
||||||
$call_table = new PhabricatorConduitMethodCallLog();
|
$call_table = new PhabricatorConduitMethodCallLog();
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
final class PhabricatorConduitTokenController
|
final class PhabricatorConduitTokenController
|
||||||
extends PhabricatorConduitController {
|
extends PhabricatorConduitController {
|
||||||
|
|
||||||
public function processRequest() {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$user = $this->getRequest()->getUser();
|
$viewer = $request->getViewer();
|
||||||
|
|
||||||
id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
|
id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
|
||||||
$user,
|
$viewer,
|
||||||
$this->getRequest(),
|
$this->getRequest(),
|
||||||
'/');
|
'/');
|
||||||
|
|
||||||
|
@ -19,13 +19,13 @@ final class PhabricatorConduitTokenController
|
||||||
$old_token = id(new PhabricatorConduitCertificateToken())
|
$old_token = id(new PhabricatorConduitCertificateToken())
|
||||||
->loadOneWhere(
|
->loadOneWhere(
|
||||||
'userPHID = %s',
|
'userPHID = %s',
|
||||||
$user->getPHID());
|
$viewer->getPHID());
|
||||||
if ($old_token) {
|
if ($old_token) {
|
||||||
$old_token->delete();
|
$old_token->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = id(new PhabricatorConduitCertificateToken())
|
$token = id(new PhabricatorConduitCertificateToken())
|
||||||
->setUserPHID($user->getPHID())
|
->setUserPHID($viewer->getPHID())
|
||||||
->setToken(Filesystem::readRandomCharacters(40))
|
->setToken(Filesystem::readRandomCharacters(40))
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ final class PhabricatorConduitTokenController
|
||||||
Javelin::initBehavior('select-on-click');
|
Javelin::initBehavior('select-on-click');
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
$form = id(new AphrontFormView())
|
||||||
->setUser($user)
|
->setUser($viewer)
|
||||||
->appendRemarkupInstructions($pre_instructions)
|
->appendRemarkupInstructions($pre_instructions)
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormTextAreaControl())
|
id(new AphrontFormTextAreaControl())
|
||||||
|
|
|
@ -5,8 +5,8 @@ final class PhabricatorConduitTokenEditController
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$viewer = $request->getViewer();
|
$viewer = $request->getViewer();
|
||||||
|
|
||||||
$id = $request->getURIData('id');
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
if ($id) {
|
if ($id) {
|
||||||
$token = id(new PhabricatorConduitTokenQuery())
|
$token = id(new PhabricatorConduitTokenQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
|
|
|
@ -5,9 +5,9 @@ final class PhabricatorConduitTokenTerminateController
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$viewer = $request->getViewer();
|
$viewer = $request->getViewer();
|
||||||
|
|
||||||
$object_phid = $request->getStr('objectPHID');
|
$object_phid = $request->getStr('objectPHID');
|
||||||
$id = $request->getURIData('id');
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
if ($id) {
|
if ($id) {
|
||||||
$token = id(new PhabricatorConduitTokenQuery())
|
$token = id(new PhabricatorConduitTokenQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
|
|
|
@ -225,18 +225,8 @@ final class PhabricatorConfigWelcomeController
|
||||||
'fa-globe',
|
'fa-globe',
|
||||||
$content);
|
$content);
|
||||||
|
|
||||||
$support_href = PhabricatorEnv::getDoclink('Give Feedback! Get Support!');
|
// TODO: Restore some sort of "Support" link here, but just nuke it for
|
||||||
$content = pht(
|
// now as we figure stuff out.
|
||||||
"=== Need Help with Setup? ===\n\n".
|
|
||||||
'Having trouble getting something set up? See '.
|
|
||||||
'**[[ %s | Give Feedback! Get Support! ]]** for ways to get in touch '.
|
|
||||||
'to get answers to questions, report bugs, and request features.',
|
|
||||||
$support_href);
|
|
||||||
|
|
||||||
$explore[] = $this->newItem(
|
|
||||||
$request,
|
|
||||||
'fa-life-ring',
|
|
||||||
$content);
|
|
||||||
|
|
||||||
$differential_uri = PhabricatorEnv::getURI('/differential/');
|
$differential_uri = PhabricatorEnv::getURI('/differential/');
|
||||||
$differential_create_uri = PhabricatorEnv::getURI(
|
$differential_create_uri = PhabricatorEnv::getURI(
|
||||||
|
|
|
@ -20,8 +20,6 @@ final class PhabricatorSecurityConfigOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOptions() {
|
public function getOptions() {
|
||||||
$support_href = PhabricatorEnv::getDoclink('Give Feedback! Get Support!');
|
|
||||||
|
|
||||||
$doc_href = PhabricatorEnv::getDoclink('Configuring a File Domain');
|
$doc_href = PhabricatorEnv::getDoclink('Configuring a File Domain');
|
||||||
$doc_name = pht('Configuration Guide: Configuring a File Domain');
|
$doc_name = pht('Configuration Guide: Configuring a File Domain');
|
||||||
|
|
||||||
|
@ -197,11 +195,8 @@ final class PhabricatorSecurityConfigOptions
|
||||||
->setSummary(pht('Whitelists editor protocols for "Open in Editor".'))
|
->setSummary(pht('Whitelists editor protocols for "Open in Editor".'))
|
||||||
->setDescription(
|
->setDescription(
|
||||||
pht(
|
pht(
|
||||||
"Users can configure a URI pattern to open files in a text ".
|
'Users can configure a URI pattern to open files in a text '.
|
||||||
"editor. The URI must use a protocol on this whitelist.\n\n".
|
'editor. The URI must use a protocol on this whitelist.'))
|
||||||
"(If you use an editor which defines a protocol not on this ".
|
|
||||||
"list, [[ %s | let us know ]] and we'll update the defaults.)",
|
|
||||||
$support_href))
|
|
||||||
->setLocked(true),
|
->setLocked(true),
|
||||||
$this->newOption(
|
$this->newOption(
|
||||||
'celerity.resource-hash',
|
'celerity.resource-hash',
|
||||||
|
|
|
@ -1060,30 +1060,13 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
||||||
|
|
||||||
$operation = head(msort($operations, 'getID'));
|
$operation = head(msort($operations, 'getID'));
|
||||||
|
|
||||||
// TODO: This is completely made up for now, give it useful information and
|
$box_view = id(new PHUIObjectBoxView())
|
||||||
// a sweet progress bar.
|
->setHeaderText(pht('Active Operations'));
|
||||||
|
|
||||||
switch ($operation->getOperationState()) {
|
return id(new DrydockRepositoryOperationStatusView())
|
||||||
case DrydockRepositoryOperation::STATE_WAIT:
|
->setUser($viewer)
|
||||||
case DrydockRepositoryOperation::STATE_WORK:
|
->setBoxView($box_view)
|
||||||
$severity = PHUIInfoView::SEVERITY_NOTICE;
|
->setOperation($operation);
|
||||||
$text = pht(
|
|
||||||
'Some sort of repository operation is currently running.');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$severity = PHUIInfoView::SEVERITY_ERROR;
|
|
||||||
$text = pht(
|
|
||||||
'Some sort of repository operation failed.');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$info_view = id(new PHUIInfoView())
|
|
||||||
->setSeverity($severity)
|
|
||||||
->appendChild($text);
|
|
||||||
|
|
||||||
return id(new PHUIObjectBoxView())
|
|
||||||
->setHeaderText(pht('Active Operations (EXPERIMENTAL!)'))
|
|
||||||
->setInfoView($info_view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ final class DiffusionBrowseFileController extends DiffusionBrowseController {
|
||||||
|
|
||||||
$repo = $drequest->getRepository();
|
$repo = $drequest->getRepository();
|
||||||
$symbol_repos = nonempty($repo->getSymbolSources(), array());
|
$symbol_repos = nonempty($repo->getSymbolSources(), array());
|
||||||
$symbol_repos[] = $repo;
|
$symbol_repos[] = $repo->getPHID();
|
||||||
|
|
||||||
$lang = last(explode('.', $drequest->getPath()));
|
$lang = last(explode('.', $drequest->getPath()));
|
||||||
$repo_languages = $repo->getSymbolLanguages();
|
$repo_languages = $repo->getSymbolLanguages();
|
||||||
|
|
|
@ -95,6 +95,7 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication {
|
||||||
=> 'DrydockRepositoryOperationListController',
|
=> 'DrydockRepositoryOperationListController',
|
||||||
'(?P<id>[1-9]\d*)/' => array(
|
'(?P<id>[1-9]\d*)/' => array(
|
||||||
'' => 'DrydockRepositoryOperationViewController',
|
'' => 'DrydockRepositoryOperationViewController',
|
||||||
|
'status/' => 'DrydockRepositoryOperationStatusController',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DrydockRepositoryOperationStatusController
|
||||||
|
extends DrydockController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $request->getViewer();
|
||||||
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
|
$operation = id(new DrydockRepositoryOperationQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->executeOne();
|
||||||
|
if (!$operation) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = $operation->getID();
|
||||||
|
|
||||||
|
$status_view = id(new DrydockRepositoryOperationStatusView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setOperation($operation);
|
||||||
|
|
||||||
|
if ($request->isAjax()) {
|
||||||
|
$payload = array(
|
||||||
|
'markup' => $status_view->renderUnderwayState(),
|
||||||
|
'isUnderway' => $operation->isUnderway(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())
|
||||||
|
->setContent($payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = pht('Repository Operation %d', $id);
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
$crumbs->addTextCrumb(
|
||||||
|
pht('Operations'),
|
||||||
|
$this->getApplicationURI('operation/'));
|
||||||
|
$crumbs->addTextCrumb($title);
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$status_view,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => array(
|
||||||
|
$title,
|
||||||
|
pht('Status'),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,6 +11,30 @@ final class DrydockLandRepositoryOperation
|
||||||
return pht('Land Revision');
|
return pht('Land Revision');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOperationCurrentStatus(
|
||||||
|
DrydockRepositoryOperation $operation,
|
||||||
|
PhabricatorUser $viewer) {
|
||||||
|
|
||||||
|
$target = $operation->getRepositoryTarget();
|
||||||
|
$repository = $operation->getRepository();
|
||||||
|
switch ($operation->getOperationState()) {
|
||||||
|
case DrydockRepositoryOperation::STATE_WAIT:
|
||||||
|
return pht(
|
||||||
|
'Waiting to land revision into %s on %s...',
|
||||||
|
$repository->getMonogram(),
|
||||||
|
$target);
|
||||||
|
case DrydockRepositoryOperation::STATE_WORK:
|
||||||
|
return pht(
|
||||||
|
'Landing revision into %s on %s...',
|
||||||
|
$repository->getMonogram(),
|
||||||
|
$target);
|
||||||
|
case DrydockRepositoryOperation::STATE_DONE:
|
||||||
|
return pht(
|
||||||
|
'Revision landed into %s.',
|
||||||
|
$repository->getMonogram());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function applyOperation(
|
public function applyOperation(
|
||||||
DrydockRepositoryOperation $operation,
|
DrydockRepositoryOperation $operation,
|
||||||
DrydockInterface $interface) {
|
DrydockInterface $interface) {
|
||||||
|
|
|
@ -12,6 +12,10 @@ abstract class DrydockRepositoryOperationType extends Phobject {
|
||||||
DrydockRepositoryOperation $operation,
|
DrydockRepositoryOperation $operation,
|
||||||
PhabricatorUser $viewer);
|
PhabricatorUser $viewer);
|
||||||
|
|
||||||
|
abstract public function getOperationCurrentStatus(
|
||||||
|
DrydockRepositoryOperation $operation,
|
||||||
|
PhabricatorUser $viewer);
|
||||||
|
|
||||||
final public function setViewer(PhabricatorUser $viewer) {
|
final public function setViewer(PhabricatorUser $viewer) {
|
||||||
$this->viewer = $viewer;
|
$this->viewer = $viewer;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -142,6 +142,22 @@ final class DrydockRepositoryOperation extends DrydockDAO
|
||||||
$viewer);
|
$viewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOperationCurrentStatus(PhabricatorUser $viewer) {
|
||||||
|
return $this->getImplementation()->getOperationCurrentStatus(
|
||||||
|
$this,
|
||||||
|
$viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isUnderway() {
|
||||||
|
switch ($this->getOperationState()) {
|
||||||
|
case self::STATE_WAIT:
|
||||||
|
case self::STATE_WORK:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DrydockRepositoryOperationStatusView
|
||||||
|
extends AphrontView {
|
||||||
|
|
||||||
|
private $operation;
|
||||||
|
private $boxView;
|
||||||
|
|
||||||
|
public function setOperation(DrydockRepositoryOperation $operation) {
|
||||||
|
$this->operation = $operation;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOperation() {
|
||||||
|
return $this->operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setBoxView(PHUIObjectBoxView $box_view) {
|
||||||
|
$this->boxView = $box_view;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBoxView() {
|
||||||
|
return $this->boxView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
$viewer = $this->getUser();
|
||||||
|
$operation = $this->getOperation();
|
||||||
|
|
||||||
|
$list = $this->renderUnderwayState();
|
||||||
|
|
||||||
|
// If the operation is currently underway, refresh the status view.
|
||||||
|
if ($operation->isUnderway()) {
|
||||||
|
$status_id = celerity_generate_unique_node_id();
|
||||||
|
$id = $operation->getID();
|
||||||
|
|
||||||
|
$list->setID($status_id);
|
||||||
|
|
||||||
|
Javelin::initBehavior(
|
||||||
|
'drydock-live-operation-status',
|
||||||
|
array(
|
||||||
|
'statusID' => $status_id,
|
||||||
|
'updateURI' => "/drydock/operation/{$id}/status/",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$box_view = $this->getBoxView();
|
||||||
|
if (!$box_view) {
|
||||||
|
$box_view = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText(pht('Operation Status'));
|
||||||
|
}
|
||||||
|
$box_view->setObjectList($list);
|
||||||
|
|
||||||
|
return $box_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderUnderwayState() {
|
||||||
|
$viewer = $this->getUser();
|
||||||
|
$operation = $this->getOperation();
|
||||||
|
|
||||||
|
$id = $operation->getID();
|
||||||
|
|
||||||
|
$state = $operation->getOperationState();
|
||||||
|
$icon = DrydockRepositoryOperation::getOperationStateIcon($state);
|
||||||
|
$name = DrydockRepositoryOperation::getOperationStateName($state);
|
||||||
|
|
||||||
|
$item = id(new PHUIObjectItemView())
|
||||||
|
->setHref("/drydock/operation/{$id}/")
|
||||||
|
->setHeader($operation->getOperationDescription($viewer))
|
||||||
|
->setStatusIcon($icon, $name);
|
||||||
|
|
||||||
|
if ($state != DrydockRepositoryOperation::STATE_FAIL) {
|
||||||
|
$item->addAttribute($operation->getOperationCurrentStatus($viewer));
|
||||||
|
} else {
|
||||||
|
// TODO: Make this more useful.
|
||||||
|
$item->addAttribute(pht('Operation encountered an error.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PHUIObjectItemListView())
|
||||||
|
->addItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -381,7 +381,6 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
|
|
||||||
private function buildActionView(ManiphestTask $task) {
|
private function buildActionView(ManiphestTask $task) {
|
||||||
$viewer = $this->getRequest()->getUser();
|
$viewer = $this->getRequest()->getUser();
|
||||||
$viewer_phid = $viewer->getPHID();
|
|
||||||
|
|
||||||
$id = $task->getID();
|
$id = $task->getID();
|
||||||
$phid = $task->getPHID();
|
$phid = $task->getPHID();
|
||||||
|
@ -391,6 +390,8 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
$task,
|
$task,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT);
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
|
$can_create = $viewer->isLoggedIn();
|
||||||
|
|
||||||
$view = id(new PhabricatorActionListView())
|
$view = id(new PhabricatorActionListView())
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->setObject($task)
|
->setObject($task)
|
||||||
|
@ -417,7 +418,9 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
id(new PhabricatorActionView())
|
id(new PhabricatorActionView())
|
||||||
->setName(pht('Create Subtask'))
|
->setName(pht('Create Subtask'))
|
||||||
->setHref($this->getApplicationURI("/task/create/?parent={$id}"))
|
->setHref($this->getApplicationURI("/task/create/?parent={$id}"))
|
||||||
->setIcon('fa-level-down'));
|
->setIcon('fa-level-down')
|
||||||
|
->setDisabled(!$can_create)
|
||||||
|
->setWorkflow(!$can_create));
|
||||||
|
|
||||||
$view->addAction(
|
$view->addAction(
|
||||||
id(new PhabricatorActionView())
|
id(new PhabricatorActionView())
|
||||||
|
|
|
@ -145,7 +145,12 @@ final class PhabricatorApplicationEditController
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->setObject($template_object)
|
->setObject($template_object)
|
||||||
->execute();
|
->execute();
|
||||||
$control->setPolicies($template_policies);
|
|
||||||
|
// NOTE: We want to expose both any object template policies
|
||||||
|
// (like "Subscribers") and any custom policy.
|
||||||
|
$all_policies = $template_policies + $policies;
|
||||||
|
|
||||||
|
$control->setPolicies($all_policies);
|
||||||
$control->setTemplateObject($template_object);
|
$control->setTemplateObject($template_object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,7 @@ final class PhabricatorContentSource extends Phobject {
|
||||||
public static function newFromRequest(AphrontRequest $request) {
|
public static function newFromRequest(AphrontRequest $request) {
|
||||||
return self::newForSource(
|
return self::newForSource(
|
||||||
self::SOURCE_WEB,
|
self::SOURCE_WEB,
|
||||||
array(
|
array());
|
||||||
'ip' => $request->getRemoteAddr(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function newFromConduitRequest(ConduitAPIRequest $request) {
|
public static function newFromConduitRequest(ConduitAPIRequest $request) {
|
||||||
|
|
|
@ -39,13 +39,11 @@ abstract class PhabricatorPasteController extends PhabricatorController {
|
||||||
|
|
||||||
public function buildSourceCodeView(
|
public function buildSourceCodeView(
|
||||||
PhabricatorPaste $paste,
|
PhabricatorPaste $paste,
|
||||||
$max_lines = null,
|
|
||||||
$highlights = array()) {
|
$highlights = array()) {
|
||||||
|
|
||||||
$lines = phutil_split_lines($paste->getContent());
|
$lines = phutil_split_lines($paste->getContent());
|
||||||
|
|
||||||
return id(new PhabricatorSourceCodeView())
|
return id(new PhabricatorSourceCodeView())
|
||||||
->setLimit($max_lines)
|
|
||||||
->setLines($lines)
|
->setLines($lines)
|
||||||
->setHighlights($highlights)
|
->setHighlights($highlights)
|
||||||
->setURI(new PhutilURI($paste->getURI()));
|
->setURI(new PhutilURI($paste->getURI()));
|
||||||
|
|
|
@ -56,10 +56,7 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController {
|
||||||
->setHeader($header)
|
->setHeader($header)
|
||||||
->addPropertyList($properties);
|
->addPropertyList($properties);
|
||||||
|
|
||||||
$source_code = $this->buildSourceCodeView(
|
$source_code = $this->buildSourceCodeView($paste, $this->highlightMap);
|
||||||
$paste,
|
|
||||||
null,
|
|
||||||
$this->highlightMap);
|
|
||||||
|
|
||||||
require_celerity_resource('paste-css');
|
require_celerity_resource('paste-css');
|
||||||
$source_code = phutil_tag(
|
$source_code = phutil_tag(
|
||||||
|
|
|
@ -10,6 +10,7 @@ final class PhabricatorPasteQuery
|
||||||
|
|
||||||
private $needContent;
|
private $needContent;
|
||||||
private $needRawContent;
|
private $needRawContent;
|
||||||
|
private $needSnippets;
|
||||||
private $languages;
|
private $languages;
|
||||||
private $includeNoLanguage;
|
private $includeNoLanguage;
|
||||||
private $dateCreatedAfter;
|
private $dateCreatedAfter;
|
||||||
|
@ -47,6 +48,11 @@ final class PhabricatorPasteQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function needSnippets($need_snippets) {
|
||||||
|
$this->needSnippets = $need_snippets;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function withLanguages(array $languages) {
|
public function withLanguages(array $languages) {
|
||||||
$this->includeNoLanguage = false;
|
$this->includeNoLanguage = false;
|
||||||
foreach ($languages as $key => $language) {
|
foreach ($languages as $key => $language) {
|
||||||
|
@ -91,6 +97,10 @@ final class PhabricatorPasteQuery
|
||||||
$pastes = $this->loadContent($pastes);
|
$pastes = $this->loadContent($pastes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->needSnippets) {
|
||||||
|
$pastes = $this->loadSnippets($pastes);
|
||||||
|
}
|
||||||
|
|
||||||
return $pastes;
|
return $pastes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +176,17 @@ final class PhabricatorPasteQuery
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getSnippetCacheKey(PhabricatorPaste $paste) {
|
||||||
|
return implode(
|
||||||
|
':',
|
||||||
|
array(
|
||||||
|
'P'.$paste->getID(),
|
||||||
|
$paste->getFilePHID(),
|
||||||
|
$paste->getLanguage(),
|
||||||
|
'snippet',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
private function loadRawContent(array $pastes) {
|
private function loadRawContent(array $pastes) {
|
||||||
$file_phids = mpull($pastes, 'getFilePHID');
|
$file_phids = mpull($pastes, 'getFilePHID');
|
||||||
$files = id(new PhabricatorFileQuery())
|
$files = id(new PhabricatorFileQuery())
|
||||||
|
@ -250,13 +271,108 @@ final class PhabricatorPasteQuery
|
||||||
return $pastes;
|
return $pastes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildContent(PhabricatorPaste $paste) {
|
private function loadSnippets(array $pastes) {
|
||||||
$language = $paste->getLanguage();
|
$cache = new PhabricatorKeyValueDatabaseCache();
|
||||||
$source = $paste->getRawContent();
|
|
||||||
|
|
||||||
|
$cache = new PhutilKeyValueCacheProfiler($cache);
|
||||||
|
$cache->setProfiler(PhutilServiceProfiler::getInstance());
|
||||||
|
|
||||||
|
$keys = array();
|
||||||
|
foreach ($pastes as $paste) {
|
||||||
|
$keys[] = $this->getSnippetCacheKey($paste);
|
||||||
|
}
|
||||||
|
|
||||||
|
$caches = $cache->getKeys($keys);
|
||||||
|
|
||||||
|
$need_raw = array();
|
||||||
|
$have_cache = array();
|
||||||
|
foreach ($pastes as $paste) {
|
||||||
|
$key = $this->getSnippetCacheKey($paste);
|
||||||
|
if (isset($caches[$key])) {
|
||||||
|
$snippet_data = phutil_json_decode($caches[$key], true);
|
||||||
|
$snippet = new PhabricatorPasteSnippet(
|
||||||
|
phutil_safe_html($snippet_data['content']),
|
||||||
|
$snippet_data['type']);
|
||||||
|
$paste->attachSnippet($snippet);
|
||||||
|
$have_cache[$paste->getPHID()] = true;
|
||||||
|
} else {
|
||||||
|
$need_raw[$key] = $paste;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$need_raw) {
|
||||||
|
return $pastes;
|
||||||
|
}
|
||||||
|
|
||||||
|
$write_data = array();
|
||||||
|
|
||||||
|
$have_raw = $this->loadRawContent($need_raw);
|
||||||
|
$have_raw = mpull($have_raw, null, 'getPHID');
|
||||||
|
foreach ($pastes as $key => $paste) {
|
||||||
|
$paste_phid = $paste->getPHID();
|
||||||
|
if (isset($have_cache[$paste_phid])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($have_raw[$paste_phid])) {
|
||||||
|
unset($pastes[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$snippet = $this->buildSnippet($paste);
|
||||||
|
$paste->attachSnippet($snippet);
|
||||||
|
$snippet_data = array(
|
||||||
|
'content' => (string)$snippet->getContent(),
|
||||||
|
'type' => (string)$snippet->getType(),
|
||||||
|
);
|
||||||
|
$write_data[$this->getSnippetCacheKey($paste)] = phutil_json_encode(
|
||||||
|
$snippet_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($write_data) {
|
||||||
|
$cache->setKeys($write_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pastes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildContent(PhabricatorPaste $paste) {
|
||||||
|
return $this->highlightSource(
|
||||||
|
$paste->getRawContent(),
|
||||||
|
$paste->getTitle(),
|
||||||
|
$paste->getLanguage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildSnippet(PhabricatorPaste $paste) {
|
||||||
|
$snippet_type = PhabricatorPasteSnippet::FULL;
|
||||||
|
$snippet = $paste->getRawContent();
|
||||||
|
|
||||||
|
if (strlen($snippet) > 1024) {
|
||||||
|
$snippet_type = PhabricatorPasteSnippet::FIRST_BYTES;
|
||||||
|
$snippet = id(new PhutilUTF8StringTruncator())
|
||||||
|
->setMaximumBytes(1024)
|
||||||
|
->setTerminator('')
|
||||||
|
->truncateString($snippet);
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines = phutil_split_lines($snippet);
|
||||||
|
if (count($lines) > 5) {
|
||||||
|
$snippet_type = PhabricatorPasteSnippet::FIRST_LINES;
|
||||||
|
$snippet = implode('', array_slice($lines, 0, 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PhabricatorPasteSnippet(
|
||||||
|
$this->highlightSource(
|
||||||
|
$snippet,
|
||||||
|
$paste->getTitle(),
|
||||||
|
$paste->getLanguage()),
|
||||||
|
$snippet_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function highlightSource($source, $title, $language) {
|
||||||
if (empty($language)) {
|
if (empty($language)) {
|
||||||
return PhabricatorSyntaxHighlighter::highlightWithFilename(
|
return PhabricatorSyntaxHighlighter::highlightWithFilename(
|
||||||
$paste->getTitle(),
|
$title,
|
||||||
$source);
|
$source);
|
||||||
} else {
|
} else {
|
||||||
return PhabricatorSyntaxHighlighter::highlightWithLanguage(
|
return PhabricatorSyntaxHighlighter::highlightWithLanguage(
|
||||||
|
|
|
@ -13,7 +13,7 @@ final class PhabricatorPasteSearchEngine
|
||||||
|
|
||||||
public function newQuery() {
|
public function newQuery() {
|
||||||
return id(new PhabricatorPasteQuery())
|
return id(new PhabricatorPasteQuery())
|
||||||
->needContent(true);
|
->needSnippets(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildQueryFromParameters(array $map) {
|
protected function buildQueryFromParameters(array $map) {
|
||||||
|
@ -136,11 +136,15 @@ final class PhabricatorPasteSearchEngine
|
||||||
$created = phabricator_date($paste->getDateCreated(), $viewer);
|
$created = phabricator_date($paste->getDateCreated(), $viewer);
|
||||||
$author = $handles[$paste->getAuthorPHID()]->renderLink();
|
$author = $handles[$paste->getAuthorPHID()]->renderLink();
|
||||||
|
|
||||||
$lines = phutil_split_lines($paste->getContent());
|
$snippet_type = $paste->getSnippet()->getType();
|
||||||
|
$lines = phutil_split_lines($paste->getSnippet()->getContent());
|
||||||
|
|
||||||
$preview = id(new PhabricatorSourceCodeView())
|
$preview = id(new PhabricatorSourceCodeView())
|
||||||
->setLimit(5)
|
|
||||||
->setLines($lines)
|
->setLines($lines)
|
||||||
|
->setTruncatedFirstBytes(
|
||||||
|
$snippet_type == PhabricatorPasteSnippet::FIRST_BYTES)
|
||||||
|
->setTruncatedFirstLines(
|
||||||
|
$snippet_type == PhabricatorPasteSnippet::FIRST_LINES)
|
||||||
->setURI(new PhutilURI($paste->getURI()));
|
->setURI(new PhutilURI($paste->getURI()));
|
||||||
|
|
||||||
$source_code = phutil_tag(
|
$source_code = phutil_tag(
|
||||||
|
|
24
src/applications/paste/snippet/PhabricatorPasteSnippet.php
Normal file
24
src/applications/paste/snippet/PhabricatorPasteSnippet.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorPasteSnippet extends Phobject {
|
||||||
|
|
||||||
|
const FULL = 'full';
|
||||||
|
const FIRST_LINES = 'first_lines';
|
||||||
|
const FIRST_BYTES = 'first_bytes';
|
||||||
|
|
||||||
|
private $content;
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
public function __construct($content, $type) {
|
||||||
|
$this->content = $content;
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getContent() {
|
||||||
|
return $this->content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType() {
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ final class PhabricatorPaste extends PhabricatorPasteDAO
|
||||||
|
|
||||||
private $content = self::ATTACHABLE;
|
private $content = self::ATTACHABLE;
|
||||||
private $rawContent = self::ATTACHABLE;
|
private $rawContent = self::ATTACHABLE;
|
||||||
|
private $snippet = self::ATTACHABLE;
|
||||||
|
|
||||||
public static function initializeNewPaste(PhabricatorUser $actor) {
|
public static function initializeNewPaste(PhabricatorUser $actor) {
|
||||||
$app = id(new PhabricatorApplicationQuery())
|
$app = id(new PhabricatorApplicationQuery())
|
||||||
|
@ -135,6 +136,15 @@ final class PhabricatorPaste extends PhabricatorPasteDAO
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSnippet() {
|
||||||
|
return $this->assertAttached($this->snippet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachSnippet(PhabricatorPasteSnippet $snippet) {
|
||||||
|
$this->snippet = $snippet;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,35 +2,29 @@
|
||||||
|
|
||||||
final class PhluxEditController extends PhluxController {
|
final class PhluxEditController extends PhluxController {
|
||||||
|
|
||||||
private $key;
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$key = $request->getURIData('key');
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
$is_new = ($key === null);
|
||||||
$this->key = idx($data, 'key');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$user = $request->getUser();
|
|
||||||
|
|
||||||
$is_new = ($this->key === null);
|
|
||||||
if ($is_new) {
|
if ($is_new) {
|
||||||
$var = new PhluxVariable();
|
$var = new PhluxVariable();
|
||||||
$var->setViewPolicy(PhabricatorPolicies::POLICY_USER);
|
$var->setViewPolicy(PhabricatorPolicies::POLICY_USER);
|
||||||
$var->setEditPolicy(PhabricatorPolicies::POLICY_USER);
|
$var->setEditPolicy(PhabricatorPolicies::POLICY_USER);
|
||||||
} else {
|
} else {
|
||||||
$var = id(new PhluxVariableQuery())
|
$var = id(new PhluxVariableQuery())
|
||||||
->setViewer($user)
|
->setViewer($viewer)
|
||||||
->requireCapabilities(
|
->requireCapabilities(
|
||||||
array(
|
array(
|
||||||
PhabricatorPolicyCapability::CAN_VIEW,
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT,
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
))
|
))
|
||||||
->withKeys(array($this->key))
|
->withKeys(array($key))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$var) {
|
if (!$var) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
$view_uri = $this->getApplicationURI('/view/'.$this->key.'/');
|
$view_uri = $this->getApplicationURI('/view/'.$key.'/');
|
||||||
}
|
}
|
||||||
|
|
||||||
$e_key = ($is_new ? true : null);
|
$e_key = ($is_new ? true : null);
|
||||||
|
@ -67,7 +61,7 @@ final class PhluxEditController extends PhluxController {
|
||||||
|
|
||||||
if (!$errors) {
|
if (!$errors) {
|
||||||
$editor = id(new PhluxVariableEditor())
|
$editor = id(new PhluxVariableEditor())
|
||||||
->setActor($user)
|
->setActor($viewer)
|
||||||
->setContinueOnNoEffect(true)
|
->setContinueOnNoEffect(true)
|
||||||
->setContentSourceFromRequest($request);
|
->setContentSourceFromRequest($request);
|
||||||
|
|
||||||
|
@ -110,12 +104,12 @@ final class PhluxEditController extends PhluxController {
|
||||||
}
|
}
|
||||||
|
|
||||||
$policies = id(new PhabricatorPolicyQuery())
|
$policies = id(new PhabricatorPolicyQuery())
|
||||||
->setViewer($user)
|
->setViewer($viewer)
|
||||||
->setObject($var)
|
->setObject($var)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
$form = id(new AphrontFormView())
|
||||||
->setUser($user)
|
->setUser($viewer)
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormTextControl())
|
id(new AphrontFormTextControl())
|
||||||
->setValue($var->getVariableKey())
|
->setValue($var->getVariableKey())
|
||||||
|
@ -161,7 +155,7 @@ final class PhluxEditController extends PhluxController {
|
||||||
$title = pht('Create Variable');
|
$title = pht('Create Variable');
|
||||||
$crumbs->addTextCrumb($title, $request->getRequestURI());
|
$crumbs->addTextCrumb($title, $request->getRequestURI());
|
||||||
} else {
|
} else {
|
||||||
$title = pht('Edit %s', $this->key);
|
$title = pht('Edit %s', $key);
|
||||||
$crumbs->addTextCrumb($title, $request->getRequestURI());
|
$crumbs->addTextCrumb($title, $request->getRequestURI());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,13 @@
|
||||||
|
|
||||||
final class PhluxListController extends PhluxController {
|
final class PhluxListController extends PhluxController {
|
||||||
|
|
||||||
public function processRequest() {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$request = $this->getRequest();
|
$viewer = $this->getViewer();
|
||||||
$user = $request->getUser();
|
|
||||||
|
|
||||||
$pager = new AphrontCursorPagerView();
|
$pager = new AphrontCursorPagerView();
|
||||||
$pager->readFromRequest($request);
|
$pager->readFromRequest($request);
|
||||||
$query = id(new PhluxVariableQuery())
|
$query = id(new PhluxVariableQuery())
|
||||||
->setViewer($user);
|
->setViewer($viewer);
|
||||||
|
|
||||||
$vars = $query->executeWithCursorPager($pager);
|
$vars = $query->executeWithCursorPager($pager);
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ final class PhluxListController extends PhluxController {
|
||||||
$item->setHref($this->getApplicationURI('/view/'.$key.'/'));
|
$item->setHref($this->getApplicationURI('/view/'.$key.'/'));
|
||||||
$item->addIcon(
|
$item->addIcon(
|
||||||
'none',
|
'none',
|
||||||
phabricator_datetime($var->getDateModified(), $user));
|
phabricator_datetime($var->getDateModified(), $viewer));
|
||||||
|
|
||||||
$view->addItem($item);
|
$view->addItem($item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,13 @@
|
||||||
|
|
||||||
final class PhluxViewController extends PhluxController {
|
final class PhluxViewController extends PhluxController {
|
||||||
|
|
||||||
private $key;
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
public function willProcessRequest(array $data) {
|
$key = $request->getURIData('key');
|
||||||
$this->key = $data['key'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$user = $request->getUser();
|
|
||||||
|
|
||||||
$var = id(new PhluxVariableQuery())
|
$var = id(new PhluxVariableQuery())
|
||||||
->setViewer($user)
|
->setViewer($viewer)
|
||||||
->withKeys(array($this->key))
|
->withKeys(array($key))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
if (!$var) {
|
if (!$var) {
|
||||||
|
@ -29,16 +23,16 @@ final class PhluxViewController extends PhluxController {
|
||||||
|
|
||||||
$header = id(new PHUIHeaderView())
|
$header = id(new PHUIHeaderView())
|
||||||
->setHeader($title)
|
->setHeader($title)
|
||||||
->setUser($user)
|
->setUser($viewer)
|
||||||
->setPolicyObject($var);
|
->setPolicyObject($var);
|
||||||
|
|
||||||
$actions = id(new PhabricatorActionListView())
|
$actions = id(new PhabricatorActionListView())
|
||||||
->setUser($user)
|
->setUser($viewer)
|
||||||
->setObjectURI($request->getRequestURI())
|
->setObjectURI($request->getRequestURI())
|
||||||
->setObject($var);
|
->setObject($var);
|
||||||
|
|
||||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
$user,
|
$viewer,
|
||||||
$var,
|
$var,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT);
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
|
||||||
|
@ -53,7 +47,7 @@ final class PhluxViewController extends PhluxController {
|
||||||
$display_value = json_encode($var->getVariableValue());
|
$display_value = json_encode($var->getVariableValue());
|
||||||
|
|
||||||
$properties = id(new PHUIPropertyListView())
|
$properties = id(new PHUIPropertyListView())
|
||||||
->setUser($user)
|
->setUser($viewer)
|
||||||
->setObject($var)
|
->setObject($var)
|
||||||
->setActionList($actions)
|
->setActionList($actions)
|
||||||
->addProperty(pht('Value'), $display_value);
|
->addProperty(pht('Value'), $display_value);
|
||||||
|
|
|
@ -67,6 +67,13 @@ final class PhabricatorProjectBoardViewController
|
||||||
// TODO: Expand the checks here if we add the ability
|
// TODO: Expand the checks here if we add the ability
|
||||||
// to hide the Backlog column
|
// to hide the Backlog column
|
||||||
if (!$columns) {
|
if (!$columns) {
|
||||||
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||||
|
$viewer,
|
||||||
|
$project,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT);
|
||||||
|
if (!$can_edit) {
|
||||||
|
return $this->noAccessDialog($project);
|
||||||
|
}
|
||||||
switch ($request->getStr('initialize-type')) {
|
switch ($request->getStr('initialize-type')) {
|
||||||
case 'backlog-only':
|
case 'backlog-only':
|
||||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||||
|
@ -713,6 +720,20 @@ final class PhabricatorProjectBoardViewController
|
||||||
->setDialog($dialog);
|
->setDialog($dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function noAccessDialog(PhabricatorProject $project) {
|
||||||
|
|
||||||
|
$instructions = pht('This workboard has not been setup yet.');
|
||||||
|
|
||||||
|
$dialog = id(new AphrontDialogView())
|
||||||
|
->setUser($this->getRequest()->getUser())
|
||||||
|
->setTitle(pht('No Workboard'))
|
||||||
|
->addCancelButton($this->getApplicationURI('view/'.$project->getID().'/'))
|
||||||
|
->appendParagraph($instructions);
|
||||||
|
|
||||||
|
return id(new AphrontDialogResponse())
|
||||||
|
->setDialog($dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add current state parameters (like order and the visibility of hidden
|
* Add current state parameters (like order and the visibility of hidden
|
||||||
|
|
|
@ -5,19 +5,12 @@ final class PhabricatorSearchController
|
||||||
|
|
||||||
const SCOPE_CURRENT_APPLICATION = 'application';
|
const SCOPE_CURRENT_APPLICATION = 'application';
|
||||||
|
|
||||||
private $queryKey;
|
|
||||||
|
|
||||||
public function shouldAllowPublic() {
|
public function shouldAllowPublic() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$this->queryKey = idx($data, 'queryKey');
|
$viewer = $this->getViewer();
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$viewer = $request->getUser();
|
|
||||||
|
|
||||||
if ($request->getStr('jump') != 'no') {
|
if ($request->getStr('jump') != 'no') {
|
||||||
$pref_jump = PhabricatorUserPreferences::PREFERENCE_SEARCHBAR_JUMP;
|
$pref_jump = PhabricatorUserPreferences::PREFERENCE_SEARCHBAR_JUMP;
|
||||||
|
@ -97,7 +90,7 @@ final class PhabricatorSearchController
|
||||||
}
|
}
|
||||||
|
|
||||||
$controller = id(new PhabricatorApplicationSearchController())
|
$controller = id(new PhabricatorApplicationSearchController())
|
||||||
->setQueryKey($this->queryKey)
|
->setQueryKey($request->getURIData('queryKey'))
|
||||||
->setSearchEngine($engine)
|
->setSearchEngine($engine)
|
||||||
->setNavigation($this->buildSideNavView());
|
->setNavigation($this->buildSideNavView());
|
||||||
|
|
||||||
|
@ -105,7 +98,7 @@ final class PhabricatorSearchController
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildSideNavView($for_app = false) {
|
public function buildSideNavView($for_app = false) {
|
||||||
$viewer = $this->getRequest()->getUser();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$nav = new AphrontSideNavFilterView();
|
$nav = new AphrontSideNavFilterView();
|
||||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||||
|
|
|
@ -3,33 +3,24 @@
|
||||||
final class PhabricatorSearchDeleteController
|
final class PhabricatorSearchDeleteController
|
||||||
extends PhabricatorSearchBaseController {
|
extends PhabricatorSearchBaseController {
|
||||||
|
|
||||||
private $queryKey;
|
public function handleRequest(AphrontRequest $request) {
|
||||||
private $engineClass;
|
$viewer = $this->getViewer();
|
||||||
|
$key = $request->getURIData('queryKey');
|
||||||
public function willProcessRequest(array $data) {
|
$engine_class = $request->getURIData('engine');
|
||||||
$this->queryKey = idx($data, 'queryKey');
|
|
||||||
$this->engineClass = idx($data, 'engine');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$user = $request->getUser();
|
|
||||||
|
|
||||||
$key = $this->queryKey;
|
|
||||||
|
|
||||||
$base_class = 'PhabricatorApplicationSearchEngine';
|
$base_class = 'PhabricatorApplicationSearchEngine';
|
||||||
if (!is_subclass_of($this->engineClass, $base_class)) {
|
if (!is_subclass_of($engine_class, $base_class)) {
|
||||||
return new Aphront400Response();
|
return new Aphront400Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$engine = newv($this->engineClass, array());
|
$engine = newv($engine_class, array());
|
||||||
$engine->setViewer($user);
|
$engine->setViewer($viewer);
|
||||||
|
|
||||||
$named_query = id(new PhabricatorNamedQueryQuery())
|
$named_query = id(new PhabricatorNamedQueryQuery())
|
||||||
->setViewer($user)
|
->setViewer($viewer)
|
||||||
->withEngineClassNames(array($this->engineClass))
|
->withEngineClassNames(array($engine_class))
|
||||||
->withQueryKeys(array($key))
|
->withQueryKeys(array($key))
|
||||||
->withUserPHIDs(array($user->getPHID()))
|
->withUserPHIDs(array($viewer->getPHID()))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
if (!$named_query && $engine->isBuiltinQuery($key)) {
|
if (!$named_query && $engine->isBuiltinQuery($key)) {
|
||||||
|
@ -84,7 +75,7 @@ final class PhabricatorSearchDeleteController
|
||||||
}
|
}
|
||||||
|
|
||||||
$dialog = id(new AphrontDialogView())
|
$dialog = id(new AphrontDialogView())
|
||||||
->setUser($user)
|
->setUser($viewer)
|
||||||
->setTitle($title)
|
->setTitle($title)
|
||||||
->appendChild($desc)
|
->appendChild($desc)
|
||||||
->addCancelButton($return_uri)
|
->addCancelButton($return_uri)
|
||||||
|
|
|
@ -3,38 +3,31 @@
|
||||||
final class PhabricatorSearchEditController
|
final class PhabricatorSearchEditController
|
||||||
extends PhabricatorSearchBaseController {
|
extends PhabricatorSearchBaseController {
|
||||||
|
|
||||||
private $queryKey;
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
public function willProcessRequest(array $data) {
|
|
||||||
$this->queryKey = idx($data, 'queryKey');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$user = $request->getUser();
|
|
||||||
|
|
||||||
$saved_query = id(new PhabricatorSavedQueryQuery())
|
$saved_query = id(new PhabricatorSavedQueryQuery())
|
||||||
->setViewer($user)
|
->setViewer($viewer)
|
||||||
->withQueryKeys(array($this->queryKey))
|
->withQueryKeys(array($request->getURIData('queryKey')))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
if (!$saved_query) {
|
if (!$saved_query) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$engine = $saved_query->newEngine()->setViewer($user);
|
$engine = $saved_query->newEngine()->setViewer($viewer);
|
||||||
|
|
||||||
$complete_uri = $engine->getQueryManagementURI();
|
$complete_uri = $engine->getQueryManagementURI();
|
||||||
$cancel_uri = $complete_uri;
|
$cancel_uri = $complete_uri;
|
||||||
|
|
||||||
$named_query = id(new PhabricatorNamedQueryQuery())
|
$named_query = id(new PhabricatorNamedQueryQuery())
|
||||||
->setViewer($user)
|
->setViewer($viewer)
|
||||||
->withQueryKeys(array($saved_query->getQueryKey()))
|
->withQueryKeys(array($saved_query->getQueryKey()))
|
||||||
->withUserPHIDs(array($user->getPHID()))
|
->withUserPHIDs(array($viewer->getPHID()))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$named_query) {
|
if (!$named_query) {
|
||||||
$named_query = id(new PhabricatorNamedQuery())
|
$named_query = id(new PhabricatorNamedQuery())
|
||||||
->setUserPHID($user->getPHID())
|
->setUserPHID($viewer->getPHID())
|
||||||
->setQueryKey($saved_query->getQueryKey())
|
->setQueryKey($saved_query->getQueryKey())
|
||||||
->setEngineClassName($saved_query->getEngineClassName());
|
->setEngineClassName($saved_query->getEngineClassName());
|
||||||
|
|
||||||
|
@ -64,7 +57,7 @@ final class PhabricatorSearchEditController
|
||||||
}
|
}
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
$form = id(new AphrontFormView())
|
||||||
->setUser($user);
|
->setUser($viewer);
|
||||||
|
|
||||||
$form->appendChild(
|
$form->appendChild(
|
||||||
id(new AphrontFormTextControl())
|
id(new AphrontFormTextControl())
|
||||||
|
|
|
@ -9,7 +9,6 @@ final class PhabricatorSearchHovercardController
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$phids = $request->getArr('phids');
|
$phids = $request->getArr('phids');
|
||||||
|
|
||||||
$handles = id(new PhabricatorHandleQuery())
|
$handles = id(new PhabricatorHandleQuery())
|
||||||
|
|
|
@ -3,25 +3,19 @@
|
||||||
final class PhabricatorSearchOrderController
|
final class PhabricatorSearchOrderController
|
||||||
extends PhabricatorSearchBaseController {
|
extends PhabricatorSearchBaseController {
|
||||||
|
|
||||||
private $engineClass;
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
public function willProcessRequest(array $data) {
|
$engine_class = $request->getURIData('engine');
|
||||||
$this->engineClass = idx($data, 'engine');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$user = $request->getUser();
|
|
||||||
|
|
||||||
$request->validateCSRF();
|
$request->validateCSRF();
|
||||||
|
|
||||||
$base_class = 'PhabricatorApplicationSearchEngine';
|
$base_class = 'PhabricatorApplicationSearchEngine';
|
||||||
if (!is_subclass_of($this->engineClass, $base_class)) {
|
if (!is_subclass_of($engine_class, $base_class)) {
|
||||||
return new Aphront400Response();
|
return new Aphront400Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$engine = newv($this->engineClass, array());
|
$engine = newv($engine_class, array());
|
||||||
$engine->setViewer($user);
|
$engine->setViewer($viewer);
|
||||||
|
|
||||||
$queries = $engine->loadAllNamedQueries();
|
$queries = $engine->loadAllNamedQueries();
|
||||||
$queries = mpull($queries, null, 'getQueryKey');
|
$queries = mpull($queries, null, 'getQueryKey');
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
},
|
},
|
||||||
"fieldmanual": {
|
"fieldmanual": {
|
||||||
"name": "Field Manuals"
|
"name": "Field Manuals"
|
||||||
|
},
|
||||||
|
"cellar": {
|
||||||
|
"name": "Musty Cellar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,14 @@
|
||||||
|
|
||||||
Describes how to file an effective Phabricator bug report.
|
Describes how to file an effective Phabricator bug report.
|
||||||
|
|
||||||
|
Include Reproduction Steps!
|
||||||
|
===========================
|
||||||
|
|
||||||
|
IMPORTANT: When filing a bug report, you **MUST** include reproduction
|
||||||
|
instructions. We can not help fix bugs we can not reproduce, and will not
|
||||||
|
accept reports which omit reproduction instructions. See below for details.
|
||||||
|
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
========
|
========
|
||||||
|
|
||||||
|
@ -28,6 +36,7 @@ If you have a feature request (not a bug report), see
|
||||||
For general information on contributing to Phabricator, see
|
For general information on contributing to Phabricator, see
|
||||||
@{article:Contributor Introduction}.
|
@{article:Contributor Introduction}.
|
||||||
|
|
||||||
|
|
||||||
Common Fixes
|
Common Fixes
|
||||||
============
|
============
|
||||||
|
|
||||||
|
@ -73,6 +82,9 @@ Supported Issues
|
||||||
Before filing a bug, make sure you're filing an issue against something we
|
Before filing a bug, make sure you're filing an issue against something we
|
||||||
support.
|
support.
|
||||||
|
|
||||||
|
**We can NOT help you with issues we can not reproduce.** It is critical that
|
||||||
|
you explain how to reproduce the issue when filing a report.
|
||||||
|
|
||||||
**We do NOT support prototype applications.** If you're running into an issue
|
**We do NOT support prototype applications.** If you're running into an issue
|
||||||
with a prototype application, you're on your own. For more information about
|
with a prototype application, you're on your own. For more information about
|
||||||
prototype applications, see @{article:User Guide: Prototype Applications}.
|
prototype applications, see @{article:User Guide: Prototype Applications}.
|
||||||
|
@ -101,6 +113,7 @@ Otherwise, if you're having an issue with a supported first-party application
|
||||||
and followed the upstream install instructions on a normal computer, we're happy
|
and followed the upstream install instructions on a normal computer, we're happy
|
||||||
to try to help.
|
to try to help.
|
||||||
|
|
||||||
|
|
||||||
Getting More Information
|
Getting More Information
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
@ -121,6 +134,7 @@ help us figure out and resolve an issue.
|
||||||
troubleshooting. Adjusting settings or enabling debugging modes may give
|
troubleshooting. Adjusting settings or enabling debugging modes may give
|
||||||
you more information about the issue.
|
you more information about the issue.
|
||||||
|
|
||||||
|
|
||||||
Reproducibility
|
Reproducibility
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
@ -135,7 +149,9 @@ trouble narrowing something down or want to check if updating might fix an
|
||||||
issue.
|
issue.
|
||||||
|
|
||||||
It is nearly impossible for us to resolve many issues if we can not reproduce
|
It is nearly impossible for us to resolve many issues if we can not reproduce
|
||||||
them.
|
them. We will not accept reports which do not contain the information required
|
||||||
|
to reproduce problems.
|
||||||
|
|
||||||
|
|
||||||
Unreproducible Problems
|
Unreproducible Problems
|
||||||
=======================
|
=======================
|
||||||
|
@ -161,6 +177,7 @@ We will make a reasonable effort to reproduce problems, but can not help with
|
||||||
issues which we can't reproduce. You can make sure we're able to help resolve
|
issues which we can't reproduce. You can make sure we're able to help resolve
|
||||||
your issue by generating clear reproduction steps.
|
your issue by generating clear reproduction steps.
|
||||||
|
|
||||||
|
|
||||||
Create a Task in Maniphest
|
Create a Task in Maniphest
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
@ -168,11 +185,10 @@ If you're up to date, supported, have collected information about the problem,
|
||||||
and have the best reproduction instructions you can come up with, you're ready
|
and have the best reproduction instructions you can come up with, you're ready
|
||||||
to file an issue.
|
to file an issue.
|
||||||
|
|
||||||
We'll look at any issue report we can find (we monitor IRC, email,
|
It is **particularly critical** that you include reproduction steps. We will
|
||||||
StackOverflow, Quora, Facebook and Twitter), but the upstream Maniphest is the
|
not accept reports which describe issues we can not reproduce.
|
||||||
authoritative bug tracker and the best place to file:
|
|
||||||
|
|
||||||
https://secure.phabricator.com/maniphest/task/create/
|
(NOTE) https://secure.phabricator.com/maniphest/task/create/
|
||||||
|
|
||||||
If you don't want to file there (or, for example, your bug relates to being
|
If you don't want to file there (or, for example, your bug relates to being
|
||||||
unable to log in or unable to file an issue in Maniphest) you can file on any
|
unable to log in or unable to file an issue in Maniphest) you can file on any
|
||||||
|
@ -182,12 +198,9 @@ filed against the upstream than if they're filed somewhere else.
|
||||||
| Effectiveness | Filing Method |
|
| Effectiveness | Filing Method |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Best | Upstream Maniphest |
|
| Best | Upstream Maniphest |
|
||||||
| Ehhh | Quora, StackOverflow, Facebook, email, etc. |
|
| Ehhh | Quora, StackOverflow, Facebook, Jelly, email, etc. |
|
||||||
| What | Passive-aggressive tweet |
|
| What | Passive-aggressive tweet |
|
||||||
|
|
||||||
If you have a quick question or want to discuss something before filing an
|
|
||||||
issue, IRC is a great way to get a sanity check first. You can find information
|
|
||||||
about IRC in @{article: Give Feedback! Get Support!}.
|
|
||||||
|
|
||||||
Next Steps
|
Next Steps
|
||||||
==========
|
==========
|
||||||
|
@ -195,6 +208,5 @@ Next Steps
|
||||||
Continue by:
|
Continue by:
|
||||||
|
|
||||||
- learning about @{article: Contributing Feature Requests}; or
|
- learning about @{article: Contributing Feature Requests}; or
|
||||||
- reading general support information in
|
- reading general support information in @{article:Support Resources}; or
|
||||||
@{article: Give Feedback! Get Support!}; or
|
|
||||||
- returning to the @{article:Contributor Introduction}.
|
- returning to the @{article:Contributor Introduction}.
|
||||||
|
|
|
@ -23,8 +23,7 @@ contribute to Phabricator:
|
||||||
|
|
||||||
- Send us an email or drop by IRC just to say "thanks". A big part of the
|
- Send us an email or drop by IRC just to say "thanks". A big part of the
|
||||||
reason we build this software is to help people solve problems, and knowing
|
reason we build this software is to help people solve problems, and knowing
|
||||||
that our efforts are appreciated is really rewarding. You can find ways to
|
that our efforts are appreciated is really rewarding.
|
||||||
get in touch in @{article:Give Feedback! Get Support!}
|
|
||||||
- Recommend Phabricator to people who you think might find it useful. Our
|
- Recommend Phabricator to people who you think might find it useful. Our
|
||||||
most powerful growth channel is word of mouth, and mentioning or tweeting
|
most powerful growth channel is word of mouth, and mentioning or tweeting
|
||||||
about Phabricator helps the project grow. If writing a tweet sounds like
|
about Phabricator helps the project grow. If writing a tweet sounds like
|
||||||
|
@ -40,7 +39,6 @@ contribute to Phabricator:
|
||||||
- Report bugs and request features. We may not always be able to fix or build
|
- Report bugs and request features. We may not always be able to fix or build
|
||||||
things right away, but knowing about issues users are encountering or
|
things right away, but knowing about issues users are encountering or
|
||||||
features they'd like to see improves our ability to plan and prioritize.
|
features they'd like to see improves our ability to plan and prioritize.
|
||||||
For ways to do this, see @{article:Give Feedback! Get Support!}
|
|
||||||
- For details on reporting bugs, see @{article:Contributing Bug Reports}.
|
- For details on reporting bugs, see @{article:Contributing Bug Reports}.
|
||||||
- For details on requesting features, see @{article:Contributing Feature
|
- For details on requesting features, see @{article:Contributing Feature
|
||||||
Requests}.
|
Requests}.
|
||||||
|
@ -48,16 +46,11 @@ contribute to Phabricator:
|
||||||
6-12 months currently exists on the [[ Roadmap ]] or in Maniphest. Telling
|
6-12 months currently exists on the [[ Roadmap ]] or in Maniphest. Telling
|
||||||
us about use cases you have can help us build better products when the time
|
us about use cases you have can help us build better products when the time
|
||||||
comes to write the code.
|
comes to write the code.
|
||||||
- Hang out in IRC, and maybe answer a question or two. IRC is a completely
|
|
||||||
legit place for serious hackers to hang out anyway, but while you're there
|
|
||||||
you might see someone ask a question that you know the answer to. Helping
|
|
||||||
them out (or pointing them to the right documentation) is a big help to us.
|
|
||||||
You can find details about the IRC channel in
|
|
||||||
@{article:Give Feedback! Get Support!}
|
|
||||||
|
|
||||||
If all of this sounds nice but you really just want to write some code, that's
|
If all of this sounds nice but you really just want to write some code, be
|
||||||
awesome too. To get started with contributing code, see
|
aware that this project often presents a high barrier to entry for new
|
||||||
@{article:Contributing Code}.
|
contributors. To continue, see @{article:Contributing Code}.
|
||||||
|
|
||||||
|
|
||||||
Next Steps
|
Next Steps
|
||||||
==========
|
==========
|
||||||
|
@ -65,6 +58,6 @@ Next Steps
|
||||||
Continue by:
|
Continue by:
|
||||||
|
|
||||||
- learning about bug reports in @{article:Contributing Bug Reports};
|
- learning about bug reports in @{article:Contributing Bug Reports};
|
||||||
- learning about feature requests in @{article:Contributing Feature Requests};
|
- learning about feature requests in
|
||||||
- learning about code contributions in @{article:Contributing Code}; or
|
@{article:Contributing Feature Requests}; or
|
||||||
- getting in touch with @{article:Give Feedback! Get Support!}
|
- learning about code contributions in @{article:Contributing Code}.
|
||||||
|
|
|
@ -3,6 +3,13 @@
|
||||||
|
|
||||||
Describes how to file an effective Phabricator feature request.
|
Describes how to file an effective Phabricator feature request.
|
||||||
|
|
||||||
|
Describe Your Problem!
|
||||||
|
======================
|
||||||
|
|
||||||
|
IMPORTANT: When filing a feature request, you **MUST** describe the root
|
||||||
|
problem you are facing. We will not accept feature requests which do not
|
||||||
|
include a problem description. See below for details.
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
========
|
========
|
||||||
|
|
||||||
|
@ -138,8 +145,9 @@ upstream.
|
||||||
Describe Problems
|
Describe Problems
|
||||||
=================
|
=================
|
||||||
|
|
||||||
When you file a feature request, it is really helpful to describe the problem
|
When you file a feature request, we need you to describe the problem you're
|
||||||
you're facing first, not just your desired solution.
|
facing first, not just your desired solution. Describing the problem you are
|
||||||
|
facing is the **most important part** of a feature request.
|
||||||
|
|
||||||
Often, your problem may have a lot in common with other similar problems. If we
|
Often, your problem may have a lot in common with other similar problems. If we
|
||||||
understand your use case we can compare it to other use cases and sometimes find
|
understand your use case we can compare it to other use cases and sometimes find
|
||||||
|
@ -159,6 +167,10 @@ which has approximately the same effect and does fit into the product direction.
|
||||||
If you only describe the solution and not the problem, we can't generalize,
|
If you only describe the solution and not the problem, we can't generalize,
|
||||||
contextualize, merge, reframe, or offer alternative solutions or workarounds.
|
contextualize, merge, reframe, or offer alternative solutions or workarounds.
|
||||||
|
|
||||||
|
You must describe the problem you are facing when filing a feature request. We
|
||||||
|
will not accept feature requests which do not contextualize the request by
|
||||||
|
describing the root problem.
|
||||||
|
|
||||||
|
|
||||||
Hypotheticals
|
Hypotheticals
|
||||||
=============
|
=============
|
||||||
|
@ -206,13 +218,13 @@ Create a Task in Maniphest
|
||||||
|
|
||||||
If you think your feature might be a good fit for the upstream, have reasonable
|
If you think your feature might be a good fit for the upstream, have reasonable
|
||||||
expectations about it, and have a good description of the problem you're trying
|
expectations about it, and have a good description of the problem you're trying
|
||||||
to solve, you're ready to file a feature request:
|
to solve, you're ready to file a feature request.
|
||||||
|
|
||||||
https://secure.phabricator.com/maniphest/task/create/
|
It is **particularly critical** that you describe the problem you are facing,
|
||||||
|
not just the feature you want. We will not accept feature requests which do
|
||||||
|
not describe the root problem the feature is intended to resolve.
|
||||||
|
|
||||||
If you have a quick question or want to discuss something before filing a
|
(NOTE) https://secure.phabricator.com/maniphest/task/create/
|
||||||
request, IRC is the best way to get a quick answer. You can find information
|
|
||||||
about IRC and other support channels in @{article: Give Feedback! Get Support!}.
|
|
||||||
|
|
||||||
|
|
||||||
Next Steps
|
Next Steps
|
||||||
|
@ -221,6 +233,5 @@ Next Steps
|
||||||
Continue by:
|
Continue by:
|
||||||
|
|
||||||
- learning about @{article: Contributing Bug Reports}; or
|
- learning about @{article: Contributing Bug Reports}; or
|
||||||
- reading general support information in
|
- reading general support information in @{article:Support Resources}; or
|
||||||
@{article: Give Feedback! Get Support!}; or
|
|
||||||
- returning to the @{article:Contributor Introduction}.
|
- returning to the @{article:Contributor Introduction}.
|
||||||
|
|
|
@ -1,44 +1,7 @@
|
||||||
@title Give Feedback! Get Support!
|
@title Give Feedback! Get Support!
|
||||||
@short Feedback/Support
|
@short Feedback/Support
|
||||||
@group intro
|
@group cellar
|
||||||
|
|
||||||
How to give us feedback, report bugs, and request features, and get support for
|
Deprecated.
|
||||||
problems with Phabricator.
|
|
||||||
|
|
||||||
Overview
|
This article has moved to @{article:Support Resources}.
|
||||||
========
|
|
||||||
|
|
||||||
We'd love to hear your feedback about Phabricator, whether it's good or bad. The
|
|
||||||
best ways to provide feedback and get support are:
|
|
||||||
|
|
||||||
- For bug reports and feature requests, file a task in our task tracker,
|
|
||||||
Maniphest.
|
|
||||||
- For questions and real-time chat, join the IRC channel.
|
|
||||||
- If you just want to provide some quick feedback, you can tweet at
|
|
||||||
us ([[ http://twitter.com/phabricator | @phabricator ]]).
|
|
||||||
|
|
||||||
Bugs and Requests
|
|
||||||
=====================
|
|
||||||
|
|
||||||
The best way to report bugs and request features is through
|
|
||||||
[[http://secure.phabricator.com/maniphest/task/create/ | Maniphest]]. For
|
|
||||||
information on filing good bug reports and feature requests, see:
|
|
||||||
|
|
||||||
- @{article:Contributing Bug Reports}
|
|
||||||
- @{article:Contributing Feature Requests}
|
|
||||||
|
|
||||||
IRC
|
|
||||||
==========
|
|
||||||
|
|
||||||
We're active in `#phabricator` on FreeNode, and it's the best place to ask
|
|
||||||
questions and get support.
|
|
||||||
|
|
||||||
Next Steps
|
|
||||||
==========
|
|
||||||
|
|
||||||
Continue by:
|
|
||||||
|
|
||||||
- learning more about bug reports with @{article:Contributing Bug Reports}; or
|
|
||||||
- learning more about feature requests with
|
|
||||||
@{article:Contributing Feature Requests}; or
|
|
||||||
- contributing to Phabricator with @{article:Contributor Introduction}.
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
Describes how to report security vulnerabilities in Phabricator.
|
Describes how to report security vulnerabilities in Phabricator.
|
||||||
|
|
||||||
= Overview =
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
Phabricator runs a disclosure and award program through
|
Phabricator runs a disclosure and award program through
|
||||||
[[ https://www.hackerone.com/ | HackerOne ]]. This program is the best way to
|
[[ https://www.hackerone.com/ | HackerOne ]]. This program is the best way to
|
||||||
|
@ -19,23 +20,17 @@ how to participate.
|
||||||
We have a 24 hour response timeline, and are usually able to respond to (and,
|
We have a 24 hour response timeline, and are usually able to respond to (and,
|
||||||
very often, fix) issues more quickly than that.
|
very often, fix) issues more quickly than that.
|
||||||
|
|
||||||
= Other Channels =
|
|
||||||
|
|
||||||
You can also contact us on another channel if you prefer. See
|
Other Channels
|
||||||
@{article:Give Feedback! Get Support!} for a list of ways to get in touch
|
==============
|
||||||
with us.
|
|
||||||
|
|
||||||
= Getting Notified =
|
If you aren't sure if something qualifies or don't want to report via
|
||||||
|
HackerOne, you can submit the issue as a normal bug report. For instructions,
|
||||||
|
see @{article:Contributing Bug Reports}.
|
||||||
|
|
||||||
When we fix significant security vulnerabilities, we currently publish
|
|
||||||
information:
|
|
||||||
|
|
||||||
- on our [[ https://www.facebook.com/phabricator | Facebook Page ]];
|
Get Updated
|
||||||
- on our [[ https://twitter.com/phabricator | Twitter Feed ]];
|
===========
|
||||||
- and on IRC (`#phabricator` on FreeNode).
|
|
||||||
|
|
||||||
If you'd prefer to receive information on other channels, let us know.
|
General information about security changes is reported weekly in the
|
||||||
|
[[ https://secure.phabricator.com/w/changelog/ | Changelog ]].
|
||||||
General information about security is reported monthly in the
|
|
||||||
[[ http://phabricator.org/changelog/ | Changelog ]]. This includes low impact
|
|
||||||
issues, reports we did not act on, and other details.
|
|
||||||
|
|
125
src/docs/user/support.diviner
Normal file
125
src/docs/user/support.diviner
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
@title Support Resources
|
||||||
|
@short Support
|
||||||
|
@group intro
|
||||||
|
|
||||||
|
Resources for reporting bugs, requesting features, and getting support.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
This document describes available support resources.
|
||||||
|
|
||||||
|
The upstream provides active, free support for a narrow range of problems
|
||||||
|
(primarily, security issues and reproducible bugs).
|
||||||
|
|
||||||
|
The upstream does not provide free support for general problems with installing
|
||||||
|
or configuring Phabricator. You may be able to get some help with these
|
||||||
|
kinds of issues from the community.
|
||||||
|
|
||||||
|
|
||||||
|
Reporting Security Vulnerabilities
|
||||||
|
==================================
|
||||||
|
|
||||||
|
The upstream accepts, fixes, and awards bounties for reports of material
|
||||||
|
security issues with the software.
|
||||||
|
|
||||||
|
To report security issues, see @{article:Reporting Security Vulnerabilities}.
|
||||||
|
|
||||||
|
|
||||||
|
Reporting Bugs
|
||||||
|
==============
|
||||||
|
|
||||||
|
The upstream will accept **reproducible** bug reports in modern, first-party
|
||||||
|
production code running in reasonable environments.
|
||||||
|
|
||||||
|
To report bugs, see @{article:Contributing Bug Reports}.
|
||||||
|
|
||||||
|
|
||||||
|
Requesting Features
|
||||||
|
===================
|
||||||
|
|
||||||
|
The upstream accepts feature requests which **describe problems** you would
|
||||||
|
like Phabricator to be able to solve.
|
||||||
|
|
||||||
|
To request features, see @{article:Contributing Feature Requests}.
|
||||||
|
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
============
|
||||||
|
|
||||||
|
Phabricator is a very difficult project to contribute to. New contributors
|
||||||
|
will face a high barrier to entry.
|
||||||
|
|
||||||
|
If you'd like to contribute to Phabricator, start with
|
||||||
|
@{article:Contributor Introduction}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Installation and Setup Help
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Installation and setup help is available from the upstream at consulting rates.
|
||||||
|
See [[ https://secure.phabricator.com/w/consulting/ | Consulting ]] for details.
|
||||||
|
|
||||||
|
Helping individual installs navigate unique setup problems takes our time
|
||||||
|
away from developing Phabricator, so we can not offer this service for free.
|
||||||
|
|
||||||
|
You may be able to get free help with these issues from the community. See
|
||||||
|
below for details.
|
||||||
|
|
||||||
|
|
||||||
|
Hosting
|
||||||
|
=========
|
||||||
|
|
||||||
|
The upstream offers Phabricator as a hosted service at
|
||||||
|
[[ https://phacility.com | Phacility ]]. This simplifies setting up and
|
||||||
|
operating a Phabricator instance, and gives you access to a broader range
|
||||||
|
of upstream support services.
|
||||||
|
|
||||||
|
Running this service gives us a strong financial incentive to make installing
|
||||||
|
and operating Phabricator as difficult as possible. Blinded by greed, we toil
|
||||||
|
endlessly to make installation a perplexing nightmare that none other than
|
||||||
|
ourselves can hope to navigate.
|
||||||
|
|
||||||
|
|
||||||
|
Prioritization
|
||||||
|
==============
|
||||||
|
|
||||||
|
The upstream offers prioritization, a service which allows you to control
|
||||||
|
our roadmap and get features you're interested in built sooner at reasonable
|
||||||
|
rates. See
|
||||||
|
[[ https://secure.phabricator.com/w/prioritization/ | Prioritization ]] for
|
||||||
|
details.
|
||||||
|
|
||||||
|
|
||||||
|
Consulting
|
||||||
|
==========
|
||||||
|
|
||||||
|
The upstream offers general-purpose consulting services. See
|
||||||
|
[[ https://secure.phabricator.com/w/consulting/ | Consulting ]] for details.
|
||||||
|
|
||||||
|
|
||||||
|
Community
|
||||||
|
=========
|
||||||
|
|
||||||
|
These resources are not provided by the upstream. They are not official support
|
||||||
|
channels and you may not receive support here, or you may receive help which is
|
||||||
|
misleading or wrong.
|
||||||
|
|
||||||
|
You may be able to get answers to questions on sites like
|
||||||
|
[[ http://stackoverflow.com | Stack Overflow ]],
|
||||||
|
[[ https://www.quora.com | Quora ]],
|
||||||
|
[[ https://jelly.co | Jelly ]], or
|
||||||
|
[[ https://twitter.com | Twitter ]]. The upstream occasionally participates on
|
||||||
|
these sites but these are not official support channels and you should not
|
||||||
|
expect to receive a response.
|
||||||
|
|
||||||
|
There is a
|
||||||
|
[[ https://secure.phabricator.com/conpherence/1336/ | General Chat ]]
|
||||||
|
Conpherence room on this install, and you can ask questions in
|
||||||
|
[[ https://secure.phabricator.com/ponder/ | Ponder ]]. These
|
||||||
|
are not upstream support channels and you may not receive a response to
|
||||||
|
questions, but someone in the community may be able to point you in the right
|
||||||
|
direction.
|
||||||
|
|
||||||
|
There is also a community IRC channel in `#phabricator` on FreeNode.
|
|
@ -129,11 +129,6 @@ able to use:
|
||||||
- Another common approach is to write an install script as an action into
|
- Another common approach is to write an install script as an action into
|
||||||
existing build scripts, so users can run `make install-arc` or
|
existing build scripts, so users can run `make install-arc` or
|
||||||
`ant install-arc` or similar.
|
`ant install-arc` or similar.
|
||||||
- In general, if this sucks and is causing you pain, let us know (see
|
|
||||||
@{article:Give Feedback! Get Support!}). We're planning to improve this at
|
|
||||||
some point, but it's somewhat complicated to get right. While it can take a
|
|
||||||
little time to set up, we aren't getting feedback that it's a persistent
|
|
||||||
pain point, so it hasn't been a priority.
|
|
||||||
|
|
||||||
== Installing Tab Completion ==
|
== Installing Tab Completion ==
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,6 @@ Phabricator supports two code review workflows, "review" (pre-push) and
|
||||||
This document summarizes the post-push "audit" workflow implemented by the
|
This document summarizes the post-push "audit" workflow implemented by the
|
||||||
creatively-named //Audit// tool.
|
creatively-named //Audit// tool.
|
||||||
|
|
||||||
NOTE: The audit workflow is new, give us feedback about it! See
|
|
||||||
@{article:Give Feedback! Get Support!}.
|
|
||||||
|
|
||||||
= How Audit Works =
|
= How Audit Works =
|
||||||
|
|
||||||
Using auditing allows you to push and deploy code without waiting for code
|
Using auditing allows you to push and deploy code without waiting for code
|
||||||
|
@ -104,5 +101,4 @@ only changes that are relevant to them.
|
||||||
|
|
||||||
= Next Steps =
|
= Next Steps =
|
||||||
|
|
||||||
- Learn more about Herald at @{article:Herald User Guide}; or
|
- Learn more about Herald at @{article:Herald User Guide}.
|
||||||
- give us feedback at @{article:Give Feedback! Get Support!}.
|
|
||||||
|
|
|
@ -65,5 +65,4 @@ files affected, etc.)
|
||||||
- learn about handling large changesets at
|
- learn about handling large changesets at
|
||||||
@{article:Differential User Guide: Large Changes}; or
|
@{article:Differential User Guide: Large Changes}; or
|
||||||
- learn about test plans at @{article:Differential User Guide: Test Plans}; or
|
- learn about test plans at @{article:Differential User Guide: Test Plans}; or
|
||||||
- learn more about Herald at @{article:Herald User Guide}; or
|
- learn more about Herald at @{article:Herald User Guide}.
|
||||||
- give us feedback at @{article:Give Feedback! Get Support!}.
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ Journal about your thoughts and feelings. Share with others. Profit.
|
||||||
|
|
||||||
= Overview =
|
= Overview =
|
||||||
|
|
||||||
|
IMPORTANT: Phame is a prototype application.
|
||||||
|
|
||||||
Phame is a simple blogging platform. You can write drafts which only you can
|
Phame is a simple blogging platform. You can write drafts which only you can
|
||||||
see. Later, you can publish these drafts as posts which anyone who can access
|
see. Later, you can publish these drafts as posts which anyone who can access
|
||||||
the Phabricator instance can see. You can also add posts to blogs to increase
|
the Phabricator instance can see. You can also add posts to blogs to increase
|
||||||
|
@ -55,9 +57,3 @@ this functionality.
|
||||||
A given comment widget is tied 1:1 with a given post. This means the same
|
A given comment widget is tied 1:1 with a given post. This means the same
|
||||||
instance of a given comment widget will appear for a given post regardless
|
instance of a given comment widget will appear for a given post regardless
|
||||||
of whether that post is being viewed in the context of a blog.
|
of whether that post is being viewed in the context of a blog.
|
||||||
|
|
||||||
= Next Steps =
|
|
||||||
|
|
||||||
- Phame is extremely new and very basic for now. Give us feedback on
|
|
||||||
what you'd like to see improve! See @{article:Give Feedback! Get
|
|
||||||
Support!}.
|
|
||||||
|
|
|
@ -3,10 +3,8 @@
|
||||||
|
|
||||||
Construct a detailed written history of your civilization.
|
Construct a detailed written history of your civilization.
|
||||||
|
|
||||||
= Overview =
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
Phriction is a simple wiki. You can edit pages, and the text you write will stay
|
Phriction is a simple wiki. You can edit pages, and the text you write will stay
|
||||||
there. Other people can see it later.
|
there. Other people can see it later.
|
||||||
|
|
||||||
NOTE: Phriction is extremely new and very basic for now. Give us feedback on
|
|
||||||
what you'd like to see improve! See @{article:Give Feedback! Get Support!}.
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ final class PHUIInfoView extends AphrontView {
|
||||||
require_celerity_resource('phui-info-view-css');
|
require_celerity_resource('phui-info-view-css');
|
||||||
|
|
||||||
$errors = $this->errors;
|
$errors = $this->errors;
|
||||||
if ($errors) {
|
if (count($errors) > 1) {
|
||||||
$list = array();
|
$list = array();
|
||||||
foreach ($errors as $error) {
|
foreach ($errors as $error) {
|
||||||
$list[] = phutil_tag(
|
$list[] = phutil_tag(
|
||||||
|
@ -64,6 +64,8 @@ final class PHUIInfoView extends AphrontView {
|
||||||
'class' => 'phui-info-view-list',
|
'class' => 'phui-info-view-list',
|
||||||
),
|
),
|
||||||
$list);
|
$list);
|
||||||
|
} else if (count($errors) == 1) {
|
||||||
|
$list = $this->errors[0];
|
||||||
} else {
|
} else {
|
||||||
$list = null;
|
$list = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,11 @@
|
||||||
final class PhabricatorSourceCodeView extends AphrontView {
|
final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
|
|
||||||
private $lines;
|
private $lines;
|
||||||
private $limit;
|
|
||||||
private $uri;
|
private $uri;
|
||||||
private $highlights = array();
|
private $highlights = array();
|
||||||
private $canClickHighlight = true;
|
private $canClickHighlight = true;
|
||||||
|
private $truncatedFirstBytes = false;
|
||||||
public function setLimit($limit) {
|
private $truncatedFirstLines = false;
|
||||||
$this->limit = $limit;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setLines(array $lines) {
|
public function setLines(array $lines) {
|
||||||
$this->lines = $lines;
|
$this->lines = $lines;
|
||||||
|
@ -33,6 +29,16 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setTruncatedFirstBytes($truncated_first_bytes) {
|
||||||
|
$this->truncatedFirstBytes = $truncated_first_bytes;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTruncatedFirstLines($truncated_first_lines) {
|
||||||
|
$this->truncatedFirstLines = $truncated_first_lines;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
require_celerity_resource('phabricator-source-code-view-css');
|
require_celerity_resource('phabricator-source-code-view-css');
|
||||||
require_celerity_resource('syntax-highlighting-css');
|
require_celerity_resource('syntax-highlighting-css');
|
||||||
|
@ -46,24 +52,31 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
|
|
||||||
foreach ($this->lines as $line) {
|
$lines = $this->lines;
|
||||||
$hit_limit = $this->limit &&
|
if ($this->truncatedFirstLines) {
|
||||||
($line_number == $this->limit) &&
|
$lines[] = phutil_tag(
|
||||||
(count($this->lines) != $this->limit);
|
|
||||||
|
|
||||||
if ($hit_limit) {
|
|
||||||
$content_number = '';
|
|
||||||
$content_line = phutil_tag(
|
|
||||||
'span',
|
'span',
|
||||||
array(
|
array(
|
||||||
'class' => 'c',
|
'class' => 'c',
|
||||||
),
|
),
|
||||||
pht('...'));
|
pht('...'));
|
||||||
} else {
|
} else if ($this->truncatedFirstBytes) {
|
||||||
$content_number = $line_number;
|
$last_key = last_key($lines);
|
||||||
|
$lines[$last_key] = hsprintf(
|
||||||
|
'%s%s',
|
||||||
|
$lines[$last_key],
|
||||||
|
phutil_tag(
|
||||||
|
'span',
|
||||||
|
array(
|
||||||
|
'class' => 'c',
|
||||||
|
),
|
||||||
|
pht('...')));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
|
||||||
// NOTE: See phabricator-oncopy behavior.
|
// NOTE: See phabricator-oncopy behavior.
|
||||||
$content_line = hsprintf("\xE2\x80\x8B%s", $line);
|
$content_line = hsprintf("\xE2\x80\x8B%s", $line);
|
||||||
}
|
|
||||||
|
|
||||||
$row_attributes = array();
|
$row_attributes = array();
|
||||||
if (isset($this->highlights[$line_number])) {
|
if (isset($this->highlights[$line_number])) {
|
||||||
|
@ -106,10 +119,6 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
$content_line),
|
$content_line),
|
||||||
));
|
));
|
||||||
|
|
||||||
if ($hit_limit) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$line_number++;
|
$line_number++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-drydock-live-operation-status
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-dom
|
||||||
|
* javelin-request
|
||||||
|
* @javelin
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('drydock-live-operation-status', function(config) {
|
||||||
|
var node = JX.$(config.statusID);
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
new JX.Request(config.updateURI, onresponse)
|
||||||
|
.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onresponse(r) {
|
||||||
|
var new_node = JX.$H(r.markup).getNode();
|
||||||
|
JX.DOM.replace(node, new_node);
|
||||||
|
node = new_node;
|
||||||
|
|
||||||
|
if (r.isUnderway) {
|
||||||
|
poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function poll() {
|
||||||
|
setTimeout(update, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
poll();
|
||||||
|
});
|
Loading…
Reference in a new issue