Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(dev/core#4433) WordPress::url() - By default, choose frontend or backend based on route #25476

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions CRM/Core/Menu.php
Expand Up @@ -280,6 +280,33 @@ public static function build(&$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'.
*/
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);
}
return isset($index[$path]);
}

/**
* This function recomputes menu from xml and populates civicrm_menu.
*
Expand All @@ -291,6 +318,7 @@ public static function store($truncate = TRUE) {
$query = 'TRUNCATE civicrm_menu';
CRM_Core_DAO::executeQuery($query);
}
Civi::cache('long')->delete('PublicRouteIndex');
$menuArray = self::items($truncate);

self::build($menuArray);
Expand Down
1 change: 1 addition & 0 deletions CRM/Core/xml/Menu/Misc.xml
Expand Up @@ -129,6 +129,7 @@
<path>civicrm/asset/builder</path>
<page_callback>\Civi\Core\AssetBuilder::pageRun</page_callback>
<access_arguments>*always allow*</access_arguments>
<is_public>1</is_public>
</item>
<item>
<path>civicrm/contribute/ajax/tableview</path>
Expand Down
4 changes: 4 additions & 0 deletions CRM/Utils/System/Base.php
Expand Up @@ -111,6 +111,10 @@ public function postURL($action) {
/**
* Generate the url string to a CiviCRM path.
*
* Note: The options `$frontend` and `$forceBackend` are opposites. If you use exactly one (and not
* the other), then the URL will follow your request. If you leave the default values, or if you
* give incompatible values, then we will use the route's preferred default (from `civicrm_menu.is_public`).
*
* @param string $path
* The path being linked to, such as "civicrm/add".
* @param string $query
Expand Down
11 changes: 11 additions & 0 deletions CRM/Utils/System/WordPress.php
Expand Up @@ -313,6 +313,17 @@ public function url(
$this->loadBootStrap();
}

// If caller didn't express a clear preference for frontend xor backend, then use default.
// Aside: I definitely find it confusing that this decision is spread across two variables.
if ($frontend === $forceBackend) {
if (CRM_Core_Menu::isPublicRoute($path)) {
$frontend = TRUE;
}
else {
$forceBackend = TRUE;
}
}

// When on the front-end.
if ($config->userFrameworkFrontend) {

Expand Down
5 changes: 5 additions & 0 deletions tests/phpunit/CRM/Core/MenuTest.php
Expand Up @@ -135,4 +135,9 @@ public function testGetArrayForPathArgs($inputString, $expectedArray) {
$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'));
}

}