/**
  * Finds and serves the requested backend controller.
  * If the controller cannot be found, returns the Cms page with the URL /404.
  * If the /404 page doesn't exist, returns the system 404 page.
  * @param string $url Specifies the requested page URL.
  * If the parameter is omitted, the current URL used.
  * @return string Returns the processed page content.
  */
 public function run($url = null)
 {
     $params = RouterHelper::segmentizeUrl($url);
     /*
      * Look for a Module controller
      */
     $module = isset($params[0]) ? $params[0] : 'backend';
     $controller = isset($params[1]) ? $params[1] : 'index';
     self::$action = $action = isset($params[2]) ? $this->parseAction($params[2]) : 'index';
     self::$params = $controllerParams = array_slice($params, 3);
     $controllerClass = '\\' . $module . '\\Controllers\\' . $controller;
     if ($controllerObj = $this->findController($controllerClass, $action, base_path() . '/modules')) {
         return $controllerObj->run($action, $controllerParams);
     }
     /*
      * Look for a Plugin controller
      */
     if (count($params) >= 2) {
         list($author, $plugin) = $params;
         $controller = isset($params[2]) ? $params[2] : 'index';
         self::$action = $action = isset($params[3]) ? $this->parseAction($params[3]) : 'index';
         self::$params = $controllerParams = array_slice($params, 4);
         $controllerClass = '\\' . $author . '\\' . $plugin . '\\Controllers\\' . $controller;
         if ($controllerObj = $this->findController($controllerClass, $action, plugins_path())) {
             return $controllerObj->run($action, $controllerParams);
         }
     }
     /*
      * Fall back on Cms controller
      */
     return App::make('Cms\\Classes\\Controller')->run($url);
 }
Exemple #2
0
 /**
  * Finds a page by its URL. Returns the page object and sets the $parameters property.
  * @param string $url The requested URL string.
  * @return \Cms\Classes\Page Returns \Cms\Classes\Page object or null if the page cannot be found.
  */
 public function findByUrl($url)
 {
     $this->url = $url;
     $url = RouterHelper::normalizeUrl($url);
     $apiResult = Event::fire('cms.router.beforeRoute', [$url], true);
     if ($apiResult !== null) {
         return $apiResult;
     }
     for ($pass = 1; $pass <= 2; $pass++) {
         $fileName = null;
         $urlList = [];
         $cacheable = Config::get('cms.enableRoutesCache');
         if ($cacheable) {
             $fileName = $this->getCachedUrlFileName($url, $urlList);
             if (is_array($fileName)) {
                 list($fileName, $this->parameters) = $fileName;
             }
         }
         /*
          * Find the page by URL and cache the route
          */
         if (!$fileName) {
             $router = $this->getRouterObject();
             if ($router->match($url)) {
                 $this->parameters = $router->getParameters();
                 $fileName = $router->matchedRoute();
                 if ($cacheable) {
                     if (!$urlList || !is_array($urlList)) {
                         $urlList = [];
                     }
                     $urlList[$url] = !empty($this->parameters) ? [$fileName, $this->parameters] : $fileName;
                     $key = $this->getUrlListCacheKey();
                     Cache::put($key, base64_encode(serialize($urlList)), Config::get('cms.urlCacheTtl', 1));
                 }
             }
         }
         /*
          * Return the page
          */
         if ($fileName) {
             if (($page = Page::loadCached($this->theme, $fileName)) === null) {
                 /*
                  * If the page was not found on the disk, clear the URL cache
                  * and repeat the routing process.
                  */
                 if ($pass == 1) {
                     $this->clearCache();
                     continue;
                 }
                 return null;
             }
             return $page;
         }
         return null;
     }
 }
