diff --git a/conf/default.conf.php b/conf/default.conf.php index a9e4cff5a1..26f76dd3ce 100644 --- a/conf/default.conf.php +++ b/conf/default.conf.php @@ -801,7 +801,8 @@ return array( // Show stack traces when unhandled exceptions occur, force reloading of // static resources (skipping the cache), show an error callout if a page // generated PHP errors, warnings, or notices, force disk reads when - // reloading. This option should not be enabled in production. + // reloading, and generally make development easier. This option should not + // be enabled in production. 'phabricator.developer-mode' => false, // When users write comments which have URIs, they'll be automatically linked diff --git a/resources/sql/patches/20130201.revisionunsubscribed.php b/resources/sql/patches/20130201.revisionunsubscribed.php new file mode 100644 index 0000000000..b15379893b --- /dev/null +++ b/resources/sql/patches/20130201.revisionunsubscribed.php @@ -0,0 +1,33 @@ +openTransaction(); + +// We couldn't use new LiskMigrationIterator($table) because the $unsubscribed +// property gets deleted. +$revs = queryfx_all( + $table->establishConnection('w'), + 'SELECT id, phid, unsubscribed FROM differential_revision'); + +foreach ($revs as $rev) { + echo "."; + + $unsubscribed = json_decode($rev['unsubscribed']); + if (!$unsubscribed) { + continue; + } + + $editor = new PhabricatorEdgeEditor(); + $editor->setSuppressEvents(true); + foreach ($unsubscribed as $user_phid => $_) { + $editor->addEdge( + $rev['phid'], + PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER, + $user_phid); + } + $editor->save(); +} + +$table->saveTransaction(); +echo "Done.\n"; diff --git a/resources/sql/patches/20130201.revisionunsubscribed.sql b/resources/sql/patches/20130201.revisionunsubscribed.sql new file mode 100644 index 0000000000..51f09cc104 --- /dev/null +++ b/resources/sql/patches/20130201.revisionunsubscribed.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_differential.differential_revision + DROP unsubscribed; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index f587f31e17..c9e7a4dd43 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1226,6 +1226,7 @@ phutil_register_library_map(array( 'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php', 'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php', 'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php', + 'PhabricatorSettingsPanelDiffPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDiffPreferences.php', 'PhabricatorSettingsPanelDisplayPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDisplayPreferences.php', 'PhabricatorSettingsPanelEmailAddresses' => 'applications/settings/panel/PhabricatorSettingsPanelEmailAddresses.php', 'PhabricatorSettingsPanelEmailPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelEmailPreferences.php', @@ -2625,6 +2626,7 @@ phutil_register_library_map(array( 'PhabricatorSettingsMainController' => 'PhabricatorController', 'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel', + 'PhabricatorSettingsPanelDiffPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelDisplayPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelEmailAddresses' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelEmailPreferences' => 'PhabricatorSettingsPanel', diff --git a/src/applications/config/check/PhabricatorSetupCheckDatabase.php b/src/applications/config/check/PhabricatorSetupCheckDatabase.php index d966b19b97..b4e19e2a0f 100644 --- a/src/applications/config/check/PhabricatorSetupCheckDatabase.php +++ b/src/applications/config/check/PhabricatorSetupCheckDatabase.php @@ -65,6 +65,20 @@ final class PhabricatorSetupCheckDatabase extends PhabricatorSetupCheck { return; } + if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) { + $mode_string = queryfx_one($conn_raw, "SELECT @@sql_mode"); + $modes = explode(',', $mode_string['@@sql_mode']); + if (!in_array('STRICT_ALL_TABLES', $modes)) { + $message = pht( + "The global sql_mode is not set to 'STRICT_ALL_TABLES'. It is ". + "recommended that you set this mode while developing Phabricator."); + + $this->newIssue('mysql.mode') + ->setName(pht('MySQL STRICT_ALL_TABLES mode not set.')) + ->setMessage($message); + } + } + $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace'); $databases = queryfx_all($conn_raw, 'SHOW DATABASES'); diff --git a/src/applications/conpherence/controller/ConpherenceListController.php b/src/applications/conpherence/controller/ConpherenceListController.php index 46bae21db9..31a00ba670 100644 --- a/src/applications/conpherence/controller/ConpherenceListController.php +++ b/src/applications/conpherence/controller/ConpherenceListController.php @@ -77,15 +77,17 @@ final class ConpherenceListController extends 'class' => 'conpherence-header-pane', 'id' => 'conpherence-header-pane', ), - ''), + '' + ), phutil_tag( 'div', array( 'class' => 'conpherence-widget-pane', 'id' => 'conpherence-widget-pane' ), - ''), - phutil_tag( + '' + ), + javelin_tag( 'div', array( 'class' => 'conpherence-message-pane', @@ -98,15 +100,19 @@ final class ConpherenceListController extends 'class' => 'conpherence-messages', 'id' => 'conpherence-messages' ), - ''), + '' + ), phutil_tag( 'div', array( 'id' => 'conpherence-form' ), - ''), - )), - )); + '' + ) + ) + ) + ) + ); } diff --git a/src/applications/conpherence/controller/ConpherenceNewController.php b/src/applications/conpherence/controller/ConpherenceNewController.php index dff27bcf9a..21616a4978 100644 --- a/src/applications/conpherence/controller/ConpherenceNewController.php +++ b/src/applications/conpherence/controller/ConpherenceNewController.php @@ -95,8 +95,7 @@ final class ConpherenceNewController extends ConpherenceController { phutil_tag( 'p', array(), - pht('Message sent successfully.')) - ); + pht('Message sent successfully.'))); $response = id(new AphrontDialogResponse()) ->setDialog($dialog); } else { diff --git a/src/applications/conpherence/controller/ConpherenceViewController.php b/src/applications/conpherence/controller/ConpherenceViewController.php index 742df97250..e272f871f3 100644 --- a/src/applications/conpherence/controller/ConpherenceViewController.php +++ b/src/applications/conpherence/controller/ConpherenceViewController.php @@ -71,7 +71,7 @@ final class ConpherenceViewController extends $edit_href = $this->getApplicationURI('update/'.$conpherence->getID().'/'); $header = - javelin_render_tag( + javelin_tag( 'a', array( 'class' => 'edit', @@ -80,7 +80,7 @@ final class ConpherenceViewController extends ), '' ). - phutil_render_tag( + phutil_tag( 'div', array( 'class' => 'header-image', @@ -88,19 +88,19 @@ final class ConpherenceViewController extends ), '' ). - phutil_render_tag( + phutil_tag( 'div', array( 'class' => 'title', ), - phutil_escape_html($display_data['title']) + $display_data['title'] ). - phutil_render_tag( + phutil_tag( 'div', array( 'class' => 'subtitle', ), - phutil_escape_html($display_data['subtitle']) + $display_data['subtitle'] ); return array('header' => $header); @@ -152,6 +152,7 @@ final class ConpherenceViewController extends private function renderWidgetPaneContent() { require_celerity_resource('conpherence-widget-pane-css'); + require_celerity_resource('sprite-conpher-css'); Javelin::initBehavior( 'conpherence-widget-pane', array( @@ -165,7 +166,7 @@ final class ConpherenceViewController extends $conpherence = $this->getConpherence(); - $widgets = phutil_render_tag( + $widgets = phutil_tag( 'div', array( 'class' => 'widgets-header' @@ -175,31 +176,44 @@ final class ConpherenceViewController extends 'a', array( 'sigil' => 'conpherence-change-widget', - 'meta' => array('widget' => 'widgets-files') + 'meta' => array( + 'widget' => 'widgets-files', + 'toggleClass' => 'conpher_files_on' + ), + 'id' => 'widgets-files-toggle', + 'class' => 'sprite-conpher conpher_files_off first-icon' ), - pht('Files') + '' ), - ' | ', javelin_tag( 'a', array( 'sigil' => 'conpherence-change-widget', - 'meta' => array('widget' => 'widgets-tasks') + 'meta' => array( + 'widget' => 'widgets-tasks', + 'toggleClass' => 'conpher_list_on' + ), + 'id' => 'widgets-tasks-toggle', + 'class' => 'sprite-conpher conpher_list_off conpher_list_on', ), - pht('Tasks') + '' ), - ' | ', javelin_tag( 'a', array( 'sigil' => 'conpherence-change-widget', - 'meta' => array('widget' => 'widgets-calendar') + 'meta' => array( + 'widget' => 'widgets-calendar', + 'toggleClass' => 'conpher_calendar_on' + ), + 'id' => 'widgets-calendar-toggle', + 'class' => 'sprite-conpher conpher_calendar_off', ), - pht('Calendar') - ), + '' + ) ) ). - phutil_render_tag( + phutil_tag( 'div', array( 'class' => 'widgets-body', @@ -208,7 +222,7 @@ final class ConpherenceViewController extends ), $this->renderFilesWidgetPaneContent() ). - phutil_render_tag( + phutil_tag( 'div', array( 'class' => 'widgets-body', @@ -216,7 +230,7 @@ final class ConpherenceViewController extends ), $this->renderTaskWidgetPaneContent() ). - phutil_render_tag( + phutil_tag( 'div', array( 'class' => 'widgets-body', @@ -253,7 +267,7 @@ final class ConpherenceViewController extends ->setNoDataString(pht('No files attached to conpherence.')) ->setHeaders(array('', pht('Name'))) ->setColumnClasses(array('', 'wide')); - return $header->render() . $table->render(); + return new PhutilSafeHTML($header->render() . $table->render()); } private function renderTaskWidgetPaneContent() { @@ -279,7 +293,8 @@ final class ConpherenceViewController extends array( 'href' => '/T'.$task->getID() ), - $task->getTitle()), + $task->getTitle() + ) ); } $table = id(new AphrontTableView($data)) @@ -288,13 +303,110 @@ final class ConpherenceViewController extends ->setColumnClasses(array('', 'wide')); $content[] = $table->render(); } - return implode('', $content); + return new PhutilSafeHTML(implode('', $content)); } private function renderCalendarWidgetPaneContent() { - $header = id(new PhabricatorHeaderView()) - ->setHeader(pht('Calendar')); - return $header->render() . 'TODO'; + $user = $this->getRequest()->getUser(); + + $conpherence = $this->getConpherence(); + $widget_data = $conpherence->getWidgetData(); + $statuses = $widget_data['statuses']; + $handles = $conpherence->getHandles(); + $content = array(); + $timestamps = $this->getCalendarWidgetWeekTimestamps(); + $one_day = 24 * 60 * 60; + foreach ($timestamps as $time => $day) { + // build a header for the new day + $content[] = id(new PhabricatorHeaderView()) + ->setHeader($day->format('l')) + ->render(); + + $day->setTime(0, 0, 0); + $epoch_start = $day->format('U'); + $day->modify('+1 day'); + $epoch_end = $day->format('U'); + + // keep looking through statuses where we last left off + foreach ($statuses as $status) { + if ($status->getDateFrom() >= $epoch_end) { + // This list is sorted, so we can stop looking. + break; + } + if ($status->getDateFrom() < $epoch_end && + $status->getDateTo() > $epoch_start) { + $timespan = $status->getDateTo() - $status->getDateFrom(); + if ($timespan > $one_day) { + $time_str = 'm/d'; + } else { + $time_str = 'h:i A'; + } + $epoch_range = phabricator_format_local_time( + $status->getDateFrom(), + $user, + $time_str + ) . ' - ' . phabricator_format_local_time( + $status->getDateTo(), + $user, + $time_str + ); + + $content[] = phutil_tag( + 'div', + array( + 'class' => 'user-status '.$status->getTextStatus(), + ), + array( + phutil_tag( + 'div', + array( + 'class' => 'epoch-range' + ), + $epoch_range + ), + phutil_tag( + 'div', + array( + 'class' => 'icon', + ), + '' + ), + phutil_tag( + 'div', + array( + 'class' => 'description' + ), + $status->getTerseSummary($user) + ), + phutil_tag( + 'div', + array( + 'class' => 'participant' + ), + $handles[$status->getUserPHID()]->getName() + ) + ) + ); + } + } + } + + return new PhutilSafeHTML(implode('', $content)); + } + + private function getCalendarWidgetWeekTimestamps() { + $user = $this->getRequest()->getUser(); + $timezone = new DateTimeZone($user->getTimezoneIdentifier()); + + $timestamps = array(); + for ($day = 0; $day < 7; $day++) { + $timestamps[] = new DateTime( + sprintf('today +%d days', $day), + $timezone + ); + } + + return $timestamps; } } diff --git a/src/applications/conpherence/query/ConpherenceThreadQuery.php b/src/applications/conpherence/query/ConpherenceThreadQuery.php index 18fc8ec1b5..d22fd03820 100644 --- a/src/applications/conpherence/query/ConpherenceThreadQuery.php +++ b/src/applications/conpherence/query/ConpherenceThreadQuery.php @@ -141,17 +141,22 @@ final class ConpherenceThreadQuery $tasks = mgroup($tasks, 'getOwnerPHID'); // statuses of everyone currently in the conpherence - // until the beginning of the next work week. - // NOTE: this is a bit boring on the weekends. + // for a rolling one week window + $start_of_week = phabricator_format_local_time( + strtotime('today'), + $this->getViewer(), + 'U' + ); $end_of_week = phabricator_format_local_time( - strtotime('Monday midnight'), + strtotime('midnight +1 week'), $this->getViewer(), 'U' ); $statuses = id(new PhabricatorUserStatus()) ->loadAllWhere( - 'userPHID in (%Ls) AND dateTo <= %d', + 'userPHID in (%Ls) AND dateTo >= %d AND dateFrom <= %d', $participant_phids, + $start_of_week, $end_of_week ); $statuses = mgroup($statuses, 'getUserPHID'); @@ -168,9 +173,12 @@ final class ConpherenceThreadQuery foreach ($conpherences as $phid => $conpherence) { $participant_phids = array_keys($conpherence->getParticipants()); + $statuses = array_select_keys($statuses, $participant_phids); + $statuses = array_mergev($statuses); + $statuses = msort($statuses, 'getDateFrom'); $widget_data = array( 'tasks' => array_select_keys($tasks, $participant_phids), - 'statuses' => array_select_keys($statuses, $participant_phids), + 'statuses' => $statuses, 'files' => array_select_keys($files, $conpherence->getFilePHIDs()), ); $conpherence->attachWidgetData($widget_data); diff --git a/src/applications/conpherence/view/ConpherenceTransactionView.php b/src/applications/conpherence/view/ConpherenceTransactionView.php index bcb3278fa7..7e6c842526 100644 --- a/src/applications/conpherence/view/ConpherenceTransactionView.php +++ b/src/applications/conpherence/view/ConpherenceTransactionView.php @@ -85,12 +85,12 @@ final class ConpherenceTransactionView extends AphrontView { } $transaction_view - ->appendChild(phutil_render_tag( + ->appendChild(phutil_tag( 'div', array( 'class' => $content_class ), - $content) + new PhutilSafeHTML($content)) ); return $transaction_view->render(); diff --git a/src/applications/differential/controller/DifferentialRevisionViewController.php b/src/applications/differential/controller/DifferentialRevisionViewController.php index c48883d6ed..5dc9211297 100644 --- a/src/applications/differential/controller/DifferentialRevisionViewController.php +++ b/src/applications/differential/controller/DifferentialRevisionViewController.php @@ -408,29 +408,42 @@ final class DifferentialRevisionViewController extends DifferentialController { ->setAnchorName('top') ->setNavigationMarker(true); - $nav = id(new DifferentialChangesetFileTreeSideNavBuilder()) - ->setAnchorName('top') - ->setTitle('D'.$revision->getID()) - ->setBaseURI(new PhutilURI('/D'.$revision->getID())) - ->build($changesets); - $nav->appendChild( - array( - $reviewer_warning, - $top_anchor, - $revision_detail, - $page_pane, - )); - + $content = array( + $reviewer_warning, + $top_anchor, + $revision_detail, + $page_pane, + ); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addCrumb( id(new PhabricatorCrumbView()) ->setName($object_id) ->setHref('/'.$object_id)); - $nav->setCrumbs($crumbs); + + $prefs = $user->loadPreferences(); + + $pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE; + if ($prefs->getPreference($pref_filetree)) { + $collapsed = $prefs->getPreference( + PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED, + false); + + $nav = id(new DifferentialChangesetFileTreeSideNavBuilder()) + ->setAnchorName('top') + ->setTitle('D'.$revision->getID()) + ->setBaseURI(new PhutilURI('/D'.$revision->getID())) + ->setCollapsed((bool)$collapsed) + ->build($changesets); + $nav->appendChild($content); + $nav->setCrumbs($crumbs); + $content = $nav; + } else { + array_unshift($content, $crumbs); + } return $this->buildApplicationPage( - $nav, + $content, array( 'title' => $object_id.' '.$revision->getTitle(), )); diff --git a/src/applications/differential/editor/DifferentialRevisionEditor.php b/src/applications/differential/editor/DifferentialRevisionEditor.php index f347cd3b1c..d7c035637a 100644 --- a/src/applications/differential/editor/DifferentialRevisionEditor.php +++ b/src/applications/differential/editor/DifferentialRevisionEditor.php @@ -238,7 +238,7 @@ final class DifferentialRevisionEditor extends PhabricatorEditor { $diff); $adapter->setExplicitCCs($new['ccs']); $adapter->setExplicitReviewers($new['rev']); - $adapter->setForbiddenCCs($revision->getUnsubscribedPHIDs()); + $adapter->setForbiddenCCs($revision->loadUnsubscribedPHIDs()); $xscript = HeraldEngine::loadAndApplyRules($adapter); $xscript_uri = '/herald/transcript/'.$xscript->getID().'/'; @@ -500,12 +500,10 @@ final class DifferentialRevisionEditor extends PhabricatorEditor { self::addCC($revision, $phid, $reason); - $unsubscribed = $revision->getUnsubscribed(); - if (isset($unsubscribed[$phid])) { - unset($unsubscribed[$phid]); - $revision->setUnsubscribed($unsubscribed); - $revision->save(); - } + $type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER; + id(new PhabricatorEdgeEditor()) + ->removeEdge($revision->getPHID(), $type, $phid) + ->save(); } public static function removeCCAndUpdateRevision( @@ -515,12 +513,10 @@ final class DifferentialRevisionEditor extends PhabricatorEditor { self::removeCC($revision, $phid, $reason); - $unsubscribed = $revision->getUnsubscribed(); - if (empty($unsubscribed[$phid])) { - $unsubscribed[$phid] = true; - $revision->setUnsubscribed($unsubscribed); - $revision->save(); - } + $type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER; + id(new PhabricatorEdgeEditor()) + ->addEdge($revision->getPHID(), $type, $phid) + ->save(); } public static function addCC( diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php index b34e5d8afe..b07f1beb29 100644 --- a/src/applications/differential/storage/DifferentialRevision.php +++ b/src/applications/differential/storage/DifferentialRevision.php @@ -17,7 +17,6 @@ final class DifferentialRevision extends DifferentialDAO { protected $lineCount; protected $attached = array(); - protected $unsubscribed = array(); protected $mailKey; protected $branchName; @@ -264,8 +263,10 @@ final class DifferentialRevision extends DifferentialDAO { return idx($this->relationships, $relation, array()); } - public function getUnsubscribedPHIDs() { - return array_keys($this->getUnsubscribed()); + public function loadUnsubscribedPHIDs() { + return PhabricatorEdgeQuery::loadDestinationPHIDs( + $this->phid, + PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER); } public function getPrimaryReviewer() { diff --git a/src/applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php b/src/applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php index f2b1e59f40..acfc3a7a88 100644 --- a/src/applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php +++ b/src/applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php @@ -5,6 +5,7 @@ final class DifferentialChangesetFileTreeSideNavBuilder { private $title; private $baseURI; private $anchorName; + private $collapsed = false; public function setAnchorName($anchor_name) { $this->anchorName = $anchor_name; @@ -30,12 +31,18 @@ final class DifferentialChangesetFileTreeSideNavBuilder { return $this->title; } + public function setCollapsed($collapsed) { + $this->collapsed = $collapsed; + return $this; + } + public function build(array $changesets) { assert_instances_of($changesets, 'DifferentialChangeset'); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI($this->getBaseURI()); $nav->setFlexible(true); + $nav->setCollapsed($this->collapsed); $anchor = $this->getAnchorName(); @@ -123,6 +130,8 @@ final class DifferentialChangesetFileTreeSideNavBuilder { ), $filetree); + Javelin::initBehavior('phabricator-file-tree', array()); + $nav->addLabel(pht('Changed Files')); $nav->addCustomBlock($filetree); $nav->setActive(true); diff --git a/src/applications/differential/view/DifferentialChangesetListView.php b/src/applications/differential/view/DifferentialChangesetListView.php index 11209f000c..8021859aff 100644 --- a/src/applications/differential/view/DifferentialChangesetListView.php +++ b/src/applications/differential/view/DifferentialChangesetListView.php @@ -127,14 +127,9 @@ final class DifferentialChangesetListView extends AphrontView { $ref, $changeset); - $prefs = $this->user->loadPreferences(); - $pref_symbols = $prefs->getPreference( - PhabricatorUserPreferences::PREFERENCE_DIFFUSION_SYMBOLS); $detail->setChangeset($changeset); $detail->addButton($view_options); - if ($pref_symbols != 'disabled') { - $detail->setSymbolIndex(idx($this->symbolIndexes, $key)); - } + $detail->setSymbolIndex(idx($this->symbolIndexes, $key)); $detail->setVsChangesetID(idx($this->vsMap, $changeset->getID())); $detail->setEditable(true); diff --git a/src/applications/diffusion/controller/DiffusionBrowseFileController.php b/src/applications/diffusion/controller/DiffusionBrowseFileController.php index fa7686699e..93caaab144 100644 --- a/src/applications/diffusion/controller/DiffusionBrowseFileController.php +++ b/src/applications/diffusion/controller/DiffusionBrowseFileController.php @@ -251,10 +251,7 @@ final class DiffusionBrowseFileController extends DiffusionController { $lang = last(explode('.', $drequest->getPath())); - $prefs = $this->getRequest()->getUser()->loadPreferences(); - $pref_symbols = $prefs->getPreference( - PhabricatorUserPreferences::PREFERENCE_DIFFUSION_SYMBOLS); - if (isset($langs[$lang]) && $pref_symbols != 'disabled') { + if (isset($langs[$lang])) { Javelin::initBehavior( 'repository-crossreference', array( diff --git a/src/applications/diffusion/controller/DiffusionCommitController.php b/src/applications/diffusion/controller/DiffusionCommitController.php index bb6ac15f3e..65e47e3af1 100644 --- a/src/applications/diffusion/controller/DiffusionCommitController.php +++ b/src/applications/diffusion/controller/DiffusionCommitController.php @@ -327,13 +327,20 @@ final class DiffusionCommitController extends DiffusionController { 'commit' => true, )); - if ($changesets) { + $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 ($changesets && $show_filetree) { $nav = id(new DifferentialChangesetFileTreeSideNavBuilder()) ->setAnchorName('top') ->setTitle($short_name) ->setBaseURI(new PhutilURI('/'.$commit_id)) ->build($changesets) ->setCrumbs($crumbs) + ->setCollapsed((bool)$collapsed) ->appendChild($content); $content = $nav; } else { diff --git a/src/applications/directory/controller/PhabricatorDirectoryController.php b/src/applications/directory/controller/PhabricatorDirectoryController.php index b7064d4360..11a47d7014 100644 --- a/src/applications/directory/controller/PhabricatorDirectoryController.php +++ b/src/applications/directory/controller/PhabricatorDirectoryController.php @@ -79,7 +79,7 @@ abstract class PhabricatorDirectoryController extends PhabricatorController { $is_hide = ($tile_display == PhabricatorApplication::TILE_HIDE); if ($is_hide) { $show_item_id = celerity_generate_unique_node_id(); - $show_tiles_id = celerity_generate_unique_node_id(); + $hide_item_id = celerity_generate_unique_node_id(); $show_item = id(new PhabricatorMenuItemView()) ->setName(pht('Show More Applications')) @@ -90,18 +90,12 @@ abstract class PhabricatorDirectoryController extends PhabricatorController { $hide_item = id(new PhabricatorMenuItemView()) ->setName(pht('Show Fewer Applications')) ->setHref('#') + ->setStyle('display: none') + ->setID($hide_item_id) ->addSigil('home-hide-applications'); $nav->addMenuItem($show_item); - $nav->addCustomBlock( - hsprintf( - '
')); } } diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php index 56fdbbf38b..8a9f486644 100644 --- a/src/applications/files/storage/PhabricatorFile.php +++ b/src/applications/files/storage/PhabricatorFile.php @@ -271,7 +271,7 @@ final class PhabricatorFile extends PhabricatorFileDAO } - public static function newFromFileDownload($uri, $name) { + public static function newFromFileDownload($uri, array $params) { $uri = new PhutilURI($uri); $protocol = $uri->getProtocol(); @@ -286,12 +286,11 @@ final class PhabricatorFile extends PhabricatorFileDAO $timeout = 5; - $file_data = HTTPSFuture::loadContent($uri, $timeout); - if ($file_data === false) { - return null; - } + list($file_data) = id(new HTTPSFuture($uri)) + ->setTimeout($timeout) + ->resolvex(); - return self::newFromFileData($file_data, array('name' => $name)); + return self::newFromFileData($file_data, $params); } public static function normalizeFileName($file_name) { diff --git a/src/applications/macro/storage/PhabricatorFileImageMacro.php b/src/applications/macro/storage/PhabricatorFileImageMacro.php index 2575ffe3e2..9c59f9699f 100644 --- a/src/applications/macro/storage/PhabricatorFileImageMacro.php +++ b/src/applications/macro/storage/PhabricatorFileImageMacro.php @@ -19,21 +19,6 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO PhabricatorPHIDConstants::PHID_TYPE_MCRO); } - static public function newFromImageURI($uri, $file_name, $image_macro_name) { - $file = PhabricatorFile::newFromFileDownload($uri, $file_name); - - if (!$file) { - return null; - } - - $image_macro = new PhabricatorFileImageMacro(); - $image_macro->setName($image_macro_name); - $image_macro->setFilePHID($file->getPHID()); - $image_macro->save(); - - return $image_macro; - } - public function isAutomaticallySubscribed($phid) { return false; } diff --git a/src/applications/maniphest/controller/ManiphestTaskListController.php b/src/applications/maniphest/controller/ManiphestTaskListController.php index a51951a4de..3f89a567a6 100644 --- a/src/applications/maniphest/controller/ManiphestTaskListController.php +++ b/src/applications/maniphest/controller/ManiphestTaskListController.php @@ -330,8 +330,8 @@ final class ManiphestTaskListController extends ManiphestController { $group = $query->getParameter('group'); $order = $query->getParameter('order'); $is_draggable = - ($group == 'priority') || - ($group == 'none' && $order == 'priority'); + ($order == 'priority') && + ($group == 'none' || $group == 'priority'); $lists = new AphrontNullView(); $lists->appendChild(''.
phutil_escape_html($example_string).
''))
- ->appendChild(
- id(new AphrontFormRadioButtonControl())
- ->setLabel('Symbol Links')
- ->setName($pref_symbols)
- ->setValue($pref_symbols_value ? $pref_symbols_value : 'enabled')
- ->addButton('enabled', 'Enabled (default)',
- 'Use this setting to disable linking symbol names in Differential '.
- 'and Diffusion to their definitions. This is enabled by default.')
- ->addButton('disabled', 'Disabled', null))
->appendChild(
id(new AphrontFormRadioButtonControl())
->setLabel('Monospaced Textareas')
diff --git a/src/applications/settings/panel/PhabricatorSettingsPanelProfile.php b/src/applications/settings/panel/PhabricatorSettingsPanelProfile.php
index 0ade8c291a..358ab27438 100644
--- a/src/applications/settings/panel/PhabricatorSettingsPanelProfile.php
+++ b/src/applications/settings/panel/PhabricatorSettingsPanelProfile.php
@@ -46,42 +46,57 @@ final class PhabricatorSettingsPanelProfile
$user->setTranslation($request->getStr('translation'));
$default_image = $request->getExists('default_image');
+ $gravatar_email = $request->getStr('gravatar');
if ($default_image) {
$profile->setProfileImagePHID(null);
$user->setProfileImagePHID(null);
- } else if (!empty($_FILES['image'])) {
- $err = idx($_FILES['image'], 'error');
- if ($err != UPLOAD_ERR_NO_FILE) {
+ } else if (!empty($gravatar_email) || $request->getFileExists('image')) {
+ $file = null;
+ if (!empty($gravatar_email)) {
+ // These steps recommended by:
+ // https://en.gravatar.com/site/implement/hash/
+ $trimmed = trim($gravatar_email);
+ $lower_cased = strtolower($trimmed);
+ $hash = md5($lower_cased);
+ $url = 'http://www.gravatar.com/avatar/'.($hash).'?s=200';
+ $file = PhabricatorFile::newFromFileDownload(
+ $url,
+ array(
+ 'name' => 'gravatar',
+ 'authorPHID' => $user->getPHID(),
+ ));
+ } else if ($request->getFileExists('image')) {
$file = PhabricatorFile::newFromPHPUpload(
$_FILES['image'],
array(
'authorPHID' => $user->getPHID(),
));
- $okay = $file->isTransformableImage();
- if ($okay) {
- $xformer = new PhabricatorImageTransformer();
+ }
- // Generate the large picture for the profile page.
- $large_xformed = $xformer->executeProfileTransform(
- $file,
- $width = 280,
- $min_height = 140,
- $max_height = 420);
- $profile->setProfileImagePHID($large_xformed->getPHID());
+ $okay = $file->isTransformableImage();
+ if ($okay) {
+ $xformer = new PhabricatorImageTransformer();
- // Generate the small picture for comments, etc.
- $small_xformed = $xformer->executeProfileTransform(
- $file,
- $width = 50,
- $min_height = 50,
- $max_height = 50);
- $user->setProfileImagePHID($small_xformed->getPHID());
- } else {
- $e_image = 'Not Supported';
- $errors[] =
- 'This server only supports these image formats: '.
- implode(', ', $supported_formats).'.';
- }
+ // Generate the large picture for the profile page.
+ $large_xformed = $xformer->executeProfileTransform(
+ $file,
+ $width = 280,
+ $min_height = 140,
+ $max_height = 420);
+ $profile->setProfileImagePHID($large_xformed->getPHID());
+
+ // Generate the small picture for comments, etc.
+ $small_xformed = $xformer->executeProfileTransform(
+ $file,
+ $width = 50,
+ $min_height = 50,
+ $max_height = 50);
+ $user->setProfileImagePHID($small_xformed->getPHID());
+ } else {
+ $e_image = 'Not Supported';
+ $errors[] =
+ 'This server only supports these image formats: '.
+ implode(', ', $supported_formats).'.';
}
}
@@ -190,6 +205,12 @@ final class PhabricatorSettingsPanelProfile
->setName('image')
->setError($e_image)
->setCaption('Supported formats: '.implode(', ', $supported_formats)))
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel('Import Gravatar')
+ ->setName('gravatar')
+ ->setError($e_image)
+ ->setCaption('Enter gravatar email address'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save')
diff --git a/src/applications/settings/storage/PhabricatorUserPreferences.php b/src/applications/settings/storage/PhabricatorUserPreferences.php
index 4338e1ef61..9f5196a215 100644
--- a/src/applications/settings/storage/PhabricatorUserPreferences.php
+++ b/src/applications/settings/storage/PhabricatorUserPreferences.php
@@ -18,11 +18,13 @@ final class PhabricatorUserPreferences extends PhabricatorUserDAO {
const PREFERENCE_SEARCH_SHORTCUT = 'search-shortcut';
const PREFERENCE_DIFFUSION_VIEW = 'diffusion-view';
- const PREFERENCE_DIFFUSION_SYMBOLS = 'diffusion-symbols';
+ const PREFERENCE_NAV_COLLAPSED = 'nav-collapsed';
const PREFERENCE_NAV_WIDTH = 'nav-width';
const PREFERENCE_APP_TILES = 'app-tiles';
+ const PREFERENCE_DIFF_FILETREE = 'diff-filetree';
+
protected $userPHID;
protected $preferences = array();
diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
index 7a3d07fd77..349bb3c453 100644
--- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
+++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
@@ -153,25 +153,20 @@ abstract class PhabricatorApplicationTransactionEditor
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
- case PhabricatorTransactions::TYPE_COMMENT:
- break;
case PhabricatorTransactions::TYPE_VIEW_POLICY:
$object->setViewPolicy($xaction->getNewValue());
break;
case PhabricatorTransactions::TYPE_EDIT_POLICY:
$object->setEditPolicy($xaction->getNewValue());
break;
- default:
- return $this->applyCustomInternalTransaction($object, $xaction);
}
+ return $this->applyCustomInternalTransaction($object, $xaction);
}
private function applyExternalEffects(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
- case PhabricatorTransactions::TYPE_COMMENT:
- break;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$subeditor = id(new PhabricatorSubscriptionsEditor())
->setObject($object)
@@ -179,9 +174,8 @@ abstract class PhabricatorApplicationTransactionEditor
->subscribeExplicit($xaction->getNewValue())
->save();
break;
- default:
- return $this->applyCustomExternalTransaction($object, $xaction);
}
+ return $this->applyCustomExternalTransaction($object, $xaction);
}
protected function applyCustomInternalTransaction(
diff --git a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleImageMacro.php b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleImageMacro.php
index db784f1169..eb048f8c4c 100644
--- a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleImageMacro.php
+++ b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleImageMacro.php
@@ -34,7 +34,7 @@ final class PhabricatorRemarkupRuleImageMacro
if ($file) {
$src_uri = $file->getBestURI();
$file_data = $file->getMetadata();
- $height = idx($file_data,PhabricatorFile::METADATA_IMAGE_HEIGHT);
+ $height = idx($file_data, PhabricatorFile::METADATA_IMAGE_HEIGHT);
$width = idx($file_data, PhabricatorFile::METADATA_IMAGE_WIDTH);
if ($height && $width) {
$style = sprintf(
diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
index 9c1dee01f2..71dbe66291 100644
--- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -1097,6 +1097,14 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'type' => 'sql',
'name' => $this->getPatchPath('20130127.altheraldtranscript.sql'),
),
+ '20130201.revisionunsubscribed.php' => array(
+ 'type' => 'php',
+ 'name' => $this->getPatchPath('20130201.revisionunsubscribed.php'),
+ ),
+ '20130201.revisionunsubscribed.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('20130201.revisionunsubscribed.sql'),
+ ),
);
}
diff --git a/src/view/form/control/AphrontFormImageControl.php b/src/view/form/control/AphrontFormImageControl.php
index 0953eabbf1..ba2adb2c92 100644
--- a/src/view/form/control/AphrontFormImageControl.php
+++ b/src/view/form/control/AphrontFormImageControl.php
@@ -15,7 +15,6 @@ final class AphrontFormImageControl extends AphrontFormControl {
array(
'type' => 'file',
'name' => $this->getName(),
- 'class' => 'image',
)).
'