Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / applications / diffusion / management / DiffusionRepositoryBasicsManagementPanel.php
blob02df82c7c0f5e89ba011002ea6602f479756f900
1 <?php
3 final class DiffusionRepositoryBasicsManagementPanel
4 extends DiffusionRepositoryManagementPanel {
6 const PANELKEY = 'basics';
8 public function getManagementPanelLabel() {
9 return pht('Basics');
12 public function getManagementPanelOrder() {
13 return 100;
16 public function getManagementPanelIcon() {
17 return 'fa-code';
20 protected function getEditEngineFieldKeys() {
21 return array(
22 'name',
23 'callsign',
24 'shortName',
25 'description',
26 'projectPHIDs',
30 public function buildManagementPanelCurtain() {
31 $repository = $this->getRepository();
32 $viewer = $this->getViewer();
34 $action_list = id(new PhabricatorActionListView())
35 ->setViewer($viewer);
37 $can_edit = PhabricatorPolicyFilter::hasCapability(
38 $viewer,
39 $repository,
40 PhabricatorPolicyCapability::CAN_EDIT);
42 $edit_uri = $this->getEditPageURI();
43 $activate_uri = $repository->getPathURI('edit/activate/');
44 $delete_uri = $repository->getPathURI('edit/delete/');
45 $encoding_uri = $this->getEditPageURI('encoding');
46 $dangerous_uri = $repository->getPathURI('edit/dangerous/');
47 $enormous_uri = $repository->getPathURI('edit/enormous/');
48 $update_uri = $repository->getPathURI('edit/update/');
49 $publish_uri = $repository->getPathURI('edit/publish/');
51 if ($repository->isTracked()) {
52 $activate_icon = 'fa-ban';
53 $activate_label = pht('Deactivate Repository');
54 } else {
55 $activate_icon = 'fa-check';
56 $activate_label = pht('Activate Repository');
59 if (!$repository->isPublishingDisabled()) {
60 $publish_icon = 'fa-ban';
61 $publish_label = pht('Disable Publishing');
62 } else {
63 $publish_icon = 'fa-check';
64 $publish_label = pht('Enable Publishing');
67 $should_dangerous = $repository->shouldAllowDangerousChanges();
68 if ($should_dangerous) {
69 $dangerous_icon = 'fa-shield';
70 $dangerous_name = pht('Prevent Dangerous Changes');
71 $can_dangerous = $can_edit;
72 } else {
73 $dangerous_icon = 'fa-exclamation-triangle';
74 $dangerous_name = pht('Allow Dangerous Changes');
75 $can_dangerous = ($can_edit && $repository->canAllowDangerousChanges());
78 $should_enormous = $repository->shouldAllowEnormousChanges();
79 if ($should_enormous) {
80 $enormous_icon = 'fa-shield';
81 $enormous_name = pht('Prevent Enormous Changes');
82 $can_enormous = $can_edit;
83 } else {
84 $enormous_icon = 'fa-exclamation-triangle';
85 $enormous_name = pht('Allow Enormous Changes');
86 $can_enormous = ($can_edit && $repository->canAllowEnormousChanges());
89 $action_list->addAction(
90 id(new PhabricatorActionView())
91 ->setName(pht('Edit Basic Information'))
92 ->setHref($edit_uri)
93 ->setIcon('fa-pencil')
94 ->setDisabled(!$can_edit)
95 ->setWorkflow(!$can_edit));
97 $action_list->addAction(
98 id(new PhabricatorActionView())
99 ->setName(pht('Edit Text Encoding'))
100 ->setIcon('fa-text-width')
101 ->setHref($encoding_uri)
102 ->setDisabled(!$can_edit)
103 ->setWorkflow(!$can_edit));
105 $action_list->addAction(
106 id(new PhabricatorActionView())
107 ->setName($dangerous_name)
108 ->setHref($dangerous_uri)
109 ->setIcon($dangerous_icon)
110 ->setDisabled(!$can_dangerous)
111 ->setWorkflow(true));
113 $action_list->addAction(
114 id(new PhabricatorActionView())
115 ->setName($enormous_name)
116 ->setHref($enormous_uri)
117 ->setIcon($enormous_icon)
118 ->setDisabled(!$can_enormous)
119 ->setWorkflow(true));
121 $action_list->addAction(
122 id(new PhabricatorActionView())
123 ->setType(PhabricatorActionView::TYPE_DIVIDER));
125 $action_list->addAction(
126 id(new PhabricatorActionView())
127 ->setName($activate_label)
128 ->setHref($activate_uri)
129 ->setIcon($activate_icon)
130 ->setDisabled(!$can_edit)
131 ->setWorkflow(true));
133 $action_list->addAction(
134 id(new PhabricatorActionView())
135 ->setName($publish_label)
136 ->setHref($publish_uri)
137 ->setIcon($publish_icon)
138 ->setDisabled(!$can_edit)
139 ->setWorkflow(true));
141 $action_list->addAction(
142 id(new PhabricatorActionView())
143 ->setName(pht('Update Now'))
144 ->setHref($update_uri)
145 ->setIcon('fa-refresh')
146 ->setWorkflow(true)
147 ->setDisabled(!$can_edit));
149 $action_list->addAction(
150 id(new PhabricatorActionView())
151 ->setType(PhabricatorActionView::TYPE_DIVIDER));
153 $action_list->addAction(
154 id(new PhabricatorActionView())
155 ->setName(pht('Delete Repository'))
156 ->setHref($delete_uri)
157 ->setIcon('fa-times')
158 ->setWorkflow(true));
160 return $this->newCurtainView()
161 ->setActionList($action_list);
164 public function buildManagementPanelContent() {
165 $basics = $this->buildBasics();
166 $basics = $this->newBox(pht('Properties'), $basics);
168 $repository = $this->getRepository();
170 $state = $this->buildStateView($repository);
172 $is_new = $repository->isNewlyInitialized();
173 $info_view = null;
174 if ($is_new) {
175 $messages = array();
177 $messages[] = pht(
178 'This newly created repository is not active yet. Configure policies, '.
179 'options, and URIs. When ready, %s the repository.',
180 phutil_tag('strong', array(), pht('Activate')));
182 if ($repository->isHosted()) {
183 $messages[] = pht(
184 'If activated now, this repository will become a new hosted '.
185 'repository. To observe an existing repository instead, configure '.
186 'it in the %s panel.',
187 phutil_tag('strong', array(), pht('URIs')));
188 } else {
189 $messages[] = pht(
190 'If activated now, this repository will observe an existing remote '.
191 'repository and begin importing changes.');
194 $info_view = id(new PHUIInfoView())
195 ->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
196 ->setErrors($messages);
199 $description = $this->buildDescription();
200 if ($description) {
201 $description = $this->newBox(pht('Description'), $description);
203 $status = $this->buildStatus();
205 return array($info_view, $state, $basics, $description, $status);
208 private function buildBasics() {
209 $repository = $this->getRepository();
210 $viewer = $this->getViewer();
212 $view = id(new PHUIPropertyListView())
213 ->setViewer($viewer);
215 $name = $repository->getName();
216 $view->addProperty(pht('Name'), $name);
218 $type = PhabricatorRepositoryType::getNameForRepositoryType(
219 $repository->getVersionControlSystem());
220 $view->addProperty(pht('Type'), $type);
222 $callsign = $repository->getCallsign();
223 if (!strlen($callsign)) {
224 $callsign = phutil_tag('em', array(), pht('No Callsign'));
226 $view->addProperty(pht('Callsign'), $callsign);
228 $short_name = $repository->getRepositorySlug();
229 if ($short_name === null) {
230 $short_name = phutil_tag('em', array(), pht('No Short Name'));
232 $view->addProperty(pht('Short Name'), $short_name);
234 $encoding = $repository->getDetail('encoding');
235 if (!$encoding) {
236 $encoding = phutil_tag('em', array(), pht('Use Default (UTF-8)'));
238 $view->addProperty(pht('Encoding'), $encoding);
240 $can_dangerous = $repository->canAllowDangerousChanges();
241 if (!$can_dangerous) {
242 $dangerous = phutil_tag('em', array(), pht('Not Preventable'));
243 } else {
244 $should_dangerous = $repository->shouldAllowDangerousChanges();
245 if ($should_dangerous) {
246 $dangerous = pht('Allowed');
247 } else {
248 $dangerous = pht('Not Allowed');
252 $view->addProperty(pht('Dangerous Changes'), $dangerous);
254 $can_enormous = $repository->canAllowEnormousChanges();
255 if (!$can_enormous) {
256 $enormous = phutil_tag('em', array(), pht('Not Preventable'));
257 } else {
258 $should_enormous = $repository->shouldAllowEnormousChanges();
259 if ($should_enormous) {
260 $enormous = pht('Allowed');
261 } else {
262 $enormous = pht('Not Allowed');
266 $view->addProperty(pht('Enormous Changes'), $enormous);
268 return $view;
272 private function buildDescription() {
273 $repository = $this->getRepository();
274 $viewer = $this->getViewer();
276 $description = $repository->getDetail('description');
278 $view = id(new PHUIPropertyListView())
279 ->setViewer($viewer);
280 if (!strlen($description)) {
281 return null;
282 } else {
283 $description = new PHUIRemarkupView($viewer, $description);
285 $view->addTextContent($description);
287 return $view;
290 private function buildStatus() {
291 $repository = $this->getRepository();
292 $viewer = $this->getViewer();
294 $view = id(new PHUIPropertyListView())
295 ->setViewer($viewer);
297 $view->addProperty(
298 pht('Update Frequency'),
299 $this->buildRepositoryUpdateInterval($repository));
301 $messages = $this->loadStatusMessages($repository);
303 $status = $this->buildRepositoryStatus($repository, $messages);
304 $raw_error = $this->buildRepositoryRawError($repository, $messages);
306 $view->addProperty(pht('Status'), $status);
307 if ($raw_error) {
308 $view->addSectionHeader(pht('Raw Error'));
309 $view->addTextContent($raw_error);
312 return $this->newBox(pht('Working Copy Status'), $view);
315 private function buildRepositoryUpdateInterval(
316 PhabricatorRepository $repository) {
318 $smart_wait = $repository->loadUpdateInterval();
320 $doc_href = PhabricatorEnv::getDoclink(
321 'Diffusion User Guide: Repository Updates');
323 return array(
324 phutil_format_relative_time_detailed($smart_wait),
325 " \xC2\xB7 ",
326 phutil_tag(
327 'a',
328 array(
329 'href' => $doc_href,
330 'target' => '_blank',
332 pht('Learn More')),
336 private function buildRepositoryStatus(
337 PhabricatorRepository $repository,
338 array $messages) {
340 $viewer = $this->getViewer();
341 $is_cluster = $repository->getAlmanacServicePHID();
343 $view = new PHUIStatusListView();
345 if ($repository->isTracked()) {
346 $view->addItem(
347 id(new PHUIStatusItemView())
348 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
349 ->setTarget(pht('Repository Active')));
350 } else {
351 $view->addItem(
352 id(new PHUIStatusItemView())
353 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'bluegrey')
354 ->setTarget(pht('Repository Inactive'))
355 ->setNote(
356 pht('Activate this repository to begin or resume import.')));
357 return $view;
360 $binaries = array();
361 $svnlook_check = false;
362 switch ($repository->getVersionControlSystem()) {
363 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
364 $binaries[] = 'git';
365 break;
366 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
367 $binaries[] = 'svn';
368 break;
369 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
370 $binaries[] = 'hg';
371 break;
374 if ($repository->isHosted()) {
375 $proto_https = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTPS;
376 $proto_http = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_HTTP;
377 $can_http = $repository->canServeProtocol($proto_http, false) ||
378 $repository->canServeProtocol($proto_https, false);
380 if ($can_http) {
381 switch ($repository->getVersionControlSystem()) {
382 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
383 $binaries[] = 'git-http-backend';
384 break;
385 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
386 $binaries[] = 'svnserve';
387 $binaries[] = 'svnadmin';
388 $binaries[] = 'svnlook';
389 $svnlook_check = true;
390 break;
391 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
392 $binaries[] = 'hg';
393 break;
398 $proto_ssh = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH;
399 $can_ssh = $repository->canServeProtocol($proto_ssh, false);
401 if ($can_ssh) {
402 switch ($repository->getVersionControlSystem()) {
403 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
404 $binaries[] = 'git-receive-pack';
405 $binaries[] = 'git-upload-pack';
406 break;
407 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
408 $binaries[] = 'svnserve';
409 $binaries[] = 'svnadmin';
410 $binaries[] = 'svnlook';
411 $svnlook_check = true;
412 break;
413 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
414 $binaries[] = 'hg';
415 break;
420 $binaries = array_unique($binaries);
421 if (!$is_cluster) {
422 // We're only checking for binaries if we aren't running with a cluster
423 // configuration. In theory, we could check for binaries on the
424 // repository host machine, but we'd need to make this more complicated
425 // to do that.
427 foreach ($binaries as $binary) {
428 $where = Filesystem::resolveBinary($binary);
429 if (!$where) {
430 $view->addItem(
431 id(new PHUIStatusItemView())
432 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
433 ->setTarget(
434 pht('Missing Binary %s', phutil_tag('tt', array(), $binary)))
435 ->setNote(pht(
436 "Unable to find this binary in the webserver's PATH. You may ".
437 "need to configure %s.",
438 $this->getEnvConfigLink())));
439 } else {
440 $view->addItem(
441 id(new PHUIStatusItemView())
442 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
443 ->setTarget(
444 pht('Found Binary %s', phutil_tag('tt', array(), $binary)))
445 ->setNote(phutil_tag('tt', array(), $where)));
449 // This gets checked generically above. However, for svn commit hooks, we
450 // need this to be in environment.append-paths because subversion strips
451 // PATH.
452 if ($svnlook_check) {
453 $where = Filesystem::resolveBinary('svnlook');
454 if ($where) {
455 $path = substr($where, 0, strlen($where) - strlen('svnlook'));
456 $dirs = PhabricatorEnv::getEnvConfig('environment.append-paths');
457 $in_path = false;
458 foreach ($dirs as $dir) {
459 if (Filesystem::isDescendant($path, $dir)) {
460 $in_path = true;
461 break;
464 if (!$in_path) {
465 $view->addItem(
466 id(new PHUIStatusItemView())
467 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
468 ->setTarget(
469 pht('Commit Hooks: %s', phutil_tag('tt', array(), $binary)))
470 ->setNote(
471 pht(
472 'The directory containing the "svnlook" binary is not '.
473 'listed in "environment.append-paths", so commit hooks '.
474 '(which execute with an empty "PATH") will not be able to '.
475 'find "svnlook". Add `%s` to %s.',
476 $path,
477 $this->getEnvConfigLink())));
483 $doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd');
485 $daemon_instructions = pht(
486 'Use %s to start daemons. See %s.',
487 phutil_tag('tt', array(), 'bin/phd start'),
488 phutil_tag(
489 'a',
490 array(
491 'href' => $doc_href,
493 pht('Managing Daemons with phd')));
496 $pull_daemon = id(new PhabricatorDaemonLogQuery())
497 ->setViewer(PhabricatorUser::getOmnipotentUser())
498 ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
499 ->withDaemonClasses(array('PhabricatorRepositoryPullLocalDaemon'))
500 ->setLimit(1)
501 ->execute();
503 if ($pull_daemon) {
505 // TODO: In a cluster environment, we need a daemon on this repository's
506 // host, specifically, and we aren't checking for that right now. This
507 // is a reasonable proxy for things being more-or-less correctly set up,
508 // though.
510 $view->addItem(
511 id(new PHUIStatusItemView())
512 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
513 ->setTarget(pht('Pull Daemon Running')));
514 } else {
515 $view->addItem(
516 id(new PHUIStatusItemView())
517 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
518 ->setTarget(pht('Pull Daemon Not Running'))
519 ->setNote($daemon_instructions));
523 $task_daemon = id(new PhabricatorDaemonLogQuery())
524 ->setViewer(PhabricatorUser::getOmnipotentUser())
525 ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
526 ->withDaemonClasses(array('PhabricatorTaskmasterDaemon'))
527 ->setLimit(1)
528 ->execute();
529 if ($task_daemon) {
530 $view->addItem(
531 id(new PHUIStatusItemView())
532 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
533 ->setTarget(pht('Task Daemon Running')));
534 } else {
535 $view->addItem(
536 id(new PHUIStatusItemView())
537 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
538 ->setTarget(pht('Task Daemon Not Running'))
539 ->setNote($daemon_instructions));
543 if ($is_cluster) {
544 // Just omit this status check for now in cluster environments. We
545 // could make a service call and pull it from the repository host
546 // eventually.
547 } else if ($repository->usesLocalWorkingCopy()) {
548 $local_parent = dirname($repository->getLocalPath());
549 if (Filesystem::pathExists($local_parent)) {
550 $view->addItem(
551 id(new PHUIStatusItemView())
552 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
553 ->setTarget(pht('Storage Directory OK'))
554 ->setNote(phutil_tag('tt', array(), $local_parent)));
555 } else {
556 $view->addItem(
557 id(new PHUIStatusItemView())
558 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
559 ->setTarget(pht('No Storage Directory'))
560 ->setNote(
561 pht(
562 'Storage directory %s does not exist, or is not readable by '.
563 'the webserver. Create this directory or make it readable.',
564 phutil_tag('tt', array(), $local_parent))));
565 return $view;
568 $local_path = $repository->getLocalPath();
569 $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT);
570 if ($message) {
571 switch ($message->getStatusCode()) {
572 case PhabricatorRepositoryStatusMessage::CODE_ERROR:
573 $view->addItem(
574 id(new PHUIStatusItemView())
575 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
576 ->setTarget(pht('Initialization Error'))
577 ->setNote($message->getParameter('message')));
578 return $view;
579 case PhabricatorRepositoryStatusMessage::CODE_OKAY:
580 if (Filesystem::pathExists($local_path)) {
581 $view->addItem(
582 id(new PHUIStatusItemView())
583 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
584 ->setTarget(pht('Working Copy OK'))
585 ->setNote(phutil_tag('tt', array(), $local_path)));
586 } else {
587 $view->addItem(
588 id(new PHUIStatusItemView())
589 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
590 ->setTarget(pht('Working Copy Error'))
591 ->setNote(
592 pht(
593 'Working copy %s has been deleted, or is not '.
594 'readable by the webserver. Make this directory '.
595 'readable. If it has been deleted, the daemons should '.
596 'restore it automatically.',
597 phutil_tag('tt', array(), $local_path))));
598 return $view;
600 break;
601 default:
602 $view->addItem(
603 id(new PHUIStatusItemView())
604 ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green')
605 ->setTarget(pht('Initializing Working Copy'))
606 ->setNote(pht('Daemons are initializing the working copy.')));
607 return $view;
609 } else {
610 $view->addItem(
611 id(new PHUIStatusItemView())
612 ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange')
613 ->setTarget(pht('No Working Copy Yet'))
614 ->setNote(
615 pht('Waiting for daemons to build a working copy.')));
616 return $view;
620 $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH);
621 if ($message) {
622 switch ($message->getStatusCode()) {
623 case PhabricatorRepositoryStatusMessage::CODE_ERROR:
624 $message = $message->getParameter('message');
626 $suggestion = null;
627 if (preg_match('/Permission denied \(publickey\)./', $message)) {
628 $suggestion = pht(
629 'Public Key Error: This error usually indicates that the '.
630 'keypair you have configured does not have permission to '.
631 'access the repository.');
634 $view->addItem(
635 id(new PHUIStatusItemView())
636 ->setIcon(PHUIStatusItemView::ICON_WARNING, 'red')
637 ->setTarget(pht('Update Error'))
638 ->setNote($suggestion));
639 return $view;
640 case PhabricatorRepositoryStatusMessage::CODE_OKAY:
641 $ago = (PhabricatorTime::getNow() - $message->getEpoch());
642 $view->addItem(
643 id(new PHUIStatusItemView())
644 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
645 ->setTarget(pht('Updates OK'))
646 ->setNote(
647 pht(
648 'Last updated %s (%s ago).',
649 phabricator_datetime($message->getEpoch(), $viewer),
650 phutil_format_relative_time_detailed($ago))));
651 break;
653 } else {
654 $view->addItem(
655 id(new PHUIStatusItemView())
656 ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'orange')
657 ->setTarget(pht('Waiting For Update'))
658 ->setNote(
659 pht('Waiting for daemons to read updates.')));
662 if ($repository->isImporting()) {
663 $ratio = $repository->loadImportProgress();
664 $percentage = sprintf('%.2f%%', 100 * $ratio);
666 $view->addItem(
667 id(new PHUIStatusItemView())
668 ->setIcon(PHUIStatusItemView::ICON_CLOCK, 'green')
669 ->setTarget(pht('Importing'))
670 ->setNote(
671 pht('%s Complete', $percentage)));
672 } else {
673 $view->addItem(
674 id(new PHUIStatusItemView())
675 ->setIcon(PHUIStatusItemView::ICON_ACCEPT, 'green')
676 ->setTarget(pht('Fully Imported')));
679 if (idx($messages, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE)) {
680 $view->addItem(
681 id(new PHUIStatusItemView())
682 ->setIcon(PHUIStatusItemView::ICON_UP, 'indigo')
683 ->setTarget(pht('Prioritized'))
684 ->setNote(pht('This repository will be updated soon!')));
687 return $view;
690 private function buildRepositoryRawError(
691 PhabricatorRepository $repository,
692 array $messages) {
693 $viewer = $this->getViewer();
695 $can_edit = PhabricatorPolicyFilter::hasCapability(
696 $viewer,
697 $repository,
698 PhabricatorPolicyCapability::CAN_EDIT);
700 $raw_error = null;
702 $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH);
703 if ($message) {
704 switch ($message->getStatusCode()) {
705 case PhabricatorRepositoryStatusMessage::CODE_ERROR:
706 $raw_error = $message->getParameter('message');
707 break;
711 if ($raw_error !== null) {
712 if (!$can_edit) {
713 $raw_message = pht(
714 'You must be able to edit a repository to see raw error messages '.
715 'because they sometimes disclose sensitive information.');
716 $raw_message = phutil_tag('em', array(), $raw_message);
717 } else {
718 $raw_message = phutil_escape_html_newlines($raw_error);
720 } else {
721 $raw_message = null;
724 return $raw_message;
727 private function loadStatusMessages(PhabricatorRepository $repository) {
728 $messages = id(new PhabricatorRepositoryStatusMessage())
729 ->loadAllWhere('repositoryID = %d', $repository->getID());
730 $messages = mpull($messages, null, 'getStatusType');
732 return $messages;
735 private function getEnvConfigLink() {
736 $config_href = '/config/edit/environment.append-paths/';
737 return phutil_tag(
738 'a',
739 array(
740 'href' => $config_href,
742 'environment.append-paths');
745 private function buildStateView(PhabricatorRepository $repository) {
746 $viewer = $this->getViewer();
747 $is_new = $repository->isNewlyInitialized();
749 $view = id(new PHUIPropertyListView())
750 ->setViewer($viewer);
752 if (!$repository->isTracked()) {
753 if ($is_new) {
754 $active_icon = 'fa-ban';
755 $active_color = 'yellow';
756 $active_label = pht('Not Activated Yet');
757 $active_note = pht('Complete Setup and Activate Repository');
758 } else {
759 $active_icon = 'fa-times';
760 $active_color = 'red';
761 $active_label = pht('Not Active');
762 $active_note = pht('Repository Disabled');
764 } else if ($repository->isImporting()) {
765 $active_icon = 'fa-hourglass';
766 $active_color = 'yellow';
767 $active_label = pht('Importing...');
768 $active_note = null;
769 } else {
770 $active_icon = 'fa-check';
771 $active_color = 'green';
772 $active_label = pht('Repository Active');
773 $active_note = null;
776 $active_view = id(new PHUIStatusListView())
777 ->addItem(
778 id(new PHUIStatusItemView())
779 ->setIcon($active_icon, $active_color)
780 ->setTarget($active_label)
781 ->setNote($active_note));
783 if ($repository->isPublishingDisabled()) {
784 $publishing_icon = 'fa-times';
785 $publishing_color = 'red';
786 $publishing_label = pht('Not Publishing');
787 $publishing_note = pht('Publishing Disabled');
788 } else if (!$repository->isTracked()) {
789 $publishing_icon = 'fa-ban';
790 $publishing_color = 'yellow';
791 $publishing_label = pht('Not Publishing');
792 if ($is_new) {
793 $publishing_note = pht('Repository Not Active Yet');
794 } else {
795 $publishing_note = pht('Repository Inactive');
797 } else if ($repository->isImporting()) {
798 $publishing_icon = 'fa-ban';
799 $publishing_color = 'yellow';
800 $publishing_label = pht('Not Publishing');
801 $publishing_note = pht('Repository Importing');
802 } else {
803 $publishing_icon = 'fa-check';
804 $publishing_color = 'green';
805 $publishing_label = pht('Publishing Active');
806 $publishing_note = null;
809 $publishing_view = id(new PHUIStatusListView())
810 ->addItem(
811 id(new PHUIStatusItemView())
812 ->setIcon($publishing_icon, $publishing_color)
813 ->setTarget($publishing_label)
814 ->setNote($publishing_note));
816 $view->addProperty(pht('Active'), $active_view);
817 $view->addProperty(pht('Publishing'), $publishing_view);
819 return $this->newBox(pht('State'), $view);