$this->buildSchema = array();
$buildSchema = ltrim($buildSchema, '/');
- $components = preg_split('~{([a-z]+)}~', $buildSchema, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+ $components = preg_split('~({(?:[a-z]+)})~', $buildSchema, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$delimiters = array('/', '-', '.', '_');
foreach ($components as $component) {
$type = 'component';
- if (in_array($component, $delimiters)) {
+ if (preg_match('~{([a-z]+)}~', $component, $matches)) {
+ $component = $matches[1];
+ }
+ else {
$type = 'separator';
}
// drop application component to avoid being appended as query string
unset($components['application']);
- $link = '';
-
// handle default values for controller
- $buildRoute = true;
+ $useBuildSchema = true;
if (count($components) == 1 && isset($components['controller'])) {
$ignoreController = false;
// drops controller from route
if ($ignoreController) {
- $buildRoute = false;
+ $useBuildSchema = false;
// unset the controller, since it would otherwise be added with http_build_query()
unset($components['controller']);
}
}
- if ($buildRoute) {
+ return $this->buildRoute($components, $application, $useBuildSchema);
+ }
+
+ /**
+ * Builds the actual link, the parameter $useBuildSchema can be set to false for
+ * empty routes, e.g. for the default page.
+ *
+ * @param array $components
+ * @param string $application
+ * @param boolean $useBuildSchema
+ * @return string
+ */
+ protected function buildRoute(array $components, $application, $useBuildSchema) {
+ $link = '';
+
+ if ($useBuildSchema) {
$lastSeparator = null;
foreach ($this->buildSchema as $component) {
$value = $component['value'];
}
}
- if (!empty($link)) {
- $link .= '/';
+ if (!empty($link) && $lastSeparator !== null) {
+ $link .= $lastSeparator;
}
}
if (!URL_LEGACY_MODE || RequestHandler::getInstance()->isACPRequest()) {
// WCF 2.1: ?Foo/Bar/
if (!empty($_SERVER['QUERY_STRING'])) {
- parse_str($_SERVER['QUERY_STRING'], $parts);
- foreach ($parts as $key => $value) {
- if ($value === '') {
- self::$pathInfo = $key;
+ // don't use parse_str as it replaces dots with underscores
+ $components = explode('&', $_SERVER['QUERY_STRING']);
+ for ($i = 0, $length = count($components); $i < $length; $i++) {
+ $component = $components[$i];
+ if (mb_strpos($component, '=') === false) {
+ self::$pathInfo = urldecode($component);
break;
}
}
--- /dev/null
+<?php
+namespace wcf\system\request;
+
+/**
+ * Static route implementation to resolve HTTP requests, handling a single controller.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.request
+ * @category Community Framework
+ */
+class StaticRoute extends FlexibleRoute {
+ /**
+ * static application identifier
+ * @var string
+ */
+ protected $staticApplication = '';
+
+ /**
+ * static controller name, not the FQN
+ * @var string
+ */
+ protected $staticController = '';
+
+ /**
+ * Creates a new static route instace.
+ */
+ public function __construct() {
+ // static routes are disallowed for ACP
+ parent::__construct(false);
+ }
+
+ /**
+ * Sets the static controller for this route.
+ *
+ * @param string $application
+ * @param string $controller
+ */
+ public function setStaticController($application, $controller) {
+ $this->staticApplication = $application;
+ $this->staticController = $controller;
+
+ $this->requireComponents['controller'] = '~^' . $this->staticController . '$~';
+ }
+
+ /**
+ * @see \wcf\system\request\IRoute::buildLink()
+ */
+ public function buildLink(array $components) {
+ // static routes don't have these components
+ unset($components['application']);
+ unset($components['controller']);
+
+ return $this->buildRoute($components, '', true);
+ }
+
+ /**
+ * @see \wcf\system\request\IRoute::canHandle()
+ */
+ public function canHandle(array $components) {
+ if (isset($components['application']) && $components['application'] == $this->staticApplication) {
+ if (isset($components['controller']) && $components['controller'] == $this->staticController) {
+ return parent::canHandle($components);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @see \wcf\system\request\IRoute::matches()
+ */
+ public function matches($requestURL) {
+ if (parent::matches($requestURL)) {
+ $this->routeData['application'] = $this->staticApplication;
+ $this->routeData['controller'] = RequestHandler::getTokenizedController($this->staticController);
+ $this->routeData['isDefaultController'] = false;
+
+ return true;
+ }
+
+ return false;
+ }
+}