processIndexRoutes($routes, $appName); $collection->addCollection($this->processIndexResources($routes, $appName)); return $collection; } public function parseOCSRoutes(array $routes, string $appName): RouteCollection { $collection = $this->processOCS($routes, $appName); $collection->addCollection($this->processOCSResources($routes, $appName)); return $collection; } private function processOCS(array $routes, string $appName): RouteCollection { $collection = new RouteCollection(); $ocsRoutes = $routes['ocs'] ?? []; foreach ($ocsRoutes as $ocsRoute) { $result = $this->processRoute($ocsRoute, $appName, 'ocs.'); $collection->add($result[0], $result[1]); } return $collection; } /** * Creates one route base on the give configuration * @param array $routes * @throws \UnexpectedValueException */ private function processIndexRoutes(array $routes, string $appName): RouteCollection { $collection = new RouteCollection(); $simpleRoutes = $routes['routes'] ?? []; foreach ($simpleRoutes as $simpleRoute) { $result = $this->processRoute($simpleRoute, $appName); $collection->add($result[0], $result[1]); } return $collection; } private function processRoute(array $route, string $appName, string $routeNamePrefix = ''): array { $name = $route['name']; $postfix = $route['postfix'] ?? ''; $root = $this->buildRootPrefix($route, $appName, $routeNamePrefix); $url = $root . '/' . ltrim($route['url'], '/'); $verb = strtoupper($route['verb'] ?? 'GET'); $split = explode('#', $name, 2); if (count($split) !== 2) { throw new \UnexpectedValueException('Invalid route name: use the format foo#bar to reference FooController::bar'); } [$controller, $action] = $split; $controllerName = $this->buildControllerName($controller); $actionName = $this->buildActionName($action); /* * The route name has to be lowercase, for symfony to match it correctly. * This is required because smyfony allows mixed casing for controller names in the routes. * To avoid breaking all the existing route names, registering and matching will only use the lowercase names. * This is also safe on the PHP side because class and method names collide regardless of the casing. */ $routeName = strtolower($routeNamePrefix . $appName . '.' . $controller . '.' . $action . $postfix); $routeObject = new Route($url); $routeObject->method($verb); // optionally register requirements for route. This is used to // tell the route parser how url parameters should be matched if (array_key_exists('requirements', $route)) { $routeObject->requirements($route['requirements']); } // optionally register defaults for route. This is used to // tell the route parser how url parameters should be default valued $defaults = []; if (array_key_exists('defaults', $route)) { $defaults = $route['defaults']; } $defaults['caller'] = [$appName, $controllerName, $actionName]; $routeObject->defaults($defaults); return [$routeName, $routeObject]; } /** * For a given name and url restful OCS routes are created: * - index * - show * - create * - update * - destroy * * @param array $routes */ private function processOCSResources(array $routes, string $appName): RouteCollection { return $this->processResources($routes['ocs-resources'] ?? [], $appName, 'ocs.'); } /** * For a given name and url restful routes are created: * - index * - show * - create * - update * - destroy * * @param array $routes */ private function processIndexResources(array $routes, string $appName): RouteCollection { return $this->processResources($routes['resources'] ?? [], $appName); } /** * For a given name and url restful routes are created: * - index * - show * - create * - update * - destroy * * @param array $resources * @param string $routeNamePrefix */ private function processResources(array $resources, string $appName, string $routeNamePrefix = ''): RouteCollection { // declaration of all restful actions $actions = [ ['name' => 'index', 'verb' => 'GET', 'on-collection' => true], ['name' => 'show', 'verb' => 'GET'], ['name' => 'create', 'verb' => 'POST', 'on-collection' => true], ['name' => 'update', 'verb' => 'PUT'], ['name' => 'destroy', 'verb' => 'DELETE'], ]; $collection = new RouteCollection(); foreach ($resources as $resource => $config) { $root = $this->buildRootPrefix($config, $appName, $routeNamePrefix); // the url parameter used as id to the resource foreach ($actions as $action) { $url = $root . '/' . ltrim($config['url'], '/'); $method = $action['name']; $verb = strtoupper($action['verb'] ?? 'GET'); $collectionAction = $action['on-collection'] ?? false; if (!$collectionAction) { $url .= '/{id}'; } $controller = $resource; $controllerName = $this->buildControllerName($controller); $actionName = $this->buildActionName($method); $routeName = $routeNamePrefix . $appName . '.' . strtolower($resource) . '.' . $method; $route = new Route($url); $route->method($verb); $route->defaults(['caller' => [$appName, $controllerName, $actionName]]); $collection->add($routeName, $route); } } return $collection; } private function buildRootPrefix(array $route, string $appName, string $routeNamePrefix): string { $defaultRoot = $appName === 'core' ? '' : '/apps/' . $appName; $root = $route['root'] ?? $defaultRoot; if ($routeNamePrefix !== '') { // In OCS all apps are whitelisted return $root; } if (!\in_array($appName, self::rootUrlApps, true)) { // Only allow root URLS for some apps return $defaultRoot; } return $root; } /** * Based on a given route name the controller name is generated * @param string $controller * @return string */ private function buildControllerName(string $controller): string { if (!isset($this->controllerNameCache[$controller])) { $this->controllerNameCache[$controller] = $this->underScoreToCamelCase(ucfirst($controller)) . 'Controller'; } return $this->controllerNameCache[$controller]; } /** * Based on the action part of the route name the controller method name is generated * @param string $action * @return string */ private function buildActionName(string $action): string { return $this->underScoreToCamelCase($action); } /** * Underscored strings are converted to camel case strings * @param string $str * @return string */ private function underScoreToCamelCase(string $str): string { $pattern = '/_[a-z]?/'; return preg_replace_callback( $pattern, function ($matches) { return strtoupper(ltrim($matches[0], '_')); }, $str); } } #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery UI Accordion - Customize icons</title>
<link rel="stylesheet" href="../../themes/base/jquery.ui.all.css">
<script src="../../jquery-1.6.2.js"></script>
<script src="../../ui/jquery.ui.core.js"></script>
<script src="../../ui/jquery.ui.widget.js"></script>
<script src="../../ui/jquery.ui.accordion.js"></script>
<script src="../../ui/jquery.ui.button.js"></script>
<link rel="stylesheet" href="../demos.css">
<script>
$(function() {
var icons = {
header: "ui-icon-circle-arrow-e",
headerSelected: "ui-icon-circle-arrow-s"
};
$( "#accordion" ).accordion({
icons: icons
});
$( "#toggle" ).button().toggle(function() {
$( "#accordion" ).accordion( "option", "icons", false );
}, function() {
$( "#accordion" ).accordion( "option", "icons", icons );
});
});
</script>
</head>
<body>
<div class="demo">
<div id="accordion">
<h3><a href="#">Section 1</a></h3>
<div>
<p>Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.</p>
</div>
<h3><a href="#">Section 2</a></h3>
<div>
<p>Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In suscipit faucibus urna. </p>
</div>
<h3><a href="#">Section 3</a></h3>
<div>
<p>Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. </p>
<ul>
<li>List item one</li>
<li>List item two</li>
<li>List item three</li>
</ul>
</div>
<h3><a href="#">Section 4</a></h3>
<div>
<p>Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est. </p><p>Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>
</div>
</div>
<button id="toggle">Toggle icons</button>
</div><!-- End demo -->
<div class="demo-description">
<p>Customize the header icons with the <code>icons</code> option, which accepts classes for the header's default and selected (open) state. Use any class from the UI CSS framework, or create custom classes with background images.</p>
</div><!-- End demo-description -->
</body>
</html>