diff --git a/.travis.yml b/.travis.yml
index 65a5b39..bdc180c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,8 @@ php:
- 5.6
- 7.0
- 7.1
- - hhvm
+ - 7.2
+ - 7.3
before_script: composer install
diff --git a/README.md b/README.md
index 50a0b2f..fc6ba9d 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
[](https://travis-ci.org/slimphp/Twig-View)
-This is a Slim Framework view helper built on top of the Twig templating component. You can use this component to create and render templates in your Slim Framework application. It works with Twig 1.18+ (PHP5.5+) and with Twig 2 (PHP7).
+This is a Slim Framework view helper built on top of the Twig templating component. You can use this component to create and render templates in your Slim Framework application. It works with Twig 1.18+ (PHP5.5+), Twig 2 (PHP7) and Twig 3.
Requires Slim Framework 3 and PHP 5.5.0 or newer.
@@ -72,7 +72,7 @@ You can use `path_for` to generate complete URLs to any Slim application named r
{% block body %}
User List
{% endblock %}
diff --git a/composer.json b/composer.json
index 2604889..b374b76 100644
--- a/composer.json
+++ b/composer.json
@@ -14,7 +14,7 @@
],
"require": {
"php": ">=5.5.0",
- "twig/twig": "^1.18|^2.0",
+ "twig/twig": "^1.38|^2.7|^3.0",
"psr/http-message": "^1.0"
},
"require-dev": {
diff --git a/src/Twig.php b/src/Twig.php
index cc94ba9..8a55c7f 100644
--- a/src/Twig.php
+++ b/src/Twig.php
@@ -24,14 +24,14 @@ class Twig implements \ArrayAccess
/**
* Twig loader
*
- * @var \Twig_LoaderInterface
+ * @var \Twig\Loader\LoaderInterface
*/
protected $loader;
/**
* Twig environment
*
- * @var \Twig_Environment
+ * @var \Twig\Environment
*/
protected $environment;
@@ -54,7 +54,8 @@ class Twig implements \ArrayAccess
*/
public function __construct($loader, $settings = [])
{
- $this->environment = new \Twig_Environment($loader, $settings);
+ $this->environment = new \Twig\Environment($loader, $settings);
+ $this->loader = $loader;
}
/********************************************************************************
@@ -64,9 +65,9 @@ public function __construct($loader, $settings = [])
/**
* Proxy method to add an extension to the Twig environment
*
- * @param \Twig_ExtensionInterface $extension A single extension instance or an array of instances
+ * @param \Twig\Extension\ExtensionInterface $extension A single extension instance or an array of instances
*/
- public function addExtension(\Twig_ExtensionInterface $extension)
+ public function addExtension(\Twig\Extension\ExtensionInterface $extension)
{
$this->environment->addExtension($extension);
}
@@ -78,6 +79,10 @@ public function addExtension(\Twig_ExtensionInterface $extension)
* @param string $template Template pathname relative to templates directory
* @param array $data Associative array of template variables
*
+ * @throws \Twig\Error\LoaderError When the template cannot be found
+ * @throws \Twig_Error\SyntaxError When an error occurred during compilation
+ * @throws \Twig_Error\RuntimeError When an error occurred during rendering
+ *
* @return string
*/
public function fetch($template, $data = [])
@@ -100,7 +105,7 @@ public function fetchBlock($template, $block, $data = [])
{
$data = array_merge($this->defaultVariables, $data);
- return $this->environment->loadTemplate($template)->renderBlock($block, $data);
+ return $this->environment->load($template)->renderBlock($block, $data);
}
/**
@@ -137,11 +142,11 @@ public function render(ResponseInterface $response, $template, $data = [])
* Create a loader with the given path
*
* @param array $paths
- * @return \Twig_Loader_Filesystem
+ * @return \Twig\Loader\FilesystemLoader
*/
public function createFilesystemLoader(array $paths)
{
- $loader = new \Twig_Loader_Filesystem();
+ $loader = new \Twig\Loader\FilesystemLoader();
foreach ($paths as $namespace => $path) {
if (is_string($namespace)) {
@@ -173,7 +178,7 @@ public function createArrayLoader(array $templates)
/**
* Return Twig loader
*
- * @return \Twig_LoaderInterface
+ * @return \Twig\Loader\LoaderInterface
*/
public function getLoader()
{
@@ -183,7 +188,7 @@ public function getLoader()
/**
* Return Twig environment
*
- * @return \Twig_Environment
+ * @return \Twig\Environment
*/
public function getEnvironment()
{
diff --git a/src/TwigExtension.php b/src/TwigExtension.php
index 806de14..e4ca999 100644
--- a/src/TwigExtension.php
+++ b/src/TwigExtension.php
@@ -8,7 +8,9 @@
*/
namespace Slim\Views;
-class TwigExtension extends \Twig_Extension
+use Slim\Http\Uri;
+
+class TwigExtension extends \Twig\Extension\AbstractExtension
{
/**
* @var \Slim\Interfaces\RouterInterface
@@ -34,10 +36,11 @@ public function getName()
public function getFunctions()
{
return [
- new \Twig_SimpleFunction('path_for', array($this, 'pathFor')),
- new \Twig_SimpleFunction('base_url', array($this, 'baseUrl')),
- new \Twig_SimpleFunction('is_current_path', array($this, 'isCurrentPath')),
- new \Twig_SimpleFunction('current_path', array($this, 'currentPath')),
+ new \Twig\TwigFunction('path_for', array($this, 'pathFor')),
+ new \Twig\TwigFunction('full_url_for', array($this, 'fullUrlFor')),
+ new \Twig\TwigFunction('base_url', array($this, 'baseUrl')),
+ new \Twig\TwigFunction('is_current_path', array($this, 'isCurrentPath')),
+ new \Twig\TwigFunction('current_path', array($this, 'currentPath')),
];
}
@@ -46,6 +49,35 @@ public function pathFor($name, $data = [], $queryParams = [], $appName = 'defaul
return $this->router->pathFor($name, $data, $queryParams);
}
+ /**
+ * Similar to pathFor but returns a fully qualified URL
+ *
+ * @param string $name The name of the route
+ * @param array $data Route placeholders
+ * @param array $queryParams
+ * @param string $appName
+ * @return string fully qualified URL
+ */
+ public function fullUrlFor($name, $data = [], $queryParams = [], $appName = 'default')
+ {
+ $path = $this->pathFor($name, $data, $queryParams, $appName);
+
+ /** @var Uri $uri */
+ if (is_string($this->uri)) {
+ $uri = Uri::createFromString($this->uri);
+ } else {
+ $uri = $this->uri;
+ }
+
+ $scheme = $uri->getScheme();
+ $authority = $uri->getAuthority();
+
+ $host = ($scheme ? $scheme . ':' : '')
+ . ($authority ? '//' . $authority : '');
+
+ return $host.$path;
+ }
+
public function baseUrl()
{
if (is_string($this->uri)) {
diff --git a/tests/TwigExtensionTest.php b/tests/TwigExtensionTest.php
index fe04c04..a69a4fe 100644
--- a/tests/TwigExtensionTest.php
+++ b/tests/TwigExtensionTest.php
@@ -74,4 +74,18 @@ public function testCurrentPath($router, $uri, $withQueryString, $expected)
$this->assertEquals($expected, $result);
}
+
+ public function testFullUrlFor()
+ {
+ $router = new Router();
+ $router->setBasePath('/app');
+ $router->map(['GET'], '/activate/{token}', null)->setName('activate');
+ $uri = Uri::createFromString('http://example.com/app/hello/world?a=b');
+
+ $extension = new TwigExtension($router, $uri);
+ $result = $extension->fullUrlFor('activate', ['token' => 'foo']);
+
+ $expected = 'http://example.com/app/activate/foo';
+ $this->assertEquals($expected, $result);
+ }
}