Skip to content

Commit

Permalink
Remove Assetic dependency and add configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Florens Verschelde committed Sep 23, 2016
1 parent 3442702 commit 8b464e9
Show file tree
Hide file tree
Showing 14 changed files with 145 additions and 110 deletions.
41 changes: 24 additions & 17 deletions Controller/StaticController.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,50 @@ class StaticController extends Controller {
*/
public function rootAction() {
return $this->render('@GradientzTwigExpress/root.html.twig', [
'bundles' => Utils::getStaticBundles($this->container)
'bundles' => $this->getParameter('twig_express.bundles')
]);
}

/**
* Find a template to render or a folder whose content to list
* @param string $bundle
* @param string $path
* @return RedirectResponse|Response
*/
public function findAction($bundle, $path) {
/**
* Find a template to render or a folder whose content to list
* @param string $slug Slug identifying a bundle
* @param string $path Path to a resource (starting with '/')
* @return RedirectResponse|Response
* @throws \Exception
*/
public function findAction($slug, $path) {
$cleanPath = Utils::getCleanPath($path);
$cleanRef = preg_replace('/(_|bundle$)/', '', strtolower($bundle));
$pathExt = pathinfo($cleanPath, PATHINFO_EXTENSION);
$showSource = $pathExt === 'twig';

// Base URL for redirects and breadcrumbs (no trailing slash)
$this->baseUrl = $this->generateUrl('gradientz_twig_express_find', [
'bundle' => $cleanRef,
'slug' => $slug,
'path' => ''
]);

// Redirect if we can clean up the URL
if ($cleanRef !== $bundle || $cleanPath !== $path) {
if ($cleanPath !== $path) {
return $this->redirect($this->baseUrl . $cleanPath);
}

// Figure out bundle name and path
$this->bundleName = Utils::findStaticBundle($this->container, $cleanRef);
if (!$this->bundleName) {
// Figure out bundle name
$bundleConfig = $this->getParameter('twig_express.bundles');
if (!array_key_exists($slug, $bundleConfig)) {
$rootUrl = $this->generateUrl('gradientz_twig_express_root');
return $this->redirect($rootUrl . '?was=' . $cleanRef);
return $this->redirect($rootUrl . '?was=' . $slug);
}
$this->bundlePath = rtrim($this->container->get('kernel')->locateResource('@'.$this->bundleName), '/');
$this->bundleName = $bundleConfig[$slug]['name'];

// Check that it's a valid bundle
$allBundles = array_keys($this->get('kernel')->getBundles());
if (!in_array($this->bundleName, $allBundles)) {
throw new \Exception('Unknown bundle "'.$this->bundleName.'". Make sur this bundle is installed and your "twig_express.bundles" config is correct.');
}

// Where is our "document root"?
$docRoot = trim(Utils::VIEWS_ROOT, '/');
$docRoot = $bundleConfig[$slug]['root'];
$this->bundlePath = rtrim($this->container->get('kernel')->locateResource('@'.$this->bundleName), '/');
$this->docRootName = '@'.$this->bundleName . '/' . $docRoot;
$this->docRootPath = $this->bundlePath . '/' . $docRoot;
$basePath = $this->docRootPath . rtrim($cleanPath, '/');
Expand Down
41 changes: 0 additions & 41 deletions Core/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@

class Utils {

// TODO: replace this path with per-bundle, user-defined configuration
const VIEWS_ROOT = 'Resources/views/static';

/**
* Cleans up a local resource path, removing back-slashes, double dots, etc.
* Should not be necessary for content from a URL but let's be on the safe side.
Expand Down Expand Up @@ -48,44 +45,6 @@ static function getMediaType($ext) {
return $type;
}

/**
* List Assetic bundles that have a 'static' views folder
* @param ContainerInterface $container
* @return array|string
*/
static function getStaticBundles($container) {
$matched = [];
$fs = new Filesystem();
$htmlPath = self::VIEWS_ROOT;
$bundles = $container->getParameter('assetic.bundles');

foreach ($bundles as $name) {
$bundlePath = $container->get('kernel')->locateResource('@' . $name);
if ($fs->exists($bundlePath . $htmlPath)) {
$matched[] = $name;
}
}

return $matched;
}

/**
* Find a bundle with 'static' views, matching a case-insensitive string,
* and return the bundle's name
* @param ContainerInterface $container
* @param string $shortName - partial bundle name to match
* @return string|null
*/
static function findStaticBundle($container, $shortName) {
$bundles = self::getStaticBundles($container);
foreach ($bundles as $name) {
if (strtolower($shortName) . 'bundle' === strtolower($name)) {
return $name;
}
}
return null;
}

/**
* Make an associative array with URL=>Name values
* representing the breadcrumbs for a given base URL and path
Expand Down
41 changes: 41 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Gradientz\TwigExpressBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;


class Configuration implements ConfigurationInterface {

public function getConfigTreeBuilder() {
$treeBuilder = new TreeBuilder();
$treeBuilder->root('twig_express')
->children()
->arrayNode('bundles')
->info('List of enabled bundles, with optional per-bundle config')
->prototype('array')
->beforeNormalization()
->ifString()->then(function($v) { return ['name' => $v]; })
->end()
->children()
->scalarNode('name')
->info('Bundle name')
->isRequired()
->end()
->scalarNode('slug')
->info('Short name to use in the URL')
->defaultValue(null)
->end()
->scalarNode('root')
->info('Document root folder from the bundle')
->defaultValue('Resources/views/static')
->end()
->end()
->end()
->end()
->end();
return $treeBuilder;
}

}
43 changes: 43 additions & 0 deletions DependencyInjection/GradientzTwigExpressExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Gradientz\TwigExpressBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;


class GradientzTwigExpressExtension extends Extension {

public function getAlias() {
return 'twig_express';
}

public function load(array $configs, ContainerBuilder $container) {
$config = $this->processConfiguration(new Configuration(), $configs);

// Make sure we have a base_url parameter so we can use it in routes
$baseUrl = $container->getParameter('twig_express.base_url');
if (is_string($baseUrl)) $baseUrl = trim($baseUrl, '/');
if (!$baseUrl) $container->setParameter('twig_express.base_url', 'static');

// Expose configured bundle information
// (Is there a better way to get access to our config from controllers???)
$bundles = [];
foreach($config['bundles'] as $item) {
$name = $item['name'];
$slug = $item['slug'];
// Create slug if necessary, and clean it up
if (!$slug) {
$slug = strtolower($name);
if (substr($slug, -6) === 'bundle') $slug = substr($slug, 0, -6);
}
$slug = str_replace('/', '', $slug);
$root = trim($item['root'], '/');
if (!array_key_exists($slug, $bundles)) {
$bundles[$slug] = ['name' => $name, 'root' => $root];
}
}
$container->setParameter('twig_express.bundles', $bundles);
}

}
8 changes: 7 additions & 1 deletion GradientzTwigExpressBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@

use Symfony\Component\HttpKernel\Bundle\Bundle;

class GradientzTwigExpressBundle extends Bundle {}
class GradientzTwigExpressBundle extends Bundle {

public function getContainerExtension() {
return new DependencyInjection\GradientzTwigExpressExtension();
}

}
11 changes: 7 additions & 4 deletions Resources/config/demo.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Enable bundle for Assetic and GradientzTwigExpressBundle use
assetic:
bundles: [ GradientzTwigExpressBundle ]
# REQUIRED: enable this bundle to be used with GradientzTwigExpressBundle
twig_express:
bundles:
- name: GradientzTwigExpressBundle
slug: twig-express-demo
root: Resources/views/demo

# (Optional) Add to Twig global variables, using a namespace to avoid collisions
# (especially if you have more than one bundle with 'static' views).
twig:
globals:
gradientz_twig_express:
twig_express_demo:
test: 'It works.'
6 changes: 3 additions & 3 deletions Resources/config/routing.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
gradientz_twig_express_root:
path: "/static/"
path: "/%twig_express.base_url%/"
defaults:
_controller: GradientzTwigExpressBundle:Static:root

gradientz_twig_express_find:
path: "/static/{bundle}{path}"
path: "/%twig_express.base_url%/{slug}{path}"
defaults:
_controller: GradientzTwigExpressBundle:Static:find
requirements:
bundle: "[A-Za-z0-9_]+"
slug: "[A-Za-z0-9_-]+"
path: "(\\/?[\\/\\.A-Za-z0-9_-]+)?"
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
</p>
<p>
This config file can also be used to declare global Twig variables. For instance,
this is the <code>gradientz_twig_express.test</code> variable:<br>
this is the <code>twig_express_demo.test</code> variable:<br>
</p>
<pre>{{ gradientz_twig_express.test }}</pre>
<pre>{{ twig_express_demo.test }}</pre>
{% endblock %}
</body>
</html>
1 change: 1 addition & 0 deletions Resources/views/demo/error-demo.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% include '@GradientzTwigExpress/demo/includes/error.twig' %}
File renamed without changes.
5 changes: 4 additions & 1 deletion Resources/views/page.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@
<main>
{% block main %}
{% if code %}
<pre class="Code{%- if ' data-num=' in code %} Code--numbers{% endif %}"><code class="twig">
<pre class="Code
{%- if ' data-num=' in code %} Code--numbers{% endif -%}
{%- if '<mark>' in code %} Code--mark{% endif -%}
"><code class="twig">
{{- code|raw -}}
</code></pre>
{% endif %}
Expand Down
19 changes: 13 additions & 6 deletions Resources/views/root.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,28 @@
{% block main %}
{% if bundles %}
<ul class="Links Links--folders">
{% for bundle in bundles %}
{% for slug,bundle in bundles %}
<li>
<a href="{{ bundle|lower|replace({'bundle':''}) }}/">
<a href="{{ slug }}/">
<svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder"/></svg>
{{ bundle }}
{{ bundle.name }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}

<footer>
<strong>About:</strong>
Static HTML bundles must be referenced in the <code>assetic.bundles</code>
config, and must have a <code>Resources/views/static</code> folder.
<h2>About:</h2>
<p>To add to this list of bundles, add to the <code>twig_express.bundles</code> config key:</p>
<pre>twig_express:
bundles: [ AcmeSuperNiceBundle ]</pre>
<p>You can also give more explicit config, including the URL slug to use and the path to the views you want to give access to:</p>
<pre>twig_express:
bundles:
- name: AcmeSuperNiceBundle
slug: super-nice
root: Resources/views/custom-dir</pre>
</footer>

{% endblock %}
1 change: 0 additions & 1 deletion Resources/views/static/2-error-demo.html.twig

This file was deleted.

34 changes: 0 additions & 34 deletions Resources/views/static/3-assetic-demo.html.twig

This file was deleted.

0 comments on commit 8b464e9

Please sign in to comment.