Cleanup deprecated CRM_Core_BAO_Settings calls CRM-17507
[civicrm-core.git] / CRM / Core / BAO / Navigation.php
index f87a855380b518ecd303061633bb5fd2052f2fe0..0a5c7da17a8b5b45df50dbf7a165b31159d1825a 100644 (file)
@@ -337,6 +337,7 @@ ORDER BY parent_id, weight";
 
     // run the Navigation  through a hook so users can modify it
     CRM_Utils_Hook::navigationMenu($navigations);
+    self::fixNavigationMenu($navigations);
 
     $i18n = CRM_Core_I18n::singleton();
 
@@ -463,6 +464,51 @@ ORDER BY parent_id, weight";
     return $navigationString;
   }
 
+  /**
+   * Given a navigation menu, generate navIDs for any items which are
+   * missing them.
+   *
+   * @param array $nodes
+   *   Each key is a numeral; each value is a node in
+   *   the menu tree (with keys "child" and "attributes").
+   */
+  public static function fixNavigationMenu(&$nodes) {
+    $maxNavID = 1;
+    array_walk_recursive($nodes, function($item, $key) use (&$maxNavID) {
+      if ($key === 'navID') {
+        $maxNavID = max($maxNavID, $item);
+      }
+    });
+    self::_fixNavigationMenu($nodes, $maxNavID, NULL);
+  }
+
+  /**
+   * @param array $nodes
+   *   Each key is a numeral; each value is a node in
+   *   the menu tree (with keys "child" and "attributes").
+   * @param int $maxNavID
+   * @param int $parentID
+   */
+  private static function _fixNavigationMenu(&$nodes, &$maxNavID, $parentID) {
+    $origKeys = array_keys($nodes);
+    foreach ($origKeys as $origKey) {
+      if (!isset($nodes[$origKey]['attributes']['parentID']) && $parentID !== NULL) {
+        $nodes[$origKey]['attributes']['parentID'] = $parentID;
+      }
+      // If no navID, then assign navID and fix key.
+      if (!isset($nodes[$origKey]['attributes']['navID'])) {
+        $newKey = ++$maxNavID;
+        $nodes[$origKey]['attributes']['navID'] = $newKey;
+        $nodes[$newKey] = $nodes[$origKey];
+        unset($nodes[$origKey]);
+        $origKey = $newKey;
+      }
+      if (isset($nodes[$origKey]['child']) && is_array($nodes[$origKey]['child'])) {
+        self::_fixNavigationMenu($nodes[$origKey]['child'], $maxNavID, $nodes[$origKey]['attributes']['navID']);
+      }
+    }
+  }
+
   /**
    * Get Menu name.
    *
@@ -515,6 +561,9 @@ ORDER BY parent_id, weight";
         }
         $url = CRM_Utils_System::url($urlParam[0], $urlParam[1], FALSE, NULL, TRUE);
       }
+      elseif (strpos($url, '&') === FALSE) {
+        $url = htmlspecialchars($url);
+      }
       $makeLink = TRUE;
     }
 
@@ -567,6 +616,7 @@ ORDER BY parent_id, weight";
     }
 
     if ($makeLink) {
+      $url = CRM_Utils_System::evalUrl($url);
       if ($target) {
         $name = "<a href=\"{$url}\" target=\"{$target}\">{$name}</a>";
       }
@@ -866,7 +916,7 @@ ORDER BY parent_id, weight";
         "compid={$component_id}&reset=1", $reports_nav->id, $permission, $domain_id, TRUE);
       foreach ($component['reports'] as $report_id => $report) {
         // Create or update the report instance links.
-        $report_nav = self::createOrUpdateReportNavItem($report['title'], $report['url'], 'reset=1', $component_nav->id, $report['permission'], $domain_id);
+        $report_nav = self::createOrUpdateReportNavItem($report['title'], $report['url'], 'reset=1', $component_nav->id, $report['permission'], $domain_id, FALSE, TRUE);
         // Update the report instance to include the navigation id.
         $query = "UPDATE civicrm_report_instance SET navigation_id = %1 WHERE id = %2";
         $params = array(
@@ -878,7 +928,7 @@ ORDER BY parent_id, weight";
     }
 
     // Create or update the All Reports link.
-    self::createOrUpdateReportNavItem('All Reports', 'civicrm/report/list', 'reset=1', $reports_nav->id, 'access CiviReport', $domain_id);
+    self::createOrUpdateReportNavItem('All Reports', 'civicrm/report/list', 'reset=1', $reports_nav->id, 'access CiviReport', $domain_id, TRUE);
   }
 
   /**
@@ -908,6 +958,9 @@ ORDER BY parent_id, weight";
   /**
    * Retrieve a navigation item using it's url.
    *
+   * Note that we use LIKE to permit a wildcard as the calling code likely doesn't
+   * care about output params appended.
+   *
    * @param string $url
    * @param array $url_params
    *
@@ -918,8 +971,9 @@ ORDER BY parent_id, weight";
    */
   public static function getNavItemByUrl($url, $url_params, $parent_id = NULL) {
     $nav = new CRM_Core_BAO_Navigation();
-    $nav->url = "{$url}?{$url_params}";
     $nav->parent_id = $parent_id;
+    $nav->whereAdd("url LIKE '{$url}?{$url_params}'");
+
     if ($nav->find(TRUE)) {
       return $nav;
     }
@@ -988,9 +1042,10 @@ ORDER BY parent_id, weight";
    * @return \CRM_Core_DAO_Navigation
    */
   protected static function createOrUpdateReportNavItem($name, $url, $url_params, $parent_id, $permission,
-                                                        $domain_id, $onlyMatchParentID = FALSE) {
+                                                        $domain_id, $onlyMatchParentID = FALSE, $useWildcard = TRUE) {
     $id = NULL;
-    $existing_nav = CRM_Core_BAO_Navigation::getNavItemByUrl($url, $url_params, ($onlyMatchParentID ? $parent_id : NULL));
+    $existing_url_params = $useWildcard ? $url_params . '%' : $url_params;
+    $existing_nav = CRM_Core_BAO_Navigation::getNavItemByUrl($url, $existing_url_params, ($onlyMatchParentID ? $parent_id : NULL));
     if ($existing_nav) {
       $id = $existing_nav->id;
     }
@@ -1042,13 +1097,9 @@ ORDER BY parent_id, weight";
    * @return object|string
    */
   public static function getCacheKey($cid) {
-    $key = CRM_Core_BAO_Setting::getItem(
-      CRM_Core_BAO_Setting::PERSONAL_PREFERENCES_NAME,
-      'navigation',
-      NULL,
-      '',
-      $cid
-    );
+    $key = Civi::service('settings_manager')
+      ->getBagByContact(NULL, $cid)
+      ->get('navigation');
     if (strlen($key) !== self::CACHE_KEY_STRLEN) {
       $key = self::resetNavigation($cid);
     }