Exemple #3
0
 /**
  * Returns the base backend URL
  */
 public function baseUrl($path = null)
 {
     $backendUri = $this->uri();
     $baseUrl = Request::getBaseUrl();
     if ($path === null) {
         return $baseUrl . '/' . $backendUri;
     }
     $path = RouterHelper::normalizeUrl($path);
     return $baseUrl . '/' . $backendUri . $path;
 }
 /**
  * Returns the base backend URL
  */
 public function baseUrl($path = null)
 {
     $backendUri = Config::get('cms.backendUri');
     $baseUrl = Request::getBaseUrl();
     if ($path === null) {
         return $baseUrl . '/' . $backendUri;
     }
     $path = RouterHelper::normalizeUrl($path);
     return $baseUrl . '/' . $backendUri . $path;
 }
Exemple #5
0
 /**
  * Looks up a path to a skin-based file, if it doesn't exist, the default path is used.
  * @param  string  $path
  * @param  boolean $isPublic
  * @return string
  */
 public function getPath($path = null, $isPublic = false)
 {
     $path = RouterHelper::normalizeUrl($path);
     $assetFile = $this->skinPath . $path;
     if (File::isFile($assetFile)) {
         return $isPublic ? $this->publicSkinPath . $path : $this->skinPath . $path;
     } else {
         return $isPublic ? $this->defaultPublicSkinPath . $path : $this->defaultSkinPath . $path;
     }
 }
 public function testDefaultValue()
 {
     $value = Helper::getSegmentDefaultValue(':my_param_name');
     $this->assertFalse($value);
     $value = Helper::getSegmentDefaultValue(':my_param_name?');
     $this->assertFalse($value);
     $value = Helper::getSegmentDefaultValue(':my_param_name?default value');
     $this->assertEquals('default value', $value);
     $value = Helper::getSegmentDefaultValue(':my_param_name|^[a-z]+[0-9]?$|^[a-z]{3}$');
     $this->assertFalse($value);
     $value = Helper::getSegmentDefaultValue(':my_param_name?default value|^[a-z]+[0-9]?$');
     $this->assertEquals('default value', $value);
 }
Exemple #7
0
 /**
  * Finds a page by its URL. Returns the page object and sets the $parameters property.
  * @param string $url The requested URL string.
  * @return \Cms\Classes\Page Returns \Cms\Classes\Page object or null if the page cannot be found.
  */
 public function findByUrl($url)
 {
     $url = RouterHelper::normalizeUrl($url);
     for ($pass = 1; $pass <= 2; $pass++) {
         $fileName = null;
         $urlList = [];
         $cacheable = Config::get('cms.enableRoutesCache') && in_array(Config::get('cache.driver'), ['apc', 'memcached', 'redis', 'array']);
         if ($cacheable) {
             $fileName = $this->getCachedUrlFileName($url, $urlList);
         }
         /*
          * Find the page by URL and cache the route
          */
         if (!$fileName) {
             $router = $this->getRouterObject();
             if ($router->match($url)) {
                 $this->parameters = $router->getParameters();
                 $fileName = $router->matchedRoute();
                 if ($cacheable) {
                     if (!$urlList || !is_array($urlList)) {
                         $urlList = [];
                     }
                     $urlList[$url] = $fileName;
                     $key = $this->getUrlListCacheKey();
                     Cache::put($key, serialize($urlList), Config::get('cms.urlCacheTtl', 1));
                 }
             }
         }
         /*
          * Return the page 
          */
         if ($fileName) {
             if (($page = Page::loadCached($this->theme, $fileName)) === null) {
                 /*
                  * If the page was not found on the disk, clear the URL cache
                  * and repeat the routing process.
                  */
                 if ($pass == 1) {
                     $this->clearCache();
                     continue;
                 }
                 return null;
             }
             return $page;
         }
         return null;
     }
 }
