public function receiveMessage(PhabricatorIRCMessage $message)
 {
     switch ($message->getCommand()) {
         case 'PRIVMSG':
             $reply_to = $message->getReplyTo();
             if (!$reply_to) {
                 break;
             }
             if (!$this->isChannelName($reply_to)) {
                 // Don't log private messages, although maybe we should for debugging?
                 break;
             }
             $logs = array(array('channel' => $reply_to, 'type' => 'mesg', 'epoch' => time(), 'author' => $message->getSenderNickname(), 'message' => $message->getMessageText()));
             $this->futures[] = $this->getConduit()->callMethod('chatlog.record', array('logs' => $logs));
             $prompts = array('/where is the (chat)?log\\?/i', '/where am i\\?/i', '/what year is (this|it)\\?/i');
             $tell = false;
             foreach ($prompts as $prompt) {
                 if (preg_match($prompt, $message->getMessageText())) {
                     $tell = true;
                     break;
                 }
             }
             if ($tell) {
                 $response = $this->getURI('/chatlog/channel/' . phutil_escape_uri($reply_to) . '/');
                 $this->write('PRIVMSG', "{$reply_to} :{$response}");
             }
             break;
     }
 }
 public function buildIconNavView(PhabricatorUser $user)
 {
     $viewer = $this->getViewer();
     $picture = $user->getProfileImageURI();
     $name = $user->getUsername();
     $nav = new AphrontSideNavFilterView();
     $nav->setIconNav(true);
     $nav->setBaseURI(new PhutilURI('/p/'));
     $nav->addIcon("{$name}/", $name, null, $picture);
     $class = 'PhabricatorCalendarApplication';
     if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
         $nav->addIcon("{$name}/calendar/", pht('Calendar'), 'fa-calendar');
     }
     $class = 'PhabricatorManiphestApplication';
     if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
         $phid = $user->getPHID();
         $view_uri = sprintf('/maniphest/?statuses=open()&assigned=%s#R', $phid);
         $nav->addIcon('maniphest', pht('Open Tasks'), 'fa-anchor', null, $view_uri);
     }
     $class = 'PhabricatorDifferentialApplication';
     if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
         $username = phutil_escape_uri($name);
         $view_uri = '/differential/?authors=' . $username;
         $nav->addIcon('differential', pht('Revisions'), 'fa-cog', null, $view_uri);
     }
     $class = 'PhabricatorAuditApplication';
     if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
         $username = phutil_escape_uri($name);
         $view_uri = '/audit/?authors=' . $username;
         $nav->addIcon('audit', pht('Commits'), 'fa-code', null, $view_uri);
     }
     return $nav;
 }
 protected function getPanelURI($path)
 {
     $user = $this->getProfileObject();
     $username = $user->getUsername();
     $username = phutil_escape_uri($username);
     return "/p/{$username}/panel/{$path}";
 }
 public function receiveMessage(PhabricatorBotMessage $message)
 {
     switch ($message->getCommand()) {
         case 'MESSAGE':
             $target = $message->getTarget();
             if (!$target->isPublic()) {
                 // Don't log private messages, although maybe we should for debugging?
                 break;
             }
             $target_name = $target->getName();
             $logs = array(array('channel' => $target_name, 'type' => 'mesg', 'epoch' => time(), 'author' => $message->getSender()->getName(), 'message' => $message->getBody(), 'serviceName' => $this->getServiceName(), 'serviceType' => $this->getServiceType()));
             $this->futures[] = $this->getConduit()->callMethod('chatlog.record', array('logs' => $logs));
             $prompts = array('/where is the (chat)?log\\?/i', '/where am i\\?/i', '/what year is (this|it)\\?/i');
             $tell = false;
             foreach ($prompts as $prompt) {
                 if (preg_match($prompt, $message->getBody())) {
                     $tell = true;
                     break;
                 }
             }
             if ($tell) {
                 $response = $this->getURI('/chatlog/channel/' . phutil_escape_uri($target_name) . '/');
                 $this->replyTo($message, $response);
             }
             break;
     }
 }
