diff options
author | Arnold Daniels <arnold@jasny.net> | 2017-01-12 23:52:12 +0100 |
---|---|---|
committer | Arnold Daniels <arnold@jasny.net> | 2017-01-12 23:52:12 +0100 |
commit | d11daf0b234296d37ce113e6914bac8b42ac4c6b (patch) | |
tree | b3358020b519751adffd039ec3ef264bdbf00688 | |
parent | bf185a308f3e727316be70bc35072bb4dbfe45be (diff) | |
download | view-d11daf0b234296d37ce113e6914bac8b42ac4c6b.zip view-d11daf0b234296d37ce113e6914bac8b42ac4c6b.tar.gz view-d11daf0b234296d37ce113e6914bac8b42ac4c6b.tar.bz2 |
Moved view logic from controller library to this lib
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | .travis.yml | 21 | ||||
-rw-r--r-- | README.md | 0 | ||||
-rw-r--r-- | composer.json | 35 | ||||
-rw-r--r-- | phpunit.xml.dist | 24 | ||||
-rw-r--r-- | src/View/Twig.php | 166 | ||||
-rw-r--r-- | src/ViewInterface.php | 31 |
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 = []); +} |