Exemple #8
0
 private static function getTagRenderUrl($theme, $item)
 {
     $tag = Tag::where('name', $item->reference)->first();
     $page = CmsPage::loadCached($theme, $item->cmsPage);
     // Always check if the page can be resolved
     if (!$page) {
         return;
     }
     $url = null;
     if (!$tag) {
         $options = ['filter' => null, 'slug' => null];
     } else {
         $options = ['filter' => 'tag', 'slug' => $tag->slug];
     }
     // Generate the URL
     $url = CmsPage::url($page->getBaseFileName(), $options, false);
     $url = URL::to(Str::lower(RouterHelper::normalizeUrl($url))) . '/';
     return $url;
 }
 /**
  * Returns a Redirect object based on supplied context and parses the model primary key.
  * @param string $context Redirect context, eg: create, update, delete
  * @param Model $model The active model to parse in it's ID and attributes.
  * @return Redirect
  */
 public function makeRedirect($context = null, $model = null)
 {
     $redirectUrl = null;
     if (post('close') && !ends_with($context, '-close')) {
         $context .= '-close';
     }
     if (post('redirect', true)) {
         $redirectUrl = Backend::url($this->getRedirectUrl($context));
     }
     if ($model && $redirectUrl) {
         $redirectUrl = RouterHelper::parseValues($model, array_keys($model->getAttributes()), $redirectUrl);
     }
     return $redirectUrl ? Redirect::to($redirectUrl) : null;
 }
Exemple #10
0
 /**
  * Builds and caches a menu item tree.
  * This method is used internally for menu items and breadcrumbs.
  * @param \Cms\Classes\Theme $theme Specifies the current theme.
  * @return array Returns an array containing the page information
  */
 public static function buildMenuTree($theme)
 {
     if (self::$menuTreeCache !== null) {
         return self::$menuTreeCache;
     }
     $key = crc32($theme->getPath()) . 'static-page-menu-tree';
     $cached = Cache::get($key, false);
     $unserialized = $cached ? @unserialize($cached) : false;
     if ($unserialized !== false) {
         return self::$menuTreeCache = $unserialized;
     }
     $menuTree = ['--root-pages--' => []];
     $iterator = function ($items, $parent, $level) use(&$menuTree, &$iterator) {
         $result = [];
         foreach ($items as $item) {
             $viewBag = $item->page->getViewBag();
             $pageCode = $item->page->getBaseFileName();
             $itemData = ['url' => Str::lower(RouterHelper::normalizeUrl($viewBag->property('url'))), 'title' => $viewBag->property('title'), 'mtime' => $item->page->mtime, 'items' => $iterator($item->subpages, $pageCode, $level + 1), 'parent' => $parent, 'navigation_hidden' => $viewBag->property('navigation_hidden')];
             if ($level == 0) {
                 $menuTree['--root-pages--'][] = $pageCode;
             }
             $result[] = $pageCode;
             $menuTree[$pageCode] = $itemData;
         }
         return $result;
     };
     $pageList = new PageList($theme);
     $iterator($pageList->getPageTree(), null, 0);
     self::$menuTreeCache = $menuTree;
     Cache::put($key, serialize($menuTree), Config::get('cms.parsedPageCacheTTL', 10));
     return self::$menuTreeCache;
 }
Exemple #11
0
 /**
  * {@inheritDoc}
  */
 public function getPath($path = null, $isPublic = false)
 {
     $path = RouterHelper::normalizeUrl($path);
     return $isPublic ? $this->defaultPublicSkinPath . $path : $this->defaultSkinPath . $path;
 }
