Skip to content

Commit 48298cb

Browse files
firefox747mdmunir
authored andcommitted
Added multi app (frontend/backend) support. (#309)
* - Added multi app (frontend/backend) support. * Bugfix * Bugfix: Expanded cache key by Yii::$app->id to differenciate between apps (frontend/backend). I did not notice, that $module->getUniqueId() returns an empty string when $module is the app itself. Therefore the cache could not differenciate between frontend and backend. Thus resulting in the same routes for all indicated apps. * Filter out empty parent items. Sometimes a menu item is defined by url = # and is used as a container for sub-items. If all the subitems are forbidden then this patch removes the parent entry as well. * Bugfix: Debug bar disappeared. Thanks to yongtiger (see #309 (comment))
1 parent cbc143c commit 48298cb

File tree

3 files changed

+118
-27
lines changed

3 files changed

+118
-27
lines changed

components/Configs.php

+15-10
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
namespace mdm\admin\components;
44

55
use Yii;
6-
use yii\db\Connection;
76
use yii\caching\Cache;
8-
use yii\rbac\ManagerInterface;
9-
use yii\helpers\ArrayHelper;
7+
use yii\db\Connection;
108
use yii\di\Instance;
9+
use yii\helpers\ArrayHelper;
10+
use yii\rbac\ManagerInterface;
1111

1212
/**
1313
* Configs
14-
* Used for configure some value. To set config you can use [[\yii\base\Application::$params]]
15-
*
14+
* Used to configure some values. To set config you can use [[\yii\base\Application::$params]]
15+
*
1616
* ```
1717
* return [
18-
*
18+
*
1919
* 'mdm.admin.configs' => [
2020
* 'db' => 'customDb',
2121
* 'menuTable' => '{{%admin_menu}}',
@@ -26,9 +26,9 @@
2626
* ]
2727
* ];
2828
* ```
29-
*
29+
*
3030
* or use [[\Yii::$container]]
31-
*
31+
*
3232
* ```
3333
* Yii::$container->set('mdm\admin\components\Configs',[
3434
* 'db' => 'customDb',
@@ -94,10 +94,15 @@ class Configs extends \yii\base\Object
9494
public $strict = true;
9595

9696
/**
97-
* @var array
97+
* @var array
9898
*/
9999
public $options;
100100

101+
/**
102+
* @var array|false
103+
*/
104+
public $advanced;
105+
101106
/**
102107
* @var self Instance of self
103108
*/
@@ -106,7 +111,7 @@ class Configs extends \yii\base\Object
106111
'db' => 'yii\db\Connection',
107112
'userDb' => 'yii\db\Connection',
108113
'cache' => 'yii\caching\Cache',
109-
'authManager' => 'yii\rbac\ManagerInterface'
114+
'authManager' => 'yii\rbac\ManagerInterface',
110115
];
111116

112117
/**

components/Helper.php

+25-12
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
namespace mdm\admin\components;
44

5+
use mdm\admin\models\Route;
56
use Yii;
6-
use yii\web\User;
7-
use yii\helpers\ArrayHelper;
87
use yii\caching\TagDependency;
8+
use yii\helpers\ArrayHelper;
9+
use yii\web\User;
910

1011
/**
1112
* Description of Helper
@@ -57,7 +58,7 @@ protected static function getDefaultRoutes()
5758
}
5859
if ($cache) {
5960
$cache->set($roles, self::$_defaultRoutes, Configs::cacheDuration(), new TagDependency([
60-
'tags' => Configs::CACHE_TAG
61+
'tags' => Configs::CACHE_TAG,
6162
]));
6263
}
6364
}
@@ -87,7 +88,7 @@ public static function getRoutesByUser($userId)
8788
self::$_userRoutes[$userId] = $routes;
8889
if ($cache) {
8990
$cache->set([__METHOD__, $userId], $routes, Configs::cacheDuration(), new TagDependency([
90-
'tags' => Configs::CACHE_TAG
91+
'tags' => Configs::CACHE_TAG,
9192
]));
9293
}
9394
}
@@ -104,7 +105,7 @@ public static function getRoutesByUser($userId)
104105
public static function checkRoute($route, $params = [], $user = null)
105106
{
106107
$config = Configs::instance();
107-
$r = static::normalizeRoute($route);
108+
$r = static::normalizeRoute($route, $config->advanced);
108109
if ($config->onlyRegisteredRoute && !isset(static::getRegisteredRoutes()[$r])) {
109110
return true;
110111
}
@@ -140,18 +141,30 @@ public static function checkRoute($route, $params = [], $user = null)
140141
}
141142
}
142143

143-
protected static function normalizeRoute($route)
144+
/**
145+
* Normalize route
146+
* @param string $route Plain route string
147+
* @param boolean|array $advanced Array containing the advanced configuration. Defaults to false.
148+
* @return string Normalized route string
149+
*/
150+
protected static function normalizeRoute($route, $advanced = false)
144151
{
145152
if ($route === '') {
146-
return '/' . Yii::$app->controller->getRoute();
153+
$normalized = '/' . Yii::$app->controller->getRoute();
147154
} elseif (strncmp($route, '/', 1) === 0) {
148-
return $route;
155+
$normalized = $route;
149156
} elseif (strpos($route, '/') === false) {
150-
return '/' . Yii::$app->controller->getUniqueId() . '/' . $route;
157+
$normalized = '/' . Yii::$app->controller->getUniqueId() . '/' . $route;
151158
} elseif (($mid = Yii::$app->controller->module->getUniqueId()) !== '') {
152-
return '/' . $mid . '/' . $route;
159+
$normalized = '/' . $mid . '/' . $route;
160+
} else {
161+
$normalized = '/' . $route;
162+
}
163+
// Prefix @app-id to route.
164+
if ($advanced) {
165+
$normalized = Route::PREFIX_ADVANCED . Yii::$app->id . $normalized;
153166
}
154-
return '/' . $route;
167+
return $normalized;
155168
}
156169