示例#5
0
 public function __toString()
 {
     $prefix = null;
     if ($this->protocol || $this->domain || $this->port) {
         $protocol = nonempty($this->protocol, 'http');
         $auth = '';
         if (strlen($this->user) && strlen($this->pass)) {
             $auth = phutil_escape_uri($this->user) . ':' . phutil_escape_uri($this->pass) . '@';
         } else {
             if (strlen($this->user)) {
                 $auth = phutil_escape_uri($this->user) . '@';
             }
         }
         $prefix = $protocol . '://' . $auth . $this->domain;
         if ($this->port) {
             $prefix .= ':' . $this->port;
         }
     }
     if ($this->query) {
         $query = '?' . http_build_query($this->query);
     } else {
         $query = null;
     }
     if (strlen($this->getFragment())) {
         $fragment = '#' . $this->getFragment();
     } else {
         $fragment = null;
     }
     return $prefix . $this->getPath() . $query . $fragment;
 }
 public function processRequest()
 {
     $viewer = $this->getRequest()->getUser();
     $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withUsernames(array($this->username))->needBadges(true)->needProfileImage(true)->needAvailability(true)->executeOne();
     if (!$user) {
         return new Aphront404Response();
     }
     $profile = $user->loadUserProfile();
     $username = phutil_escape_uri($user->getUserName());
     $picture = $user->getProfileImageURI();
     $header = id(new PHUIHeaderView())->setHeader($user->getFullName())->setSubheader($profile->getTitle())->setImage($picture);
     $actions = id(new PhabricatorActionListView())->setObject($user)->setUser($viewer);
     $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $user, PhabricatorPolicyCapability::CAN_EDIT);
     $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-pencil')->setName(pht('Edit Profile'))->setHref($this->getApplicationURI('editprofile/' . $user->getID() . '/'))->setDisabled(!$can_edit)->setWorkflow(!$can_edit));
     $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-picture-o')->setName(pht('Edit Profile Picture'))->setHref($this->getApplicationURI('picture/' . $user->getID() . '/'))->setDisabled(!$can_edit)->setWorkflow(!$can_edit));
     $class = 'PhabricatorConpherenceApplication';
     if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
         $href = id(new PhutilURI('/conpherence/new/'))->setQueryParam('participant', $user->getPHID());
         $can_send = $viewer->isLoggedIn();
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-comments')->setName(pht('Send Message'))->setWorkflow(true)->setDisabled(!$can_send)->setHref($href));
     }
     if ($viewer->getIsAdmin()) {
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-wrench')->setName(pht('Edit Settings'))->setDisabled(!$can_edit)->setWorkflow(!$can_edit)->setHref('/settings/' . $user->getID() . '/'));
         if ($user->getIsAdmin()) {
             $empower_icon = 'fa-arrow-circle-o-down';
             $empower_name = pht('Remove Administrator');
         } else {
             $empower_icon = 'fa-arrow-circle-o-up';
             $empower_name = pht('Make Administrator');
         }
         $actions->addAction(id(new PhabricatorActionView())->setIcon($empower_icon)->setName($empower_name)->setDisabled($user->getPHID() == $viewer->getPHID())->setWorkflow(true)->setHref($this->getApplicationURI('empower/' . $user->getID() . '/')));
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-tag')->setName(pht('Change Username'))->setWorkflow(true)->setHref($this->getApplicationURI('rename/' . $user->getID() . '/')));
         if ($user->getIsDisabled()) {
             $disable_icon = 'fa-check-circle-o';
             $disable_name = pht('Enable User');
         } else {
             $disable_icon = 'fa-ban';
             $disable_name = pht('Disable User');
         }
         $actions->addAction(id(new PhabricatorActionView())->setIcon($disable_icon)->setName($disable_name)->setDisabled($user->getPHID() == $viewer->getPHID())->setWorkflow(true)->setHref($this->getApplicationURI('disable/' . $user->getID() . '/')));
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-times')->setName(pht('Delete User'))->setDisabled($user->getPHID() == $viewer->getPHID())->setWorkflow(true)->setHref($this->getApplicationURI('delete/' . $user->getID() . '/')));
         $can_welcome = $user->canEstablishWebSessions();
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-envelope')->setName(pht('Send Welcome Email'))->setWorkflow(true)->setDisabled(!$can_welcome)->setHref($this->getApplicationURI('welcome/' . $user->getID() . '/')));
     }
     $properties = $this->buildPropertyView($user, $actions);
     $name = $user->getUsername();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($name);
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $feed = id(new PHUIObjectBoxView())->setHeaderText(pht('Recent Activity'))->appendChild($this->buildPeopleFeed($user, $viewer));
     $badges = $this->buildBadgesView($user);
     $nav = $this->buildIconNavView($user);
     $nav->selectFilter("{$name}/");
     $nav->appendChild($object_box);
     $nav->appendChild($badges);
     $nav->appendChild($feed);
     return $this->buildApplicationPage($nav, array('title' => $user->getUsername()));
 }
 public static function getJumpResponse(PhabricatorUser $viewer, $jump)
 {
     $jump = trim($jump);
     $help_href = PhabricatorEnv::getDocLink('Jump Nav User Guide');
     $patterns = array('/^help/i' => 'uri:' . $help_href, '/^a$/i' => 'uri:/audit/', '/^f$/i' => 'uri:/feed/', '/^d$/i' => 'uri:/differential/', '/^r$/i' => 'uri:/diffusion/', '/^t$/i' => 'uri:/maniphest/', '/^p$/i' => 'uri:/project/', '/^u$/i' => 'uri:/people/', '/^p\\s+(.+)$/i' => 'project', '/^u\\s+(\\S+)$/i' => 'user', '/^task:\\s*(.+)/i' => 'create-task', '/^(?:s|symbol)\\s+(\\S+)/i' => 'find-symbol', '/^r\\s+(.+)$/i' => 'find-repository');
     foreach ($patterns as $pattern => $effect) {
         $matches = null;
         if (preg_match($pattern, $jump, $matches)) {
             if (!strncmp($effect, 'uri:', 4)) {
                 return id(new AphrontRedirectResponse())->setURI(substr($effect, 4));
             } else {
                 switch ($effect) {
                     case 'user':
                         return id(new AphrontRedirectResponse())->setURI('/p/' . $matches[1] . '/');
                     case 'project':
                         $project = self::findCloselyNamedProject($matches[1]);
                         if ($project) {
                             return id(new AphrontRedirectResponse())->setURI('/project/view/' . $project->getID() . '/');
                         } else {
                             $jump = $matches[1];
                         }
                         break;
                     case 'find-symbol':
                         $context = '';
                         $symbol = $matches[1];
                         $parts = array();
                         if (preg_match('/(.*)(?:\\.|::|->)(.*)/', $symbol, $parts)) {
                             $context = '&context=' . phutil_escape_uri($parts[1]);
                             $symbol = $parts[2];
                         }
                         return id(new AphrontRedirectResponse())->setURI("/diffusion/symbol/{$symbol}/?jump=true{$context}");
                     case 'find-repository':
                         $name = $matches[1];
                         $repositories = id(new PhabricatorRepositoryQuery())->setViewer($viewer)->withNameContains($name)->execute();
                         if (count($repositories) == 1) {
                             // Just one match, jump to repository.
                             $uri = '/diffusion/' . head($repositories)->getCallsign() . '/';
                         } else {
                             // More than one match, jump to search.
                             $uri = urisprintf('/diffusion/?order=name&name=%s', $name);
                         }
                         return id(new AphrontRedirectResponse())->setURI($uri);
                     case 'create-task':
                         return id(new AphrontRedirectResponse())->setURI('/maniphest/task/create/?title=' . phutil_escape_uri($matches[1]));
                     default:
                         throw new Exception("Unknown jump effect '{$effect}'!");
                 }
             }
         }
     }
     // If none of the patterns matched, look for an object by name.
     $objects = id(new PhabricatorObjectQuery())->setViewer($viewer)->withNames(array($jump))->execute();
     if (count($objects) == 1) {
         $handle = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs(mpull($objects, 'getPHID'))->executeOne();
         return id(new AphrontRedirectResponse())->setURI($handle->getURI());
     }
     return null;
 }
 private function renderUserItems(PhutilEvent $event)
 {
     if (!$this->canUseApplication($event->getUser())) {
         return null;
     }
     $user = $event->getValue('object');
     $username = phutil_escape_uri($user->getUsername());
     $view_uri = '/audit/?authors=' . $username;
     return id(new PhabricatorActionView())->setIcon('fa-check-circle-o')->setName(pht('View Commits'))->setHref($view_uri);
 }
