@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge profile "About" into main profile and simplify some custom field stuff

Summary:
Ref T1703. Drive "user since" with a custom field and make the other fields render into a property list.

Users can make their profiles a little more personal/obnoxious now.

Also delete a bunch of code.

Test Plan: {F49415}

Reviewers: chad, btrahan

Reviewed By: chad

CC: aran

Maniphest Tasks: T1703

Differential Revision: https://secure.phabricator.com/D6401

+196 -105
+2
src/__phutil_library_map__.php
··· 1616 1616 'PhabricatorUserRealNameField' => 'applications/people/customfield/PhabricatorUserRealNameField.php', 1617 1617 'PhabricatorUserSSHKey' => 'applications/settings/storage/PhabricatorUserSSHKey.php', 1618 1618 'PhabricatorUserSearchIndexer' => 'applications/people/search/PhabricatorUserSearchIndexer.php', 1619 + 'PhabricatorUserSinceField' => 'applications/people/customfield/PhabricatorUserSinceField.php', 1619 1620 'PhabricatorUserStatus' => 'applications/people/storage/PhabricatorUserStatus.php', 1620 1621 'PhabricatorUserStatusInvalidEpochException' => 'applications/people/exception/PhabricatorUserStatusInvalidEpochException.php', 1621 1622 'PhabricatorUserStatusOverlapException' => 'applications/people/exception/PhabricatorUserStatusOverlapException.php', ··· 3568 3569 'PhabricatorUserRealNameField' => 'PhabricatorUserCustomField', 3569 3570 'PhabricatorUserSSHKey' => 'PhabricatorUserDAO', 3570 3571 'PhabricatorUserSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 3572 + 'PhabricatorUserSinceField' => 'PhabricatorUserCustomField', 3571 3573 'PhabricatorUserStatus' => 'PhabricatorUserDAO', 3572 3574 'PhabricatorUserStatusInvalidEpochException' => 'Exception', 3573 3575 'PhabricatorUserStatusOverlapException' => 'Exception',
+1
src/applications/people/config/PhabricatorUserConfigOptions.php
··· 16 16 $default = array( 17 17 id(new PhabricatorUserRealNameField())->getFieldKey() => true, 18 18 id(new PhabricatorUserTitleField())->getFieldKey() => true, 19 + id(new PhabricatorUserSinceField())->getFieldKey() => true, 19 20 id(new PhabricatorUserBlurbField())->getFieldKey() => true, 20 21 ); 21 22
+17 -66
src/applications/people/controller/PhabricatorPeopleProfileController.php
··· 5 5 6 6 private $username; 7 7 private $page; 8 - private $profileUser; 9 8 10 9 public function shouldRequireAdmin() { 11 10 // Default for people app is true ··· 18 17 $this->page = idx($data, 'page'); 19 18 } 20 19 21 - public function getProfileUser() { 22 - return $this->profileUser; 23 - } 24 - 25 20 private function getMainFilters($username) { 26 21 return array( 27 22 array( ··· 29 24 'name' => pht('Feed'), 30 25 'href' => '/p/'.$username.'/feed/' 31 26 ), 32 - array( 33 - 'key' => 'about', 34 - 'name' => pht('About'), 35 - 'href' => '/p/'.$username.'/about/' 36 - ) 37 27 ); 38 28 } 39 29 ··· 48 38 return new Aphront404Response(); 49 39 } 50 40 51 - $this->profileUser = $user; 52 - 53 41 require_celerity_resource('phabricator-profile-css'); 54 42 55 43 $profile = $user->loadUserProfile(); ··· 76 64 77 65 $this->page = $nav->selectFilter($this->page, 'feed'); 78 66 79 - switch ($this->page) { 80 - case 'feed': 81 - $content = $this->renderUserFeed($user); 82 - break; 83 - case 'about': 84 - $content = $this->renderBasicInformation($user, $profile); 85 - break; 86 - default: 87 - throw new Exception("Unknown page '{$this->page}'!"); 88 - } 67 + $content = $this->renderUserFeed($user); 89 68 90 69 $picture = $user->loadProfileImageURI(); 91 70 ··· 133 112 ->setHref($this->getApplicationURI('edit/'.$user->getID().'/'))); 134 113 } 135 114 115 + $properties = $this->buildPropertyView($user); 116 + 136 117 $nav->appendChild($header); 137 118 $nav->appendChild($actions); 119 + $nav->appendChild($properties); 138 120 $nav->appendChild($content); 139 121 140 122 return $this->buildApplicationPage( ··· 146 128 )); 147 129 } 148 130 149 - private function renderBasicInformation($user, $profile) { 131 + private function buildPropertyView(PhabricatorUser $user) { 132 + $viewer = $this->getRequest()->getUser(); 150 133 151 - $blurb = nonempty( 152 - $profile->getBlurb(), 153 - '//'.pht('Nothing is known about this rare specimen.').'//'); 134 + $view = id(new PhabricatorPropertyListView()) 135 + ->setUser($viewer) 136 + ->setObject($user); 154 137 155 - $viewer = $this->getRequest()->getUser(); 138 + $fields = PhabricatorCustomField::getObjectFields( 139 + $user, 140 + PhabricatorCustomField::ROLE_VIEW); 156 141 157 - $engine = PhabricatorMarkupEngine::newProfileMarkupEngine(); 158 - $engine->setConfig('viewer', $viewer); 159 - $blurb = $engine->markupText($blurb); 142 + foreach ($fields as $field) { 143 + $field->setViewer($viewer); 144 + } 160 145 161 - $content = hsprintf( 162 - '<div class="phabricator-profile-info-group profile-wrap-responsive"> 163 - <h1 class="phabricator-profile-info-header">%s</h1> 164 - <div class="phabricator-profile-info-pane"> 165 - <table class="phabricator-profile-info-table"> 166 - <tr> 167 - <th>%s</th> 168 - <td>%s</td> 169 - </tr> 170 - <tr> 171 - <th>%s</th> 172 - <td>%s</td> 173 - </tr> 174 - </table> 175 - </div> 176 - </div>'. 177 - '<div class="phabricator-profile-info-group profile-wrap-responsive"> 178 - <h1 class="phabricator-profile-info-header">%s</h1> 179 - <div class="phabricator-profile-info-pane"> 180 - <table class="phabricator-profile-info-table"> 181 - <tr> 182 - <th>%s</th> 183 - <td>%s</td> 184 - </tr> 185 - </table> 186 - </div> 187 - </div>', 188 - pht('Basic Information'), 189 - pht('PHID'), 190 - $user->getPHID(), 191 - pht('User Since'), 192 - phabricator_datetime($user->getDateCreated(), $viewer), 193 - pht('Flavor Text'), 194 - pht('Blurb'), 195 - $blurb); 146 + $view->applyCustomFields($fields); 196 147 197 - return $content; 148 + return $view; 198 149 } 199 150 200 151 private function renderUserFeed(PhabricatorUser $user) {
+1 -1
src/applications/people/controller/PhabricatorPeopleProfileEditController.php
··· 34 34 35 35 $fields = PhabricatorCustomField::getObjectFields( 36 36 $user, 37 - PhabricatorUserCustomFieldInterface::ROLE_EDIT); 37 + PhabricatorCustomField::ROLE_EDIT); 38 38 39 39 if ($request->isFormPost()) { 40 40 $xactions = array();
+28 -1
src/applications/people/customfield/PhabricatorUserBlurbField.php
··· 17 17 return pht('Short blurb about the user.'); 18 18 } 19 19 20 - public function canDisableField() { 20 + public function shouldAppearInApplicationTransactions() { 21 + return true; 22 + } 23 + 24 + public function shouldAppearInEditView() { 25 + return true; 26 + } 27 + 28 + public function shouldAppearInPropertyView() { 21 29 return true; 22 30 } 23 31 ··· 47 55 ->setName($this->getFieldKey()) 48 56 ->setValue($this->value) 49 57 ->setLabel($this->getFieldName()); 58 + } 59 + 60 + public function renderPropertyViewLabel() { 61 + return null; 62 + } 63 + 64 + public function renderPropertyViewValue() { 65 + $blurb = $this->getObject()->loadUserProfile()->getBlurb(); 66 + if (!strlen($blurb)) { 67 + return null; 68 + } 69 + return PhabricatorMarkupEngine::renderOneObject( 70 + id(new PhabricatorMarkupOneOff())->setContent($blurb), 71 + 'default', 72 + $this->getViewer()); 73 + } 74 + 75 + public function getStyleForPropertyView() { 76 + return 'block'; 50 77 } 51 78 52 79 }
-24
src/applications/people/customfield/PhabricatorUserCustomField.php
··· 5 5 implements PhabricatorUserCustomFieldInterface { 6 6 7 7 8 - public function shouldEnableForRole($role) { 9 - switch ($role) { 10 - case PhabricatorUserCustomFieldInterface::ROLE_EDIT: 11 - return $this->shouldAppearOnProfileEdit(); 12 - } 13 - return parent::shouldEnableForRole($role); 14 - } 15 - 16 - public function shouldAppearOnProfileEdit() { 17 - return true; 18 - } 19 - 20 - 21 - /* -( PhabricatorCustomField )--------------------------------------------- */ 22 - 23 - 24 - public function canDisableField() { 25 - return false; 26 - } 27 - 28 - public function shouldAppearInApplicationTransactions() { 29 - return true; 30 - } 31 - 32 8 }
-3
src/applications/people/customfield/PhabricatorUserCustomFieldInterface.php
··· 2 2 3 3 interface PhabricatorUserCustomFieldInterface { 4 4 5 - const ROLE_EDIT = 'user.edit'; 6 - 7 - public function shouldAppearOnProfileEdit(); 8 5 9 6 }
+12
src/applications/people/customfield/PhabricatorUserRealNameField.php
··· 17 17 return pht('Stores the real name of the user, like "Abraham Lincoln".'); 18 18 } 19 19 20 + public function canDisableField() { 21 + return false; 22 + } 23 + 24 + public function shouldAppearInApplicationTransactions() { 25 + return true; 26 + } 27 + 28 + public function shouldAppearInEditView() { 29 + return true; 30 + } 31 + 20 32 protected function didSetObject(PhabricatorCustomFieldInterface $object) { 21 33 $this->value = $object->getRealName(); 22 34 }
+30
src/applications/people/customfield/PhabricatorUserSinceField.php
··· 1 + <?php 2 + 3 + final class PhabricatorUserSinceField 4 + extends PhabricatorUserCustomField { 5 + 6 + private $value; 7 + 8 + public function getFieldKey() { 9 + return 'user:since'; 10 + } 11 + 12 + public function getFieldName() { 13 + return pht('User Since'); 14 + } 15 + 16 + public function getFieldDescription() { 17 + return pht('Shows user join date.'); 18 + } 19 + 20 + public function shouldAppearInPropertyView() { 21 + return true; 22 + } 23 + 24 + public function renderPropertyViewValue() { 25 + return phabricator_datetime( 26 + $this->getObject()->getDateCreated(), 27 + $this->getViewer()); 28 + } 29 + 30 + }
+12
src/applications/people/customfield/PhabricatorUserTitleField.php
··· 17 17 return pht('User title, like "CEO" or "Assistant to the Manager".'); 18 18 } 19 19 20 + public function canDisableField() { 21 + return false; 22 + } 23 + 24 + public function shouldAppearInApplicationTransactions() { 25 + return true; 26 + } 27 + 28 + public function shouldAppearInEditView() { 29 + return true; 30 + } 31 + 20 32 protected function didSetObject(PhabricatorCustomFieldInterface $object) { 21 33 $this->value = $object->loadUserProfile()->getTitle(); 22 34 }
+68 -1
src/infrastructure/customfield/field/PhabricatorCustomField.php
··· 7 7 * @task storage Field Storage 8 8 * @task appsearch Integration with ApplicationSearch 9 9 * @task appxaction Integration with ApplicationTransactions 10 + * @task edit Integration with edit views 11 + * @task view Integration with property views 12 + * @task list Integration with list views 10 13 */ 11 14 abstract class PhabricatorCustomField { 12 15 ··· 17 20 const ROLE_APPLICATIONSEARCH = 'ApplicationSearch'; 18 21 const ROLE_STORAGE = 'storage'; 19 22 const ROLE_DEFAULT = 'default'; 23 + const ROLE_EDIT = 'edit'; 24 + const ROLE_VIEW = 'view'; 25 + const ROLE_LIST = 'list'; 20 26 21 27 22 28 /* -( Building Applications with Custom Fields )--------------------------- */ ··· 219 225 return $this->shouldAppearInApplicationSearch(); 220 226 case self::ROLE_STORAGE: 221 227 return ($this->getStorageKey() !== null); 228 + case self::ROLE_EDIT: 229 + return $this->shouldAppearInEditView(); 230 + case self::ROLE_VIEW: 231 + return $this->shouldAppearInPropertyView(); 232 + case self::ROLE_LIST: 233 + return $this->shouldAppearInListView(); 222 234 case self::ROLE_DEFAULT: 223 235 return true; 224 236 default: ··· 605 617 /** 606 618 * @task edit 607 619 */ 608 - public function shouldAppearOnEditView() { 620 + public function shouldAppearInEditView() { 609 621 return false; 610 622 } 611 623 ··· 624 636 public function renderEditControl() { 625 637 throw new PhabricatorCustomFieldImplementationIncompleteException($this); 626 638 } 639 + 640 + 641 + /* -( Property View )------------------------------------------------------ */ 642 + 643 + 644 + /** 645 + * @task view 646 + */ 647 + public function shouldAppearInPropertyView() { 648 + return false; 649 + } 650 + 651 + 652 + /** 653 + * @task view 654 + */ 655 + public function renderPropertyViewLabel() { 656 + return $this->getFieldName(); 657 + } 658 + 659 + 660 + /** 661 + * @task view 662 + */ 663 + public function renderPropertyViewValue() { 664 + throw new PhabricatorCustomFieldImplementationIncompleteException($this); 665 + } 666 + 667 + 668 + /** 669 + * @task view 670 + */ 671 + public function getStyleForPropertyView() { 672 + return 'property'; 673 + } 674 + 675 + 676 + /* -( List View )---------------------------------------------------------- */ 677 + 678 + 679 + /** 680 + * @task list 681 + */ 682 + public function shouldAppearInListView() { 683 + return false; 684 + } 685 + 686 + 687 + /** 688 + * @task list 689 + */ 690 + public function renderOnListItem(PhabricatorObjectItemView $view) { 691 + throw new PhabricatorCustomFieldImplementationIncompleteException($this); 692 + } 693 + 627 694 628 695 629 696 }
-9
src/infrastructure/markup/PhabricatorMarkupEngine.php
··· 349 349 /** 350 350 * @task engine 351 351 */ 352 - public static function newProfileMarkupEngine() { 353 - return self::newMarkupEngine(array( 354 - )); 355 - } 356 - 357 - 358 - /** 359 - * @task engine 360 - */ 361 352 public static function newSlowvoteMarkupEngine() { 362 353 return self::newMarkupEngine(array( 363 354 ));
+25
src/view/layout/PhabricatorPropertyListView.php
··· 81 81 $this->invokedWillRenderEvent = true; 82 82 } 83 83 84 + public function applyCustomFields(array $fields) { 85 + assert_instances_of($fields, 'PhabricatorCustomField'); 84 86 87 + foreach ($fields as $field) { 88 + $label = $field->renderPropertyViewLabel(); 89 + $value = $field->renderPropertyViewValue(); 90 + if ($value !== null) { 91 + switch ($field->getStyleForPropertyView()) { 92 + case 'property': 93 + $this->addProperty($label, $value); 94 + break; 95 + case 'block': 96 + $this->invokeWillRenderEvent(); 97 + if ($label !== null) { 98 + $this->addSectionHeader($label); 99 + } 100 + $this->addTextContent($value); 101 + break; 102 + default: 103 + throw new Exception( 104 + "Unknown field property view style; valid styles are ". 105 + "'block' and 'property'."); 106 + } 107 + } 108 + } 109 + } 85 110 86 111 public function render() { 87 112 $this->invokeWillRenderEvent();