Exemple #12
0
 /**
  * Loads the URL map - a list of page file names and corresponding URL patterns.
  * The URL map can is cached. The clearUrlMap() method resets the cache. By default
  * the map is updated every time when a page is saved in the back-end, or 
  * when the interval defined with the cms.urlCacheTtl expires.
  * @return boolean Returns true if the URL map was loaded from the cache. Otherwise returns false.
  */
 protected function loadUrlMap()
 {
     $key = $this->getCacheKey('static-page-url-map');
     $cacheable = Config::get('cms.enableRoutesCache');
     $cached = $cacheable ? Cache::get($key, false) : false;
     if (!$cached || ($unserialized = @unserialize($cached)) === false) {
         /*
          * The item doesn't exist in the cache, create the map
          */
         $pageList = new PageList($this->theme);
         $pages = $pageList->listPages();
         $map = ['urls' => [], 'files' => [], 'titles' => []];
         foreach ($pages as $page) {
             $url = $page->getViewBag()->property('url');
             if (!$url) {
                 continue;
             }
             $url = Str::lower(RouterHelper::normalizeUrl($url));
             $file = $page->getBaseFileName();
             $map['urls'][$url] = $file;
             $map['files'][$file] = $url;
             $map['titles'][$file] = $page->getViewBag()->property('title');
         }
         self::$urlMap = $map;
         if ($cacheable) {
             Cache::put($key, serialize($map), Config::get('cms.urlCacheTtl', 1));
         }
         return false;
     }
     self::$urlMap = $unserialized;
     return true;
 }
 /**
  * Register the service provider.
  *
  * @return void
  */
 public function register()
 {
     /*
      * Register self
      */
     parent::register('system');
     /*
      * Register core providers
      */
     App::register('October\\Rain\\Config\\ConfigServiceProvider');
     App::register('October\\Rain\\Translation\\TranslationServiceProvider');
     /*
      * Define path constants
      */
     if (!defined('PATH_APP')) {
         define('PATH_APP', app_path());
     }
     if (!defined('PATH_BASE')) {
         define('PATH_BASE', base_path());
     }
     if (!defined('PATH_PUBLIC')) {
         define('PATH_PUBLIC', public_path());
     }
     if (!defined('PATH_STORAGE')) {
         define('PATH_STORAGE', storage_path());
     }
     if (!defined('PATH_PLUGINS')) {
         define('PATH_PLUGINS', base_path() . Config::get('cms.pluginsDir', '/plugins'));
     }
     /*
      * Register singletons
      */
     App::singleton('string', function () {
         return new \October\Rain\Support\Str();
     });
     App::singleton('backend.helper', function () {
         return new \Backend\Classes\BackendHelper();
     });
     App::singleton('backend.menu', function () {
         return \Backend\Classes\NavigationManager::instance();
     });
     App::singleton('backend.auth', function () {
         return \Backend\Classes\AuthManager::instance();
     });
     /*
      * Check for CLI or system/updates route and disable any plugin initialization
      * @todo This should be moved to middleware
      */
     $requestPath = \October\Rain\Router\Helper::normalizeUrl(\Request::path());
     $systemPath = \October\Rain\Router\Helper::normalizeUrl(Config::get('cms.backendUri') . '/system/updates');
     if (stripos($requestPath, $systemPath) === 0) {
         PluginManager::$noInit = true;
     }
     $updateCommands = ['october:up', 'october:update'];
     if (App::runningInConsole() && count(array_intersect($updateCommands, Request::server('argv'))) > 0) {
         PluginManager::$noInit = true;
     }
     /*
      * Register all plugins
      */
     $pluginManager = PluginManager::instance();
     $pluginManager->registerAll();
     /*
      * Error handling for uncaught Exceptions
      */
     App::error(function (\Exception $exception, $httpCode) {
         $handler = new ErrorHandler();
         return $handler->handleException($exception, $httpCode);
     });
     /*
      * Write all log events to the database
      */
     Event::listen('illuminate.log', function ($level, $message, $context) {
         if (!DbDongle::hasDatabase()) {
             return;
         }
         EventLog::add($message, $level);
     });
     /*
      * Register basic Twig
      */
     App::bindShared('twig', function ($app) {
         $twig = new Twig_Environment(new TwigLoader(), ['auto_reload' => true]);
         $twig->addExtension(new TwigExtension());
         return $twig;
     });
     /*
      * Register .htm extension for Twig views
      */
     App::make('view')->addExtension('htm', 'twig', function () {
         return new TwigEngine(App::make('twig'));
     });
     /*
      * Register Twig that will parse strings
      */
     App::bindShared('twig.string', function ($app) {
         $twig = $app['twig'];
         $twig->setLoader(new Twig_Loader_String());
         return $twig;
     });
     /*
      * Override system mailer with mail settings
      */
     Event::listen('mailer.beforeRegister', function () {
         if (MailSettings::isConfigured()) {
             MailSettings::applyConfigValues();
         }
     });
     /*
      * Override standard Mailer content with template
      */
     Event::listen('mailer.beforeAddContent', function ($mailer, $message, $view, $plain, $data) {
         if (MailTemplate::addContentToMailer($message, $view, $data)) {
             return false;
         }
     });
     /*
      * Register other module providers
      */
     foreach (Config::get('cms.loadModules', []) as $module) {
         if (strtolower(trim($module)) == 'system') {
             continue;
         }
         App::register('\\' . $module . '\\ServiceProvider');
     }
     /*
      * Register navigation
      */
     BackendMenu::registerCallback(function ($manager) {
         $manager->registerMenuItems('October.System', ['system' => ['label' => 'system::lang.settings.menu_label', 'icon' => 'icon-cog', 'url' => Backend::url('system/settings'), 'permissions' => ['backend.manage_users', 'system.*'], 'order' => 1000]]);
     });
     /*
      * Register report widgets
      */
     WidgetManager::instance()->registerReportWidgets(function ($manager) {
         $manager->registerReportWidget('System\\ReportWidgets\\Status', ['label' => 'backend::lang.dashboard.status.widget_title_default', 'context' => 'dashboard']);
     });
     /*
      * Register permissions
      */
     BackendAuth::registerCallback(function ($manager) {
         $manager->registerPermissions('October.System', ['system.manage_updates' => ['label' => 'system::lang.permissions.manage_software_updates', 'tab' => 'system::lang.permissions.name'], 'system.manage_mail_settings' => ['label' => 'system::lang.permissions.manage_mail_settings', 'tab' => 'system::lang.permissions.name'], 'system.manage_mail_templates' => ['label' => 'system::lang.permissions.manage_mail_templates', 'tab' => 'system::lang.permissions.name']]);
     });
     /*
      * Register markup tags
      */
     MarkupManager::instance()->registerCallback(function ($manager) {
         $manager->registerFunctions(['input' => 'input', 'post' => 'post', 'get' => 'get', 'link_to' => 'link_to', 'link_to_asset' => 'link_to_asset', 'link_to_route' => 'link_to_route', 'link_to_action' => 'link_to_action', 'asset' => 'asset', 'action' => 'action', 'url' => 'url', 'route' => 'route', 'secure_url' => 'secure_url', 'secure_asset' => 'secure_asset', 'str_*' => ['Str', '*'], 'url_*' => ['URL', '*'], 'html_*' => ['HTML', '*'], 'form_*' => ['Form', '*'], 'form_macro' => ['Form', '__call']]);
         $manager->registerFilters(['slug' => ['Str', 'slug'], 'plural' => ['Str', 'plural'], 'singular' => ['Str', 'singular'], 'finish' => ['Str', 'finish'], 'snake' => ['Str', 'snake'], 'camel' => ['Str', 'camel'], 'studly' => ['Str', 'studly'], 'trans' => ['Lang', 'get'], 'transchoice' => ['Lang', 'choice'], 'md' => ['October\\Rain\\Support\\Markdown', 'parse']]);
     });
     /*
      * Register settings
      */
     SettingsManager::instance()->registerCallback(function ($manager) {
         $manager->registerSettingItems('October.System', ['administrators' => ['label' => 'backend::lang.user.menu_label', 'description' => 'backend::lang.user.menu_description', 'category' => SettingsManager::CATEGORY_SYSTEM, 'icon' => 'icon-users', 'url' => Backend::url('backend/users'), 'permissions' => ['backend.manage_users'], 'order' => 600], 'updates' => ['label' => 'system::lang.updates.menu_label', 'description' => 'system::lang.updates.menu_description', 'category' => SettingsManager::CATEGORY_SYSTEM, 'icon' => 'icon-cloud-download', 'url' => Backend::url('system/updates'), 'permissions' => ['system.manage_updates'], 'order' => 700], 'event_logs' => ['label' => 'system::lang.event_log.menu_label', 'description' => 'system::lang.event_log.menu_description', 'category' => SettingsManager::CATEGORY_LOGS, 'icon' => 'icon-exclamation-triangle', 'url' => Backend::url('system/eventlogs'), 'permissions' => ['system.access_event_logs'], 'order' => 800], 'request_logs' => ['label' => 'system::lang.request_log.menu_label', 'description' => 'system::lang.request_log.menu_description', 'category' => SettingsManager::CATEGORY_LOGS, 'icon' => 'icon-file-o', 'url' => Backend::url('system/requestlogs'), 'permissions' => ['system.access_request_logs'], 'order' => 800], 'mail_settings' => ['label' => 'system::lang.mail.menu_label', 'description' => 'system::lang.mail.menu_description', 'category' => SettingsManager::CATEGORY_MAIL, 'icon' => 'icon-envelope', 'class' => 'System\\Models\\MailSettings', 'permissions' => ['system.manage_mail_settings'], 'order' => 400], 'mail_templates' => ['label' => 'system::lang.mail_templates.menu_label', 'description' => 'system::lang.mail_templates.menu_description', 'category' => SettingsManager::CATEGORY_MAIL, 'icon' => 'icon-envelope-square', 'url' => Backend::url('system/mailtemplates'), 'permissions' => ['system.manage_mail_templates'], 'order' => 500]]);
     });
     /*
      * Register console commands
      */
     $this->registerConsoleCommand('october.up', 'System\\Console\\OctoberUp');
     $this->registerConsoleCommand('october.down', 'System\\Console\\OctoberDown');
     $this->registerConsoleCommand('october.update', 'System\\Console\\OctoberUpdate');
     $this->registerConsoleCommand('october.util', 'System\\Console\\OctoberUtil');
     $this->registerConsoleCommand('plugin.install', 'System\\Console\\PluginInstall');
     $this->registerConsoleCommand('plugin.remove', 'System\\Console\\PluginRemove');
     $this->registerConsoleCommand('plugin.refresh', 'System\\Console\\PluginRefresh');
     /*
      * Override clear cache command
      */
     App::bindShared('command.cache.clear', function ($app) {
         return new \System\Console\CacheClear($app['cache'], $app['files']);
     });
     /*
      * Register the sidebar for the System main menu
      */
     BackendMenu::registerContextSidenavPartial('October.System', 'system', '@/modules/system/partials/_system_sidebar.htm');
 }
 /**
  * Captures and removes every segment of a URL after a wildcard
  * pattern segment is detected, until both collections of segments
  * are the same size.
  * @param array $urlSegments
  * @return array
  */
 protected function captureWildcardSegments(&$urlSegments)
 {
     $wildSegments = [];
     $patternSegments = $this->segments;
     $segmentDiff = count($urlSegments) - count($patternSegments);
     $wildMode = false;
     $wildCount = 0;
     foreach ($urlSegments as $index => $urlSegment) {
         if ($wildMode) {
             if ($wildCount < $segmentDiff) {
                 $wildSegments[] = $urlSegment;
                 $wildCount++;
                 unset($urlSegments[$index]);
                 continue;
             } else {
                 break;
             }
         }
         $patternSegment = $patternSegments[$index];
         if (Helper::segmentIsWildcard($patternSegment)) {
             $wildMode = true;
         }
     }
     // Reset array index
     $urlSegments = array_values($urlSegments);
     return $wildSegments;
 }