示例#9
0
 public function getViewURI($blogger_name = '')
 {
     // go for the pretty uri if we can
     if ($blogger_name) {
         $phame_title = PhabricatorSlug::normalize($this->getPhameTitle());
         $uri = phutil_escape_uri('/phame/posts/' . $blogger_name . '/' . $phame_title);
     } else {
         $uri = $this->getActionURI('view');
     }
     return $uri;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     // Redirect "/panel/XYZ/" to the viewer's personal settings panel. This
     // was the primary URI before global settings were introduced and allows
     // generation of viewer-agnostic URIs for email.
     $panel = $request->getURIData('panel');
     if ($panel) {
         $panel = phutil_escape_uri($panel);
         $username = $viewer->getUsername();
         $panel_uri = "/user/{$username}/page/{$panel}/";
         $panel_uri = $this->getApplicationURI($panel_uri);
         return id(new AphrontRedirectResponse())->setURI($panel_uri);
     }
     $username = $request->getURIData('username');
     $builtin = $request->getURIData('builtin');
     $key = $request->getURIData('pageKey');
     if ($builtin) {
         $this->builtinKey = $builtin;
         $preferences = id(new PhabricatorUserPreferencesQuery())->setViewer($viewer)->withBuiltinKeys(array($builtin))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$preferences) {
             $preferences = id(new PhabricatorUserPreferences())->attachUser(null)->setBuiltinKey($builtin);
         }
     } else {
         $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withUsernames(array($username))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$user) {
             return new Aphront404Response();
         }
         $preferences = PhabricatorUserPreferences::loadUserPreferences($user);
         $this->user = $user;
     }
     if (!$preferences) {
         return new Aphront404Response();
     }
     PhabricatorPolicyFilter::requireCapability($viewer, $preferences, PhabricatorPolicyCapability::CAN_EDIT);
     $this->preferences = $preferences;
     $panels = $this->buildPanels($preferences);
     $nav = $this->renderSideNav($panels);
     $key = $nav->selectFilter($key, head($panels)->getPanelKey());
     $panel = $panels[$key]->setController($this)->setNavigation($nav);
     $response = $panel->processRequest($request);
     if ($response instanceof AphrontResponse || $response instanceof AphrontResponseProducerInterface) {
         return $response;
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($panel->getPanelName());
     $title = $panel->getPanelName();
     $view = id(new PHUITwoColumnView())->setNavigation($nav)->setMainColumn($response);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public static function jumpPostResponse($jump)
 {
     $jump = trim($jump);
     $help_href = PhabricatorEnv::getDocLink('article/Jump_Nav_User_Guide.html');
     $patterns = array('/^help/i' => 'uri:' . $help_href, '/^a$/i' => 'uri:/audit/', '/^f$/i' => 'uri:/feed/', '/^d$/i' => 'uri:/differential/', '/^r$/i' => 'uri:/diffusion/', '/^t$/i' => 'uri:/maniphest/', '/^p$/i' => 'uri:/project/', '/^u$/i' => 'uri:/people/', '/^r([A-Z]+)$/' => 'repository', '/^r([A-Z]+)(\\S+)$/' => 'commit', '/^d(\\d+)$/i' => 'revision', '/^t(\\d+)$/i' => 'task', '/^p\\s+(.+)$/i' => 'project', '/^u\\s+(\\S+)$/i' => 'user', '/^task:\\s*(.+)/i' => 'create-task', '/^(?:s|symbol)\\s+(\\S+)/i' => 'find-symbol');
     foreach ($patterns as $pattern => $effect) {
         $matches = null;
         if (preg_match($pattern, $jump, $matches)) {
             if (!strncmp($effect, 'uri:', 4)) {
                 return id(new AphrontRedirectResponse())->setURI(substr($effect, 4));
             } else {
                 switch ($effect) {
                     case 'repository':
                         return id(new AphrontRedirectResponse())->setURI('/diffusion/' . $matches[1] . '/');
                     case 'commit':
                         return id(new AphrontRedirectResponse())->setURI('/' . $matches[0]);
                     case 'revision':
                         return id(new AphrontRedirectResponse())->setURI('/D' . $matches[1]);
                     case 'task':
                         return id(new AphrontRedirectResponse())->setURI('/T' . $matches[1]);
                     case 'user':
                         return id(new AphrontRedirectResponse())->setURI('/p/' . $matches[1] . '/');
                     case 'project':
                         $project = self::findCloselyNamedProject($matches[1]);
                         if ($project) {
                             return id(new AphrontRedirectResponse())->setURI('/project/view/' . $project->getID() . '/');
                         } else {
                             $jump = $matches[1];
                         }
                         break;
                     case 'find-symbol':
                         $context = '';
                         $symbol = $matches[1];
                         $parts = array();
                         if (preg_match('/(.*)(?:\\.|::|->)(.*)/', $symbol, $parts)) {
                             $context = '&context=' . phutil_escape_uri($parts[1]);
                             $symbol = $parts[2];
                         }
                         return id(new AphrontRedirectResponse())->setURI("/diffusion/symbol/{$symbol}/?jump=true{$context}");
                     case 'create-task':
                         return id(new AphrontRedirectResponse())->setURI('/maniphest/task/create/?title=' . phutil_escape_uri($matches[1]));
                     default:
                         throw new Exception("Unknown jump effect '{$effect}'!");
                 }
             }
         }
     }
     return null;
 }
 public function processRequest()
 {
     $viewer = $this->getRequest()->getUser();
     $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withUsernames(array($this->username))->needProfileImage(true)->executeOne();
     if (!$user) {
         return new Aphront404Response();
     }
     require_celerity_resource('phabricator-profile-css');
     $profile = $user->loadUserProfile();
     $username = phutil_escape_uri($user->getUserName());
     $picture = $user->loadProfileImageURI();
     $header = id(new PHUIHeaderView())->setHeader($user->getFullName())->setSubheader($profile->getTitle())->setImage($picture);
     $actions = id(new PhabricatorActionListView())->setObject($user)->setObjectURI($this->getRequest()->getRequestURI())->setUser($viewer);
     $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $user, PhabricatorPolicyCapability::CAN_EDIT);
     $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-pencil')->setName(pht('Edit Profile'))->setHref($this->getApplicationURI('editprofile/' . $user->getID() . '/'))->setDisabled(!$can_edit)->setWorkflow(!$can_edit));
     $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-picture-o')->setName(pht('Edit Profile Picture'))->setHref($this->getApplicationURI('picture/' . $user->getID() . '/'))->setDisabled(!$can_edit)->setWorkflow(!$can_edit));
     if ($viewer->getIsAdmin()) {
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-wrench')->setName(pht('Edit Settings'))->setDisabled(!$can_edit)->setWorkflow(!$can_edit)->setHref('/settings/' . $user->getID() . '/'));
         if ($user->getIsAdmin()) {
             $empower_icon = 'fa-arrow-circle-o-down';
             $empower_name = pht('Remove Administrator');
         } else {
             $empower_icon = 'fa-arrow-circle-o-up';
             $empower_name = pht('Make Administrator');
         }
         $actions->addAction(id(new PhabricatorActionView())->setIcon($empower_icon)->setName($empower_name)->setDisabled($user->getPHID() == $viewer->getPHID())->setWorkflow(true)->setHref($this->getApplicationURI('empower/' . $user->getID() . '/')));
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-tag')->setName(pht('Change Username'))->setWorkflow(true)->setHref($this->getApplicationURI('rename/' . $user->getID() . '/')));
         if ($user->getIsDisabled()) {
             $disable_icon = 'fa-check-circle-o';
             $disable_name = pht('Enable User');
         } else {
             $disable_icon = 'fa-ban';
             $disable_name = pht('Disable User');
         }
         $actions->addAction(id(new PhabricatorActionView())->setIcon($disable_icon)->setName($disable_name)->setDisabled($user->getPHID() == $viewer->getPHID())->setWorkflow(true)->setHref($this->getApplicationURI('disable/' . $user->getID() . '/')));
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-times')->setName(pht('Delete User'))->setDisabled($user->getPHID() == $viewer->getPHID())->setWorkflow(true)->setHref($this->getApplicationURI('delete/' . $user->getID() . '/')));
         $actions->addAction(id(new PhabricatorActionView())->setIcon('fa-envelope')->setName(pht('Send Welcome Email'))->setWorkflow(true)->setHref($this->getApplicationURI('welcome/' . $user->getID() . '/')));
     }
     $properties = $this->buildPropertyView($user, $actions);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($user->getUsername());
     $crumbs->setActionList($actions);
     $feed = $this->renderUserFeed($user);
     $calendar = $this->renderUserCalendar($user);
     $activity = phutil_tag('div', array('class' => 'profile-activity-view grouped'), array($calendar, $feed));
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     return $this->buildApplicationPage(array($crumbs, $object_box, $activity), array('title' => $user->getUsername()));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $nav = $this->buildNavAndSelectFilter();
     if ($request->isFormPost()) {
         // If the list filter is POST'ed, redirect to GET so the page can be
         // bookmarked.
         $uri = $request->getRequestURI();
         $phid = head($request->getArr('set_phid'));
         $user = id(new PhabricatorUser())->loadOneWhere('phid = %s', $phid);
         $uri = $request->getRequestURI();
         if ($user) {
             $username = phutil_escape_uri($user->getUsername());
             $uri = '/audit/view/' . $this->filter . '/' . $username . '/';
         } else {
             if ($phid) {
                 $uri = $request->getRequestURI();
                 $uri = $uri->alter('phid', $phid);
             }
         }
         return id(new AphrontRedirectResponse())->setURI($uri);
     }
     $this->filterStatus = $request->getStr('status', 'all');
     $handle = $this->loadHandle();
     $nav->appendChild($this->buildListFilters($handle));
     $title = null;
     $message = null;
     if (!$handle) {
         switch ($this->filter) {
             case 'project':
                 $title = 'Choose A Project';
                 $message = 'Choose a project to view audits for.';
                 break;
             case 'package':
             case 'packagecommits':
                 $title = 'Choose a Package';
                 $message = 'Choose a package to view audits for.';
                 break;
         }
     }
     if (!$message) {
         $nav->appendChild($this->buildViews($handle));
     } else {
         $panel = id(new AphrontErrorView())->setSeverity(AphrontErrorView::SEVERITY_NODATA)->setTitle($title)->appendChild($message);
         $nav->appendChild($panel);
     }
     return $this->buildStandardPageResponse($nav, array('title' => 'Audits'));
 }
