Merge pull request #13345 from GinkgoFJG/generic-settings-form
[civicrm-core.git] / CRM / Admin / Form / SettingTrait.php
index bbc755092621ec79714e44f1b2f8f4bd1ce817e9..f124ef72e65aec4fd41dd6c3853d181fd1f0fb47 100644 (file)
  */
 trait CRM_Admin_Form_SettingTrait {
 
+  /**
+   * The setting page filter.
+   *
+   * @var string
+   */
+  private $_filter;
+
   /**
    * @var array
    */
@@ -118,6 +125,44 @@ trait CRM_Admin_Form_SettingTrait {
     return CRM_Utils_Array::value($item, $this->getSettingsMetaData()[$setting]);
   }
 
+  /**
+   * @return string
+   */
+  protected function getSettingPageFilter() {
+    if (!isset($this->_filter)) {
+      // Get the last URL component without modifying the urlPath property.
+      $urlPath = array_values($this->urlPath);
+      $this->_filter = end($urlPath);
+    }
+    return $this->_filter;
+  }
+
+  /**
+   * Returns a re-keyed copy of the settings, ordered by weight.
+   *
+   * @return array
+   */
+  protected function getSettingsOrderedByWeight() {
+    $settingMetaData = $this->getSettingsMetaData();
+    $filter = $this->getSettingPageFilter();
+
+    usort($settingMetaData, function ($a, $b) use ($filter) {
+      // Handle cases in which a comparison is impossible. Such will be considered ties.
+      if (
+        // A comparison can't be made unless both setting weights are declared.
+        !isset($a['settings_pages'][$filter]['weight'], $b['settings_pages'][$filter]['weight'])
+        // A pair of settings might actually have the same weight.
+        || $a['settings_pages'][$filter]['weight'] === $b['settings_pages'][$filter]['weight']
+      ) {
+        return 0;
+      }
+
+      return $a['settings_pages'][$filter]['weight'] > $b['settings_pages'][$filter]['weight'] ? 1 : -1;
+    });
+
+    return $settingMetaData;
+  }
+
   /**
    * Add fields in the metadata to the template.
    */
@@ -207,7 +252,7 @@ trait CRM_Admin_Form_SettingTrait {
     // setting_description should be deprecated - see Mail.tpl for metadata based tpl.
     $this->assign('setting_descriptions', $descriptions);
     $this->assign('settings_fields', $settingMetaData);
-    $this->assign('fields', $settingMetaData);
+    $this->assign('fields', $this->getSettingsOrderedByWeight());
   }
 
   /**