Exemple #15
0
 /**
  * Returns URL of a category page.
  */
 protected static function getCategoryPageUrl($pageCode, $category, $theme)
 {
     $page = CmsPage::loadCached($theme, $pageCode);
     if (!$page) {
         return;
     }
     $properties = $page->getComponentProperties('blogPosts');
     if (!isset($properties['categoryFilter'])) {
         return;
     }
     $filter = substr($properties['categoryFilter'], 1);
     $url = CmsPage::url($page->getBaseFileName(), [$filter => $category->slug], false);
     return Str::lower(RouterHelper::normalizeUrl($url));
 }
Exemple #16
0
 /**
  * Check for CLI or system/updates route and disable any plugin initialization
  */
 protected function registerPrivilegedActions()
 {
     $requests = ['/combine', '@/system/updates', '@/system/install', '@/backend/auth'];
     $commands = ['october:up', 'october:update'];
     /*
      * Requests
      */
     $path = RouterHelper::normalizeUrl(Request::path());
     $backendUri = RouterHelper::normalizeUrl(Config::get('cms.backendUri', 'backend'));
     foreach ($requests as $request) {
         if (substr($request, 0, 1) == '@') {
             $request = $backendUri . substr($request, 1);
         }
         if (stripos($path, $request) === 0) {
             PluginManager::$noInit = true;
         }
     }
     /*
      * CLI
      */
     if (App::runningInConsole() && count(array_intersect($commands, Request::server('argv'))) > 0) {
         PluginManager::$noInit = true;
     }
 }