示例#14
0
 protected final function buildSideNav($selected, $has_change_view)
 {
     $nav = new AphrontSideNavView();
     $navs = array('history' => 'History View', 'browse' => 'Browse View', 'change' => 'Change View');
     if (!$has_change_view) {
         unset($navs['change']);
     }
     $drequest = $this->getDiffusionRequest();
     foreach ($navs as $action => $name) {
         $href = $drequest->generateURI(array('action' => $action));
         $nav->addNavItem(phutil_render_tag('a', array('href' => $href, 'class' => $action == $selected ? 'aphront-side-nav-selected' : null), $name));
     }
     // TODO: URI encoding might need to be sorted out for this link.
     $nav->addNavItem(phutil_render_tag('a', array('href' => '/owners/view/search/' . '?repository=' . phutil_escape_uri($drequest->getCallsign()) . '&path=' . phutil_escape_uri('/' . $drequest->getPath())), 'Search Owners'));
     return $nav;
 }
 public function processRequest()
 {
     $table = new PhabricatorChatLogEvent();
     $channels = queryfx_all($table->establishConnection('r'), 'SELECT DISTINCT channel FROM %T', $table->getTableName());
     $rows = array();
     foreach ($channels as $channel) {
         $name = $channel['channel'];
         $rows[] = array(phutil_render_tag('a', array('href' => '/chatlog/channel/' . phutil_escape_uri($name) . '/'), phutil_escape_html($name)));
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array('Channel'));
     $table->setColumnClasses(array('pri wide'));
     $panel = new AphrontPanelView();
     $panel->appendChild($table);
     return $this->buildStandardPageResponse($panel, array('title' => 'Channel List'));
 }
示例#16
0
 public static function getSlugURI($slug, $type = 'document')
 {
     static $types = array('document' => '/w/', 'history' => '/phriction/history/');
     if (empty($types[$type])) {
         throw new Exception("Unknown URI type '{$type}'!");
     }
     $prefix = $types[$type];
     if ($slug == '/') {
         return $prefix;
     } else {
         // NOTE: The effect here is to escape non-latin characters, since modern
         // browsers deal with escaped UTF8 characters in a reasonable way (showing
         // the user a readable URI) but older programs may not.
         $slug = phutil_escape_uri($slug);
         return $prefix . $slug;
     }
 }
示例#17
0
/**
 * uri_sprintf() callback for URI encoding.
 * @group markup
 */
