1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528:
<?php
namespace MvcCore\Ext\Debugs\Tracys;
class RoutingPanel implements \Tracy\IBarPanel {
const VERSION = '5.0.0';
protected $app = NULL;
protected $toolClass = NULL;
protected $request = NULL;
protected $requestLang = NULL;
protected $requestParams = [];
protected $router = NULL;
protected $routes = [];
protected $currentRoute = NULL;
protected $defaultLang = NULL;
protected $view = NULL;
private $_debugCode = '';
public function getId() {
return 'routing-panel';
}
public function getTab() {
ob_start();
$view = $this->getViewData();
if ($view) include(__DIR__ . '/routing.tab.phtml');
return ob_get_clean();
}
public function getPanel() {
ob_start();
$view = $this->getViewData();
if ($view) include(__DIR__ . '/routing.panel.phtml');
return ob_get_clean();
}
public function getViewData () {
if ($this->view !== NULL) return $this->view;
$this->view = new \stdClass;
try {
$this->initMainApplicationProperties();
if ($this->router === NULL) return $this->view;
$this->initViewPanelTitle();
$this->initViewPanelTableData();
$this->initViewPanelRequestedUrlData();
} catch (\Exception $e) {
$this->_debug($e);
$this->_debug($e->getTrace());
} catch (\Throwable $e) {
$this->_debug($e);
$this->_debug($e->getTrace());
}
$this->view->_debugCode = $this->_debugCode;
return $this->view;
}
protected function initMainApplicationProperties () {
$this->app = \MvcCore\Application::GetInstance();
$this->router = $this->app->GetRouter();
$this->routes = $this->router->GetRoutes();
$this->currentRoute = $this->router->GetCurrentRoute();
$this->request = $this->app->GetRequest();
$this->requestLang = $this->request->GetLang();
$router = $this->router;
$ctrlParamName = $router::URL_PARAM_CONTROLLER;
$actionParamName = $router::URL_PARAM_ACTION;
$getParamsKeys = array_unique(array_merge(
[$ctrlParamName => NULL, $actionParamName => NULL],
$this->currentRoute ? $this->currentRoute->GetMatchedParams() : [],
array_keys($_GET)
));
$this->requestParams = & $this->request->GetParams(['#[\<\>\'"]#' => ''], array_keys($getParamsKeys));
if (method_exists($this->router, 'GetDefaultLang'))
$this->defaultLang = $this->router->GetDefaultLang();
}
protected function initViewPanelTitle () {
$panelTitle = 'No route match';
if ($this->currentRoute !== NULL)
$panelTitle = $this->currentRoute->GetName();
$this->view->panelTitle = htmlSpecialChars($panelTitle, ENT_NOQUOTES, 'UTF-8');
}
protected function initViewPanelTableData () {
$items = [];
$currentRouteName = $this->currentRoute ? $this->currentRoute->GetName() : NULL;
foreach ($this->routes as $route) {
$matched = FALSE;
if ($currentRouteName !== NULL && $route->GetName() === $currentRouteName) {
$matched = TRUE;
}
$items[] = $this->initViewPanelTableRow($route, $matched);
}
$this->view->items = $items;
}
protected function initViewPanelTableRow (\MvcCore\IRoute $route, $matched) {
$route->InitAll();
$row = new \stdClass;
$row->matched = $matched;
$row->method = $route->GetMethod();
$row->method = $row->method === NULL ? '*' : $row->method;
$row->className = htmlSpecialChars('\\'.get_class($route), ENT_QUOTES, 'UTF-8');
$routeMatch = $this->getRouteLocalizedRecord($route, 'GetMatch');
$routeMatch = rtrim($routeMatch, 'imsxeADSUXJu');
$routeReverse = $this->getRouteLocalizedRecord($route, 'GetReverse');
$routeDefaults = $this->getRouteLocalizedRecord($route, 'GetDefaults');
$row->match = $this->completeFormatedPatternCharGroups($routeMatch, ['(', ')']);
unset($routeMatch);
if ($routeReverse !== NULL) {
$row->reverse = $this->completeFormatedPatternCharGroups($routeReverse, ['<', '>']);
} else {
$row->reverse = NULL;
}
unset($routeReverse);
$row->routeName = $route->GetName();
$row->ctrlActionName = $route->GetControllerAction();
if ($row->ctrlActionName !== ':') {
$row->ctrlActionLink = $this->completeCtrlActionLink($route->GetController(), $route->GetAction());
} else {
$row->ctrlActionName = NULL;
$row->ctrlActionLink = NULL;
}
$routeReverseParams = $route->GetReverseParams() ?: [];
$paramsKeys = array_unique(array_merge($routeReverseParams, array_keys($routeDefaults)));
unset($routeReverseParams);
$row->defaults = $this->completeParams($route, $paramsKeys, TRUE);
unset($paramsKeys);
$row->params = [];
if ($matched) {
$paramsAndReqestParams = array_merge($routeDefaults, $this->requestParams);
unset($routeDefaults);
$row->params = $this->completeParams($route, array_keys($paramsAndReqestParams), FALSE);
unset($paramsAndReqestParams, $route);
}
return $row;
}
protected function completeParams (\MvcCore\IRoute $route, $paramsNames = [], $useDefaults = TRUE) {
$result = [];
if ($this->defaultLang !== NULL) {
$result['lang'] = '<span class="tracy-dump-string">"' . $this->requestLang . '"</span><br />';
}
if (!$paramsNames) return $result;
$routeDefaults = $this->getRouteLocalizedRecord($route, 'GetDefaults');
$routeDefaultsKeys = array_keys($routeDefaults);
if ($useDefaults) {
$paramValues = $routeDefaults;
} else {
$paramValues = $this->requestParams;
}
$router = $this->router;
$ctrlParamName = $router::URL_PARAM_CONTROLLER;
$actionParamName = $router::URL_PARAM_ACTION;
foreach ($paramsNames as $key => $paramName) {
if ($paramName == $ctrlParamName || $paramName == $actionParamName) {
if (!in_array($paramName, $routeDefaultsKeys, TRUE) && !isset($_GET[$paramName])) continue;
}
$paramValue = isset($paramValues[$paramName])
? $paramValues[$paramName]
: NULL;
if ($key === 0 && $paramName === 0 && $paramValue === NULL) continue;
$paramNameEncoded = htmlSpecialChars($paramName, ENT_IGNORE, 'UTF-8');
if ($paramValue === NULL) {
$paramValueRendered = '<span class="tracy-dump-null">NULL</span><br />';
} else if (is_string($paramValue)) {
$paramValueRendered = '<span class="tracy-dump-string">"'
. htmlSpecialChars($paramValue, ENT_IGNORE, 'UTF-8')
. '"</span><br />';
} else {
$paramValueRendered = \Tracy\Dumper::toHtml($paramValue, [
\Tracy\Dumper::COLLAPSE => TRUE,
\Tracy\Dumper::LIVE => TRUE
]);
}
$result[$paramNameEncoded] = $paramValueRendered;
}
return $result;
}
protected function completeFormatedPatternCharGroups ($str, $brackets) {
$matches = $this->completeMatchingBracketsPositions($str, $brackets[0], $brackets[1]);
if ($matches) {
$pos = 0;
$result = '';
foreach ($matches as $key => $match) {
list($subStr, $begin, $end) = $match;
$result .= mb_substr($str, $pos, $begin - $pos);
$result .= '<span class="c'.($key % 6).'">';
$result .= htmlSpecialChars($subStr, ENT_NOQUOTES, 'UTF-8');
$result .= '</span>';
$pos = $end + 1;
}
$result .= mb_substr($str, $pos);
} else {
$result = $str;
}
return $result;
}
protected function completeMatchingBracketsPositions ($str, $begin, $end) {
$result = [];
$i = 0;
$l = mb_strlen($str);
$matches = [];
while ($i < $l) {
$beginPos = mb_strpos($str, $begin, $i);
$endPos = mb_strpos($str, $end, $i);
$beginContained = $beginPos !== FALSE;
$endContained = $endPos !== FALSE;
if ($beginContained && $endContained) {
if ($beginPos < $endPos) {
$matches[] = [$begin, $beginPos];
$i = $beginPos + 1;
} else {
$matches[] = [$end, $endPos];
$i = $endPos + 1;
}
} else if ($beginContained) {
$matches[] = [$begin, $beginPos];
$i = $beginPos + 1;
} else if ($endContained) {
$matches[] = [$end, $endPos];
$i = $endPos + 1;
} else {
break;
}
}
if ($matches) {
$level = 0;
$groupBegin = -1;
$paramLevel = 0;
foreach ($matches as $item) {
list($itemChar, $itemPos) = $item;
$backSlashesCnt = 0;
$backSlashPos = $itemPos - 1;
while ($backSlashPos > -1) {
$prevChar = mb_substr($str, $backSlashPos, 1);
if ($prevChar == '\\') {
$backSlashesCnt += 1;
$backSlashPos -= 1;
} else {
break;
}
}
if (
$backSlashesCnt === 0 || (
($backSlashesCnt > 0 && $backSlashesCnt % 2 === 0)
)) {
if ($itemChar == $begin) {
if ($begin == '(') {
$itemCharNext = mb_substr($str, $itemPos + 1, 1);
if ($itemCharNext !== '?') {
$level += 1;
continue;
}
}
$paramLevel = $level;
$groupBegin = $itemPos;
$level += 1;
} else {
$level -= 1;
if ($level === $paramLevel && $groupBegin > -1) {
$result[] = [
mb_substr($str, $groupBegin, $itemPos - $groupBegin + 1),
$groupBegin,
$itemPos
];
}
}
}
}
}
unset(
$str, $begin, $end,
$beginPos, $endPos,
$beginContained, $endContained,
$matches, $item, $i, $l,
$level, $groupBegin, $paramLevel,
$itemPos, $itemCharNext, $itemChar,
$backSlashesCnt, $backSlashPos, $prevChar
);
return $result;
}
protected function completeCtrlActionLink ($ctrlName = '', $actionName = '') {
$fullControllerClassName = '';
static $controllersDir = NULL;
if ($controllersDir === NULL) {
$controllersDir = '\\' . implode('\\', [$this->app->GetAppDir(), $this->app->GetControllersDir()]) . '\\';
}
if (substr($ctrlName, 0, 2) == '//') {
$fullControllerClassName = $ctrlName;
$fullClassToSearch = substr($ctrlName, 2);
} else {
$fullControllerClassName = $controllersDir . $ctrlName;
$fullClassToSearch = $fullControllerClassName;
}
$result = ['', $fullControllerClassName . ':' . $actionName . 'Action'];
try {
$ctrlReflection = new \ReflectionClass($fullClassToSearch);
if ($ctrlReflection instanceof \ReflectionClass) {
$file = $ctrlReflection->getFileName();
$actionReflection = $ctrlReflection->getMethod($actionName . 'Action');
if ($actionReflection instanceof \ReflectionMethod) {
$line = $actionReflection->getStartLine();
$result = [
\Tracy\Helpers::editorUri($file, $line),
$fullControllerClassName . ':' . $actionName . 'Action'
];
}
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
}
return $result;
}
protected function getRouteLocalizedRecord (\MvcCore\IRoute $route, $getter) {
$result = $route->$getter($this->requestLang);
if ($result === NULL && $this->defaultLang !== NULL)
$result = $route->$getter($this->defaultLang);
return $result;
}
protected function initViewPanelRequestedUrlData () {
$req = $this->request;
$this->view->requestedUrl = (object) [
'method' => htmlSpecialChars($req->GetMethod(), ENT_IGNORE, 'UTF-8'),
'baseUrl' => htmlSpecialChars($req->GetBaseUrl(), ENT_IGNORE, 'UTF-8'),
'path' => htmlSpecialChars($req->GetRequestPath(), ENT_IGNORE, 'UTF-8'),
];
}
private function _debug ($var) {
$this->_debugCode .= \Tracy\Dumper::toHtml($var, [
\Tracy\Dumper::LIVE => TRUE,
]);
}
}