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);
 }
Ejemplo n.º 5
0
<?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');
Ejemplo n.º 6
0
 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);
 }