function xsprintf_uri($userdata, &$pattern, &$pos, &$value, &$length)
{
    $type = $pattern[$pos];
    switch ($type) {
        case 's':
            $value = phutil_escape_uri($value);
            $type = 's';
            break;
        case 'p':
            $value = phutil_escape_uri_path_component($value);
            $type = 's';
            break;
        case 'R':
            $type = 's';
            break;
    }
    $pattern[$pos] = $type;
}
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     if ($request->isFormPost()) {
         $files = $request->getArr('file');
         if (count($files) > 1) {
             return id(new AphrontRedirectResponse())->setURI('/file/?author=' . phutil_escape_uri($user->getUserName()));
         } else {
             return id(new AphrontRedirectResponse())->setURI('/file/info/' . end($files) . '/');
         }
     }
     $panel_id = celerity_generate_unique_node_id();
     $form = new AphrontFormView();
     $form->setAction('/file/upload/');
     $form->setUser($request->getUser());
     $form->setEncType('multipart/form-data')->appendChild(id(new AphrontFormDragAndDropUploadControl())->setLabel('Files')->setName('file')->setError(true)->setDragAndDropTarget($panel_id)->setActivatedClass('aphront-panel-view-drag-and-drop'))->appendChild(id(new AphrontFormSubmitControl())->setValue('Done here!'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Upload File');
     $panel->appendChild($form);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     $panel->setID($panel_id);
     return $this->buildStandardPageResponse(array($panel), array('title' => 'Upload File'));
 }
 public static function getProxyImageURI($uri)
 {
     return '/file/proxy/?uri=' . phutil_escape_uri($uri);
 }
示例#20
0
 /**
  * Generate a Diffusion URI from a parameter map. Applies the correct encoding
  * and formatting to the URI. Parameters are:
  *
  *   - `action` One of `history`, `browse`, `change`, `lastmodified`,
  *     `branch`, `tags`, `branches`,  or `revision-ref`. The action specified
  *      by the URI.
  *   - `repository` Repository.
  *   - `callsign` Repository callsign.
  *   - `branch` Optional if action is not `branch`, branch name.
  *   - `path` Optional, path to file.
  *   - `commit` Optional, commit identifier.
  *   - `line` Optional, line range.
  *   - `lint` Optional, lint code.
  *   - `params` Optional, query parameters.
  *
  * The function generates the specified URI and returns it.
  *
  * @param   map         See documentation.
  * @return  PhutilURI   Generated URI.
  * @task uri
  */
 public static function generateDiffusionURI(array $params)
 {
     $action = idx($params, 'action');
     $repository = idx($params, 'repository');
     if ($repository) {
         $callsign = $repository->getCallsign();
     } else {
         $callsign = idx($params, 'callsign');
     }
     $path = idx($params, 'path');
     $branch = idx($params, 'branch');
     $commit = idx($params, 'commit');
     $line = idx($params, 'line');
     if (strlen($callsign)) {
         $callsign = phutil_escape_uri_path_component($callsign) . '/';
     }
     if (strlen($branch)) {
         $branch = phutil_escape_uri_path_component($branch) . '/';
     }
     if (strlen($path)) {
         $path = ltrim($path, '/');
         $path = str_replace(array(';', '$'), array(';;', '$$'), $path);
         $path = phutil_escape_uri($path);
     }
     $path = "{$branch}{$path}";
     if (strlen($commit)) {
         $commit = str_replace('$', '$$', $commit);
         $commit = ';' . phutil_escape_uri($commit);
     }
     if (strlen($line)) {
         $line = '$' . phutil_escape_uri($line);
     }
     $req_callsign = false;
     $req_branch = false;
     $req_commit = false;
     switch ($action) {
         case 'history':
         case 'browse':
         case 'change':
         case 'lastmodified':
         case 'tags':
         case 'branches':
         case 'lint':
         case 'refs':
             $req_callsign = true;
             break;
         case 'branch':
             $req_callsign = true;
             $req_branch = true;
             break;
         case 'commit':
             $req_callsign = true;
             $req_commit = true;
             break;
     }
     if ($req_callsign && !strlen($callsign)) {
         throw new Exception(pht("Diffusion URI action '%s' requires callsign!", $action));
     }
     if ($req_commit && !strlen($commit)) {
         throw new Exception(pht("Diffusion URI action '%s' requires commit!", $action));
     }
     switch ($action) {
         case 'change':
         case 'history':
         case 'browse':
         case 'lastmodified':
         case 'tags':
         case 'branches':
         case 'lint':
         case 'pathtree':
         case 'refs':
             $uri = "/diffusion/{$callsign}{$action}/{$path}{$commit}{$line}";
             break;
         case 'branch':
             if (strlen($path)) {
                 $uri = "/diffusion/{$callsign}repository/{$path}";
             } else {
                 $uri = "/diffusion/{$callsign}";
             }
             break;
         case 'external':
             $commit = ltrim($commit, ';');
             $uri = "/diffusion/external/{$commit}/";
             break;
         case 'rendering-ref':
             // This isn't a real URI per se, it's passed as a query parameter to
             // the ajax changeset stuff but then we parse it back out as though
             // it came from a URI.
             $uri = rawurldecode("{$path}{$commit}");
             break;
         case 'commit':
             $commit = ltrim($commit, ';');
             $callsign = rtrim($callsign, '/');
             $uri = "/r{$callsign}{$commit}";
             break;
         default:
             throw new Exception(pht("Unknown Diffusion URI action '%s'!", $action));
     }
     if ($action == 'rendering-ref') {
         return $uri;
     }
     $uri = new PhutilURI($uri);
     if (isset($params['lint'])) {
         $params['params'] = idx($params, 'params', array()) + array('lint' => $params['lint']);
     }
     if (idx($params, 'params')) {
         $uri->setQueryParams($params['params']);
     }
     return $uri;
 }
示例#21
0
 public function loadEditorLink($path, $line, $callsign)
 {
     $editor = $this->loadPreferences()->getPreference(PhabricatorUserPreferences::PREFERENCE_EDITOR);
     if (is_array($path)) {
         $multiedit = $this->loadPreferences()->getPreference(PhabricatorUserPreferences::PREFERENCE_MULTIEDIT);
         switch ($multiedit) {
             case '':
                 $path = implode(' ', $path);
                 break;
             case 'disable':
                 return null;
         }
     }
     if (!strlen($editor)) {
         return null;
     }
     $uri = strtr($editor, array('%%' => '%', '%f' => phutil_escape_uri($path), '%l' => phutil_escape_uri($line), '%r' => phutil_escape_uri($callsign)));
     // The resulting URI must have an allowed protocol. Otherwise, we'll return
     // a link to an error page explaining the misconfiguration.
     $ok = PhabricatorHelpEditorProtocolController::hasAllowedProtocol($uri);
     if (!$ok) {
         return '/help/editorprotocol/';
     }
     return (string) $uri;
 }
示例#22
0
 public function loadEditorLink($path, $line, PhabricatorRepository $repository = null)
 {
     $editor = $this->getUserSetting(PhabricatorEditorSetting::SETTINGKEY);
     if (is_array($path)) {
         $multi_key = PhabricatorEditorMultipleSetting::SETTINGKEY;
         $multiedit = $this->getUserSetting($multi_key);
         switch ($multiedit) {
             case PhabricatorEditorMultipleSetting::VALUE_SPACES:
                 $path = implode(' ', $path);
                 break;
             case PhabricatorEditorMultipleSetting::VALUE_SINGLE:
             default:
                 return null;
         }
     }
     if (!strlen($editor)) {
         return null;
     }
     if ($repository) {
         $callsign = $repository->getCallsign();
     } else {
         $callsign = null;
     }
     $uri = strtr($editor, array('%%' => '%', '%f' => phutil_escape_uri($path), '%l' => phutil_escape_uri($line), '%r' => phutil_escape_uri($callsign)));
     // The resulting URI must have an allowed protocol. Otherwise, we'll return
     // a link to an error page explaining the misconfiguration.
     $ok = PhabricatorHelpEditorProtocolController::hasAllowedProtocol($uri);
     if (!$ok) {
         return '/help/editorprotocol/';
     }
     return (string) $uri;
 }
 public function processRequest()
 {
     $drequest = $this->getDiffusionRequest();
     $request = $this->getRequest();
     $user = $request->getUser();
     $callsign = $drequest->getRepository()->getCallsign();
     $content = array();
     $content[] = $this->buildCrumbs(array('commit' => true));
     $repository = $drequest->getRepository();
     $commit = $drequest->loadCommit();
     if (!$commit) {
         // TODO: Make more user-friendly.
         throw new Exception('This commit has not parsed yet.');
     }
     $commit_data = $drequest->loadCommitData();
     $commit->attachCommitData($commit_data);
     $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
     if ($is_foreign) {
         $subpath = $commit_data->getCommitDetail('svn-subpath');
         $error_panel = new AphrontErrorView();
         $error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
         $error_panel->setTitle('Commit Not Tracked');
         $error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING);
         $error_panel->appendChild("This Diffusion repository is configured to track only one " . "subdirectory of the entire Subversion repository, and this commit " . "didn't affect the tracked subdirectory ('" . phutil_escape_html($subpath) . "'), so no information is available.");
         $content[] = $error_panel;
     } else {
         $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
         require_celerity_resource('diffusion-commit-view-css');
         require_celerity_resource('phabricator-remarkup-css');
         $parent_query = DiffusionCommitParentsQuery::newFromDiffusionRequest($drequest);
         $headsup_panel = new AphrontHeadsupView();
         $headsup_panel->setHeader('Commit Detail');
         $headsup_panel->setActionList($this->renderHeadsupActionList($commit));
         $headsup_panel->setProperties($this->getCommitProperties($commit, $commit_data, $parent_query->loadParents()));
         $headsup_panel->appendChild('<div class="diffusion-commit-message phabricator-remarkup">' . $engine->markupText($commit_data->getCommitMessage()) . '</div>');
         $content[] = $headsup_panel;
     }
     $query = new PhabricatorAuditQuery();
     $query->withCommitPHIDs(array($commit->getPHID()));
     $audit_requests = $query->execute();
     $this->auditAuthorityPHIDs = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
     $content[] = $this->buildAuditTable($commit, $audit_requests);
     $content[] = $this->buildComments($commit);
     $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest($drequest);
     $changes = $change_query->loadChanges();
     $content[] = $this->buildMergesTable($commit);
     $original_changes_count = count($changes);
     if ($request->getStr('show_all') !== 'true' && $original_changes_count > self::CHANGES_LIMIT) {
         $changes = array_slice($changes, 0, self::CHANGES_LIMIT);
     }
     $change_table = new DiffusionCommitChangeTableView();
     $change_table->setDiffusionRequest($drequest);
     $change_table->setPathChanges($changes);
     $count = count($changes);
     $bad_commit = null;
     if ($count == 0) {
         $bad_commit = queryfx_one(id(new PhabricatorRepository())->establishConnection('r'), 'SELECT * FROM %T WHERE fullCommitName = %s', PhabricatorRepository::TABLE_BADCOMMIT, 'r' . $callsign . $commit->getCommitIdentifier());
     }
     if ($bad_commit) {
         $error_panel = new AphrontErrorView();
         $error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
         $error_panel->setTitle('Bad Commit');
         $error_panel->appendChild(phutil_escape_html($bad_commit['description']));
         $content[] = $error_panel;
     } else {
         if ($is_foreign) {
             // Don't render anything else.
         } else {
             if (!count($changes)) {
                 $no_changes = new AphrontErrorView();
                 $no_changes->setWidth(AphrontErrorView::WIDTH_WIDE);
                 $no_changes->setSeverity(AphrontErrorView::SEVERITY_WARNING);
                 $no_changes->setTitle('Not Yet Parsed');
                 // TODO: This can also happen with weird SVN changes that don't do
                 // anything (or only alter properties?), although the real no-changes case
                 // is extremely rare and might be impossible to produce organically. We
                 // should probably write some kind of "Nothing Happened!" change into the
                 // DB once we parse these changes so we can distinguish between
                 // "not parsed yet" and "no changes".
                 $no_changes->appendChild("This commit hasn't been fully parsed yet (or doesn't affect any " . "paths).");
                 $content[] = $no_changes;
             } else {
                 $change_panel = new AphrontPanelView();
                 $change_panel->setHeader("Changes (" . number_format($count) . ")");
                 if ($count !== $original_changes_count) {
                     $show_all_button = phutil_render_tag('a', array('class' => 'button green', 'href' => '?show_all=true'), phutil_escape_html('Show All Changes'));
                     $warning_view = id(new AphrontErrorView())->setSeverity(AphrontErrorView::SEVERITY_WARNING)->setTitle(sprintf("Showing only the first %d changes out of %s!", self::CHANGES_LIMIT, number_format($original_changes_count)));
                     $change_panel->appendChild($warning_view);
                     $change_panel->addButton($show_all_button);
                 }
                 $change_panel->appendChild($change_table);
                 $content[] = $change_panel;
                 $changesets = DiffusionPathChange::convertToDifferentialChangesets($changes);
                 $vcs = $repository->getVersionControlSystem();
                 switch ($vcs) {
                     case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
                         $vcs_supports_directory_changes = true;
                         break;
                     case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
                     case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
                         $vcs_supports_directory_changes = false;
                         break;
                     default:
                         throw new Exception("Unknown VCS.");
                 }
                 $references = array();
                 foreach ($changesets as $key => $changeset) {
                     $file_type = $changeset->getFileType();
                     if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
                         if (!$vcs_supports_directory_changes) {
                             unset($changesets[$key]);
                             continue;
                         }
                     }
                     $references[$key] = $drequest->generateURI(array('action' => 'rendering-ref', 'path' => $changeset->getFilename()));
                 }
                 // TODO: Some parts of the views still rely on properties of the
                 // DifferentialChangeset. Make the objects ephemeral to make sure we don't
                 // accidentally save them, and then set their ID to the appropriate ID for
                 // this application (the path IDs).
                 $pquery = new DiffusionPathIDQuery(mpull($changesets, 'getFilename'));
                 $path_ids = $pquery->loadPathIDs();
                 foreach ($changesets as $changeset) {
                     $changeset->makeEphemeral();
                     $changeset->setID($path_ids[$changeset->getFilename()]);
                 }
                 $change_list = new DifferentialChangesetListView();
                 $change_list->setChangesets($changesets);
                 $change_list->setRenderingReferences($references);
                 $change_list->setRenderURI('/diffusion/' . $callsign . '/diff/');
                 $change_list->setRepository($repository);
                 $change_list->setUser($user);
                 $change_list->setStandaloneURI('/diffusion/' . $callsign . '/diff/');
                 $change_list->setRawFileURIs(null, '/diffusion/' . $callsign . '/diff/?view=r');
                 $change_list->setInlineCommentControllerURI('/diffusion/inline/' . phutil_escape_uri($commit->getPHID()) . '/');
                 // TODO: This is pretty awkward, unify the CSS between Diffusion and
                 // Differential better.
                 require_celerity_resource('differential-core-view-css');
                 $change_list = '<div class="differential-primary-pane">' . $change_list->render() . '</div>';
                 $content[] = $change_list;
             }
         }
     }
     $content[] = $this->buildAddCommentView($commit, $audit_requests);
     return $this->buildStandardPageResponse($content, array('title' => 'r' . $callsign . $commit->getCommitIdentifier()));
 }
 private function buildDefined(PHUIPropertyListView $view, DivinerLiveSymbol $symbol)
 {
     $atom = $symbol->getAtom();
     $defined = $atom->getFile() . ':' . $atom->getLine();
     $link = $symbol->getBook()->getConfig('uri.source');
     if ($link) {
         $link = strtr($link, array('%%' => '%', '%f' => phutil_escape_uri($atom->getFile()), '%l' => phutil_escape_uri($atom->getLine())));
         $defined = phutil_tag('a', array('href' => $link, 'target' => '_blank'), $defined);
     }
     $view->addProperty(pht('Defined'), $defined);
 }
 public function generateURI(array $params)
 {
     $req_branch = false;
     $req_commit = false;
     $action = idx($params, 'action');
     switch ($action) {
         case 'history':
         case 'browse':
         case 'change':
         case 'lastmodified':
         case 'tags':
         case 'branches':
         case 'lint':
         case 'pathtree':
         case 'refs':
             break;
         case 'branch':
             // NOTE: This does not actually require a branch, and won't have one
             // in Subversion. Possibly this should be more clear.
             break;
         case 'commit':
         case 'rendering-ref':
             $req_commit = true;
             break;
         default:
             throw new Exception(pht('Action "%s" is not a valid repository URI action.', $action));
     }
     $path = idx($params, 'path');
     $branch = idx($params, 'branch');
     $commit = idx($params, 'commit');
     $line = idx($params, 'line');
     if ($req_commit && !strlen($commit)) {
         throw new Exception(pht('Diffusion URI action "%s" requires commit!', $action));
     }
     if ($req_branch && !strlen($branch)) {
         throw new Exception(pht('Diffusion URI action "%s" requires branch!', $action));
     }
     if ($action === 'commit') {
         return $this->getCommitURI($commit);
     }
     $identifier = $this->getID();
     $callsign = $this->getCallsign();
     if ($callsign !== null) {
         $identifier = $callsign;
     }
     if (strlen($identifier)) {
         $identifier = phutil_escape_uri_path_component($identifier);
     }
     if (strlen($path)) {
         $path = ltrim($path, '/');
         $path = str_replace(array(';', '$'), array(';;', '$$'), $path);
         $path = phutil_escape_uri($path);
     }
     if (strlen($branch)) {
         $branch = phutil_escape_uri_path_component($branch);
         $path = "{$branch}/{$path}";
     }
     if (strlen($commit)) {
         $commit = str_replace('$', '$$', $commit);
         $commit = ';' . phutil_escape_uri($commit);
     }
     if (strlen($line)) {
         $line = '$' . phutil_escape_uri($line);
     }
     switch ($action) {
         case 'change':
         case 'history':
         case 'browse':
         case 'lastmodified':
         case 'tags':
         case 'branches':
         case 'lint':
         case 'pathtree':
         case 'refs':
             $uri = "/diffusion/{$identifier}/{$action}/{$path}{$commit}{$line}";
             break;
         case 'branch':
             if (strlen($path)) {
                 $uri = "/diffusion/{$identifier}/repository/{$path}";
             } else {
                 $uri = "/diffusion/{$identifier}/";
             }
             break;
         case 'external':
             $commit = ltrim($commit, ';');
             $uri = "/diffusion/external/{$commit}/";
             break;
         case 'rendering-ref':
             // This isn't a real URI per se, it's passed as a query parameter to
             // the ajax changeset stuff but then we parse it back out as though
             // it came from a URI.
             $uri = rawurldecode("{$path}{$commit}");
             break;
     }
     if ($action == 'rendering-ref') {
         return $uri;
     }
     $uri = new PhutilURI($uri);
     if (isset($params['lint'])) {
         $params['params'] = idx($params, 'params', array()) + array('lint' => $params['lint']);
     }
     if (idx($params, 'params')) {
         $uri->setQueryParams($params['params']);
     }
     return $uri;
 }
 public function pullRefs(array $refs)
 {
     $id_map = mpull($refs, 'getObjectID', 'getObjectKey');
     $viewer = $this->getViewer();
     $provider = PhabricatorJIRAAuthProvider::getJIRAProvider();
     if (!$provider) {
         return;
     }
     $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs(array($viewer->getPHID()))->withAccountTypes(array($provider->getProviderType()))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     if (!$accounts) {
         return $this->didFailOnMissingLink();
     }
     // TODO: When we support multiple JIRA instances, we need to disambiguate
     // issues (perhaps with additional configuration) or cast a wide net
     // (by querying all instances). For now, just query the one instance.
     $account = head($accounts);
     $futures = array();
     foreach ($id_map as $key => $id) {
         $futures[$key] = $provider->newJIRAFuture($account, 'rest/api/2/issue/' . phutil_escape_uri($id), 'GET');
     }
     $results = array();
     $failed = array();
     foreach (new FutureIterator($futures) as $key => $future) {
         try {
             $results[$key] = $future->resolveJSON();
         } catch (Exception $ex) {
             if ($ex instanceof HTTPFutureResponseStatus && $ex->getStatusCode() == 404) {
                 // This indicates that the object has been deleted (or never existed,
                 // or isn't visible to the current user) but it's a successful sync of
                 // an object which isn't visible.
             } else {
                 // This is something else, so consider it a synchronization failure.
                 phlog($ex);
                 $failed[$key] = $ex;
             }
         }
     }
     foreach ($refs as $ref) {
         $ref->setAttribute('name', pht('JIRA %s', $ref->getObjectID()));
         $did_fail = idx($failed, $ref->getObjectKey());
         if ($did_fail) {
             $ref->setSyncFailed(true);
             continue;
         }
         $result = idx($results, $ref->getObjectKey());
         if (!$result) {
             continue;
         }
         $fields = idx($result, 'fields', array());
         $ref->setIsVisible(true);
         $ref->setAttribute('fullname', pht('JIRA %s %s', $result['key'], idx($fields, 'summary')));
         $ref->setAttribute('title', idx($fields, 'summary'));
         $ref->setAttribute('description', idx($result, 'description'));
         $obj = $ref->getExternalObject();
         if ($obj->getID()) {
             continue;
         }
         $this->fillObjectFromData($obj, $result);
         $this->saveExternalObject($ref, $obj);
     }
 }
