1
0
Fork 0
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:
epriestley 2015-10-24 05:41:48 -07:00
commit 9520a6b0ed
54 changed files with 780 additions and 369 deletions

View file

@ -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',

View file

@ -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',

View file

@ -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 {

View file

@ -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

View file

@ -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')

View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -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())

View file

@ -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)

View file

@ -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)

View file

@ -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(

View file

@ -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',

View file

@ -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);
}
}

View file

@ -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();

View file

@ -95,6 +95,7 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication {
=> 'DrydockRepositoryOperationListController',
'(?P<id>[1-9]\d*)/' => array(
'' => 'DrydockRepositoryOperationViewController',
'status/' => 'DrydockRepositoryOperationStatusController',
),
),
),

View file

@ -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'),
),
));
}
}

View file

@ -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) {

View file

@ -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;

View file

@ -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 )----------------------------------------- */

View file

@ -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);
}
}

View file

@ -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())

View file

@ -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);
}
}

View file

@ -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) {

View file

@ -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()));

View file

@ -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(

View file

@ -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() {

View file

@ -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(

View 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;
}
}

View file

@ -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 )----------------------------------- */

View file

@ -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());
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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()));

View file

@ -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)

View file

@ -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())

View file

@ -9,7 +9,6 @@ final class PhabricatorSearchHovercardController
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$phids = $request->getArr('phids');
$handles = id(new PhabricatorHandleQuery())

View file

@ -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');

View file

@ -31,6 +31,9 @@
},
"fieldmanual": {
"name": "Field Manuals"
},
"cellar": {
"name": "Musty Cellar"
}
}
}

View file

@ -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}.

View file

@ -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}.

View file

@ -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}.

View file

@ -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}.

View file

@ -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 ]].

View 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.

View file

@ -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 ==

View file

@ -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}.

View file

@ -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}.

View file

@ -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!}.

View file

@ -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!}.

View file

@ -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;
}

View file

@ -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++;
}

View file

@ -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();
});