summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold Daniels <arnold@jasny.net>2017-01-12 23:52:12 +0100
committerArnold Daniels <arnold@jasny.net>2017-01-12 23:52:12 +0100
commitd11daf0b234296d37ce113e6914bac8b42ac4c6b (patch)
treeb3358020b519751adffd039ec3ef264bdbf00688
parentbf185a308f3e727316be70bc35072bb4dbfe45be (diff)
downloadview-d11daf0b234296d37ce113e6914bac8b42ac4c6b.zip
view-d11daf0b234296d37ce113e6914bac8b42ac4c6b.tar.gz
view-d11daf0b234296d37ce113e6914bac8b42ac4c6b.tar.bz2
Moved view logic from controller library to this lib
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml21
-rw-r--r--README.md0
-rw-r--r--composer.json35
-rw-r--r--phpunit.xml.dist24
-rw-r--r--src/View/Twig.php166
-rw-r--r--src/ViewInterface.php31
7 files changed, 279 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8b7ef35
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/vendor
+composer.lock
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..d1f4a6c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,21 @@
+language: php
+
+php:
+ - 5.6
+ - 7.0
+ - 7.1
+
+branches:
+ only:
+ - master
+
+install:
+ - composer install
+ - wget https://scrutinizer-ci.com/ocular.phar -O "$HOME/ocular.phar"
+
+script:
+ - vendor/bin/phpunit --coverage-clover cache/logs/clover.xml
+
+after_success:
+ - php "$HOME/ocular.phar" code-coverage:upload --format=php-clover cache/logs/clover.xml
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..cdfae3e
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "jasny/view",
+ "description": "An abstraction for using PSR-7 with template engines",
+ "keywords": ["MVC", "view", "templates", "PSR-7"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Arnold Daniels",
+ "email": "arnold@jasny.net",
+ "homepage": "http://www.jasny.net"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/jasny/view/issues",
+ "source": "https://github.com/jasny/view"
+ },
+ "require": {
+ "php": ">=5.6.0",
+ "psr/http-message": "^1.0"
+ },
+ "require-dev": {
+ "jasny/php-code-quality": "^2.0",
+ "jasny/twig-extensions": "^1.0",
+ "twig/twig": "^1.31"
+ },
+ "suggest": {
+ "twig/twig": "Needed to work with Twig templates",
+ "jasny/twig-extensions": "Useful extensions for Twig"
+ },
+ "autoload": {
+ "psr-4": {
+ "Jasny\\": "src/"
+ }
+ }
+}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..1861d7c
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit
+ colors="true"
+ bootstrap="vendor/autoload.php"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+>
+ <testsuites>
+ <testsuite>
+ <directory>tests/</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist processUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">src</directory>
+ </whitelist>
+ </filter>
+ <logging>
+ <log type="coverage-text" target="php://stdout"/>
+ </logging>
+</phpunit>
+
diff --git a/src/View/Twig.php b/src/View/Twig.php
new file mode 100644
index 0000000..c9e4798
--- /dev/null
+++ b/src/View/Twig.php
@@ -0,0 +1,166 @@
+<?php
+
+namespace Jasny\View;
+
+use Jasny\ViewInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Abstraction to use Twig with PSR-7
+ */
+class Twig implements ViewInterface
+{
+ /**
+ * Twig environment
+ * @var \Twig_Environment
+ */
+ protected $twig;
+
+
+ /**
+ * Class constructor
+ *
+ * @param \Twig_Environment|array $options
+ */
+ public function __construct($options)
+ {
+ if (is_array($options)) {
+ if (!isset($options['path'])) {
+ throw new \BadMethodCallException("'path' option is required");
+ }
+
+ $loader = new \Twig_Loader_Filesystem($options['path']);
+ $twig = new \Twig_Environment($loader);
+ } else {
+ $twig = $options;
+ }
+
+ if (!$twig instanceof \Twig_Environment) {
+ throw new \InvalidArgumentException("Was expecting an array with options or a Twig_Environment, got a "
+ . (is_object($twig) ? get_class($twig) . ' ' : '') . gettype($twig));
+ }
+
+ $this->twig = $twig;
+ }
+
+ /**
+ * Get Twig environment
+ *
+ * @return \Twig_Environment
+ */
+ public function getTwig()
+ {
+ return $this->twig;
+ }
+
+
+ /**
+ * Assert valid variable, function and filter name
+ *
+ * @param string $name
+ * @throws \InvalidArgumentException
+ */
+ protected function assertViewVariableName($name)
+ {
+ if (!is_string($name)) {
+ $type = (is_object($name) ? get_class($name) . ' ' : '') . gettype($name);
+ throw new \InvalidArgumentException("Expected name to be a string, not a $type");
+ }
+
+ if (!preg_match('/^[a-z]\w*$/i', $name)) {
+ throw new \InvalidArgumentException("Invalid name '$name'");
+ }
+ }
+
+ /**
+ * Expose a function to the view.
+ *
+ * @param string $name Function name in template
+ * @param callable|null $function
+ * @param string $as 'function' or 'filter'
+ * @return $this
+ */
+ public function expose($name, $function = null, $as = 'function')
+ {
+ $this->assertViewVariableName($name);
+
+ if ($as === 'function') {
+ $function = new \Twig_SimpleFunction($name, $function ?: $name);
+ $this->getTwig()->addFunction($function);
+ } elseif ($as === 'filter') {
+ $filter = new \Twig_SimpleFilter($name, $function ?: $name);
+ $this->getTwig()->addFilter($filter);
+ } else {
+ $not = is_string($as) ? "'$as'" : 'a ' . gettype($as);
+ throw new \InvalidArgumentException("You should create either a 'function' or 'filter', not $not");
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add the official Twig extension and Jansy Twig extensions.
+ *
+ * @link https://github.com/twigphp/Twig-extensions
+ * @link https://github.com/jasny/twig-extensions
+ *
+ * @return $this
+ */
+ public function addDefaultExtensions()
+ {
+ $extensions = [
+ 'Twig_Extensions_Extension_Array',
+ 'Twig_Extensions_Extension_Date',
+ 'Twig_Extensions_Extension_I18n',
+ 'Twig_Extensions_Extension_Intl',
+ 'Twig_Extensions_Extension_Text',
+ 'Jasny\Twig\DateExtension',
+ 'Jasny\Twig\PcreExtension',
+ 'Jasny\Twig\TextExtension',
+ 'Jasny\Twig\ArrayExtension'
+ ];
+
+ foreach ($extensions as $class) {
+ if (class_exists($class)) {
+ $this->getTwig()->addExtension(new $class());
+ }
+ }
+ }
+
+ /**
+ * Add a twig extension
+ *
+ * @param \Twig_ExtensionInterface $extension
+ * @return $this
+ */
+ public function addExtension(\Twig_ExtensionInterface $extension)
+ {
+ $this->getTwig()->addExtension($extension);
+ }
+
+
+ /**
+ * Render and output template
+ *
+ * @param ResponseInterface $response
+ * @param string $name Template name
+ * @param array $context Template context as associated array
+ * @return ResponseInterface
+ */
+ public function view(ResponseInterface $response, $name, array $context = [])
+ {
+ if (!pathinfo($name, PATHINFO_EXTENSION)) {
+ $name .= '.html.twig';
+ }
+
+ $twig = $this->getTwig();
+ $tmpl = $twig->loadTemplate($name);
+
+ $contents = $tmpl->render($context);
+
+ $newResponse = $response->withHeader('Content-Type', 'text/html; charset=' . $twig->getCharset());
+ $newResponse->getBody()->write($contents);
+
+ return $newResponse;
+ }
+}
diff --git a/src/ViewInterface.php b/src/ViewInterface.php
new file mode 100644
index 0000000..fe5a5a2
--- /dev/null
+++ b/src/ViewInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Jasny;
+
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Interface for abstracting over template engine.
+ */
+interface ViewInterface
+{
+ /**
+ * Expose a function to the view.
+ *
+ * @param string $name Function name in template
+ * @param callable|null $function
+ * @return $this
+ * @throws \BadMethodCallException if function can't be exposed
+ */
+ public function expose($name, $function = null);
+
+ /**
+ * Render and output template
+ *
+ * @param ResponseInterface $response
+ * @param string $name Template name
+ * @param array $context Template context as associated array
+ * @return ResponseInterface
+ */
+ public function view(ResponseInterface $response, $name, array $context = []);
+}