Initial commit: apps.prometeysev.ru
This commit is contained in:
commit
96ccabcd8b
6561 files changed
+1270349
No files matched your search
+42
@@ -0,0 +1,42 @@
|
||||
# Contributing
|
||||
|
||||
Pull requests are highly appreciated. Here's a quick guide.
|
||||
|
||||
Fork, then clone the repo:
|
||||
|
||||
git clone git@github.com:your-username/TwigView.git
|
||||
|
||||
Set up your machine:
|
||||
|
||||
composer install
|
||||
|
||||
Make sure the tests pass:
|
||||
|
||||
make unit
|
||||
|
||||
Make sure the tests pass on all supported PHP versions (requires docker):
|
||||
|
||||
make dunit
|
||||
|
||||
Make your change. Add tests for your change. Make the tests pass:
|
||||
|
||||
make dunit && make unit
|
||||
|
||||
Before committing and submitting your pull request make sure it passes PSR2 coding style, unit tests pass and pass on all supported PHP versions:
|
||||
|
||||
make contrib
|
||||
|
||||
Push to your fork and [submit a pull request][pr].
|
||||
|
||||
[pr]: https://help.github.com/articles/creating-a-pull-request/
|
||||
|
||||
At this point you're waiting on me. I like to at least comment on pull requests
|
||||
within a day or two. I may suggest some changes or improvements or alternatives.
|
||||
|
||||
Some things that will increase the chance that your pull request is accepted:
|
||||
|
||||
* Write tests.
|
||||
* Follow PSR2 (travis will also check for this).
|
||||
* Write a [good commit message][commit].
|
||||
|
||||
[commit]: http://chris.beams.io/posts/git-commit/
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Cees-Jan Kiewiet
|
||||
|
||||
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.
|
||||
+429
@@ -0,0 +1,429 @@
|
||||
# TwigView plugin for CakePHP #
|
||||
|
||||
[](https://travis-ci.org/WyriHaximus/TwigView)
|
||||
[](https://packagist.org/packages/WyriHaximus/Twig-View)
|
||||
[](https://packagist.org/packages/WyriHaximus/Twig-View/stats)
|
||||
[](https://scrutinizer-ci.com/g/WyriHaximus/TwigView/?branch=master)
|
||||
[](https://packagist.org/packages/wyrihaximus/Twig-View)
|
||||
[](https://travis-ci.org/WyriHaximus/TwigView)
|
||||
|
||||
This plugin for version 3 the [CakePHP Framework](http://cakephp.org) allows you to use the [Twig Templating Language](http://twig.sensiolabs.org) for your views.
|
||||
|
||||
In addition to enabling the use of most of Twig's features, the plugin is tightly integrated with the CakePHP view renderer giving you full access to helpers, objects and elements.
|
||||
|
||||
## Installation ##
|
||||
|
||||
To install via [Composer](http://getcomposer.org/), use the command below, it will automatically detect the latest version and bind it with `~`.
|
||||
|
||||
```bash
|
||||
composer require wyrihaximus/twig-view
|
||||
```
|
||||
|
||||
## Configuration ##
|
||||
|
||||
### Load Plugin
|
||||
Add the following to your `config/bootstrap.php` to load the plugin.
|
||||
```php
|
||||
Plugin::load('WyriHaximus/TwigView', [
|
||||
'bootstrap' => true,
|
||||
]);
|
||||
```
|
||||
|
||||
### Use View class
|
||||
Instead of extending from the `View` let `AppView` extend `TwigView`:
|
||||
|
||||
```php
|
||||
namespace App\View;
|
||||
|
||||
use WyriHaximus\TwigView\View\TwigView;
|
||||
|
||||
class AppView extends TwigView
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Load Helpers
|
||||
In `Controller/AppController` load your helpers:
|
||||
|
||||
```PHP
|
||||
public $helpers = ['Html', 'Form']; // And more
|
||||
```
|
||||
|
||||
Or in your AppView file :
|
||||
|
||||
```PHP
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$this->loadHelper('Html');
|
||||
$this->loadHelper('Form');
|
||||
}
|
||||
```
|
||||
|
||||
Note: TwigView will look for its templates with the extension `.twig` and then for `.tpl` (deprecated).
|
||||
|
||||
### Layout
|
||||
Replace `Template/Layout/default.ctp` by this `Layout/default.twig`
|
||||
|
||||
``` twig
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
{{ Html.charset()|raw }}
|
||||
|
||||
<title>
|
||||
{{ __('myTwigExample') }}
|
||||
{{ _view.fetch('title')|raw }}
|
||||
</title>
|
||||
|
||||
{{ Html.meta('icon')|raw }}
|
||||
|
||||
{{ Html.css('default.app.css')|raw }}
|
||||
{{ Html.script('app')|raw }}
|
||||
|
||||
{{ _view.fetch('meta')|raw }}
|
||||
{{ _view.fetch('css')|raw }}
|
||||
{{ _view.fetch('script')|raw }}
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
{{ _view.fetch('header')|raw }}
|
||||
</header>
|
||||
|
||||
{{ Flash.render()|raw }}
|
||||
|
||||
<section>
|
||||
|
||||
<h1>{{ _view.fetch('title')|raw }}</h1>
|
||||
|
||||
{{ _view.fetch('content')|raw }}
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
{{ _view.fetch('footer')|raw }}
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Template View
|
||||
Create a template, for exemple `Template/Users/index.twig` like this
|
||||
```Twig
|
||||
{{ _view.assign('title', __("I'm title")) }}
|
||||
|
||||
{{ _view.start('header') }}
|
||||
<p>I'm header</p>
|
||||
{{ _view.end() }}
|
||||
|
||||
{{ _view.start('footer') }}
|
||||
<p>I'm footer</p>
|
||||
{{ _view.end() }}
|
||||
|
||||
<p>I'm content</p>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Use `$this`
|
||||
With twig `$this` is replaced by `_view`
|
||||
|
||||
For example, without using Twig writing
|
||||
```php
|
||||
<?= $this->fetch('content') ?>
|
||||
```
|
||||
But with Twig
|
||||
```twig
|
||||
{{ _view.fetch('content')|raw }}
|
||||
```
|
||||
### Helpers
|
||||
|
||||
Any helper you defined in your controller.
|
||||
|
||||
```php
|
||||
public $helpers = ['Html', 'Form']; // ...
|
||||
```
|
||||
|
||||
Can be access by their CamelCase name, for example creating a form using the `FormHelper`:
|
||||
|
||||
```twig
|
||||
{{ Html.link('Edit user', {'controller':'Users', 'action': 'edit' ~ '/' ~ user.id}, {'class':'myclass'})|raw }}
|
||||
```
|
||||
|
||||
### Elements
|
||||
Basic
|
||||
```Twig
|
||||
{% element 'Element' %}
|
||||
```
|
||||
With variables or options
|
||||
```Twig
|
||||
{% element 'Plugin.Element' {
|
||||
dataName: 'dataValue'
|
||||
} {
|
||||
optionName: 'optionValue'
|
||||
} %}
|
||||
```
|
||||
|
||||
### Cells
|
||||
|
||||
Store in context then echo it
|
||||
```twig
|
||||
{% cell cellObject = 'Plugin.Cell' {
|
||||
dataName: 'dataValue'
|
||||
} {
|
||||
optionName: 'optionValue'
|
||||
} %}
|
||||
|
||||
{{ cellObject|raw }}
|
||||
```
|
||||
|
||||
Fetch and directly echo it
|
||||
```twig
|
||||
{% cell 'Plugin.Cell' {
|
||||
dataName: 'dataValue'
|
||||
} {
|
||||
optionName: 'optionValue'
|
||||
} %}
|
||||
```
|
||||
|
||||
### Extends
|
||||
If i want extend to `Common/demo.twig`
|
||||
```twig
|
||||
<div id="sidebar">
|
||||
{% block sidebar %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
```
|
||||
We can write in a view
|
||||
```twig
|
||||
{% extends 'Common/demo' %}
|
||||
|
||||
{% block sidebar %}
|
||||
<ul>
|
||||
<li>Item 1</li>
|
||||
<li>Item 2</li>
|
||||
<li>Item 3</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
{{ _view.assign('title', __("I'm title")) }}
|
||||
|
||||
{{ _view.start('header') }}
|
||||
<p>I'm header</p>
|
||||
{{ _view.end() }}
|
||||
|
||||
{{ _view.start('footer') }}
|
||||
<p>I'm footer</p>
|
||||
{{ _view.end() }}
|
||||
|
||||
<p>I'm content</p>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
**Note : the block `body` is required, it's equivalent to `<?= $this->fetch('content') ?>`**
|
||||
|
||||
### Filters
|
||||
* `debug` maps to [`debug`](https://book.cakephp.org/3.0/en/development/debugging.html#basic-debugging)
|
||||
* `pr` maps to `pr`
|
||||
* `low` maps to [`low`](http://php.net/low)
|
||||
* `up` maps to [`up`](http://php.net/up)
|
||||
* `env` maps to [`env`](http://php.net/env)
|
||||
* `count` maps to [`count`](http://php.net/count)
|
||||
* `pluralize` maps to [`Cake\Utility\Inflector::pluralize`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::pluralize)
|
||||
* `singularize` maps to [`Cake\Utility\Inflector::singularize`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::singularize)
|
||||
* `camelize` maps to [`Cake\Utility\Inflector::camelize`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::camelize)
|
||||
* `underscore` maps to [`Cake\Utility\Inflector::underscore`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::underscore)
|
||||
* `humanize` maps to [`Cake\Utility\Inflector::humanize`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::humanize)
|
||||
* `tableize` maps to [`Cake\Utility\Inflector::tableize`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::tableize)
|
||||
* `classify` maps to [`Cake\Utility\Inflector::classify`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::classify)
|
||||
* `variable` maps to [`Cake\Utility\Inflector::variable`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::variable)
|
||||
* `slug` maps to [`Cake\Utility\Inflector::slug`](https://book.cakephp.org/3.0/en/core-libraries/inflector.html#Cake\\Utility\\Inflector::slug)
|
||||
* `toReadableSize` maps to [`Cake\I18n\Number::toReadableSize`](https://book.cakephp.org/3.0/en/core-libraries/number.html#Cake\\I18n\\Number::toReadableSize)
|
||||
* `fromReadableSize` maps to [`Cake\I18n\Number::fromReadableSize`](https://book.cakephp.org/3.0/en/core-libraries/number.html#Cake\\I18n\\Number::fromReadableSize)
|
||||
* `toPercentage` maps to [`Cake\I18n\Number::toPercentage`](https://book.cakephp.org/3.0/en/core-libraries/number.html#Cake\\I18n\\Number::toPercentage)
|
||||
* `number_format` maps to [`Cake\I18n\Number::format`](https://book.cakephp.org/3.0/en/core-libraries/number.html#Cake\\I18n\\Number::format)
|
||||
* `formatDelta` maps to [`Cake\I18n\Number::formatDelta`](https://book.cakephp.org/3.0/en/core-libraries/number.html#Cake\\I18n\\Number::formatDelta)
|
||||
* `currency` maps to [`Cake\I18n\Number::currency`](https://book.cakephp.org/3.0/en/core-libraries/number.html#Cake\\I18n\\Number::currency)
|
||||
* `substr` maps to [`substr`](http://php.net/substr)
|
||||
* `tokenize` maps to [`Cake\Utility\Text::tokenize`](https://book.cakephp.org/3.0/en/core-libraries/text.html#simple-string-parsing)
|
||||
* `insert` maps to [`Cake\Utility\Text::insert`](https://book.cakephp.org/3.0/en/core-libraries/text.html#formatting-strings)
|
||||
* `cleanInsert` maps to [`Cake\Utility\Text::cleanInsert`](https://book.cakephp.org/3.0/en/core-libraries/text.html#formatting-strings)
|
||||
* `wrap` maps to [`Cake\Utility\Text::wrap`](https://book.cakephp.org/3.0/en/core-libraries/text.html#wrapping-text)
|
||||
* `wrapBlock` maps to [`Cake\Utility\Text::wrapBlock`](https://book.cakephp.org/3.0/en/core-libraries/text.html#wrapping-text)
|
||||
* `wordWrap` maps to [`Cake\Utility\Text::wordWrap`](https://book.cakephp.org/3.0/en/core-libraries/text.html#wrapping-text)
|
||||
* `highlight` maps to [`Cake\Utility\Text::highlight`](https://book.cakephp.org/3.0/en/core-libraries/text.html#highlighting-substrings)
|
||||
* `tail` maps to [`Cake\Utility\Text::tail`](https://book.cakephp.org/3.0/en/core-libraries/text.html#truncating-the-tail-of-a-string)
|
||||
* `truncate` maps to [`Cake\Utility\Text::truncate`](https://book.cakephp.org/3.0/en/core-libraries/text.html#truncating-text)
|
||||
* `excerpt` maps to [`Cake\Utility\Text::excerpt`](https://book.cakephp.org/3.0/en/core-libraries/text.html#extracting-an-excerpt)
|
||||
* `toList` maps to [`Cake\Utility\Text::toList`](https://book.cakephp.org/3.0/en/core-libraries/text.html#converting-an-array-to-sentence-)
|
||||
* `stripLinks` maps to [`Cake\Utility\Text::stripLinks`](https://book.cakephp.org/3.0/en/core-libraries/text.html#removing-links)
|
||||
* `isMultibyte` maps to `Cake\Utility\Text::isMultibyte`
|
||||
* `utf8` maps to `Cake\Utility\Text::utf8`
|
||||
* `ascii` maps to `Cake\Utility\Text::ascii`
|
||||
* `parseFileSize` maps to [`Cake\Utility\Text::parseFileSize`](https://book.cakephp.org/3.0/en/core-libraries/text.html#simple-string-parsing)
|
||||
* `serialize` maps to [`serialize`](http://php.net/serialize)
|
||||
* `unserialize` maps to [`unserialize`](http://php.net/unserialize)
|
||||
* `md5` maps to [`md5`](http://php.net/md5)
|
||||
* `base64_encode` maps to [`base64_encode`](http://php.net/base64_encode)
|
||||
* `base64_decode` maps to [`base64_decode`](http://php.net/base64_decode)
|
||||
* `nl2br` maps to [`nl2br`](http://php.net/nl2br)
|
||||
* `string` cast to [`string`](http://php.net/manual/en/language.types.type-juggling.php)
|
||||
|
||||
### Functions
|
||||
* `in_array` maps to [`in_array`](http://php.net/in_array)
|
||||
* `explode` maps to [`explode`](http://php.net/explode)
|
||||
* `array` cast to [`array`](http://php.net/manual/en/language.types.type-juggling.php)
|
||||
* `array_push` maps to [`push`](http://php.net/push)
|
||||
* `array_add` maps to [`add`](http://php.net/add)
|
||||
* `array_prev` maps to [`prev`](http://php.net/prev)
|
||||
* `array_next` maps to [`next`](http://php.net/next)
|
||||
* `array_current` maps to [`current`](http://php.net/current)
|
||||
* `array_each` maps to [`each`](http://php.net/each)
|
||||
* `__` maps to [`__`](https://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html)
|
||||
* `__d` maps to [`__d`](https://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html)
|
||||
* `__n` maps to [`__n`](https://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html)
|
||||
* `__x` maps to [`__x`](https://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html)
|
||||
* `__dn` maps to [`__dn`](https://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html)
|
||||
* `defaultCurrency` maps to [`Cake\I18n\Number::defaultCurrency`](https://book.cakephp.org/3.0/en/core-libraries/number.html#Cake\\I18n\\Number::defaultCurrency)
|
||||
* `number_formatter` maps to [`Cake\I18n\Number::formatter`](https://book.cakephp.org/3.0/en/core-libraries/number.html#Cake\\I18n\\Number::formatter)
|
||||
* `uuid` maps to [`Cake\Utility\Text::uuid`](https://book.cakephp.org/3.0/en/core-libraries/text.html#generating-uuids)
|
||||
* `time` passed the first and optional second argument into [`new \Cake\I18n\Time()`](https://book.cakephp.org/3.0/en/core-libraries/time.html#creating-time-instances)
|
||||
* `timezones` maps to `Cake\I18n\Time::listTimezones`
|
||||
* `elementExists` maps to `Cake\View\View::elementExists`,
|
||||
* `getVars` maps to `Cake\View\View::getVars`
|
||||
* `get` maps to `Cake\View\View::get`
|
||||
|
||||
### Twig
|
||||
Visite [Twig Documentaion](http://twig.sensiolabs.org/documentation) for more tips
|
||||
|
||||
### Extra included extensions
|
||||
|
||||
* [Breakpoint extension](https://github.com/ajgarlag/AjglBreakpointTwigExtension)
|
||||
* [aptoma/twig-markdown](https://github.com/aptoma/twig-markdown)
|
||||
* [jasny/twig-extensions](https://github.com/jasny/twig-extensions)
|
||||
* [umpirsky/twig-php-function](https://github.com/umpirsky/twig-php-function)
|
||||
|
||||
## Events ##
|
||||
|
||||
This plugin emits several events.
|
||||
|
||||
### Loaders ###
|
||||
|
||||
The default loader can be replace by listening to the `WyriHaximus\TwigView\Event\LoaderEvent::EVENT`, for example with [twital](https://github.com/goetas/twital):
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Cake\Event\EventListenerInterface;
|
||||
use Goetas\Twital\TwitalLoader;
|
||||
use WyriHaximus\TwigView\Event\ConstructEvent;
|
||||
use WyriHaximus\TwigView\Event\LoaderEvent;
|
||||
|
||||
class LoaderListener implements EventListenerInterface
|
||||
{
|
||||
public function implementedEvents()
|
||||
{
|
||||
return [
|
||||
LoaderEvent::EVENT => 'loader',
|
||||
ConstructEvent::EVENT => 'construct',
|
||||
];
|
||||
}
|
||||
|
||||
public function loader(LoaderEvent $event)
|
||||
{
|
||||
$event->result = new TwitalLoader($event->getLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* We've also listening in on this event so we can add the needed extensions to check for to the view
|
||||
*/
|
||||
public function construct(ConstructEvent $event)
|
||||
{
|
||||
$event->getTwigView()->unshiftExtension('.twital.html');
|
||||
$event->getTwigView()->unshiftExtension('.twital.xml');
|
||||
$event->getTwigView()->unshiftExtension('.twital.xhtml');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
### Extensions ###
|
||||
|
||||
Extensions can be added to the twig environment by listening to the `WyriHaximus\TwigView\Event\ConstructEvent::EVENT`, for example:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Cake\Event\EventListenerInterface;
|
||||
use WyriHaximus\TwigView\Event\ConstructEvent;
|
||||
|
||||
class LoaderListener implements EventListenerInterface
|
||||
{
|
||||
public function implementedEvents()
|
||||
{
|
||||
return [
|
||||
ConstructEvent::EVENT => 'construct',
|
||||
];
|
||||
}
|
||||
|
||||
public function construct(ConstructEvent $event)
|
||||
{
|
||||
$event->getTwig()->addExtension(new YourTwigExtension);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Bake
|
||||
|
||||
You can use Bake to generate your basic CRUD views using the `theme` option.
|
||||
Let's say you have a `TasksController` for which you want to generate twig templates.
|
||||
You can use the following command to generate your index, add, edit and view file formatted
|
||||
using Twig :
|
||||
|
||||
```bash
|
||||
bin/cake bake twig_template Tasks all -t WyriHaximus/TwigView
|
||||
```
|
||||
|
||||
## Screenshots ##
|
||||
|
||||
### Profiler ###
|
||||
|
||||

|
||||
|
||||
### Templates found ###
|
||||
|
||||

|
||||
|
||||
## License ##
|
||||
|
||||
Copyright 2015 [Cees-Jan Kiewiet](http://wyrihaximus.net/)
|
||||
|
||||
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.
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "wyrihaximus/twig-view",
|
||||
"description": "Twig powered View for CakePHP3",
|
||||
"type":"cakephp-plugin",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"twig",
|
||||
"view",
|
||||
"cakephp",
|
||||
"cakephp3"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Cees-Jan Kiewiet",
|
||||
"email": "ceesjank@gmail.com",
|
||||
"homepage": "http://wyrihaximus.net/"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0",
|
||||
"ajgl/breakpoint-twig-extension": "^0.3.0",
|
||||
"aptoma/twig-markdown": "^2.0",
|
||||
"asm89/twig-cache-extension": "^1.0",
|
||||
"cakephp/cakephp": "^3.6",
|
||||
"jasny/twig-extensions": "^1.0",
|
||||
"twig/twig": "^1.27",
|
||||
"umpirsky/twig-php-function": "0.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"cakephp/bake": "^1.5",
|
||||
"cakephp/debug_kit": "^3.0",
|
||||
"phake/phake": "^1.0.4",
|
||||
"phpunit/phpunit": "^5.7.14",
|
||||
"squizlabs/php_codesniffer": "^1.5.6",
|
||||
"wyrihaximus/phpunit-class-reflection-helpers": "dev-master"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WyriHaximus\\TwigView\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"WyriHaximus\\CakePHP\\Tests\\TwigView\\": "tests/",
|
||||
"App\\": "tests/test_app/",
|
||||
"Cake\\Test\\": "./vendor/cakephp/cakephp/tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"platform": {
|
||||
"php": "5.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
+2179
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Core\Plugin;
|
||||
use Cake\Event\EventManager;
|
||||
use WyriHaximus\TwigView\Event;
|
||||
|
||||
EventManager::instance()->on(new Event\ExtensionsListener());
|
||||
EventManager::instance()->on(new Event\TokenParsersListener());
|
||||
|
||||
if (Configure::read('debug') && Plugin::getCollection()->has('DebugKit')) {
|
||||
Configure::write('DebugKit.panels', array_merge(
|
||||
(array)Configure::read('DebugKit.panels'),
|
||||
[
|
||||
'WyriHaximus/TwigView.Twig',
|
||||
]
|
||||
));
|
||||
EventManager::instance()->on(new Event\ProfilerListener());
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'WyriHaximus' => [
|
||||
'TwigView' => [
|
||||
'environment' => [
|
||||
// Anything you would pass into \Twig_Environment to overwrite the default settings, see: http://twig.sensiolabs.org/doc/api.html#environment-options
|
||||
],
|
||||
'markdown' => [
|
||||
'engine' => 'engine', // See https://github.com/aptoma/twig-markdown#installation
|
||||
],
|
||||
'flags' => [
|
||||
'potentialDangerous' => false,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
## Change AppView
|
||||
```PHP
|
||||
// src/View/AppView.php
|
||||
namespace App\View;
|
||||
|
||||
use WyriHaximus\TwigView\View\TwigView;
|
||||
|
||||
class AppView extends TwigView
|
||||
{
|
||||
// Code ...
|
||||
}
|
||||
```
|
||||
|
||||
## Load Helpers
|
||||
```PHP
|
||||
// src/View/AppView.php
|
||||
namespace App\View;
|
||||
|
||||
use WyriHaximus\TwigView\View\TwigView;
|
||||
|
||||
class AppView extends TwigView
|
||||
{
|
||||
public function initialize()
|
||||
{
|
||||
$this->loadHelper('Html');
|
||||
$this->loadHelper('Form');
|
||||
}
|
||||
```
|
||||
|
||||
Note: TwigView will look for its templates with the extension `.twig` and then for `.tpl` (deprecated).
|
||||
|
||||
## Create the default layout to be used by TwigView named `default.twig` instead of `default.ctp`
|
||||
Layout example
|
||||
```Twig
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
{{ Html.charset()|raw }}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
{{ __('MySite') }}
|
||||
{{ _view.fetch('title')|raw }}
|
||||
</title>
|
||||
{{ Html.meta('icon')|raw }}
|
||||
|
||||
{{ Html.css('app.css')|raw }}
|
||||
{{ Html.script('app')|raw }}
|
||||
|
||||
{{ _view.fetch('meta')|raw }}
|
||||
{{ _view.fetch('css')|raw }}
|
||||
{{ _view.fetch('script')|raw }}
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
{{ _view.fetch('header')|raw }}
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<h1 class="page-title">{{ _view.fetch('title') }}</h1>
|
||||
{{ _view.fetch('content')|raw }}
|
||||
</section>
|
||||
|
||||
</body>
|
||||
```
|
||||
|
||||
## Create a view template
|
||||
in Template/Controller/action.twig
|
||||
```Twig
|
||||
|
||||
{{ _view.start('header') }}
|
||||
<p>It's my header</p>
|
||||
{{ _view.end() }}
|
||||
|
||||
{{ _view.assign('title', "it's my title") }}
|
||||
|
||||
<p>It's my content</p>
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Event;
|
||||
|
||||
use Cake\Event\Event;
|
||||
use WyriHaximus\TwigView\View\TwigView;
|
||||
|
||||
class ConstructEvent extends Event
|
||||
{
|
||||
const EVENT = 'TwigView.TwigView.construct';
|
||||
|
||||
/**
|
||||
* @param TwigView $twigView
|
||||
* @param \Twig_Environment $twig
|
||||
* @return static
|
||||
*/
|
||||
public static function create(TwigView $twigView, \Twig_Environment $twig)
|
||||
{
|
||||
return new static(static::EVENT, $twigView, [
|
||||
'twigView' => $twigView,
|
||||
'twig' => $twig,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TwigView
|
||||
*/
|
||||
public function getTwigView()
|
||||
{
|
||||
return $this->getData()['twigView'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Twig_Environment
|
||||
*/
|
||||
public function getTwig()
|
||||
{
|
||||
return $this->getData()['twig'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Event;
|
||||
|
||||
use Cake\Event\Event;
|
||||
|
||||
class EnvironmentConfigEvent extends Event
|
||||
{
|
||||
const EVENT = 'TwigView.TwigView.environment';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $config = [];
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function create(array $config)
|
||||
{
|
||||
$event = new static(static::EVENT);
|
||||
$event->setConfig($config);
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function setConfig(array $config)
|
||||
{
|
||||
$this->config = array_replace_recursive($this->config, $config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Event;
|
||||
|
||||
use Aptoma\Twig\Extension\MarkdownEngineInterface;
|
||||
use Aptoma\Twig\Extension\MarkdownExtension;
|
||||
use Aptoma\Twig\TokenParser\MarkdownTokenParser;
|
||||
use Ajgl\Twig\Extension\BreakpointExtension;
|
||||
use Asm89\Twig\CacheExtension\CacheStrategy\LifetimeCacheStrategy;
|
||||
use Asm89\Twig\CacheExtension\Extension as CacheExtension;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Event\EventListenerInterface;
|
||||
use Jasny\Twig\ArrayExtension;
|
||||
use Jasny\Twig\DateExtension;
|
||||
use Jasny\Twig\PcreExtension;
|
||||
use Jasny\Twig\TextExtension;
|
||||
use Umpirsky\Twig\Extension\PhpFunctionExtension;
|
||||
use WyriHaximus\TwigView\Lib\Cache;
|
||||
use WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
use WyriHaximus\TwigView\Lib\Twig\TokenParser;
|
||||
|
||||
/**
|
||||
* Class ExtensionsListener
|
||||
* @package WyriHaximus\TwigView\Event
|
||||
*/
|
||||
class ExtensionsListener implements EventListenerInterface
|
||||
{
|
||||
/**
|
||||
* Return implemented events.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function implementedEvents()
|
||||
{
|
||||
return [
|
||||
ConstructEvent::EVENT => 'construct',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler.
|
||||
*
|
||||
* @param ConstructEvent $event Event.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function construct(ConstructEvent $event)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
// @codingStandardsIgnoreStart
|
||||
// Twig core extensions
|
||||
$event->getTwig()->addExtension(new \Twig_Extension_StringLoader);
|
||||
$event->getTwig()->addExtension(new \Twig_Extension_Debug);
|
||||
|
||||
// CakePHP bridging extensions
|
||||
$event->getTwig()->addExtension(new Extension\I18n);
|
||||
$event->getTwig()->addExtension(new Extension\Time);
|
||||
$event->getTwig()->addExtension(new Extension\Basic);
|
||||
$event->getTwig()->addExtension(new Extension\Number);
|
||||
$event->getTwig()->addExtension(new Extension\Utils);
|
||||
$event->getTwig()->addExtension(new Extension\Arrays);
|
||||
$event->getTwig()->addExtension(new Extension\Strings);
|
||||
$event->getTwig()->addExtension(new Extension\Inflector);
|
||||
|
||||
if (
|
||||
!Configure::check('WyriHaximus.TwigView.flags.potentialDangerous') ||
|
||||
(
|
||||
Configure::check('WyriHaximus.TwigView.flags.potentialDangerous') &&
|
||||
Configure::read('WyriHaximus.TwigView.flags.potentialDangerous') === true
|
||||
)
|
||||
) {
|
||||
$event->getTwig()->addExtension(new Extension\PotentialDangerous);
|
||||
}
|
||||
|
||||
// Markdown extension
|
||||
if (
|
||||
Configure::check('WyriHaximus.TwigView.markdown.engine') &&
|
||||
Configure::read('WyriHaximus.TwigView.markdown.engine') instanceof MarkdownEngineInterface
|
||||
) {
|
||||
$engine = Configure::read('WyriHaximus.TwigView.markdown.engine');
|
||||
$event->getTwig()->addExtension(new MarkdownExtension($engine));
|
||||
$event->getTwig()->addTokenParser(new MarkdownTokenParser($engine));
|
||||
}
|
||||
|
||||
// Third party cache extension
|
||||
$cacheProvider = new Cache();
|
||||
$cacheStrategy = new LifetimeCacheStrategy($cacheProvider);
|
||||
$cacheExtension = new CacheExtension($cacheStrategy);
|
||||
$event->getTwig()->addExtension($cacheExtension);
|
||||
|
||||
// jasny/twig-extensions
|
||||
$event->getTwig()->addExtension(new DateExtension());
|
||||
$event->getTwig()->addExtension(new PcreExtension());
|
||||
$event->getTwig()->addExtension(new TextExtension());
|
||||
$event->getTwig()->addExtension(new ArrayExtension());
|
||||
|
||||
// umpirsky/twig-php-function
|
||||
$event->getTwig()->addExtension(new PhpFunctionExtension());
|
||||
|
||||
// Breakpoint extension
|
||||
if (Configure::read('debug') === true) {
|
||||
$event->getTwig()->addExtension(new BreakpointExtension());
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Event;
|
||||
|
||||
use Cake\Event\Event;
|
||||
|
||||
class LoaderEvent extends Event
|
||||
{
|
||||
const EVENT = 'TwigView.TwigView.loader';
|
||||
|
||||
/**
|
||||
* @param \Twig_LoaderInterface $loader
|
||||
* @return LoaderEvent
|
||||
*/
|
||||
public static function create(\Twig_LoaderInterface $loader)
|
||||
{
|
||||
return new static(static::EVENT, $loader, [
|
||||
'loader' => $loader,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Twig_LoaderInterface
|
||||
*/
|
||||
public function getLoader()
|
||||
{
|
||||
return $this->getSubject();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|Twig_LoaderInterface
|
||||
*/
|
||||
public function getResultLoader()
|
||||
{
|
||||
if ($this->result instanceof \Twig_LoaderInterface) {
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
if (is_array($this->result) && $this->result['loader'] instanceof \Twig_LoaderInterface) {
|
||||
return $this->result['loader'];
|
||||
}
|
||||
|
||||
return $this->getLoader();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Event;
|
||||
|
||||
use Cake\Event\Event;
|
||||
|
||||
class ProfileEvent extends Event
|
||||
{
|
||||
const EVENT = 'TwigView.TwigView.profile';
|
||||
|
||||
/**
|
||||
* @param \Twig_Profiler_Profile $profile
|
||||
* @return static
|
||||
*/
|
||||
public static function create(\Twig_Profiler_Profile $profile)
|
||||
{
|
||||
return new static(static::EVENT, $profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Twig_Profiler_Profile
|
||||
*/
|
||||
public function getLoader()
|
||||
{
|
||||
return $this->getSubject();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Event;
|
||||
|
||||
use Cake\Event\EventListenerInterface;
|
||||
use Cake\Event\EventManager;
|
||||
use WyriHaximus\TwigView\Lib\Cache;
|
||||
use WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
use WyriHaximus\TwigView\Lib\Twig\TokenParser;
|
||||
|
||||
/**
|
||||
* Class ExtensionsListener
|
||||
* @package WyriHaximus\TwigView\Event
|
||||
*/
|
||||
class ProfilerListener implements EventListenerInterface
|
||||
{
|
||||
/**
|
||||
* Return implemented events.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function implementedEvents()
|
||||
{
|
||||
return [
|
||||
ConstructEvent::EVENT => 'construct',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler.
|
||||
*
|
||||
* @param ConstructEvent $event Event.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function construct(ConstructEvent $event)
|
||||
{
|
||||
$profile = new \Twig_Profiler_Profile();
|
||||
$event->
|
||||
getTwig()->
|
||||
addExtension(new Extension\Profiler($profile));
|
||||
|
||||
EventManager::instance()->dispatch(ProfileEvent::create($profile));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Event;
|
||||
|
||||
use Cake\Event\EventListenerInterface;
|
||||
use WyriHaximus\TwigView\Lib\Cache;
|
||||
use WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
use WyriHaximus\TwigView\Lib\Twig\TokenParser;
|
||||
|
||||
/**
|
||||
* Class TokenParsersListener
|
||||
* @package WyriHaximus\TwigView\Event
|
||||
*/
|
||||
class TokenParsersListener implements EventListenerInterface
|
||||
{
|
||||
/**
|
||||
* Return implemented events.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function implementedEvents()
|
||||
{
|
||||
return [
|
||||
ConstructEvent::EVENT => 'construct',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler.
|
||||
*
|
||||
* @param ConstructEvent $event Event.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function construct(ConstructEvent $event)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
// @codingStandardsIgnoreStart
|
||||
// CakePHP specific tags
|
||||
$event->getTwig()->addTokenParser(new TokenParser\Cell);
|
||||
$event->getTwig()->addTokenParser(new TokenParser\Element);
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace WyriHaximus\TwigView\Lib;
|
||||
|
||||
use Asm89\Twig\CacheExtension\CacheProviderInterface;
|
||||
use Cake\Cache\Cache as CakeCache;
|
||||
|
||||
class Cache implements CacheProviderInterface
|
||||
{
|
||||
const CACHE_PREFIX = 'twig-view-in-template-item-';
|
||||
|
||||
/**
|
||||
* Retrieve data from the cache.
|
||||
*
|
||||
* @param string $identifier Identifier for this bit of data to read.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetch($identifier)
|
||||
{
|
||||
list($config, $key) = $this->configSplit($identifier);
|
||||
|
||||
return CakeCache::read(static::CACHE_PREFIX . $key, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract $configName and $key from $name and $config.
|
||||
*
|
||||
* @param string $name Name.
|
||||
* @param string $config Cache configuration name to used.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function configSplit($name, $config = 'default')
|
||||
{
|
||||
if (strpos($name, ':') !== false) {
|
||||
$parts = explode(':', $name, 2);
|
||||
return $parts;
|
||||
}
|
||||
|
||||
return [$config, $name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data to the cache.
|
||||
*
|
||||
* @param string $identifier Identifier for this bit of data to write.
|
||||
* @param string $data Data to cache.
|
||||
* @param integer $lifeTime Time to life inside the cache.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function save($identifier, $data, $lifeTime = 0)
|
||||
{
|
||||
list($config, $key) = $this->configSplit($identifier);
|
||||
|
||||
return CakeCache::write(static::CACHE_PREFIX . $key, $data, $config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace WyriHaximus\TwigView\Lib;
|
||||
|
||||
use Cake\Core\App;
|
||||
|
||||
/**
|
||||
* Class RelativeScanner
|
||||
* @package WyriHaximus\TwigView\Lib
|
||||
*/
|
||||
class RelativeScanner
|
||||
{
|
||||
/**
|
||||
* Return all sections (app & plugins) with an Template directory.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function all()
|
||||
{
|
||||
return static::strip(Scanner::all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all templates for a given plugin.
|
||||
*
|
||||
* @param string $plugin The plugin to find all templates for.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function plugin($plugin)
|
||||
{
|
||||
return static::strip([
|
||||
$plugin => Scanner::plugin($plugin),
|
||||
])[$plugin];
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip the absolute path of template's paths for all given sections.
|
||||
*
|
||||
* @param string $sections Sections to iterate over.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function strip($sections)
|
||||
{
|
||||
foreach ($sections as $section => $paths) {
|
||||
$sections[$section] = static::stripAbsolutePath($paths, $section == 'APP' ? null : $section);
|
||||
}
|
||||
return $sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip the absolute path of template's paths.
|
||||
*
|
||||
* @param array $paths Paths to strip.
|
||||
* @param string|null $plugin Hold plugin name or null for App.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function stripAbsolutePath(array $paths, $plugin = null)
|
||||
{
|
||||
foreach (App::path('Template', $plugin) as $templatesPath) {
|
||||
array_walk($paths, function (&$path) use ($templatesPath) {
|
||||
if (substr($path, 0, strlen($templatesPath)) == $templatesPath) {
|
||||
$path = substr($path, strlen($templatesPath));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace WyriHaximus\TwigView\Lib;
|
||||
|
||||
use Cake\Core\App;
|
||||
use Cake\Core\Plugin;
|
||||
use WyriHaximus\TwigView\View\TwigView;
|
||||
|
||||
/**
|
||||
* Class Scanner
|
||||
* @package WyriHaximus\TwigView\Lib
|
||||
*/
|
||||
class Scanner
|
||||
{
|
||||
/**
|
||||
* Return all sections (app & plugins) with an Template directory.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public static function all()
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
$sections = [];
|
||||
|
||||
foreach (App::path('Template') as $path) {
|
||||
if (is_dir($path)) {
|
||||
$sections['APP'] = isset($sections['APP']) ? $sections['APP'] : [];
|
||||
$sections['APP'] = array_merge($sections['APP'], static::iteratePath($path));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (static::pluginsWithTemplates() as $plugin) {
|
||||
foreach (App::path('Template', $plugin) as $path) {
|
||||
if (is_dir($path)) {
|
||||
$sections[$plugin] = isset($sections[$plugin]) ? $sections[$plugin] : [];
|
||||
$sections[$plugin] = array_merge($sections[$plugin], static::iteratePath($path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static::clearEmptySections($sections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check sections a remove the ones without anything in them.
|
||||
*
|
||||
* @param array $sections Sections to check.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function clearEmptySections(array $sections)
|
||||
{
|
||||
array_walk($sections, function ($templates, $index) use (&$sections) {
|
||||
if (count($templates) == 0) {
|
||||
unset($sections[$index]);
|
||||
}
|
||||
});
|
||||
|
||||
return $sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all plugins with a Template directory.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function pluginsWithTemplates()
|
||||
{
|
||||
$plugins = Plugin::loaded();
|
||||
|
||||
array_walk($plugins, function ($plugin, $index) use (&$plugins) {
|
||||
$paths = App::path('Template', $plugin);
|
||||
|
||||
array_walk($paths, function ($path, $index) use (&$paths) {
|
||||
if (!is_dir($path)) {
|
||||
unset($paths[$index]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all templates for a given plugin.
|
||||
*
|
||||
* @param string $plugin The plugin to find all templates for.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function plugin($plugin)
|
||||
{
|
||||
$templates = [];
|
||||
|
||||
foreach (App::path('Template', $plugin) as $path) {
|
||||
$templates = array_merge($templates, static::iteratePath($path));
|
||||
}
|
||||
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterage over the given path and return all matching .tpl files in it.
|
||||
*
|
||||
* @param string $path Path to iterate over.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function iteratePath($path)
|
||||
{
|
||||
return static::walkIterator(static::setupIterator($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup iterator for given path.
|
||||
*
|
||||
* @param string $path Path to setup iterator for.
|
||||
*
|
||||
* @return \Iterator
|
||||
*/
|
||||
protected static function setupIterator($path)
|
||||
{
|
||||
return new \RegexIterator(new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator(
|
||||
$path,
|
||||
\FilesystemIterator::KEY_AS_PATHNAME |
|
||||
\FilesystemIterator::CURRENT_AS_FILEINFO |
|
||||
\FilesystemIterator::SKIP_DOTS
|
||||
),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST,
|
||||
\RecursiveIteratorIterator::CATCH_GET_CHILD
|
||||
), '/.*?' . TwigView::EXT . '$/', \RegexIterator::GET_MATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk over the iterator and compile all templates.
|
||||
*
|
||||
* @param \Iterator $iterator Iterator to walk.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
protected static function walkIterator(\Iterator $iterator)
|
||||
{
|
||||
$items = [];
|
||||
|
||||
$array = iterator_to_array($iterator);
|
||||
uasort($array, function ($a, $b) {
|
||||
if ($a == $b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($a < $b) ? -1 : 1;
|
||||
});
|
||||
|
||||
foreach ($array as $paths) {
|
||||
foreach ($paths as $path) {
|
||||
$items[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace WyriHaximus\TwigView\Lib;
|
||||
|
||||
/**
|
||||
* Class TreeScanner
|
||||
* @package WyriHaximus\TwigView\Lib
|
||||
*/
|
||||
class TreeScanner
|
||||
{
|
||||
/**
|
||||
* Return all sections (app & plugins) with an Template directory.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function all()
|
||||
{
|
||||
return static::deepen(RelativeScanner::all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all templates for a given plugin.
|
||||
*
|
||||
* @param string $plugin The plugin to find all templates for.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function plugin($plugin)
|
||||
{
|
||||
return static::deepen([
|
||||
$plugin => RelativeScanner::plugin($plugin),
|
||||
])[$plugin];
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip the absolute path of template's paths for all given sections.
|
||||
*
|
||||
* @param string $sections Sections to iterate over.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function deepen($sections)
|
||||
{
|
||||
foreach ($sections as $section => $paths) {
|
||||
$sections[$section] = static::convertToTree($paths);
|
||||
}
|
||||
return $sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a set of paths into a tree.
|
||||
*
|
||||
* @param array $paths Paths to turn into a tree.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function convertToTree(array $paths)
|
||||
{
|
||||
foreach ($paths as $index => $path) {
|
||||
static::convertPathToTree($paths, $index, $path);
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a path into a tree when it contains a directory separator.
|
||||
*
|
||||
* @param array $paths The paths to work on.
|
||||
* @param mixed $index Index of $path.
|
||||
* @param string $path Path to breakup and turn into a tree.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function convertPathToTree(array &$paths, $index, $path)
|
||||
{
|
||||
if (strpos($path, DIRECTORY_SEPARATOR) !== false) {
|
||||
$chunks = explode(DIRECTORY_SEPARATOR, $path);
|
||||
$paths = static::branch($paths, $chunks);
|
||||
unset($paths[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a branch for the current level and push a twig on it.
|
||||
*
|
||||
* @param array $paths Paths to append.
|
||||
* @param array $branches Branches to use untill only one left.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function branch(array $paths, array $branches)
|
||||
{
|
||||
$twig = array_shift($branches);
|
||||
if (count($branches) == 0) {
|
||||
$paths[] = $twig;
|
||||
return $paths;
|
||||
}
|
||||
|
||||
if (!isset($paths[$twig])) {
|
||||
$paths[$twig] = [];
|
||||
}
|
||||
|
||||
$paths[$twig] = static::branch($paths[$twig], $branches);
|
||||
|
||||
return $paths;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
/**
|
||||
* Class Arrays
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class Arrays extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* Get declared functions.
|
||||
*
|
||||
* @return \Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('in_array', 'in_array'),
|
||||
new \Twig_SimpleFunction('explode', 'explode'),
|
||||
new \Twig_SimpleFunction('array', function ($array) {
|
||||
return (array)$array;
|
||||
}),
|
||||
new \Twig_SimpleFunction('array_push', 'push'),
|
||||
new \Twig_SimpleFunction('array_add', 'add'),
|
||||
new \Twig_SimpleFunction('array_prev', 'prev'),
|
||||
new \Twig_SimpleFunction('array_next', 'next'),
|
||||
new \Twig_SimpleFunction('array_current', 'current'),
|
||||
new \Twig_SimpleFunction('array_each', 'each'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'array';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
/**
|
||||
* Class Basic
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class Basic extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* Get declared filters.
|
||||
*
|
||||
* @return \Twig_SimpleFilter[]
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFilter('debug', 'debug'),
|
||||
new \Twig_SimpleFilter('pr', 'pr'),
|
||||
new \Twig_SimpleFilter('low', 'low'),
|
||||
new \Twig_SimpleFilter('up', 'up'),
|
||||
new \Twig_SimpleFilter('count', 'count'),
|
||||
new \Twig_SimpleFilter('h', 'h'),
|
||||
new \Twig_SimpleFilter('null', function () {
|
||||
return '';
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'basic';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
/**
|
||||
* Class I18n
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class I18n extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* Get declared functions.
|
||||
*
|
||||
* @return \Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('__', '__'),
|
||||
new \Twig_SimpleFunction('__d', '__d'),
|
||||
new \Twig_SimpleFunction('__n', '__n'),
|
||||
new \Twig_SimpleFunction('__x', '__x'),
|
||||
new \Twig_SimpleFunction('__dn', '__dn'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'i18n';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
/**
|
||||
* Class Inflector
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class Inflector extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* Get filters for this extension.
|
||||
*
|
||||
* @return \Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFilter('pluralize', 'Cake\Utility\Inflector::pluralize'),
|
||||
new \Twig_SimpleFilter('singularize', 'Cake\Utility\Inflector::singularize'),
|
||||
new \Twig_SimpleFilter('camelize', 'Cake\Utility\Inflector::camelize'),
|
||||
new \Twig_SimpleFilter('underscore', 'Cake\Utility\Inflector::underscore'),
|
||||
new \Twig_SimpleFilter('humanize', 'Cake\Utility\Inflector::humanize'),
|
||||
new \Twig_SimpleFilter('tableize', 'Cake\Utility\Inflector::tableize'),
|
||||
new \Twig_SimpleFilter('classify', 'Cake\Utility\Inflector::classify'),
|
||||
new \Twig_SimpleFilter('variable', 'Cake\Utility\Inflector::variable'),
|
||||
new \Twig_SimpleFilter('dasherize', 'Cake\Utility\Inflector::dasherize'),
|
||||
new \Twig_SimpleFilter('slug', 'Cake\Utility\Text::slug'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'inflector';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
/**
|
||||
* Class Number
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class Number extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* Get declared functions.
|
||||
*
|
||||
* @return \Twig_SimpleFilter[]
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFilter('toReadableSize', 'Cake\I18n\Number::toReadableSize'),
|
||||
new \Twig_SimpleFilter('fromReadableSize', 'Cake\I18n\Number::fromReadableSize'),
|
||||
new \Twig_SimpleFilter('toPercentage', 'Cake\I18n\Number::toPercentage'),
|
||||
new \Twig_SimpleFilter('number_format', 'Cake\I18n\Number::format'),
|
||||
new \Twig_SimpleFilter('formatDelta', 'Cake\I18n\Number::formatDelta'),
|
||||
new \Twig_SimpleFilter('currency', 'Cake\I18n\Number::currency'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get declared functions.
|
||||
*
|
||||
* @return \Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('defaultCurrency', 'Cake\I18n\Number::defaultCurrency'),
|
||||
new \Twig_SimpleFunction('number_formatter', 'Cake\I18n\Number::formatter'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'number';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
/**
|
||||
* Class Basic
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class PotentialDangerous extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* Get declared filters.
|
||||
*
|
||||
* @return \Twig_SimpleFilter[]
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFilter('env', 'env'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get declared functions.
|
||||
*
|
||||
* @return \Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('config', 'Cake\Core\Configure::read'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'potential_dangerous';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
use DebugKit\DebugTimer;
|
||||
|
||||
/**
|
||||
* Class Basic
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class Profiler extends \Twig_Extension_Profiler
|
||||
{
|
||||
/**
|
||||
* Enter $profile.
|
||||
*
|
||||
* @param \Twig_Profiler_Profile $profile Profile.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enter(\Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$name = 'Twig Template: ' . substr($profile->getName(), strlen(ROOT) + 1);
|
||||
DebugTimer::start($name, __d('twig_view', $name));
|
||||
|
||||
parent::enter($profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave $profile.
|
||||
*
|
||||
* @param \Twig_Profiler_Profile $profile Profile.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function leave(\Twig_Profiler_Profile $profile)
|
||||
{
|
||||
parent::leave($profile);
|
||||
|
||||
$name = 'Twig Template: ' . substr($profile->getName(), strlen(ROOT) + 1);
|
||||
DebugTimer::stop($name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
use Cake\Utility\Text;
|
||||
|
||||
/**
|
||||
* Class Strings
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class Strings extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* Get declared filters.
|
||||
*
|
||||
* @return \Twig_SimpleFilter[]
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFilter('substr', 'substr'),
|
||||
new \Twig_SimpleFilter('tokenize', 'Cake\Utility\Text::tokenize'),
|
||||
new \Twig_SimpleFilter('insert', 'Cake\Utility\Text::insert'),
|
||||
new \Twig_SimpleFilter('cleanInsert', 'Cake\Utility\Text::cleanInsert'),
|
||||
new \Twig_SimpleFilter('wrap', 'Cake\Utility\Text::wrap'),
|
||||
new \Twig_SimpleFilter('wrapBlock', 'Cake\Utility\Text::wrapBlock'),
|
||||
new \Twig_SimpleFilter('wordWrap', 'Cake\Utility\Text::wordWrap'),
|
||||
new \Twig_SimpleFilter('highlight', 'Cake\Utility\Text::highlight'),
|
||||
new \Twig_SimpleFilter('tail', 'Cake\Utility\Text::tail'),
|
||||
new \Twig_SimpleFilter('truncate', 'Cake\Utility\Text::truncate'),
|
||||
new \Twig_SimpleFilter('excerpt', 'Cake\Utility\Text::excerpt'),
|
||||
new \Twig_SimpleFilter('toList', 'Cake\Utility\Text::toList'),
|
||||
new \Twig_SimpleFilter('stripLinks', function ($string) {
|
||||
$previousrErrorHandler = set_error_handler(function () {
|
||||
});
|
||||
$strippedString = Text::stripLinks($string);
|
||||
set_error_handler($previousrErrorHandler);
|
||||
return $strippedString;
|
||||
}),
|
||||
new \Twig_SimpleFilter('isMultibyte', 'Cake\Utility\Text::isMultibyte'),
|
||||
new \Twig_SimpleFilter('utf8', 'Cake\Utility\Text::utf8'),
|
||||
new \Twig_SimpleFilter('ascii', 'Cake\Utility\Text::ascii'),
|
||||
new \Twig_SimpleFilter('parseFileSize', 'Cake\Utility\Text::parseFileSize'),
|
||||
new \Twig_SimpleFilter('none', function ($string) {
|
||||
return;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get declared functions.
|
||||
*
|
||||
* @return \Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('uuid', 'Cake\Utility\Text::uuid'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'string';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
/**
|
||||
* Class Time
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class Time extends \Twig_Extension
|
||||
{
|
||||
/**
|
||||
* Get declared functions.
|
||||
*
|
||||
* @return \Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('time', function ($time = null, $timezone = null) {
|
||||
return new \Cake\I18n\Time($time, $timezone);
|
||||
}),
|
||||
new \Twig_SimpleFunction('timezones', 'Cake\I18n\Time::listTimezones'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'time';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
/**
|
||||
* Class Utils
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
class Utils extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* Get declared filters.
|
||||
*
|
||||
* @return \Twig_SimpleFilter[]
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFilter('serialize', 'serialize'),
|
||||
new \Twig_SimpleFilter('unserialize', 'unserialize'),
|
||||
new \Twig_SimpleFilter('md5', 'md5'),
|
||||
new \Twig_SimpleFilter('base64_encode', 'base64_encode'),
|
||||
new \Twig_SimpleFilter('base64_decode', 'base64_decode'),
|
||||
new \Twig_SimpleFilter('nl2br', 'nl2br'),
|
||||
new \Twig_SimpleFilter('string', function ($str) {
|
||||
return (string)$str;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'utils';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Extension;
|
||||
|
||||
use Cake\View\View as CakeView;
|
||||
|
||||
/**
|
||||
* Class View
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Extension
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
class View extends \Twig_Extension
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
/**
|
||||
* View to call methods upon.
|
||||
*
|
||||
* @var CakeView
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param CakeView $view View instance.
|
||||
*/
|
||||
public function __construct(CakeView $view)
|
||||
{
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get declared functions.
|
||||
*
|
||||
* @return \Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('elementExists', function ($name) {
|
||||
return $this->view->elementExists($name);
|
||||
}),
|
||||
new \Twig_SimpleFunction('getVars', function () {
|
||||
return $this->view->getVars();
|
||||
}),
|
||||
new \Twig_SimpleFunction('get', function ($var, $default = null) {
|
||||
return $this->view->get($var, $default);
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'view';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig;
|
||||
|
||||
use Cake\Core\App;
|
||||
use Cake\Core\Plugin;
|
||||
use Twig_Error_Loader;
|
||||
use Twig_Source;
|
||||
use WyriHaximus\TwigView\View\TwigView;
|
||||
|
||||
/**
|
||||
* Class Loader
|
||||
* @package WyriHaximus\TwigView\Lib\Twig
|
||||
*/
|
||||
class Loader implements \Twig_LoaderInterface, \Twig_ExistsLoaderInterface, \Twig_SourceContextLoaderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the file contents of a template.
|
||||
*
|
||||
* @param string $name Template.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSource($name)
|
||||
{
|
||||
$name = $this->resolveFileName($name);
|
||||
return file_get_contents($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for template.
|
||||
*
|
||||
* @param string $name Template.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
return $this->resolveFileName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if template is still fresh.
|
||||
*
|
||||
* @param string $name Template.
|
||||
* @param integer $time Timestamp.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
||||
$name = $this->resolveFileName($name);
|
||||
return filemtime($name) < $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve template name to filename.
|
||||
*
|
||||
* @param string $name Template.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Twig_Error_Loader Thrown when template file isn't found.
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
protected function resolveFileName($name)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
if (file_exists($name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
list($plugin, $file) = pluginSplit($name);
|
||||
foreach ([
|
||||
null,
|
||||
$plugin,
|
||||
] as $scope) {
|
||||
$paths = $this->getPaths($scope);
|
||||
foreach ($paths as $path) {
|
||||
$filePath = $path . $file;
|
||||
if (file_exists($filePath)) {
|
||||
return $filePath;
|
||||
}
|
||||
|
||||
$filePath = $path . $file . TwigView::EXT;
|
||||
if (file_exists($filePath)) {
|
||||
return $filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new \Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if $plugin is active and return it's template paths or return the aps template paths.
|
||||
*
|
||||
* @param string|null $plugin The plugin in question.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getPaths($plugin)
|
||||
{
|
||||
if ($plugin === null || !Plugin::loaded($plugin)) {
|
||||
return App::path('Template');
|
||||
}
|
||||
|
||||
return App::path('Template', $plugin);
|
||||
}
|
||||
|
||||
public function exists($name)
|
||||
{
|
||||
$name = $this->resolveFileName($name);
|
||||
|
||||
return file_exists($name);
|
||||
}
|
||||
|
||||
public function getSourceContext($name)
|
||||
{
|
||||
$path = $this->resolveFileName($name);
|
||||
|
||||
return new Twig_Source(file_get_contents($path), $name, $path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Node;
|
||||
|
||||
/**
|
||||
* Class Cell
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Node
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
class Cell extends \Twig_Node implements \Twig_NodeOutputInterface
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
|
||||
/**
|
||||
* Whether to assign the data or not.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $assign = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param boolean $assign Assign or echo.
|
||||
* @param mixed $variable Variable to assign to.
|
||||
* @param \Twig_Node_Expression $name Name.
|
||||
* @param \Twig_Node_Expression $data Data array.
|
||||
* @param \Twig_Node_Expression $options Options array.
|
||||
* @param string $lineno Line number.
|
||||
* @param string $tag Tag name.
|
||||
*/
|
||||
public function __construct(
|
||||
$assign,
|
||||
$variable,
|
||||
\Twig_Node_Expression $name,
|
||||
\Twig_Node_Expression $data = null,
|
||||
\Twig_Node_Expression $options = null,
|
||||
$lineno = '',
|
||||
$tag = null
|
||||
) {
|
||||
if ($data === null) {
|
||||
$data = new \Twig_Node_Expression_Array([], $lineno);
|
||||
}
|
||||
|
||||
if ($options === null) {
|
||||
$options = new \Twig_Node_Expression_Array([], $lineno);
|
||||
}
|
||||
|
||||
parent::__construct(
|
||||
[
|
||||
'name' => $name,
|
||||
'data' => $data,
|
||||
'options' => $options,
|
||||
],
|
||||
[
|
||||
'variable' => $variable,
|
||||
],
|
||||
$lineno,
|
||||
$tag
|
||||
);
|
||||
|
||||
$this->assign = $assign;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile tag.
|
||||
*
|
||||
* @param \Twig_Compiler $compiler Compiler.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function compile(\Twig_Compiler $compiler)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
$compiler->addDebugInfo($this);
|
||||
|
||||
if ($this->assign) {
|
||||
$compiler->raw('$context[\'' . $this->getAttribute('variable') . '\'] = ');
|
||||
// @codingStandardsIgnoreStart
|
||||
} else {
|
||||
// @codingStandardsIgnoreEnd
|
||||
$compiler->raw('echo ');
|
||||
}
|
||||
$compiler->raw('$context[\'_view\']->cell(');
|
||||
$compiler->subcompile($this->getNode('name'));
|
||||
$data = $this->getNode('data');
|
||||
if ($data !== null) {
|
||||
$compiler->raw(',');
|
||||
$compiler->subcompile($data);
|
||||
}
|
||||
$options = $this->getNode('options');
|
||||
if ($options !== null) {
|
||||
$compiler->raw(',');
|
||||
$compiler->subcompile($options);
|
||||
}
|
||||
$compiler->raw(");\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\Node;
|
||||
|
||||
/**
|
||||
* Class Element
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\Node
|
||||
*/
|
||||
class Element extends \Twig_Node
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Twig_Node_Expression $name Name.
|
||||
* @param \Twig_Node_Expression $data Data.
|
||||
* @param \Twig_Node_Expression $options Options.
|
||||
* @param string $lineno Linenumber.
|
||||
* @param string $tag Tag.
|
||||
*/
|
||||
public function __construct(
|
||||
\Twig_Node_Expression $name,
|
||||
\Twig_Node_Expression $data = null,
|
||||
\Twig_Node_Expression $options = null,
|
||||
$lineno = '',
|
||||
$tag = null
|
||||
) {
|
||||
if ($data === null) {
|
||||
$data = new \Twig_Node_Expression_Array([], $lineno);
|
||||
}
|
||||
|
||||
if ($options === null) {
|
||||
$options = new \Twig_Node_Expression_Array([], $lineno);
|
||||
}
|
||||
|
||||
parent::__construct(
|
||||
[
|
||||
'name' => $name,
|
||||
'data' => $data,
|
||||
'options' => $options,
|
||||
],
|
||||
[],
|
||||
$lineno,
|
||||
$tag
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile node.
|
||||
*
|
||||
* @param \Twig_Compiler $compiler Compiler.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function compile(\Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->addDebugInfo($this);
|
||||
|
||||
$compiler->raw('echo $context[\'_view\']->element(');
|
||||
$compiler->subcompile($this->getNode('name'));
|
||||
$data = $this->getNode('data');
|
||||
if ($data !== null) {
|
||||
$compiler->raw(',');
|
||||
$compiler->subcompile($data);
|
||||
}
|
||||
$options = $this->getNode('options');
|
||||
if ($options !== null) {
|
||||
$compiler->raw(',');
|
||||
$compiler->subcompile($options);
|
||||
}
|
||||
$compiler->raw(");\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\TokenParser;
|
||||
|
||||
use Twig_Token;
|
||||
use WyriHaximus\TwigView\Lib\Twig\Node\Cell as CellNode;
|
||||
|
||||
/**
|
||||
* Class Element
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\TokenParser
|
||||
*/
|
||||
class Cell extends \Twig_TokenParser_Include
|
||||
{
|
||||
/**
|
||||
* Parse token.
|
||||
*
|
||||
* @param Twig_Token $token Token.
|
||||
*
|
||||
* @return CellNode
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function parse(Twig_Token $token)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
$stream = $this->parser->getStream();
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
$variable = null;
|
||||
if ($stream->test(Twig_Token::NAME_TYPE)) {
|
||||
$variable = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
||||
}
|
||||
$assign = false;
|
||||
if ($stream->test(Twig_Token::OPERATOR_TYPE)) {
|
||||
$stream->expect(Twig_Token::OPERATOR_TYPE, '=');
|
||||
$assign = true;
|
||||
}
|
||||
|
||||
$name = $this->parser->getExpressionParser()->parseExpression();
|
||||
$data = null;
|
||||
if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) {
|
||||
$data = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
$options = null;
|
||||
if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) {
|
||||
$options = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
||||
|
||||
return new CellNode($assign, $variable, $name, $data, $options, $token->getLine(), $this->getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTag()
|
||||
{
|
||||
return 'cell';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Lib\Twig\TokenParser;
|
||||
|
||||
use WyriHaximus\TwigView\Lib\Twig\Node\Element as ElementNode;
|
||||
|
||||
/**
|
||||
* Class Element
|
||||
* @package WyriHaximus\TwigView\Lib\Twig\TokenParser
|
||||
*/
|
||||
class Element extends \Twig_TokenParser_Include
|
||||
{
|
||||
|
||||
/**
|
||||
* Parse token.
|
||||
*
|
||||
* @param \Twig_Token $token Token.
|
||||
*
|
||||
* @return \Twig_NodeInterface|ElementNode
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function parse(\Twig_Token $token)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
// @codingStandardsIgnoreStart
|
||||
$stream = $this->parser->getStream();
|
||||
$name = $this->parser->getExpressionParser()->parseExpression();
|
||||
|
||||
$data = null;
|
||||
if (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
|
||||
$data = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
|
||||
$options = null;
|
||||
if (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
|
||||
$options = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
|
||||
|
||||
return new ElementNode($name, $data, $options, $token->getLine(), $this->getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tag name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTag()
|
||||
{
|
||||
return 'element';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace WyriHaximus\TwigView\Panel;
|
||||
|
||||
use DebugKit\DebugPanel;
|
||||
use WyriHaximus\TwigView\Lib\TreeScanner;
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
class TwigPanel extends DebugPanel
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
/**
|
||||
* Plugin name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public $plugin = 'WyriHaximus/TwigView';
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
/**
|
||||
* Get the data for the twig panel.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data()
|
||||
{
|
||||
return [
|
||||
'templates' => TreeScanner::all(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Shell;
|
||||
|
||||
use Cake\Console\ConsoleIo;
|
||||
use Cake\Console\Shell;
|
||||
use Cake\Core\Plugin;
|
||||
use WyriHaximus\TwigView\Lib\Scanner;
|
||||
use WyriHaximus\TwigView\View\TwigView;
|
||||
|
||||
/**
|
||||
* Class CompileTemplatesShell
|
||||
* @package WyriHaximus\TwigView\Console\Command
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
class CompileShell extends Shell
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance of TwigView to be used to compile templates.
|
||||
*
|
||||
* @var TwigView
|
||||
*/
|
||||
protected $twigView;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ConsoleIo $consoleIo An IO instance.
|
||||
*/
|
||||
public function __construct(ConsoleIo $consoleIo = null)
|
||||
{
|
||||
parent::__construct($consoleIo);
|
||||
|
||||
$this->twigView = new TwigView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TwigView.
|
||||
*
|
||||
* @param TwigView $twigView TwigView instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setTwigview(TwigView $twigView)
|
||||
{
|
||||
$this->twigView = $twigView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile all templates.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function all()
|
||||
{
|
||||
$this->out('<info>Compiling all templates</info>');
|
||||
|
||||
foreach(Scanner::all() as $section => $templates) {
|
||||
$this->out('<info>Compiling ' . $section . '\'s templates</info>');
|
||||
$this->walkIterator($templates);
|
||||
}
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
/**
|
||||
* Compile only this plugin.
|
||||
*
|
||||
* @param string $plugin Plugin name.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function plugin($plugin)
|
||||
{
|
||||
$this->out('<info>Compiling one ' . $plugin . '\'s templates</info>');
|
||||
$this->walkIterator(Scanner::plugin($plugin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Only compile one file.
|
||||
*
|
||||
* @param string $fileName File to compile.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function file($fileName)
|
||||
{
|
||||
$this->out('<info>Compiling one template</info>');
|
||||
$this->compileTemplate($fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk over $iterator and compile all templates in it.
|
||||
*
|
||||
* @param mixed $iterator Iterator to walk over.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function walkIterator($iterator)
|
||||
{
|
||||
foreach ($iterator as $template) {
|
||||
$this->compileTemplate($template);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a template.
|
||||
*
|
||||
* @param string $fileName Template to compile.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function compileTemplate($fileName)
|
||||
{
|
||||
try {
|
||||
$this->
|
||||
twigView->
|
||||
getTwig()->
|
||||
loadTemplate($fileName);
|
||||
$this->out('<success>' . $fileName . '</success>');
|
||||
} catch (\Exception $exception) {
|
||||
$this->out('<error>' . $fileName . '</error>');
|
||||
$this->out('<error>' . $exception->getMessage() . '</error>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options for this console.
|
||||
*
|
||||
* @return \Cake\Console\ConsoleOptionParser
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
public function getOptionParser()
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
return parent::getOptionParser()->addSubcommand(
|
||||
'all',
|
||||
[
|
||||
'short' => 'a',
|
||||
// @codingStandardsIgnoreStart
|
||||
'help' => __('Searches and precompiles all twig templates it finds.')
|
||||
// @codingStandardsIgnoreEnd
|
||||
]
|
||||
)->addSubcommand(
|
||||
'plugin',
|
||||
[
|
||||
'short' => 'p',
|
||||
// @codingStandardsIgnoreStart
|
||||
'help' => __('Searches and precompiles all twig templates for a specific plugin.')
|
||||
// @codingStandardsIgnoreEnd
|
||||
]
|
||||
)->addSubcommand(
|
||||
'file',
|
||||
[
|
||||
'short' => 'f',
|
||||
// @codingStandardsIgnoreStart
|
||||
'help' => __('Precompile a specific file.')
|
||||
// @codingStandardsIgnoreEnd
|
||||
]
|
||||
// @codingStandardsIgnoreStart
|
||||
)->setDescription(__('TwigView templates precompiler'));
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\Shell\Task;
|
||||
|
||||
use Bake\Shell\Task\TemplateTask;
|
||||
use Cake\Console\Shell;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Utility\Inflector;
|
||||
|
||||
/**
|
||||
* Task class for creating and updating twig view template files.
|
||||
*
|
||||
*/
|
||||
class TwigTemplateTask extends TemplateTask
|
||||
{
|
||||
|
||||
public function name()
|
||||
{
|
||||
return 'twig_template';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles and writes bakes the twig view file.
|
||||
*
|
||||
* @param string $template Template to generate content with.
|
||||
* @param string $content Content to write.
|
||||
* @param string $outputFile The destination action name. If null, will fallback to $template.
|
||||
* @return string Generated file content.
|
||||
*/
|
||||
public function bake($template, $content = '', $outputFile = null)
|
||||
{
|
||||
if ($outputFile === null) {
|
||||
$outputFile = $template;
|
||||
}
|
||||
if ($content === true) {
|
||||
$content = $this->getContent($template);
|
||||
}
|
||||
if (empty($content)) {
|
||||
$this->err("<warning>No generated content for '{$template}.ctp', not generating template.</warning>");
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->out("\n" . sprintf('Baking `%s` view twig template file...', $outputFile), 1, Shell::QUIET);
|
||||
$path = $this->getPath();
|
||||
$filename = $path . Inflector::underscore($outputFile) . '.twig';
|
||||
$this->createFile($filename, $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<%
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
use Cake\Utility\Inflector;
|
||||
|
||||
$fields = collection($fields)
|
||||
->filter(function($field) use ($schema) {
|
||||
return $schema->getColumnType($field) !== 'binary';
|
||||
});
|
||||
|
||||
if (isset($modelObject) && $modelObject->behaviors()->has('Tree')) {
|
||||
$fields = $fields->reject(function ($field) {
|
||||
return $field === 'lft' || $field === 'rght';
|
||||
});
|
||||
}
|
||||
%>
|
||||
<nav class="large-3 medium-4 columns" id="actions-sidebar">
|
||||
<ul class="side-nav">
|
||||
<li class="heading">{{ __('Actions') }}</li>
|
||||
<% if (strpos($action, 'add') === false): %>
|
||||
<li>{{ Form.postLink(
|
||||
__('Delete'),
|
||||
{'action' : 'delete', 0 : <%= $singularVar %>.<%= $primaryKey[0] %>},
|
||||
{'confirm' : __('Are you sure you want to delete # {0}?', <%= $singularVar %>.<%= $primaryKey[0] %>)}
|
||||
)|raw
|
||||
}}
|
||||
</li>
|
||||
<% endif; %>
|
||||
<li>{{ Html.link(__('List <%= $pluralHumanName %>'), {'action' : 'index'})|raw }}</li>
|
||||
<%
|
||||
$done = [];
|
||||
foreach ($associations as $type => $data) {
|
||||
foreach ($data as $alias => $details) {
|
||||
if ($details['controller'] !== $this->name && !in_array($details['controller'], $done)) {
|
||||
%>
|
||||
<li>{{ Html.link(__('List <%= $this->_pluralHumanName($alias) %>'), {'controller' : '<%= $details['controller'] %>', 'action' : 'index'})|raw }}</li>
|
||||
<li>{{ Html.link(__('New <%= $this->_singularHumanName($alias) %>'), {'controller' : '<%= $details['controller'] %>', 'action' : 'add'})|raw }}</li>
|
||||
<%
|
||||
$done[] = $details['controller'];
|
||||
}
|
||||
}
|
||||
}
|
||||
%>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="<%= $pluralVar %> form large-9 medium-8 columns content">
|
||||
{{ Form.create(<%= $singularVar %>)|raw }}
|
||||
<fieldset>
|
||||
<legend>{{ __('<%= Inflector::humanize($action) %> <%= $singularHumanName %>') }}</legend>
|
||||
<%
|
||||
foreach ($fields as $field) {
|
||||
if (in_array($field, $primaryKey)) {
|
||||
continue;
|
||||
}
|
||||
if (isset($keyFields[$field])) {
|
||||
$fieldData = $schema->getColumn($field);
|
||||
if (!empty($fieldData['null'])) {
|
||||
%>
|
||||
{{ Form.input('<%= $field %>', {'options' : <%= $keyFields[$field] %>, 'empty' : true})|raw }}
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
{{ Form.input('<%= $field %>', {'options' : <%= $keyFields[$field] %>})|raw }}
|
||||
<%
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!in_array($field, ['created', 'modified', 'updated'])) {
|
||||
$fieldData = $schema->getColumn($field);
|
||||
if (in_array($fieldData['type'], ['date', 'datetime', 'time']) && (!empty($fieldData['null']))) {
|
||||
%>
|
||||
{{ Form.input('<%= $field %>', {'empty' : true})|raw }}
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
{{ Form.input('<%= $field %>')|raw }}
|
||||
<%
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($associations['BelongsToMany'])) {
|
||||
foreach ($associations['BelongsToMany'] as $assocName => $assocData) {
|
||||
%>
|
||||
{{ Form.input('<%= $assocData['property'] %>._ids', {'options' : <%= $assocData['variable'] %>})|raw }}
|
||||
<%
|
||||
}
|
||||
}
|
||||
%>
|
||||
</fieldset>
|
||||
{{ Form.button(__('Submit'))|raw }}
|
||||
{{ Form.end()|raw }}
|
||||
</div>
|
||||
@@ -0,0 +1,11 @@
|
||||
<%
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
echo $this->element('form');
|
||||
@@ -0,0 +1,11 @@
|
||||
<%
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
echo $this->element('form');
|
||||
@@ -0,0 +1,107 @@
|
||||
<%
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
use Cake\Utility\Inflector;
|
||||
|
||||
$fields = collection($fields)
|
||||
->filter(function($field) use ($schema) {
|
||||
return !in_array($schema->getColumnType($field), ['binary', 'text']);
|
||||
});
|
||||
|
||||
if (isset($modelObject) && $modelObject->behaviors()->has('Tree')) {
|
||||
$fields = $fields->reject(function ($field) {
|
||||
return $field === 'lft' || $field === 'rght';
|
||||
});
|
||||
}
|
||||
|
||||
if (!empty($indexColumns)) {
|
||||
$fields = $fields->take($indexColumns);
|
||||
}
|
||||
|
||||
%>
|
||||
<nav class="large-3 medium-4 columns" id="actions-sidebar">
|
||||
<ul class="side-nav">
|
||||
<li class="heading">{{ __('Actions') }}</li>
|
||||
<li>{{ Html.link(__('New <%= $singularHumanName %>'), {'action' : 'add'})|raw }}</li>
|
||||
<%
|
||||
$done = [];
|
||||
foreach ($associations as $type => $data):
|
||||
foreach ($data as $alias => $details):
|
||||
if (!empty($details['navLink']) && $details['controller'] !== $this->name && !in_array($details['controller'], $done)):
|
||||
%>
|
||||
<li>{{ Html.link(__('List <%= $this->_pluralHumanName($alias) %>'), {'controller' : '<%= $details['controller'] %>', 'action' : 'index'})|raw }}</li>
|
||||
<li>{{ Html.link(__('New <%= $this->_singularHumanName($alias) %>'), {'controller' : '<%= $details['controller'] %>', 'action' : 'add'})|raw }}</li>
|
||||
<%
|
||||
$done[] = $details['controller'];
|
||||
endif;
|
||||
endforeach;
|
||||
endforeach;
|
||||
%>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="<%= $pluralVar %> index large-9 medium-8 columns content">
|
||||
<h3>{{ __('<%= $pluralHumanName %>') }}</h3>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<% foreach ($fields as $field): %>
|
||||
<th>{{ Paginator.sort('<%= $field %>')|raw }}</th>
|
||||
<% endforeach; %>
|
||||
<th class="actions">{{ __('Actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for <%= $singularVar %> in <%= $pluralVar %> %}
|
||||
<tr>
|
||||
<% foreach ($fields as $field) {
|
||||
$isKey = false;
|
||||
if (!empty($associations['BelongsTo'])) {
|
||||
foreach ($associations['BelongsTo'] as $alias => $details) {
|
||||
if ($field === $details['foreignKey']) {
|
||||
$isKey = true;
|
||||
%>
|
||||
<td>{{ <%= $singularVar %>.has('<%= $details['property'] %>') ? Html.link(<%= $singularVar %>.<%= $details['property'] %>.<%= $details['displayField'] %>, {'controller' : '<%= $details['controller'] %>', 'action' : 'view', 0 : <%= $singularVar %>.<%= $details['property'] %>.<%= $details['primaryKey'][0] %>})|raw : '' }}</td>
|
||||
<%
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($isKey !== true) {
|
||||
if (!in_array($schema->getColumnType($field), ['integer', 'biginteger', 'decimal', 'float'])) {
|
||||
%>
|
||||
<td>{{ <%= $singularVar %>.<%= $field %>|h }}</td>
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
<td>{{ Number.format(<%= $singularVar %>.<%= $field %>) }}</td>
|
||||
<%
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$pk = $singularVar . '.' . $primaryKey[0];
|
||||
%>
|
||||
<td class="actions">
|
||||
{{ Html.link(__('View'), {'action' : 'view', 0 : <%= $pk %>})|raw }}
|
||||
{{ Html.link(__('Edit'), {'action' : 'edit', 0 : <%= $pk %>})|raw }}
|
||||
{{ Form.postLink(__('Delete'), {'action' : 'delete', 0 : <%= $pk %>}, {'confirm' : __('Are you sure you want to delete # {0}?', <%= $pk %>)})|raw }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="paginator">
|
||||
<ul class="pagination">
|
||||
{{ Paginator.prev('< ' ~ __('previous'))|raw }}
|
||||
{{ Paginator.numbers()|raw }}
|
||||
{{ Paginator.next(__('next') ~ ' >')|raw }}
|
||||
</ul>
|
||||
<p>{{ Paginator.counter()|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,166 @@
|
||||
<%
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2015 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
use Cake\Utility\Inflector;
|
||||
|
||||
$associations += ['BelongsTo' => [], 'HasOne' => [], 'HasMany' => [], 'BelongsToMany' => []];
|
||||
$immediateAssociations = $associations['BelongsTo'];
|
||||
$associationFields = collection($fields)
|
||||
->map(function($field) use ($immediateAssociations) {
|
||||
foreach ($immediateAssociations as $alias => $details) {
|
||||
if ($field === $details['foreignKey']) {
|
||||
return [$field => $details];
|
||||
}
|
||||
}
|
||||
})
|
||||
->filter()
|
||||
->reduce(function($fields, $value) {
|
||||
return $fields + $value;
|
||||
}, []);
|
||||
|
||||
$groupedFields = collection($fields)
|
||||
->filter(function($field) use ($schema) {
|
||||
return $schema->getColumnType($field) !== 'binary';
|
||||
})
|
||||
->groupBy(function($field) use ($schema, $associationFields) {
|
||||
$type = $schema->getColumnType($field);
|
||||
if (isset($associationFields[$field])) {
|
||||
return 'string';
|
||||
}
|
||||
if (in_array($type, ['integer', 'float', 'decimal', 'biginteger'])) {
|
||||
return 'number';
|
||||
}
|
||||
if (in_array($type, ['date', 'time', 'datetime', 'timestamp'])) {
|
||||
return 'date';
|
||||
}
|
||||
return in_array($type, ['text', 'boolean']) ? $type : 'string';
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$groupedFields += ['number' => [], 'string' => [], 'boolean' => [], 'date' => [], 'text' => []];
|
||||
$pk = "$singularVar.{$primaryKey[0]}";
|
||||
%>
|
||||
<nav class="large-3 medium-4 columns" id="actions-sidebar">
|
||||
<ul class="side-nav">
|
||||
<li class="heading">{{ __('Actions') }}</li>
|
||||
<li>{{ Html.link(__('Edit <%= $singularHumanName %>'), {'action' : 'edit', 0 : <%= $pk %>})|raw }}</li>
|
||||
<li>{{ Form.postLink(__('Delete <%= $singularHumanName %>'), {'action' : 'delete', 0 : <%= $pk %>}, {'confirm' : __('Are you sure you want to delete # {0}?', <%= $pk %>)})|raw }}</li>
|
||||
<li>{{ Html.link(__('List <%= $pluralHumanName %>'), {'action' : 'index'})|raw }}</li>
|
||||
<li>{{ Html.link(__('New <%= $singularHumanName %>'), {'action' : 'add'})|raw }}</li>
|
||||
<%
|
||||
$done = [];
|
||||
foreach ($associations as $type => $data) {
|
||||
foreach ($data as $alias => $details) {
|
||||
if ($details['controller'] !== $this->name && !in_array($details['controller'], $done)) {
|
||||
%>
|
||||
<li>{{ Html.link(__('List <%= $this->_pluralHumanName($alias) %>'), {'controller' : '<%= $details['controller'] %>', 'action' : 'index'})|raw }}</li>
|
||||
<li>{{ Html.link(__('New <%= Inflector::humanize(Inflector::singularize(Inflector::underscore($alias))) %>'), {'controller' : '<%= $details['controller'] %>', 'action' : 'add'})|raw }}</li>
|
||||
<%
|
||||
$done[] = $details['controller'];
|
||||
}
|
||||
}
|
||||
}
|
||||
%>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="<%= $pluralVar %> view large-9 medium-8 columns content">
|
||||
<h3>{{ <%= $singularVar %>.<%= $displayField %>|h }}</h3>
|
||||
<table class="vertical-table">
|
||||
<% if ($groupedFields['string']) : %>
|
||||
<% foreach ($groupedFields['string'] as $field) : %>
|
||||
<% if (isset($associationFields[$field])) :
|
||||
$details = $associationFields[$field];
|
||||
%>
|
||||
<tr>
|
||||
<th>{{ __('<%= Inflector::humanize($details['property']) %>') }}</th>
|
||||
<td>{{ <%= $singularVar %>.has('<%= $details['property'] %>') ? Html.link(<%= $singularVar %>.<%= $details['property'] %>.<%= $details['displayField'] %>, {'controller' : '<%= $details['controller'] %>', 'action' : 'view', 0 : <%= $singularVar %>.<%= $details['property'] %>.<%= $details['primaryKey'][0] %>})|raw : '' }}</td>
|
||||
</tr>
|
||||
<% else : %>
|
||||
<tr>
|
||||
<th>{{ __('<%= Inflector::humanize($field) %>') }}</th>
|
||||
<td>{{ <%= $singularVar %>.<%= $field %>|h }}</td>
|
||||
</tr>
|
||||
<% endif; %>
|
||||
<% endforeach; %>
|
||||
<% endif; %>
|
||||
<% if ($associations['HasOne']) : %>
|
||||
<%- foreach ($associations['HasOne'] as $alias => $details) : %>
|
||||
<tr>
|
||||
<th>{{ __('<%= Inflector::humanize(Inflector::singularize(Inflector::underscore($alias))) %>') }}</th>
|
||||
<td>{{ <%= $singularVar %>.has('<%= $details['property'] %>') ? Html.link(<%= $singularVar %>.<%= $details['property'] %>.<%= $details['displayField'] %>, {'controller' : '<%= $details['controller'] %>', 'action' : 'view', 0 : <%= $singularVar %>.<%= $details['property'] %>.<%= $details['primaryKey'][0] %>})|raw : '' }}</td>
|
||||
</tr>
|
||||
<%- endforeach; %>
|
||||
<% endif; %>
|
||||
<% if ($groupedFields['number']) : %>
|
||||
<% foreach ($groupedFields['number'] as $field) : %>
|
||||
<tr>
|
||||
<th>{{ __('<%= Inflector::humanize($field) %>') }}</th>
|
||||
<td>{{ Number.format(<%= $singularVar %>.<%= $field %>) }}</td>
|
||||
</tr>
|
||||
<% endforeach; %>
|
||||
<% endif; %>
|
||||
<% if ($groupedFields['date']) : %>
|
||||
<% foreach ($groupedFields['date'] as $field) : %>
|
||||
<tr>
|
||||
<th>{{ __('<%= Inflector::humanize($field) %>') }}</th>
|
||||
<td>{{ <%= $singularVar %>.<%= $field %>|h }}</td>
|
||||
</tr>
|
||||
<% endforeach; %>
|
||||
<% endif; %>
|
||||
<% if ($groupedFields['boolean']) : %>
|
||||
<% foreach ($groupedFields['boolean'] as $field) : %>
|
||||
<tr>
|
||||
<th>{{ __('<%= Inflector::humanize($field) %>') }}</th>
|
||||
<td>{{ <%= $singularVar %>.<%= $field %> ? __('Yes') : __('No'); }}</td>
|
||||
</tr>
|
||||
<% endforeach; %>
|
||||
<% endif; %>
|
||||
</table>
|
||||
<% if ($groupedFields['text']) : %>
|
||||
<% foreach ($groupedFields['text'] as $field) : %>
|
||||
<div class="row">
|
||||
<h4>{{ __('<%= Inflector::humanize($field) %>') }}</h4>
|
||||
{{ Text.autoParagraph(<%= $singularVar %>.<%= $field %>|h)|raw }}
|
||||
</div>
|
||||
<% endforeach; %>
|
||||
<% endif; %>
|
||||
<%
|
||||
$relations = $associations['HasMany'] + $associations['BelongsToMany'];
|
||||
foreach ($relations as $alias => $details):
|
||||
$otherSingularVar = Inflector::variable($alias);
|
||||
$otherPluralHumanName = Inflector::humanize(Inflector::underscore($details['controller']));
|
||||
%>
|
||||
<div class="related">
|
||||
<h4>{{ __('Related <%= $otherPluralHumanName %>') }}</h4>
|
||||
{% if (<%= $singularVar %>.<%= $details['property'] %> is not empty): %}
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<% foreach ($details['fields'] as $field): %>
|
||||
<th>{{ __('<%= Inflector::humanize($field) %>') }}</th>
|
||||
<% endforeach; %>
|
||||
<th class="actions">{{ __('Actions') }}</th>
|
||||
</tr>
|
||||
{% for (<%= $otherSingularVar %> in <%= $singularVar %>.<%= $details['property'] %>): %}
|
||||
<tr>
|
||||
<%- foreach ($details['fields'] as $field): %>
|
||||
<td>{{ <%= $otherSingularVar %>.<%= $field %>|h }}</td>
|
||||
<%- endforeach; %>
|
||||
<%- $otherPk = "{$otherSingularVar}.{$details['primaryKey'][0]}"; %>
|
||||
<td class="actions">
|
||||
{{ Html.link(__('View'), {'controller' : '<%= $details['controller'] %>', 'action' : 'view', 0 : <%= $otherPk %>})|raw }}
|
||||
{{ Html.link(__('Edit'), {'controller' : '<%= $details['controller'] %>', 'action' : 'edit', 0 : <%= $otherPk %>})|raw }}
|
||||
{{ Form.postLink(__('Delete'), {'controller' : '<%= $details['controller'] %>', 'action' : 'delete', 0 : <%= $otherPk %>], {'confirm' : __('Are you sure you want to delete # {0}?', <%= $otherPk %>)})|raw }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
<% endforeach; %>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
<h4>Templates</h4>
|
||||
<?= $this->Toolbar->makeNeatArray($templates) ?>
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of TwigView.
|
||||
*
|
||||
** (c) 2014 Cees-Jan Kiewiet
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace WyriHaximus\TwigView\View;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\View\Exception\MissingLayoutException;
|
||||
use Cake\View\Exception\MissingTemplateException;
|
||||
use Cake\View\View;
|
||||
use Exception;
|
||||
use WyriHaximus\TwigView\Event\ConstructEvent;
|
||||
use WyriHaximus\TwigView\Event\EnvironmentConfigEvent;
|
||||
use WyriHaximus\TwigView\Event\LoaderEvent;
|
||||
use WyriHaximus\TwigView\Lib\Twig\Loader;
|
||||
|
||||
/**
|
||||
* Class TwigView
|
||||
* @package WyriHaximus\TwigView\View
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
class TwigView extends View
|
||||
// @codingStandardsIgnoreEnd
|
||||
{
|
||||
const EXT = '.twig';
|
||||
|
||||
const ENV_CONFIG = 'WyriHaximus.TwigView.environment';
|
||||
|
||||
/**
|
||||
* Extension to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
protected $_ext = self::EXT;
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = [
|
||||
self::EXT,
|
||||
'.tpl',
|
||||
'.ctp',
|
||||
];
|
||||
|
||||
/**
|
||||
* Twig instance.
|
||||
*
|
||||
* @var \Twig_Environment
|
||||
*/
|
||||
protected $twig;
|
||||
|
||||
/**
|
||||
* Initialize view.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
$this->twig = new \Twig_Environment($this->getLoader(), $this->resolveConfig());
|
||||
|
||||
$this->getEventManager()->dispatch(ConstructEvent::create($this, $this->twig));
|
||||
|
||||
$this->_ext = self::EXT;
|
||||
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function resolveConfig()
|
||||
{
|
||||
$config = [
|
||||
'cache' => CACHE . 'twigView' . DS,
|
||||
'charset' => strtolower(Configure::readOrFail('App.encoding')),
|
||||
'auto_reload' => Configure::read('debug'),
|
||||
'debug' => Configure::read('debug'),
|
||||
];
|
||||
|
||||
$config = array_replace($config, $this->readConfig());
|
||||
|
||||
$configEvent = EnvironmentConfigEvent::create($config);
|
||||
$this->getEventManager()->dispatch($configEvent);
|
||||
return $configEvent->getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function readConfig()
|
||||
{
|
||||
if (!Configure::check(static::ENV_CONFIG)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$config = Configure::read(static::ENV_CONFIG);
|
||||
if (!is_array($config)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $extension
|
||||
*/
|
||||
public function unshiftExtension($extension)
|
||||
{
|
||||
array_unshift($this->extensions, $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the template loader.
|
||||
*
|
||||
* @return \Twig_LoaderInterface
|
||||
*/
|
||||
protected function getLoader()
|
||||
{
|
||||
$event = LoaderEvent::create(new Loader());
|
||||
$this->getEventManager()->dispatch($event);
|
||||
return $event->getResultLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get helper list.
|
||||
*
|
||||
* @return \Cake\View\Helper[]
|
||||
*/
|
||||
protected function generateHelperList()
|
||||
{
|
||||
$registry = $this->helpers();
|
||||
$helperList = [];
|
||||
|
||||
foreach ($registry->loaded() as $alias) {
|
||||
$helperList[$alias] = $registry->get($alias);
|
||||
}
|
||||
|
||||
return $helperList;
|
||||
}
|
||||
/**
|
||||
* Render the template.
|
||||
*
|
||||
* @param string $viewFile Template file.
|
||||
* @param array $data Data that can be used by the template.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return string
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
protected function _render($viewFile, $data = array())
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
if (empty($data)) {
|
||||
$data = $this->viewVars;
|
||||
}
|
||||
|
||||
if (substr($viewFile, -3) === 'ctp') {
|
||||
$out = parent::_render($viewFile, $data);
|
||||
// @codingStandardsIgnoreStart
|
||||
} else {
|
||||
// @codingStandardsIgnoreEnd
|
||||
$data = array_merge(
|
||||
$data,
|
||||
$this->generateHelperList(),
|
||||
[
|
||||
'_view' => $this,
|
||||
]
|
||||
);
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
try {
|
||||
$out = $this->getTwig()->loadTemplate($viewFile)->render($data);
|
||||
} catch (Exception $e) {
|
||||
$previous = $e->getPrevious();
|
||||
|
||||
if ($previous !== null && $previous instanceof Exception) {
|
||||
throw $previous;
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
protected function _getViewFileName($name = null)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
$templatePath = $subDir = '';
|
||||
|
||||
if ($this->subDir !== null) {
|
||||
$subDir = $this->subDir . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
if ($this->templatePath) {
|
||||
$templatePath = $this->templatePath . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
if ($name === null) {
|
||||
$name = $this->template;
|
||||
}
|
||||
|
||||
list($plugin, $name) = $this->pluginSplit($name);
|
||||
$name = str_replace('/', DIRECTORY_SEPARATOR, $name);
|
||||
|
||||
if (strpos($name, DIRECTORY_SEPARATOR) === false && $name[0] !== '.') {
|
||||
$name = $templatePath . $subDir . $this->_inflectViewFileName($name);
|
||||
} elseif (strpos($name, DIRECTORY_SEPARATOR) !== false) {
|
||||
if ($name[0] === DIRECTORY_SEPARATOR || $name[1] === ':') {
|
||||
$name = trim($name, DIRECTORY_SEPARATOR);
|
||||
} elseif (!$plugin || $this->templatePath !== $this->name) {
|
||||
$name = $templatePath . $subDir . $name;
|
||||
} else {
|
||||
$name = DIRECTORY_SEPARATOR . $subDir . $name;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->_paths($plugin) as $path) {
|
||||
foreach ($this->extensions as $extension) {
|
||||
if (file_exists($path . $name . $extension)) {
|
||||
return $this->_checkFilePath($path . $name . $extension, $path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new MissingTemplateException(['file' => $name . $this->_ext]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
protected function _getLayoutFileName($name = null)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
if ($name === null) {
|
||||
$name = $this->layout;
|
||||
}
|
||||
$subDir = null;
|
||||
|
||||
if ($this->layoutPath) {
|
||||
$subDir = $this->layoutPath . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
list($plugin, $name) = $this->pluginSplit($name);
|
||||
|
||||
$layoutPaths = $this->_getSubPaths('Layout' . DIRECTORY_SEPARATOR . $subDir);
|
||||
|
||||
foreach ($this->_paths($plugin) as $path) {
|
||||
foreach ($layoutPaths as $layoutPath) {
|
||||
$currentPath = $path . $layoutPath;
|
||||
foreach ($this->extensions as $extension) {
|
||||
if (file_exists($currentPath . $name . $extension)) {
|
||||
return $this->_checkFilePath($currentPath . $name . $extension, $currentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new MissingLayoutException([
|
||||
'file' => $layoutPaths[0] . $name . $this->_ext
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param bool $pluginCheck
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
protected function _getElementFileName($name, $pluginCheck = true)
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
list($plugin, $name) = $this->pluginSplit($name, $pluginCheck);
|
||||
|
||||
$paths = $this->_paths($plugin);
|
||||
$elementPaths = $this->_getSubPaths('Element');
|
||||
|
||||
foreach ($paths as $path) {
|
||||
foreach ($elementPaths as $elementPath) {
|
||||
foreach ($this->extensions as $extension) {
|
||||
if (file_exists($path . $elementPath . DIRECTORY_SEPARATOR . $name . $extension)) {
|
||||
return $path . $elementPath . DIRECTORY_SEPARATOR . $name . $extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get twig environment instance.
|
||||
*
|
||||
* @return \Twig_Environment
|
||||
*/
|
||||
public function getTwig()
|
||||
{
|
||||
return $this->twig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return empty string when View instance is cast to string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user