157170
/**
@@ -187,7 +200,7 @@ protected static function filterRecursive($items, $user)
187200
}
188201
$item['items'] = $subItems;
189202
}
190-
if ($allow) {
203+
if ($allow && !($url == '#' && empty($item['items']))) {
191204
$result[$i] = $item;
192205
}
193206
}

models/Route.php

+78-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ class Route extends \yii\base\Object
2020
{
2121
const CACHE_TAG = 'mdm.admin.route';
2222

23+
const PREFIX_ADVANCED = '@';
24+
const PREFIX_BASIC = '/';
25+
26+
private $_routePrefix;
27+
2328
/**
2429
* Assign or remove items
2530
* @param array $routes
@@ -31,7 +36,7 @@ public function addNew($routes)
3136
foreach ($routes as $route) {
3237
try {
3338
$r = explode('&', $route);
34-
$item = $manager->createPermission('/' . trim($route, '/'));
39+
$item = $manager->createPermission($this->getPermissionName($route));
3540
if (count($r) > 1) {
3641
$action = '/' . trim($r[0], '/');
3742
if (($itemAction = $manager->getPermission($action)) === null) {
@@ -67,7 +72,7 @@ public function remove($routes)
6772
$manager = Configs::authManager();
6873
foreach ($routes as $route) {
6974
try {
70-
$item = $manager->createPermission('/' . trim($route, '/'));
75+
$item = $manager->createPermission($this->getPermissionName($route));
7176
$manager->remove($item);
7277
} catch (Exception $exc) {
7378
Yii::error($exc->getMessage(), __METHOD__);
@@ -76,17 +81,85 @@ public function remove($routes)
7681
Helper::invalidate();
7782
}
7883

84+
/**
85+
* Returns route prefix depending on the configuration.
86+
* @return string Route prefix
87+
*/
88+
public function getRoutePrefix()
89+
{
90+
if (!$this->_routePrefix) {
91+
$this->_routePrefix = Configs::instance()->advanced ? self::PREFIX_ADVANCED : self::PREFIX_BASIC;
92+
}
93+
return $this->_routePrefix;
94+
}
95+
96+
/**
97+
* Returns the correct permission name depending on the configuration.
98+
* @param string $route Route
99+
* @return string Permission name
100+
*/
101+
public function getPermissionName($route)
102+
{
103+
if (self::PREFIX_BASIC == $this->routePrefix) {
104+
return self::PREFIX_BASIC . trim($route, self::PREFIX_BASIC);
105+
} else {
106+
return self::PREFIX_ADVANCED . ltrim(trim($route, self::PREFIX_BASIC), self::PREFIX_ADVANCED);
107+
}
108+
}
109+
79110
/**
80111
* Get available and assigned routes
81112
* @return array
82113
*/
83114
public function getRoutes()
84115
{
85116
$manager = Configs::authManager();
86-
$routes = $this->getAppRoutes();
117+
// Get advanced configuration
118+
$advanced = Configs::instance()->advanced;
119+
if ($advanced) {
120+
// Use advanced route scheme.
121+
// Set advanced route prefix.
122+
$this->_routePrefix = self::PREFIX_ADVANCED;
123+
// Create empty routes array.
124+
$routes = [];
125+
// Save original app.
126+
$yiiApp = Yii::$app;
127+
// Step through each configured application
128+
foreach ($advanced as $id => $configPaths) {
129+
// Force correct id string.
130+
$id = $this->routePrefix . ltrim(trim($id), $this->routePrefix);
131+
// Create empty config array.
132+
$config = [];
133+
// Assemble configuration for current app.
134+
foreach ($configPaths as $configPath) {
135+
// Merge every new configuration with the old config array.
136+
$config = yii\helpers\ArrayHelper::merge($config, require (Yii::getAlias($configPath)));
137+
}
138+
// Create new app using the config array.
139+
unset($config['bootstrap']);
140+
$app = new yii\web\Application($config);
141+
// Get all the routes of the newly created app.
142+
$r = $this->getAppRoutes($app);
143+
// Dump new app
144+
unset($app);
145+
// Prepend the app id to all routes.
146+
foreach ($r as $route) {
147+
$routes[$id . $route] = $id . $route;
148+
}
149+
}
150+
// Switch back to original app.
151+
Yii::$app = $yiiApp;
152+
unset($yiiApp);
153+
} else {
154+
// Use basic route scheme.
155+
// Set basic route prefix
156+
$this->_routePrefix = self::PREFIX_BASIC;
157+
// Get basic app routes.
158+
$routes = $this->getAppRoutes();
159+
}
87160
$exists = [];
88161
foreach (array_keys($manager->getPermissions()) as $name) {
89-
if ($name[0] !== '/') {
162+
if ($name[0] !== $this->routePrefix) {
90163
continue;
91164
}
92165
$exists[] = $name;
@@ -109,7 +182,7 @@ public function getAppRoutes($module = null)
109182
} elseif (is_string($module)) {
110183
$module = Yii::$app->getModule($module);
111184
}
112-
$key = [__METHOD__, $module->getUniqueId()];
185+
$key = [__METHOD__, Yii::$app->id, $module->getUniqueId()];
113186
$cache = Configs::instance()->cache;
114187
if ($cache === null || ($result = $cache->get($key)) === false) {
115188
$result = [];

0 commit comments

Comments
 (0)