(DX) Civi::contactSettings - Add a facade for working with the logged-in user's settings
authorTim Otten <totten@civicrm.org>
Thu, 27 Sep 2018 21:05:06 +0000 (17:05 -0400)
committerTim Otten <totten@civicrm.org>
Thu, 27 Sep 2018 21:05:06 +0000 (17:05 -0400)
Before
------

To read/write a setting for the logged-in user, you need a snippet like this:

```php
$cid = CRM_Core_Session::getLoggedInContactID();
$myFilter = Civi::service('settings_manager')
  ->getBagByContact(NULL, $cid)
  ->get('activity_tab_filter');
```

After
-----

To read/write a setting for the logged-in user, you can use a snippet like this:

```php
$myFilter = Civi::contactSettings()->get('activity_tab_filter');
```

Technical Details
-----------------

* A convenience function like this is liable to be used in lazy circumstances where
  the developer is unlikely to check their conditions carefully. Therefore, the
  errors are reported as exceptions so that mistakes are easiliy revealed.
* This is technically a small contract change to `SettingsManager::getBagByContact()`
  because it now interprets `$contactId===NULL` as meaning "the logged-in user".
  However, I don't think NULL was a sensible value before, and this interface
  isn't widely known/used.

Civi.php
Civi/Core/SettingsManager.php
tests/phpunit/Civi/Core/CiviFacadeTest.php [new file with mode: 0644]

index 8acfdba76862963e124de00335dd48a67e58806c..90aebee174d2ead75b84dafce2047acfe23ef110 100644 (file)
--- a/Civi.php
+++ b/Civi.php
@@ -108,6 +108,22 @@ class Civi {
     return CRM_Core_Resources::singleton();
   }
 
+  /**
+   * Obtain the contact's personal settings.
+   *
+   * @param NULL|int $contactID
+   *   For the default/active user's contact, leave $domainID as NULL.
+   * @param NULL|int $domainID
+   *   For the default domain, leave $domainID as NULL.
+   * @return \Civi\Core\SettingsBag
+   * @throws CRM_Core_Exception
+   *   If there is no contact, then there's no SettingsBag, and we'll throw
+   *   an exception.
+   */
+  public static function contactSettings($contactID = NULL, $domainID = NULL) {
+    return \Civi\Core\Container::getBootService('settings_manager')->getBagByContact($domainID, $contactID);
+  }
+
   /**
    * Obtain the domain settings.
    *
index e56d723b2fbaf501a18acd9953530bd9462b872b..cca82f79dec907c1138cda0889073f9b77d467a7 100644 (file)
@@ -171,13 +171,24 @@ class SettingsManager {
 
   /**
    * @param int|NULL $domainId
+   *   For the default domain, leave $domainID as NULL.
    * @param int|NULL $contactId
+   *   For the default/active user's contact, leave $domainID as NULL.
    * @return SettingsBag
+   * @throws \CRM_Core_Exception
+   *   If there is no contact, then there's no SettingsBag, and we'll throw
+   *   an exception.
    */
   public function getBagByContact($domainId, $contactId) {
     if ($domainId === NULL) {
       $domainId = \CRM_Core_Config::domainID();
     }
+    if ($contactId === NULL) {
+      $contactId = \CRM_Core_Session::getLoggedInContactID();
+      if (!$contactId) {
+        throw new \CRM_Core_Exception("Cannot access settings subsystem - user or domain is unavailable");
+      }
+    }
 
     $key = "$domainId:$contactId";
     if (!isset($this->bagsByContact[$key])) {
diff --git a/tests/phpunit/Civi/Core/CiviFacadeTest.php b/tests/phpunit/Civi/Core/CiviFacadeTest.php
new file mode 100644 (file)
index 0000000..0f678ea
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+namespace Civi\Core;
+
+class CiviFacadeTest extends \CiviUnitTestCase {
+
+  protected $origSetting;
+
+  protected function setUp() {
+    $this->origSetting = $GLOBALS['civicrm_setting'];
+
+    parent::setUp();
+    $this->useTransaction(TRUE);
+
+    $this->mandates = array();
+  }
+
+  public function tearDown() {
+    $GLOBALS['civicrm_setting'] = $this->origSetting;
+    parent::tearDown();
+  }
+
+  /**
+   * Get the the settingsbag for a logged-in user.
+   */
+  public function testContactSettings_loggedIn() {
+    $this->createLoggedInUser();
+    $settingsBag = \Civi::contactSettings();
+    $settingsBag->set('foo', 'bar');
+    $this->assertEquals('bar', $settingsBag->get('foo'));
+  }
+
+  /**
+   * Anonymous users don't have a SettingsBag.
+   * @expectedException \CRM_Core_Exception
+   */
+  public function testContactSettings_anonFail() {
+    \Civi::contactSettings();
+  }
+
+  /**
+   * Get the SettingsBag for a specific user.
+   */
+  public function testContactSettings_byId() {
+    $cid = \CRM_Core_DAO::singleValueQuery('SELECT MIN(id) FROM civicrm_contact');
+    $settingsBag = \Civi::contactSettings($cid);
+    $settingsBag->set('foo', 'bar');
+    $this->assertEquals('bar', $settingsBag->get('foo'));
+  }
+
+}