示例#27
0
 public function getRequestURI()
 {
     $get = $_GET;
     unset($get['__path__']);
     $path = phutil_escape_uri($this->getPath());
     return id(new PhutilURI($path))->setQueryParams($get);
 }
示例#28
0
 public function getViewURI()
 {
     if (!$this->getPHID()) {
         throw new Exception("You must save a file before you can generate a view URI.");
     }
     $name = phutil_escape_uri($this->getName());
     $path = '/file/data/' . $this->getSecretKey() . '/' . $this->getPHID() . '/' . $name;
     return PhabricatorEnv::getCDNURI($path);
 }
 protected function processDiffusionRequest(AphrontRequest $request)
 {
     $user = $request->getUser();
     // This controller doesn't use blob/path stuff, just pass the dictionary
     // in directly instead of using the AphrontRequest parsing mechanism.
     $data = $request->getURIMap();
     $data['user'] = $user;
     $drequest = DiffusionRequest::newFromDictionary($data);
     $this->diffusionRequest = $drequest;
     if ($request->getStr('diff')) {
         return $this->buildRawDiffResponse($drequest);
     }
     $repository = $drequest->getRepository();
     $callsign = $repository->getCallsign();
     $content = array();
     $commit = id(new DiffusionCommitQuery())->setViewer($request->getUser())->withRepository($repository)->withIdentifiers(array($drequest->getCommit()))->needCommitData(true)->needAuditRequests(true)->executeOne();
     $crumbs = $this->buildCrumbs(array('commit' => true));
     if (!$commit) {
         $exists = $this->callConduitWithDiffusionRequest('diffusion.existsquery', array('commit' => $drequest->getCommit()));
         if (!$exists) {
             return new Aphront404Response();
         }
         $error = id(new PHUIInfoView())->setTitle(pht('Commit Still Parsing'))->appendChild(pht('Failed to load the commit because the commit has not been ' . 'parsed yet.'));
         return $this->buildApplicationPage(array($crumbs, $error), array('title' => pht('Commit Still Parsing')));
     }
     $audit_requests = $commit->getAudits();
     $this->auditAuthorityPHIDs = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
     $commit_data = $commit->getCommitData();
     $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
     if ($is_foreign) {
         $subpath = $commit_data->getCommitDetail('svn-subpath');
         $error_panel = new PHUIInfoView();
         $error_panel->setTitle(pht('Commit Not Tracked'));
         $error_panel->setSeverity(PHUIInfoView::SEVERITY_WARNING);
         $error_panel->appendChild(pht("This Diffusion repository is configured to track only one " . "subdirectory of the entire Subversion repository, and this commit " . "didn't affect the tracked subdirectory ('%s'), so no " . "information is available.", $subpath));
         $content[] = $error_panel;
     } else {
         $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
         $engine->setConfig('viewer', $user);
         require_celerity_resource('phabricator-remarkup-css');
         $parents = $this->callConduitWithDiffusionRequest('diffusion.commitparentsquery', array('commit' => $drequest->getCommit()));
         if ($parents) {
             $parents = id(new DiffusionCommitQuery())->setViewer($user)->withRepository($repository)->withIdentifiers($parents)->execute();
         }
         $headsup_view = id(new PHUIHeaderView())->setHeader(nonempty($commit->getSummary(), pht('Commit Detail')));
         $headsup_actions = $this->renderHeadsupActionList($commit, $repository);
         $commit_properties = $this->loadCommitProperties($commit, $commit_data, $parents, $audit_requests);
         $property_list = id(new PHUIPropertyListView())->setHasKeyboardShortcuts(true)->setUser($user)->setObject($commit);
         foreach ($commit_properties as $key => $value) {
             $property_list->addProperty($key, $value);
         }
         $message = $commit_data->getCommitMessage();
         $revision = $commit->getCommitIdentifier();
         $message = $this->linkBugtraq($message);
         $message = $engine->markupText($message);
         $property_list->invokeWillRenderEvent();
         $property_list->setActionList($headsup_actions);
         $detail_list = new PHUIPropertyListView();
         $detail_list->addSectionHeader(pht('Description'), PHUIPropertyListView::ICON_SUMMARY);
         $detail_list->addTextContent(phutil_tag('div', array('class' => 'diffusion-commit-message phabricator-remarkup'), $message));
         $headsup_view->setTall(true);
         $object_box = id(new PHUIObjectBoxView())->setHeader($headsup_view)->addPropertyList($property_list)->addPropertyList($detail_list);
         $content[] = $object_box;
     }
     $content[] = $this->buildComments($commit);
     $hard_limit = 1000;
     if ($commit->isImported()) {
         $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest($drequest);
         $change_query->setLimit($hard_limit + 1);
         $changes = $change_query->loadChanges();
     } else {
         $changes = array();
     }
     $was_limited = count($changes) > $hard_limit;
     if ($was_limited) {
         $changes = array_slice($changes, 0, $hard_limit);
     }
     $content[] = $this->buildMergesTable($commit);
     $highlighted_audits = $commit->getAuthorityAudits($user, $this->auditAuthorityPHIDs);
     $count = count($changes);
     $bad_commit = null;
     if ($count == 0) {
         $bad_commit = queryfx_one(id(new PhabricatorRepository())->establishConnection('r'), 'SELECT * FROM %T WHERE fullCommitName = %s', PhabricatorRepository::TABLE_BADCOMMIT, 'r' . $callsign . $commit->getCommitIdentifier());
     }
     $show_changesets = false;
     if ($bad_commit) {
         $content[] = $this->renderStatusMessage(pht('Bad Commit'), $bad_commit['description']);
     } else {
         if ($is_foreign) {
             // Don't render anything else.
         } else {
             if (!$commit->isImported()) {
                 $content[] = $this->renderStatusMessage(pht('Still Importing...'), pht('This commit is still importing. Changes will be visible once ' . 'the import finishes.'));
             } else {
                 if (!count($changes)) {
                     $content[] = $this->renderStatusMessage(pht('Empty Commit'), pht('This commit is empty and does not affect any paths.'));
                 } else {
                     if ($was_limited) {
                         $content[] = $this->renderStatusMessage(pht('Enormous Commit'), pht('This commit is enormous, and affects more than %d files. ' . 'Changes are not shown.', $hard_limit));
                     } else {
                         $show_changesets = true;
                         // The user has clicked "Show All Changes", and we should show all the
                         // changes inline even if there are more than the soft limit.
                         $show_all_details = $request->getBool('show_all');
                         $change_panel = new PHUIObjectBoxView();
                         $header = new PHUIHeaderView();
                         $header->setHeader(pht('Changes (%s)', new PhutilNumber($count)));
                         $change_panel->setID('toc');
                         if ($count > self::CHANGES_LIMIT && !$show_all_details) {
                             $icon = id(new PHUIIconView())->setIconFont('fa-files-o');
                             $button = id(new PHUIButtonView())->setText(pht('Show All Changes'))->setHref('?show_all=true')->setTag('a')->setIcon($icon);
                             $warning_view = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setTitle(pht('Very Large Commit'))->appendChild(pht('This commit is very large. Load each file individually.'));
                             $change_panel->setInfoView($warning_view);
                             $header->addActionLink($button);
                         }
                         $changesets = DiffusionPathChange::convertToDifferentialChangesets($user, $changes);
                         // TODO: This table and panel shouldn't really be separate, but we need
                         // to clean up the "Load All Files" interaction first.
                         $change_table = $this->buildTableOfContents($changesets);
                         $change_panel->setTable($change_table);
                         $change_panel->setHeader($header);
                         $content[] = $change_panel;
                         $vcs = $repository->getVersionControlSystem();
                         switch ($vcs) {
                             case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
                                 $vcs_supports_directory_changes = true;
                                 break;
                             case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
                             case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
                                 $vcs_supports_directory_changes = false;
                                 break;
                             default:
                                 throw new Exception(pht('Unknown VCS.'));
                         }
                         $references = array();
                         foreach ($changesets as $key => $changeset) {
                             $file_type = $changeset->getFileType();
                             if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
                                 if (!$vcs_supports_directory_changes) {
                                     unset($changesets[$key]);
                                     continue;
                                 }
                             }
                             $references[$key] = $drequest->generateURI(array('action' => 'rendering-ref', 'path' => $changeset->getFilename()));
                         }
                         // TODO: Some parts of the views still rely on properties of the
                         // DifferentialChangeset. Make the objects ephemeral to make sure we don't
                         // accidentally save them, and then set their ID to the appropriate ID for
                         // this application (the path IDs).
                         $path_ids = array_flip(mpull($changes, 'getPath'));
                         foreach ($changesets as $changeset) {
                             $changeset->makeEphemeral();
                             $changeset->setID($path_ids[$changeset->getFilename()]);
                         }
                         if ($count <= self::CHANGES_LIMIT || $show_all_details) {
                             $visible_changesets = $changesets;
                         } else {
                             $visible_changesets = array();
                             $inlines = PhabricatorAuditInlineComment::loadDraftAndPublishedComments($user, $commit->getPHID());
                             $path_ids = mpull($inlines, null, 'getPathID');
                             foreach ($changesets as $key => $changeset) {
                                 if (array_key_exists($changeset->getID(), $path_ids)) {
                                     $visible_changesets[$key] = $changeset;
                                 }
                             }
                         }
                         $change_list_title = DiffusionView::nameCommit($repository, $commit->getCommitIdentifier());
                         $change_list = new DifferentialChangesetListView();
                         $change_list->setTitle($change_list_title);
                         $change_list->setChangesets($changesets);
                         $change_list->setVisibleChangesets($visible_changesets);
                         $change_list->setRenderingReferences($references);
                         $change_list->setRenderURI('/diffusion/' . $callsign . '/diff/');
                         $change_list->setRepository($repository);
                         $change_list->setUser($user);
                         // TODO: Try to setBranch() to something reasonable here?
                         $change_list->setStandaloneURI('/diffusion/' . $callsign . '/diff/');
                         $change_list->setRawFileURIs(null, '/diffusion/' . $callsign . '/diff/?view=r');
                         $change_list->setInlineCommentControllerURI('/diffusion/inline/edit/' . phutil_escape_uri($commit->getPHID()) . '/');
                         $content[] = $change_list->render();
                     }
                 }
             }
         }
     }
     $content[] = $this->renderAddCommentPanel($commit, $audit_requests);
     $commit_id = 'r' . $callsign . $commit->getCommitIdentifier();
     $short_name = DiffusionView::nameCommit($repository, $commit->getCommitIdentifier());
     $prefs = $user->loadPreferences();
     $pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
     $pref_collapse = PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED;
     $show_filetree = $prefs->getPreference($pref_filetree);
     $collapsed = $prefs->getPreference($pref_collapse);
     if ($show_changesets && $show_filetree) {
         $nav = id(new DifferentialChangesetFileTreeSideNavBuilder())->setTitle($short_name)->setBaseURI(new PhutilURI('/' . $commit_id))->build($changesets)->setCrumbs($crumbs)->setCollapsed((bool) $collapsed)->appendChild($content);
         $content = $nav;
     } else {
         $content = array($crumbs, $content);
     }
     return $this->buildApplicationPage($content, array('title' => $commit_id, 'pageObjects' => array($commit->getPHID())));
 }
 public function execute(HarbormasterBuild $build, HarbormasterBuildTarget $build_target)
 {
     $viewer = PhabricatorUser::getOmnipotentUser();
     $buildable = $build->getBuildable();
     $object = $buildable->getBuildableObject();
     $object_phid = $object->getPHID();
     if (!$object instanceof HarbormasterCircleCIBuildableInterface) {
         throw new Exception(pht('Object ("%s") does not implement interface "%s". Only objects ' . 'which implement this interface can be built with CircleCI.', $object_phid, 'HarbormasterCircleCIBuildableInterface'));
     }
     $github_uri = $object->getCircleCIGitHubRepositoryURI();
     $build_type = $object->getCircleCIBuildIdentifierType();
     $build_identifier = $object->getCircleCIBuildIdentifier();
     $path = self::getGitHubPath($github_uri);
     if ($path === null) {
         throw new Exception(pht('Object ("%s") claims "%s" is a GitHub repository URI, but the ' . 'domain does not appear to be GitHub.', $object_phid, $github_uri));
     }
     $path_parts = trim($path, '/');
     $path_parts = explode('/', $path_parts);
     if (count($path_parts) < 2) {
         throw new Exception(pht('Object ("%s") claims "%s" is a GitHub repository URI, but the ' . 'path ("%s") does not have enough components (expected at least ' . 'two).', $object_phid, $github_uri, $path));
     }
     list($github_namespace, $github_name) = $path_parts;
     $github_name = preg_replace('(\\.git$)', '', $github_name);
     $credential_phid = $this->getSetting('token');
     $api_token = id(new PassphraseCredentialQuery())->setViewer($viewer)->withPHIDs(array($credential_phid))->needSecrets(true)->executeOne();
     if (!$api_token) {
         throw new Exception(pht('Unable to load API token ("%s")!', $credential_phid));
     }
     // When we pass "revision", the branch is ignored (and does not even need
     // to exist), and only shows up in the UI. Use a cute string which will
     // certainly never break anything or cause any kind of problem.
     $ship = "🚢";
     $branch = "{$ship}Harbormaster";
     $token = $api_token->getSecret()->openEnvelope();
     $parts = array('https://circleci.com/api/v1/project', phutil_escape_uri($github_namespace), phutil_escape_uri($github_name) . "?circle-token={$token}");
     $uri = implode('/', $parts);
     $data_structure = array();
     switch ($build_type) {
         case 'tag':
             $data_structure['tag'] = $build_identifier;
             break;
         case 'revision':
             $data_structure['revision'] = $build_identifier;
             break;
         default:
             throw new Exception(pht('Unknown CircleCI build type "%s". Expected "%s" or "%s".', $build_type, 'tag', 'revision'));
     }
     $data_structure['build_parameters'] = array('HARBORMASTER_BUILD_TARGET_PHID' => $build_target->getPHID());
     $json_data = phutil_json_encode($data_structure);
     $future = id(new HTTPSFuture($uri, $json_data))->setMethod('POST')->addHeader('Content-Type', 'application/json')->addHeader('Accept', 'application/json')->setTimeout(60);
     $this->resolveFutures($build, $build_target, array($future));
     $this->logHTTPResponse($build, $build_target, $future, pht('CircleCI'));
     list($status, $body) = $future->resolve();
     if ($status->isError()) {
         throw new HarbormasterBuildFailureException();
     }
     $response = phutil_json_decode($body);
     $build_uri = idx($response, 'build_url');
     if (!$build_uri) {
         throw new Exception(pht('CircleCI did not return a "%s"!', 'build_url'));
     }
     $target_phid = $build_target->getPHID();
     // Write an artifact to create a link to the external build in CircleCI.
     $api_method = 'harbormaster.createartifact';
     $api_params = array('buildTargetPHID' => $target_phid, 'artifactType' => HarbormasterURIArtifact::ARTIFACTCONST, 'artifactKey' => 'circleci.uri', 'artifactData' => array('uri' => $build_uri, 'name' => pht('View in CircleCI'), 'ui.external' => true));
     id(new ConduitCall($api_method, $api_params))->setUser($viewer)->execute();
 }