Исключить воспроизводимые зависимости Composer из Git
Сохранить ручные библиотеки, изменённые и непроверенные пакеты. Добавить исключения и порядок восстановления зависимостей.
This commit is contained in:
1 parent
e955e1da36
commit
d4e51a5dc2
3821 files changed
+45
-588946
No files matched your search
+29
-1
@@ -2,4 +2,32 @@ tmp
|
|||||||
logs
|
logs
|
||||||
.idea
|
.idea
|
||||||
files
|
files
|
||||||
archive/*
|
archive/*
|
||||||
|
|
||||||
|
# Зависимости Composer без локальных изменений не храним в Git.
|
||||||
|
/vendor/*
|
||||||
|
!/vendor/browser_detection/
|
||||||
|
!/vendor/dbf/
|
||||||
|
!/vendor/sms/
|
||||||
|
!/vendor/cakephp/
|
||||||
|
/vendor/cakephp/*
|
||||||
|
!/vendor/cakephp/cakephp/
|
||||||
|
!/vendor/composer/
|
||||||
|
/vendor/composer/*
|
||||||
|
!/vendor/composer/composer/
|
||||||
|
!/vendor/dompdf/
|
||||||
|
/vendor/dompdf/*
|
||||||
|
!/vendor/dompdf/dompdf/
|
||||||
|
!/vendor/m1/
|
||||||
|
/vendor/m1/*
|
||||||
|
!/vendor/m1/env/
|
||||||
|
!/vendor/parsecsv/
|
||||||
|
/vendor/parsecsv/*
|
||||||
|
!/vendor/parsecsv/php-parsecsv/
|
||||||
|
!/vendor/squizlabs/
|
||||||
|
/vendor/squizlabs/*
|
||||||
|
!/vendor/squizlabs/php_codesniffer/
|
||||||
|
!/vendor/symfony/
|
||||||
|
/vendor/symfony/*
|
||||||
|
!/vendor/symfony/debug/
|
||||||
|
!/vendor/empty
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Зависимости приложения
|
||||||
|
|
||||||
|
Версии зависимостей зафиксированы в `composer.lock`. Пакеты, совпавшие с
|
||||||
|
официальными архивами этих версий, и создаваемые Composer служебные файлы
|
||||||
|
исключены из Git.
|
||||||
|
|
||||||
|
В `vendor` сохранены ручные DBF/SMS/BrowserDetection-библиотеки, пакеты с
|
||||||
|
локальными отличиями и пакеты без подтверждённого эталона. В том числе
|
||||||
|
сохраняются правки CakePHP и дополнительные шрифты Dompdf. Состав каталогов
|
||||||
|
задан исключениями в `.gitignore`.
|
||||||
|
|
||||||
|
Перед восстановлением зависимостей нужно сохранить отслеживаемую часть
|
||||||
|
`vendor` в отдельную копию. После восстановления пакетов по `composer.lock`
|
||||||
|
в изолированном окружении сохранённые файлы возвращаются поверх пакетов.
|
||||||
|
Это сохраняет существующие правки и шрифты; слепая переустановка может их
|
||||||
|
перезаписать. Восстановление и проверка работы приложения выполняются отдельно.
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
/vendor/
|
|
||||||
*.cache
|
|
||||||
composer.lock
|
|
||||||
phpunit.xml
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
$header = <<<EOF
|
|
||||||
AJGL Breakpoint Twig Extension Component
|
|
||||||
|
|
||||||
Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
|
|
||||||
For the full copyright and license information, please view the LICENSE
|
|
||||||
file that was distributed with this source code.
|
|
||||||
EOF;
|
|
||||||
|
|
||||||
return \PhpCsFixer\Config::create()
|
|
||||||
->setRiskyAllowed(true)
|
|
||||||
->setRules(
|
|
||||||
[
|
|
||||||
'@Symfony' => true,
|
|
||||||
'@Symfony:risky' => true,
|
|
||||||
'array_syntax' => array('syntax' => 'short'),
|
|
||||||
'fully_qualified_strict_types' => true,
|
|
||||||
'header_comment' => array('header' => $header),
|
|
||||||
'native_function_invocation' => false,
|
|
||||||
'ordered_imports' => [
|
|
||||||
'imports_order' => ['class', 'const', 'function'],
|
|
||||||
],
|
|
||||||
'phpdoc_order' => true,
|
|
||||||
'psr4' => true,
|
|
||||||
'strict_comparison' => true,
|
|
||||||
'strict_param' => true,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
->setFinder(
|
|
||||||
\PhpCsFixer\Finder::create()
|
|
||||||
->in(__DIR__.'/src')
|
|
||||||
->in(__DIR__.'/tests')
|
|
||||||
)
|
|
||||||
;
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# .scrutinizer.yml
|
|
||||||
checks:
|
|
||||||
php: true
|
|
||||||
|
|
||||||
tools:
|
|
||||||
external_code_coverage:
|
|
||||||
timeout: 900
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
language: php
|
|
||||||
sudo: false
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.composer/cache/files
|
|
||||||
- $HOME/symfony-bridge/.phpunit
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- PHPUNIT_FLAGS="-v"
|
|
||||||
- SYMFONY_PHPUNIT_DIR="$HOME/symfony-bridge/.phpunit"
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
include:
|
|
||||||
# Minimum supported dependencies with the latest and oldest PHP version
|
|
||||||
- php: 7.3
|
|
||||||
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
|
|
||||||
- php: 5.6
|
|
||||||
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
|
|
||||||
|
|
||||||
# Test the latest stable release
|
|
||||||
- php: 5.6
|
|
||||||
- php: 7.0
|
|
||||||
- php: 7.1
|
|
||||||
- php: 7.2
|
|
||||||
- php: 7.3
|
|
||||||
env: COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text" LINT=true
|
|
||||||
|
|
||||||
# Test LTS versions. This makes sure we do not use Symfony packages with version greater
|
|
||||||
# than 2 or 3 respectively. Read more at https://github.com/symfony/lts
|
|
||||||
- php: 7.3
|
|
||||||
env: DEPENDENCIES="symfony/lts:^2"
|
|
||||||
- php: 7.3
|
|
||||||
env: DEPENDENCIES="symfony/lts:^3"
|
|
||||||
|
|
||||||
# Latest commit to master
|
|
||||||
- php: 7.3
|
|
||||||
env: STABILITY="dev"
|
|
||||||
- php: 7.4
|
|
||||||
env: STABILITY="dev"
|
|
||||||
- php: nightly
|
|
||||||
env: STABILITY="dev"
|
|
||||||
|
|
||||||
allow_failures:
|
|
||||||
# Dev-master is allowed to fail.
|
|
||||||
- env: STABILITY="dev"
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi
|
|
||||||
- if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; fi;
|
|
||||||
- if ! [ -v "$DEPENDENCIES" ]; then composer require --no-update ${DEPENDENCIES}; fi;
|
|
||||||
- if [[ $LINT = true ]]; then wget https://cs.symfony.com/download/php-cs-fixer-v2.phar; fi
|
|
||||||
|
|
||||||
install:
|
|
||||||
- composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
|
|
||||||
- ./vendor/bin/simple-phpunit install
|
|
||||||
|
|
||||||
script:
|
|
||||||
- composer validate --strict --no-check-lock
|
|
||||||
- if [[ $LINT = true ]]; then php php-cs-fixer-v2.phar fix --dry-run --diff --no-ansi; fi
|
|
||||||
# simple-phpunit is the PHPUnit wrapper provided by the PHPUnit Bridge component and
|
|
||||||
# it helps with testing legacy code and deprecations (composer require symfony/phpunit-bridge)
|
|
||||||
- ./vendor/bin/simple-phpunit $PHPUNIT_FLAGS
|
|
||||||
|
|
||||||
after_script:
|
|
||||||
- wget https://scrutinizer-ci.com/ocular.phar
|
|
||||||
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
# [CHANGELOG](http://keepachangelog.com/)
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
||||||
|
|
||||||
## [Unreleased][unreleased]
|
|
||||||
|
|
||||||
|
|
||||||
## [0.3.4] - 2019-04-10
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Population of `$arguments` variable
|
|
||||||
|
|
||||||
|
|
||||||
## [0.3.3] - 2019-03-18
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Population of `$arguments` variable
|
|
||||||
- Usage of deprecated classes
|
|
||||||
|
|
||||||
|
|
||||||
## [0.3.2] - 2018-12-10
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Add support for Symfony 4
|
|
||||||
|
|
||||||
## [0.3.1] - 2017-11-20
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Require PHP 5.6
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Update requirements to allow twig 2.x
|
|
||||||
|
|
||||||
|
|
||||||
## [0.3.0] - 2016-03-31
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Add `$environment` and `$context` variables
|
|
||||||
- Allow to inspect function arguments
|
|
||||||
|
|
||||||
|
|
||||||
## [0.2.0] - 2016-03-10
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Add Symfony Bundle
|
|
||||||
|
|
||||||
|
|
||||||
## 0.1.0 - 2016-03-09
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Add `breakpoint` function
|
|
||||||
|
|
||||||
|
|
||||||
[unreleased]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.4...master
|
|
||||||
[0.3.4]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.3...0.3.4
|
|
||||||
[0.3.3]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.2...0.3.3
|
|
||||||
[0.3.2]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.1...0.3.2
|
|
||||||
[0.3.1]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.3.0...0.3.1
|
|
||||||
[0.3.0]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.2.0...0.3.0
|
|
||||||
[0.2.0]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/compare/0.1.0...0.2.0
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
Copyright (c) 2013-2016 Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
|
||||||
person obtaining a copy of this software and associated
|
|
||||||
documentation files (the "Software"), to deal in the
|
|
||||||
Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the
|
|
||||||
Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice
|
|
||||||
shall be included in all copies or substantial portions of
|
|
||||||
the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
||||||
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
|
||||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
||||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
||||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
-124
@@ -1,124 +0,0 @@
|
|||||||
AjglBreakpointTwigExtension
|
|
||||||
===========================
|
|
||||||
|
|
||||||
The AjglBreakpointTwigExtension component allows you set breakpoints in twig templates.
|
|
||||||
|
|
||||||
[](https://travis-ci.org/ajgarlag/AjglBreakpointTwigExtension)
|
|
||||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
|
||||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
|
||||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
|
||||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
|
||||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
|
||||||
[](https://packagist.org/packages/ajgl/breakpoint-twig-extension)
|
|
||||||
[](https://scrutinizer-ci.com/g/ajgarlag/AjglBreakpointTwigExtension/?branch=master)
|
|
||||||
[](https://scrutinizer-ci.com/g/ajgarlag/AjglBreakpointTwigExtension/?branch=master)
|
|
||||||
[](https://insight.sensiolabs.com/projects/e0f1276d-6ded-4a20-9b3f-1a7c77a92015)
|
|
||||||
|
|
||||||
This component requires the [Xdebug] PHP extension to be installed.
|
|
||||||
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
To install the latest stable version of this component, open a console and execute the following command:
|
|
||||||
```
|
|
||||||
$ composer require ajgl/breakpoint-twig-extension
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
The first step is to register the extension into the twig environment
|
|
||||||
```php
|
|
||||||
/* @var $twig Twig_Environment */
|
|
||||||
$twig->addExtension(new Ajgl\Twig\Extension\BreakpointExtension());
|
|
||||||
```
|
|
||||||
|
|
||||||
Once registered, you can call the new `breakpoint` function:
|
|
||||||
```twig
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>title</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{{ breakpoint() }}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
Once stopped, your debugger will allow you to inspect the `$environment` and `$context` variables.
|
|
||||||
|
|
||||||
### Function arguments
|
|
||||||
|
|
||||||
Any argument passed to the twig function will be added to the `$arguments` array, so you can inspect it easily.
|
|
||||||
|
|
||||||
```twig
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>title</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{{ breakpoint(app.user, app.session) }}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
Symfony Bundle
|
|
||||||
--------------
|
|
||||||
|
|
||||||
If you want to use this extension in your Symfony application, you can enable the
|
|
||||||
Symfony Bundle included in this package.
|
|
||||||
|
|
||||||
The bundle will register the twig extension automatically. So, once enabled, you
|
|
||||||
can insert the `breakpoint` twig function in your templates.
|
|
||||||
|
|
||||||
### Symfony 2/3
|
|
||||||
|
|
||||||
```php
|
|
||||||
// app/AppKernel.php
|
|
||||||
if (in_array($this->getEnvironment(), array('dev', 'test'), true)) {
|
|
||||||
$bundles[] = new Ajgl\Twig\Extension\SymfonyBundle\AjglBreakpointTwigExtensionBundle();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Symfony 4
|
|
||||||
|
|
||||||
```php
|
|
||||||
// config/bundles.php
|
|
||||||
//...
|
|
||||||
return [
|
|
||||||
//...
|
|
||||||
Ajgl\Twig\Extension\SymfonyBundle\AjglBreakpointTwigExtensionBundle::class => ['dev' => true]
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
This component is under the MIT license. See the complete license in the [LICENSE] file.
|
|
||||||
|
|
||||||
|
|
||||||
Reporting an issue or a feature request
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
Issues and feature requests are tracked in the [Github issue tracker].
|
|
||||||
|
|
||||||
|
|
||||||
Author Information
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Developed with ♥ by [Antonio J. García Lagar].
|
|
||||||
|
|
||||||
If you find this component useful, please add a ★ in the [GitHub repository page] and/or the [Packagist package page].
|
|
||||||
|
|
||||||
[Xdebug]: https://xdebug.org/
|
|
||||||
[LICENSE]: LICENSE
|
|
||||||
[Github issue tracker]: https://github.com/ajgarlag/AjglBreakpointTwigExtension/issues
|
|
||||||
[Antonio J. García Lagar]: http://aj.garcialagar.es
|
|
||||||
[GitHub repository page]: https://github.com/ajgarlag/AjglBreakpointTwigExtension
|
|
||||||
[Packagist package page]: https://packagist.org/packages/ajgl/breakpoint-twig-extension
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "ajgl/breakpoint-twig-extension",
|
|
||||||
"description": "Twig extension to set breakpoints",
|
|
||||||
"keywords": ["twig", "xdebug", "breakpoint"],
|
|
||||||
"homepage": "https://github.com/ajgarlag/AjglBreakpointTwigExtension",
|
|
||||||
"license": "MIT",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Antonio J. García Lagar",
|
|
||||||
"email": "aj@garcialagar.es",
|
|
||||||
"homepage": "http://aj.garcialagar.es",
|
|
||||||
"role": "developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": { "Ajgl\\Twig\\Extension\\": "src/" }
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": { "Ajgl\\Twig\\Extension\\Tests\\": "tests/" }
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.6",
|
|
||||||
"twig/twig": "^1.14|^2.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"symfony/framework-bundle": "^2.7|^3.2|^4.1",
|
|
||||||
"symfony/twig-bundle": "^2.7|^3.2|^4.1",
|
|
||||||
"symfony/phpunit-bridge": "^3.4|^4.1"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-xdebug": "The Xdebug extension is required for the breakpoint to work",
|
|
||||||
"symfony/framework-bundle": "The framework bundle to integrate the extension into Symfony",
|
|
||||||
"symfony/twig-bundle": "The twig bundle to integrate the extension into Symfony"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"phpunit": "vendor/bin/simple-phpunit --colors=always",
|
|
||||||
"test": [
|
|
||||||
"@phpunit"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "0.3.x-dev"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<phpunit
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.0/phpunit.xsd"
|
|
||||||
backupGlobals="false"
|
|
||||||
colors="true"
|
|
||||||
bootstrap="vendor/autoload.php"
|
|
||||||
>
|
|
||||||
|
|
||||||
<testsuites>
|
|
||||||
<testsuite name="AjglBreakpointTwigExtension Test Suite">
|
|
||||||
<directory>./tests</directory>
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
||||||
|
|
||||||
<filter>
|
|
||||||
<whitelist>
|
|
||||||
<directory>./src</directory>
|
|
||||||
</whitelist>
|
|
||||||
</filter>
|
|
||||||
|
|
||||||
</phpunit>
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AJGL Breakpoint Twig Extension Component
|
|
||||||
*
|
|
||||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Ajgl\Twig\Extension;
|
|
||||||
|
|
||||||
use Twig\Environment;
|
|
||||||
use Twig\Extension\AbstractExtension;
|
|
||||||
use Twig\TwigFunction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*/
|
|
||||||
class BreakpointExtension extends AbstractExtension
|
|
||||||
{
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return 'breakpoint';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFunctions()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
new TwigFunction('breakpoint', [$this, 'setBreakpoint'], ['needs_environment' => true, 'needs_context' => true]),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If Xdebug is detected, makes the debugger break.
|
|
||||||
*
|
|
||||||
* @param Environment $environment the environment instance
|
|
||||||
* @param mixed $context variables from the Twig template
|
|
||||||
*/
|
|
||||||
public function setBreakpoint(Environment $environment, $context)
|
|
||||||
{
|
|
||||||
if (function_exists('xdebug_break')) {
|
|
||||||
$arguments = func_get_args();
|
|
||||||
$arguments = array_slice($arguments, 2);
|
|
||||||
xdebug_break();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-21
@@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AJGL Breakpoint Twig Extension Component
|
|
||||||
*
|
|
||||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Ajgl\Twig\Extension\SymfonyBundle;
|
|
||||||
|
|
||||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*/
|
|
||||||
class AjglBreakpointTwigExtensionBundle extends Bundle
|
|
||||||
{
|
|
||||||
}
|
|
||||||
-29
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AJGL Breakpoint Twig Extension Component
|
|
||||||
*
|
|
||||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Ajgl\Twig\Extension\SymfonyBundle\DependencyInjection;
|
|
||||||
|
|
||||||
use Symfony\Component\Config\FileLocator;
|
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|
||||||
use Symfony\Component\DependencyInjection\Loader;
|
|
||||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*/
|
|
||||||
class AjglBreakpointTwigExtensionExtension extends Extension
|
|
||||||
{
|
|
||||||
public function load(array $config, ContainerBuilder $container)
|
|
||||||
{
|
|
||||||
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
|
||||||
$loader->load('twig.xml');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
|
|
||||||
<container xmlns="http://symfony.com/schema/dic/services"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
|
||||||
|
|
||||||
<services>
|
|
||||||
<service id="ajgl_twig_extension.breakpoint" class="Ajgl\Twig\Extension\BreakpointExtension" public="false">
|
|
||||||
<tag name="twig.extension"/>
|
|
||||||
</service>
|
|
||||||
</services>
|
|
||||||
|
|
||||||
</container>
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AJGL Breakpoint Twig Extension Component
|
|
||||||
*
|
|
||||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Ajgl\Twig\Extension\Tests;
|
|
||||||
|
|
||||||
use Ajgl\Twig\Extension\BreakpointExtension;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*/
|
|
||||||
class BreakpointExtensionTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var BreakpointExtension
|
|
||||||
*/
|
|
||||||
protected $extension;
|
|
||||||
|
|
||||||
protected function setUp()
|
|
||||||
{
|
|
||||||
$this->extension = new BreakpointExtension();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetName()
|
|
||||||
{
|
|
||||||
$this->assertSame('breakpoint', $this->extension->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetFunctions()
|
|
||||||
{
|
|
||||||
$functions = $this->extension->getFunctions();
|
|
||||||
$this->assertCount(1, $functions);
|
|
||||||
$function = reset($functions);
|
|
||||||
$this->assertInstanceOf('Twig_SimpleFunction', $function);
|
|
||||||
$callable = $function->getCallable();
|
|
||||||
$this->assertTrue(is_array($callable));
|
|
||||||
$this->assertCount(2, $callable);
|
|
||||||
$this->assertSame($this->extension, $callable[0]);
|
|
||||||
$this->assertSame('setBreakpoint', $callable[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-50
@@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AJGL Breakpoint Twig Extension Component
|
|
||||||
*
|
|
||||||
* Copyright (C) Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Ajgl\Twig\Extension\Tests\SymfonyBundle\DependencyInjection;
|
|
||||||
|
|
||||||
use Ajgl\Twig\Extension\SymfonyBundle\DependencyInjection\AjglBreakpointTwigExtensionExtension;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Antonio J. García Lagar <aj@garcialagar.es>
|
|
||||||
*/
|
|
||||||
class AjglBreakpointTwigExtensionExtensionTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var ContainerBuilder
|
|
||||||
*/
|
|
||||||
protected $container;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var AjglBreakpointTwigExtensionExtension
|
|
||||||
*/
|
|
||||||
protected $extension;
|
|
||||||
|
|
||||||
protected function setUp()
|
|
||||||
{
|
|
||||||
$this->container = new ContainerBuilder();
|
|
||||||
$this->extension = new AjglBreakpointTwigExtensionExtension();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testTwigExtensionsDefinition()
|
|
||||||
{
|
|
||||||
$this->extension->load([], $this->container);
|
|
||||||
$this->assertTrue($this->container->hasDefinition('ajgl_twig_extension.breakpoint'));
|
|
||||||
$definition = $this->container->getDefinition('ajgl_twig_extension.breakpoint');
|
|
||||||
$this->assertSame(
|
|
||||||
'Ajgl\Twig\Extension\BreakpointExtension',
|
|
||||||
$definition->getClass()
|
|
||||||
);
|
|
||||||
$this->assertNotNull($definition->getTag('twig.extension'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
language: php
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
php:
|
|
||||||
- 5.4
|
|
||||||
- 5.5
|
|
||||||
- 5.6
|
|
||||||
- 7
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
# travis encrypt CODECLIMATE_REPO_TOKEN=<https://codeclimate.com/repos/53e0fcc8e30ba02d78013d4c/coverage_setup>
|
|
||||||
- secure: "n4I9GwRCxi9UGjhDGe79SV6Nr/fRKpA8N+qqqbkveJv01Z4IRcAsRBRxKrSAX8zJUoFhlJK73VeRnBfdSBddsL3RqgDMbHilZFy6yC7Dj/vVyNe90RPWxc5J7w3sidT2g1OsgWueiUis8y3dGOQd2sewfcb2pZa29/eQusBV5i0="
|
|
||||||
|
|
||||||
install:
|
|
||||||
- composer install
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- mkdir -p build/logs
|
|
||||||
|
|
||||||
script:
|
|
||||||
- vendor/bin/phpunit --coverage-clover build/logs/clover.xml
|
|
||||||
|
|
||||||
after_script:
|
|
||||||
- php vendor/bin/coveralls -v
|
|
||||||
- ./vendor/bin/test-reporter --stdout > codeclimate.json
|
|
||||||
- "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v1.0.1-dev)' https://codeclimate.com/test_reports"
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
CHANGELOG
|
|
||||||
=========
|
|
||||||
|
|
||||||
2.0.0
|
|
||||||
-----
|
|
||||||
|
|
||||||
- **BC**: Require Twig v1.12, in order to replace deprecated Twig_Filter_Method with Twig_SimpleFilter
|
|
||||||
- **Added**: Add support for ParsedownEnging
|
|
||||||
|
|
||||||
1.2.0
|
|
||||||
-----
|
|
||||||
|
|
||||||
- **Added**: Add support for GitHub's markdown engine
|
|
||||||
|
|
||||||
1.1.0
|
|
||||||
-----
|
|
||||||
|
|
||||||
- **Added**: Add support for PHP League CommonMark engine
|
|
||||||
|
|
||||||
1.0.0
|
|
||||||
-----
|
|
||||||
|
|
||||||
- **BC**: Remove deprecated dflydev-markdown parser
|
|
||||||
-171
@@ -1,171 +0,0 @@
|
|||||||
Twig Markdown Extension
|
|
||||||
=======================
|
|
||||||
|
|
||||||
[](http://travis-ci.org/aptoma/twig-markdown)
|
|
||||||
[](https://coveralls.io/r/aptoma/twig-markdown)
|
|
||||||
|
|
||||||
Twig Markdown extension provides a new filter and a tag to allow parsing of
|
|
||||||
content as Markdown in [Twig][1] templates.
|
|
||||||
|
|
||||||
This extension could be integrated with several Markdown parser as it provides an interface, which allows you to customize your Markdown parser.
|
|
||||||
|
|
||||||
### Supported parsers
|
|
||||||
|
|
||||||
* [michelf/php-markdown](https://github.com/michelf/php-markdown) (+ MarkdownExtra)
|
|
||||||
* [league/commonmark](http://commonmark.thephpleague.com/)
|
|
||||||
* [KnpLabs/php-github-api](https://github.com/KnpLabs/php-github-api)
|
|
||||||
* [erusev/parsedown](https://github.com/erusev/parsedown)
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
* Filter support `{{ "# Heading Level 1"|markdown }}`
|
|
||||||
* Tag support `{% markdown %}{% endmarkdown %}`
|
|
||||||
|
|
||||||
When used as a tag, the indentation level of the first line sets the default indentation level for the rest of the tag content.
|
|
||||||
From this indentation level, all same indentation or outdented levels text will be transformed as regular text.
|
|
||||||
|
|
||||||
This feature allows you to write your Markdown content at any indentation level without caring of Markdown internal transformation:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<div>
|
|
||||||
<h1 class="someClass">{{ title }}</h1>
|
|
||||||
|
|
||||||
{% markdown %}
|
|
||||||
This is a list that is indented to match the context around the markdown tag:
|
|
||||||
|
|
||||||
* List item 1
|
|
||||||
* List item 2
|
|
||||||
* Sub List Item
|
|
||||||
* Sub Sub List Item
|
|
||||||
|
|
||||||
The following block will be transformed as code, as it is indented more than the
|
|
||||||
surrounding content:
|
|
||||||
|
|
||||||
$code = "good";
|
|
||||||
|
|
||||||
{% endmarkdown %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Run the composer command to install the latest stable version:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer require aptoma/twig-markdown
|
|
||||||
```
|
|
||||||
|
|
||||||
Or update your `composer.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"require": {
|
|
||||||
"aptoma/twig-markdown": "~1.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can choose to provide your own Markdown engine, although we recommend
|
|
||||||
using [michelf/php-markdown](https://github.com/michelf/php-markdown):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer require michelf/php-markdown ~1.3
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"require": {
|
|
||||||
"michelf/php-markdown": "~1.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You may also use the [PHP League CommonMark engine](http://commonmark.thephpleague.com/):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer require league/commonmark ~0.5
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"require": {
|
|
||||||
"league/commonmark": "~0.5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Twig Extension
|
|
||||||
|
|
||||||
The Twig extension provides the `markdown` tag and filter support.
|
|
||||||
|
|
||||||
Assuming that you are using [composer](http://getcomposer.org) autoloading,
|
|
||||||
add the extension to the Twig environment:
|
|
||||||
|
|
||||||
```php
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownExtension;
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
$engine = new MarkdownEngine\MichelfMarkdownEngine();
|
|
||||||
|
|
||||||
$twig->addExtension(new MarkdownExtension($engine));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Twig Token Parser
|
|
||||||
|
|
||||||
The Twig token parser provides the `markdown` tag only!
|
|
||||||
|
|
||||||
```php
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
use Aptoma\Twig\TokenParser\MarkdownTokenParser;
|
|
||||||
|
|
||||||
$engine = new MarkdownEngine\MichelfMarkdownEngine();
|
|
||||||
|
|
||||||
$twig->addTokenParser(new MarkdownTokenParser($engine));
|
|
||||||
```
|
|
||||||
|
|
||||||
### GitHub Markdown Engine
|
|
||||||
|
|
||||||
`MarkdownEngine\GitHubMarkdownEngine` provides an interface to GitHub's markdown engine using their public API via [`KnpLabs\php-github-api`][2]. To reduce API calls, rendered documents are hashed and cached in the filesystem. You can pass a GitHub repository and the path to be used for caching to the constructor:
|
|
||||||
|
|
||||||
```php
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
$engine = new MarkdownEngine\GitHubMarkdownEngine(
|
|
||||||
'aptoma/twig-markdown', // The GitHub repository to use as a context
|
|
||||||
true, // Whether to use GitHub's Flavored Markdown (GFM)
|
|
||||||
'/tmp/markdown-cache', // Path on filesystem to store rendered documents
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
In order to authenticate the API client (for instance), it's possible to pass an own instance of `\GitHub\Client` instead of letting the engine create one itself:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$client = new \GitHub\Client;
|
|
||||||
$client->authenticate('GITHUB_CLIENT_ID', 'GITHUB_CLIENT_SECRET', \Github\Client::AUTH_URL_CLIENT_ID);
|
|
||||||
|
|
||||||
$engine = new MarkdownEngine\GitHubMarkdownEngine('aptoma/twig-markdown', true, '/tmp/markdown-cache', $client);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using a different Markdown parser engine
|
|
||||||
|
|
||||||
If you want to use a different Markdown parser, you need to create an adapter
|
|
||||||
that implements `Aptoma\Twig\Extension\MarkdownEngineInterface.php`. Have
|
|
||||||
a look at `Aptoma\Twig\Extension\MarkdownEngine\MichelfMarkdownEngine` for an
|
|
||||||
example.
|
|
||||||
|
|
||||||
## Tests
|
|
||||||
|
|
||||||
The test suite uses PHPUnit:
|
|
||||||
|
|
||||||
$ phpunit
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Twig Markdown Extension is licensed under the MIT license.
|
|
||||||
|
|
||||||
[1]: http://twig.sensiolabs.org
|
|
||||||
[2]: https://github.com/knplabs/php-github-api
|
|
||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "aptoma/twig-markdown",
|
|
||||||
"description": "Twig extension to work with Markdown content",
|
|
||||||
"keywords": ["twig", "markdown"],
|
|
||||||
"license": "MIT",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Gunnar Lium",
|
|
||||||
"email": "gunnar@aptoma.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Joris Berthelot",
|
|
||||||
"email": "joris@berthelot.tel"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"twig/twig": "~1.12"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "~4.0",
|
|
||||||
"satooshi/php-coveralls": "~0.6",
|
|
||||||
"codeclimate/php-test-reporter": "dev-master",
|
|
||||||
"michelf/php-markdown": "~1",
|
|
||||||
"league/commonmark": "~0.5",
|
|
||||||
"knplabs/github-api": "~1.2",
|
|
||||||
"erusev/parsedown": "^1.6"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"michelf/php-markdown": "Original Markdown engine with MarkdownExtra.",
|
|
||||||
"knplabs/github-api": "Needed for using GitHub's Markdown engine provided through their API."
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-0": { "Aptoma": "src/" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-1772
File diff suppressed because it is too large.
Load diff
-18
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<phpunit backupGlobals="false"
|
|
||||||
backupStaticAttributes="false"
|
|
||||||
colors="true"
|
|
||||||
convertErrorsToExceptions="true"
|
|
||||||
convertNoticesToExceptions="true"
|
|
||||||
convertWarningsToExceptions="true"
|
|
||||||
processIsolation="false"
|
|
||||||
stopOnFailure="false"
|
|
||||||
syntaxCheck="false"
|
|
||||||
bootstrap="vendor/autoload.php"
|
|
||||||
>
|
|
||||||
<testsuites>
|
|
||||||
<testsuite name="Aptoma Markdown Test Suite">
|
|
||||||
<directory>./tests/</directory>
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
||||||
</phpunit>
|
|
||||||
Vendored
-76
@@ -1,76 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GithubMarkdownEngine.php
|
|
||||||
*
|
|
||||||
* Maps GitHub's Markdown engine API to Aptoma\Twig Markdown Extension using
|
|
||||||
* KnpLabs\php-github-api.
|
|
||||||
*
|
|
||||||
* @author Lukas W <lukaswhl@gmail.com>
|
|
||||||
*/
|
|
||||||
class GitHubMarkdownEngine implements MarkdownEngineInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param string $contextRepo The repository context. Pass a GitHub repo
|
|
||||||
* such as 'aptoma/twig-markdown' to render e.g. issues #23 in the
|
|
||||||
* context of the repo.
|
|
||||||
* @param bool $gfm Whether to use GitHub's Flavored Markdown or the
|
|
||||||
* standard markdown. Default is true.
|
|
||||||
* @param string $cacheDir Location on disk where rendered documents should
|
|
||||||
* be stored.
|
|
||||||
* @param \Github\Client $client Client object to use. A new Github\Client()
|
|
||||||
* object is constructed automatically if $client is null.
|
|
||||||
*/
|
|
||||||
public function __construct($contextRepo = null, $gfm = true, $cacheDir = '/tmp/github-markdown-cache', \GitHub\Client $client=null)
|
|
||||||
{
|
|
||||||
$this->repo = $contextRepo;
|
|
||||||
$this->mode = $gfm ? 'gfm' : 'markdown';
|
|
||||||
$this->cacheDir = rtrim($cacheDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
|
||||||
if (!is_dir($this->cacheDir)) {
|
|
||||||
@mkdir($this->cacheDir, 0777, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($client === null) {
|
|
||||||
$client = new \Github\Client();
|
|
||||||
}
|
|
||||||
$this->api = $client->api('markdown');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function transform($content)
|
|
||||||
{
|
|
||||||
$cacheFile = $this->getCachePath($content);
|
|
||||||
if (file_exists($cacheFile)) {
|
|
||||||
return file_get_contents($cacheFile);;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->api->render($content, $this->mode, $this->repo);
|
|
||||||
file_put_contents($cacheFile, $response);
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return 'KnpLabs\php-github-api';
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getCachePath($content)
|
|
||||||
{
|
|
||||||
return $this->cacheDir . md5($content) . '_' . $this->mode. '_' . str_replace('/', '.', $this->repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private $api;
|
|
||||||
private $cacheDir;
|
|
||||||
private $repo;
|
|
||||||
private $mode;
|
|
||||||
}
|
|
||||||
Vendored
-32
@@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
|
||||||
use Michelf\MarkdownExtra;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MichelfMarkdownEngine.php
|
|
||||||
*
|
|
||||||
* Maps Michelf\MarkdownExtra to Aptoma\Twig Markdown Extension
|
|
||||||
*
|
|
||||||
* @author Joris Berthelot <joris@berthelot.tel>
|
|
||||||
*/
|
|
||||||
class MichelfMarkdownEngine implements MarkdownEngineInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function transform($content)
|
|
||||||
{
|
|
||||||
return MarkdownExtra::defaultTransform($content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return 'Michelf\Markdown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-49
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
|
||||||
use League\CommonMark\CommonMarkConverter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PHPLeagueCommonMarkEngine.php
|
|
||||||
*
|
|
||||||
* Maps League\CommonMark\CommonMarkConverter to Aptoma\Twig Markdown Extension
|
|
||||||
*
|
|
||||||
* @author Casey McLaughlin <caseyamcl@gmail.com>
|
|
||||||
*/
|
|
||||||
class PHPLeagueCommonMarkEngine implements MarkdownEngineInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \League\CommonMark\CommonMarkConverter
|
|
||||||
*/
|
|
||||||
private $converter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* Accepts CommonMarkConverter or creates one automatically
|
|
||||||
*
|
|
||||||
* @param \League\CommonMark\CommonMarkConverter $converter
|
|
||||||
*/
|
|
||||||
public function __construct(CommonMarkConverter $converter = null)
|
|
||||||
{
|
|
||||||
$this->converter = $converter ?: new CommonMarkConverter();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function transform($content)
|
|
||||||
{
|
|
||||||
return $this->converter->convertToHtml($content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return 'League\CommonMark';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-45
@@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
|
||||||
use Parsedown;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ParsedownEngine.php
|
|
||||||
*
|
|
||||||
* Maps erusev/parsedown to Aptoma\Twig Markdown Extension
|
|
||||||
*
|
|
||||||
* @author Sébastien Lourseau <https://github.com/SebLours>
|
|
||||||
*/
|
|
||||||
class ParsedownEngine implements MarkdownEngineInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var Parsedown
|
|
||||||
*/
|
|
||||||
protected $engine;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|null $instanceName
|
|
||||||
*/
|
|
||||||
public function __construct($instanceName = null)
|
|
||||||
{
|
|
||||||
$this->engine = Parsedown::instance($instanceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function transform($content)
|
|
||||||
{
|
|
||||||
return $this->engine->parse($content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return 'erusev/parsedown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MarkdownEngineInterface.php
|
|
||||||
*
|
|
||||||
* Provide software interface to maps various Markdown engines
|
|
||||||
*
|
|
||||||
* @author Joris Berthelot <joris@berthelot.tel>
|
|
||||||
*/
|
|
||||||
interface MarkdownEngineInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Transforms the given markdown data in HTML
|
|
||||||
*
|
|
||||||
* @param $content Markdown data
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function transform($content);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return Markdown engine vendor ID
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getName();
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension;
|
|
||||||
|
|
||||||
use Aptoma\Twig\TokenParser\MarkdownTokenParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MarkdownExtension provides support for Markdown.
|
|
||||||
*
|
|
||||||
* @author Gunnar Lium <gunnar@aptoma.com>
|
|
||||||
* @author Joris Berthelot <joris@berthelot.tel>
|
|
||||||
*/
|
|
||||||
class MarkdownExtension extends \Twig_Extension
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var MarkdownEngineInterface $markdownEngine
|
|
||||||
*/
|
|
||||||
private $markdownEngine;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param MarkdownEngineInterface $markdownEngine The Markdown parser engine
|
|
||||||
*/
|
|
||||||
public function __construct(MarkdownEngineInterface $markdownEngine)
|
|
||||||
{
|
|
||||||
$this->markdownEngine = $markdownEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getFilters()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
new \Twig_SimpleFilter(
|
|
||||||
'markdown',
|
|
||||||
array($this, 'parseMarkdown'),
|
|
||||||
array('is_safe' => array('html'))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform Markdown content to HTML
|
|
||||||
*
|
|
||||||
* @param $content The Markdown content to be transformed
|
|
||||||
* @return string The result of the Markdown engine transformation
|
|
||||||
*/
|
|
||||||
public function parseMarkdown($content)
|
|
||||||
{
|
|
||||||
return $this->markdownEngine->transform($content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getTokenParsers()
|
|
||||||
{
|
|
||||||
return array(new MarkdownTokenParser($this->markdownEngine));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return 'markdown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Node;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a markdown node.
|
|
||||||
*
|
|
||||||
* It parses content as Markdown.
|
|
||||||
*
|
|
||||||
* @author Gunnar Lium <gunnar@aptoma.com>
|
|
||||||
* @author Joris Berthelot <joris@berthelot.tel>
|
|
||||||
*/
|
|
||||||
class MarkdownNode extends \Twig_Node
|
|
||||||
{
|
|
||||||
public function __construct(\Twig_NodeInterface $body, $lineno, $tag = 'markdown')
|
|
||||||
{
|
|
||||||
parent::__construct(array('body' => $body), array(), $lineno, $tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the node to PHP.
|
|
||||||
*
|
|
||||||
* @param \Twig_Compiler A Twig_Compiler instance
|
|
||||||
*/
|
|
||||||
public function compile(\Twig_Compiler $compiler)
|
|
||||||
{
|
|
||||||
$compiler
|
|
||||||
->addDebugInfo($this)
|
|
||||||
->write('ob_start();' . PHP_EOL)
|
|
||||||
->subcompile($this->getNode('body'))
|
|
||||||
->write('$content = ob_get_clean();' . PHP_EOL)
|
|
||||||
->write('preg_match("/^\s*/", $content, $matches);' . PHP_EOL)
|
|
||||||
->write('$lines = explode("\n", $content);' . PHP_EOL)
|
|
||||||
->write('$content = preg_replace(\'/^\' . $matches[0]. \'/\', "", $lines);' . PHP_EOL)
|
|
||||||
->write('$content = join("\n", $content);' . PHP_EOL)
|
|
||||||
->write('echo $this->env->getTokenParsers()->getTokenParser(\'markdown\')->getEngine()->transform($content);' . PHP_EOL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-76
@@ -1,76 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\TokenParser;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Node\MarkdownNode;
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gunnar Lium <gunnar@aptoma.com>
|
|
||||||
* @author Joris Berthelot <joris@berthelot.tel>
|
|
||||||
*/
|
|
||||||
class MarkdownTokenParser extends \Twig_TokenParser
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var The Markdown engine
|
|
||||||
*/
|
|
||||||
protected $markdownEngine;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param MarkdownEngineInterface $markdownEngine The Markdown parser engine
|
|
||||||
*/
|
|
||||||
public function __construct(MarkdownEngineInterface $markdownEngine)
|
|
||||||
{
|
|
||||||
$this->markdownEngine = $markdownEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Markdown parser engine getter
|
|
||||||
*
|
|
||||||
* @return MarkdownEngineInterface
|
|
||||||
*/
|
|
||||||
public function getEngine()
|
|
||||||
{
|
|
||||||
return $this->markdownEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a token and returns a node.
|
|
||||||
*
|
|
||||||
* @param \Twig_Token $token A \Twig_Token instance
|
|
||||||
*
|
|
||||||
* @throws \Twig_Error_Syntax
|
|
||||||
* @return \Twig_NodeInterface A \Twig_NodeInterface instance
|
|
||||||
*/
|
|
||||||
public function parse(\Twig_Token $token)
|
|
||||||
{
|
|
||||||
$lineno = $token->getLine();
|
|
||||||
|
|
||||||
$this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE);
|
|
||||||
$body = $this->parser->subparse(array($this, 'decideMarkdownEnd'), true);
|
|
||||||
$this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE);
|
|
||||||
|
|
||||||
return new MarkdownNode($body, $lineno, $this->getTag());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decide if current token marks end of Markdown block.
|
|
||||||
*
|
|
||||||
* @param \Twig_Token $token
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function decideMarkdownEnd(\Twig_Token $token)
|
|
||||||
{
|
|
||||||
return $token->test('endmarkdown');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the tag name associated with this token parser.
|
|
||||||
*
|
|
||||||
* @return string The tag name
|
|
||||||
*/
|
|
||||||
public function getTag()
|
|
||||||
{
|
|
||||||
return 'markdown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-31
@@ -1,31 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownExtensionTest;
|
|
||||||
|
|
||||||
require_once(__DIR__ . '/../MarkdownExtensionTest.php');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class GitHubMarkdownEngineTest
|
|
||||||
*
|
|
||||||
* @author Lukas W <lukaswhl@gmail.com>
|
|
||||||
*/
|
|
||||||
class GitHubMarkdownEngineTest extends MarkdownExtensionTest
|
|
||||||
{
|
|
||||||
public function getParseMarkdownTests()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('{{ "# Main Title"|markdown }}', '<h1>Main Title</h1>'),
|
|
||||||
array('{{ content|markdown }}', '<h1>Main Title</h1>', array('content' => '# Main Title')),
|
|
||||||
// Check if GFM is working
|
|
||||||
array('{{ "@aptoma"|markdown }}',
|
|
||||||
'<p><a href="https://github.com/aptoma" class="user-mention">@aptoma</a></p>'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getEngine()
|
|
||||||
{
|
|
||||||
return new GitHubMarkdownEngine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownExtensionTest;
|
|
||||||
|
|
||||||
// Require parent class if not autoloaded
|
|
||||||
if (!class_exists('\Aptoma\Twig\Extension\MarkdownExtensionTest')) {
|
|
||||||
require_once(__DIR__ . '/../MarkdownExtensionTest.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class PHPLeagueCommonMarkEngineTest
|
|
||||||
*
|
|
||||||
* @author Casey McLaughlin <caseyamcl@gmail.com>
|
|
||||||
*/
|
|
||||||
class PHPLeagueCommonMarkEngineTest extends MarkdownExtensionTest
|
|
||||||
{
|
|
||||||
protected function getEngine()
|
|
||||||
{
|
|
||||||
return new PHPLeagueCommonMarkEngine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-32
@@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension\MarkdownEngine;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownExtensionTest;
|
|
||||||
|
|
||||||
// Require parent class if not autoloaded
|
|
||||||
if (!class_exists('\Aptoma\Twig\Extension\MarkdownExtensionTest')) {
|
|
||||||
require_once(__DIR__ . '/../MarkdownExtensionTest.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ParsedownEngineTest
|
|
||||||
*
|
|
||||||
* @author Sébastien Lourseau <https://github.com/SebLours>
|
|
||||||
*/
|
|
||||||
class ParsedownEngineTest extends MarkdownExtensionTest
|
|
||||||
{
|
|
||||||
public function getParseMarkdownTests()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('{{ "# Main Title"|markdown }}', '<h1>Main Title</h1>'),
|
|
||||||
array('{{ content|markdown }}', '<h1>Main Title</h1>', array('content' => '# Main Title')),
|
|
||||||
array('{% markdown %}{{ content }}{% endmarkdown %}', '<h1>Main Title</h1>', array('content' => '# Main Title'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getEngine()
|
|
||||||
{
|
|
||||||
return new ParsedownEngine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-41
@@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\Extension;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngine\MichelfMarkdownEngine;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gunnar Liun <gunnar@aptoma.com>
|
|
||||||
*/
|
|
||||||
class MarkdownExtensionTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @dataProvider getParseMarkdownTests
|
|
||||||
*/
|
|
||||||
public function testParseMarkdown($template, $expected, $context = array())
|
|
||||||
{
|
|
||||||
$this->assertEquals($expected, $this->getTemplate($template)->render($context));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getParseMarkdownTests()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('{{ "# Main Title"|markdown }}', '<h1>Main Title</h1>' . PHP_EOL),
|
|
||||||
array('{{ content|markdown }}', '<h1>Main Title</h1>' . PHP_EOL, array('content' => '# Main Title'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getEngine()
|
|
||||||
{
|
|
||||||
return new MichelfMarkdownEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getTemplate($template)
|
|
||||||
{
|
|
||||||
$loader = new \Twig_Loader_Array(array('index' => $template));
|
|
||||||
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
|
|
||||||
$twig->addExtension(new MarkdownExtension($this->getEngine()));
|
|
||||||
|
|
||||||
return $twig->loadTemplate('index');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-109
@@ -1,109 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Aptoma\Twig\TokenParser;
|
|
||||||
|
|
||||||
use Aptoma\Twig\Extension\MarkdownEngine\MichelfMarkdownEngine;
|
|
||||||
use Aptoma\Twig\Node\MarkdownNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gunnar Lium <gunnar@aptoma.com>
|
|
||||||
*/
|
|
||||||
class MarkdownTokenParserTest extends \Twig_Test_NodeTestCase
|
|
||||||
{
|
|
||||||
public function testConstructor()
|
|
||||||
{
|
|
||||||
$body = new \Twig_Node(array(new \Twig_Node_Text("#Title\n\nparagraph\n", 1)));
|
|
||||||
$node = new MarkdownNode($body, 1);
|
|
||||||
|
|
||||||
$this->assertEquals($body, $node->getNode('body'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the generated code actually do what we expect
|
|
||||||
*
|
|
||||||
* The contents of this test is the same that we write in the compile method.
|
|
||||||
* This requires manual synchronization, which we should probably not rely on.
|
|
||||||
*/
|
|
||||||
public function testMarkdownPrepareBehavior()
|
|
||||||
{
|
|
||||||
$body = " #Title\n\n paragraph\n\n code";
|
|
||||||
$bodyPrepared = "#Title\n\nparagraph\n\n code";
|
|
||||||
|
|
||||||
ob_start();
|
|
||||||
echo $body;
|
|
||||||
$content = ob_get_clean();
|
|
||||||
preg_match("/^\s*/", $content, $matches);
|
|
||||||
$lines = explode("\n", $content);
|
|
||||||
$content = preg_replace('/^' . $matches[0]. '/', "", $lines);
|
|
||||||
$content = join("\n", $content);
|
|
||||||
|
|
||||||
// Assert prepared content looks right
|
|
||||||
$this->assertEquals($bodyPrepared, $content);
|
|
||||||
|
|
||||||
// Assert Markdown output
|
|
||||||
$expectedOutput = "<h1>Title</h1>\n\n<p>paragraph</p>\n\n<pre><code>code\n</code></pre>\n";
|
|
||||||
$this->assertEquals($expectedOutput, $this->getEngine()->transform($content));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the generated code looks as expected
|
|
||||||
*
|
|
||||||
* @dataProvider getTests
|
|
||||||
*/
|
|
||||||
public function testCompile($node, $source, $environment = null)
|
|
||||||
{
|
|
||||||
parent::testCompile($node, $source, $environment);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getEngine()
|
|
||||||
{
|
|
||||||
return new MichelfMarkdownEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTests()
|
|
||||||
{
|
|
||||||
$tests = array();
|
|
||||||
|
|
||||||
$body = new \Twig_Node(array(new \Twig_Node_Text("#Title\n\nparagraph\n", 1)));
|
|
||||||
$node = new MarkdownNode($body, 1);
|
|
||||||
|
|
||||||
$tests['simple text'] = array($node, <<<EOF
|
|
||||||
// line 1
|
|
||||||
ob_start();
|
|
||||||
echo "#Title
|
|
||||||
|
|
||||||
paragraph
|
|
||||||
";
|
|
||||||
\$content = ob_get_clean();
|
|
||||||
preg_match("/^\s*/", \$content, \$matches);
|
|
||||||
\$lines = explode("\\n", \$content);
|
|
||||||
\$content = preg_replace('/^' . \$matches[0]. '/', "", \$lines);
|
|
||||||
\$content = join("\\n", \$content);
|
|
||||||
echo \$this->env->getTokenParsers()->getTokenParser('markdown')->getEngine()->transform(\$content);
|
|
||||||
EOF
|
|
||||||
);
|
|
||||||
|
|
||||||
$body = new \Twig_Node(array(new \Twig_Node_Text(" #Title\n\n paragraph\n\n code\n", 1)));
|
|
||||||
$node = new MarkdownNode($body, 1);
|
|
||||||
|
|
||||||
$tests['text with leading indent'] = array($node, <<<EOF
|
|
||||||
// line 1
|
|
||||||
ob_start();
|
|
||||||
echo " #Title
|
|
||||||
|
|
||||||
paragraph
|
|
||||||
|
|
||||||
code
|
|
||||||
";
|
|
||||||
\$content = ob_get_clean();
|
|
||||||
preg_match("/^\s*/", \$content, \$matches);
|
|
||||||
\$lines = explode("\\n", \$content);
|
|
||||||
\$content = preg_replace('/^' . \$matches[0]. '/', "", \$lines);
|
|
||||||
\$content = join("\\n", \$content);
|
|
||||||
echo \$this->env->getTokenParsers()->getTokenParser('markdown')->getEngine()->transform(\$content);
|
|
||||||
EOF
|
|
||||||
);
|
|
||||||
|
|
||||||
return $tests;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
phpunit.xml
|
|
||||||
composer.lock
|
|
||||||
composer.phar
|
|
||||||
/vendor/
|
|
||||||
-44
@@ -1,44 +0,0 @@
|
|||||||
language: php
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- php: 5.6
|
|
||||||
dist: xenial
|
|
||||||
env: 'COMPOSER_FLAGS="--prefer-stable --prefer-lowest" TWIG_VERSION="^1.0"'
|
|
||||||
- php: 5.6
|
|
||||||
dist: xenial
|
|
||||||
env: TWIG_VERSION="^1.0"
|
|
||||||
- php: 7.0
|
|
||||||
dist: xenial
|
|
||||||
env: TWIG_VERSION="^1.0"
|
|
||||||
- php: 7.1
|
|
||||||
dist: bionic
|
|
||||||
env: TWIG_VERSION="^1.0"
|
|
||||||
- php: 7.2
|
|
||||||
dist: bionic
|
|
||||||
env: TWIG_VERSION="^1.0"
|
|
||||||
- php: 7.3
|
|
||||||
dist: bionic
|
|
||||||
env: TWIG_VERSION="^1.0"
|
|
||||||
- php: 7.4
|
|
||||||
dist: bionic
|
|
||||||
env: TWIG_VERSION="^1.0"
|
|
||||||
- php: 7.0
|
|
||||||
dist: xenial
|
|
||||||
env: TWIG_VERSION="^2.0"
|
|
||||||
- php: 7.1
|
|
||||||
dist: bionic
|
|
||||||
env: TWIG_VERSION="^2.0"
|
|
||||||
- php: 7.2
|
|
||||||
dist: bionic
|
|
||||||
env: TWIG_VERSION="^2.0"
|
|
||||||
- php: 7.3
|
|
||||||
dist: bionic
|
|
||||||
env: TWIG_VERSION="^2.0"
|
|
||||||
- php: 7.4
|
|
||||||
dist: bionic
|
|
||||||
env: TWIG_VERSION="^2.0"
|
|
||||||
|
|
||||||
install: composer require twig/twig:${TWIG_VERSION}
|
|
||||||
|
|
||||||
script: composer test
|
|
||||||
-19
@@ -1,19 +0,0 @@
|
|||||||
Copyright (c) 2013 Alexander <iam.asm89@gmail.com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is furnished
|
|
||||||
to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
-238
@@ -1,238 +0,0 @@
|
|||||||
Twig cache extension
|
|
||||||
====================
|
|
||||||
|
|
||||||
The missing cache extension for Twig. The extension allows for caching rendered parts of
|
|
||||||
templates using several cache strategies.
|
|
||||||
|
|
||||||
[](http://travis-ci.org/asm89/twig-cache-extension)
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
The extension is installable via composer:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"require": {
|
|
||||||
"asm89/twig-cache-extension": "~1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Quick start
|
|
||||||
|
|
||||||
### Setup
|
|
||||||
|
|
||||||
A minimal setup for adding the extension with the `LifeTimeCacheStrategy` and
|
|
||||||
doctrine array cache is as following:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use Doctrine\Common\Cache\ArrayCache;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheProvider\DoctrineCacheAdapter;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\LifetimeCacheStrategy;
|
|
||||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
|
||||||
|
|
||||||
$cacheProvider = new DoctrineCacheAdapter(new ArrayCache());
|
|
||||||
$cacheStrategy = new LifetimeCacheStrategy($cacheProvider);
|
|
||||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
|
||||||
|
|
||||||
$twig->addExtension($cacheExtension);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Want to use a PSR-6 cache pool?
|
|
||||||
|
|
||||||
Instead of using the default `DoctrineCacheAdapter` the extension also has
|
|
||||||
a `PSR-6` compatible adapter. You need to instantiate one of the cache pool
|
|
||||||
implementations as can be found on: http://php-cache.readthedocs.io/en/latest/
|
|
||||||
|
|
||||||
Example: Making use of the `ApcuCachePool` via the `PsrCacheAdapter`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer require cache/apcu-adapter
|
|
||||||
```
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheProvider\PsrCacheAdapter;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\LifetimeCacheStrategy;
|
|
||||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
|
||||||
use Cache\Adapter\Apcu\ApcuCachePool;
|
|
||||||
|
|
||||||
$cacheProvider = new PsrCacheAdapter(new ApcuCachePool());
|
|
||||||
$cacheStrategy = new LifetimeCacheStrategy($cacheProvider);
|
|
||||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
|
||||||
|
|
||||||
$twig->addExtension($cacheExtension);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
To cache a part of a template in Twig surround the code with a `cache` block.
|
|
||||||
The cache block takes two parameters, first an "annotation" part, second the
|
|
||||||
"value" the cache strategy can work with. Example:
|
|
||||||
|
|
||||||
```jinja
|
|
||||||
{% cache 'v1/summary' 900 %}
|
|
||||||
{# heavy lifting template stuff here, include/render other partials etc #}
|
|
||||||
{% endcache %}
|
|
||||||
```
|
|
||||||
|
|
||||||
Cache blocks can be nested:
|
|
||||||
|
|
||||||
```jinja
|
|
||||||
{% cache 'v1' 900 %}
|
|
||||||
{% for item in items %}
|
|
||||||
{% cache 'v1' item %}
|
|
||||||
{# ... #}
|
|
||||||
{% endcache %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endcache %}
|
|
||||||
```
|
|
||||||
|
|
||||||
The annotation can also be an expression:
|
|
||||||
|
|
||||||
```jinja
|
|
||||||
{% set version = 42 %}
|
|
||||||
{% cache 'hello_v' ~ version 900 %}
|
|
||||||
Hello {{ name }}!
|
|
||||||
{% endcache %}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Cache strategies
|
|
||||||
|
|
||||||
The extension ships with a few cache strategies out of the box. Setup and usage
|
|
||||||
of all of them is described below.
|
|
||||||
|
|
||||||
### Lifetime
|
|
||||||
|
|
||||||
See the ["Quick start"](#quick-start) for usage information of the `LifetimeCacheStrategy`.
|
|
||||||
|
|
||||||
### Generational
|
|
||||||
|
|
||||||
Strategy for generational caching.
|
|
||||||
|
|
||||||
In theory the strategy only saves fragments to the cache with infinite
|
|
||||||
lifetime. The key of the strategy lies in the fact that the keys for blocks
|
|
||||||
will change as the value for which the key is generated changes.
|
|
||||||
|
|
||||||
For example: entities containing a last update time, would include a timestamp
|
|
||||||
in the key. For an interesting blog post about this type of caching see:
|
|
||||||
http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works
|
|
||||||
|
|
||||||
### Blackhole
|
|
||||||
|
|
||||||
Strategy for development mode.
|
|
||||||
|
|
||||||
In development mode it often not very useful to cache fragments. The blackhole
|
|
||||||
strategy provides an easy way to not cache anything it all. It always generates
|
|
||||||
a new key and does not fetch or save any fragments.
|
|
||||||
|
|
||||||
#### Setup
|
|
||||||
|
|
||||||
In order to use the strategy you need to setup a `KeyGenerator` class that is
|
|
||||||
able to generate a cache key for a given value.
|
|
||||||
|
|
||||||
The following naive example always assumes the value is an object with the methods
|
|
||||||
`getId()` and `getUpdatedAt()` method. The key then composed from the class
|
|
||||||
name, the id and the updated time of the object:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\KeyGeneratorInterface;
|
|
||||||
|
|
||||||
class MyKeyGenerator implements KeyGeneratorInterface
|
|
||||||
{
|
|
||||||
public function generateKey($value)
|
|
||||||
{
|
|
||||||
return get_class($value) . '_' . $value->getId() . '_' . $value->getUpdatedAt();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Next the `GenerationalCacheStrategy` needs to be setup with the keygenerator.
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy;
|
|
||||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
|
||||||
|
|
||||||
$keyGenerator = new MyKeyGenerator();
|
|
||||||
$cacheProvider = /* see Quick start */;
|
|
||||||
$cacheStrategy = new GenerationalCacheStrategy($cacheProvider, $keyGenerator, 0 /* = infinite lifetime */);
|
|
||||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
|
||||||
|
|
||||||
$twig->addExtension($cacheExtension);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
The strategy expects an object as value for determining the cache key of the
|
|
||||||
block:
|
|
||||||
|
|
||||||
```jinja
|
|
||||||
{% cache 'v1/summary' item %}
|
|
||||||
{# heavy lifting template stuff here, include/render other partials etc #}
|
|
||||||
{% endcache %}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using multiple strategies
|
|
||||||
|
|
||||||
Different cache strategies are useful for different usecases. It is possible to
|
|
||||||
mix multiple strategies in an application with the
|
|
||||||
`IndexedChainingCacheStrategy`. The strategy takes an array of `'name' =>
|
|
||||||
$strategy` and delegates the caching to the appropriate strategy.
|
|
||||||
|
|
||||||
#### Setup
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\IndexedChainingCacheStrategy;
|
|
||||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
|
||||||
|
|
||||||
$cacheStrategy = new IndexedChainingCacheStrategy(array(
|
|
||||||
'time' => $lifetimeCacheStrategy,
|
|
||||||
'gen' => $generationalCacheStrategy,
|
|
||||||
));
|
|
||||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
|
||||||
|
|
||||||
$twig->addExtension($cacheExtension);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
The strategy expects an array with as key the name of the strategy which it
|
|
||||||
needs to delegate to and as value the appropriate value for the delegated
|
|
||||||
strategy.
|
|
||||||
|
|
||||||
```jinja
|
|
||||||
{# delegate to lifetime strategy #}
|
|
||||||
{% cache 'v1/summary' {time: 300} %}
|
|
||||||
{# heavy lifting template stuff here, include/render other partials etc #}
|
|
||||||
{% endcache %}
|
|
||||||
|
|
||||||
{# delegate to generational strategy #}
|
|
||||||
{% cache 'v1/summary' {gen: item} %}
|
|
||||||
{# heavy lifting template stuff here, include/render other partials etc #}
|
|
||||||
{% endcache %}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Implementing a cache strategy
|
|
||||||
|
|
||||||
Creating separate caches for different access levels, languages or other
|
|
||||||
usecases can be done by implementing a custom cache strategy. In order to do so
|
|
||||||
implement the `CacheProviderInterface`. It is recommended to use composition
|
|
||||||
and wrap a custom strategy around an existing one.
|
|
||||||
|
|
||||||
## Authors
|
|
||||||
|
|
||||||
Alexander <iam.asm89@gmail.com>
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
twig-cache-extension is licensed under the MIT License - see the LICENSE file for details
|
|
||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "asm89/twig-cache-extension",
|
|
||||||
"description": "Cache fragments of templates directly within Twig.",
|
|
||||||
"keywords": ["twig", "cache", "extension"],
|
|
||||||
"homepage": "https://github.com/asm89/twig-cache-extension",
|
|
||||||
"type": "library",
|
|
||||||
"license": "MIT",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Alexander",
|
|
||||||
"email": "iam.asm89@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.2",
|
|
||||||
"twig/twig": "^1.0|^2.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^5.0 || ^4.8.10",
|
|
||||||
"doctrine/cache": "~1.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "phpunit"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"psr/cache-implementation": "To make use of PSR-6 cache implementation via PsrCacheAdapter."
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"": "lib/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {
|
|
||||||
"": "test/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.4-dev"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\CacheProvider;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
|
||||||
use Doctrine\Common\Cache\Cache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter class to use the cache classes provider by Doctrine.
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
class DoctrineCacheAdapter implements CacheProviderInterface
|
|
||||||
{
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Cache $cache
|
|
||||||
*/
|
|
||||||
public function __construct(Cache $cache)
|
|
||||||
{
|
|
||||||
$this->cache = $cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function fetch($key)
|
|
||||||
{
|
|
||||||
return $this->cache->fetch($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function save($key, $value, $lifetime = 0)
|
|
||||||
{
|
|
||||||
return $this->cache->save($key, $value, $lifetime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-68
@@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\CacheProvider;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
|
||||||
use Psr\Cache\CacheItemPoolInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter class to make extension interoperable with every PSR-6 adapter.
|
|
||||||
*
|
|
||||||
* @see http://php-cache.readthedocs.io/
|
|
||||||
*
|
|
||||||
* @author Rvanlaak <rvanlaak@gmail.com>
|
|
||||||
*/
|
|
||||||
class PsrCacheAdapter implements CacheProviderInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var CacheItemPoolInterface
|
|
||||||
*/
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param CacheItemPoolInterface $cache
|
|
||||||
*/
|
|
||||||
public function __construct(CacheItemPoolInterface $cache)
|
|
||||||
{
|
|
||||||
$this->cache = $cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $key
|
|
||||||
* @return mixed|false
|
|
||||||
*/
|
|
||||||
public function fetch($key)
|
|
||||||
{
|
|
||||||
// PSR-6 implementation returns null, CacheProviderInterface expects false
|
|
||||||
$item = $this->cache->getItem($key);
|
|
||||||
if ($item->isHit()) {
|
|
||||||
return $item->get();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $key
|
|
||||||
* @param string $value
|
|
||||||
* @param int|\DateInterval $lifetime
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function save($key, $value, $lifetime = 0)
|
|
||||||
{
|
|
||||||
$item = $this->cache->getItem($key);
|
|
||||||
$item->set($value);
|
|
||||||
$item->expiresAfter($lifetime);
|
|
||||||
|
|
||||||
return $this->cache->save($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache provider interface.
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
interface CacheProviderInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param string $key
|
|
||||||
*
|
|
||||||
* @return mixed False, if there was no value to be fetched. Null or a string otherwise.
|
|
||||||
*/
|
|
||||||
public function fetch($key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $key
|
|
||||||
* @param string $value
|
|
||||||
* @param integer $lifetime
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function save($key, $value, $lifetime = 0);
|
|
||||||
}
|
|
||||||
-53
@@ -1,53 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategyInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CacheStrategy which doesn't cache at all
|
|
||||||
*
|
|
||||||
* This strategy can be used in development mode, e.g. editing twig templates,
|
|
||||||
* to prevent previously cached versions from being rendered.
|
|
||||||
*
|
|
||||||
* @see https://github.com/asm89/twig-cache-extension/pull/29
|
|
||||||
*
|
|
||||||
* @author Hagen Hübel <hhuebel@itinance.com>
|
|
||||||
*
|
|
||||||
* @package Asm89\Twig\CacheExtension\CacheStrategy
|
|
||||||
*/
|
|
||||||
class BlackholeCacheStrategy implements CacheStrategyInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function fetchBlock($key)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function generateKey($annotation, $value)
|
|
||||||
{
|
|
||||||
return microtime(true) . mt_rand();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function saveBlock($key, $block)
|
|
||||||
{
|
|
||||||
// fire and forget
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-79
@@ -1,79 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategyInterface;
|
|
||||||
use Asm89\Twig\CacheExtension\Exception\InvalidCacheKeyException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strategy for generational caching.
|
|
||||||
*
|
|
||||||
* In theory the strategy only saves fragments to the cache with infinite
|
|
||||||
* lifetime. The key of the strategy lies in the fact that the keys for blocks
|
|
||||||
* will change as the value for which the key is generated changes.
|
|
||||||
*
|
|
||||||
* For example: entities containing a last update time, would include a
|
|
||||||
* timestamp in the key.
|
|
||||||
*
|
|
||||||
* @see http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
class GenerationalCacheStrategy implements CacheStrategyInterface
|
|
||||||
{
|
|
||||||
private $keyGenerator;
|
|
||||||
private $cache;
|
|
||||||
private $lifetime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param CacheProviderInterface $cache
|
|
||||||
* @param KeyGeneratorInterface $keyGenerator
|
|
||||||
* @param integer $lifetime
|
|
||||||
*/
|
|
||||||
public function __construct(CacheProviderInterface $cache, KeyGeneratorInterface $keyGenerator, $lifetime = 0)
|
|
||||||
{
|
|
||||||
$this->keyGenerator = $keyGenerator;
|
|
||||||
$this->cache = $cache;
|
|
||||||
$this->lifetime = $lifetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function fetchBlock($key)
|
|
||||||
{
|
|
||||||
return $this->cache->fetch($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function generateKey($annotation, $value)
|
|
||||||
{
|
|
||||||
$key = $this->keyGenerator->generateKey($value);
|
|
||||||
|
|
||||||
if (null === $key) {
|
|
||||||
throw new InvalidCacheKeyException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $annotation . '__GCS__' . $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function saveBlock($key, $block)
|
|
||||||
{
|
|
||||||
return $this->cache->save($key, $block, $this->lifetime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-76
@@ -1,76 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategyInterface;
|
|
||||||
use Asm89\Twig\CacheExtension\Exception\NonExistingStrategyException;
|
|
||||||
use Asm89\Twig\CacheExtension\Exception\NonExistingStrategyKeyException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Combines several configured cache strategies.
|
|
||||||
*
|
|
||||||
* Useful for combining for example generational cache strategy with a lifetime
|
|
||||||
* cache strategy, but also useful when combining several generational cache
|
|
||||||
* strategies which differ on cache lifetime (infinite, 1hr, 5m).
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
class IndexedChainingCacheStrategy implements CacheStrategyInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var CacheStrategyInterface[]
|
|
||||||
*/
|
|
||||||
private $strategies;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $strategies
|
|
||||||
*/
|
|
||||||
public function __construct(array $strategies)
|
|
||||||
{
|
|
||||||
$this->strategies = $strategies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function fetchBlock($key)
|
|
||||||
{
|
|
||||||
return $this->strategies[$key['strategyKey']]->fetchBlock($key['key']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function generateKey($annotation, $value)
|
|
||||||
{
|
|
||||||
if (!is_array($value) || null === $strategyKey = key($value)) {
|
|
||||||
throw new NonExistingStrategyKeyException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($this->strategies[$strategyKey])) {
|
|
||||||
throw new NonExistingStrategyException($strategyKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'strategyKey' => $strategyKey,
|
|
||||||
'key' => $this->strategies[$strategyKey]->generateKey($annotation, current($value)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function saveBlock($key, $block)
|
|
||||||
{
|
|
||||||
return $this->strategies[$key['strategyKey']]->saveBlock($key['key'], $block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-29
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a key for a given value.
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
interface KeyGeneratorInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Generate a cache key for a given value.
|
|
||||||
*
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function generateKey($value);
|
|
||||||
}
|
|
||||||
-68
@@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\CacheStrategy;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategyInterface;
|
|
||||||
use Asm89\Twig\CacheExtension\Exception\InvalidCacheLifetimeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strategy for caching with a pre-defined lifetime.
|
|
||||||
*
|
|
||||||
* The value passed to the strategy is the lifetime of the cache block in
|
|
||||||
* seconds.
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
class LifetimeCacheStrategy implements CacheStrategyInterface
|
|
||||||
{
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param CacheProviderInterface $cache
|
|
||||||
*/
|
|
||||||
public function __construct(CacheProviderInterface $cache)
|
|
||||||
{
|
|
||||||
$this->cache = $cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function fetchBlock($key)
|
|
||||||
{
|
|
||||||
return $this->cache->fetch($key['key']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function generateKey($annotation, $value)
|
|
||||||
{
|
|
||||||
if (!is_numeric($value)) {
|
|
||||||
throw new InvalidCacheLifetimeException($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'lifetime' => $value,
|
|
||||||
'key' => '__LCS__' . $annotation,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function saveBlock($key, $block)
|
|
||||||
{
|
|
||||||
return $this->cache->save($key['key'], $block, $key['lifetime']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache strategy interface.
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
interface CacheStrategyInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Fetch the block for a given key.
|
|
||||||
*
|
|
||||||
* @param mixed $key
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function fetchBlock($key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a key for the value.
|
|
||||||
*
|
|
||||||
* @param string $annotation
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function generateKey($annotation, $value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the contents of a rendered block.
|
|
||||||
*
|
|
||||||
* @param mixed $key
|
|
||||||
* @param string $block
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function saveBlock($key, $block);
|
|
||||||
}
|
|
||||||
Vendored
-20
@@ -1,20 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo Replace \RuntimeException with \InvalidArgumentException at version 2.0
|
|
||||||
*/
|
|
||||||
class BaseException extends \RuntimeException
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Exception;
|
|
||||||
|
|
||||||
class InvalidCacheKeyException extends BaseException
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function __construct($message = 'Key generator did not return a key.', $code = 0, \Exception $previous = null)
|
|
||||||
{
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Exception;
|
|
||||||
|
|
||||||
class InvalidCacheLifetimeException extends BaseException
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function __construct($lifetime, $code = 0, \Exception $previous = null)
|
|
||||||
{
|
|
||||||
parent::__construct(sprintf('Value "%s" is not a valid lifetime.', gettype($lifetime)), $code, $previous);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Exception;
|
|
||||||
|
|
||||||
class NonExistingStrategyException extends BaseException
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function __construct($strategyKey, $code = 0, \Exception $previous = null)
|
|
||||||
{
|
|
||||||
parent::__construct(sprintf('No strategy configured with key "%s".', $strategyKey), $code, $previous);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Exception;
|
|
||||||
|
|
||||||
class NonExistingStrategyKeyException extends BaseException
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function __construct($message = 'No strategy key found in value.', $code = 0, \Exception $previous = null)
|
|
||||||
{
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-59
@@ -1,59 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension for caching template blocks with twig.
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
class Extension extends \Twig_Extension
|
|
||||||
{
|
|
||||||
private $cacheStrategy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param CacheStrategyInterface $cacheStrategy
|
|
||||||
*/
|
|
||||||
public function __construct(CacheStrategyInterface $cacheStrategy)
|
|
||||||
{
|
|
||||||
$this->cacheStrategy = $cacheStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return CacheStrategyInterface
|
|
||||||
*/
|
|
||||||
public function getCacheStrategy()
|
|
||||||
{
|
|
||||||
return $this->cacheStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
if (version_compare(\Twig_Environment::VERSION, '1.26.0', '>=')) {
|
|
||||||
return __CLASS__;
|
|
||||||
}
|
|
||||||
return 'asm89_cache';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function getTokenParsers()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
new TokenParser\Cache(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-71
@@ -1,71 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Node;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache twig node.
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
class CacheNode extends \Twig_Node
|
|
||||||
{
|
|
||||||
private static $cacheCount = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Twig_Node_Expression $annotation
|
|
||||||
* @param \Twig_Node_Expression $keyInfo
|
|
||||||
* @param \Twig_NodeInterface $body
|
|
||||||
* @param integer $lineno
|
|
||||||
* @param string $tag
|
|
||||||
*/
|
|
||||||
public function __construct(\Twig_Node_Expression $annotation, \Twig_Node_Expression $keyInfo, \Twig_Node $body, $lineno, $tag = null)
|
|
||||||
{
|
|
||||||
parent::__construct(array('key_info' => $keyInfo, 'body' => $body, 'annotation' => $annotation), array(), $lineno, $tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function compile(\Twig_Compiler $compiler)
|
|
||||||
{
|
|
||||||
$i = self::$cacheCount++;
|
|
||||||
|
|
||||||
if (version_compare(\Twig_Environment::VERSION, '1.26.0', '>=')) {
|
|
||||||
$extension = 'Asm89\Twig\CacheExtension\Extension';
|
|
||||||
} else {
|
|
||||||
$extension = 'asm89_cache';
|
|
||||||
}
|
|
||||||
|
|
||||||
$compiler
|
|
||||||
->addDebugInfo($this)
|
|
||||||
->write("\$asm89CacheStrategy".$i." = \$this->env->getExtension('{$extension}')->getCacheStrategy();\n")
|
|
||||||
->write("\$asm89Key".$i." = \$asm89CacheStrategy".$i."->generateKey(")
|
|
||||||
->subcompile($this->getNode('annotation'))
|
|
||||||
->raw(", ")
|
|
||||||
->subcompile($this->getNode('key_info'))
|
|
||||||
->write(");\n")
|
|
||||||
->write("\$asm89CacheBody".$i." = \$asm89CacheStrategy".$i."->fetchBlock(\$asm89Key".$i.");\n")
|
|
||||||
->write("if (\$asm89CacheBody".$i." === false) {\n")
|
|
||||||
->indent()
|
|
||||||
->write("ob_start();\n")
|
|
||||||
->indent()
|
|
||||||
->subcompile($this->getNode('body'))
|
|
||||||
->outdent()
|
|
||||||
->write("\n")
|
|
||||||
->write("\$asm89CacheBody".$i." = ob_get_clean();\n")
|
|
||||||
->write("\$asm89CacheStrategy".$i."->saveBlock(\$asm89Key".$i.", \$asm89CacheBody".$i.");\n")
|
|
||||||
->outdent()
|
|
||||||
->write("}\n")
|
|
||||||
->write("echo \$asm89CacheBody".$i.";\n")
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-59
@@ -1,59 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\TokenParser;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\Node\CacheNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser for cache/endcache blocks.
|
|
||||||
*
|
|
||||||
* @author Alexander <iam.asm89@gmail.com>
|
|
||||||
*/
|
|
||||||
class Cache extends \Twig_TokenParser
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param \Twig_Token $token
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function decideCacheEnd(\Twig_Token $token)
|
|
||||||
{
|
|
||||||
return $token->test('endcache');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function getTag()
|
|
||||||
{
|
|
||||||
return 'cache';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function parse(\Twig_Token $token)
|
|
||||||
{
|
|
||||||
$lineno = $token->getLine();
|
|
||||||
$stream = $this->parser->getStream();
|
|
||||||
|
|
||||||
$annotation = $this->parser->getExpressionParser()->parseExpression();
|
|
||||||
|
|
||||||
$key = $this->parser->getExpressionParser()->parseExpression();
|
|
||||||
|
|
||||||
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
|
|
||||||
$body = $this->parser->subparse(array($this, 'decideCacheEnd'), true);
|
|
||||||
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
|
|
||||||
|
|
||||||
return new CacheNode($annotation, $key, $body, $lineno, $this->getTag());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<phpunit backupGlobals="false"
|
|
||||||
backupStaticAttributes="false"
|
|
||||||
colors="true"
|
|
||||||
convertErrorsToExceptions="true"
|
|
||||||
convertNoticesToExceptions="true"
|
|
||||||
convertWarningsToExceptions="true"
|
|
||||||
processIsolation="false"
|
|
||||||
stopOnFailure="false"
|
|
||||||
syntaxCheck="false"
|
|
||||||
bootstrap="test/bootstrap.php"
|
|
||||||
>
|
|
||||||
<testsuites>
|
|
||||||
<testsuite name="Twig Cache Extension Test Suite">
|
|
||||||
<directory>./test/Asm89/</directory>
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
||||||
|
|
||||||
<filter>
|
|
||||||
<whitelist>
|
|
||||||
<directory suffix=".php">./lib/</directory>
|
|
||||||
</whitelist>
|
|
||||||
</filter>
|
|
||||||
</phpunit>
|
|
||||||
-46
@@ -1,46 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Tests\CacheProvider;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheProvider\DoctrineCacheAdapter;
|
|
||||||
|
|
||||||
class DoctrineCacheAdapterTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
public function testFetch()
|
|
||||||
{
|
|
||||||
$cacheMock = $this->createCacheMock();
|
|
||||||
$cacheMock->expects($this->any())
|
|
||||||
->method('fetch')
|
|
||||||
->will($this->returnValue('fromcache'));
|
|
||||||
|
|
||||||
$cache = new DoctrineCacheAdapter($cacheMock);
|
|
||||||
|
|
||||||
$this->assertEquals('fromcache', $cache->fetch('test'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSave()
|
|
||||||
{
|
|
||||||
$cacheMock = $this->createCacheMock();
|
|
||||||
$cacheMock->expects($this->once())
|
|
||||||
->method('save')
|
|
||||||
->with('key', 'value', 42);
|
|
||||||
|
|
||||||
$cache = new DoctrineCacheAdapter($cacheMock);
|
|
||||||
|
|
||||||
$cache->save('key', 'value', 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createCacheMock()
|
|
||||||
{
|
|
||||||
return $this->createMock('Doctrine\Common\Cache\Cache');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-80
@@ -1,80 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Tests\CacheStrategy;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy;
|
|
||||||
|
|
||||||
class GenerationalCacheStrategyTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
private $keyGeneratorMock;
|
|
||||||
private $cacheProviderMock;
|
|
||||||
|
|
||||||
public function createCacheStrategy($lifetime = 0)
|
|
||||||
{
|
|
||||||
$this->keyGeneratorMock = $this->createKeyGeneratorMock();
|
|
||||||
$this->cacheProviderMock = $this->createCacheProviderMock();
|
|
||||||
|
|
||||||
return new GenerationalCacheStrategy($this->cacheProviderMock, $this->keyGeneratorMock, $lifetime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGenerateKeyContainsAnnotation()
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy();
|
|
||||||
$this->keyGeneratorMock->expects($this->any())
|
|
||||||
->method('generateKey')
|
|
||||||
->will($this->returnValue('foo'));
|
|
||||||
|
|
||||||
$this->assertEquals('v42__GCS__foo', $strategy->generateKey('v42', 'value'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Asm89\Twig\CacheExtension\Exception\InvalidCacheKeyException
|
|
||||||
*/
|
|
||||||
public function testGenerationKeyThrowsExceptionWhenKeyGeneratorReturnsNull()
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy();
|
|
||||||
|
|
||||||
$strategy->generateKey('v42', 'value');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider getLifeTimes
|
|
||||||
*/
|
|
||||||
public function testSaveBlockUsesConfiguredLifetime($lifetime)
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy($lifetime);
|
|
||||||
$this->cacheProviderMock->expects($this->any())
|
|
||||||
->method('save')
|
|
||||||
->with('key', 'value', $lifetime)
|
|
||||||
->will($this->returnValue('foo'));
|
|
||||||
|
|
||||||
$strategy->saveBlock('key', 'value');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLifetimes()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array(0),
|
|
||||||
array(60),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createKeyGeneratorMock()
|
|
||||||
{
|
|
||||||
return $this->createMock('Asm89\Twig\CacheExtension\CacheStrategy\KeyGeneratorInterface');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createCacheProviderMock()
|
|
||||||
{
|
|
||||||
return $this->createMock('Asm89\Twig\CacheExtension\CacheProviderInterface');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-80
@@ -1,80 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Tests\CacheStrategy;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\IndexedChainingCacheStrategy;
|
|
||||||
|
|
||||||
class IndexedChainingCacheStrategyTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
private $cacheStrategyMocks = array();
|
|
||||||
|
|
||||||
public function createCacheStrategy()
|
|
||||||
{
|
|
||||||
foreach($this->getStrategies() as $config) {
|
|
||||||
list($key, $return) = $config;
|
|
||||||
|
|
||||||
$cacheStrategyMock = $this->createCacheStrategyMock();
|
|
||||||
$cacheStrategyMock->expects($this->any())
|
|
||||||
->method('generateKey')
|
|
||||||
->will($this->returnValue($return));
|
|
||||||
|
|
||||||
$this->cacheStrategyMocks[$key] = $cacheStrategyMock;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IndexedChainingCacheStrategy($this->cacheStrategyMocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider getStrategies
|
|
||||||
*/
|
|
||||||
public function testGenerateKeyProxiesToAppropriateStrategy($key, $return)
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy();
|
|
||||||
|
|
||||||
$generatedKey = $strategy->generateKey('v42', array($key => 'proxied_value'));
|
|
||||||
|
|
||||||
$this->assertEquals($return, $generatedKey['key']);
|
|
||||||
$this->assertEquals($key, $generatedKey['strategyKey']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Asm89\Twig\CacheExtension\Exception\NonExistingStrategyKeyException
|
|
||||||
*/
|
|
||||||
public function testGenerateKeyThrowsExceptionOnMissingKey()
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy();
|
|
||||||
$strategy->generateKey('v42', 'proxied_value');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Asm89\Twig\CacheExtension\Exception\NonExistingStrategyException
|
|
||||||
* @expectedExceptionMessage No strategy configured with key "unknown"
|
|
||||||
*/
|
|
||||||
public function testGenerateKeyThrowsExceptionOnUnknownKey()
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy();
|
|
||||||
$strategy->generateKey('v42', array('unknown' => 'proxied_value'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getStrategies()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('foo', 'foo_key'),
|
|
||||||
array('bar', 'bar_key'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createCacheStrategyMock()
|
|
||||||
{
|
|
||||||
return $this->createMock('Asm89\Twig\CacheExtension\CacheStrategyInterface');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-68
@@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Tests\CacheStrategy;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\LifetimeCacheStrategy;
|
|
||||||
|
|
||||||
class LifetimeCacheStrategyTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
private $cacheProviderMock;
|
|
||||||
|
|
||||||
public function createCacheStrategy()
|
|
||||||
{
|
|
||||||
$this->cacheProviderMock = $this->createCacheProviderMock();
|
|
||||||
|
|
||||||
return new LifetimeCacheStrategy($this->cacheProviderMock);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGenerateKeyUsesGivenLifetime()
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy();
|
|
||||||
|
|
||||||
$key = $strategy->generateKey('v42', 42);
|
|
||||||
|
|
||||||
$this->assertEquals(42, $key['lifetime']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGenerateKeyAnnotatesKey()
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy();
|
|
||||||
|
|
||||||
$key = $strategy->generateKey('the_annotation', 42);
|
|
||||||
|
|
||||||
$this->assertContains('the_annotation', $key['key']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider getInvalidLifetimeValues
|
|
||||||
* @expectedException \Asm89\Twig\CacheExtension\Exception\InvalidCacheLifetimeException
|
|
||||||
*/
|
|
||||||
public function testGenerateKeyThrowsExceptionWhenNoLifetimeProvided($value)
|
|
||||||
{
|
|
||||||
$strategy = $this->createCacheStrategy();
|
|
||||||
|
|
||||||
$strategy->generateKey('v42', $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getInvalidLifetimeValues()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('foo'),
|
|
||||||
array(array('foo')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createCacheProviderMock()
|
|
||||||
{
|
|
||||||
return $this->createMock('Asm89\Twig\CacheExtension\CacheProviderInterface');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-182
@@ -1,182 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Asm89\Twig\CacheExtension\Tests;
|
|
||||||
|
|
||||||
use Asm89\Twig\CacheExtension\CacheProvider\DoctrineCacheAdapter;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\KeyGeneratorInterface;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\GenerationalCacheStrategy;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\IndexedChainingCacheStrategy;
|
|
||||||
use Asm89\Twig\CacheExtension\CacheStrategy\LifetimeCacheStrategy;
|
|
||||||
use Asm89\Twig\CacheExtension\Extension;
|
|
||||||
use Doctrine\Common\Cache\ArrayCache;
|
|
||||||
use Twig_Loader_Filesystem;
|
|
||||||
use Twig_Environment;
|
|
||||||
|
|
||||||
class FunctionalExtensionTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
protected function createCacheProvider()
|
|
||||||
{
|
|
||||||
$this->cache = new ArrayCache();
|
|
||||||
|
|
||||||
return new DoctrineCacheAdapter($this->cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function createCacheStrategy($name = null)
|
|
||||||
{
|
|
||||||
$cacheProvider = $this->createCacheProvider();
|
|
||||||
$keyGenerator = $this->createKeyGenerator();
|
|
||||||
$lifetime = 0;
|
|
||||||
|
|
||||||
switch ($name) {
|
|
||||||
case 'time':
|
|
||||||
return new LifetimeCacheStrategy($cacheProvider);
|
|
||||||
case 'indexed':
|
|
||||||
return new IndexedChainingCacheStrategy(array(
|
|
||||||
'gcs' => new GenerationalCacheStrategy($cacheProvider, $keyGenerator, $lifetime),
|
|
||||||
'time' => new LifetimeCacheStrategy($cacheProvider),
|
|
||||||
));
|
|
||||||
default:
|
|
||||||
return new GenerationalCacheStrategy($cacheProvider, $keyGenerator, $lifetime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function createKeyGenerator()
|
|
||||||
{
|
|
||||||
return new KeyGenerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function createTwig($cacheStrategyName = null)
|
|
||||||
{
|
|
||||||
$loader = new Twig_Loader_Filesystem(__DIR__ . '/fixtures/');
|
|
||||||
$twig = new Twig_Environment($loader);
|
|
||||||
|
|
||||||
$cacheExtension = new Extension($this->createCacheStrategy($cacheStrategyName));
|
|
||||||
|
|
||||||
$twig->addExtension($cacheExtension);
|
|
||||||
|
|
||||||
return $twig;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getValue($value, $updatedAt)
|
|
||||||
{
|
|
||||||
return new Value($value, $updatedAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCachesWithSameCacheKey()
|
|
||||||
{
|
|
||||||
$twig = $this->createTwig();
|
|
||||||
|
|
||||||
$rendered = $twig->render('gcs_value.twig', array('value' => $this->getValue('asm89', 1)));
|
|
||||||
$this->assertEquals('Hello asm89!', $rendered);
|
|
||||||
|
|
||||||
$rendered2 = $twig->render('gcs_value.twig', array('value' => $this->getValue('fabpot', 1)));
|
|
||||||
$this->assertEquals('Hello asm89!', $rendered2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testDifferentCacheOnDifferentAnnotation()
|
|
||||||
{
|
|
||||||
$twig = $this->createTwig();
|
|
||||||
|
|
||||||
$rendered = $twig->render('gcs_value.twig', array('value' => $this->getValue('asm89', 1)));
|
|
||||||
$this->assertEquals('Hello asm89!', $rendered);
|
|
||||||
|
|
||||||
$rendered2 = $twig->render('gcs_value.twig', array('value' => $this->getValue('fabpot', 1)));
|
|
||||||
$this->assertEquals('Hello asm89!', $rendered2);
|
|
||||||
|
|
||||||
$rendered3 = $twig->render('gcs_value_v2.twig', array('value' => $this->getValue('fabpot', 1)));
|
|
||||||
$this->assertEquals('Hello fabpot!', $rendered3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testLifetimeCacheStrategy()
|
|
||||||
{
|
|
||||||
$twig = $this->createTwig('time');
|
|
||||||
|
|
||||||
$rendered = $twig->render('lcs_value.twig', array('value' => $this->getValue('asm89', 1)));
|
|
||||||
$this->assertEquals('Hello asm89!', $rendered);
|
|
||||||
|
|
||||||
$rendered2 = $twig->render('lcs_value.twig', array('value' => $this->getValue('fabpot', 1)));
|
|
||||||
$this->assertEquals('Hello asm89!', $rendered2);
|
|
||||||
|
|
||||||
$this->cache->flushAll();
|
|
||||||
|
|
||||||
$rendered3 = $twig->render('lcs_value.twig', array('value' => $this->getValue('fabpot', 1)));
|
|
||||||
$this->assertEquals('Hello fabpot!', $rendered3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIndexedChainingStrategy()
|
|
||||||
{
|
|
||||||
$twig = $this->createTwig('indexed');
|
|
||||||
|
|
||||||
$rendered = $twig->render('ics_value.twig', array('value' => $this->getValue('asm89', 1)));
|
|
||||||
$this->assertEquals('Hello asm89!', $rendered);
|
|
||||||
|
|
||||||
$rendered2 = $twig->render('ics_value.twig', array('value' => $this->getValue('fabpot', 1)));
|
|
||||||
$this->assertEquals('Hello asm89!', $rendered2);
|
|
||||||
|
|
||||||
$this->cache->flushAll();
|
|
||||||
|
|
||||||
$rendered3 = $twig->render('ics_value.twig', array('value' => $this->getValue('fabpot', 1)));
|
|
||||||
$this->assertEquals('Hello fabpot!', $rendered3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException Twig_Error_Runtime
|
|
||||||
* @expectedExceptionMessage An exception has been thrown during the rendering of a template ("No strategy key found in value.")
|
|
||||||
*/
|
|
||||||
public function testIndexedChainingStrategyNeedsKey()
|
|
||||||
{
|
|
||||||
$twig = $this->createTwig('indexed');
|
|
||||||
|
|
||||||
$twig->render('ics_no_key.twig', array('value' => $this->getValue('asm89', 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testAnnotationExpression()
|
|
||||||
{
|
|
||||||
$twig = $this->createTwig('indexed');
|
|
||||||
|
|
||||||
$rendered = $twig->render('annotation_expression.twig', array('value' => $this->getValue('asm89', 1), 'version' => 1));
|
|
||||||
$this->assertEquals('Hello asm89!Hello asm89!', $rendered);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class KeyGenerator implements KeyGeneratorInterface
|
|
||||||
{
|
|
||||||
public function generateKey($value)
|
|
||||||
{
|
|
||||||
return get_class($value) . '_' . $value->getUpdatedAt();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Value
|
|
||||||
{
|
|
||||||
private $value;
|
|
||||||
private $updatedAt;
|
|
||||||
|
|
||||||
public function __construct($value, $updatedAt)
|
|
||||||
{
|
|
||||||
$this->value = $value;
|
|
||||||
$this->updatedAt = $updatedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUpdatedAt()
|
|
||||||
{
|
|
||||||
return $this->updatedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __toString()
|
|
||||||
{
|
|
||||||
return $this->value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
{%- set k = "v'" ~ version -%}
|
|
||||||
{%- cache k {time: 10} -%}Hello {{ value }}!{%- endcache -%}
|
|
||||||
{%- cache 'bob'|capitalize {gcs: value} %}Hello {{ value }}!{%- endcache -%}
|
|
||||||
-2
@@ -1,2 +0,0 @@
|
|||||||
{% set annotation = 'v1' %}
|
|
||||||
{% cache annotation value %}Hello {{ value }}!{% endcache %}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
{% cache 'v1' value %}Hello {{ value }}!{% endcache %}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
{% cache 'v2' value %}Hello {{ value }}!{% endcache %}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
{% cache 'v1' 10 %}Hello {{ value }}!{% endcache %}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
{% cache 'v1' {time: 10} %}Hello {{ value }}!{% endcache %}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
{% cache 'v1' 10 %}Hello {{ value }}!{% endcache %}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of twig-cache-extension.
|
|
||||||
*
|
|
||||||
* (c) Alexander <iam.asm89@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (file_exists($file = __DIR__.'/../vendor/autoload.php')) {
|
|
||||||
$autoload = require_once $file;
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException('Install dependencies to run test suite.');
|
|
||||||
}
|
|
||||||
Vendored
-10
@@ -1,10 +0,0 @@
|
|||||||
filter:
|
|
||||||
paths: ["src/*"]
|
|
||||||
tools:
|
|
||||||
external_code_coverage: true
|
|
||||||
php_code_coverage: true
|
|
||||||
php_sim: true
|
|
||||||
php_mess_detector: true
|
|
||||||
php_pdepend: true
|
|
||||||
php_analyzer: true
|
|
||||||
php_cpd: true
|
|
||||||
Vendored
-14
@@ -1,14 +0,0 @@
|
|||||||
sudo: false
|
|
||||||
language: php
|
|
||||||
php:
|
|
||||||
- 5.6
|
|
||||||
- hhvm
|
|
||||||
- 7
|
|
||||||
before_script:
|
|
||||||
- composer self-update
|
|
||||||
- composer install
|
|
||||||
script:
|
|
||||||
- phpunit --coverage-clover=coverage.clover
|
|
||||||
after_script:
|
|
||||||
- wget https://scrutinizer-ci.com/ocular.phar
|
|
||||||
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
|
|
||||||
Vendored
-66
@@ -1,66 +0,0 @@
|
|||||||
# CHANGELOG
|
|
||||||
|
|
||||||
## 3.0.0
|
|
||||||
|
|
||||||
- Final release. No changes after first beta.
|
|
||||||
|
|
||||||
## 3.0.0-beta1
|
|
||||||
|
|
||||||
- Removed `aura/installer-default` from composer.json which was used by aura framework version 1 to install in package folder.
|
|
||||||
- Fixes [issue 17](https://github.com/auraphp/Aura.Intl/issues/17) by removing Aura.Di wiring trait tests.
|
|
||||||
- Changed directory structure from PSR-0 to PSR-4.
|
|
||||||
- Supported PHP version : 5.6+.
|
|
||||||
- There is no other BC breaks from 1.x version
|
|
||||||
|
|
||||||
|
|
||||||
## 1.1.1
|
|
||||||
|
|
||||||
Hygiene release: Composer update.
|
|
||||||
|
|
||||||
## 1.1.0
|
|
||||||
|
|
||||||
- Merge pull request #11 from lorenzo/feature/format-key. If Translator::translate() cannot translate, it now returns the incoming translation key as the translated message. This makes it easier to use the key as a human readable string, which can contain formatting placeholders. With this feature the developer will be able to see immediate feedback of their translation messages without having to translate to a specific locale beforehand.
|
|
||||||
|
|
||||||
## 1.0.1
|
|
||||||
|
|
||||||
Hygiene release.
|
|
||||||
|
|
||||||
- Merge pull request #10 from harikt/fixdoc; fixes #9, add a test for failure. The expected exception need to be fixed.
|
|
||||||
|
|
||||||
- Merge pull request #8 from harikt/v2config, adding v2 config files.
|
|
||||||
|
|
||||||
- Merge pull request #7 from harikt/issue6, add a test to show it works. Thank you @samdark.
|
|
||||||
|
|
||||||
- Point travis status badge to develop branch
|
|
||||||
|
|
||||||
## 1.0.0
|
|
||||||
|
|
||||||
- [CHG] When interpolating array values into strings, now converts the array
|
|
||||||
to comma-separated values instead of printing 'Array'.
|
|
||||||
|
|
||||||
- [DOC] PHP 5.5 appears to be able to format strings with missing token
|
|
||||||
replacements; updated tests to account for this.
|
|
||||||
|
|
||||||
## 1.0.0-beta2
|
|
||||||
|
|
||||||
- [FIX] Multiple typo fixes; thanks, @pborreli.
|
|
||||||
|
|
||||||
- [CHG] Use {foo} instead of {:foo} in line with PSR-3 placeholders.
|
|
||||||
|
|
||||||
- [NEW] Add a PackageFactory
|
|
||||||
|
|
||||||
- [NEW] Add more-detailed exception classes
|
|
||||||
|
|
||||||
- [ADD] In config, add 'intl_package_factory' as a service
|
|
||||||
|
|
||||||
- [CHG] Throw IcuVersionTooLow Exception if IntlFormatter is instantiated with
|
|
||||||
ICU Version lower than 4.8; Skip all IntlFormatter tests if the intl
|
|
||||||
extension is not loaded. Thanks, @mapthegod.
|
|
||||||
|
|
||||||
- [CHG] In the FormatterLocator, registry entries *must* be wrapped in a
|
|
||||||
callable from now on.
|
|
||||||
|
|
||||||
|
|
||||||
## 1.0.0-beta1
|
|
||||||
|
|
||||||
Initial release.
|
|
||||||
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
# Contributing
|
|
||||||
|
|
||||||
We are happy to review any contributions you want to make. When contributing, please follow the rules outlined at <http://auraphp.com/contributing>.
|
|
||||||
|
|
||||||
The time between submitting a contribution and its review one may be extensive; do not be discouraged if there is not immediate feedback.
|
|
||||||
|
|
||||||
Thanks!
|
|
||||||
Vendored
-21
@@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2017, Aura for PHP
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
Vendored
-59
@@ -1,59 +0,0 @@
|
|||||||
# Aura.Intl
|
|
||||||
|
|
||||||
The Aura.Intl package provides internationalization (I18N) tools, specifically
|
|
||||||
package-oriented per-locale message translation.
|
|
||||||
|
|
||||||
## Installation and Autoloading
|
|
||||||
|
|
||||||
This package is installable and PSR-4 autoloadable via Composer as
|
|
||||||
[aura/intl][].
|
|
||||||
|
|
||||||
Alternatively, [download a release][], or clone this repository, then map the
|
|
||||||
`Aura\Intl\` namespace to the package `src/` directory.
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
This package requires PHP 5.6 or later; it has been tested on PHP 5.6, 7.0
|
|
||||||
and HHVM. We recommend using the latest available version of PHP as a matter of
|
|
||||||
principle.
|
|
||||||
|
|
||||||
Aura library packages may sometimes depend on external interfaces, but never on
|
|
||||||
external implementations. This allows compliance with community standards
|
|
||||||
without compromising flexibility. For specifics, please examine the package
|
|
||||||
[composer.json][] file.
|
|
||||||
|
|
||||||
## Quality
|
|
||||||
|
|
||||||
[](https://scrutinizer-ci.com/g/auraphp/Aura.Intl/)
|
|
||||||
[](https://scrutinizer-ci.com/g/auraphp/Aura.Intl/)
|
|
||||||
[](https://travis-ci.org/auraphp/Aura.Intl)
|
|
||||||
|
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
||||||
|
|
||||||
To run the unit tests at the command line, issue `composer install` and then
|
|
||||||
`phpunit` at the package root. This requires [Composer][] to be available as
|
|
||||||
`composer`, and [PHPUnit][] to be available as `phpunit`.
|
|
||||||
|
|
||||||
This package attempts to comply with [PSR-1][], [PSR-2][], and [PSR-4][]. If
|
|
||||||
you notice compliance oversights, please send a patch via pull request.
|
|
||||||
|
|
||||||
## Community
|
|
||||||
|
|
||||||
To ask questions, provide feedback, or otherwise communicate with other Aura
|
|
||||||
users, please join our [Google Group][], follow [@auraphp][], or chat with us
|
|
||||||
on Freenode in the #auraphp channel.
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
This package is fully documented [here](./docs/index.md).
|
|
||||||
|
|
||||||
[PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
|
|
||||||
[PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
|
|
||||||
[PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md
|
|
||||||
[Composer]: http://getcomposer.org/
|
|
||||||
[PHPUnit]: http://phpunit.de/
|
|
||||||
[Google Group]: http://groups.google.com/group/auraphp
|
|
||||||
[@auraphp]: http://twitter.com/auraphp
|
|
||||||
[download a release]: https://github.com/auraphp/Aura.Intl/releases
|
|
||||||
[aura/intl]: https://packagist.org/packages/aura/intl
|
|
||||||
[composer.json]: ./composer.json
|
|
||||||
Vendored
-35
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "aura/intl",
|
|
||||||
"type": "library",
|
|
||||||
"description": "The Aura Intl package provides internationalization tools, specifically message translation.",
|
|
||||||
"keywords": [
|
|
||||||
"intl",
|
|
||||||
"internationalization",
|
|
||||||
"i18n",
|
|
||||||
"l10n",
|
|
||||||
"localization",
|
|
||||||
"globalization",
|
|
||||||
"g11n"
|
|
||||||
],
|
|
||||||
"homepage": "https://github.com/auraphp/Aura.Intl",
|
|
||||||
"license": "MIT",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Aura.Intl Contributors",
|
|
||||||
"homepage": "https://github.com/auraphp/Aura.Intl/contributors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"php": "^5.6|^7.0"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Aura\\Intl\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {
|
|
||||||
"Aura\\Intl\\": "tests/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-218
@@ -1,218 +0,0 @@
|
|||||||
# Aura.Intl
|
|
||||||
|
|
||||||
The Aura.Intl package provides internationalization (I18N) tools, specifically
|
|
||||||
package-oriented per-locale message translation.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
You can instantiate _TranslatorLocator_ object from _TranslatorLocatorFactory_
|
|
||||||
as below
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
use Aura\Intl\TranslatorLocatorFactory;
|
|
||||||
|
|
||||||
$factory = new TranslatorLocatorFactory();
|
|
||||||
$translators = $factory->newInstance();
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, we can add the Aura.Intl package `/path/to/Aura.Intl/src` to
|
|
||||||
our autoloader and build a translator locator manually:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
use Aura\Intl\PackageLocator;
|
|
||||||
use Aura\Intl\FormatterLocator;
|
|
||||||
use Aura\Intl\TranslatorFactory;
|
|
||||||
use Aura\Intl\TranslatorLocator;
|
|
||||||
|
|
||||||
return new TranslatorLocator(
|
|
||||||
new PackageLocator,
|
|
||||||
new FormatterLocator([
|
|
||||||
'basic' => function () { return new \Aura\Intl\BasicFormatter; },
|
|
||||||
'intl' => function () { return new \Aura\Intl\IntlFormatter; },
|
|
||||||
]),
|
|
||||||
new TranslatorFactory,
|
|
||||||
'en_US'
|
|
||||||
);
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Setting Localized Messages For A Package
|
|
||||||
|
|
||||||
We can set localized messages for a package through the `PackageLocator` object
|
|
||||||
from the translator locator. We create a new `Package` with messages and place
|
|
||||||
it into the locator as a callable. The messages take the form of a message key and
|
|
||||||
and message string.
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
use Aura\Intl\Package;
|
|
||||||
|
|
||||||
// get the package locator
|
|
||||||
$packages = $translators->getPackages();
|
|
||||||
|
|
||||||
// place into the locator for Vendor.Package
|
|
||||||
$packages->set('Vendor.Package', 'en_US', function() {
|
|
||||||
// create a US English message set
|
|
||||||
$package = new Package;
|
|
||||||
$package->setMessages([
|
|
||||||
'FOO' => 'The text for "foo."',
|
|
||||||
'BAR' => 'The text for "bar."',
|
|
||||||
]);
|
|
||||||
return $package;
|
|
||||||
});
|
|
||||||
|
|
||||||
// place into the locator for a Vendor.Package
|
|
||||||
$packages->set('Vendor.Package', 'pt_BR', function() {
|
|
||||||
// a Brazilian Portuguese message set
|
|
||||||
$package = new Package;
|
|
||||||
$package->setMessages([
|
|
||||||
'FOO' => 'O texto de "foo".',
|
|
||||||
'BAR' => 'O texto de "bar".',
|
|
||||||
]);
|
|
||||||
return $package;
|
|
||||||
});
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Setting The Default Locale
|
|
||||||
|
|
||||||
We can set the default locale for translations using the `setLocale()` method:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
$translators->setLocale('pt_BR');
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Getting A Localized Message
|
|
||||||
|
|
||||||
Now that the translator locator has messages and a default locale, we can get
|
|
||||||
an individual package translator. The package translator is suitable for
|
|
||||||
injection into another class, or for standalone use.
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// recall that the default locale is pt_BR
|
|
||||||
$translator = $translators->get('Vendor.Package');
|
|
||||||
echo $translator->translate('FOO'); // 'O texto de "foo".'
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
You can get a translator for a non-default locale as well:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
$translator = $translators->get('Vendor.Package', 'en_US');
|
|
||||||
echo $translator->translate('FOO'); // 'The text for "foo."'
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Replacing Message Tokens With Values
|
|
||||||
|
|
||||||
We often need to use dynamic values in translated messages. First, the
|
|
||||||
message string needs to have a token placeholder for the dynamic value:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// get the packages out of the translator locator
|
|
||||||
$packages = $translators->getPackages();
|
|
||||||
|
|
||||||
$packages->set('Vendor.Dynamic', 'en_US', function() {
|
|
||||||
|
|
||||||
// US English messages
|
|
||||||
$package = new Package;
|
|
||||||
$package->setMessages([
|
|
||||||
'PAGE' => 'Page {page} of {pages} pages.',
|
|
||||||
]);
|
|
||||||
return $package;
|
|
||||||
});
|
|
||||||
|
|
||||||
$packages->set('Vendor.Dynamic', 'pt_BR', function() {
|
|
||||||
// Brazilian Portuguese messages
|
|
||||||
$package = new Package;
|
|
||||||
$package->setMessages([
|
|
||||||
'PAGE' => 'Página {page} de {pages} páginas.',
|
|
||||||
]);
|
|
||||||
return $package;
|
|
||||||
});
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, when we translate the message, we provide an array of tokens and
|
|
||||||
replacement values. These will be interpolated into the message string.
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// recall that the default locale is pt_BR
|
|
||||||
$translator = $translators->get('Vendor.Dynamic');
|
|
||||||
echo $translator->translate('PAGE', [
|
|
||||||
'page' => 1,
|
|
||||||
'pages' => 1,
|
|
||||||
]); // 'Página 1 de 1 páginas.'
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pluralized Messages
|
|
||||||
|
|
||||||
Usually, we need to use different messages when a value is singular or plural.
|
|
||||||
The `BasicFormatter` is not capable of presenting different messages based on
|
|
||||||
different token values. The `IntlFormatter` *is* capable, but the PHP
|
|
||||||
[`intl`](http://php.net/intl) extension must be loaded to take advantage of
|
|
||||||
it, and we must specify the `'intl'` formatter for the package in the catalog.
|
|
||||||
|
|
||||||
When using the `IntlFormatter`, we can build our message strings to present
|
|
||||||
singular or plural messages, as in the following example:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// get the packages out of the translator locator
|
|
||||||
$packages = $translators->getCatalog();
|
|
||||||
|
|
||||||
// get the Vendor.Dynamic package en_US locale and set
|
|
||||||
// US English messages with pluralization. note the use
|
|
||||||
// of # instead of {pages} herein; using the placeholder
|
|
||||||
// "inside itself" with the Intl formatter causes trouble.
|
|
||||||
$package->setMessages([
|
|
||||||
'PAGE' => '{pages,plural,'
|
|
||||||
. '=0{No pages.}'
|
|
||||||
. '=1{One page only.}'
|
|
||||||
. 'other{Page {page} of # pages.}'
|
|
||||||
. '}'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// use the 'intl' formatter for this package and locale
|
|
||||||
$package->setFormatter('intl');
|
|
||||||
|
|
||||||
// now that we have added the pluralizable messages,
|
|
||||||
// get the US English translator for the package
|
|
||||||
$translator = $translators->get('Vendor.Dynamic', 'en_US');
|
|
||||||
|
|
||||||
// zero translation
|
|
||||||
echo $translator->translate('PAGE', [
|
|
||||||
'page' => 0,
|
|
||||||
'pages' => 0,
|
|
||||||
]); // 'No pages.'
|
|
||||||
|
|
||||||
// singular translation
|
|
||||||
echo $translator->translate('PAGE', [
|
|
||||||
'page' => 1,
|
|
||||||
'pages' => 1,
|
|
||||||
]); // 'One page only.'
|
|
||||||
|
|
||||||
// plural translation
|
|
||||||
echo $translator->translate('PAGE', [
|
|
||||||
'page' => 3,
|
|
||||||
'pages' => 10,
|
|
||||||
]); // 'Page 3 of 10 pages.'
|
|
||||||
?>
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that you can use other tokens within a pluralized token string to build
|
|
||||||
more complex messages. For more information, see the following:
|
|
||||||
|
|
||||||
<http://icu-project.org/apiref/icu4j/com/ibm/icu/text/MessageFormat.html>
|
|
||||||
Vendored
-9
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
error_reporting(E_ALL);
|
|
||||||
$autoloader = __DIR__ . '/vendor/autoload.php';
|
|
||||||
if (! file_exists($autoloader)) {
|
|
||||||
echo "Composer autoloader not found: $autoloader" . PHP_EOL;
|
|
||||||
echo "Please issue 'composer install' and try again." . PHP_EOL;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
require $autoloader;
|
|
||||||
Vendored
-12
@@ -1,12 +0,0 @@
|
|||||||
<phpunit bootstrap="./phpunit.php">
|
|
||||||
<testsuites>
|
|
||||||
<testsuite>
|
|
||||||
<directory>./tests</directory>
|
|
||||||
</testsuite>
|
|
||||||
</testsuites>
|
|
||||||
<filter>
|
|
||||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
|
||||||
<directory suffix=".php">./src/</directory>
|
|
||||||
</whitelist>
|
|
||||||
</filter>
|
|
||||||
</phpunit>
|
|
||||||
-47
@@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* BasicFormatter
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class BasicFormatter implements FormatterInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Format message
|
|
||||||
*
|
|
||||||
* @param string $locale
|
|
||||||
*
|
|
||||||
* @param string $string
|
|
||||||
*
|
|
||||||
* @param array $tokens_values
|
|
||||||
*
|
|
||||||
* @return string A string replaced with the token values
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function format($locale, $string, array $tokens_values)
|
|
||||||
{
|
|
||||||
$replace = [];
|
|
||||||
foreach ($tokens_values as $token => $value) {
|
|
||||||
// convert an array to a CSV string
|
|
||||||
if (is_array($value)) {
|
|
||||||
$value = '"' . implode('", "', $value) . '"';
|
|
||||||
}
|
|
||||||
$replace['{' . $token . '}'] = $value;
|
|
||||||
}
|
|
||||||
return strtr($string, $replace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-22
@@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Exception
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Exception extends \Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl\Exception;
|
|
||||||
|
|
||||||
use Aura\Intl\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Could not format a message.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class CannotFormat extends \Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl\Exception;
|
|
||||||
|
|
||||||
use Aura\Intl\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Could not instantiate a formatter object.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class CannotInstantiateFormatter extends \Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl\Exception;
|
|
||||||
|
|
||||||
use Aura\Intl\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A formatter name is not mapped in the locator.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class FormatterNotMapped extends \Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl\Exception;
|
|
||||||
|
|
||||||
use Aura\Intl\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* ICU Version is too low for Aura.Intl to work properly.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class IcuVersionTooLow extends \Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
-34
@@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Formatter Interface
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
interface FormatterInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Format message
|
|
||||||
*
|
|
||||||
* @param string $locale
|
|
||||||
*
|
|
||||||
* @param string $string
|
|
||||||
*
|
|
||||||
* @param array $tokens_values
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function format($locale, $string, array $tokens_values);
|
|
||||||
}
|
|
||||||
-98
@@ -1,98 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A ServiceLocator implementation for loading and retaining formatter objects.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class FormatterLocator
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A registry to retain formatter objects.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $registry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Tracks whether or not a registry entry has been converted from a
|
|
||||||
* callable to a formatter object.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $converted = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param array $registry An array of key-value pairs where the key is the
|
|
||||||
* formatter name the value is a callable that returns a formatter object.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct(array $registry = [])
|
|
||||||
{
|
|
||||||
foreach ($registry as $name => $spec) {
|
|
||||||
$this->set($name, $spec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Sets a formatter into the registry by name.
|
|
||||||
*
|
|
||||||
* @param string $name The formatter name.
|
|
||||||
*
|
|
||||||
* @param callable $spec A callable that returns a formatter object.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function set($name, $spec)
|
|
||||||
{
|
|
||||||
$this->registry[$name] = $spec;
|
|
||||||
$this->converted[$name] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets a formatter from the registry by name.
|
|
||||||
*
|
|
||||||
* @param string $name The formatter to retrieve.
|
|
||||||
*
|
|
||||||
* @return FormatterInterface A formatter object.
|
|
||||||
*
|
|
||||||
* @throws Exception\FormatterNotMapped
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function get($name)
|
|
||||||
{
|
|
||||||
if (! isset($this->registry[$name])) {
|
|
||||||
throw new Exception\FormatterNotMapped($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $this->converted[$name]) {
|
|
||||||
$func = $this->registry[$name];
|
|
||||||
$this->registry[$name] = $func();
|
|
||||||
$this->converted[$name] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->registry[$name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-98
@@ -1,98 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
use MessageFormatter;
|
|
||||||
use Aura\Intl\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Uses php intl extension to format messages
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class IntlFormatter implements FormatterInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param string $icu_version The current ICU version; mostly used for
|
|
||||||
* testing.
|
|
||||||
*
|
|
||||||
* @throws Exception\IcuVersionTooLow when the Version of ICU installed
|
|
||||||
* is too low for Aura.Intl to work properly.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct($icu_version = INTL_ICU_VERSION)
|
|
||||||
{
|
|
||||||
if (version_compare($icu_version, '4.8') < 0) {
|
|
||||||
throw new Exception\IcuVersionTooLow('ICU Version 4.8 or higher required.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Format the message with the help of php intl extension
|
|
||||||
*
|
|
||||||
* @param string $locale
|
|
||||||
* @param string $string
|
|
||||||
* @param array $tokens_values
|
|
||||||
* @return string
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public function format($locale, $string, array $tokens_values)
|
|
||||||
{
|
|
||||||
$values = [];
|
|
||||||
foreach ($tokens_values as $token => $value) {
|
|
||||||
// convert an array to a CSV string
|
|
||||||
if (is_array($value)) {
|
|
||||||
$value = '"' . implode('", "', $value) . '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
$values[$token] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$formatter = new MessageFormatter($locale, $string);
|
|
||||||
if (! $formatter) {
|
|
||||||
$this->throwCannotInstantiateFormatter();
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$this->throwCannotInstantiateFormatter();
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $formatter->format($values);
|
|
||||||
if ($result === false) {
|
|
||||||
throw new Exception\CannotFormat(
|
|
||||||
$formatter->getErrorMessage(),
|
|
||||||
$formatter->getErrorCode()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Throws exception
|
|
||||||
*
|
|
||||||
* @throws Exception\CannotInstantiateFormatter
|
|
||||||
*/
|
|
||||||
protected function throwCannotInstantiateFormatter()
|
|
||||||
{
|
|
||||||
throw new Exception\CannotInstantiateFormatter(
|
|
||||||
intl_get_error_message(),
|
|
||||||
intl_get_error_code()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-197
@@ -1,197 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Message Catalog
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Package
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Message keys and translations in this package.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $messages;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The name of a fallback package to use when a message key does not
|
|
||||||
* exist.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $fallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The name of the formatter to use when formatting translated messages.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $formatter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param string $formatter The name of the formatter to use.
|
|
||||||
*
|
|
||||||
* @param string $fallback The name of the fallback package to use.
|
|
||||||
*
|
|
||||||
* @param array $messages The messages in this package.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
$formatter = 'basic',
|
|
||||||
$fallback = null,
|
|
||||||
array $messages = []
|
|
||||||
) {
|
|
||||||
$this->formatter = $formatter;
|
|
||||||
$this->fallback = $fallback;
|
|
||||||
$this->messages = $messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Sets the messages for this package.
|
|
||||||
*
|
|
||||||
* @param array $messages The messages for this package.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function setMessages(array $messages)
|
|
||||||
{
|
|
||||||
$this->messages = $messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Adds one message for this package.
|
|
||||||
*
|
|
||||||
* @param string $key the key of the message
|
|
||||||
*
|
|
||||||
* @param string $message the actual message
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function addMessage($key, $message)
|
|
||||||
{
|
|
||||||
$this->messages[$key] = $message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Adds new messages for this package.
|
|
||||||
*
|
|
||||||
* @param array $messages The messages to add in this package.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function addMessages($messages)
|
|
||||||
{
|
|
||||||
$this->messages = array_merge($this->messages, $messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets the messages for this package.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getMessages()
|
|
||||||
{
|
|
||||||
return $this->messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets the message of the given key for this package.
|
|
||||||
*
|
|
||||||
* @param string $key the key of the message to return
|
|
||||||
*
|
|
||||||
* @return mixed The message translation string, or false if not found.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getMessage($key)
|
|
||||||
{
|
|
||||||
if (isset($this->messages[$key])) {
|
|
||||||
return $this->messages[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Sets the formatter name for this package.
|
|
||||||
*
|
|
||||||
* @param string $formatter The formatter name for this package.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function setFormatter($formatter)
|
|
||||||
{
|
|
||||||
$this->formatter = $formatter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets the formatter name for this package.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getFormatter()
|
|
||||||
{
|
|
||||||
return $this->formatter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Sets the fallback package name.
|
|
||||||
*
|
|
||||||
* @param string $fallback The fallback package name.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function setFallback($fallback)
|
|
||||||
{
|
|
||||||
$this->fallback = $fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets the fallback package name.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getFallback()
|
|
||||||
{
|
|
||||||
return $this->fallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-47
@@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Creates new package instances.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class PackageFactory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Returns a new Package instance.
|
|
||||||
*
|
|
||||||
* @param array $info An array of package information with keys
|
|
||||||
* 'formatter', 'fallback', and 'messages'. Typically read from an
|
|
||||||
* `intl/xx_XX.php` file.
|
|
||||||
*
|
|
||||||
* @return Package
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function newInstance(array $info)
|
|
||||||
{
|
|
||||||
$package = new Package;
|
|
||||||
if (isset($info['fallback'])) {
|
|
||||||
$package->setFallback($info['fallback']);
|
|
||||||
}
|
|
||||||
if (isset($info['formatter'])) {
|
|
||||||
$package->setFormatter($info['formatter']);
|
|
||||||
}
|
|
||||||
if (isset($info['messages'])) {
|
|
||||||
$package->setMessages($info['messages']);
|
|
||||||
}
|
|
||||||
return $package;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A ServiceLocator implementation for loading and retaining translator objects.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class PackageLocator implements PackageLocatorInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A registry of packages.
|
|
||||||
*
|
|
||||||
* Unlike many other registries, this one is two layers deep. The first
|
|
||||||
* key is a package name, the second key is a locale code, and the value
|
|
||||||
* is a callable that returns a Package object for that name and locale.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $registry = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Tracks whether or not a registry entry has been converted from a
|
|
||||||
* callable to a Package object.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $converted = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param array $registry A registry of packages.
|
|
||||||
*
|
|
||||||
* @see $registry
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct(array $registry = [])
|
|
||||||
{
|
|
||||||
foreach ($registry as $name => $locales) {
|
|
||||||
foreach ($locales as $locale => $spec) {
|
|
||||||
$this->set($name, $locale, $spec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Sets a Package object.
|
|
||||||
*
|
|
||||||
* @param string $name The package name.
|
|
||||||
*
|
|
||||||
* @param string $locale The locale for the package.
|
|
||||||
*
|
|
||||||
* @param callable $spec A callable that returns a package.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function set($name, $locale, callable $spec)
|
|
||||||
{
|
|
||||||
$this->registry[$name][$locale] = $spec;
|
|
||||||
$this->converted[$name][$locale] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets a Package object.
|
|
||||||
*
|
|
||||||
* @param string $name The package name.
|
|
||||||
*
|
|
||||||
* @param string $locale The locale for the package.
|
|
||||||
*
|
|
||||||
* @return Package
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function get($name, $locale)
|
|
||||||
{
|
|
||||||
if (! isset($this->registry[$name][$locale])) {
|
|
||||||
throw new Exception("Package '$name' with locale '$locale' is not registered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $this->converted[$name][$locale]) {
|
|
||||||
$func = $this->registry[$name][$locale];
|
|
||||||
$this->registry[$name][$locale] = $func();
|
|
||||||
$this->converted[$name][$locale] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->registry[$name][$locale];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Package locator interface.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
interface PackageLocatorInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Sets a Package object.
|
|
||||||
*
|
|
||||||
* @param string $name The package name.
|
|
||||||
*
|
|
||||||
* @param string $locale The locale for the package.
|
|
||||||
*
|
|
||||||
* @param callable $spec A callable that returns a Package object.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function set($name, $locale, callable $spec);
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets a Package object.
|
|
||||||
*
|
|
||||||
* @param string $name The package name.
|
|
||||||
*
|
|
||||||
* @param string $locale The locale for the package.
|
|
||||||
*
|
|
||||||
* @return Package
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function get($name, $locale);
|
|
||||||
}
|
|
||||||
Vendored
-158
@@ -1,158 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Translator to translate the message
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Translator implements TranslatorInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A fallback translator.
|
|
||||||
*
|
|
||||||
* @var TranslatorInterface
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $fallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The formatter to use when translating messages.
|
|
||||||
*
|
|
||||||
* @var FormatterInterface
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $formatter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The locale being used for translations.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Package containing keys and translations.
|
|
||||||
*
|
|
||||||
* @var Package
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $package;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param string $locale The locale being used.
|
|
||||||
*
|
|
||||||
* @param Package $package The Package containing keys and translations.
|
|
||||||
*
|
|
||||||
* @param FormatterInterface $formatter A message formatter.
|
|
||||||
*
|
|
||||||
* @param TranslatorInterface $fallback A fallback translator.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
$locale,
|
|
||||||
Package $package,
|
|
||||||
FormatterInterface $formatter,
|
|
||||||
TranslatorInterface $fallback = null
|
|
||||||
) {
|
|
||||||
$this->locale = $locale;
|
|
||||||
$this->package = $package;
|
|
||||||
$this->formatter = $formatter;
|
|
||||||
$this->fallback = $fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets the message translation by its key.
|
|
||||||
*
|
|
||||||
* @param string $key The message key.
|
|
||||||
*
|
|
||||||
* @return mixed The message translation string, or false if not found.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected function getMessage($key)
|
|
||||||
{
|
|
||||||
$message = $this->package->getMessage($key);
|
|
||||||
if ($message) {
|
|
||||||
return $message;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->fallback) {
|
|
||||||
// get the message from the fallback translator
|
|
||||||
$message = $this->fallback->getMessage($key);
|
|
||||||
if ($message) {
|
|
||||||
// speed optimization: retain locally
|
|
||||||
$this->package->addMessage($key, $message);
|
|
||||||
// done!
|
|
||||||
return $message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no local message, no fallback
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Translates the message indicated by they key, replacing token values
|
|
||||||
* along the way.
|
|
||||||
*
|
|
||||||
* @param string $key The message key.
|
|
||||||
*
|
|
||||||
* @param array $tokens_values Token values to interpolate into the
|
|
||||||
* message.
|
|
||||||
*
|
|
||||||
* @return string The translated message with tokens replaced.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function translate($key, array $tokens_values = [])
|
|
||||||
{
|
|
||||||
// get the message string
|
|
||||||
$message = $this->getMessage($key);
|
|
||||||
|
|
||||||
// do we have a message string?
|
|
||||||
if (! $message) {
|
|
||||||
// no, return the message key as-is
|
|
||||||
$message = $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
// are there token replacement values?
|
|
||||||
if (empty($tokens_values)) {
|
|
||||||
// no, return the message string as-is
|
|
||||||
return $message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// run message string through formatter to replace tokens with values
|
|
||||||
return $this->formatter->format($this->locale, $message, $tokens_values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* An object of type Package
|
|
||||||
*
|
|
||||||
* @return Package
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getPackage()
|
|
||||||
{
|
|
||||||
return $this->package;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-57
@@ -1,57 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Factory to create Translator objects.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TranslatorFactory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The class to use for new instances.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $class = Translator::class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Returns a new Translator.
|
|
||||||
*
|
|
||||||
* @param string $locale The locale code for the translator.
|
|
||||||
*
|
|
||||||
* @param Package $package The localized package for the translator.
|
|
||||||
*
|
|
||||||
* @param FormatterInterface $formatter The formatter to use for
|
|
||||||
* interpolating token values.
|
|
||||||
*
|
|
||||||
* @param TranslatorInterface $fallback A fallback translator to use, if
|
|
||||||
* any.
|
|
||||||
*
|
|
||||||
* @return Translator
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function newInstance(
|
|
||||||
$locale,
|
|
||||||
Package $package,
|
|
||||||
FormatterInterface $formatter,
|
|
||||||
TranslatorInterface $fallback = null
|
|
||||||
) {
|
|
||||||
$class = $this->class;
|
|
||||||
return new $class($locale, $package, $formatter, $fallback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* TranslatorInterface
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
interface TranslatorInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* translate
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
*
|
|
||||||
* @param array $tokens_values
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function translate($key, array $tokens_values = []);
|
|
||||||
}
|
|
||||||
-197
@@ -1,197 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A ServiceLocator implementation for loading and retaining translator objects.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TranslatorLocator
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A registry to retain translator objects.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $registry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The current locale code.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A translator factory.
|
|
||||||
*
|
|
||||||
* @var TranslatorFactory
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A package locator.
|
|
||||||
*
|
|
||||||
* @var PackageLocator
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $packages;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* A formatter locator.
|
|
||||||
*
|
|
||||||
* @var FormatterLocator
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $formatters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param PackageLocator $packages The package locator.
|
|
||||||
*
|
|
||||||
* @param FormatterLocator $formatters The formatter locator.
|
|
||||||
*
|
|
||||||
* @param TranslatorFactory $factory A translator factory to
|
|
||||||
* create translator objects for the locale and package.
|
|
||||||
*
|
|
||||||
* @param string $locale The default locale code to use.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
PackageLocator $packages,
|
|
||||||
FormatterLocator $formatters,
|
|
||||||
TranslatorFactory $factory,
|
|
||||||
$locale
|
|
||||||
) {
|
|
||||||
$this->packages = $packages;
|
|
||||||
$this->factory = $factory;
|
|
||||||
$this->formatters = $formatters;
|
|
||||||
$this->setLocale($locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Sets the default locale code.
|
|
||||||
*
|
|
||||||
* @param string $locale The new locale code.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function setLocale($locale)
|
|
||||||
{
|
|
||||||
$this->locale = $locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Returns the default locale code.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getLocale()
|
|
||||||
{
|
|
||||||
return $this->locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* The TranslatorFactory object
|
|
||||||
*
|
|
||||||
* @return TranslatorFactory
|
|
||||||
*/
|
|
||||||
public function getFactory()
|
|
||||||
{
|
|
||||||
return $this->factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* An object of type PackageLocator
|
|
||||||
*
|
|
||||||
* @return PackageLocator
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getPackages()
|
|
||||||
{
|
|
||||||
return $this->packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* An object of type FormatterLocator
|
|
||||||
*
|
|
||||||
* @return FormatterLocator
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getFormatters()
|
|
||||||
{
|
|
||||||
return $this->formatters;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Gets a translator from the registry by package for a locale.
|
|
||||||
*
|
|
||||||
* @param string $name The translator package to retrieve.
|
|
||||||
*
|
|
||||||
* @param string $locale The locale to use; if empty, uses the default
|
|
||||||
* locale.
|
|
||||||
*
|
|
||||||
* @return TranslatorInterface A translator object.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function get($name, $locale = null)
|
|
||||||
{
|
|
||||||
if (! $name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $locale) {
|
|
||||||
$locale = $this->getLocale();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! isset($this->registry[$name][$locale])) {
|
|
||||||
|
|
||||||
// get the package descriptor
|
|
||||||
$package = $this->packages->get($name, $locale);
|
|
||||||
|
|
||||||
// build a translator; note the recursive nature of the
|
|
||||||
// 'fallback' param at the very end.
|
|
||||||
$translator = $this->factory->newInstance(
|
|
||||||
$locale,
|
|
||||||
$package,
|
|
||||||
$this->formatters->get($package->getFormatter()),
|
|
||||||
$this->get($package->getFallback(), $locale)
|
|
||||||
);
|
|
||||||
|
|
||||||
// retain in the registry
|
|
||||||
$this->registry[$name][$locale] = $translator;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->registry[$name][$locale];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This file is part of the Aura Project for PHP.
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
* @license http://opensource.org/licenses/MIT MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
namespace Aura\Intl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Formatter Interface
|
|
||||||
*
|
|
||||||
* @package Aura.Intl
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class TranslatorLocatorFactory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Returns a new TranslatorLocator.
|
|
||||||
*
|
|
||||||
* @return TranslatorLocator
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function newInstance()
|
|
||||||
{
|
|
||||||
return new TranslatorLocator(
|
|
||||||
new PackageLocator,
|
|
||||||
new FormatterLocator([
|
|
||||||
'basic' => function () {
|
|
||||||
return new \Aura\Intl\BasicFormatter;
|
|
||||||
},
|
|
||||||
'intl' => function () {
|
|
||||||
return new \Aura\Intl\IntlFormatter;
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
new TranslatorFactory,
|
|
||||||
'en_US'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loaded 100 of 3821 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user