Exemple #17
0
 /**
  * Returns the onclick event for a list row.
  * @param  Model $record
  * @return string
  */
 public function getRecordOnClick($record)
 {
     if (!isset($this->recordOnClick)) {
         return null;
     }
     $columns = array_keys($record->getAttributes());
     $recordOnClick = RouterHelper::parseValues($record, $columns, $this->recordOnClick);
     return Html::attributes(['onclick' => $recordOnClick]);
 }
Exemple #18
0
 /**
  * Checks whether a given URL matches a given pattern.
  * @param string $url The URL to check.
  * @param array $parameters A reference to a PHP array variable to return the parameter list fetched from URL.
  * @return boolean Returns true if the URL matches the pattern. Otherwise returns false.
  */
 public function resolveUrl($url, &$parameters)
 {
     $parameters = array();
     $patternSegments = $this->segments;
     $patternSegmentNum = count($patternSegments);
     $urlSegments = Helper::segmentizeUrl($url);
     /*
      * If the number of URL segments is more than the number of pattern segments - return false
      */
     if (count($urlSegments) > count($patternSegments)) {
         return false;
     }
     /*
      * Compare pattern and URL segments
      */
     foreach ($patternSegments as $index => $patternSegment) {
         $patternSegmentLower = mb_strtolower($patternSegment);
         if (strpos($patternSegment, ':') !== 0) {
             /*
              * Static segment
              */
             if (!array_key_exists($index, $urlSegments) || $patternSegmentLower != mb_strtolower($urlSegments[$index])) {
                 return false;
             }
         } else {
             /*
              * Dynamic segment. Initialize the parameter
              */
             $paramName = Helper::getParameterName($patternSegment);
             $parameters[$paramName] = false;
             /*
              * Determine whether it is optional
              */
             $optional = Helper::segmentIsOptional($patternSegment);
             /*
              * Check if the optional segment has no required segments following it
              */
             if ($optional && $index < $patternSegmentNum - 1) {
                 for ($i = $index + 1; $i < $patternSegmentNum; $i++) {
                     if (!Helper::segmentIsOptional($patternSegments[$i])) {
                         $optional = false;
                         break;
                     }
                 }
             }
             /*
              * If the segment is optional and there is no corresponding value in the URL, assign the default value (if provided)
              * and skip to the next segment.
              */
             $urlSegmentExists = array_key_exists($index, $urlSegments);
             if ($optional && !$urlSegmentExists) {
                 $parameters[$paramName] = Helper::getSegmentDefaultValue($patternSegment);
                 continue;
             }
             /*
              * If the segment is not optional and there is no corresponding value in the URL, return false
              */
             if (!$optional && !$urlSegmentExists) {
                 return false;
             }
             /*
              * Validate the value with the regular expression
              */
             $regexp = Helper::getSegmentRegExp($patternSegment);
             if ($regexp) {
                 try {
                     if (!preg_match($regexp, $urlSegments[$index])) {
                         return false;
                     }
                 } catch (\Exception $ex) {
                 }
             }
             /*
              * Set the parameter value
              */
             $parameters[$paramName] = $urlSegments[$index];
         }
     }
     return true;
 }