public function renderModuleStatus(AphrontRequest $request) { $viewer = $request->getViewer(); $collectors = PhabricatorGarbageCollector::getAllCollectors(); $collectors = msort($collectors, 'getCollectorConstant'); $rows = array(); $rowc = array(); foreach ($collectors as $key => $collector) { $class = null; if ($collector->hasAutomaticPolicy()) { $policy_view = phutil_tag('em', array(), pht('Automatic')); } else { $policy = $collector->getRetentionPolicy(); if ($policy === null) { $policy_view = pht('Indefinite'); } else { $days = ceil($policy / phutil_units('1 day in seconds')); $policy_view = pht('%s Day(s)', new PhutilNumber($days)); } $default = $collector->getDefaultRetentionPolicy(); if ($policy !== $default) { $class = 'highlighted'; $policy_view = phutil_tag('strong', array(), $policy_view); } } $rowc[] = $class; $rows[] = array($collector->getCollectorConstant(), $collector->getCollectorName(), $policy_view); } $table = id(new AphrontTableView($rows))->setRowClasses($rowc)->setHeaders(array(pht('Constant'), pht('Name'), pht('Retention Policy')))->setColumnClasses(array(null, 'pri wide', null)); $header = id(new PHUIHeaderView())->setHeader(pht('Garbage Collectors'))->setSubheader(pht('Collectors with custom policies are highlighted. Use ' . '%s to change retention policies.', phutil_tag('tt', array(), 'bin/garbage set-policy'))); return id(new PHUIObjectBoxView())->setHeader($header)->setTable($table); }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); // If the user already has a full session, just kick them out of here. $has_partial_session = $viewer->hasSession() && $viewer->getSession()->getIsPartial(); if (!$has_partial_session) { return id(new AphrontRedirectResponse())->setURI('/'); } $engine = new PhabricatorAuthSessionEngine(); // If this cookie is set, the user is headed into a high security area // after login (normally because of a password reset) so if they are // able to pass the checkpoint we just want to put their account directly // into high security mode, rather than prompt them again for the same // set of credentials. $jump_into_hisec = $request->getCookie(PhabricatorCookies::COOKIE_HISEC); try { $token = $engine->requireHighSecuritySession($viewer, $request, '/logout/', $jump_into_hisec); } catch (PhabricatorAuthHighSecurityRequiredException $ex) { $form = id(new PhabricatorAuthSessionEngine())->renderHighSecurityForm($ex->getFactors(), $ex->getFactorValidationResults(), $viewer, $request); return $this->newDialog()->setTitle(pht('Provide Multi-Factor Credentials'))->setShortTitle(pht('Multi-Factor Login'))->setWidth(AphrontDialogView::WIDTH_FORM)->addHiddenInput(AphrontRequest::TYPE_HISEC, true)->appendParagraph(pht('Welcome, %s. To complete the login process, provide your ' . 'multi-factor credentials.', phutil_tag('strong', array(), $viewer->getUsername())))->appendChild($form->buildLayoutView())->setSubmitURI($request->getPath())->addCancelButton($ex->getCancelURI())->addSubmitButton(pht('Continue')); } // Upgrade the partial session to a full session. $engine->upgradePartialSession($viewer); // TODO: It might be nice to add options like "bind this session to my IP" // here, even for accounts without multi-factor auth attached to them. $next = PhabricatorCookies::getNextURICookie($request); $request->clearCookie(PhabricatorCookies::COOKIE_NEXTURI); $request->clearCookie(PhabricatorCookies::COOKIE_HISEC); if (!PhabricatorEnv::isValidLocalURIForLink($next)) { $next = '/'; } return id(new AphrontRedirectResponse())->setURI($next); }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $configs = id(new PhabricatorAuthProviderConfigQuery())->setViewer($viewer)->execute(); $list = new PHUIObjectItemListView(); $can_manage = $this->hasApplicationCapability(AuthManageProvidersCapability::CAPABILITY); foreach ($configs as $config) { $item = new PHUIObjectItemView(); $id = $config->getID(); $edit_uri = $this->getApplicationURI('config/edit/' . $id . '/'); $enable_uri = $this->getApplicationURI('config/enable/' . $id . '/'); $disable_uri = $this->getApplicationURI('config/disable/' . $id . '/'); $provider = $config->getProvider(); if ($provider) { $name = $provider->getProviderName(); } else { $name = $config->getProviderType() . ' (' . $config->getProviderClass() . ')'; } $item->setHeader($name); if ($provider) { $item->setHref($edit_uri); } else { $item->addAttribute(pht('Provider Implementation Missing!')); } $domain = null; if ($provider) { $domain = $provider->getProviderDomain(); if ($domain !== 'self') { $item->addAttribute($domain); } } if ($config->getShouldAllowRegistration()) { $item->addAttribute(pht('Allows Registration')); } else { $item->addAttribute(pht('Does Not Allow Registration')); } if ($config->getIsEnabled()) { $item->setStatusIcon('fa-check-circle green'); $item->addAction(id(new PHUIListItemView())->setIcon('fa-times')->setHref($disable_uri)->setDisabled(!$can_manage)->addSigil('workflow')); } else { $item->setStatusIcon('fa-ban red'); $item->addIcon('fa-ban grey', pht('Disabled')); $item->addAction(id(new PHUIListItemView())->setIcon('fa-plus')->setHref($enable_uri)->setDisabled(!$can_manage)->addSigil('workflow')); } $list->addItem($item); } $list->setNoDataString(pht('%s You have not added authentication providers yet. Use "%s" to add ' . 'a provider, which will let users register new Phabricator accounts ' . 'and log in.', phutil_tag('strong', array(), pht('No Providers Configured:')), phutil_tag('a', array('href' => $this->getApplicationURI('config/new/')), pht('Add Authentication Provider')))); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Auth Providers')); $crumbs->setBorder(true); $guidance_context = new PhabricatorAuthProvidersGuidanceContext(); $guidance = id(new PhabricatorGuidanceEngine())->setViewer($viewer)->setGuidanceContext($guidance_context)->newInfoView(); $button = id(new PHUIButtonView())->setTag('a')->setColor(PHUIButtonView::SIMPLE)->setHref($this->getApplicationURI('config/new/'))->setIcon('fa-plus')->setDisabled(!$can_manage)->setText(pht('Add Provider')); $list->setFlush(true); $list = id(new PHUIObjectBoxView())->setHeaderText(pht('Providers'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->appendChild($list); $title = pht('Auth Providers'); $header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon('fa-key')->addActionLink($button); $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($guidance, $list)); return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view); }
protected function processDiffusionRequest(AphrontRequest $request) { $viewer = $request->getUser(); $this->requireApplicationCapability(DiffusionCreateRepositoriesCapability::CAPABILITY); if ($request->isFormPost()) { if ($request->getStr('type')) { switch ($request->getStr('type')) { case 'create': $uri = $this->getApplicationURI('create/'); break; case 'import': default: $uri = $this->getApplicationURI('import/'); break; } return id(new AphrontRedirectResponse())->setURI($uri); } } $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Repository Hosting'); $doc_link = phutil_tag('a', array('href' => $doc_href, 'target' => '_blank'), pht('Diffusion User Guide: Repository Hosting')); $form = id(new AphrontFormView())->setUser($viewer)->appendChild(id(new AphrontFormRadioButtonControl())->setName('type')->addButton('create', pht('Create a New Hosted Repository'), array(pht('Create a new, empty repository which Phabricator will host. ' . 'For instructions on configuring repository hosting, see %s.', $doc_link)))->addButton('import', pht('Import an Existing External Repository'), pht("Import a repository hosted somewhere else, like GitHub, " . "Bitbucket, or your organization's existing servers. " . "Phabricator will read changes from the repository but will " . "not host or manage it. The authoritative master version of " . "the repository will stay where it is now.")))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Continue'))->addCancelButton($this->getApplicationURI())); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('New Repository')); $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Create or Import Repository'))->setForm($form); return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => pht('New Repository'))); }
public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->withIDs(array($this->id))->needMembers(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne(); if (!$project) { return new Aphront404Response(); } $member_phids = $project->getMemberPHIDs(); $remove_phid = $request->getStr('phid'); if (!in_array($remove_phid, $member_phids)) { return new Aphront404Response(); } $members_uri = $this->getApplicationURI('members/' . $project->getID() . '/'); if ($request->isFormPost()) { $member_spec = array(); $member_spec['-'] = array($remove_phid => $remove_phid); $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; $xactions = array(); $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $type_member)->setNewValue($member_spec); $editor = id(new PhabricatorProjectTransactionEditor($project))->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->applyTransactions($project, $xactions); return id(new AphrontRedirectResponse())->setURI($members_uri); } $handle = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs(array($remove_phid))->executeOne(); $dialog = id(new AphrontDialogView())->setUser($viewer)->setTitle(pht('Really Remove Member?'))->appendParagraph(pht('Really remove %s from the project %s?', phutil_tag('strong', array(), $handle->getName()), phutil_tag('strong', array(), $project->getName())))->addCancelButton($members_uri)->addSubmitButton(pht('Remove Project Member')); return id(new AphrontDialogResponse())->setDialog($dialog); }
/** * Makes sure a given custom blog uri is properly configured in DNS * to point at this Phabricator instance. If there is an error in * the configuration, return a string describing the error and how * to fix it. If there is no error, return an empty string. * * @return string */ public function validateCustomDomain($custom_domain) { $example_domain = 'blog.example.com'; $label = pht('Invalid'); // note this "uri" should be pretty busted given the desired input // so just use it to test if there's a protocol specified $uri = new PhutilURI($custom_domain); if ($uri->getProtocol()) { return array($label, pht('The custom domain should not include a protocol. Just provide ' . 'the bare domain name (for example, "%s").', $example_domain)); } if ($uri->getPort()) { return array($label, pht('The custom domain should not include a port number. Just provide ' . 'the bare domain name (for example, "%s").', $example_domain)); } if (strpos($custom_domain, '/') !== false) { return array($label, pht('The custom domain should not specify a path (hosting a Phame ' . 'blog at a path is currently not supported). Instead, just provide ' . 'the bare domain name (for example, "%s").', $example_domain)); } if (strpos($custom_domain, '.') === false) { return array($label, pht('The custom domain should contain at least one dot (.) because ' . 'some browsers fail to set cookies on domains without a dot. ' . 'Instead, use a normal looking domain name like "%s".', $example_domain)); } if (!PhabricatorEnv::getEnvConfig('policy.allow-public')) { $href = PhabricatorEnv::getProductionURI('/config/edit/policy.allow-public/'); return array(pht('Fix Configuration'), pht('For custom domains to work, this Phabricator instance must be ' . 'configured to allow the public access policy. Configure this ' . 'setting %s, or ask an administrator to configure this setting. ' . 'The domain can be specified later once this setting has been ' . 'changed.', phutil_tag('a', array('href' => $href), pht('here')))); } return null; }
public function buildNav() { $user = $this->getRequest()->getUser(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI('/')); $applications = id(new PhabricatorApplicationQuery())->setViewer($user)->withInstalled(true)->withUnlisted(false)->withLaunchable(true)->execute(); $pinned = $user->loadPreferences()->getPinnedApplications($applications, $user); // Force "Applications" to appear at the bottom. $meta_app = 'PhabricatorApplicationsApplication'; $pinned = array_fuse($pinned); unset($pinned[$meta_app]); $pinned[$meta_app] = $meta_app; $applications[$meta_app] = PhabricatorApplication::getByClass($meta_app); $tiles = array(); $home_app = new PhabricatorHomeApplication(); $tiles[] = id(new PhabricatorApplicationLaunchView())->setApplication($home_app)->setApplicationStatus($home_app->loadStatus($user))->addClass('phabricator-application-launch-phone-only')->setUser($user); foreach ($pinned as $pinned_application) { if (empty($applications[$pinned_application])) { continue; } $application = $applications[$pinned_application]; $tile = id(new PhabricatorApplicationLaunchView())->setApplication($application)->setApplicationStatus($application->loadStatus($user))->setUser($user); $tiles[] = $tile; } $nav->addCustomBlock(phutil_tag('div', array('class' => 'application-tile-group'), $tiles)); $nav->addFilter('', pht('Customize Applications...'), '/settings/panel/home/'); $nav->addClass('phabricator-side-menu-home'); $nav->selectFilter(null); return $nav; }
public function processRequest() { $request = $this->getRequest(); $admin = $request->getUser(); $user = id(new PhabricatorPeopleQuery())->setViewer($admin)->withIDs(array($this->id))->executeOne(); if (!$user) { return new Aphront404Response(); } $profile_uri = '/p/' . $user->getUsername() . '/'; id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession($admin, $request, $profile_uri); if ($user->getPHID() == $admin->getPHID()) { return $this->newDialog()->setTitle(pht('Your Way is Blocked'))->appendParagraph(pht('After a time, your efforts fail. You can not adjust your own ' . 'status as an administrator.'))->addCancelButton($profile_uri, pht('Accept Fate')); } if ($request->isFormPost()) { id(new PhabricatorUserEditor())->setActor($admin)->makeAdminUser($user, !$user->getIsAdmin()); return id(new AphrontRedirectResponse())->setURI($profile_uri); } if ($user->getIsAdmin()) { $title = pht('Remove as Administrator?'); $short = pht('Remove Administrator'); $body = pht('Remove %s as an administrator? They will no longer be able to ' . 'perform administrative functions on this Phabricator install.', phutil_tag('strong', array(), $user->getUsername())); $submit = pht('Remove Administrator'); } else { $title = pht('Make Administrator?'); $short = pht('Make Administrator'); $body = pht('Empower %s as an administrator? They will be able to create users, ' . 'approve users, make and remove administrators, delete accounts, and ' . 'perform other administrative functions on this Phabricator install.', phutil_tag('strong', array(), $user->getUsername())); $submit = pht('Make Administrator'); } return $this->newDialog()->setTitle($title)->setShortTitle($short)->appendParagraph($body)->addCancelButton($profile_uri)->addSubmitButton($submit); }
public function markupText($text, $children) { $matches = array(); preg_match($this->getRegEx(), $text, $matches); if (idx($matches, 'showword')) { $word = $matches['showword']; $show = true; } else { $word = $matches['hideword']; $show = false; } $class_suffix = phutil_utf8_strtolower($word); // This is the "(IMPORTANT)" or "NOTE:" part. $word_part = rtrim(substr($text, 0, strlen($matches[0]))); // This is the actual text. $text_part = substr($text, strlen($matches[0])); $text_part = $this->applyRules(rtrim($text_part)); $text_mode = $this->getEngine()->isTextMode(); if ($text_mode) { return $word_part . ' ' . $text_part; } if ($show) { $content = array(phutil_tag('span', array('class' => 'remarkup-note-word'), $word_part), ' ', $text_part); } else { $content = $text_part; } return phutil_tag('div', array('class' => 'remarkup-' . $class_suffix), $content); }
private function buildPropertyListView(DrydockResource $resource, PhabricatorActionListView $actions) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView())->setActionList($actions); $status = $resource->getStatus(); $status = DrydockResourceStatus::getNameForStatus($status); $view->addProperty(pht('Status'), $status); $until = $resource->getUntil(); if ($until) { $until_display = phabricator_datetime($until, $viewer); } else { $until_display = phutil_tag('em', array(), pht('Never')); } $view->addProperty(pht('Expires'), $until_display); $view->addProperty(pht('Resource Type'), $resource->getType()); $view->addProperty(pht('Blueprint'), $viewer->renderHandle($resource->getBlueprintPHID())); $attributes = $resource->getAttributes(); if ($attributes) { $view->addSectionHeader(pht('Attributes'), 'fa-list-ul'); foreach ($attributes as $key => $value) { $view->addProperty($key, $value); } } return $view; }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $id = $request->getURIData('id'); $client = id(new PhabricatorOAuthServerClientQuery())->setViewer($viewer)->withIDs(array($id))->executeOne(); if (!$client) { return new Aphront404Response(); } $view_uri = $client->getViewURI(); // Look for an existing authorization. $authorization = id(new PhabricatorOAuthClientAuthorizationQuery())->setViewer($viewer)->withUserPHIDs(array($viewer->getPHID()))->withClientPHIDs(array($client->getPHID()))->executeOne(); if ($authorization) { return $this->newDialog()->setTitle(pht('Already Authorized'))->appendParagraph(pht('You have already authorized this application to access your ' . 'account.'))->addCancelButton($view_uri, pht('Close')); } if ($request->isFormPost()) { $server = id(new PhabricatorOAuthServer())->setUser($viewer)->setClient($client); $scope = array(); $authorization = $server->authorizeClient($scope); $id = $authorization->getID(); $panel_uri = '/settings/panel/oauthorizations/?id=' . $id; return id(new AphrontRedirectResponse())->setURI($panel_uri); } // TODO: It would be nice to put scope options in this dialog, maybe? return $this->newDialog()->setTitle(pht('Authorize Application?'))->appendParagraph(pht('This will create an authorization, permitting %s to access ' . 'your account.', phutil_tag('strong', array(), $client->getName())))->addCancelButton($view_uri)->addSubmitButton(pht('Authorize Application')); }
public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $keys = $request->getStr('keys'); try { $keys = phutil_json_decode($keys); } catch (PhutilJSONParserException $ex) { return new Aphront400Response(); } // There have been at least two users asking for a keyboard shortcut to // close the dialog, so be explicit that escape works since it isn't // terribly discoverable. $keys[] = array('keys' => array('esc'), 'description' => pht('Close any dialog, including this one.')); $stroke_map = array('left' => "←", 'right' => "→", 'up' => "↑", 'down' => "↓", 'return' => "⏎", 'tab' => "⇥", 'delete' => "⌫"); $rows = array(); foreach ($keys as $shortcut) { $keystrokes = array(); foreach ($shortcut['keys'] as $stroke) { $stroke = idx($stroke_map, $stroke, $stroke); $keystrokes[] = phutil_tag('kbd', array(), $stroke); } $keystrokes = phutil_implode_html(' or ', $keystrokes); $rows[] = phutil_tag('tr', array(), array(phutil_tag('th', array(), $keystrokes), phutil_tag('td', array(), $shortcut['description']))); } $table = phutil_tag('table', array('class' => 'keyboard-shortcut-help'), $rows); return $this->newDialog()->setTitle(pht('Keyboard Shortcuts'))->appendChild($table)->addCancelButton('#', pht('Close')); }
/** * @param string $date */ public function execute($tasks, $recently_closed, $date) { $result = array(); $leftover = array(); foreach ($tasks as $task) { $phids = $task->getProjectPHIDs(); if ($phids) { foreach ($phids as $project_phid) { $result[$project_phid][] = $task; } } else { $leftover[] = $task; } } $result_closed = array(); $leftover_closed = array(); foreach ($recently_closed as $task) { $phids = $task->getProjectPHIDs(); if ($phids) { foreach ($phids as $project_phid) { $result_closed[$project_phid][] = $task; } } else { $leftover_closed[] = $task; } } $base_link = '/maniphest/?allProjects='; $leftover_name = phutil_tag('em', array(), pht('(No Project)')); $col_header = pht('Project'); $header = pht('Open Tasks by Project and Priority (%s)', $date); return array($leftover, $base_link, $leftover_name, $col_header, $header, $result_closed, $leftover_closed, $result); }
public static final function linkRevision($id) { if (!$id) { return null; } return phutil_tag('a', array('href' => "/D{$id}"), "D{$id}"); }
protected function processDiffusionRequest(AphrontRequest $request) { $limit = 500; $offset = $request->getInt('offset', 0); $drequest = $this->getDiffusionRequest(); $branch = $drequest->loadBranch(); $messages = $this->loadLintMessages($branch, $limit, $offset); $is_dir = substr('/' . $drequest->getPath(), -1) == '/'; $authors = $this->loadViewerHandles(ipull($messages, 'authorPHID')); $rows = array(); foreach ($messages as $message) { $path = phutil_tag('a', array('href' => $drequest->generateURI(array('action' => 'lint', 'path' => $message['path']))), substr($message['path'], strlen($drequest->getPath()) + 1)); $line = phutil_tag('a', array('href' => $drequest->generateURI(array('action' => 'browse', 'path' => $message['path'], 'line' => $message['line'], 'commit' => $branch->getLintCommit()))), $message['line']); $author = $message['authorPHID']; if ($author && $authors[$author]) { $author = $authors[$author]->renderLink(); } $rows[] = array($path, $line, $author, ArcanistLintSeverity::getStringForSeverity($message['severity']), $message['name'], $message['description']); } $table = id(new AphrontTableView($rows))->setHeaders(array(pht('Path'), pht('Line'), pht('Author'), pht('Severity'), pht('Name'), pht('Description')))->setColumnClasses(array('', 'n'))->setColumnVisibility(array($is_dir)); $content = array(); $pager = id(new AphrontPagerView())->setPageSize($limit)->setOffset($offset)->setHasMorePages(count($messages) >= $limit)->setURI($request->getRequestURI(), 'offset'); $content[] = id(new PHUIObjectBoxView())->setHeaderText(pht('Lint Details'))->appendChild($table); $crumbs = $this->buildCrumbs(array('branch' => true, 'path' => true, 'view' => 'lint')); return $this->buildApplicationPage(array($crumbs, $content, $pager), array('title' => array(pht('Lint'), $drequest->getRepository()->getCallsign()))); }
public function markupText($text, $children) { $text = $this->applyRules($text); if ($this->getEngine()->isTextMode()) { $children = phutil_split_lines($children, true); foreach ($children as $key => $child) { if (strlen(trim($child))) { $children[$key] = '> ' . $child; } else { $children[$key] = '>' . $child; } } $children = implode('', $children); return $text . "\n\n" . $children; } if ($this->getEngine()->isHTMLMailMode()) { $block_attributes = array('style' => 'border-left: 3px solid #8C98B8; color: #6B748C; font-style: italic; margin: 4px 0 12px 0; padding: 8px 12px; background-color: #F8F9FC;'); $head_attributes = array('style' => 'font-style: normal; padding-bottom: 4px;'); $reply_attributes = array('style' => 'margin: 0; padding: 0; border: 0; color: rgb(107, 116, 140);'); } else { $block_attributes = array('class' => 'remarkup-reply-block'); $head_attributes = array('class' => 'remarkup-reply-head'); $reply_attributes = array('class' => 'remarkup-reply-body'); } return phutil_tag('blockquote', $block_attributes, array("\n", phutil_tag('div', $head_attributes, $text), "\n", phutil_tag('div', $reply_attributes, $children), "\n")); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $query = id(new PhabricatorNotificationQuery())->setViewer($user)->withUserPHIDs(array($user->getPHID()))->setLimit(15); $stories = $query->execute(); $clear_ui_class = 'phabricator-notification-clear-all'; $clear_uri = id(new PhutilURI('/notification/clear/')); if ($stories) { $builder = new PhabricatorNotificationBuilder($stories); $notifications_view = $builder->buildView(); $content = $notifications_view->render(); $clear_uri->setQueryParam('chronoKey', head($stories)->getChronologicalKey()); } else { $content = phutil_tag_div('phabricator-notification no-notifications', pht('You have no notifications.')); $clear_ui_class .= ' disabled'; } $clear_ui = javelin_tag('a', array('sigil' => 'workflow', 'href' => (string) $clear_uri, 'class' => $clear_ui_class), pht('Mark All Read')); $notifications_link = phutil_tag('a', array('href' => '/notification/'), pht('Notifications')); if (PhabricatorEnv::getEnvConfig('notification.enabled')) { $connection_status = new PhabricatorNotificationStatusView(); } else { $connection_status = phutil_tag('a', array('href' => PhabricatorEnv::getDoclink('Notifications User Guide: Setup and Configuration')), pht('Notification Server not enabled.')); } $connection_ui = phutil_tag('div', array('class' => 'phabricator-notification-footer'), $connection_status); $header = phutil_tag('div', array('class' => 'phabricator-notification-header'), array($notifications_link, $clear_ui)); $content = hsprintf('%s%s%s', $header, $content, $connection_ui); $unread_count = id(new PhabricatorFeedStoryNotification())->countUnread($user); $json = array('content' => $content, 'number' => (int) $unread_count); return id(new AphrontAjaxResponse())->setContent($json); }
public function render() { $messages = $this->lintMessages; $messages = msort($messages, 'getSortKey'); if ($this->limit) { $messages = array_slice($messages, 0, $this->limit); } $rows = array(); foreach ($messages as $message) { $path = $message->getPath(); $line = $message->getLine(); $href = null; if (strlen(idx($this->pathURIMap, $path))) { $href = $this->pathURIMap[$path] . max($line, 1); } $severity = $this->renderSeverity($message->getSeverity()); $location = $path . ':' . $line; if (strlen($href)) { $location = phutil_tag('a', array('href' => $href), $location); } $rows[] = array($severity, $location, $message->getCode(), $message->getName()); } $table = id(new AphrontTableView($rows))->setHeaders(array(pht('Severity'), pht('Location'), pht('Code'), pht('Message')))->setColumnClasses(array(null, 'pri', null, 'wide')); return $table; }
private function getCardAttributes() { $pointslabel = 'Points:'; $pointsvalue = phutil_tag('dd', array('class' => 'phui-card-list-value'), array($this->points, ' ')); $pointskey = phutil_tag('dt', array('class' => 'phui-card-list-key'), array($pointslabel, ' ')); return phutil_tag('dl', array('class' => 'phui-property-list-container'), array($pointskey, $pointsvalue)); }
protected function getTagContent() { require_celerity_resource('phui-document-view-css'); require_celerity_resource('phui-document-view-pro-css'); Javelin::initBehavior('phabricator-reveal-content'); $classes = array(); $classes[] = 'phui-document-view'; $classes[] = 'phui-document-view-pro'; $book = null; if ($this->bookname) { $book = pht('%s (%s)', $this->bookname, $this->bookdescription); } $main_content = $this->renderChildren(); if ($book) { $this->header->setSubheader($book); } $table_of_contents = null; if ($this->toc) { $toc = array(); $toc_id = celerity_generate_unique_node_id(); $toc[] = id(new PHUIButtonView())->setTag('a')->setIconFont('fa-align-left')->setColor(PHUIButtonView::SIMPLE)->addClass('phui-document-toc')->addSigil('jx-toggle-class')->setMetaData(array('map' => array($toc_id => 'phui-document-toc-open'))); $toc[] = phutil_tag('div', array('class' => 'phui-list-sidenav phui-document-toc-list'), $this->toc); $table_of_contents = phutil_tag('div', array('class' => 'phui-document-toc-container', 'id' => $toc_id), $toc); } $content_inner = phutil_tag('div', array('class' => 'phui-document-inner'), array($table_of_contents, $this->header, $main_content)); $content = phutil_tag('div', array('class' => 'phui-document-content'), $content_inner); $view = phutil_tag('div', array('class' => implode(' ', $classes)), $content); $list = null; if ($this->propertyList) { $list = phutil_tag_div('phui-document-properties', $this->propertyList); } return array($view, $list); }
private function renderCommitsTable(PhabricatorRepositoryPushEvent $event, array $commits) { $viewer = $this->getRequest()->getUser(); $repository = $event->getRepository(); $rows = array(); foreach ($commits as $identifier => $commit) { if ($commit) { $partial_import = PhabricatorRepositoryCommit::IMPORTED_MESSAGE | PhabricatorRepositoryCommit::IMPORTED_CHANGE; if ($commit->isPartiallyImported($partial_import)) { $summary = AphrontTableView::renderSingleDisplayLine($commit->getSummary()); } else { $summary = phutil_tag('em', array(), pht('Importing...')); } } else { $summary = phutil_tag('em', array(), pht('Discovering...')); } $commit_name = $repository->formatCommitName($identifier); if ($commit) { $commit_name = phutil_tag('a', array('href' => '/' . $commit_name), $commit_name); } $rows[] = array($commit_name, $summary); } $table = id(new AphrontTableView($rows))->setNoDataString(pht("This push didn't push any new commits."))->setHeaders(array(pht('Commit'), pht('Summary')))->setColumnClasses(array('n', 'wide')); return $table; }
public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $post = id(new PhamePostQuery())->setViewer($viewer)->withIDs(array($request->getURIData('id')))->executeOne(); if (!$post) { return new Aphront404Response(); } $blog = $post->getBlog(); $crumbs = $this->buildApplicationCrumbs(); if ($blog) { $crumbs->addTextCrumb($blog->getName(), $this->getApplicationURI('blog/view/' . $blog->getID() . '/')); } else { $crumbs->addTextCrumb(pht('[No Blog]'), null); } $crumbs->addTextCrumb($post->getTitle(), $this->getApplicationURI('post/view/' . $post->getID() . '/')); $crumbs->setBorder(true); $actions = $this->renderActions($post, $viewer); $properties = $this->renderProperties($post, $viewer); $action_button = id(new PHUIButtonView())->setTag('a')->setText(pht('Actions'))->setHref('#')->setIconFont('fa-bars')->addClass('phui-mobile-menu')->setDropdownMenu($actions); $header = id(new PHUIHeaderView())->setHeader($post->getTitle())->setUser($viewer)->setPolicyObject($post)->addActionLink($action_button); $document = id(new PHUIDocumentViewPro())->setHeader($header)->setPropertyList($properties); if ($post->isDraft()) { $document->appendChild(id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->setTitle(pht('Draft Post'))->appendChild(pht('Only you can see this draft until you publish it. ' . 'Use "Preview / Publish" to publish this post.'))); } if (!$post->getBlog()) { $document->appendChild(id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setTitle(pht('Not On A Blog'))->appendChild(pht('This post is not associated with a blog (the blog may have ' . 'been deleted). Use "Move Post" to move it to a new blog.'))); } $engine = id(new PhabricatorMarkupEngine())->setViewer($viewer)->addObject($post, PhamePost::MARKUP_FIELD_BODY)->process(); $document->appendChild(phutil_tag('div', array('class' => 'phabricator-remarkup'), $engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY))); $timeline = $this->buildTransactionTimeline($post, id(new PhamePostTransactionQuery())->withTransactionTypes(array(PhabricatorTransactions::TYPE_COMMENT))); $timeline = phutil_tag_div('phui-document-view-pro-box', $timeline); $add_comment = $this->buildCommentForm($post); return $this->newPage()->setTitle($post->getTitle())->addClass('pro-white-background')->setPageObjectPHIDs(array($post->getPHID()))->setCrumbs($crumbs)->appendChild(array($document, $timeline, $add_comment)); }
public final function render() { require_celerity_resource('aphront-error-view-css'); $errors = $this->errors; if ($errors) { $list = array(); foreach ($errors as $error) { $list[] = phutil_tag('li', array(), $error); } $list = phutil_tag('ul', array('class' => 'aphront-error-view-list'), $list); } else { $list = null; } $title = $this->title; if (strlen($title)) { $title = phutil_tag('h1', array('class' => 'aphront-error-view-head'), $title); } else { $title = null; } $this->severity = nonempty($this->severity, self::SEVERITY_ERROR); $classes = array(); $classes[] = 'aphront-error-view'; $classes[] = 'aphront-error-severity-' . $this->severity; $classes = implode(' ', $classes); $children = $this->renderChildren(); $children[] = $list; return phutil_tag('div', array('id' => $this->id, 'class' => $classes), array($title, phutil_tag('div', array('class' => 'aphront-error-view-body'), $children))); }
protected function renderInput() { $drop_id = celerity_generate_unique_node_id(); Javelin::initBehavior('conpherence-drag-and-drop-photo', array('target' => $drop_id, 'form_pane' => 'conpherence-form', 'upload_uri' => '/file/dropupload/', 'activated_class' => 'conpherence-dialogue-upload-photo')); require_celerity_resource('conpherence-update-css'); return phutil_tag('div', array('id' => $drop_id, 'class' => 'conpherence-dialogue-drag-photo'), pht('Drag and drop an image here to upload it.')); }
protected function renderHyperlink($link, $name) { if ($this->getEngine()->isTextMode()) { $text = $link; if (strncmp($link, '/', 1) == 0 || strncmp($link, '#', 1) == 0) { $base = $this->getEngine()->getConfig('uri.prefix'); if (strncmp($link, '/', 1) == 0) { $base = rtrim($base, '/'); } $text = $base . $text; } // If present, strip off "mailto:" or "tel:". $text = preg_replace('/^(?:mailto|tel):/', '', $text); if ($link == $name) { return $text; } return $name . ' <' . $text . '>'; } // By default, we open links in a new window or tab. For anchors on the same // page, just jump normally. $target = '_blank'; if (strncmp($link, '#', 1) == 0) { $target = null; } $name = preg_replace('/^(?:mailto|tel):/', '', $name); if ($this->getEngine()->getState('toc')) { return $name; } else { return phutil_tag('a', array('href' => $link, 'class' => 'remarkup-link', 'target' => $target), $name); } }
protected function getTagContent() { if ($this->previewURI === null) { throw new PhutilInvalidStateException('setPreviewURI'); } if ($this->controlID === null) { throw new PhutilInvalidStateException('setControlID'); } $preview_id = celerity_generate_unique_node_id(); require_celerity_resource('phui-remarkup-preview-css'); Javelin::initBehavior('remarkup-preview', array('previewID' => $preview_id, 'controlID' => $this->controlID, 'uri' => $this->previewURI)); $loading = phutil_tag('div', array('class' => 'phui-preview-loading-text'), nonempty($this->loadingText, pht('Loading preview...'))); $header = null; if ($this->header) { $header = phutil_tag('div', array('class' => 'phui-preview-header'), $this->header); } $preview = phutil_tag('div', array('id' => $preview_id, 'class' => 'phabricator-remarkup'), $loading); $content = array($header, $preview); switch ($this->skin) { case 'document': $content = id(new PHUIDocumentView())->appendChild($content)->setFontKit(PHUIDocumentView::FONT_SOURCE_SANS); break; default: $content = id(new PHUIBoxView())->appendChild($content)->setBorder(true)->addMargin(PHUI::MARGIN_LARGE)->addPadding(PHUI::PADDING_LARGE)->addClass('phui-panel-preview'); break; } return $content; }
function phabricator_form(PhabricatorUser $user, $attributes, $content) { $body = array(); $http_method = idx($attributes, 'method'); $is_post = strcasecmp($http_method, 'POST') === 0; $http_action = idx($attributes, 'action'); $is_absolute_uri = preg_match('#^(https?:|//)#', $http_action); if ($is_post) { // NOTE: We only include CSRF tokens if a URI is a local URI on the same // domain. This is an important security feature and prevents forms which // submit to foreign sites from leaking CSRF tokens. // In some cases, we may construct a fully-qualified local URI. For example, // we can construct these for download links, depending on configuration. // These forms do not receive CSRF tokens, even though they safely could. // This can be confusing, if you're developing for Phabricator and // manage to construct a local form with a fully-qualified URI, since it // won't get CSRF tokens and you'll get an exception at the other end of // the request which is a bit disconnected from the actual root cause. // However, this is rare, and there are reasonable cases where this // construction occurs legitimately, and the simplest fix is to omit CSRF // tokens for these URIs in all cases. The error message you receive also // gives you some hints as to this potential source of error. if (!$is_absolute_uri) { $body[] = phutil_tag('input', array('type' => 'hidden', 'name' => AphrontRequest::getCSRFTokenName(), 'value' => $user->getCSRFToken())); $body[] = phutil_tag('input', array('type' => 'hidden', 'name' => '__form__', 'value' => true)); } } if (is_array($content)) { $body = array_merge($body, $content); } else { $body[] = $content; } return javelin_tag('form', $attributes, $body); }
private function renderCommonProperties(PHUIPropertyListView $properties, PhabricatorCacheSpec $cache) { if ($cache->getName() !== null) { $name = $this->renderYes($cache->getName()); } else { $name = $this->renderNo(pht('None')); } $properties->addProperty(pht('Cache'), $name); if ($cache->getIsEnabled()) { $enabled = $this->renderYes(pht('Enabled')); } else { $enabled = $this->renderNo(pht('Not Enabled')); } $properties->addProperty(pht('Enabled'), $enabled); $version = $cache->getVersion(); if ($version) { $properties->addProperty(pht('Version'), $this->renderInfo($version)); } if ($cache->getName() === null) { return; } $mem_total = $cache->getTotalMemory(); $mem_used = $cache->getUsedMemory(); if ($mem_total) { $percent = 100 * ($mem_used / $mem_total); $properties->addProperty(pht('Memory Usage'), pht('%s of %s', phutil_tag('strong', array(), sprintf('%.1f%%', $percent)), phutil_format_bytes($mem_total))); } $entry_count = $cache->getEntryCount(); if ($entry_count !== null) { $properties->addProperty(pht('Cache Entries'), pht('%s', new PhutilNumber($entry_count))); } }
public function render() { $leases = $this->leases; $viewer = $this->getUser(); $view = new PHUIObjectItemListView(); foreach ($leases as $lease) { $item = id(new PHUIObjectItemView())->setUser($viewer)->setHeader($lease->getLeaseName())->setHref('/drydock/lease/' . $lease->getID() . '/'); if ($lease->hasAttachedResource()) { $resource = $lease->getResource(); $resource_href = '/drydock/resource/' . $resource->getID() . '/'; $resource_name = $resource->getName(); $item->addAttribute(phutil_tag('a', array('href' => $resource_href), $resource_name)); } $status = DrydockLeaseStatus::getNameForStatus($lease->getStatus()); $item->addAttribute($status); $item->setEpoch($lease->getDateCreated()); // TODO: Tailor this for clarity. if ($lease->isActivating()) { $item->setStatusIcon('fa-dot-circle-o yellow'); } else { if ($lease->isActive()) { $item->setStatusIcon('fa-dot-circle-o green'); } else { $item->setStatusIcon('fa-dot-circle-o red'); } } $view->addItem($item); } return $view; }
public function render() { $conpherence = $this->getConpherence(); $widget_data = $conpherence->getWidgetData(); $viewer = $this->getUser(); $participants = $conpherence->getParticipants(); $handles = $conpherence->getHandles(); $head_handles = array_select_keys($handles, array($viewer->getPHID())); $handle_list = mpull($handles, 'getName'); natcasesort($handle_list); $handles = mpull($handles, null, 'getName'); $handles = array_select_keys($handles, $handle_list); $head_handles = mpull($head_handles, null, 'getName'); $handles = $head_handles + $handles; $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $conpherence, PhabricatorPolicyCapability::CAN_EDIT); $body = array(); foreach ($handles as $handle) { $user_phid = $handle->getPHID(); if ($user_phid == $viewer->getPHID() || $can_edit) { $icon = id(new PHUIIconView())->setIcon('fa-times lightbluetext'); $remove_html = javelin_tag('a', array('class' => 'remove', 'sigil' => 'remove-person', 'meta' => array('remove_person' => $user_phid, 'action' => 'remove_person')), $icon); } else { $remove_html = null; } $body[] = phutil_tag('div', array('class' => 'person-entry grouped'), array(phutil_tag('a', array('class' => 'pic', 'href' => $handle->getURI()), phutil_tag('img', array('src' => $handle->getImageURI()), '')), $handle->renderLink(), $remove_html)); } return $body; }