mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 18:22:41 +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-pull-lastmodified.js' => 'f01586dc',
|
||||
'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-launch-icon-composer.js' => '48086888',
|
||||
'rsrc/js/application/herald/HeraldRuleEditor.js' => '91a6031b',
|
||||
|
@ -576,6 +577,7 @@ return array(
|
|||
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
||||
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
|
||||
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
||||
'javelin-behavior-drydock-live-operation-status' => '901935ef',
|
||||
'javelin-behavior-durable-column' => 'c72aa091',
|
||||
'javelin-behavior-error-log' => '6882e80a',
|
||||
'javelin-behavior-event-all-day' => '38dcf3c8',
|
||||
|
@ -1518,6 +1520,11 @@ return array(
|
|||
'javelin-dom',
|
||||
'javelin-stratcom',
|
||||
),
|
||||
'901935ef' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-dom',
|
||||
'javelin-request',
|
||||
),
|
||||
'91a6031b' => array(
|
||||
'multirow-row-manager',
|
||||
'javelin-install',
|
||||
|
|
|
@ -885,6 +885,8 @@ phutil_register_library_map(array(
|
|||
'DrydockRepositoryOperationPHIDType' => 'applications/drydock/phid/DrydockRepositoryOperationPHIDType.php',
|
||||
'DrydockRepositoryOperationQuery' => 'applications/drydock/query/DrydockRepositoryOperationQuery.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',
|
||||
'DrydockRepositoryOperationUpdateWorker' => 'applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php',
|
||||
'DrydockRepositoryOperationViewController' => 'applications/drydock/controller/DrydockRepositoryOperationViewController.php',
|
||||
|
@ -2552,6 +2554,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPasteRemarkupRule' => 'applications/paste/remarkup/PhabricatorPasteRemarkupRule.php',
|
||||
'PhabricatorPasteSchemaSpec' => 'applications/paste/storage/PhabricatorPasteSchemaSpec.php',
|
||||
'PhabricatorPasteSearchEngine' => 'applications/paste/query/PhabricatorPasteSearchEngine.php',
|
||||
'PhabricatorPasteSnippet' => 'applications/paste/snippet/PhabricatorPasteSnippet.php',
|
||||
'PhabricatorPasteTestDataGenerator' => 'applications/paste/lipsum/PhabricatorPasteTestDataGenerator.php',
|
||||
'PhabricatorPasteTransaction' => 'applications/paste/storage/PhabricatorPasteTransaction.php',
|
||||
'PhabricatorPasteTransactionComment' => 'applications/paste/storage/PhabricatorPasteTransactionComment.php',
|
||||
|
@ -4671,6 +4674,8 @@ phutil_register_library_map(array(
|
|||
'DrydockRepositoryOperationPHIDType' => 'PhabricatorPHIDType',
|
||||
'DrydockRepositoryOperationQuery' => 'DrydockQuery',
|
||||
'DrydockRepositoryOperationSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'DrydockRepositoryOperationStatusController' => 'DrydockController',
|
||||
'DrydockRepositoryOperationStatusView' => 'AphrontView',
|
||||
'DrydockRepositoryOperationType' => 'Phobject',
|
||||
'DrydockRepositoryOperationUpdateWorker' => 'DrydockWorker',
|
||||
'DrydockRepositoryOperationViewController' => 'DrydockController',
|
||||
|
@ -6633,6 +6638,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPasteRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||
'PhabricatorPasteSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'PhabricatorPasteSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PhabricatorPasteSnippet' => 'Phobject',
|
||||
'PhabricatorPasteTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
||||
'PhabricatorPasteTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'PhabricatorPasteTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||
|
|
|
@ -113,6 +113,27 @@ final class PhabricatorAuthLoginController
|
|||
$provider->getProviderName()));
|
||||
}
|
||||
} 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()) {
|
||||
return $this->processLinkUser($account);
|
||||
} 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
|
||||
// we can).
|
||||
|
||||
// In some setups, the parent PID is more stable and longer-lived that the
|
||||
// PID (e.g., under apache, our PID will be a worker while the ppid will
|
||||
// be the main httpd process). If we're confident we're running under such
|
||||
// a setup, we can try to use the PPID as the basis for our cache instead
|
||||
// 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;
|
||||
}
|
||||
// Unfortunately, we don't have a very good strategy for minimizing the
|
||||
// churn rate of the cache. We previously tried to use the parent process
|
||||
// PID in some cases, but this was not reliable. See T9599 for one case of
|
||||
// this.
|
||||
|
||||
$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
|
||||
// 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() {
|
||||
if (version_compare(phpversion(), '5.5', '>=')) {
|
||||
$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
|
||||
->newIssue('extension.apcu')
|
||||
|
|
|
@ -7,18 +7,9 @@ final class PhabricatorConduitAPIController
|
|||
return false;
|
||||
}
|
||||
|
||||
private $method;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->method = $data['method'];
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$method = $request->getURIData('method');
|
||||
$time_start = microtime(true);
|
||||
$request = $this->getRequest();
|
||||
|
||||
$method = $this->method;
|
||||
|
||||
$api_request = null;
|
||||
$method_implementation = null;
|
||||
|
@ -55,7 +46,7 @@ final class PhabricatorConduitAPIController
|
|||
$conduit_username = '-';
|
||||
if ($call->shouldRequireAuthentication()) {
|
||||
$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
|
||||
// CSRF validation or are using a non-web authentication mechanism.
|
||||
$allow_unguarded_writes = true;
|
||||
|
@ -169,7 +160,8 @@ final class PhabricatorConduitAPIController
|
|||
*/
|
||||
private function authenticateUser(
|
||||
ConduitAPIRequest $api_request,
|
||||
array $metadata) {
|
||||
array $metadata,
|
||||
$method) {
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
|
@ -207,7 +199,7 @@ final class PhabricatorConduitAPIController
|
|||
unset($protocol_data['scope']);
|
||||
|
||||
ConduitClient::verifySignature(
|
||||
$this->method,
|
||||
$method,
|
||||
$api_request->getAllParameters(),
|
||||
$protocol_data,
|
||||
$ssl_public_key);
|
||||
|
|
|
@ -3,19 +3,13 @@
|
|||
final class PhabricatorConduitListController
|
||||
extends PhabricatorConduitController {
|
||||
|
||||
private $queryKey;
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->queryKey = idx($data, 'queryKey');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$controller = id(new PhabricatorApplicationSearchController())
|
||||
->setQueryKey($this->queryKey)
|
||||
->setQueryKey($request->getURIData('queryKey'))
|
||||
->setSearchEngine(new PhabricatorConduitSearchEngine())
|
||||
->setNavigation($this->buildSideNavView());
|
||||
return $this->delegateToController($controller);
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
final class PhabricatorConduitLogController
|
||||
extends PhabricatorConduitController {
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$conn_table = new PhabricatorConduitConnectionLog();
|
||||
$call_table = new PhabricatorConduitMethodCallLog();
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
final class PhabricatorConduitTokenController
|
||||
extends PhabricatorConduitController {
|
||||
|
||||
public function processRequest() {
|
||||
$user = $this->getRequest()->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
|
||||
$user,
|
||||
$viewer,
|
||||
$this->getRequest(),
|
||||
'/');
|
||||
|
||||
|
@ -19,13 +19,13 @@ final class PhabricatorConduitTokenController
|
|||
$old_token = id(new PhabricatorConduitCertificateToken())
|
||||
->loadOneWhere(
|
||||
'userPHID = %s',
|
||||
$user->getPHID());
|
||||
$viewer->getPHID());
|
||||
if ($old_token) {
|
||||
$old_token->delete();
|
||||
}
|
||||
|
||||
$token = id(new PhabricatorConduitCertificateToken())
|
||||
->setUserPHID($user->getPHID())
|
||||
->setUserPHID($viewer->getPHID())
|
||||
->setToken(Filesystem::readRandomCharacters(40))
|
||||
->save();
|
||||
|
||||
|
@ -42,7 +42,7 @@ final class PhabricatorConduitTokenController
|
|||
Javelin::initBehavior('select-on-click');
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->setUser($viewer)
|
||||
->appendRemarkupInstructions($pre_instructions)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextAreaControl())
|
||||
|
|
|
@ -5,8 +5,8 @@ final class PhabricatorConduitTokenEditController
|
|||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
|
||||
if ($id) {
|
||||
$token = id(new PhabricatorConduitTokenQuery())
|
||||
->setViewer($viewer)
|
||||
|
|
|
@ -5,9 +5,9 @@ final class PhabricatorConduitTokenTerminateController
|
|||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$object_phid = $request->getStr('objectPHID');
|
||||
$id = $request->getURIData('id');
|
||||
|
||||
if ($id) {
|
||||
$token = id(new PhabricatorConduitTokenQuery())
|
||||
->setViewer($viewer)
|
||||
|
|
|
@ -225,18 +225,8 @@ final class PhabricatorConfigWelcomeController
|
|||
'fa-globe',
|
||||
$content);
|
||||
|
||||
$support_href = PhabricatorEnv::getDoclink('Give Feedback! Get Support!');
|
||||
$content = pht(
|
||||
"=== 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);
|
||||
// TODO: Restore some sort of "Support" link here, but just nuke it for
|
||||
// now as we figure stuff out.
|
||||
|
||||
$differential_uri = PhabricatorEnv::getURI('/differential/');
|
||||
$differential_create_uri = PhabricatorEnv::getURI(
|
||||
|
|
|
@ -20,8 +20,6 @@ final class PhabricatorSecurityConfigOptions
|
|||
}
|
||||
|
||||
public function getOptions() {
|
||||
$support_href = PhabricatorEnv::getDoclink('Give Feedback! Get Support!');
|
||||
|
||||
$doc_href = PhabricatorEnv::getDoclink('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".'))
|
||||
->setDescription(
|
||||
pht(
|
||||
"Users can configure a URI pattern to open files in a text ".
|
||||
"editor. The URI must use a protocol on this whitelist.\n\n".
|
||||
"(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))
|
||||
'Users can configure a URI pattern to open files in a text '.
|
||||
'editor. The URI must use a protocol on this whitelist.'))
|
||||
->setLocked(true),
|
||||
$this->newOption(
|
||||
'celerity.resource-hash',
|
||||
|
|
|
@ -1060,30 +1060,13 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
|
||||
$operation = head(msort($operations, 'getID'));
|
||||
|
||||
// TODO: This is completely made up for now, give it useful information and
|
||||
// a sweet progress bar.
|
||||
$box_view = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Active Operations'));
|
||||
|
||||
switch ($operation->getOperationState()) {
|
||||
case DrydockRepositoryOperation::STATE_WAIT:
|
||||
case DrydockRepositoryOperation::STATE_WORK:
|
||||
$severity = PHUIInfoView::SEVERITY_NOTICE;
|
||||
$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);
|
||||
return id(new DrydockRepositoryOperationStatusView())
|
||||
->setUser($viewer)
|
||||
->setBoxView($box_view)
|
||||
->setOperation($operation);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -288,7 +288,7 @@ final class DiffusionBrowseFileController extends DiffusionBrowseController {
|
|||
|
||||
$repo = $drequest->getRepository();
|
||||
$symbol_repos = nonempty($repo->getSymbolSources(), array());
|
||||
$symbol_repos[] = $repo;
|
||||
$symbol_repos[] = $repo->getPHID();
|
||||
|
||||
$lang = last(explode('.', $drequest->getPath()));
|
||||
$repo_languages = $repo->getSymbolLanguages();
|
||||
|
|
|
@ -95,6 +95,7 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication {
|
|||
=> 'DrydockRepositoryOperationListController',
|
||||
'(?P<id>[1-9]\d*)/' => array(
|
||||
'' => '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');
|
||||
}
|
||||
|
||||
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(
|
||||
DrydockRepositoryOperation $operation,
|
||||
DrydockInterface $interface) {
|
||||
|
|
|
@ -12,6 +12,10 @@ abstract class DrydockRepositoryOperationType extends Phobject {
|
|||
DrydockRepositoryOperation $operation,
|
||||
PhabricatorUser $viewer);
|
||||
|
||||
abstract public function getOperationCurrentStatus(
|
||||
DrydockRepositoryOperation $operation,
|
||||
PhabricatorUser $viewer);
|
||||
|
||||
final public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
return $this;
|
||||
|
|
|
@ -142,6 +142,22 @@ final class DrydockRepositoryOperation extends DrydockDAO
|
|||
$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 )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -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) {
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
$viewer_phid = $viewer->getPHID();
|
||||
|
||||
$id = $task->getID();
|
||||
$phid = $task->getPHID();
|
||||
|
@ -391,6 +390,8 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
|||
$task,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$can_create = $viewer->isLoggedIn();
|
||||
|
||||
$view = id(new PhabricatorActionListView())
|
||||
->setUser($viewer)
|
||||
->setObject($task)
|
||||
|
@ -417,7 +418,9 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
|||
id(new PhabricatorActionView())
|
||||
->setName(pht('Create Subtask'))
|
||||
->setHref($this->getApplicationURI("/task/create/?parent={$id}"))
|
||||
->setIcon('fa-level-down'));
|
||||
->setIcon('fa-level-down')
|
||||
->setDisabled(!$can_create)
|
||||
->setWorkflow(!$can_create));
|
||||
|
||||
$view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
|
|
|
@ -145,7 +145,12 @@ final class PhabricatorApplicationEditController
|
|||
->setViewer($user)
|
||||
->setObject($template_object)
|
||||
->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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,9 +54,7 @@ final class PhabricatorContentSource extends Phobject {
|
|||
public static function newFromRequest(AphrontRequest $request) {
|
||||
return self::newForSource(
|
||||
self::SOURCE_WEB,
|
||||
array(
|
||||
'ip' => $request->getRemoteAddr(),
|
||||
));
|
||||
array());
|
||||
}
|
||||
|
||||
public static function newFromConduitRequest(ConduitAPIRequest $request) {
|
||||
|
|
|
@ -39,13 +39,11 @@ abstract class PhabricatorPasteController extends PhabricatorController {
|
|||
|
||||
public function buildSourceCodeView(
|
||||
PhabricatorPaste $paste,
|
||||
$max_lines = null,
|
||||
$highlights = array()) {
|
||||
|
||||
$lines = phutil_split_lines($paste->getContent());
|
||||
|
||||
return id(new PhabricatorSourceCodeView())
|
||||
->setLimit($max_lines)
|
||||
->setLines($lines)
|
||||
->setHighlights($highlights)
|
||||
->setURI(new PhutilURI($paste->getURI()));
|
||||
|
|
|
@ -56,10 +56,7 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController {
|
|||
->setHeader($header)
|
||||
->addPropertyList($properties);
|
||||
|
||||
$source_code = $this->buildSourceCodeView(
|
||||
$paste,
|
||||
null,
|
||||
$this->highlightMap);
|
||||
$source_code = $this->buildSourceCodeView($paste, $this->highlightMap);
|
||||
|
||||
require_celerity_resource('paste-css');
|
||||
$source_code = phutil_tag(
|
||||
|
|
|
@ -10,6 +10,7 @@ final class PhabricatorPasteQuery
|
|||
|
||||
private $needContent;
|
||||
private $needRawContent;
|
||||
private $needSnippets;
|
||||
private $languages;
|
||||
private $includeNoLanguage;
|
||||
private $dateCreatedAfter;
|
||||
|
@ -47,6 +48,11 @@ final class PhabricatorPasteQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function needSnippets($need_snippets) {
|
||||
$this->needSnippets = $need_snippets;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withLanguages(array $languages) {
|
||||
$this->includeNoLanguage = false;
|
||||
foreach ($languages as $key => $language) {
|
||||
|
@ -91,6 +97,10 @@ final class PhabricatorPasteQuery
|
|||
$pastes = $this->loadContent($pastes);
|
||||
}
|
||||
|
||||
if ($this->needSnippets) {
|
||||
$pastes = $this->loadSnippets($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) {
|
||||
$file_phids = mpull($pastes, 'getFilePHID');
|
||||
$files = id(new PhabricatorFileQuery())
|
||||
|
@ -250,19 +271,114 @@ final class PhabricatorPasteQuery
|
|||
return $pastes;
|
||||
}
|
||||
|
||||
private function buildContent(PhabricatorPaste $paste) {
|
||||
$language = $paste->getLanguage();
|
||||
$source = $paste->getRawContent();
|
||||
private function loadSnippets(array $pastes) {
|
||||
$cache = new PhabricatorKeyValueDatabaseCache();
|
||||
|
||||
if (empty($language)) {
|
||||
return PhabricatorSyntaxHighlighter::highlightWithFilename(
|
||||
$paste->getTitle(),
|
||||
$source);
|
||||
} else {
|
||||
return PhabricatorSyntaxHighlighter::highlightWithLanguage(
|
||||
$language,
|
||||
$source);
|
||||
$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)) {
|
||||
return PhabricatorSyntaxHighlighter::highlightWithFilename(
|
||||
$title,
|
||||
$source);
|
||||
} else {
|
||||
return PhabricatorSyntaxHighlighter::highlightWithLanguage(
|
||||
$language,
|
||||
$source);
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
|
|
|
@ -13,7 +13,7 @@ final class PhabricatorPasteSearchEngine
|
|||
|
||||
public function newQuery() {
|
||||
return id(new PhabricatorPasteQuery())
|
||||
->needContent(true);
|
||||
->needSnippets(true);
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
|
@ -136,11 +136,15 @@ final class PhabricatorPasteSearchEngine
|
|||
$created = phabricator_date($paste->getDateCreated(), $viewer);
|
||||
$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())
|
||||
->setLimit(5)
|
||||
->setLines($lines)
|
||||
->setTruncatedFirstBytes(
|
||||
$snippet_type == PhabricatorPasteSnippet::FIRST_BYTES)
|
||||
->setTruncatedFirstLines(
|
||||
$snippet_type == PhabricatorPasteSnippet::FIRST_LINES)
|
||||
->setURI(new PhutilURI($paste->getURI()));
|
||||
|
||||
$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 $rawContent = self::ATTACHABLE;
|
||||
private $snippet = self::ATTACHABLE;
|
||||
|
||||
public static function initializeNewPaste(PhabricatorUser $actor) {
|
||||
$app = id(new PhabricatorApplicationQuery())
|
||||
|
@ -135,6 +136,15 @@ final class PhabricatorPaste extends PhabricatorPasteDAO
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getSnippet() {
|
||||
return $this->assertAttached($this->snippet);
|
||||
}
|
||||
|
||||
public function attachSnippet(PhabricatorPasteSnippet $snippet) {
|
||||
$this->snippet = $snippet;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -2,35 +2,29 @@
|
|||
|
||||
final class PhluxEditController extends PhluxController {
|
||||
|
||||
private $key;
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$key = $request->getURIData('key');
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->key = idx($data, 'key');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$is_new = ($this->key === null);
|
||||
$is_new = ($key === null);
|
||||
if ($is_new) {
|
||||
$var = new PhluxVariable();
|
||||
$var->setViewPolicy(PhabricatorPolicies::POLICY_USER);
|
||||
$var->setEditPolicy(PhabricatorPolicies::POLICY_USER);
|
||||
} else {
|
||||
$var = id(new PhluxVariableQuery())
|
||||
->setViewer($user)
|
||||
->setViewer($viewer)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->withKeys(array($this->key))
|
||||
->withKeys(array($key))
|
||||
->executeOne();
|
||||
if (!$var) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$view_uri = $this->getApplicationURI('/view/'.$this->key.'/');
|
||||
$view_uri = $this->getApplicationURI('/view/'.$key.'/');
|
||||
}
|
||||
|
||||
$e_key = ($is_new ? true : null);
|
||||
|
@ -67,7 +61,7 @@ final class PhluxEditController extends PhluxController {
|
|||
|
||||
if (!$errors) {
|
||||
$editor = id(new PhluxVariableEditor())
|
||||
->setActor($user)
|
||||
->setActor($viewer)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContentSourceFromRequest($request);
|
||||
|
||||
|
@ -110,12 +104,12 @@ final class PhluxEditController extends PhluxController {
|
|||
}
|
||||
|
||||
$policies = id(new PhabricatorPolicyQuery())
|
||||
->setViewer($user)
|
||||
->setViewer($viewer)
|
||||
->setObject($var)
|
||||
->execute();
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->setUser($viewer)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setValue($var->getVariableKey())
|
||||
|
@ -161,7 +155,7 @@ final class PhluxEditController extends PhluxController {
|
|||
$title = pht('Create Variable');
|
||||
$crumbs->addTextCrumb($title, $request->getRequestURI());
|
||||
} else {
|
||||
$title = pht('Edit %s', $this->key);
|
||||
$title = pht('Edit %s', $key);
|
||||
$crumbs->addTextCrumb($title, $request->getRequestURI());
|
||||
}
|
||||
|
||||
|
|
|
@ -2,14 +2,13 @@
|
|||
|
||||
final class PhluxListController extends PhluxController {
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$pager = new AphrontCursorPagerView();
|
||||
$pager->readFromRequest($request);
|
||||
$query = id(new PhluxVariableQuery())
|
||||
->setViewer($user);
|
||||
->setViewer($viewer);
|
||||
|
||||
$vars = $query->executeWithCursorPager($pager);
|
||||
|
||||
|
@ -22,7 +21,7 @@ final class PhluxListController extends PhluxController {
|
|||
$item->setHref($this->getApplicationURI('/view/'.$key.'/'));
|
||||
$item->addIcon(
|
||||
'none',
|
||||
phabricator_datetime($var->getDateModified(), $user));
|
||||
phabricator_datetime($var->getDateModified(), $viewer));
|
||||
|
||||
$view->addItem($item);
|
||||
}
|
||||
|
|
|
@ -2,19 +2,13 @@
|
|||
|
||||
final class PhluxViewController extends PhluxController {
|
||||
|
||||
private $key;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->key = $data['key'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$key = $request->getURIData('key');
|
||||
|
||||
$var = id(new PhluxVariableQuery())
|
||||
->setViewer($user)
|
||||
->withKeys(array($this->key))
|
||||
->setViewer($viewer)
|
||||
->withKeys(array($key))
|
||||
->executeOne();
|
||||
|
||||
if (!$var) {
|
||||
|
@ -29,16 +23,16 @@ final class PhluxViewController extends PhluxController {
|
|||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader($title)
|
||||
->setUser($user)
|
||||
->setUser($viewer)
|
||||
->setPolicyObject($var);
|
||||
|
||||
$actions = id(new PhabricatorActionListView())
|
||||
->setUser($user)
|
||||
->setUser($viewer)
|
||||
->setObjectURI($request->getRequestURI())
|
||||
->setObject($var);
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$user,
|
||||
$viewer,
|
||||
$var,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
|
@ -53,7 +47,7 @@ final class PhluxViewController extends PhluxController {
|
|||
$display_value = json_encode($var->getVariableValue());
|
||||
|
||||
$properties = id(new PHUIPropertyListView())
|
||||
->setUser($user)
|
||||
->setUser($viewer)
|
||||
->setObject($var)
|
||||
->setActionList($actions)
|
||||
->addProperty(pht('Value'), $display_value);
|
||||
|
|
|
@ -67,6 +67,13 @@ final class PhabricatorProjectBoardViewController
|
|||
// TODO: Expand the checks here if we add the ability
|
||||
// to hide the Backlog column
|
||||
if (!$columns) {
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$project,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
if (!$can_edit) {
|
||||
return $this->noAccessDialog($project);
|
||||
}
|
||||
switch ($request->getStr('initialize-type')) {
|
||||
case 'backlog-only':
|
||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||
|
@ -713,6 +720,20 @@ final class PhabricatorProjectBoardViewController
|
|||
->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
|
||||
|
|
|
@ -5,19 +5,12 @@ final class PhabricatorSearchController
|
|||
|
||||
const SCOPE_CURRENT_APPLICATION = 'application';
|
||||
|
||||
private $queryKey;
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->queryKey = idx($data, 'queryKey');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
if ($request->getStr('jump') != 'no') {
|
||||
$pref_jump = PhabricatorUserPreferences::PREFERENCE_SEARCHBAR_JUMP;
|
||||
|
@ -97,7 +90,7 @@ final class PhabricatorSearchController
|
|||
}
|
||||
|
||||
$controller = id(new PhabricatorApplicationSearchController())
|
||||
->setQueryKey($this->queryKey)
|
||||
->setQueryKey($request->getURIData('queryKey'))
|
||||
->setSearchEngine($engine)
|
||||
->setNavigation($this->buildSideNavView());
|
||||
|
||||
|
@ -105,7 +98,7 @@ final class PhabricatorSearchController
|
|||
}
|
||||
|
||||
public function buildSideNavView($for_app = false) {
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
|
|
|
@ -3,33 +3,24 @@
|
|||
final class PhabricatorSearchDeleteController
|
||||
extends PhabricatorSearchBaseController {
|
||||
|
||||
private $queryKey;
|
||||
private $engineClass;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->queryKey = idx($data, 'queryKey');
|
||||
$this->engineClass = idx($data, 'engine');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$key = $this->queryKey;
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$key = $request->getURIData('queryKey');
|
||||
$engine_class = $request->getURIData('engine');
|
||||
|
||||
$base_class = 'PhabricatorApplicationSearchEngine';
|
||||
if (!is_subclass_of($this->engineClass, $base_class)) {
|
||||
if (!is_subclass_of($engine_class, $base_class)) {
|
||||
return new Aphront400Response();
|
||||
}
|
||||
|
||||
$engine = newv($this->engineClass, array());
|
||||
$engine->setViewer($user);
|
||||
$engine = newv($engine_class, array());
|
||||
$engine->setViewer($viewer);
|
||||
|
||||
$named_query = id(new PhabricatorNamedQueryQuery())
|
||||
->setViewer($user)
|
||||
->withEngineClassNames(array($this->engineClass))
|
||||
->setViewer($viewer)
|
||||
->withEngineClassNames(array($engine_class))
|
||||
->withQueryKeys(array($key))
|
||||
->withUserPHIDs(array($user->getPHID()))
|
||||
->withUserPHIDs(array($viewer->getPHID()))
|
||||
->executeOne();
|
||||
|
||||
if (!$named_query && $engine->isBuiltinQuery($key)) {
|
||||
|
@ -84,7 +75,7 @@ final class PhabricatorSearchDeleteController
|
|||
}
|
||||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($user)
|
||||
->setUser($viewer)
|
||||
->setTitle($title)
|
||||
->appendChild($desc)
|
||||
->addCancelButton($return_uri)
|
||||
|
|
|
@ -3,38 +3,31 @@
|
|||
final class PhabricatorSearchEditController
|
||||
extends PhabricatorSearchBaseController {
|
||||
|
||||
private $queryKey;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->queryKey = idx($data, 'queryKey');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$saved_query = id(new PhabricatorSavedQueryQuery())
|
||||
->setViewer($user)
|
||||
->withQueryKeys(array($this->queryKey))
|
||||
->setViewer($viewer)
|
||||
->withQueryKeys(array($request->getURIData('queryKey')))
|
||||
->executeOne();
|
||||
|
||||
if (!$saved_query) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$engine = $saved_query->newEngine()->setViewer($user);
|
||||
$engine = $saved_query->newEngine()->setViewer($viewer);
|
||||
|
||||
$complete_uri = $engine->getQueryManagementURI();
|
||||
$cancel_uri = $complete_uri;
|
||||
|
||||
$named_query = id(new PhabricatorNamedQueryQuery())
|
||||
->setViewer($user)
|
||||
->setViewer($viewer)
|
||||
->withQueryKeys(array($saved_query->getQueryKey()))
|
||||
->withUserPHIDs(array($user->getPHID()))
|
||||
->withUserPHIDs(array($viewer->getPHID()))
|
||||
->executeOne();
|
||||
if (!$named_query) {
|
||||
$named_query = id(new PhabricatorNamedQuery())
|
||||
->setUserPHID($user->getPHID())
|
||||
->setUserPHID($viewer->getPHID())
|
||||
->setQueryKey($saved_query->getQueryKey())
|
||||
->setEngineClassName($saved_query->getEngineClassName());
|
||||
|
||||
|
@ -64,7 +57,7 @@ final class PhabricatorSearchEditController
|
|||
}
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user);
|
||||
->setUser($viewer);
|
||||
|
||||
$form->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
|
|
|
@ -9,7 +9,6 @@ final class PhabricatorSearchHovercardController
|
|||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$phids = $request->getArr('phids');
|
||||
|
||||
$handles = id(new PhabricatorHandleQuery())
|
||||
|
|
|
@ -3,25 +3,19 @@
|
|||
final class PhabricatorSearchOrderController
|
||||
extends PhabricatorSearchBaseController {
|
||||
|
||||
private $engineClass;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->engineClass = idx($data, 'engine');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$engine_class = $request->getURIData('engine');
|
||||
|
||||
$request->validateCSRF();
|
||||
|
||||
$base_class = 'PhabricatorApplicationSearchEngine';
|
||||
if (!is_subclass_of($this->engineClass, $base_class)) {
|
||||
if (!is_subclass_of($engine_class, $base_class)) {
|
||||
return new Aphront400Response();
|
||||
}
|
||||
|
||||
$engine = newv($this->engineClass, array());
|
||||
$engine->setViewer($user);
|
||||
$engine = newv($engine_class, array());
|
||||
$engine->setViewer($viewer);
|
||||
|
||||
$queries = $engine->loadAllNamedQueries();
|
||||
$queries = mpull($queries, null, 'getQueryKey');
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
},
|
||||
"fieldmanual": {
|
||||
"name": "Field Manuals"
|
||||
},
|
||||
"cellar": {
|
||||
"name": "Musty Cellar"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
|
||||
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
|
||||
========
|
||||
|
||||
|
@ -28,6 +36,7 @@ If you have a feature request (not a bug report), see
|
|||
For general information on contributing to Phabricator, see
|
||||
@{article:Contributor Introduction}.
|
||||
|
||||
|
||||
Common Fixes
|
||||
============
|
||||
|
||||
|
@ -73,6 +82,9 @@ Supported Issues
|
|||
Before filing a bug, make sure you're filing an issue against something we
|
||||
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
|
||||
with a prototype application, you're on your own. For more information about
|
||||
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
|
||||
to try to help.
|
||||
|
||||
|
||||
Getting More Information
|
||||
========================
|
||||
|
||||
|
@ -121,6 +134,7 @@ help us figure out and resolve an issue.
|
|||
troubleshooting. Adjusting settings or enabling debugging modes may give
|
||||
you more information about the issue.
|
||||
|
||||
|
||||
Reproducibility
|
||||
===============
|
||||
|
||||
|
@ -135,7 +149,9 @@ trouble narrowing something down or want to check if updating might fix an
|
|||
issue.
|
||||
|
||||
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
|
||||
=======================
|
||||
|
@ -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
|
||||
your issue by generating clear reproduction steps.
|
||||
|
||||
|
||||
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
|
||||
to file an issue.
|
||||
|
||||
We'll look at any issue report we can find (we monitor IRC, email,
|
||||
StackOverflow, Quora, Facebook and Twitter), but the upstream Maniphest is the
|
||||
authoritative bug tracker and the best place to file:
|
||||
It is **particularly critical** that you include reproduction steps. We will
|
||||
not accept reports which describe issues we can not reproduce.
|
||||
|
||||
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
|
||||
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 |
|
||||
|---|---|
|
||||
| Best | Upstream Maniphest |
|
||||
| Ehhh | Quora, StackOverflow, Facebook, email, etc. |
|
||||
| Ehhh | Quora, StackOverflow, Facebook, Jelly, email, etc. |
|
||||
| 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
|
||||
==========
|
||||
|
@ -195,6 +208,5 @@ Next Steps
|
|||
Continue by:
|
||||
|
||||
- learning about @{article: Contributing Feature Requests}; or
|
||||
- reading general support information in
|
||||
@{article: Give Feedback! Get Support!}; or
|
||||
- reading general support information in @{article:Support Resources}; or
|
||||
- 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
|
||||
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
|
||||
get in touch in @{article:Give Feedback! Get Support!}
|
||||
that our efforts are appreciated is really rewarding.
|
||||
- Recommend Phabricator to people who you think might find it useful. Our
|
||||
most powerful growth channel is word of mouth, and mentioning or tweeting
|
||||
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
|
||||
things right away, but knowing about issues users are encountering or
|
||||
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 requesting features, see @{article:Contributing Feature
|
||||
Requests}.
|
||||
|
@ -48,16 +46,11 @@ contribute to Phabricator:
|
|||
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
|
||||
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
|
||||
awesome too. To get started with contributing code, see
|
||||
@{article:Contributing Code}.
|
||||
If all of this sounds nice but you really just want to write some code, be
|
||||
aware that this project often presents a high barrier to entry for new
|
||||
contributors. To continue, see @{article:Contributing Code}.
|
||||
|
||||
|
||||
Next Steps
|
||||
==========
|
||||
|
@ -65,6 +58,6 @@ Next Steps
|
|||
Continue by:
|
||||
|
||||
- learning about bug reports in @{article:Contributing Bug Reports};
|
||||
- learning about feature requests in @{article:Contributing Feature Requests};
|
||||
- learning about code contributions in @{article:Contributing Code}; or
|
||||
- getting in touch with @{article:Give Feedback! Get Support!}
|
||||
- learning about feature requests in
|
||||
@{article:Contributing Feature Requests}; or
|
||||
- learning about code contributions in @{article:Contributing Code}.
|
||||
|
|
|
@ -3,6 +3,13 @@
|
|||
|
||||
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
|
||||
========
|
||||
|
||||
|
@ -138,8 +145,9 @@ upstream.
|
|||
Describe Problems
|
||||
=================
|
||||
|
||||
When you file a feature request, it is really helpful to describe the problem
|
||||
you're facing first, not just your desired solution.
|
||||
When you file a feature request, we need you to describe the problem you're
|
||||
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
|
||||
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,
|
||||
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
|
||||
=============
|
||||
|
@ -206,13 +218,13 @@ Create a Task in Maniphest
|
|||
|
||||
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
|
||||
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
|
||||
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!}.
|
||||
(NOTE) https://secure.phabricator.com/maniphest/task/create/
|
||||
|
||||
|
||||
Next Steps
|
||||
|
@ -221,6 +233,5 @@ Next Steps
|
|||
Continue by:
|
||||
|
||||
- learning about @{article: Contributing Bug Reports}; or
|
||||
- reading general support information in
|
||||
@{article: Give Feedback! Get Support!}; or
|
||||
- reading general support information in @{article:Support Resources}; or
|
||||
- returning to the @{article:Contributor Introduction}.
|
||||
|
|
|
@ -1,44 +1,7 @@
|
|||
@title Give Feedback! Get Support!
|
||||
@short Feedback/Support
|
||||
@group intro
|
||||
@group cellar
|
||||
|
||||
How to give us feedback, report bugs, and request features, and get support for
|
||||
problems with Phabricator.
|
||||
Deprecated.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
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}.
|
||||
This article has moved to @{article:Support Resources}.
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
Describes how to report security vulnerabilities in Phabricator.
|
||||
|
||||
= Overview =
|
||||
Overview
|
||||
========
|
||||
|
||||
Phabricator runs a disclosure and award program through
|
||||
[[ 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,
|
||||
very often, fix) issues more quickly than that.
|
||||
|
||||
= Other Channels =
|
||||
|
||||
You can also contact us on another channel if you prefer. See
|
||||
@{article:Give Feedback! Get Support!} for a list of ways to get in touch
|
||||
with us.
|
||||
Other Channels
|
||||
==============
|
||||
|
||||
= 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 ]];
|
||||
- on our [[ https://twitter.com/phabricator | Twitter Feed ]];
|
||||
- and on IRC (`#phabricator` on FreeNode).
|
||||
Get Updated
|
||||
===========
|
||||
|
||||
If you'd prefer to receive information on other channels, let us know.
|
||||
|
||||
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.
|
||||
General information about security changes is reported weekly in the
|
||||
[[ https://secure.phabricator.com/w/changelog/ | Changelog ]].
|
||||
|
|
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
|
||||
existing build scripts, so users can run `make install-arc` or
|
||||
`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 ==
|
||||
|
||||
|
|
|
@ -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
|
||||
creatively-named //Audit// tool.
|
||||
|
||||
NOTE: The audit workflow is new, give us feedback about it! See
|
||||
@{article:Give Feedback! Get Support!}.
|
||||
|
||||
= How Audit Works =
|
||||
|
||||
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 =
|
||||
|
||||
- Learn more about Herald at @{article:Herald User Guide}; or
|
||||
- give us feedback at @{article:Give Feedback! Get Support!}.
|
||||
- Learn more about Herald at @{article:Herald User Guide}.
|
||||
|
|
|
@ -65,5 +65,4 @@ files affected, etc.)
|
|||
- learn about handling large changesets at
|
||||
@{article:Differential User Guide: Large Changes}; or
|
||||
- learn about test plans at @{article:Differential User Guide: Test Plans}; or
|
||||
- learn more about Herald at @{article:Herald User Guide}; or
|
||||
- give us feedback at @{article:Give Feedback! Get Support!}.
|
||||
- learn more about Herald at @{article:Herald User Guide}.
|
||||
|
|
|
@ -5,6 +5,8 @@ Journal about your thoughts and feelings. Share with others. Profit.
|
|||
|
||||
= Overview =
|
||||
|
||||
IMPORTANT: Phame is a prototype application.
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
= 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.
|
||||
|
||||
= Overview =
|
||||
Overview
|
||||
========
|
||||
|
||||
Phriction is a simple wiki. You can edit pages, and the text you write will stay
|
||||
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');
|
||||
|
||||
$errors = $this->errors;
|
||||
if ($errors) {
|
||||
if (count($errors) > 1) {
|
||||
$list = array();
|
||||
foreach ($errors as $error) {
|
||||
$list[] = phutil_tag(
|
||||
|
@ -64,6 +64,8 @@ final class PHUIInfoView extends AphrontView {
|
|||
'class' => 'phui-info-view-list',
|
||||
),
|
||||
$list);
|
||||
} else if (count($errors) == 1) {
|
||||
$list = $this->errors[0];
|
||||
} else {
|
||||
$list = null;
|
||||
}
|
||||
|
|
|
@ -3,15 +3,11 @@
|
|||
final class PhabricatorSourceCodeView extends AphrontView {
|
||||
|
||||
private $lines;
|
||||
private $limit;
|
||||
private $uri;
|
||||
private $highlights = array();
|
||||
private $canClickHighlight = true;
|
||||
|
||||
public function setLimit($limit) {
|
||||
$this->limit = $limit;
|
||||
return $this;
|
||||
}
|
||||
private $truncatedFirstBytes = false;
|
||||
private $truncatedFirstLines = false;
|
||||
|
||||
public function setLines(array $lines) {
|
||||
$this->lines = $lines;
|
||||
|
@ -33,6 +29,16 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
|||
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() {
|
||||
require_celerity_resource('phabricator-source-code-view-css');
|
||||
require_celerity_resource('syntax-highlighting-css');
|
||||
|
@ -46,24 +52,31 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
|||
|
||||
$rows = array();
|
||||
|
||||
foreach ($this->lines as $line) {
|
||||
$hit_limit = $this->limit &&
|
||||
($line_number == $this->limit) &&
|
||||
(count($this->lines) != $this->limit);
|
||||
|
||||
if ($hit_limit) {
|
||||
$content_number = '';
|
||||
$content_line = phutil_tag(
|
||||
$lines = $this->lines;
|
||||
if ($this->truncatedFirstLines) {
|
||||
$lines[] = phutil_tag(
|
||||
'span',
|
||||
array(
|
||||
'class' => 'c',
|
||||
),
|
||||
pht('...'));
|
||||
} else {
|
||||
$content_number = $line_number;
|
||||
// NOTE: See phabricator-oncopy behavior.
|
||||
$content_line = hsprintf("\xE2\x80\x8B%s", $line);
|
||||
}
|
||||
} else if ($this->truncatedFirstBytes) {
|
||||
$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.
|
||||
$content_line = hsprintf("\xE2\x80\x8B%s", $line);
|
||||
|
||||
$row_attributes = array();
|
||||
if (isset($this->highlights[$line_number])) {
|
||||
|
@ -106,10 +119,6 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
|||
$content_line),
|
||||
));
|
||||
|
||||
if ($hit_limit) {
|
||||
break;
|
||||
}
|
||||
|
||||
$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