From 418cdfc15174917ea00ed820ae4b96d15ae7db96 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 31 Jan 2023 01:13:53 -0800 Subject: [PATCH] CRM_Core_Menu - Add helper method, `isPublicRoute($path)`. --- CRM/Core/Menu.php | 39 +++++++++++++++++++++++++++++ tests/phpunit/CRM/Core/MenuTest.php | 5 ++++ 2 files changed, 44 insertions(+) diff --git a/CRM/Core/Menu.php b/CRM/Core/Menu.php index d22073f07b..1f9b8c123b 100644 --- a/CRM/Core/Menu.php +++ b/CRM/Core/Menu.php @@ -280,6 +280,44 @@ class CRM_Core_Menu { self::buildAdminLinks($menu); } + /** + * Determine whether a route should canonically use a frontend or backend UI. + * + * @param string $path + * Ex: 'civicrm/contribute/transact' + * @return bool + * TRUE if the route is marked with 'is_public=1'. + * @internal + * We may wish to revise the metadata to allow more distinctions. In that case, `isPublicRoute()` + * would probably get replaced by something else. + */ + public static function isPublicRoute(string $path): bool { + // A page-view may include hundreds of links - so don't hit DB for every link. Use cache. + // In default+demo builds, the list of public routes is much smaller than the list of + // private routes (roughly 1:10; ~50 entries vs ~450 entries). Cache the smaller list. + $cache = Civi::cache('long'); + $index = $cache->get('PublicRouteIndex'); + if ($index === NULL) { + $routes = CRM_Core_DAO::executeQuery('SELECT id, path FROM civicrm_menu WHERE is_public = 1') + ->fetchMap('id', 'path'); + if (empty($routes)) { + Civi::log()->warning('isPublicRoute() should not be called before the menu has been built.'); + return FALSE; + } + $index = array_fill_keys(array_values($routes), TRUE); + $cache->set('PublicRouteIndex', $index); + } + + $parts = explode('/', $path); + while (count($parts) > 1) { + if (isset($index[implode('/', $parts)])) { + return TRUE; + } + array_pop($parts); + } + return FALSE; + } + /** * This function recomputes menu from xml and populates civicrm_menu. * @@ -291,6 +329,7 @@ class CRM_Core_Menu { $query = 'TRUNCATE civicrm_menu'; CRM_Core_DAO::executeQuery($query); } + Civi::cache('long')->delete('PublicRouteIndex'); $menuArray = self::items($truncate); self::build($menuArray); diff --git a/tests/phpunit/CRM/Core/MenuTest.php b/tests/phpunit/CRM/Core/MenuTest.php index a018420776..c70023a091 100644 --- a/tests/phpunit/CRM/Core/MenuTest.php +++ b/tests/phpunit/CRM/Core/MenuTest.php @@ -135,4 +135,9 @@ class CRM_Core_MenuTest extends CiviUnitTestCase { $this->assertEquals($expectedArray, $actual); } + public function testIsPublicRoute(): void { + $this->assertEquals(FALSE, \CRM_Core_Menu::isPublicRoute('civicrm/contribute')); + $this->assertEquals(TRUE, \CRM_Core_Menu::isPublicRoute('civicrm/contribute/transact')); + } + } -- 2.25.1