public function processRequest(AphrontRequest $request) { $user = $request->getUser(); $preferences = $user->loadPreferences(); $pref_monospaced = PhabricatorUserPreferences::PREFERENCE_MONOSPACED; $pref_editor = PhabricatorUserPreferences::PREFERENCE_EDITOR; $pref_multiedit = PhabricatorUserPreferences::PREFERENCE_MULTIEDIT; $pref_titles = PhabricatorUserPreferences::PREFERENCE_TITLES; $pref_monospaced_textareas = PhabricatorUserPreferences::PREFERENCE_MONOSPACED_TEXTAREAS; $errors = array(); $e_editor = null; if ($request->isFormPost()) { $monospaced = $request->getStr($pref_monospaced); $monospaced = PhabricatorUserPreferences::filterMonospacedCSSRule($monospaced); $preferences->setPreference($pref_titles, $request->getStr($pref_titles)); $preferences->setPreference($pref_editor, $request->getStr($pref_editor)); $preferences->setPreference($pref_multiedit, $request->getStr($pref_multiedit)); $preferences->setPreference($pref_monospaced, $monospaced); $preferences->setPreference($pref_monospaced_textareas, $request->getStr($pref_monospaced_textareas)); $editor_pattern = $preferences->getPreference($pref_editor); if (strlen($editor_pattern)) { $ok = PhabricatorHelpEditorProtocolController::hasAllowedProtocol($editor_pattern); if (!$ok) { $allowed_key = 'uri.allowed-editor-protocols'; $allowed_protocols = PhabricatorEnv::getEnvConfig($allowed_key); $proto_names = array(); foreach (array_keys($allowed_protocols) as $protocol) { $proto_names[] = $protocol . '://'; } $errors[] = pht('Editor link has an invalid or missing protocol. You must ' . 'use a whitelisted editor protocol from this list: %s. To ' . 'add protocols, update %s.', implode(', ', $proto_names), phutil_tag('tt', array(), $allowed_key)); $e_editor = pht('Invalid'); } } if (!$errors) { $preferences->save(); return id(new AphrontRedirectResponse())->setURI($this->getPanelURI('?saved=true')); } } $example_string = <<<EXAMPLE // This is what your monospaced font currently looks like. function helloWorld() { alert("Hello world!"); } EXAMPLE; $editor_doc_link = phutil_tag('a', array('href' => PhabricatorEnv::getDoclink('User Guide: Configuring an External Editor')), pht('User Guide: Configuring an External Editor')); $pref_monospaced_textareas_value = $preferences->getPreference($pref_monospaced_textareas); if (!$pref_monospaced_textareas_value) { $pref_monospaced_textareas_value = 'disabled'; } $editor_instructions = pht('Link to edit files in external editor. ' . '%%f is replaced by filename, %%l by line number, %%r by repository ' . 'callsign, %%%% by literal %%. For documentation, see: %s', $editor_doc_link); $font_instructions = pht('Overrides default fonts in tools like Differential. ' . 'Input should be valid CSS "font" declaration, such as ' . '"13px Consolas"'); $form = id(new AphrontFormView())->setUser($user)->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Page Titles'))->setName($pref_titles)->setValue($preferences->getPreference($pref_titles))->setOptions(array('glyph' => pht('In page titles, show Tool names as unicode glyphs: %s', "⚙"), 'text' => pht('In page titles, show Tool names as plain text: ' . '[Differential]'))))->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Editor Link'))->setName($pref_editor)->setCaption($editor_instructions)->setError($e_editor)->setValue($preferences->getPreference($pref_editor)))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Edit Multiple Files'))->setName($pref_multiedit)->setOptions(array('' => pht('Supported (paths separated by spaces)'), 'disable' => pht('Not Supported')))->setValue($preferences->getPreference($pref_multiedit)))->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Monospaced Font'))->setName($pref_monospaced)->setCaption($font_instructions)->setValue($preferences->getPreference($pref_monospaced)))->appendChild(id(new AphrontFormMarkupControl())->setValue(phutil_tag('pre', array('class' => 'PhabricatorMonospaced'), $example_string)))->appendChild(id(new AphrontFormRadioButtonControl())->setLabel(pht('Monospaced Textareas'))->setName($pref_monospaced_textareas)->setValue($pref_monospaced_textareas_value)->addButton('enabled', pht('Enabled'), pht('Show all textareas using the monospaced font defined above.'))->addButton('disabled', pht('Disabled'), null)); $form->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save Preferences'))); $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Display Preferences'))->setFormErrors($errors)->setFormSaved($request->getStr('saved') === 'true')->setForm($form); return array($form_box); }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $preferences = PhabricatorUserPreferences::loadUserPreferences($viewer); $editor = id(new PhabricatorUserPreferencesEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $key = $request->getStr('key'); $value = $request->getStr('value'); $xactions = array(); $xactions[] = $preferences->newTransaction($key, $value); $editor->applyTransactions($preferences, $xactions); return id(new AphrontAjaxResponse())->setContent(array()); }
private function writeSettings(array $map) { $request = $this->getRequest(); $viewer = $this->getViewer(); $preferences = PhabricatorUserPreferences::loadUserPreferences($viewer); $editor = id(new PhabricatorUserPreferencesEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $xactions = array(); foreach ($map as $key => $value) { $xactions[] = $preferences->newTransaction($key, $value); } $editor->applyTransactions($preferences, $xactions); }
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); }
<?php $applications = array('Audit', 'Auth', 'Calendar', 'ChatLog', 'Conduit', 'Config', 'Conpherence', 'Countdown', 'Daemons', 'Dashboard', 'Differential', 'Diffusion', 'Diviner', 'Doorkeeper', 'Drydock', 'Fact', 'Feed', 'Files', 'Flags', 'Harbormaster', 'Help', 'Herald', 'Home', 'Legalpad', 'Macro', 'MailingLists', 'Maniphest', 'Applications', 'MetaMTA', 'Notifications', 'Nuance', 'OAuthServer', 'Owners', 'Passphrase', 'Paste', 'People', 'Phame', 'Phlux', 'Pholio', 'Phortune', 'PHPAST', 'Phragment', 'Phrequent', 'Phriction', 'Policy', 'Ponder', 'Project', 'Releeph', 'Repositories', 'Search', 'Settings', 'Slowvote', 'Subscriptions', 'Support', 'System', 'Test', 'Tokens', 'Transactions', 'Typeahead', 'UIExamples', 'XHProf'); $map = array(); foreach ($applications as $application) { $old_name = 'PhabricatorApplication' . $application; $new_name = 'Phabricator' . $application . 'Application'; $map[$old_name] = $new_name; } /* -( User preferences )--------------------------------------------------- */ echo "Migrating user preferences...\n"; $table = new PhabricatorUserPreferences(); $conn_w = $table->establishConnection('w'); $pref_pinned = PhabricatorUserPreferences::PREFERENCE_APP_PINNED; foreach (new LiskMigrationIterator(new PhabricatorUser()) as $user) { $user_preferences = $user->loadPreferences(); $old_pinned_apps = $user_preferences->getPreference($pref_pinned); $new_pinned_apps = array(); if (!$old_pinned_apps) { continue; } foreach ($old_pinned_apps as $pinned_app) { $new_pinned_apps[] = idx($map, $pinned_app, $pinned_app); } $user_preferences->setPreference($pref_pinned, $new_pinned_apps); queryfx($conn_w, 'UPDATE %T SET preferences = %s WHERE id = %d', $user_preferences->getTableName(), json_encode($user_preferences->getPreferences()), $user_preferences->getID()); } /* -( Dashboard installs )------------------------------------------------- */ echo "Migrating dashboard installs...\n"; $table = new PhabricatorDashboardInstall(); $conn_w = $table->establishConnection('w');
public function loadPreferences() { if ($this->preferences) { return $this->preferences; } $preferences = null; if ($this->getPHID()) { $preferences = id(new PhabricatorUserPreferences())->loadOneWhere('userPHID = %s', $this->getPHID()); } if (!$preferences) { $preferences = new PhabricatorUserPreferences(); $preferences->setUserPHID($this->getPHID()); $default_dict = array(PhabricatorUserPreferences::PREFERENCE_TITLES => 'glyph', PhabricatorUserPreferences::PREFERENCE_EDITOR => '', PhabricatorUserPreferences::PREFERENCE_MONOSPACED => '', PhabricatorUserPreferences::PREFERENCE_DARK_CONSOLE => 0); $preferences->setPreferences($default_dict); } $this->preferences = $preferences; return $preferences; }
private function shouldSendHTML(PhabricatorUserPreferences $preferences) { $value = $preferences->getSettingValue(PhabricatorEmailFormatSetting::SETTINGKEY); return $value == PhabricatorEmailFormatSetting::VALUE_HTML_EMAIL; }
protected function getHead() { $monospaced = null; $request = $this->getRequest(); if ($request) { $user = $request->getUser(); if ($user) { $monospaced = $user->loadPreferences()->getPreference(PhabricatorUserPreferences::PREFERENCE_MONOSPACED); } } $response = CelerityAPI::getStaticResourceResponse(); $font_css = null; if (!empty($monospaced)) { // We can't print this normally because escaping quotation marks will // break the CSS. Instead, filter it strictly and then mark it as safe. $monospaced = new PhutilSafeHTML(PhabricatorUserPreferences::filterMonospacedCSSRule($monospaced)); $font_css = hsprintf('<style type="text/css">' . '.PhabricatorMonospaced, ' . '.phabricator-remarkup .remarkup-code-block ' . '.remarkup-code { font: %s !important; } ' . '</style>', $monospaced); } return hsprintf('%s%s%s', parent::getHead(), $font_css, $response->renderSingleResource('javelin-magical-init', 'phabricator')); }
<?php $table = new PhabricatorUserPreferences(); $conn_w = $table->establishConnection('w'); // Convert "Mail Format", "Re Prefix" and "Vary Subjects" mail settings to // string constants to avoid weird stuff where we store "true" and "false" as // strings in the database. // Each of these keys will be converted to the first value if present and // truthy, or the second value if present and falsey. $remap = array('html-emails' => array('html', 'text'), 're-prefix' => array('re', 'none'), 'vary-subject' => array('vary', 'static')); foreach (new LiskMigrationIterator($table) as $row) { $dict = $row->getPreferences(); $should_update = false; foreach ($remap as $key => $value) { if (isset($dict[$key])) { if ($dict[$key]) { $dict[$key] = $value[0]; } else { $dict[$key] = $value[1]; } $should_update = true; } } if (!$should_update) { continue; } queryfx($conn_w, 'UPDATE %T SET preferences = %s WHERE id = %d', $table->getTableName(), phutil_json_encode($dict), $row->getID()); } $prefs_key = PhabricatorUserPreferencesCacheType::KEY_PREFERENCES; PhabricatorUserCache::clearCacheForAllUsers($prefs_key);
private function browseFile() { $viewer = $this->getViewer(); $request = $this->getRequest(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $before = $request->getStr('before'); if ($before) { return $this->buildBeforeResponse($before); } $path = $drequest->getPath(); $blame_key = PhabricatorDiffusionBlameSetting::SETTINGKEY; $color_key = PhabricatorDiffusionColorSetting::SETTINGKEY; $show_blame = $request->getBool('blame', $viewer->getUserSetting($blame_key)); $show_color = $request->getBool('color', $viewer->getUserSetting($color_key)); $view = $request->getStr('view'); if ($request->isFormPost() && $view != 'raw' && $viewer->isLoggedIn()) { $preferences = PhabricatorUserPreferences::loadUserPreferences($viewer); $editor = id(new PhabricatorUserPreferencesEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $xactions = array(); $xactions[] = $preferences->newTransaction($blame_key, $show_blame); $xactions[] = $preferences->newTransaction($color_key, $show_color); $editor->applyTransactions($preferences, $xactions); $uri = $request->getRequestURI()->alter('blame', null)->alter('color', null); return id(new AphrontRedirectResponse())->setURI($uri); } // We need the blame information if blame is on and we're building plain // text, or blame is on and this is an Ajax request. If blame is on and // this is a colorized request, we don't show blame at first (we ajax it // in afterward) so we don't need to query for it. $needs_blame = $show_blame && !$show_color || $show_blame && $request->isAjax(); $params = array('commit' => $drequest->getCommit(), 'path' => $drequest->getPath()); $byte_limit = null; if ($view !== 'raw') { $byte_limit = PhabricatorFileStorageEngine::getChunkThreshold(); $time_limit = 10; $params += array('timeout' => $time_limit, 'byteLimit' => $byte_limit); } $response = $this->callConduitWithDiffusionRequest('diffusion.filecontentquery', $params); $hit_byte_limit = $response['tooHuge']; $hit_time_limit = $response['tooSlow']; $file_phid = $response['filePHID']; if ($hit_byte_limit) { $corpus = $this->buildErrorCorpus(pht('This file is larger than %s byte(s), and too large to display ' . 'in the web UI.', phutil_format_bytes($byte_limit))); } else { if ($hit_time_limit) { $corpus = $this->buildErrorCorpus(pht('This file took too long to load from the repository (more than ' . '%s second(s)).', new PhutilNumber($time_limit))); } else { $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($file_phid))->executeOne(); if (!$file) { throw new Exception(pht('Failed to load content file!')); } if ($view === 'raw') { return $file->getRedirectResponse(); } $data = $file->loadFileData(); $ref = $this->getGitLFSRef($repository, $data); if ($ref) { if ($view == 'git-lfs') { $file = $this->loadGitLFSFile($ref); // Rename the file locally so we generate a better vanity URI for // it. In storage, it just has a name like "lfs-13f9a94c0923...", // since we don't get any hints about possible human-readable names // at upload time. $basename = basename($drequest->getPath()); $file->makeEphemeral(); $file->setName($basename); return $file->getRedirectResponse(); } else { $corpus = $this->buildGitLFSCorpus($ref); } } else { if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) { $file_uri = $file->getBestURI(); if ($file->isViewableImage()) { $corpus = $this->buildImageCorpus($file_uri); } else { $corpus = $this->buildBinaryCorpus($file_uri, $data); } } else { $this->loadLintMessages(); $this->coverage = $drequest->loadCoverage(); // Build the content of the file. $corpus = $this->buildCorpus($show_blame, $show_color, $data, $needs_blame, $drequest, $path, $data); } } } } if ($request->isAjax()) { return id(new AphrontAjaxResponse())->setContent($corpus); } require_celerity_resource('diffusion-source-css'); // Render the page. $view = $this->buildCurtain($drequest); $curtain = $this->enrichCurtain($view, $drequest, $show_blame, $show_color); $properties = $this->buildPropertyView($drequest); $header = $this->buildHeaderView($drequest); $header->setHeaderIcon('fa-file-code-o'); $content = array(); $follow = $request->getStr('follow'); if ($follow) { $notice = new PHUIInfoView(); $notice->setSeverity(PHUIInfoView::SEVERITY_WARNING); $notice->setTitle(pht('Unable to Continue')); switch ($follow) { case 'first': $notice->appendChild(pht('Unable to continue tracing the history of this file because ' . 'this commit is the first commit in the repository.')); break; case 'created': $notice->appendChild(pht('Unable to continue tracing the history of this file because ' . 'this commit created the file.')); break; } $content[] = $notice; } $renamed = $request->getStr('renamed'); if ($renamed) { $notice = new PHUIInfoView(); $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE); $notice->setTitle(pht('File Renamed')); $notice->appendChild(pht('File history passes through a rename from "%s" to "%s".', $drequest->getPath(), $renamed)); $content[] = $notice; } $content[] = $corpus; $content[] = $this->buildOpenRevisions(); $crumbs = $this->buildCrumbs(array('branch' => true, 'path' => true, 'view' => 'browse')); $crumbs->setBorder(true); $basename = basename($this->getDiffusionRequest()->getPath()); $view = id(new PHUITwoColumnView())->setHeader($header)->setCurtain($curtain)->setMainColumn(array($content)); if ($properties) { $view->addPropertySection(pht('Details'), $properties); } $title = array($basename, $repository->getDisplayName()); return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild(array($view)); }
<?php $table = new PhabricatorUserPreferences(); $conn_w = $table->establishConnection('w'); foreach (new LiskMigrationIterator($table) as $row) { if ($row->getPHID() !== '') { continue; } queryfx($conn_w, 'UPDATE %T SET phid = %s WHERE id = %d', $table->getTableName(), $table->generatePHID(), $row->getID()); }
private function handleProjectRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $errors = array(); $e_project = true; if ($request->isFormPost()) { $project_phids = $request->getArr('projectPHIDs'); $project_phid = head($project_phids); $project = id(new PhabricatorObjectQuery())->setViewer($viewer)->withPHIDs(array($project_phid))->executeOne(); if ($project) { // Save this project as one of the user's most recently used projects, // so we'll show it by default in future menus. $favorites_key = PhabricatorPolicyFavoritesSetting::SETTINGKEY; $favorites = $viewer->getUserSetting($favorites_key); if (!is_array($favorites)) { $favorites = array(); } // Add this, or move it to the end of the list. unset($favorites[$project_phid]); $favorites[$project_phid] = true; $preferences = PhabricatorUserPreferences::loadUserPreferences($viewer); $editor = id(new PhabricatorUserPreferencesEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $xactions = array(); $xactions[] = $preferences->newTransaction($favorites_key, $favorites); $editor->applyTransactions($preferences, $xactions); $data = array('phid' => $project->getPHID(), 'info' => array('name' => $project->getName(), 'full' => $project->getName(), 'icon' => $project->getDisplayIconIcon())); return id(new AphrontAjaxResponse())->setContent($data); } else { $errors[] = pht('You must choose a project.'); $e_project = pht('Required'); } } $project_datasource = id(new PhabricatorProjectDatasource())->setParameters(array('policy' => 1)); $form = id(new AphrontFormView())->setUser($viewer)->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Members Of'))->setName('projectPHIDs')->setLimit(1)->setError($e_project)->setDatasource($project_datasource)); return $this->newDialog()->setWidth(AphrontDialogView::WIDTH_FORM)->setErrors($errors)->setTitle(pht('Select Project'))->appendForm($form)->addSubmitButton(pht('Done'))->addCancelButton('#'); }
<?php // Move timezone, translation and pronoun from the user object to preferences // so they can be defaulted and edited like other settings. $table = new PhabricatorUser(); $conn_w = $table->establishConnection('w'); $table_name = $table->getTableName(); $prefs_table = new PhabricatorUserPreferences(); foreach (new LiskRawMigrationIterator($conn_w, $table_name) as $row) { $phid = $row['phid']; $pref_row = queryfx_one($conn_w, 'SELECT preferences FROM %T WHERE userPHID = %s', $prefs_table->getTableName(), $phid); if ($pref_row) { try { $prefs = phutil_json_decode($pref_row['preferences']); } catch (Exception $ex) { $prefs = array(); } } else { $prefs = array(); } $zone = $row['timezoneIdentifier']; if (strlen($zone)) { $prefs[PhabricatorTimezoneSetting::SETTINGKEY] = $zone; } $pronoun = $row['sex']; if (strlen($pronoun)) { $prefs[PhabricatorPronounSetting::SETTINGKEY] = $pronoun; } $translation = $row['translation']; if (strlen($translation)) { $prefs[PhabricatorTranslationSetting::SETTINGKEY] = $translation;
private function writeSetting(PhabricatorUser $user, $key, $value) { $preferences = PhabricatorUserPreferences::loadUserPreferences($user); $editor = id(new PhabricatorUserPreferencesEditor())->setActor($user)->setContentSource($this->newContentSource())->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $xactions = array(); $xactions[] = $preferences->newTransaction($key, $value); $editor->applyTransactions($preferences, $xactions); return id(new PhabricatorPeopleQuery())->setViewer($user)->withIDs(array($user->getID()))->executeOne(); }
protected function writeSetting(PhabricatorUserPreferences $preferences, $key, $value) { $viewer = $this->getViewer(); $request = $this->getController()->getRequest(); $editor = id(new PhabricatorUserPreferencesEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $xactions = array(); $xactions[] = $preferences->newTransaction($key, $value); $editor->applyTransactions($preferences, $xactions); }