mirror of
https://github.com/klaussilveira/gitlist.git
synced 2025-11-18 03:30:55 +01:00
Initial commit
This commit is contained in:
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
cache/
|
||||||
|
*.diff
|
||||||
|
*.err
|
||||||
|
*.orig
|
||||||
|
*.log
|
||||||
|
*.rej
|
||||||
|
*.swo
|
||||||
|
*.swp
|
||||||
|
*.zip
|
||||||
|
*.vi
|
||||||
|
*~
|
||||||
|
*.sass-cache
|
||||||
|
.DS_Store
|
||||||
|
._*
|
||||||
|
Thumbs.db
|
||||||
|
.cache
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.tmproj
|
||||||
|
*.esproj
|
||||||
|
nbproject
|
||||||
|
*.sublime-project
|
||||||
|
*.sublime-workspace
|
||||||
|
.hg
|
||||||
|
.svn
|
||||||
|
.CVS
|
||||||
|
.idea
|
||||||
|
node_modules
|
||||||
7
.htaccess
Normal file
7
.htaccess
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
Options -MultiViews
|
||||||
|
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteRule ^ index.php [L]
|
||||||
|
</IfModule>
|
||||||
5
.travis.yml
Normal file
5
.travis.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
language: php
|
||||||
|
php:
|
||||||
|
- 5.3
|
||||||
|
- 5.4
|
||||||
|
script: phpunit
|
||||||
9
LICENSE.txt
Normal file
9
LICENSE.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Copyright (c) 2012, Klaus Silveira and contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
Neither the name of GitList nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
53
README.md
Normal file
53
README.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# GitList: an elegant and modern git repository viewer
|
||||||
|
[](http://travis-ci.org/klaussilveira/GitList)
|
||||||
|
|
||||||
|
GitList is an elegant and modern web interface for interacting with multiple git repositories. It allows you to browse repositories using your favorite browser, viewing files under different revisions, commit history, diffs. It also generates RSS feeds for each repository, allowing you to stay up-to-date with the latest changes anytime, anywhere. GitList was written in PHP, on top of the [Silex](http://silex.sensiolabs.org/) microframework and powered by the Twig template engine. This means that GitList is easy to install and easy to customize. Also, the GitList gorgeous interface was made possible due to [Bootstrap](http://twitter.github.com/bootstrap/).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
* Multiple repository support
|
||||||
|
* Multiple branch support
|
||||||
|
* Multiple tag support
|
||||||
|
* Commit history, blame, diff
|
||||||
|
* RSS feeds
|
||||||
|
* Syntax highlighting
|
||||||
|
* Repository statistics
|
||||||
|
|
||||||
|
## Authors and contributors
|
||||||
|
* [Klaus Silveira](http://www.klaussilveira.com) (Creator, developer)
|
||||||
|
|
||||||
|
## License
|
||||||
|
[New BSD license](http://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
|
||||||
|
## Todo
|
||||||
|
* improve the current test code coverage
|
||||||
|
* test the interface
|
||||||
|
* error handling can be greatly improved during parsing
|
||||||
|
* submodule support
|
||||||
|
* multilanguage support
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
In order to run GitList on your server, you'll need:
|
||||||
|
|
||||||
|
* git
|
||||||
|
* Apache and mod_rewrite enabled
|
||||||
|
* PHP 5.3.3
|
||||||
|
|
||||||
|
## Installing
|
||||||
|
Download the GitList latest package and decompress to your `/var/www/gitlist` folder, or anywhere else you want to place GitList. You can also clone the repository:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/klaussilveira/gitlist.git /var/www/gitlist
|
||||||
|
```
|
||||||
|
|
||||||
|
Now open up the `config.ini` and configure your installation. You'll have to provide where your repositories are located and the base GitList URL (in our case, http://localhost/gitlist). Now, let's create the cache folder and give the correct permissions:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /var/www/gitlist
|
||||||
|
mkdir cache
|
||||||
|
chmod 777 cache
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it, installation complete!
|
||||||
|
|
||||||
|
## Further information
|
||||||
|
If you want to know more about customizing GitList, check the [Customization](https://github.com/klaussilveira/gitlist/wiki/Customizing) page on the wiki. Also, if you're having problems with GitList, check the [Troubleshooting](https://github.com/klaussilveira/gitlist/wiki/Customizing) page. Don't forget to report issues and suggest new features! :)
|
||||||
6
config.ini
Normal file
6
config.ini
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[git]
|
||||||
|
client = '/usr/bin/git' ; Your git executable path
|
||||||
|
repositories = '/home/git/' ; Path to your repositories (with ending slash)
|
||||||
|
|
||||||
|
[app]
|
||||||
|
baseurl = 'http://localhost/gitlist' ; Base URL of the application (without ending slash)
|
||||||
32
controllers/blobController.php
Normal file
32
controllers/blobController.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$app->get('{repo}/blob/{branch}/{file}/', function($repo, $branch, $file) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$blob = $repository->getBlob("$branch:$file");
|
||||||
|
$breadcrumbs = $app['utils']->getBreadcrumbs("$repo/tree/$branch/$file");
|
||||||
|
$fileType = $app['utils']->getFileType($file);
|
||||||
|
|
||||||
|
return $app['twig']->render('file.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'files',
|
||||||
|
'file' => $file,
|
||||||
|
'fileType' => $fileType,
|
||||||
|
'blob' => $blob->output(),
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => $branch,
|
||||||
|
'breadcrumbs' => $breadcrumbs,
|
||||||
|
'branches' => $repository->getBranches(),
|
||||||
|
'tags' => $repository->getTags(),
|
||||||
|
));
|
||||||
|
})->assert('file', '.+')
|
||||||
|
->assert('repo', '[\w-._]+')
|
||||||
|
->assert('branch', '[\w-._]+');
|
||||||
|
|
||||||
|
$app->get('{repo}/raw/{branch}/{file}', function($repo, $branch, $file) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$blob = $repository->getBlob("$branch:$file")->output();
|
||||||
|
|
||||||
|
return new Symfony\Component\HttpFoundation\Response($blob, 200, array('Content-Type' => 'text/plain'));
|
||||||
|
})->assert('file', '.+')
|
||||||
|
->assert('repo', '[\w-._]+')
|
||||||
|
->assert('branch', '[\w-._]+');
|
||||||
79
controllers/commitController.php
Normal file
79
controllers/commitController.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$app->get('{repo}/commits/{branch}', function($repo, $branch) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$commits = $repository->getCommits();
|
||||||
|
|
||||||
|
foreach ($commits as $commit) {
|
||||||
|
$date = $commit->getDate();
|
||||||
|
$date = $date->format('m/d/Y');
|
||||||
|
$categorized[$date][] = $commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $app['twig']->render('commits.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'commits',
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => $branch,
|
||||||
|
'branches' => $repository->getBranches(),
|
||||||
|
'tags' => $repository->getTags(),
|
||||||
|
'commits' => $categorized,
|
||||||
|
));
|
||||||
|
})->assert('repo', '[\w-._]+')
|
||||||
|
->assert('branch', '[\w-._]+')
|
||||||
|
->value('branch', 'master');
|
||||||
|
|
||||||
|
$app->get('{repo}/commits/{branch}/{file}/', function($repo, $branch, $file) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$commits = $repository->getCommits($file);
|
||||||
|
|
||||||
|
foreach ($commits as $commit) {
|
||||||
|
$date = $commit->getDate();
|
||||||
|
$date = $date->format('m/d/Y');
|
||||||
|
$categorized[$date][] = $commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $app['twig']->render('commits.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'commits',
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => $branch,
|
||||||
|
'branches' => $repository->getBranches(),
|
||||||
|
'tags' => $repository->getTags(),
|
||||||
|
'commits' => $categorized,
|
||||||
|
));
|
||||||
|
})->assert('repo', '[\w-._]+')
|
||||||
|
->assert('file', '.+')
|
||||||
|
->assert('branch', '[\w-._]+');
|
||||||
|
|
||||||
|
$app->get('{repo}/commit/{commit}/', function($repo, $commit) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$commit = $repository->getCommit($commit);
|
||||||
|
|
||||||
|
return $app['twig']->render('commit.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'commits',
|
||||||
|
'branch' => 'master',
|
||||||
|
'repo' => $repo,
|
||||||
|
'commit' => $commit,
|
||||||
|
));
|
||||||
|
})->assert('repo', '[\w-._]+')
|
||||||
|
->assert('commit', '[a-f0-9]+');
|
||||||
|
|
||||||
|
$app->get('{repo}/blame/{branch}/{file}/', function($repo, $branch, $file) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$blames = $repository->getBlame($file);
|
||||||
|
|
||||||
|
return $app['twig']->render('blame.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'commits',
|
||||||
|
'file' => $file,
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => $branch,
|
||||||
|
'branches' => $repository->getBranches(),
|
||||||
|
'tags' => $repository->getTags(),
|
||||||
|
'blames' => $blames,
|
||||||
|
));
|
||||||
|
})->assert('repo', '[\w-._]+')
|
||||||
|
->assert('file', '.+')
|
||||||
|
->assert('branch', '[\w-._]+');
|
||||||
10
controllers/indexController.php
Normal file
10
controllers/indexController.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$app->get('/', function() use($app) {
|
||||||
|
$repositories = $app['git']->getRepositories($app['git.repos']);
|
||||||
|
|
||||||
|
return $app['twig']->render('index.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'repositories' => $repositories,
|
||||||
|
));
|
||||||
|
});
|
||||||
16
controllers/rssController.php
Normal file
16
controllers/rssController.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$app->get('{repo}/{branch}/rss/', function($repo, $branch) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$commits = $repository->getCommits();
|
||||||
|
|
||||||
|
$html = $app['twig']->render('rss.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => $branch,
|
||||||
|
'commits' => $commits,
|
||||||
|
));
|
||||||
|
|
||||||
|
return new Symfony\Component\HttpFoundation\Response($html, 200, array('Content-Type' => 'application/rss+xml'));
|
||||||
|
})->assert('repo', '[\w-._]+')
|
||||||
|
->assert('branch', '[\w-._]+');
|
||||||
20
controllers/statsController.php
Normal file
20
controllers/statsController.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$app->get('{repo}/stats/{branch}', function($repo, $branch) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$stats = $repository->getStatistics($branch);
|
||||||
|
$authors = $repository->getAuthorStatistics();
|
||||||
|
|
||||||
|
return $app['twig']->render('stats.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'stats',
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => $branch,
|
||||||
|
'branches' => $repository->getBranches(),
|
||||||
|
'tags' => $repository->getTags(),
|
||||||
|
'stats' => $stats,
|
||||||
|
'authors' => $authors,
|
||||||
|
));
|
||||||
|
})->assert('repo', '[\w-._]+')
|
||||||
|
->assert('branch', '[\w-._]+')
|
||||||
|
->value('branch', 'master');
|
||||||
67
controllers/treeController.php
Normal file
67
controllers/treeController.php
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$app->get('{repo}/', function($repo) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$tree = $repository->getTree('master');
|
||||||
|
$breadcrumbs = $app['utils']->getBreadcrumbs("$repo/");
|
||||||
|
|
||||||
|
return $app['twig']->render('tree.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'files',
|
||||||
|
'files' => $tree->output(),
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => 'master',
|
||||||
|
'path' => '',
|
||||||
|
'parent' => '',
|
||||||
|
'breadcrumbs' => $breadcrumbs,
|
||||||
|
'branches' => $repository->getBranches(),
|
||||||
|
'tags' => $repository->getTags(),
|
||||||
|
));
|
||||||
|
})->assert('repo', '[\w-._]+');
|
||||||
|
|
||||||
|
$app->get('{repo}/tree/{branch}/', function($repo, $branch) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$tree = $repository->getTree($branch);
|
||||||
|
$breadcrumbs = $app['utils']->getBreadcrumbs("$repo/");
|
||||||
|
|
||||||
|
return $app['twig']->render('tree.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'files',
|
||||||
|
'files' => $tree->output(),
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => $branch,
|
||||||
|
'path' => '',
|
||||||
|
'parent' => '',
|
||||||
|
'breadcrumbs' => $breadcrumbs,
|
||||||
|
'branches' => $repository->getBranches(),
|
||||||
|
'tags' => $repository->getTags(),
|
||||||
|
));
|
||||||
|
})->assert('repo', '[\w-._]+')
|
||||||
|
->assert('branch', '[\w-._]+');
|
||||||
|
|
||||||
|
$app->get('{repo}/tree/{branch}/{tree}/', function($repo, $branch, $tree) use($app) {
|
||||||
|
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
|
||||||
|
$files = $repository->getTree("$branch:$tree/");
|
||||||
|
$breadcrumbs = $app['utils']->getBreadcrumbs("$repo/tree/$branch/$tree");
|
||||||
|
|
||||||
|
if (($slash = strrpos($tree, '/')) !== false) {
|
||||||
|
$parent = '/' . substr($tree, 0, $slash);
|
||||||
|
} else {
|
||||||
|
$parent = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $app['twig']->render('tree.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'page' => 'files',
|
||||||
|
'files' => $files->output(),
|
||||||
|
'repo' => $repo,
|
||||||
|
'branch' => $branch,
|
||||||
|
'path' => "$tree/",
|
||||||
|
'parent' => $parent,
|
||||||
|
'breadcrumbs' => $breadcrumbs,
|
||||||
|
'branches' => $repository->getBranches(),
|
||||||
|
'tags' => $repository->getTags(),
|
||||||
|
));
|
||||||
|
})->assert('tree', '.+')
|
||||||
|
->assert('repo', '[\w-._]+')
|
||||||
|
->assert('branch', '[\w-._]+');
|
||||||
52
index.php
Normal file
52
index.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GitList 0.1
|
||||||
|
* https://github.com/klaussilveira/gitlist
|
||||||
|
*/
|
||||||
|
|
||||||
|
$config = parse_ini_file('config.ini', true);
|
||||||
|
|
||||||
|
if (empty($config['git']['repositories'])) {
|
||||||
|
die("Please, edit the config.ini file and provide your repositories directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__.'/vendor/silex.phar';
|
||||||
|
|
||||||
|
$app = new Silex\Application();
|
||||||
|
$app['baseurl'] = $config['app']['baseurl'];
|
||||||
|
|
||||||
|
// Register Git and Twig libraries
|
||||||
|
$app['autoloader']->registerNamespace('Git', __DIR__.'/lib');
|
||||||
|
$app['autoloader']->registerNamespace('Application', __DIR__.'/lib');
|
||||||
|
$app->register(new Silex\Provider\TwigServiceProvider(), array(
|
||||||
|
'twig.path' => __DIR__.'/views',
|
||||||
|
'twig.class_path' => __DIR__.'/vendor',
|
||||||
|
'twig.options' => array('cache' => __DIR__.'/cache'),
|
||||||
|
));
|
||||||
|
$app->register(new Git\GitServiceProvider(), array(
|
||||||
|
'git.client' => $config['git']['client'],
|
||||||
|
'git.repos' => $config['git']['repositories'],
|
||||||
|
));
|
||||||
|
$app->register(new Application\UtilsServiceProvider());
|
||||||
|
|
||||||
|
// Add the md5() function to Twig scope
|
||||||
|
$app['twig']->addFilter('md5', new Twig_Filter_Function('md5'));
|
||||||
|
|
||||||
|
// Load controllers
|
||||||
|
include 'controllers/indexController.php';
|
||||||
|
include 'controllers/treeController.php';
|
||||||
|
include 'controllers/blobController.php';
|
||||||
|
include 'controllers/commitController.php';
|
||||||
|
include 'controllers/statsController.php';
|
||||||
|
include 'controllers/rssController.php';
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
$app->error(function (\Exception $e, $code) use ($app) {
|
||||||
|
return $app['twig']->render('error.twig', array(
|
||||||
|
'baseurl' => $app['baseurl'],
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
$app->run();
|
||||||
206
lib/Application/Utils.php
Normal file
206
lib/Application/Utils.php
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General helper class, mostly used for string parsing inside the application controllers
|
||||||
|
*/
|
||||||
|
class Utils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Builds a breadcrumb array based on a path spec
|
||||||
|
*
|
||||||
|
* @param string $spec Path spec
|
||||||
|
* @return array Array with parts of the breadcrumb
|
||||||
|
*/
|
||||||
|
public function getBreadcrumbs($spec)
|
||||||
|
{
|
||||||
|
$paths = explode('/', $spec);
|
||||||
|
$last = '';
|
||||||
|
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
$dir['dir'] = $path;
|
||||||
|
$dir['path'] = "$last/$path";
|
||||||
|
$breadcrumbs[] = $dir;
|
||||||
|
$last .= '/' . $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($paths[2])) {
|
||||||
|
$breadcrumbs[0]['path'] .= '/' . $paths[1] . '/' . $paths[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($breadcrumbs[1], $breadcrumbs[2]);
|
||||||
|
return $breadcrumbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the file type based on filename by treating the extension
|
||||||
|
*
|
||||||
|
* The file type is used by CodeMirror, a Javascript-based IDE implemented in
|
||||||
|
* GitList, to properly highlight the blob syntax (if it's a source-code)
|
||||||
|
*
|
||||||
|
* @param string $spec File name
|
||||||
|
* @return string File type
|
||||||
|
*/
|
||||||
|
public function getFileType($file)
|
||||||
|
{
|
||||||
|
if (($pos = strrpos($file, '.')) !== FALSE) {
|
||||||
|
$fileType = substr($file, $pos + 1);
|
||||||
|
} else {
|
||||||
|
return 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($fileType) {
|
||||||
|
case 'php':
|
||||||
|
return 'php';
|
||||||
|
case 'c':
|
||||||
|
return 'clike';
|
||||||
|
case 'h':
|
||||||
|
return 'clike';
|
||||||
|
case 'cpp':
|
||||||
|
return 'clike';
|
||||||
|
case 'cs':
|
||||||
|
return 'clike';
|
||||||
|
case 'm':
|
||||||
|
return 'clike';
|
||||||
|
case 'mm':
|
||||||
|
return 'clike';
|
||||||
|
case 'java':
|
||||||
|
return 'clike';
|
||||||
|
case 'clj':
|
||||||
|
return 'clojure';
|
||||||
|
case 'coffee':
|
||||||
|
return 'coffeescript';
|
||||||
|
case 'css':
|
||||||
|
return 'css';
|
||||||
|
case 'diff':
|
||||||
|
return 'diff';
|
||||||
|
case 'ecl':
|
||||||
|
return 'ecl';
|
||||||
|
case 'el':
|
||||||
|
return 'erlang';
|
||||||
|
case 'go':
|
||||||
|
return 'go';
|
||||||
|
case 'groovy':
|
||||||
|
return 'groovy';
|
||||||
|
case 'hs':
|
||||||
|
return 'haskell';
|
||||||
|
case 'lhs':
|
||||||
|
return 'haskell';
|
||||||
|
case 'jsp':
|
||||||
|
return 'htmlembedded';
|
||||||
|
case 'asp':
|
||||||
|
return 'htmlembedded';
|
||||||
|
case 'aspx':
|
||||||
|
return 'htmlembedded';
|
||||||
|
case 'html':
|
||||||
|
return 'htmlmixed';
|
||||||
|
case 'tpl':
|
||||||
|
return 'htmlmixed';
|
||||||
|
case 'js':
|
||||||
|
return 'javascript';
|
||||||
|
case 'json':
|
||||||
|
return 'javascript';
|
||||||
|
case 'less':
|
||||||
|
return 'less';
|
||||||
|
case 'lua':
|
||||||
|
return 'lua';
|
||||||
|
case 'md':
|
||||||
|
return 'markdown';
|
||||||
|
case 'markdown':
|
||||||
|
return 'markdown';
|
||||||
|
case 'sql':
|
||||||
|
return 'mysql';
|
||||||
|
case 'pl':
|
||||||
|
return 'perl';
|
||||||
|
case 'pm':
|
||||||
|
return 'perl';
|
||||||
|
case 'pas':
|
||||||
|
return 'pascal';
|
||||||
|
case 'ini':
|
||||||
|
return 'properties';
|
||||||
|
case 'cfg':
|
||||||
|
return 'properties';
|
||||||
|
case 'nt':
|
||||||
|
return 'ntriples';
|
||||||
|
case 'py':
|
||||||
|
return 'python';
|
||||||
|
case 'rb':
|
||||||
|
return 'ruby';
|
||||||
|
case 'rst':
|
||||||
|
return 'rst';
|
||||||
|
case 'r':
|
||||||
|
return 'r';
|
||||||
|
case 'sh':
|
||||||
|
return 'shell';
|
||||||
|
case 'ss':
|
||||||
|
return 'scheme';
|
||||||
|
case 'scm':
|
||||||
|
return 'scheme';
|
||||||
|
case 'sls':
|
||||||
|
return 'scheme';
|
||||||
|
case 'sps':
|
||||||
|
return 'scheme';
|
||||||
|
case 'rs':
|
||||||
|
return 'rust';
|
||||||
|
case 'st':
|
||||||
|
return 'smalltalk';
|
||||||
|
case 'tex':
|
||||||
|
return 'stex';
|
||||||
|
case 'vbs':
|
||||||
|
return 'vbscript';
|
||||||
|
case 'v':
|
||||||
|
return 'verilog';
|
||||||
|
case 'xml':
|
||||||
|
return 'xml';
|
||||||
|
case 'xsd':
|
||||||
|
return 'xml';
|
||||||
|
case 'xsl':
|
||||||
|
return 'xml';
|
||||||
|
case 'xul':
|
||||||
|
return 'xml';
|
||||||
|
case 'xlf':
|
||||||
|
return 'xml';
|
||||||
|
case 'xliff':
|
||||||
|
return 'xml';
|
||||||
|
case 'xaml':
|
||||||
|
return 'xml';
|
||||||
|
case 'wxs':
|
||||||
|
return 'xml';
|
||||||
|
case 'wxl':
|
||||||
|
return 'xml';
|
||||||
|
case 'wxi':
|
||||||
|
return 'xml';
|
||||||
|
case 'wsdl':
|
||||||
|
return 'xml';
|
||||||
|
case 'svg':
|
||||||
|
return 'xml';
|
||||||
|
case 'rss':
|
||||||
|
return 'xml';
|
||||||
|
case 'rdf':
|
||||||
|
return 'xml';
|
||||||
|
case 'plist':
|
||||||
|
return 'xml';
|
||||||
|
case 'mxml':
|
||||||
|
return 'xml';
|
||||||
|
case 'kml':
|
||||||
|
return 'xml';
|
||||||
|
case 'glade':
|
||||||
|
return 'xml';
|
||||||
|
case 'xq':
|
||||||
|
return 'xquery';
|
||||||
|
case 'xqm':
|
||||||
|
return 'xquery';
|
||||||
|
case 'xquery':
|
||||||
|
return 'xquery';
|
||||||
|
case 'xqy':
|
||||||
|
return 'xquery';
|
||||||
|
case 'yml':
|
||||||
|
return 'yaml';
|
||||||
|
case 'yaml':
|
||||||
|
return 'yaml';
|
||||||
|
default:
|
||||||
|
return 'text';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
lib/Application/UtilsServiceProvider.php
Normal file
22
lib/Application/UtilsServiceProvider.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Application;
|
||||||
|
|
||||||
|
use Silex\Application;
|
||||||
|
use Silex\ServiceProviderInterface;
|
||||||
|
|
||||||
|
class UtilsServiceProvider implements ServiceProviderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register the Utils class on the Application ServiceProvider
|
||||||
|
*
|
||||||
|
* @param Application $app Silex Application
|
||||||
|
* @return Utils Instance of the Utils class
|
||||||
|
*/
|
||||||
|
public function register(Application $app)
|
||||||
|
{
|
||||||
|
$app['utils'] = function () use ($app) {
|
||||||
|
return new Utils;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
122
lib/Git/Client.php
Normal file
122
lib/Git/Client.php
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git;
|
||||||
|
|
||||||
|
class Client
|
||||||
|
{
|
||||||
|
protected $path;
|
||||||
|
|
||||||
|
public function __construct($path)
|
||||||
|
{
|
||||||
|
$this->setPath($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new repository on the specified path
|
||||||
|
*
|
||||||
|
* @param string $path Path where the new repository will be created
|
||||||
|
* @return Repository Instance of Repository
|
||||||
|
*/
|
||||||
|
public function createRepository($path)
|
||||||
|
{
|
||||||
|
if (file_exists($path . '/.git/HEAD') && !file_exists($path . '/HEAD')) {
|
||||||
|
throw new \RuntimeException('A GIT repository already exists at ' . $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$repository = new Repository($path, $this);
|
||||||
|
return $repository->create();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a repository at the specified path
|
||||||
|
*
|
||||||
|
* @param string $path Path where the repository is located
|
||||||
|
* @return Repository Instance of Repository
|
||||||
|
*/
|
||||||
|
public function getRepository($path)
|
||||||
|
{
|
||||||
|
if (!file_exists($path) || !file_exists($path . '/.git/HEAD') && !file_exists($path . '/HEAD')) {
|
||||||
|
throw new \RuntimeException('There is no GIT repository at ' . $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Repository($path, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for valid repositories on the specified path
|
||||||
|
*
|
||||||
|
* @param string $path Path where repositories will be searched
|
||||||
|
* @return array Found repositories, containing their name, path and description
|
||||||
|
*/
|
||||||
|
public function getRepositories($path)
|
||||||
|
{
|
||||||
|
$dir = new \DirectoryIterator($path);
|
||||||
|
|
||||||
|
foreach ($dir as $file) {
|
||||||
|
$isBare = file_exists($file->getPathname() . '/HEAD');
|
||||||
|
$isRepository = file_exists($file->getPathname() . '/.git/HEAD');
|
||||||
|
|
||||||
|
if ($file->isDir() && !$file->isDot() && $isRepository || $isBare) {
|
||||||
|
if ($isBare) {
|
||||||
|
$description = file_get_contents($file->getPathname() . '/description');
|
||||||
|
} else {
|
||||||
|
$description = file_get_contents($file->getPathname() . '/.git/description');
|
||||||
|
}
|
||||||
|
|
||||||
|
$repositories[] = array('name' => $file->getFilename(), 'path' => $file->getPathname(), 'description' => $description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($repositories)) {
|
||||||
|
throw new \RuntimeException('There are no GIT repositories in ' . $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
sort($repositories);
|
||||||
|
|
||||||
|
return $repositories;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a git command on the repository being manipulated
|
||||||
|
*
|
||||||
|
* This method will start a new process on the current machine and
|
||||||
|
* run git commands. Once the command has been run, the method will
|
||||||
|
* return the command line output.
|
||||||
|
*
|
||||||
|
* @param Repository $repository Repository where the command will be run
|
||||||
|
* @param string $command Git command to be run
|
||||||
|
* @return string Returns the command output
|
||||||
|
*/
|
||||||
|
public function run(Repository $repository, $command)
|
||||||
|
{
|
||||||
|
$descriptors = array(0 => array("pipe", "r"), 1 => array("pipe", "w"));
|
||||||
|
$process = proc_open($this->getPath() . ' ' . $command, $descriptors, $pipes, $repository->getPath());
|
||||||
|
|
||||||
|
if (is_resource($process)) {
|
||||||
|
$stdout = stream_get_contents($pipes[1]);
|
||||||
|
fclose($pipes[1]);
|
||||||
|
proc_close($process);
|
||||||
|
return $stdout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current Git binary path
|
||||||
|
*
|
||||||
|
* @return string Path where the Git binary is located
|
||||||
|
*/
|
||||||
|
protected function getPath()
|
||||||
|
{
|
||||||
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current Git binary path
|
||||||
|
*
|
||||||
|
* @param string $path Path where the Git binary is located
|
||||||
|
*/
|
||||||
|
protected function setPath($path)
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
lib/Git/Commit/Author.php
Normal file
35
lib/Git/Commit/Author.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git\Commit;
|
||||||
|
|
||||||
|
class Author
|
||||||
|
{
|
||||||
|
protected $name;
|
||||||
|
protected $email;
|
||||||
|
|
||||||
|
public function __construct($name, $email)
|
||||||
|
{
|
||||||
|
$this->setName($name);
|
||||||
|
$this->setEmail($email);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEmail()
|
||||||
|
{
|
||||||
|
return $this->email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEmail($email)
|
||||||
|
{
|
||||||
|
$this->email = $email;
|
||||||
|
}
|
||||||
|
}
|
||||||
148
lib/Git/Commit/Commit.php
Normal file
148
lib/Git/Commit/Commit.php
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git\Commit;
|
||||||
|
|
||||||
|
class Commit
|
||||||
|
{
|
||||||
|
protected $hash;
|
||||||
|
protected $shortHash;
|
||||||
|
protected $treeHash;
|
||||||
|
protected $parentHash;
|
||||||
|
protected $author;
|
||||||
|
protected $date;
|
||||||
|
protected $commiter;
|
||||||
|
protected $commiterDate;
|
||||||
|
protected $message;
|
||||||
|
protected $diffs;
|
||||||
|
|
||||||
|
public function importData(array $data)
|
||||||
|
{
|
||||||
|
$this->setHash($data['hash']);
|
||||||
|
$this->setShortHash($data['short_hash']);
|
||||||
|
$this->setTreeHash($data['tree']);
|
||||||
|
$this->setParentHash($data['parent']);
|
||||||
|
|
||||||
|
$this->setAuthor(
|
||||||
|
new Author($data['author'], $data['author_email'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setDate(
|
||||||
|
new \DateTime('@' . $data['date'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setCommiter(
|
||||||
|
new Author($data['commiter'], $data['commiter_email'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setCommiterDate(
|
||||||
|
new \DateTime('@' . $data['commiter_date'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setMessage($data['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHash()
|
||||||
|
{
|
||||||
|
return $this->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHash($hash)
|
||||||
|
{
|
||||||
|
$this->hash = $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShortHash()
|
||||||
|
{
|
||||||
|
return $this->shortHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShortHash($shortHash)
|
||||||
|
{
|
||||||
|
$this->shortHash = $shortHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTreeHash()
|
||||||
|
{
|
||||||
|
return $this->treeHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTreeHash($treeHash)
|
||||||
|
{
|
||||||
|
$this->treeHash = $treeHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParentHash()
|
||||||
|
{
|
||||||
|
return $this->parentHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setParentHash($parentHash)
|
||||||
|
{
|
||||||
|
$this->parentHash = $parentHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthor()
|
||||||
|
{
|
||||||
|
return $this->author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAuthor($author)
|
||||||
|
{
|
||||||
|
$this->author = $author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDate()
|
||||||
|
{
|
||||||
|
return $this->date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDate($date)
|
||||||
|
{
|
||||||
|
$this->date = $date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommiter()
|
||||||
|
{
|
||||||
|
return $this->commiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCommiter($commiter)
|
||||||
|
{
|
||||||
|
$this->commiter = $commiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommiterDate()
|
||||||
|
{
|
||||||
|
return $this->commiterDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCommiterDate($commiterDate)
|
||||||
|
{
|
||||||
|
$this->commiterDate = $commiterDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMessage()
|
||||||
|
{
|
||||||
|
return $this->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMessage($message)
|
||||||
|
{
|
||||||
|
$this->message = $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDiffs()
|
||||||
|
{
|
||||||
|
return $this->diffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDiffs($diffs)
|
||||||
|
{
|
||||||
|
$this->diffs = $diffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChangedFiles()
|
||||||
|
{
|
||||||
|
return sizeof($this->diffs);
|
||||||
|
}
|
||||||
|
}
|
||||||
23
lib/Git/GitServiceProvider.php
Normal file
23
lib/Git/GitServiceProvider.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git;
|
||||||
|
|
||||||
|
use Silex\Application;
|
||||||
|
use Silex\ServiceProviderInterface;
|
||||||
|
|
||||||
|
class GitServiceProvider implements ServiceProviderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register the Git\Client on the Application ServiceProvider
|
||||||
|
*
|
||||||
|
* @param Application $app Silex Application
|
||||||
|
* @return Git\Client Instance of the Git\Client
|
||||||
|
*/
|
||||||
|
public function register(Application $app)
|
||||||
|
{
|
||||||
|
$app['git'] = function () use ($app) {
|
||||||
|
$default = $app['git.client'] ? $app['git.client'] : '/usr/bin/git';
|
||||||
|
return new Client($app['git.client']);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
67
lib/Git/Model/Blob.php
Normal file
67
lib/Git/Model/Blob.php
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git\Model;
|
||||||
|
|
||||||
|
use Git\Client;
|
||||||
|
use Git\Repository;
|
||||||
|
use Git\ScopeAware;
|
||||||
|
|
||||||
|
class Blob extends ScopeAware
|
||||||
|
{
|
||||||
|
protected $mode;
|
||||||
|
protected $hash;
|
||||||
|
protected $name;
|
||||||
|
protected $size;
|
||||||
|
|
||||||
|
public function __construct($hash, Client $client, Repository $repository) {
|
||||||
|
$this->setClient($client);
|
||||||
|
$this->setRepository($repository);
|
||||||
|
$this->setHash($hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function output()
|
||||||
|
{
|
||||||
|
$data = $this->getClient()->run($this->getRepository(), 'show ' . $this->getHash());
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMode()
|
||||||
|
{
|
||||||
|
return $this->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMode($mode)
|
||||||
|
{
|
||||||
|
$this->mode = $mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHash()
|
||||||
|
{
|
||||||
|
return $this->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHash($hash)
|
||||||
|
{
|
||||||
|
$this->hash = $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSize()
|
||||||
|
{
|
||||||
|
return $this->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSize($size)
|
||||||
|
{
|
||||||
|
$this->size = $size;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
lib/Git/Model/Diff.php
Normal file
60
lib/Git/Model/Diff.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git\Model;
|
||||||
|
|
||||||
|
use Git\Model\Line;
|
||||||
|
|
||||||
|
class Diff
|
||||||
|
{
|
||||||
|
protected $lines;
|
||||||
|
protected $index;
|
||||||
|
protected $old;
|
||||||
|
protected $new;
|
||||||
|
protected $file;
|
||||||
|
|
||||||
|
public function addLine($line)
|
||||||
|
{
|
||||||
|
$this->lines[] = new Line($line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLines()
|
||||||
|
{
|
||||||
|
return $this->lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIndex($index)
|
||||||
|
{
|
||||||
|
$this->index = $index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIndex()
|
||||||
|
{
|
||||||
|
return $this->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOld($old)
|
||||||
|
{
|
||||||
|
$this->old = $old;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOld()
|
||||||
|
{
|
||||||
|
return $this->old;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setNew($new)
|
||||||
|
{
|
||||||
|
$this->new = $new;
|
||||||
|
$this->file = substr($new, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNew()
|
||||||
|
{
|
||||||
|
return $this->new;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFile()
|
||||||
|
{
|
||||||
|
return $this->file;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
lib/Git/Model/Line.php
Normal file
48
lib/Git/Model/Line.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git\Model;
|
||||||
|
|
||||||
|
class Line
|
||||||
|
{
|
||||||
|
protected $line;
|
||||||
|
protected $type;
|
||||||
|
|
||||||
|
public function __construct($data)
|
||||||
|
{
|
||||||
|
if (!empty($data)) {
|
||||||
|
if ($data[0] == '@') {
|
||||||
|
$this->setType('chunk');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data[0] == '-') {
|
||||||
|
$this->setType('old');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data[0] == '+') {
|
||||||
|
$this->setType('new');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setLine($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLine()
|
||||||
|
{
|
||||||
|
return $this->line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLine($line)
|
||||||
|
{
|
||||||
|
$this->line = $line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setType($type)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
lib/Git/Model/Symlink.php
Normal file
44
lib/Git/Model/Symlink.php
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git\Model;
|
||||||
|
|
||||||
|
use Git\Client;
|
||||||
|
use Git\Repository;
|
||||||
|
use Git\ScopeAware;
|
||||||
|
|
||||||
|
class Symlink
|
||||||
|
{
|
||||||
|
protected $mode;
|
||||||
|
protected $name;
|
||||||
|
protected $path;
|
||||||
|
|
||||||
|
public function getMode()
|
||||||
|
{
|
||||||
|
return $this->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMode($mode)
|
||||||
|
{
|
||||||
|
$this->mode = $mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPath()
|
||||||
|
{
|
||||||
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPath($path)
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
172
lib/Git/Model/Tree.php
Normal file
172
lib/Git/Model/Tree.php
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git\Model;
|
||||||
|
|
||||||
|
use Git\Client;
|
||||||
|
use Git\Repository;
|
||||||
|
use Git\ScopeAware;
|
||||||
|
|
||||||
|
class Tree extends ScopeAware implements \RecursiveIterator
|
||||||
|
{
|
||||||
|
protected $mode;
|
||||||
|
protected $hash;
|
||||||
|
protected $name;
|
||||||
|
protected $data;
|
||||||
|
protected $position = 0;
|
||||||
|
|
||||||
|
public function __construct($hash, Client $client, Repository $repository) {
|
||||||
|
$this->setClient($client);
|
||||||
|
$this->setRepository($repository);
|
||||||
|
$this->setHash($hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parse()
|
||||||
|
{
|
||||||
|
$data = $this->getClient()->run($this->getRepository(), 'ls-tree -l ' . $this->getHash());
|
||||||
|
$lines = explode("\n", $data);
|
||||||
|
$files = array();
|
||||||
|
$root = array();
|
||||||
|
|
||||||
|
foreach ($lines as $key => $line) {
|
||||||
|
if (empty($line)) {
|
||||||
|
unset($lines[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$files[] = preg_split("/[\s]+/", $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($file[1] == 'commit') {
|
||||||
|
// submodule
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file[0] == '120000') {
|
||||||
|
$show = $this->getClient()->run($this->getRepository(), 'show ' . $file[2]);
|
||||||
|
$tree = new Symlink;
|
||||||
|
$tree->setMode($file[0]);
|
||||||
|
$tree->setName($file[4]);
|
||||||
|
$tree->setPath($show);
|
||||||
|
$root[] = $tree;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file[1] == 'blob') {
|
||||||
|
$blob = new Blob($file[2], $this->getClient(), $this->getRepository());
|
||||||
|
$blob->setMode($file[0]);
|
||||||
|
$blob->setName($file[4]);
|
||||||
|
$blob->setSize($file[3]);
|
||||||
|
$root[] = $blob;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tree = new Tree($file[2], $this->getClient(), $this->getRepository());
|
||||||
|
$tree->setMode($file[0]);
|
||||||
|
$tree->setName($file[4]);
|
||||||
|
$root[] = $tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->data = $root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function output()
|
||||||
|
{
|
||||||
|
$files = $folders = array();
|
||||||
|
|
||||||
|
foreach ($this as $node) {
|
||||||
|
if ($node instanceof Blob) {
|
||||||
|
$file['type'] = 'blob';
|
||||||
|
$file['name'] = $node->getName();
|
||||||
|
$file['size'] = $node->getSize();
|
||||||
|
$file['mode'] = $node->getMode();
|
||||||
|
$file['hash'] = $node->getHash();
|
||||||
|
$files[] = $file;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($node instanceof Tree) {
|
||||||
|
$folder['type'] = 'folder';
|
||||||
|
$folder['name'] = $node->getName();
|
||||||
|
$folder['size'] = '';
|
||||||
|
$folder['mode'] = $node->getMode();
|
||||||
|
$folder['hash'] = $node->getHash();
|
||||||
|
$folders[] = $folder;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($node instanceof Symlink) {
|
||||||
|
$folder['type'] = 'symlink';
|
||||||
|
$folder['name'] = $node->getName();
|
||||||
|
$folder['size'] = '';
|
||||||
|
$folder['mode'] = $node->getMode();
|
||||||
|
$folder['hash'] = '';
|
||||||
|
$folder['path'] = $node->getPath();
|
||||||
|
$folders[] = $folder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Little hack to make folders appear before files
|
||||||
|
$files = array_merge($folders, $files);
|
||||||
|
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function valid() {
|
||||||
|
return isset($this->data[$this->position]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasChildren() {
|
||||||
|
return is_array($this->data[$this->position]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function next() {
|
||||||
|
$this->position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function current() {
|
||||||
|
return $this->data[$this->position];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChildren() {
|
||||||
|
return $this->data[$this->position];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rewind() {
|
||||||
|
$this->position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function key() {
|
||||||
|
return $this->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMode()
|
||||||
|
{
|
||||||
|
return $this->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMode($mode)
|
||||||
|
{
|
||||||
|
$this->mode = $mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHash()
|
||||||
|
{
|
||||||
|
return $this->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHash($hash)
|
||||||
|
{
|
||||||
|
$this->hash = $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
465
lib/Git/Repository.php
Normal file
465
lib/Git/Repository.php
Normal file
@@ -0,0 +1,465 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git;
|
||||||
|
|
||||||
|
use Git\Commit\Commit;
|
||||||
|
use Git\Model\Tree;
|
||||||
|
use Git\Model\Blob;
|
||||||
|
use Git\Model\Diff;
|
||||||
|
|
||||||
|
class Repository
|
||||||
|
{
|
||||||
|
protected $path;
|
||||||
|
protected $client;
|
||||||
|
|
||||||
|
public function __construct($path, Client $client)
|
||||||
|
{
|
||||||
|
$this->setPath($path);
|
||||||
|
$this->setClient($client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setClient(Client $client)
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClient()
|
||||||
|
{
|
||||||
|
return $this->client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
mkdir($this->getPath());
|
||||||
|
$this->getClient()->run($this, 'init');
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfig($key)
|
||||||
|
{
|
||||||
|
$key = $this->getClient()->run($this, 'config ' . $key);
|
||||||
|
return trim($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setConfig($key, $value)
|
||||||
|
{
|
||||||
|
$this->getClient()->run($this, "config $key \"$value\"");
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add untracked files
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param mixed $files Files to be added to the repository
|
||||||
|
*/
|
||||||
|
public function add($files = '.')
|
||||||
|
{
|
||||||
|
if(is_array($files)) {
|
||||||
|
$files = implode(' ', $files);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->getClient()->run($this, "add $files");
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all untracked files
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function addAll()
|
||||||
|
{
|
||||||
|
$this->getClient()->run($this, "add -A");
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commit changes to the repository
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $message Description of the changes made
|
||||||
|
*/
|
||||||
|
public function commit($message)
|
||||||
|
{
|
||||||
|
$this->getClient()->run($this, "commit -m '$message'");
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checkout a branch
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $branch Branch to be checked out
|
||||||
|
*/
|
||||||
|
public function checkout($branch)
|
||||||
|
{
|
||||||
|
$this->getClient()->run($this, "checkout $branch");
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull repository changes
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function pull()
|
||||||
|
{
|
||||||
|
$this->getClient()->run($this, "pull");
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update remote references
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $repository Repository to be pushed
|
||||||
|
* @param string $refspec Refspec for the push
|
||||||
|
*/
|
||||||
|
public function push($repository = null, $refspec = null)
|
||||||
|
{
|
||||||
|
$command = "push";
|
||||||
|
|
||||||
|
if($repository) {
|
||||||
|
$command .= " $repository";
|
||||||
|
}
|
||||||
|
|
||||||
|
if($refspec) {
|
||||||
|
$command .= " $refspec";
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->getClient()->run($this, $command);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a list of the repository branches
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array List of branches
|
||||||
|
*/
|
||||||
|
public function getBranches()
|
||||||
|
{
|
||||||
|
$branches = $this->getClient()->run($this, "branch");
|
||||||
|
$branches = explode("\n", $branches);
|
||||||
|
$branches = array_filter(preg_replace('/[\*\s]/', '', $branches));
|
||||||
|
|
||||||
|
return $branches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the current repository branch
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string Current repository branch
|
||||||
|
*/
|
||||||
|
public function getCurrentBranch()
|
||||||
|
{
|
||||||
|
$branches = $this->getClient()->run($this, "branch");
|
||||||
|
$branches = explode("\n", $branches);
|
||||||
|
|
||||||
|
foreach($branches as $branch) {
|
||||||
|
if($branch[0] == '*') {
|
||||||
|
return substr($branch, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a specified branch exists
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $branch Branch to be checked
|
||||||
|
* @return boolean True if the branch exists
|
||||||
|
*/
|
||||||
|
public function hasBranch($branch)
|
||||||
|
{
|
||||||
|
$branches = $this->getBranches();
|
||||||
|
$status = in_array($branch, $branches);
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new repository branch
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $branch Branch name
|
||||||
|
*/
|
||||||
|
public function createBranch($branch)
|
||||||
|
{
|
||||||
|
$this->getClient()->run($this, "branch $branch");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a list of the repository tags
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array List of tags
|
||||||
|
*/
|
||||||
|
public function getTags()
|
||||||
|
{
|
||||||
|
$tags = $this->getClient()->run($this, "tag");
|
||||||
|
$tags = explode("\n", $tags);
|
||||||
|
|
||||||
|
if (empty($tags[0])) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the repository commit log
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array Commit log
|
||||||
|
*/
|
||||||
|
public function getCommits($file = null)
|
||||||
|
{
|
||||||
|
$command = 'log --pretty=format:\'"%h": {"hash": "%H", "short_hash": "%h", "tree": "%T", "parent": "%P", "author": "%an", "author_email": "%ae", "date": "%at", "commiter": "%cn", "commiter_email": "%ce", "commiter_date": "%ct", "message": "%f"}\'';
|
||||||
|
|
||||||
|
if ($file) {
|
||||||
|
$command .= " $file";
|
||||||
|
}
|
||||||
|
|
||||||
|
$logs = $this->getClient()->run($this, $command);
|
||||||
|
$logs = str_replace("\n", ',', $logs);
|
||||||
|
$logs = json_decode("{ $logs }", true);
|
||||||
|
|
||||||
|
foreach ($logs as $log) {
|
||||||
|
$log['message'] = str_replace('-', ' ', $log['message']);
|
||||||
|
$commit = new Commit;
|
||||||
|
$commit->importData($log);
|
||||||
|
$commits[] = $commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $commits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRelatedCommits($hash)
|
||||||
|
{
|
||||||
|
$logs = $this->getClient()->run($this, 'log --pretty=format:\'"%h": {"hash": "%H", "short_hash": "%h", "tree": "%T", "parent": "%P", "author": "%an", "author_email": "%ae", "date": "%at", "commiter": "%cn", "commiter_email": "%ce", "commiter_date": "%ct", "message": "%f"}\'');
|
||||||
|
$logs = str_replace("\n", ',', $logs);
|
||||||
|
$logs = json_decode("{ $logs }", true);
|
||||||
|
|
||||||
|
foreach ($logs as $log) {
|
||||||
|
$log['message'] = str_replace('-', ' ', $log['message']);
|
||||||
|
$logTree = $this->getClient()->run($this, 'diff-tree -t -r ' . $log['hash']);
|
||||||
|
$lines = explode("\n", $logTree);
|
||||||
|
array_shift($lines);
|
||||||
|
$files = array();
|
||||||
|
|
||||||
|
foreach ($lines as $key => $line) {
|
||||||
|
if (empty($line)) {
|
||||||
|
unset($lines[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$files[] = preg_split("/[\s]+/", $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now let's find the commits who have our hash within them
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($file[1] == 'commit') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file[3] == $hash) {
|
||||||
|
$commit = new Commit;
|
||||||
|
$commit->importData($log);
|
||||||
|
$commits[] = $commit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $commits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommit($commit)
|
||||||
|
{
|
||||||
|
$logs = $this->getClient()->run($this, 'show --pretty=format:\'{"hash": "%H", "short_hash": "%h", "tree": "%T", "parent": "%P", "author": "%an", "author_email": "%ae", "date": "%at", "commiter": "%cn", "commiter_email": "%ce", "commiter_date": "%ct", "message": "%f"}\' ' . $commit);
|
||||||
|
$logs = explode("\n", $logs);
|
||||||
|
|
||||||
|
// Read commit metadata
|
||||||
|
$data = json_decode($logs[0], true);
|
||||||
|
$data['message'] = str_replace('-', ' ', $data['message']);
|
||||||
|
$commit = new Commit;
|
||||||
|
$commit->importData($data);
|
||||||
|
unset($logs[0]);
|
||||||
|
|
||||||
|
// Read diff logs
|
||||||
|
foreach ($logs as $log) {
|
||||||
|
if ('diff' === substr($log, 0, 4)) {
|
||||||
|
if (isset($diff)) {
|
||||||
|
$diffs[] = $diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
$diff = new Diff;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('index' === substr($log, 0, 5)) {
|
||||||
|
$diff->setIndex($log);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('---' === substr($log, 0, 3)) {
|
||||||
|
$diff->setOld($log);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('+++' === substr($log, 0, 3)) {
|
||||||
|
$diff->setNew($log);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$diff->addLine($log);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($diff)) {
|
||||||
|
$diffs[] = $diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
$commit->setDiffs($diffs);
|
||||||
|
|
||||||
|
return $commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthorStatistics()
|
||||||
|
{
|
||||||
|
$logs = $this->getClient()->run($this, 'log --pretty=format:\'%an||%ae\'');
|
||||||
|
$logs = explode("\n", $logs);
|
||||||
|
$logs = array_count_values($logs);
|
||||||
|
arsort($logs);
|
||||||
|
|
||||||
|
foreach ($logs as $user => $count) {
|
||||||
|
$user = explode('||', $user);
|
||||||
|
$data[] = array('name' => $user[0], 'email' => $user[1], 'commits' => $count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatistics($branch)
|
||||||
|
{
|
||||||
|
// Calculate amount of files, extensions and file size
|
||||||
|
$logs = $this->getClient()->run($this, 'ls-tree -r -l ' . $branch);
|
||||||
|
$lines = explode("\n", $logs);
|
||||||
|
$files = array();
|
||||||
|
$data['extensions'] = array();
|
||||||
|
$data['size'] = 0;
|
||||||
|
$data['files'] = 0;
|
||||||
|
|
||||||
|
foreach ($lines as $key => $line) {
|
||||||
|
if (empty($line)) {
|
||||||
|
unset($lines[$key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$files[] = preg_split("/[\s]+/", $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($file[1] == 'blob') {
|
||||||
|
$data['files']++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_numeric($file[3])) {
|
||||||
|
$data['size'] += $file[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($pos = strrpos($file[4], '.')) !== FALSE) {
|
||||||
|
$data['extensions'][] = substr($file[4], $pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['extensions'] = array_count_values($data['extensions']);
|
||||||
|
arsort($data['extensions']);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Tree for the provided folder
|
||||||
|
*
|
||||||
|
* @param string $tree Folder that will be parsed
|
||||||
|
* @return Tree Instance of Tree for the provided folder
|
||||||
|
*/
|
||||||
|
public function getTree($tree)
|
||||||
|
{
|
||||||
|
$tree = new Tree($tree, $this->getClient(), $this);
|
||||||
|
$tree->parse();
|
||||||
|
return $tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Blob for the provided file
|
||||||
|
*
|
||||||
|
* @param string $blob File that will be parsed
|
||||||
|
* @return Blob Instance of Blob for the provided file
|
||||||
|
*/
|
||||||
|
public function getBlob($blob)
|
||||||
|
{
|
||||||
|
return new Blob($blob, $this->getClient(), $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blames the provided file and parses the output
|
||||||
|
*
|
||||||
|
* @param string $file File that will be blamed
|
||||||
|
* @return array Commits hashes containing the lines
|
||||||
|
*/
|
||||||
|
public function getBlame($file)
|
||||||
|
{
|
||||||
|
$logs = $this->getClient()->run($this, "blame -s $file");
|
||||||
|
$logs = explode("\n", $logs);
|
||||||
|
|
||||||
|
foreach ($logs as $log) {
|
||||||
|
if ($log == '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$split = preg_split("/[a-zA-Z0-9^]{8}[\s]+[0-9]+\)/", $log);
|
||||||
|
preg_match_all("/([a-zA-Z0-9^]{8})[\s]+([0-9]+)\)/", $log, $match);
|
||||||
|
|
||||||
|
$commit = $match[1][0];
|
||||||
|
|
||||||
|
if (!isset($blame[$commit]['line'])) {
|
||||||
|
$blame[$commit]['line'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$blame[$commit]['line'] .= PHP_EOL . $split[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $blame;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current Repository path
|
||||||
|
*
|
||||||
|
* @return string Path where the repository is located
|
||||||
|
*/
|
||||||
|
public function getPath()
|
||||||
|
{
|
||||||
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current Repository path
|
||||||
|
*
|
||||||
|
* @param string $path Path where the repository is located
|
||||||
|
*/
|
||||||
|
public function setPath($path)
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/Git/ScopeAware.php
Normal file
29
lib/Git/ScopeAware.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Git;
|
||||||
|
|
||||||
|
class ScopeAware
|
||||||
|
{
|
||||||
|
protected $client;
|
||||||
|
protected $repository;
|
||||||
|
|
||||||
|
public function setClient(Client $client)
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClient()
|
||||||
|
{
|
||||||
|
return $this->client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRepository()
|
||||||
|
{
|
||||||
|
return $this->repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRepository($repository)
|
||||||
|
{
|
||||||
|
$this->repository = $repository;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
phpunit.xml.dist
Normal file
18
phpunit.xml.dist
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<phpunit backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnFailure="false"
|
||||||
|
syntaxCheck="true"
|
||||||
|
>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="GitList Test Suite">
|
||||||
|
<directory>./tests/</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
</phpunit>
|
||||||
371
tests/ClientTest.php
Normal file
371
tests/ClientTest.php
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Git\Client;
|
||||||
|
use Git\Repository;
|
||||||
|
|
||||||
|
spl_autoload_register(function($class)
|
||||||
|
{
|
||||||
|
if (0 === strpos($class, 'Git\\')) {
|
||||||
|
$file = __DIR__ . '/../lib/' . str_replace('\\', '/', $class) . '.php';
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
require_once $file;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function recursiveDelete($dir)
|
||||||
|
{
|
||||||
|
$files = scandir($dir);
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if ($file == '.' || $file == '..') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = "$dir/$file";
|
||||||
|
|
||||||
|
if (is_dir($path)) {
|
||||||
|
recursiveDelete($path);
|
||||||
|
} else {
|
||||||
|
unlink($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rmdir($dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClientTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected $client;
|
||||||
|
protected $repoPath = '/tmp/gitlist/testrepo';
|
||||||
|
|
||||||
|
public static function setUpBeforeClass()
|
||||||
|
{
|
||||||
|
mkdir('/tmp/gitlist');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
if (!is_writable('/tmp/gitlist')) {
|
||||||
|
$this->markTestSkipped('There are no write permissions in order to create test repositories.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->client = new Client('/usr/bin/git');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException RuntimeException
|
||||||
|
*/
|
||||||
|
public function testIsNotFindingRepositories()
|
||||||
|
{
|
||||||
|
$this->client->getRepositories($this->repoPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException RuntimeException
|
||||||
|
*/
|
||||||
|
public function testIsNotAbleToGetUnexistingRepository()
|
||||||
|
{
|
||||||
|
$this->client->getRepository($this->repoPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsCreatingRepository()
|
||||||
|
{
|
||||||
|
$repository = $this->client->createRepository($this->repoPath);
|
||||||
|
$this->assertRegExp("/nothing to commit/", $repository->getClient()->run($repository, 'status'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException RuntimeException
|
||||||
|
*/
|
||||||
|
public function testIsNotAbleToCreateRepositoryDueToExistingOne()
|
||||||
|
{
|
||||||
|
$this->client->createRepository($this->repoPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsListingRepositories()
|
||||||
|
{
|
||||||
|
$this->client->createRepository($this->repoPath . '/../anothertestrepo');
|
||||||
|
$this->client->createRepository($this->repoPath . '/../bigbadrepo');
|
||||||
|
$repositories = $this->client->getRepositories($this->repoPath . '/../');
|
||||||
|
|
||||||
|
$this->assertEquals($repositories[0]['name'], 'anothertestrepo');
|
||||||
|
$this->assertEquals($repositories[1]['name'], 'bigbadrepo');
|
||||||
|
$this->assertEquals($repositories[2]['name'], 'testrepo');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsConfiguratingRepository()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$repository->setConfig('user.name', 'Luke Skywalker');
|
||||||
|
$repository->setConfig('user.email', 'luke@republic.com');
|
||||||
|
|
||||||
|
$this->assertEquals($repository->getConfig('user.name'), 'Luke Skywalker');
|
||||||
|
$this->assertEquals($repository->getConfig('user.email'), 'luke@republic.com');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testIsCreatingRepository
|
||||||
|
*/
|
||||||
|
public function testIsAdding()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
file_put_contents($this->repoPath . '/test_file.txt', 'Your mother is so ugly, glCullFace always returns TRUE.');
|
||||||
|
$repository->add('test_file.txt');
|
||||||
|
$this->assertRegExp("/new file: test_file.txt/", $repository->getClient()->run($repository, 'status'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testIsAdding
|
||||||
|
*/
|
||||||
|
public function testIsAddingDot()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
|
||||||
|
file_put_contents($this->repoPath . '/test_file1.txt', 'Your mother is so ugly, glCullFace always returns TRUE.');
|
||||||
|
file_put_contents($this->repoPath . '/test_file2.txt', 'Your mother is so ugly, glCullFace always returns TRUE.');
|
||||||
|
file_put_contents($this->repoPath . '/test_file3.txt', 'Your mother is so ugly, glCullFace always returns TRUE.');
|
||||||
|
|
||||||
|
$repository->add();
|
||||||
|
|
||||||
|
$this->assertRegExp("/new file: test_file1.txt/", $repository->getClient()->run($repository, 'status'));
|
||||||
|
$this->assertRegExp("/new file: test_file2.txt/", $repository->getClient()->run($repository, 'status'));
|
||||||
|
$this->assertRegExp("/new file: test_file3.txt/", $repository->getClient()->run($repository, 'status'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testIsAddingDot
|
||||||
|
*/
|
||||||
|
public function testIsAddingAll()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
|
||||||
|
file_put_contents($this->repoPath . '/test_file4.txt', 'Your mother is so ugly, glCullFace always returns TRUE.');
|
||||||
|
file_put_contents($this->repoPath . '/test_file5.txt', 'Your mother is so ugly, glCullFace always returns TRUE.');
|
||||||
|
file_put_contents($this->repoPath . '/test_file6.txt', 'Your mother is so ugly, glCullFace always returns TRUE.');
|
||||||
|
|
||||||
|
$repository->addAll();
|
||||||
|
|
||||||
|
$this->assertRegExp("/new file: test_file4.txt/", $repository->getClient()->run($repository, 'status'));
|
||||||
|
$this->assertRegExp("/new file: test_file5.txt/", $repository->getClient()->run($repository, 'status'));
|
||||||
|
$this->assertRegExp("/new file: test_file6.txt/", $repository->getClient()->run($repository, 'status'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testIsAddingAll
|
||||||
|
*/
|
||||||
|
public function testIsCommiting()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$repository->commit("The truth unveiled");
|
||||||
|
$this->assertRegExp("/The truth unveiled/", $repository->getClient()->run($repository, 'log'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsCreatingBranches()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$repository->createBranch('issue12');
|
||||||
|
$repository->createBranch('issue42');
|
||||||
|
$branches = $repository->getBranches();
|
||||||
|
$this->assertContains('issue12', $branches);
|
||||||
|
$this->assertContains('issue42', $branches);
|
||||||
|
$this->assertContains('master', $branches);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsGettingCurrentBranch()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$branch = $repository->getCurrentBranch();
|
||||||
|
$this->assertTrue($branch === 'master');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testIsCommiting
|
||||||
|
*/
|
||||||
|
public function testIsGettingCommits()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$commits = $repository->getCommits();
|
||||||
|
|
||||||
|
foreach ($commits as $commit) {
|
||||||
|
$this->assertInstanceOf('Git\Commit\Commit', $commit);
|
||||||
|
$this->assertTrue($commit->getMessage() === 'The truth unveiled');
|
||||||
|
$this->assertInstanceOf('Git\Commit\Author', $commit->getAuthor());
|
||||||
|
$this->assertEquals($commit->getAuthor()->getName(), 'Luke Skywalker');
|
||||||
|
$this->assertEquals($commit->getAuthor()->getEmail(), 'luke@republic.com');
|
||||||
|
$this->assertEquals($commit->getCommiter()->getName(), 'Luke Skywalker');
|
||||||
|
$this->assertEquals($commit->getCommiter()->getEmail(), 'luke@republic.com');
|
||||||
|
$this->assertEquals($commit->getParentHash(), '');
|
||||||
|
$this->assertInstanceOf('DateTime', $commit->getDate());
|
||||||
|
$this->assertInstanceOf('DateTime', $commit->getCommiterDate());
|
||||||
|
$this->assertRegExp('/[a-f0-9]+/', $commit->getHash());
|
||||||
|
$this->assertRegExp('/[a-f0-9]+/', $commit->getShortHash());
|
||||||
|
$this->assertRegExp('/[a-f0-9]+/', $commit->getTreeHash());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testIsGettingCommits
|
||||||
|
*/
|
||||||
|
public function testIsGettingCommitsFromSpecificFile()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$commits = $repository->getCommits('test_file4.txt');
|
||||||
|
|
||||||
|
foreach ($commits as $commit) {
|
||||||
|
$this->assertInstanceOf('Git\Commit\Commit', $commit);
|
||||||
|
$this->assertTrue($commit->getMessage() === 'The truth unveiled');
|
||||||
|
$this->assertInstanceOf('Git\Commit\Author', $commit->getAuthor());
|
||||||
|
$this->assertEquals($commit->getAuthor()->getName(), 'Luke Skywalker');
|
||||||
|
$this->assertEquals($commit->getAuthor()->getEmail(), 'luke@republic.com');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsGettingTree()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$files = $repository->getTree('master');
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$this->assertInstanceOf('Git\Model\Blob', $file);
|
||||||
|
$this->assertRegExp('/test_file[0-9]*.txt/', $file->getName());
|
||||||
|
$this->assertEquals($file->getSize(), '55');
|
||||||
|
$this->assertEquals($file->getMode(), '100644');
|
||||||
|
$this->assertRegExp('/[a-f0-9]+/', $file->getHash());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsGettingTreeOutput()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$files = $repository->getTree('master')->output();
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$this->assertEquals('blob', $file['type']);
|
||||||
|
$this->assertRegExp('/test_file[0-9]*.txt/', $file['name']);
|
||||||
|
$this->assertEquals($file['size'], '55');
|
||||||
|
$this->assertEquals($file['mode'], '100644');
|
||||||
|
$this->assertRegExp('/[a-f0-9]+/', $file['hash']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsGettingTreesWithinTree()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
|
||||||
|
// Creating folders
|
||||||
|
mkdir($this->repoPath . '/MyFolder');
|
||||||
|
mkdir($this->repoPath . '/MyTest');
|
||||||
|
mkdir($this->repoPath . '/MyFolder/Tests');
|
||||||
|
|
||||||
|
// Populating created folders
|
||||||
|
file_put_contents($this->repoPath . '/MyFolder/crazy.php', 'Lorem ipsum dolor sit amet');
|
||||||
|
file_put_contents($this->repoPath . '/MyFolder/skywalker.php', 'Lorem ipsum dolor sit amet');
|
||||||
|
file_put_contents($this->repoPath . '/MyTest/fortytwo.php', 'Lorem ipsum dolor sit amet');
|
||||||
|
file_put_contents($this->repoPath . '/MyFolder/Tests/web.php', 'Lorem ipsum dolor sit amet');
|
||||||
|
file_put_contents($this->repoPath . '/MyFolder/Tests/cli.php', 'Lorem ipsum dolor sit amet');
|
||||||
|
|
||||||
|
// Adding and commiting
|
||||||
|
$repository->addAll();
|
||||||
|
$repository->commit("Creating folders for testIsGettingTreesWithinTrees");
|
||||||
|
|
||||||
|
// Checking tree
|
||||||
|
$files = $repository->getTree('master')->output();
|
||||||
|
|
||||||
|
$this->assertEquals('folder', $files[0]['type']);
|
||||||
|
$this->assertEquals('MyFolder', $files[0]['name']);
|
||||||
|
$this->assertEquals('', $files[0]['size']);
|
||||||
|
$this->assertEquals('040000', $files[0]['mode']);
|
||||||
|
$this->assertEquals('4143e982237f3bdf56b5350f862c334054aad69e', $files[0]['hash']);
|
||||||
|
|
||||||
|
$this->assertEquals('folder', $files[1]['type']);
|
||||||
|
$this->assertEquals('MyTest', $files[1]['name']);
|
||||||
|
$this->assertEquals('', $files[1]['size']);
|
||||||
|
$this->assertEquals('040000', $files[1]['mode']);
|
||||||
|
$this->assertEquals('632240595eabd59e4217d196d6c12efb81f9c011', $files[1]['hash']);
|
||||||
|
|
||||||
|
$this->assertEquals('blob', $files[2]['type']);
|
||||||
|
$this->assertEquals('test_file.txt', $files[2]['name']);
|
||||||
|
$this->assertEquals('55', $files[2]['size']);
|
||||||
|
$this->assertEquals('100644', $files[2]['mode']);
|
||||||
|
$this->assertEquals('a773bfc0fda6f878e3d17d78c667d18297c8831f', $files[2]['hash']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsGettingBlobsWithinTrees()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$files = $repository->getTree('master:MyFolder/')->output();
|
||||||
|
|
||||||
|
$this->assertEquals('folder', $files[0]['type']);
|
||||||
|
$this->assertEquals('Tests', $files[0]['name']);
|
||||||
|
$this->assertEquals('', $files[0]['size']);
|
||||||
|
$this->assertEquals('040000', $files[0]['mode']);
|
||||||
|
$this->assertEquals('8542f67d011ff2ea5ec49a729ba81a52935676d1', $files[0]['hash']);
|
||||||
|
|
||||||
|
$this->assertEquals('blob', $files[1]['type']);
|
||||||
|
$this->assertEquals('crazy.php', $files[1]['name']);
|
||||||
|
$this->assertEquals('26', $files[1]['size']);
|
||||||
|
$this->assertEquals('100644', $files[1]['mode']);
|
||||||
|
$this->assertEquals('d781006b2d05cc31751954a0fb920c990e825aad', $files[1]['hash']);
|
||||||
|
|
||||||
|
$this->assertEquals('blob', $files[2]['type']);
|
||||||
|
$this->assertEquals('skywalker.php', $files[2]['name']);
|
||||||
|
$this->assertEquals('26', $files[2]['size']);
|
||||||
|
$this->assertEquals('100644', $files[2]['mode']);
|
||||||
|
$this->assertEquals('d781006b2d05cc31751954a0fb920c990e825aad', $files[2]['hash']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsGettingBlobOutput()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$blob = $repository->getBlob('master:MyFolder/crazy.php')->output();
|
||||||
|
$this->assertEquals('Lorem ipsum dolor sit amet', $blob);
|
||||||
|
|
||||||
|
$blob = $repository->getBlob('master:test_file4.txt')->output();
|
||||||
|
$this->assertEquals('Your mother is so ugly, glCullFace always returns TRUE.', $blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsGettingStatistics()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$stats = $repository->getStatistics('master');
|
||||||
|
|
||||||
|
$this->assertEquals('7', $stats['extensions']['.txt']);
|
||||||
|
$this->assertEquals('5', $stats['extensions']['.php']);
|
||||||
|
$this->assertEquals('515', $stats['size']);
|
||||||
|
$this->assertEquals('12', $stats['files']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsGettingAuthorStatistics()
|
||||||
|
{
|
||||||
|
$repository = $this->client->getRepository($this->repoPath);
|
||||||
|
$stats = $repository->getAuthorStatistics();
|
||||||
|
|
||||||
|
$this->assertEquals('Luke Skywalker', $stats[0]['name']);
|
||||||
|
$this->assertEquals('luke@republic.com', $stats[0]['email']);
|
||||||
|
$this->assertEquals('2', $stats[0]['commits']);
|
||||||
|
|
||||||
|
$repository->setConfig('user.name', 'Princess Leia');
|
||||||
|
$repository->setConfig('user.email', 'sexyleia@republic.com');
|
||||||
|
file_put_contents($this->repoPath . '/MyFolder/crazy.php', 'Lorem ipsum dolor sit AMET');
|
||||||
|
$repository->addAll();
|
||||||
|
$repository->commit("Fixing AMET case");
|
||||||
|
|
||||||
|
$stats = $repository->getAuthorStatistics();
|
||||||
|
|
||||||
|
$this->assertEquals('Luke Skywalker', $stats[0]['name']);
|
||||||
|
$this->assertEquals('luke@republic.com', $stats[0]['email']);
|
||||||
|
$this->assertEquals('2', $stats[0]['commits']);
|
||||||
|
|
||||||
|
$this->assertEquals('Princess Leia', $stats[1]['name']);
|
||||||
|
$this->assertEquals('sexyleia@republic.com', $stats[1]['email']);
|
||||||
|
$this->assertEquals('1', $stats[1]['commits']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function tearDownAfterClass()
|
||||||
|
{
|
||||||
|
recursiveDelete('/tmp/gitlist');
|
||||||
|
}
|
||||||
|
}
|
||||||
46
vendor/Twig/Autoloader.php
vendored
Normal file
46
vendor/Twig/Autoloader.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autoloads Twig classes.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Autoloader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Registers Twig_Autoloader as an SPL autoloader.
|
||||||
|
*/
|
||||||
|
static public function register()
|
||||||
|
{
|
||||||
|
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||||
|
spl_autoload_register(array(new self, 'autoload'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles autoloading of classes.
|
||||||
|
*
|
||||||
|
* @param string $class A class name.
|
||||||
|
*
|
||||||
|
* @return boolean Returns true if the class has been loaded
|
||||||
|
*/
|
||||||
|
static public function autoload($class)
|
||||||
|
{
|
||||||
|
if (0 !== strpos($class, 'Twig')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
|
||||||
|
require $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
242
vendor/Twig/Compiler.php
vendored
Normal file
242
vendor/Twig/Compiler.php
vendored
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a node to PHP code.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Compiler implements Twig_CompilerInterface
|
||||||
|
{
|
||||||
|
protected $lastLine;
|
||||||
|
protected $source;
|
||||||
|
protected $indentation;
|
||||||
|
protected $env;
|
||||||
|
protected $debugInfo;
|
||||||
|
protected $sourceOffset;
|
||||||
|
protected $sourceLine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param Twig_Environment $env The twig environment instance
|
||||||
|
*/
|
||||||
|
public function __construct(Twig_Environment $env)
|
||||||
|
{
|
||||||
|
$this->env = $env;
|
||||||
|
$this->debugInfo = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the environment instance related to this compiler.
|
||||||
|
*
|
||||||
|
* @return Twig_Environment The environment instance
|
||||||
|
*/
|
||||||
|
public function getEnvironment()
|
||||||
|
{
|
||||||
|
return $this->env;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current PHP code after compilation.
|
||||||
|
*
|
||||||
|
* @return string The PHP code
|
||||||
|
*/
|
||||||
|
public function getSource()
|
||||||
|
{
|
||||||
|
return $this->source;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a node.
|
||||||
|
*
|
||||||
|
* @param Twig_NodeInterface $node The node to compile
|
||||||
|
* @param integer $indentation The current indentation
|
||||||
|
*
|
||||||
|
* @return Twig_Compiler The current compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_NodeInterface $node, $indentation = 0)
|
||||||
|
{
|
||||||
|
$this->lastLine = null;
|
||||||
|
$this->source = '';
|
||||||
|
$this->sourceOffset = 0;
|
||||||
|
$this->sourceLine = 0;
|
||||||
|
$this->indentation = $indentation;
|
||||||
|
|
||||||
|
$node->compile($this);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function subcompile(Twig_NodeInterface $node, $raw = true)
|
||||||
|
{
|
||||||
|
if (false === $raw) {
|
||||||
|
$this->addIndentation();
|
||||||
|
}
|
||||||
|
|
||||||
|
$node->compile($this);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a raw string to the compiled code.
|
||||||
|
*
|
||||||
|
* @param string $string The string
|
||||||
|
*
|
||||||
|
* @return Twig_Compiler The current compiler instance
|
||||||
|
*/
|
||||||
|
public function raw($string)
|
||||||
|
{
|
||||||
|
$this->source .= $string;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a string to the compiled code by adding indentation.
|
||||||
|
*
|
||||||
|
* @return Twig_Compiler The current compiler instance
|
||||||
|
*/
|
||||||
|
public function write()
|
||||||
|
{
|
||||||
|
$strings = func_get_args();
|
||||||
|
foreach ($strings as $string) {
|
||||||
|
$this->addIndentation();
|
||||||
|
$this->source .= $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addIndentation()
|
||||||
|
{
|
||||||
|
$this->source .= str_repeat(' ', $this->indentation * 4);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a quoted string to the compiled code.
|
||||||
|
*
|
||||||
|
* @param string $value The string
|
||||||
|
*
|
||||||
|
* @return Twig_Compiler The current compiler instance
|
||||||
|
*/
|
||||||
|
public function string($value)
|
||||||
|
{
|
||||||
|
$this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\"));
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a PHP representation of a given value.
|
||||||
|
*
|
||||||
|
* @param mixed $value The value to convert
|
||||||
|
*
|
||||||
|
* @return Twig_Compiler The current compiler instance
|
||||||
|
*/
|
||||||
|
public function repr($value)
|
||||||
|
{
|
||||||
|
if (is_int($value) || is_float($value)) {
|
||||||
|
if (false !== $locale = setlocale(LC_NUMERIC, 0)) {
|
||||||
|
setlocale(LC_NUMERIC, 'C');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->raw($value);
|
||||||
|
|
||||||
|
if (false !== $locale) {
|
||||||
|
setlocale(LC_NUMERIC, $locale);
|
||||||
|
}
|
||||||
|
} elseif (null === $value) {
|
||||||
|
$this->raw('null');
|
||||||
|
} elseif (is_bool($value)) {
|
||||||
|
$this->raw($value ? 'true' : 'false');
|
||||||
|
} elseif (is_array($value)) {
|
||||||
|
$this->raw('array(');
|
||||||
|
$i = 0;
|
||||||
|
foreach ($value as $key => $value) {
|
||||||
|
if ($i++) {
|
||||||
|
$this->raw(', ');
|
||||||
|
}
|
||||||
|
$this->repr($key);
|
||||||
|
$this->raw(' => ');
|
||||||
|
$this->repr($value);
|
||||||
|
}
|
||||||
|
$this->raw(')');
|
||||||
|
} else {
|
||||||
|
$this->string($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds debugging information.
|
||||||
|
*
|
||||||
|
* @param Twig_NodeInterface $node The related twig node
|
||||||
|
*
|
||||||
|
* @return Twig_Compiler The current compiler instance
|
||||||
|
*/
|
||||||
|
public function addDebugInfo(Twig_NodeInterface $node)
|
||||||
|
{
|
||||||
|
if ($node->getLine() != $this->lastLine) {
|
||||||
|
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
|
||||||
|
$this->sourceOffset = strlen($this->source);
|
||||||
|
$this->debugInfo[$this->sourceLine] = $node->getLine();
|
||||||
|
|
||||||
|
$this->lastLine = $node->getLine();
|
||||||
|
$this->write("// line {$node->getLine()}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDebugInfo()
|
||||||
|
{
|
||||||
|
return $this->debugInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indents the generated code.
|
||||||
|
*
|
||||||
|
* @param integer $step The number of indentation to add
|
||||||
|
*
|
||||||
|
* @return Twig_Compiler The current compiler instance
|
||||||
|
*/
|
||||||
|
public function indent($step = 1)
|
||||||
|
{
|
||||||
|
$this->indentation += $step;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outdents the generated code.
|
||||||
|
*
|
||||||
|
* @param integer $step The number of indentation to remove
|
||||||
|
*
|
||||||
|
* @return Twig_Compiler The current compiler instance
|
||||||
|
*/
|
||||||
|
public function outdent($step = 1)
|
||||||
|
{
|
||||||
|
$this->indentation -= $step;
|
||||||
|
|
||||||
|
if ($this->indentation < 0) {
|
||||||
|
throw new Twig_Error('Unable to call outdent() as the indentation would become negative');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
vendor/Twig/CompilerInterface.php
vendored
Normal file
35
vendor/Twig/CompilerInterface.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface implemented by compiler classes.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
interface Twig_CompilerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles a node.
|
||||||
|
*
|
||||||
|
* @param Twig_NodeInterface $node The node to compile
|
||||||
|
*
|
||||||
|
* @return Twig_CompilerInterface The current compiler instance
|
||||||
|
*/
|
||||||
|
function compile(Twig_NodeInterface $node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current PHP code after compilation.
|
||||||
|
*
|
||||||
|
* @return string The PHP code
|
||||||
|
*/
|
||||||
|
function getSource();
|
||||||
|
}
|
||||||
1106
vendor/Twig/Environment.php
vendored
Normal file
1106
vendor/Twig/Environment.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
199
vendor/Twig/Error.php
vendored
Normal file
199
vendor/Twig/Error.php
vendored
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Twig base exception.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Error extends Exception
|
||||||
|
{
|
||||||
|
protected $lineno;
|
||||||
|
protected $filename;
|
||||||
|
protected $rawMessage;
|
||||||
|
protected $previous;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param string $message The error message
|
||||||
|
* @param integer $lineno The template line where the error occurred
|
||||||
|
* @param string $filename The template file name where the error occurred
|
||||||
|
* @param Exception $previous The previous exception
|
||||||
|
*/
|
||||||
|
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
|
||||||
|
{
|
||||||
|
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||||
|
$this->previous = $previous;
|
||||||
|
parent::__construct('');
|
||||||
|
} else {
|
||||||
|
parent::__construct('', 0, $previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->lineno = $lineno;
|
||||||
|
$this->filename = $filename;
|
||||||
|
|
||||||
|
if (-1 === $this->lineno || null === $this->filename) {
|
||||||
|
$this->guessTemplateInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->rawMessage = $message;
|
||||||
|
|
||||||
|
$this->updateRepr();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the raw message.
|
||||||
|
*
|
||||||
|
* @return string The raw message
|
||||||
|
*/
|
||||||
|
public function getRawMessage()
|
||||||
|
{
|
||||||
|
return $this->rawMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the filename where the error occurred.
|
||||||
|
*
|
||||||
|
* @return string The filename
|
||||||
|
*/
|
||||||
|
public function getTemplateFile()
|
||||||
|
{
|
||||||
|
return $this->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the filename where the error occurred.
|
||||||
|
*
|
||||||
|
* @param string $filename The filename
|
||||||
|
*/
|
||||||
|
public function setTemplateFile($filename)
|
||||||
|
{
|
||||||
|
$this->filename = $filename;
|
||||||
|
|
||||||
|
$this->updateRepr();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the template line where the error occurred.
|
||||||
|
*
|
||||||
|
* @return integer The template line
|
||||||
|
*/
|
||||||
|
public function getTemplateLine()
|
||||||
|
{
|
||||||
|
return $this->lineno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the template line where the error occurred.
|
||||||
|
*
|
||||||
|
* @param integer $lineno The template line
|
||||||
|
*/
|
||||||
|
public function setTemplateLine($lineno)
|
||||||
|
{
|
||||||
|
$this->lineno = $lineno;
|
||||||
|
|
||||||
|
$this->updateRepr();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For PHP < 5.3.0, provides access to the getPrevious() method.
|
||||||
|
*
|
||||||
|
* @param string $method The method name
|
||||||
|
* @param array $arguments The parameters to be passed to the method
|
||||||
|
*
|
||||||
|
* @return Exception The previous exception or null
|
||||||
|
*/
|
||||||
|
public function __call($method, $arguments)
|
||||||
|
{
|
||||||
|
if ('getprevious' == strtolower($method)) {
|
||||||
|
return $this->previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function updateRepr()
|
||||||
|
{
|
||||||
|
$this->message = $this->rawMessage;
|
||||||
|
|
||||||
|
$dot = false;
|
||||||
|
if ('.' === substr($this->message, -1)) {
|
||||||
|
$this->message = substr($this->message, 0, -1);
|
||||||
|
$dot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->filename) {
|
||||||
|
if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
|
||||||
|
$filename = sprintf('"%s"', $this->filename);
|
||||||
|
} else {
|
||||||
|
$filename = json_encode($this->filename);
|
||||||
|
}
|
||||||
|
$this->message .= sprintf(' in %s', $filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->lineno >= 0) {
|
||||||
|
$this->message .= sprintf(' at line %d', $this->lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dot) {
|
||||||
|
$this->message .= '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function guessTemplateInfo()
|
||||||
|
{
|
||||||
|
$template = null;
|
||||||
|
foreach (debug_backtrace() as $trace) {
|
||||||
|
if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
|
||||||
|
$template = $trace['object'];
|
||||||
|
|
||||||
|
// update template filename
|
||||||
|
if (null === $this->filename) {
|
||||||
|
$this->filename = $template->getTemplateName();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $template || $this->lineno > -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = new ReflectionObject($template);
|
||||||
|
$file = $r->getFileName();
|
||||||
|
|
||||||
|
$exceptions = array($e = $this);
|
||||||
|
while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) {
|
||||||
|
$exceptions[] = $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($e = array_pop($exceptions)) {
|
||||||
|
$traces = $e->getTrace();
|
||||||
|
while ($trace = array_shift($traces)) {
|
||||||
|
if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
|
||||||
|
if ($codeLine <= $trace['line']) {
|
||||||
|
// update template line
|
||||||
|
$this->lineno = $templateLine;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
vendor/Twig/Error/Loader.php
vendored
Normal file
20
vendor/Twig/Error/Loader.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when an error occurs during template loading.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Error_Loader extends Twig_Error
|
||||||
|
{
|
||||||
|
}
|
||||||
21
vendor/Twig/Error/Runtime.php
vendored
Normal file
21
vendor/Twig/Error/Runtime.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when an error occurs at runtime.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Error_Runtime extends Twig_Error
|
||||||
|
{
|
||||||
|
}
|
||||||
21
vendor/Twig/Error/Syntax.php
vendored
Normal file
21
vendor/Twig/Error/Syntax.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when a syntax error occurs during lexing or parsing of a template.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Error_Syntax extends Twig_Error
|
||||||
|
{
|
||||||
|
}
|
||||||
488
vendor/Twig/ExpressionParser.php
vendored
Normal file
488
vendor/Twig/ExpressionParser.php
vendored
Normal file
@@ -0,0 +1,488 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses expressions.
|
||||||
|
*
|
||||||
|
* This parser implements a "Precedence climbing" algorithm.
|
||||||
|
*
|
||||||
|
* @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
|
||||||
|
* @see http://en.wikipedia.org/wiki/Operator-precedence_parser
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_ExpressionParser
|
||||||
|
{
|
||||||
|
const OPERATOR_LEFT = 1;
|
||||||
|
const OPERATOR_RIGHT = 2;
|
||||||
|
|
||||||
|
protected $parser;
|
||||||
|
protected $unaryOperators;
|
||||||
|
protected $binaryOperators;
|
||||||
|
|
||||||
|
public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators)
|
||||||
|
{
|
||||||
|
$this->parser = $parser;
|
||||||
|
$this->unaryOperators = $unaryOperators;
|
||||||
|
$this->binaryOperators = $binaryOperators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseExpression($precedence = 0)
|
||||||
|
{
|
||||||
|
$expr = $this->getPrimary();
|
||||||
|
$token = $this->parser->getCurrentToken();
|
||||||
|
while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) {
|
||||||
|
$op = $this->binaryOperators[$token->getValue()];
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
|
||||||
|
if (isset($op['callable'])) {
|
||||||
|
$expr = call_user_func($op['callable'], $this->parser, $expr);
|
||||||
|
} else {
|
||||||
|
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
|
||||||
|
$class = $op['class'];
|
||||||
|
$expr = new $class($expr, $expr1, $token->getLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $this->parser->getCurrentToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === $precedence) {
|
||||||
|
return $this->parseConditionalExpression($expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPrimary()
|
||||||
|
{
|
||||||
|
$token = $this->parser->getCurrentToken();
|
||||||
|
|
||||||
|
if ($this->isUnary($token)) {
|
||||||
|
$operator = $this->unaryOperators[$token->getValue()];
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
$expr = $this->parseExpression($operator['precedence']);
|
||||||
|
$class = $operator['class'];
|
||||||
|
|
||||||
|
return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
|
||||||
|
} elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
$expr = $this->parseExpression();
|
||||||
|
$this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed');
|
||||||
|
|
||||||
|
return $this->parsePostfixExpression($expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parsePrimaryExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseConditionalExpression($expr)
|
||||||
|
{
|
||||||
|
while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
$expr2 = $this->parseExpression();
|
||||||
|
$this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'The ternary operator must have a default value');
|
||||||
|
$expr3 = $this->parseExpression();
|
||||||
|
|
||||||
|
$expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isUnary(Twig_Token $token)
|
||||||
|
{
|
||||||
|
return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isBinary(Twig_Token $token)
|
||||||
|
{
|
||||||
|
return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parsePrimaryExpression()
|
||||||
|
{
|
||||||
|
$token = $this->parser->getCurrentToken();
|
||||||
|
switch ($token->getType()) {
|
||||||
|
case Twig_Token::NAME_TYPE:
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
switch ($token->getValue()) {
|
||||||
|
case 'true':
|
||||||
|
case 'TRUE':
|
||||||
|
$node = new Twig_Node_Expression_Constant(true, $token->getLine());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'false':
|
||||||
|
case 'FALSE':
|
||||||
|
$node = new Twig_Node_Expression_Constant(false, $token->getLine());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'none':
|
||||||
|
case 'NONE':
|
||||||
|
case 'null':
|
||||||
|
case 'NULL':
|
||||||
|
$node = new Twig_Node_Expression_Constant(null, $token->getLine());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if ('(' === $this->parser->getCurrentToken()->getValue()) {
|
||||||
|
$node = $this->getFunctionNode($token->getValue(), $token->getLine());
|
||||||
|
} else {
|
||||||
|
$node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Twig_Token::NUMBER_TYPE:
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
$node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Twig_Token::STRING_TYPE:
|
||||||
|
case Twig_Token::INTERPOLATION_START_TYPE:
|
||||||
|
$node = $this->parseStringExpression();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
|
||||||
|
$node = $this->parseArrayExpression();
|
||||||
|
} elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
|
||||||
|
$node = $this->parseHashExpression();
|
||||||
|
} else {
|
||||||
|
throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parsePostfixExpression($node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseStringExpression()
|
||||||
|
{
|
||||||
|
$stream = $this->parser->getStream();
|
||||||
|
|
||||||
|
$nodes = array();
|
||||||
|
// a string cannot be followed by another string in a single expression
|
||||||
|
$nextCanBeString = true;
|
||||||
|
while (true) {
|
||||||
|
if ($stream->test(Twig_Token::STRING_TYPE) && $nextCanBeString) {
|
||||||
|
$token = $stream->next();
|
||||||
|
$nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
|
||||||
|
$nextCanBeString = false;
|
||||||
|
} elseif ($stream->test(Twig_Token::INTERPOLATION_START_TYPE)) {
|
||||||
|
$stream->next();
|
||||||
|
$nodes[] = $this->parseExpression();
|
||||||
|
$stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
|
||||||
|
$nextCanBeString = true;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$expr = array_shift($nodes);
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
$expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseArrayExpression()
|
||||||
|
{
|
||||||
|
$stream = $this->parser->getStream();
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected');
|
||||||
|
|
||||||
|
$node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
|
||||||
|
$first = true;
|
||||||
|
while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
|
||||||
|
if (!$first) {
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma');
|
||||||
|
|
||||||
|
// trailing ,?
|
||||||
|
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$first = false;
|
||||||
|
|
||||||
|
$node->addElement($this->parseExpression());
|
||||||
|
}
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed');
|
||||||
|
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseHashExpression()
|
||||||
|
{
|
||||||
|
$stream = $this->parser->getStream();
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected');
|
||||||
|
|
||||||
|
$node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
|
||||||
|
$first = true;
|
||||||
|
while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
|
||||||
|
if (!$first) {
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma');
|
||||||
|
|
||||||
|
// trailing ,?
|
||||||
|
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$first = false;
|
||||||
|
|
||||||
|
// a hash key can be:
|
||||||
|
//
|
||||||
|
// * a number -- 12
|
||||||
|
// * a string -- 'a'
|
||||||
|
// * a name, which is equivalent to a string -- a
|
||||||
|
// * an expression, which must be enclosed in parentheses -- (1 + 2)
|
||||||
|
if ($stream->test(Twig_Token::STRING_TYPE) || $stream->test(Twig_Token::NAME_TYPE) || $stream->test(Twig_Token::NUMBER_TYPE)) {
|
||||||
|
$token = $stream->next();
|
||||||
|
$key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
|
||||||
|
} elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||||
|
$key = $this->parseExpression();
|
||||||
|
} else {
|
||||||
|
$current = $stream->getCurrent();
|
||||||
|
|
||||||
|
throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType(), $current->getLine()), $current->getValue()), $current->getLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
|
||||||
|
$value = $this->parseExpression();
|
||||||
|
|
||||||
|
$node->addElement($value, $key);
|
||||||
|
}
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed');
|
||||||
|
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parsePostfixExpression($node)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
$token = $this->parser->getCurrentToken();
|
||||||
|
if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) {
|
||||||
|
if ('.' == $token->getValue() || '[' == $token->getValue()) {
|
||||||
|
$node = $this->parseSubscriptExpression($node);
|
||||||
|
} elseif ('|' == $token->getValue()) {
|
||||||
|
$node = $this->parseFilterExpression($node);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFunctionNode($name, $line)
|
||||||
|
{
|
||||||
|
$args = $this->parseArguments();
|
||||||
|
switch ($name) {
|
||||||
|
case 'parent':
|
||||||
|
if (!count($this->parser->getBlockStack())) {
|
||||||
|
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
|
||||||
|
throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
|
||||||
|
case 'block':
|
||||||
|
return new Twig_Node_Expression_BlockReference($args->getNode(0), false, $line);
|
||||||
|
case 'attribute':
|
||||||
|
if (count($args) < 2) {
|
||||||
|
throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_TemplateInterface::ANY_CALL, $line);
|
||||||
|
default:
|
||||||
|
if (null !== $alias = $this->parser->getImportedFunction($name)) {
|
||||||
|
$arguments = new Twig_Node_Expression_Array(array(), $line);
|
||||||
|
foreach ($args as $n) {
|
||||||
|
$arguments->addElement($n);
|
||||||
|
}
|
||||||
|
|
||||||
|
$node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line);
|
||||||
|
$node->setAttribute('safe', true);
|
||||||
|
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = $this->getFunctionNodeClass($name);
|
||||||
|
|
||||||
|
return new $class($name, $args, $line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseSubscriptExpression($node)
|
||||||
|
{
|
||||||
|
$stream = $this->parser->getStream();
|
||||||
|
$token = $stream->next();
|
||||||
|
$lineno = $token->getLine();
|
||||||
|
$arguments = new Twig_Node_Expression_Array(array(), $lineno);
|
||||||
|
$type = Twig_TemplateInterface::ANY_CALL;
|
||||||
|
if ($token->getValue() == '.') {
|
||||||
|
$token = $stream->next();
|
||||||
|
if (
|
||||||
|
$token->getType() == Twig_Token::NAME_TYPE
|
||||||
|
||
|
||||||
|
$token->getType() == Twig_Token::NUMBER_TYPE
|
||||||
|
||
|
||||||
|
($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
|
||||||
|
) {
|
||||||
|
$arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
|
||||||
|
|
||||||
|
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||||
|
$type = Twig_TemplateInterface::METHOD_CALL;
|
||||||
|
foreach ($this->parseArguments() as $n) {
|
||||||
|
$arguments->addElement($n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Twig_Error_Syntax('Expected name or number', $lineno);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$type = Twig_TemplateInterface::ARRAY_CALL;
|
||||||
|
|
||||||
|
$arg = $this->parseExpression();
|
||||||
|
|
||||||
|
// slice?
|
||||||
|
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||||
|
$stream->next();
|
||||||
|
|
||||||
|
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
|
||||||
|
$length = new Twig_Node_Expression_Constant(null, $token->getLine());
|
||||||
|
} else {
|
||||||
|
$length = $this->parseExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = $this->getFilterNodeClass('slice');
|
||||||
|
$arguments = new Twig_Node(array($arg, $length));
|
||||||
|
$filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine());
|
||||||
|
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
|
||||||
|
|
||||||
|
return $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseFilterExpression($node)
|
||||||
|
{
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
|
||||||
|
return $this->parseFilterExpressionRaw($node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseFilterExpressionRaw($node, $tag = null)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
$token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE);
|
||||||
|
|
||||||
|
$name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
|
||||||
|
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||||
|
$arguments = new Twig_Node();
|
||||||
|
} else {
|
||||||
|
$arguments = $this->parseArguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = $this->getFilterNodeClass($name->getAttribute('value'));
|
||||||
|
|
||||||
|
$node = new $class($node, $name, $arguments, $token->getLine(), $tag);
|
||||||
|
|
||||||
|
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseArguments()
|
||||||
|
{
|
||||||
|
$args = array();
|
||||||
|
$stream = $this->parser->getStream();
|
||||||
|
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must be opened by a parenthesis');
|
||||||
|
while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) {
|
||||||
|
if (!empty($args)) {
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
|
||||||
|
}
|
||||||
|
$args[] = $this->parseExpression();
|
||||||
|
}
|
||||||
|
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
|
||||||
|
|
||||||
|
return new Twig_Node($args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseAssignmentExpression()
|
||||||
|
{
|
||||||
|
$targets = array();
|
||||||
|
while (true) {
|
||||||
|
$token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
|
||||||
|
if (in_array($token->getValue(), array('true', 'false', 'none'))) {
|
||||||
|
throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine());
|
||||||
|
}
|
||||||
|
$targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());
|
||||||
|
|
||||||
|
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Twig_Node($targets);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parseMultitargetExpression()
|
||||||
|
{
|
||||||
|
$targets = array();
|
||||||
|
while (true) {
|
||||||
|
$targets[] = $this->parseExpression();
|
||||||
|
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$this->parser->getStream()->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Twig_Node($targets);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFunctionNodeClass($name)
|
||||||
|
{
|
||||||
|
$functionMap = $this->parser->getEnvironment()->getFunctions();
|
||||||
|
if (isset($functionMap[$name]) && $functionMap[$name] instanceof Twig_Function_Node) {
|
||||||
|
return $functionMap[$name]->getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Twig_Node_Expression_Function';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFilterNodeClass($name)
|
||||||
|
{
|
||||||
|
$filterMap = $this->parser->getEnvironment()->getFilters();
|
||||||
|
if (isset($filterMap[$name]) && $filterMap[$name] instanceof Twig_Filter_Node) {
|
||||||
|
return $filterMap[$name]->getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Twig_Node_Expression_Filter';
|
||||||
|
}
|
||||||
|
}
|
||||||
93
vendor/Twig/Extension.php
vendored
Normal file
93
vendor/Twig/Extension.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
abstract class Twig_Extension implements Twig_ExtensionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes the runtime environment.
|
||||||
|
*
|
||||||
|
* This is where you can load some file that contains filter functions for instance.
|
||||||
|
*
|
||||||
|
* @param Twig_Environment $environment The current Twig_Environment instance
|
||||||
|
*/
|
||||||
|
public function initRuntime(Twig_Environment $environment)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the token parser instances to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
||||||
|
*/
|
||||||
|
public function getTokenParsers()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node visitor instances to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of Twig_NodeVisitorInterface instances
|
||||||
|
*/
|
||||||
|
public function getNodeVisitors()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of filters to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of filters
|
||||||
|
*/
|
||||||
|
public function getFilters()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of tests to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of tests
|
||||||
|
*/
|
||||||
|
public function getTests()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of functions to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of functions
|
||||||
|
*/
|
||||||
|
public function getFunctions()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of operators to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of operators
|
||||||
|
*/
|
||||||
|
public function getOperators()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of global variables to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of global variables
|
||||||
|
*/
|
||||||
|
public function getGlobals()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
||||||
1037
vendor/Twig/Extension/Core.php
vendored
Normal file
1037
vendor/Twig/Extension/Core.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
64
vendor/Twig/Extension/Debug.php
vendored
Normal file
64
vendor/Twig/Extension/Debug.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2011 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Extension_Debug extends Twig_Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a list of global functions to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of global functions
|
||||||
|
*/
|
||||||
|
public function getFunctions()
|
||||||
|
{
|
||||||
|
// dump is safe if var_dump is overriden by xdebug
|
||||||
|
$isDumpOutputHtmlSafe = extension_loaded('xdebug') && (false === get_cfg_var('xdebug.overload_var_dump') || get_cfg_var('xdebug.overload_var_dump')) && get_cfg_var('html_errors');
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'dump' => new Twig_Function_Function('twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the extension.
|
||||||
|
*
|
||||||
|
* @return string The extension name
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'debug';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function twig_var_dump(Twig_Environment $env, $context)
|
||||||
|
{
|
||||||
|
if (!$env->isDebug()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
$count = func_num_args();
|
||||||
|
if (2 === $count) {
|
||||||
|
$vars = array();
|
||||||
|
foreach ($context as $key => $value) {
|
||||||
|
if (!$value instanceof Twig_Template) {
|
||||||
|
$vars[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var_dump($vars);
|
||||||
|
} else {
|
||||||
|
for ($i = 2; $i < $count; $i++) {
|
||||||
|
var_dump(func_get_arg($i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ob_get_clean();
|
||||||
|
}
|
||||||
106
vendor/Twig/Extension/Escaper.php
vendored
Normal file
106
vendor/Twig/Extension/Escaper.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Extension_Escaper extends Twig_Extension
|
||||||
|
{
|
||||||
|
protected $defaultStrategy;
|
||||||
|
|
||||||
|
public function __construct($defaultStrategy = 'html')
|
||||||
|
{
|
||||||
|
$this->setDefaultStrategy($defaultStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the token parser instances to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
||||||
|
*/
|
||||||
|
public function getTokenParsers()
|
||||||
|
{
|
||||||
|
return array(new Twig_TokenParser_AutoEscape());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node visitor instances to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of Twig_NodeVisitorInterface instances
|
||||||
|
*/
|
||||||
|
public function getNodeVisitors()
|
||||||
|
{
|
||||||
|
return array(new Twig_NodeVisitor_Escaper());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of filters to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of filters
|
||||||
|
*/
|
||||||
|
public function getFilters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'raw' => new Twig_Filter_Function('twig_raw_filter', array('is_safe' => array('all'))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default strategy to use when not defined by the user.
|
||||||
|
*
|
||||||
|
* The strategy can be a valid PHP callback that takes the template
|
||||||
|
* "filename" as an argument and returns the strategy to use.
|
||||||
|
*
|
||||||
|
* @param mixed $defaultStrategy An escaping strategy
|
||||||
|
*/
|
||||||
|
public function setDefaultStrategy($defaultStrategy)
|
||||||
|
{
|
||||||
|
// for BC
|
||||||
|
if (true === $defaultStrategy) {
|
||||||
|
$defaultStrategy = 'html';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->defaultStrategy = $defaultStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default strategy to use when not defined by the user.
|
||||||
|
*
|
||||||
|
* @param string $filename The template "filename"
|
||||||
|
*
|
||||||
|
* @return string The default strategy to use for the template
|
||||||
|
*/
|
||||||
|
public function getDefaultStrategy($filename)
|
||||||
|
{
|
||||||
|
if (is_callable($this->defaultStrategy)) {
|
||||||
|
return call_user_func($this->defaultStrategy, $filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->defaultStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the extension.
|
||||||
|
*
|
||||||
|
* @return string The extension name
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'escaper';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a variable as being safe.
|
||||||
|
*
|
||||||
|
* @param string $string A PHP variable
|
||||||
|
*/
|
||||||
|
function twig_raw_filter($string)
|
||||||
|
{
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
35
vendor/Twig/Extension/Optimizer.php
vendored
Normal file
35
vendor/Twig/Extension/Optimizer.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Extension_Optimizer extends Twig_Extension
|
||||||
|
{
|
||||||
|
protected $optimizers;
|
||||||
|
|
||||||
|
public function __construct($optimizers = -1)
|
||||||
|
{
|
||||||
|
$this->optimizers = $optimizers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getNodeVisitors()
|
||||||
|
{
|
||||||
|
return array(new Twig_NodeVisitor_Optimizer($this->optimizers));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'optimizer';
|
||||||
|
}
|
||||||
|
}
|
||||||
112
vendor/Twig/Extension/Sandbox.php
vendored
Normal file
112
vendor/Twig/Extension/Sandbox.php
vendored
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Extension_Sandbox extends Twig_Extension
|
||||||
|
{
|
||||||
|
protected $sandboxedGlobally;
|
||||||
|
protected $sandboxed;
|
||||||
|
protected $policy;
|
||||||
|
|
||||||
|
public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
|
||||||
|
{
|
||||||
|
$this->policy = $policy;
|
||||||
|
$this->sandboxedGlobally = $sandboxed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the token parser instances to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
||||||
|
*/
|
||||||
|
public function getTokenParsers()
|
||||||
|
{
|
||||||
|
return array(new Twig_TokenParser_Sandbox());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node visitor instances to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of Twig_NodeVisitorInterface instances
|
||||||
|
*/
|
||||||
|
public function getNodeVisitors()
|
||||||
|
{
|
||||||
|
return array(new Twig_NodeVisitor_Sandbox());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enableSandbox()
|
||||||
|
{
|
||||||
|
$this->sandboxed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disableSandbox()
|
||||||
|
{
|
||||||
|
$this->sandboxed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isSandboxed()
|
||||||
|
{
|
||||||
|
return $this->sandboxedGlobally || $this->sandboxed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isSandboxedGlobally()
|
||||||
|
{
|
||||||
|
return $this->sandboxedGlobally;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy)
|
||||||
|
{
|
||||||
|
$this->policy = $policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSecurityPolicy()
|
||||||
|
{
|
||||||
|
return $this->policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkSecurity($tags, $filters, $functions)
|
||||||
|
{
|
||||||
|
if ($this->isSandboxed()) {
|
||||||
|
$this->policy->checkSecurity($tags, $filters, $functions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkMethodAllowed($obj, $method)
|
||||||
|
{
|
||||||
|
if ($this->isSandboxed()) {
|
||||||
|
$this->policy->checkMethodAllowed($obj, $method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkPropertyAllowed($obj, $method)
|
||||||
|
{
|
||||||
|
if ($this->isSandboxed()) {
|
||||||
|
$this->policy->checkPropertyAllowed($obj, $method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ensureToStringAllowed($obj)
|
||||||
|
{
|
||||||
|
if (is_object($obj)) {
|
||||||
|
$this->policy->checkMethodAllowed($obj, '__toString');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the extension.
|
||||||
|
*
|
||||||
|
* @return string The extension name
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'sandbox';
|
||||||
|
}
|
||||||
|
}
|
||||||
84
vendor/Twig/ExtensionInterface.php
vendored
Normal file
84
vendor/Twig/ExtensionInterface.php
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface implemented by extension classes.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
interface Twig_ExtensionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes the runtime environment.
|
||||||
|
*
|
||||||
|
* This is where you can load some file that contains filter functions for instance.
|
||||||
|
*
|
||||||
|
* @param Twig_Environment $environment The current Twig_Environment instance
|
||||||
|
*/
|
||||||
|
function initRuntime(Twig_Environment $environment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the token parser instances to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
||||||
|
*/
|
||||||
|
function getTokenParsers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node visitor instances to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of Twig_NodeVisitorInterface instances
|
||||||
|
*/
|
||||||
|
function getNodeVisitors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of filters to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of filters
|
||||||
|
*/
|
||||||
|
function getFilters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of tests to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of tests
|
||||||
|
*/
|
||||||
|
function getTests();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of functions to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of functions
|
||||||
|
*/
|
||||||
|
function getFunctions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of operators to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of operators
|
||||||
|
*/
|
||||||
|
function getOperators();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of global variables to add to the existing list.
|
||||||
|
*
|
||||||
|
* @return array An array of global variables
|
||||||
|
*/
|
||||||
|
function getGlobals();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the extension.
|
||||||
|
*
|
||||||
|
* @return string The extension name
|
||||||
|
*/
|
||||||
|
function getName();
|
||||||
|
}
|
||||||
75
vendor/Twig/Filter.php
vendored
Normal file
75
vendor/Twig/Filter.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a template filter.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
abstract class Twig_Filter implements Twig_FilterInterface
|
||||||
|
{
|
||||||
|
protected $options;
|
||||||
|
protected $arguments = array();
|
||||||
|
|
||||||
|
public function __construct(array $options = array())
|
||||||
|
{
|
||||||
|
$this->options = array_merge(array(
|
||||||
|
'needs_environment' => false,
|
||||||
|
'needs_context' => false,
|
||||||
|
'pre_escape' => null,
|
||||||
|
'preserves_safety' => null,
|
||||||
|
), $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setArguments($arguments)
|
||||||
|
{
|
||||||
|
$this->arguments = $arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getArguments()
|
||||||
|
{
|
||||||
|
return $this->arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function needsEnvironment()
|
||||||
|
{
|
||||||
|
return $this->options['needs_environment'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function needsContext()
|
||||||
|
{
|
||||||
|
return $this->options['needs_context'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSafe(Twig_Node $filterArgs)
|
||||||
|
{
|
||||||
|
if (isset($this->options['is_safe'])) {
|
||||||
|
return $this->options['is_safe'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->options['is_safe_callback'])) {
|
||||||
|
return call_user_func($this->options['is_safe_callback'], $filterArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreservesSafety()
|
||||||
|
{
|
||||||
|
return $this->options['preserves_safety'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPreEscape()
|
||||||
|
{
|
||||||
|
return $this->options['pre_escape'];
|
||||||
|
}
|
||||||
|
}
|
||||||
33
vendor/Twig/Filter/Function.php
vendored
Normal file
33
vendor/Twig/Filter/Function.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a function template filter.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Filter_Function extends Twig_Filter
|
||||||
|
{
|
||||||
|
protected $function;
|
||||||
|
|
||||||
|
public function __construct($function, array $options = array())
|
||||||
|
{
|
||||||
|
parent::__construct($options);
|
||||||
|
|
||||||
|
$this->function = $function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
return $this->function;
|
||||||
|
}
|
||||||
|
}
|
||||||
34
vendor/Twig/Filter/Method.php
vendored
Normal file
34
vendor/Twig/Filter/Method.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a method template filter.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Filter_Method extends Twig_Filter
|
||||||
|
{
|
||||||
|
protected $extension, $method;
|
||||||
|
|
||||||
|
public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
|
||||||
|
{
|
||||||
|
parent::__construct($options);
|
||||||
|
|
||||||
|
$this->extension = $extension;
|
||||||
|
$this->method = $method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
vendor/Twig/Filter/Node.php
vendored
Normal file
37
vendor/Twig/Filter/Node.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2011 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a template filter as a node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Filter_Node extends Twig_Filter
|
||||||
|
{
|
||||||
|
protected $class;
|
||||||
|
|
||||||
|
public function __construct($class, array $options = array())
|
||||||
|
{
|
||||||
|
parent::__construct($options);
|
||||||
|
|
||||||
|
$this->class = $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClass()
|
||||||
|
{
|
||||||
|
return $this->class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
40
vendor/Twig/FilterInterface.php
vendored
Normal file
40
vendor/Twig/FilterInterface.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a template filter.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
interface Twig_FilterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles a filter.
|
||||||
|
*
|
||||||
|
* @return string The PHP code for the filter
|
||||||
|
*/
|
||||||
|
function compile();
|
||||||
|
|
||||||
|
function needsEnvironment();
|
||||||
|
|
||||||
|
function needsContext();
|
||||||
|
|
||||||
|
function getSafe(Twig_Node $filterArgs);
|
||||||
|
|
||||||
|
function getPreservesSafety();
|
||||||
|
|
||||||
|
function getPreEscape();
|
||||||
|
|
||||||
|
function setArguments($arguments);
|
||||||
|
|
||||||
|
function getArguments();
|
||||||
|
}
|
||||||
63
vendor/Twig/Function.php
vendored
Normal file
63
vendor/Twig/Function.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a template function.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
abstract class Twig_Function implements Twig_FunctionInterface
|
||||||
|
{
|
||||||
|
protected $options;
|
||||||
|
protected $arguments = array();
|
||||||
|
|
||||||
|
public function __construct(array $options = array())
|
||||||
|
{
|
||||||
|
$this->options = array_merge(array(
|
||||||
|
'needs_environment' => false,
|
||||||
|
'needs_context' => false,
|
||||||
|
), $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setArguments($arguments)
|
||||||
|
{
|
||||||
|
$this->arguments = $arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getArguments()
|
||||||
|
{
|
||||||
|
return $this->arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function needsEnvironment()
|
||||||
|
{
|
||||||
|
return $this->options['needs_environment'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function needsContext()
|
||||||
|
{
|
||||||
|
return $this->options['needs_context'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSafe(Twig_Node $functionArgs)
|
||||||
|
{
|
||||||
|
if (isset($this->options['is_safe'])) {
|
||||||
|
return $this->options['is_safe'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->options['is_safe_callback'])) {
|
||||||
|
return call_user_func($this->options['is_safe_callback'], $functionArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
||||||
34
vendor/Twig/Function/Function.php
vendored
Normal file
34
vendor/Twig/Function/Function.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2010 Arnaud Le Blanc
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a function template function.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||||
|
*/
|
||||||
|
class Twig_Function_Function extends Twig_Function
|
||||||
|
{
|
||||||
|
protected $function;
|
||||||
|
|
||||||
|
public function __construct($function, array $options = array())
|
||||||
|
{
|
||||||
|
parent::__construct($options);
|
||||||
|
|
||||||
|
$this->function = $function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
return $this->function;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
vendor/Twig/Function/Method.php
vendored
Normal file
35
vendor/Twig/Function/Method.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2010 Arnaud Le Blanc
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a method template function.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||||
|
*/
|
||||||
|
class Twig_Function_Method extends Twig_Function
|
||||||
|
{
|
||||||
|
protected $extension, $method;
|
||||||
|
|
||||||
|
public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
|
||||||
|
{
|
||||||
|
parent::__construct($options);
|
||||||
|
|
||||||
|
$this->extension = $extension;
|
||||||
|
$this->method = $method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
vendor/Twig/Function/Node.php
vendored
Normal file
37
vendor/Twig/Function/Node.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2011 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a template function as a node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Function_Node extends Twig_Filter
|
||||||
|
{
|
||||||
|
protected $class;
|
||||||
|
|
||||||
|
public function __construct($class, array $options = array())
|
||||||
|
{
|
||||||
|
parent::__construct($options);
|
||||||
|
|
||||||
|
$this->class = $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClass()
|
||||||
|
{
|
||||||
|
return $this->class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
37
vendor/Twig/FunctionInterface.php
vendored
Normal file
37
vendor/Twig/FunctionInterface.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
* (c) 2010 Arnaud Le Blanc
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a template function.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||||
|
*/
|
||||||
|
interface Twig_FunctionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles a function.
|
||||||
|
*
|
||||||
|
* @return string The PHP code for the function
|
||||||
|
*/
|
||||||
|
function compile();
|
||||||
|
|
||||||
|
function needsEnvironment();
|
||||||
|
|
||||||
|
function needsContext();
|
||||||
|
|
||||||
|
function getSafe(Twig_Node $filterArgs);
|
||||||
|
|
||||||
|
function setArguments($arguments);
|
||||||
|
|
||||||
|
function getArguments();
|
||||||
|
}
|
||||||
406
vendor/Twig/Lexer.php
vendored
Normal file
406
vendor/Twig/Lexer.php
vendored
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lexes a template string.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Lexer implements Twig_LexerInterface
|
||||||
|
{
|
||||||
|
protected $tokens;
|
||||||
|
protected $code;
|
||||||
|
protected $cursor;
|
||||||
|
protected $lineno;
|
||||||
|
protected $end;
|
||||||
|
protected $state;
|
||||||
|
protected $states;
|
||||||
|
protected $brackets;
|
||||||
|
protected $env;
|
||||||
|
protected $filename;
|
||||||
|
protected $options;
|
||||||
|
protected $regexes;
|
||||||
|
|
||||||
|
const STATE_DATA = 0;
|
||||||
|
const STATE_BLOCK = 1;
|
||||||
|
const STATE_VAR = 2;
|
||||||
|
const STATE_STRING = 3;
|
||||||
|
const STATE_INTERPOLATION = 4;
|
||||||
|
|
||||||
|
const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
|
||||||
|
const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A';
|
||||||
|
const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
|
||||||
|
const REGEX_DQ_STRING_DELIM = '/"/A';
|
||||||
|
const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
|
||||||
|
const PUNCTUATION = '()[]{}?:.,|';
|
||||||
|
|
||||||
|
public function __construct(Twig_Environment $env, array $options = array())
|
||||||
|
{
|
||||||
|
$this->env = $env;
|
||||||
|
|
||||||
|
$this->options = array_merge(array(
|
||||||
|
'tag_comment' => array('{#', '#}'),
|
||||||
|
'tag_block' => array('{%', '%}'),
|
||||||
|
'tag_variable' => array('{{', '}}'),
|
||||||
|
'whitespace_trim' => '-',
|
||||||
|
'interpolation' => array('#{', '}'),
|
||||||
|
), $options);
|
||||||
|
|
||||||
|
$this->regexes = array(
|
||||||
|
'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
|
||||||
|
'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
|
||||||
|
'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*endraw\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
|
||||||
|
'operator' => $this->getOperatorRegex(),
|
||||||
|
'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
|
||||||
|
'lex_block_raw' => '/\s*raw\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
|
||||||
|
'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
|
||||||
|
'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
|
||||||
|
'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
|
||||||
|
'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenizes a source code.
|
||||||
|
*
|
||||||
|
* @param string $code The source code
|
||||||
|
* @param string $filename A unique identifier for the source code
|
||||||
|
*
|
||||||
|
* @return Twig_TokenStream A token stream instance
|
||||||
|
*/
|
||||||
|
public function tokenize($code, $filename = null)
|
||||||
|
{
|
||||||
|
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
|
||||||
|
$mbEncoding = mb_internal_encoding();
|
||||||
|
mb_internal_encoding('ASCII');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->code = str_replace(array("\r\n", "\r"), "\n", $code);
|
||||||
|
$this->filename = $filename;
|
||||||
|
$this->cursor = 0;
|
||||||
|
$this->lineno = 1;
|
||||||
|
$this->end = strlen($this->code);
|
||||||
|
$this->tokens = array();
|
||||||
|
$this->state = self::STATE_DATA;
|
||||||
|
$this->states = array();
|
||||||
|
$this->brackets = array();
|
||||||
|
$this->position = -1;
|
||||||
|
|
||||||
|
// find all token starts in one go
|
||||||
|
preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, PREG_OFFSET_CAPTURE);
|
||||||
|
$this->positions = $matches;
|
||||||
|
|
||||||
|
while ($this->cursor < $this->end) {
|
||||||
|
// dispatch to the lexing functions depending
|
||||||
|
// on the current state
|
||||||
|
switch ($this->state) {
|
||||||
|
case self::STATE_DATA:
|
||||||
|
$this->lexData();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case self::STATE_BLOCK:
|
||||||
|
$this->lexBlock();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case self::STATE_VAR:
|
||||||
|
$this->lexVar();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case self::STATE_STRING:
|
||||||
|
$this->lexString();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case self::STATE_INTERPOLATION:
|
||||||
|
$this->lexInterpolation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pushToken(Twig_Token::EOF_TYPE);
|
||||||
|
|
||||||
|
if (!empty($this->brackets)) {
|
||||||
|
list($expect, $lineno) = array_pop($this->brackets);
|
||||||
|
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($mbEncoding)) {
|
||||||
|
mb_internal_encoding($mbEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Twig_TokenStream($this->tokens, $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lexData()
|
||||||
|
{
|
||||||
|
// if no matches are left we return the rest of the template as simple text token
|
||||||
|
if ($this->position == count($this->positions[0]) - 1) {
|
||||||
|
$this->pushToken(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor));
|
||||||
|
$this->cursor = $this->end;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the first token after the current cursor
|
||||||
|
$position = $this->positions[0][++$this->position];
|
||||||
|
while ($position[1] < $this->cursor) {
|
||||||
|
if ($this->position == count($this->positions[0]) - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$position = $this->positions[0][++$this->position];
|
||||||
|
}
|
||||||
|
|
||||||
|
// push the template text first
|
||||||
|
$text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor);
|
||||||
|
if (isset($this->positions[2][$this->position][0])) {
|
||||||
|
$text = rtrim($text);
|
||||||
|
}
|
||||||
|
$this->pushToken(Twig_Token::TEXT_TYPE, $text);
|
||||||
|
$this->moveCursor($textContent.$position[0]);
|
||||||
|
|
||||||
|
switch ($this->positions[1][$this->position][0]) {
|
||||||
|
case $this->options['tag_comment'][0]:
|
||||||
|
$this->lexComment();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case $this->options['tag_block'][0]:
|
||||||
|
// raw data?
|
||||||
|
if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
$this->lexRawData();
|
||||||
|
// {% line \d+ %}
|
||||||
|
} elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
$this->lineno = (int) $match[1];
|
||||||
|
} else {
|
||||||
|
$this->pushToken(Twig_Token::BLOCK_START_TYPE);
|
||||||
|
$this->pushState(self::STATE_BLOCK);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case $this->options['tag_variable'][0]:
|
||||||
|
$this->pushToken(Twig_Token::VAR_START_TYPE);
|
||||||
|
$this->pushState(self::STATE_VAR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lexBlock()
|
||||||
|
{
|
||||||
|
if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->pushToken(Twig_Token::BLOCK_END_TYPE);
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
$this->popState();
|
||||||
|
} else {
|
||||||
|
$this->lexExpression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lexVar()
|
||||||
|
{
|
||||||
|
if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->pushToken(Twig_Token::VAR_END_TYPE);
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
$this->popState();
|
||||||
|
} else {
|
||||||
|
$this->lexExpression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lexExpression()
|
||||||
|
{
|
||||||
|
// whitespace
|
||||||
|
if (preg_match('/\s+/A', $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
|
||||||
|
if ($this->cursor >= $this->end) {
|
||||||
|
throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s"', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->lineno, $this->filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// operators
|
||||||
|
if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->pushToken(Twig_Token::OPERATOR_TYPE, $match[0]);
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
}
|
||||||
|
// names
|
||||||
|
elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->pushToken(Twig_Token::NAME_TYPE, $match[0]);
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
}
|
||||||
|
// numbers
|
||||||
|
elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) {
|
||||||
|
$number = (float) $match[0]; // floats
|
||||||
|
if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) {
|
||||||
|
$number = (int) $match[0]; // integers lower than the maximum
|
||||||
|
}
|
||||||
|
$this->pushToken(Twig_Token::NUMBER_TYPE, $number);
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
}
|
||||||
|
// punctuation
|
||||||
|
elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) {
|
||||||
|
// opening bracket
|
||||||
|
if (false !== strpos('([{', $this->code[$this->cursor])) {
|
||||||
|
$this->brackets[] = array($this->code[$this->cursor], $this->lineno);
|
||||||
|
}
|
||||||
|
// closing bracket
|
||||||
|
elseif (false !== strpos(')]}', $this->code[$this->cursor])) {
|
||||||
|
if (empty($this->brackets)) {
|
||||||
|
throw new Twig_Error_Syntax(sprintf('Unexpected "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($expect, $lineno) = array_pop($this->brackets);
|
||||||
|
if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) {
|
||||||
|
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pushToken(Twig_Token::PUNCTUATION_TYPE, $this->code[$this->cursor]);
|
||||||
|
++$this->cursor;
|
||||||
|
}
|
||||||
|
// strings
|
||||||
|
elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->pushToken(Twig_Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)));
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
}
|
||||||
|
// opening double quoted string
|
||||||
|
elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->brackets[] = array('"', $this->lineno);
|
||||||
|
$this->pushState(self::STATE_STRING);
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
}
|
||||||
|
// unlexable
|
||||||
|
else {
|
||||||
|
throw new Twig_Error_Syntax(sprintf('Unexpected character "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lexRawData()
|
||||||
|
{
|
||||||
|
if (!preg_match($this->regexes['lex_raw_data'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
||||||
|
throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "block"'), $this->lineno, $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
|
||||||
|
$this->moveCursor($text.$match[0][0]);
|
||||||
|
|
||||||
|
if (false !== strpos($match[1][0], $this->options['whitespace_trim'])) {
|
||||||
|
$text = rtrim($text);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pushToken(Twig_Token::TEXT_TYPE, $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lexComment()
|
||||||
|
{
|
||||||
|
if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
||||||
|
throw new Twig_Error_Syntax('Unclosed comment', $this->lineno, $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lexString()
|
||||||
|
{
|
||||||
|
if (preg_match($this->regexes['interpolation_start'], $this->code, $match, null, $this->cursor)) {
|
||||||
|
$this->brackets[] = array($this->options['interpolation'][0], $this->lineno);
|
||||||
|
$this->pushToken(Twig_Token::INTERPOLATION_START_TYPE);
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
$this->pushState(self::STATE_INTERPOLATION);
|
||||||
|
|
||||||
|
} elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) {
|
||||||
|
$this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0]));
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
|
||||||
|
} elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
|
||||||
|
|
||||||
|
list($expect, $lineno) = array_pop($this->brackets);
|
||||||
|
if ($this->code[$this->cursor] != '"') {
|
||||||
|
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->popState();
|
||||||
|
++$this->cursor;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lexInterpolation()
|
||||||
|
{
|
||||||
|
$bracket = end($this->brackets);
|
||||||
|
if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, null, $this->cursor)) {
|
||||||
|
array_pop($this->brackets);
|
||||||
|
$this->pushToken(Twig_Token::INTERPOLATION_END_TYPE);
|
||||||
|
$this->moveCursor($match[0]);
|
||||||
|
$this->popState();
|
||||||
|
} else {
|
||||||
|
$this->lexExpression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pushToken($type, $value = '')
|
||||||
|
{
|
||||||
|
// do not push empty text tokens
|
||||||
|
if (Twig_Token::TEXT_TYPE === $type && '' === $value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->tokens[] = new Twig_Token($type, $value, $this->lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function moveCursor($text)
|
||||||
|
{
|
||||||
|
$this->cursor += strlen($text);
|
||||||
|
$this->lineno += substr_count($text, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getOperatorRegex()
|
||||||
|
{
|
||||||
|
$operators = array_merge(
|
||||||
|
array('='),
|
||||||
|
array_keys($this->env->getUnaryOperators()),
|
||||||
|
array_keys($this->env->getBinaryOperators())
|
||||||
|
);
|
||||||
|
|
||||||
|
$operators = array_combine($operators, array_map('strlen', $operators));
|
||||||
|
arsort($operators);
|
||||||
|
|
||||||
|
$regex = array();
|
||||||
|
foreach ($operators as $operator => $length) {
|
||||||
|
// an operator that ends with a character must be followed by
|
||||||
|
// a whitespace or a parenthesis
|
||||||
|
if (ctype_alpha($operator[$length - 1])) {
|
||||||
|
$regex[] = preg_quote($operator, '/').'(?=[\s()])';
|
||||||
|
} else {
|
||||||
|
$regex[] = preg_quote($operator, '/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '/'.implode('|', $regex).'/A';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pushState($state)
|
||||||
|
{
|
||||||
|
$this->states[] = $this->state;
|
||||||
|
$this->state = $state;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function popState()
|
||||||
|
{
|
||||||
|
if (0 === count($this->states)) {
|
||||||
|
throw new Exception('Cannot pop state without a previous state');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->state = array_pop($this->states);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
vendor/Twig/LexerInterface.php
vendored
Normal file
29
vendor/Twig/LexerInterface.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface implemented by lexer classes.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
interface Twig_LexerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Tokenizes a source code.
|
||||||
|
*
|
||||||
|
* @param string $code The source code
|
||||||
|
* @param string $filename A unique identifier for the source code
|
||||||
|
*
|
||||||
|
* @return Twig_TokenStream A token stream instance
|
||||||
|
*/
|
||||||
|
function tokenize($code, $filename = null);
|
||||||
|
}
|
||||||
102
vendor/Twig/Loader/Array.php
vendored
Normal file
102
vendor/Twig/Loader/Array.php
vendored
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a template from an array.
|
||||||
|
*
|
||||||
|
* When using this loader with a cache mechanism, you should know that a new cache
|
||||||
|
* key is generated each time a template content "changes" (the cache key being the
|
||||||
|
* source code of the template). If you don't want to see your cache grows out of
|
||||||
|
* control, you need to take care of clearing the old cache file by yourself.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Loader_Array implements Twig_LoaderInterface
|
||||||
|
{
|
||||||
|
protected $templates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param array $templates An array of templates (keys are the names, and values are the source code)
|
||||||
|
*
|
||||||
|
* @see Twig_Loader
|
||||||
|
*/
|
||||||
|
public function __construct(array $templates)
|
||||||
|
{
|
||||||
|
$this->templates = array();
|
||||||
|
foreach ($templates as $name => $template) {
|
||||||
|
$this->templates[$name] = $template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds or overrides a template.
|
||||||
|
*
|
||||||
|
* @param string $name The template name
|
||||||
|
* @param string $template The template source
|
||||||
|
*/
|
||||||
|
public function setTemplate($name, $template)
|
||||||
|
{
|
||||||
|
$this->templates[(string) $name] = $template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the source code of a template, given its name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The template source code
|
||||||
|
*/
|
||||||
|
public function getSource($name)
|
||||||
|
{
|
||||||
|
$name = (string) $name;
|
||||||
|
if (!isset($this->templates[$name])) {
|
||||||
|
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->templates[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache key to use for the cache for a given template name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The cache key
|
||||||
|
*/
|
||||||
|
public function getCacheKey($name)
|
||||||
|
{
|
||||||
|
$name = (string) $name;
|
||||||
|
if (!isset($this->templates[$name])) {
|
||||||
|
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->templates[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the template is still fresh.
|
||||||
|
*
|
||||||
|
* @param string $name The template name
|
||||||
|
* @param timestamp $time The last modification time of the cached template
|
||||||
|
*/
|
||||||
|
public function isFresh($name, $time)
|
||||||
|
{
|
||||||
|
$name = (string) $name;
|
||||||
|
if (!isset($this->templates[$name])) {
|
||||||
|
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
100
vendor/Twig/Loader/Chain.php
vendored
Normal file
100
vendor/Twig/Loader/Chain.php
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2011 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads templates from other loaders.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Loader_Chain implements Twig_LoaderInterface
|
||||||
|
{
|
||||||
|
protected $loaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param Twig_LoaderInterface[] $loaders An array of loader instances
|
||||||
|
*/
|
||||||
|
public function __construct(array $loaders = array())
|
||||||
|
{
|
||||||
|
$this->loaders = array();
|
||||||
|
foreach ($loaders as $loader) {
|
||||||
|
$this->addLoader($loader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a loader instance.
|
||||||
|
*
|
||||||
|
* @param Twig_LoaderInterface $loader A Loader instance
|
||||||
|
*/
|
||||||
|
public function addLoader(Twig_LoaderInterface $loader)
|
||||||
|
{
|
||||||
|
$this->loaders[] = $loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the source code of a template, given its name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The template source code
|
||||||
|
*/
|
||||||
|
public function getSource($name)
|
||||||
|
{
|
||||||
|
foreach ($this->loaders as $loader) {
|
||||||
|
try {
|
||||||
|
return $loader->getSource($name);
|
||||||
|
} catch (Twig_Error_Loader $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache key to use for the cache for a given template name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The cache key
|
||||||
|
*/
|
||||||
|
public function getCacheKey($name)
|
||||||
|
{
|
||||||
|
foreach ($this->loaders as $loader) {
|
||||||
|
try {
|
||||||
|
return $loader->getCacheKey($name);
|
||||||
|
} catch (Twig_Error_Loader $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the template is still fresh.
|
||||||
|
*
|
||||||
|
* @param string $name The template name
|
||||||
|
* @param timestamp $time The last modification time of the cached template
|
||||||
|
*/
|
||||||
|
public function isFresh($name, $time)
|
||||||
|
{
|
||||||
|
foreach ($this->loaders as $loader) {
|
||||||
|
try {
|
||||||
|
return $loader->isFresh($name, $time);
|
||||||
|
} catch (Twig_Error_Loader $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
||||||
|
}
|
||||||
|
}
|
||||||
152
vendor/Twig/Loader/Filesystem.php
vendored
Normal file
152
vendor/Twig/Loader/Filesystem.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads template from the filesystem.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Loader_Filesystem implements Twig_LoaderInterface
|
||||||
|
{
|
||||||
|
protected $paths;
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param string|array $paths A path or an array of paths where to look for templates
|
||||||
|
*/
|
||||||
|
public function __construct($paths)
|
||||||
|
{
|
||||||
|
$this->setPaths($paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the paths to the templates.
|
||||||
|
*
|
||||||
|
* @return array The array of paths where to look for templates
|
||||||
|
*/
|
||||||
|
public function getPaths()
|
||||||
|
{
|
||||||
|
return $this->paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the paths where templates are stored.
|
||||||
|
*
|
||||||
|
* @param string|array $paths A path or an array of paths where to look for templates
|
||||||
|
*/
|
||||||
|
public function setPaths($paths)
|
||||||
|
{
|
||||||
|
if (!is_array($paths)) {
|
||||||
|
$paths = array($paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->paths = array();
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
$this->addPath($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a path where templates are stored.
|
||||||
|
*
|
||||||
|
* @param string $path A path where to look for templates
|
||||||
|
*/
|
||||||
|
public function addPath($path)
|
||||||
|
{
|
||||||
|
// invalidate the cache
|
||||||
|
$this->cache = array();
|
||||||
|
|
||||||
|
if (!is_dir($path)) {
|
||||||
|
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->paths[] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the source code of a template, given its name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The template source code
|
||||||
|
*/
|
||||||
|
public function getSource($name)
|
||||||
|
{
|
||||||
|
return file_get_contents($this->findTemplate($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache key to use for the cache for a given template name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The cache key
|
||||||
|
*/
|
||||||
|
public function getCacheKey($name)
|
||||||
|
{
|
||||||
|
return $this->findTemplate($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the template is still fresh.
|
||||||
|
*
|
||||||
|
* @param string $name The template name
|
||||||
|
* @param timestamp $time The last modification time of the cached template
|
||||||
|
*/
|
||||||
|
public function isFresh($name, $time)
|
||||||
|
{
|
||||||
|
return filemtime($this->findTemplate($name)) <= $time;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function findTemplate($name)
|
||||||
|
{
|
||||||
|
// normalize name
|
||||||
|
$name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));
|
||||||
|
|
||||||
|
if (isset($this->cache[$name])) {
|
||||||
|
return $this->cache[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->validateName($name);
|
||||||
|
|
||||||
|
foreach ($this->paths as $path) {
|
||||||
|
if (is_file($path.'/'.$name)) {
|
||||||
|
return $this->cache[$name] = $path.'/'.$name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function validateName($name)
|
||||||
|
{
|
||||||
|
if (false !== strpos($name, "\0")) {
|
||||||
|
throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts = explode('/', $name);
|
||||||
|
$level = 0;
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
if ('..' === $part) {
|
||||||
|
--$level;
|
||||||
|
} elseif ('.' !== $part) {
|
||||||
|
++$level;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($level < 0) {
|
||||||
|
throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
vendor/Twig/Loader/String.php
vendored
Normal file
59
vendor/Twig/Loader/String.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a template from a string.
|
||||||
|
*
|
||||||
|
* When using this loader with a cache mechanism, you should know that a new cache
|
||||||
|
* key is generated each time a template content "changes" (the cache key being the
|
||||||
|
* source code of the template). If you don't want to see your cache grows out of
|
||||||
|
* control, you need to take care of clearing the old cache file by yourself.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Loader_String implements Twig_LoaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Gets the source code of a template, given its name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The template source code
|
||||||
|
*/
|
||||||
|
public function getSource($name)
|
||||||
|
{
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache key to use for the cache for a given template name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The cache key
|
||||||
|
*/
|
||||||
|
public function getCacheKey($name)
|
||||||
|
{
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the template is still fresh.
|
||||||
|
*
|
||||||
|
* @param string $name The template name
|
||||||
|
* @param timestamp $time The last modification time of the cached template
|
||||||
|
*/
|
||||||
|
public function isFresh($name, $time)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
vendor/Twig/LoaderInterface.php
vendored
Normal file
53
vendor/Twig/LoaderInterface.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface all loaders must implement.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
interface Twig_LoaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Gets the source code of a template, given its name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The template source code
|
||||||
|
*
|
||||||
|
* @throws Twig_Error_Loader When $name is not found
|
||||||
|
*/
|
||||||
|
function getSource($name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache key to use for the cache for a given template name.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the template to load
|
||||||
|
*
|
||||||
|
* @return string The cache key
|
||||||
|
*
|
||||||
|
* @throws Twig_Error_Loader When $name is not found
|
||||||
|
*/
|
||||||
|
function getCacheKey($name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the template is still fresh.
|
||||||
|
*
|
||||||
|
* @param string $name The template name
|
||||||
|
* @param timestamp $time The last modification time of the cached template
|
||||||
|
*
|
||||||
|
* @return Boolean true if the template is fresh, false otherwise
|
||||||
|
*
|
||||||
|
* @throws Twig_Error_Loader When $name is not found
|
||||||
|
*/
|
||||||
|
function isFresh($name, $time);
|
||||||
|
}
|
||||||
38
vendor/Twig/Markup.php
vendored
Normal file
38
vendor/Twig/Markup.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a content as safe.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Markup implements Countable
|
||||||
|
{
|
||||||
|
protected $content;
|
||||||
|
protected $charset;
|
||||||
|
|
||||||
|
public function __construct($content, $charset)
|
||||||
|
{
|
||||||
|
$this->content = (string) $content;
|
||||||
|
$this->charset = $charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content);
|
||||||
|
}
|
||||||
|
}
|
||||||
227
vendor/Twig/Node.php
vendored
Normal file
227
vendor/Twig/Node.php
vendored
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a node in the AST.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node implements Twig_NodeInterface
|
||||||
|
{
|
||||||
|
protected $nodes;
|
||||||
|
protected $attributes;
|
||||||
|
protected $lineno;
|
||||||
|
protected $tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* The nodes are automatically made available as properties ($this->node).
|
||||||
|
* The attributes are automatically made available as array items ($this['name']).
|
||||||
|
*
|
||||||
|
* @param array $nodes An array of named nodes
|
||||||
|
* @param array $attributes An array of attributes (should not be nodes)
|
||||||
|
* @param integer $lineno The line number
|
||||||
|
* @param string $tag The tag name associated with the Node
|
||||||
|
*/
|
||||||
|
public function __construct(array $nodes = array(), array $attributes = array(), $lineno = 0, $tag = null)
|
||||||
|
{
|
||||||
|
$this->nodes = $nodes;
|
||||||
|
$this->attributes = $attributes;
|
||||||
|
$this->lineno = $lineno;
|
||||||
|
$this->tag = $tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
$attributes = array();
|
||||||
|
foreach ($this->attributes as $name => $value) {
|
||||||
|
$attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$repr = array(get_class($this).'('.implode(', ', $attributes));
|
||||||
|
|
||||||
|
if (count($this->nodes)) {
|
||||||
|
foreach ($this->nodes as $name => $node) {
|
||||||
|
$len = strlen($name) + 4;
|
||||||
|
$noderepr = array();
|
||||||
|
foreach (explode("\n", (string) $node) as $line) {
|
||||||
|
$noderepr[] = str_repeat(' ', $len).$line;
|
||||||
|
}
|
||||||
|
|
||||||
|
$repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$repr[] = ')';
|
||||||
|
} else {
|
||||||
|
$repr[0] .= ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $repr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toXml($asDom = false)
|
||||||
|
{
|
||||||
|
$dom = new DOMDocument('1.0', 'UTF-8');
|
||||||
|
$dom->formatOutput = true;
|
||||||
|
$dom->appendChild($xml = $dom->createElement('twig'));
|
||||||
|
|
||||||
|
$xml->appendChild($node = $dom->createElement('node'));
|
||||||
|
$node->setAttribute('class', get_class($this));
|
||||||
|
|
||||||
|
foreach ($this->attributes as $name => $value) {
|
||||||
|
$node->appendChild($attribute = $dom->createElement('attribute'));
|
||||||
|
$attribute->setAttribute('name', $name);
|
||||||
|
$attribute->appendChild($dom->createTextNode($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->nodes as $name => $n) {
|
||||||
|
if (null === $n) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$child = $n->toXml(true)->getElementsByTagName('node')->item(0);
|
||||||
|
$child = $dom->importNode($child, true);
|
||||||
|
$child->setAttribute('name', $name);
|
||||||
|
|
||||||
|
$node->appendChild($child);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $asDom ? $dom : $dom->saveXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
foreach ($this->nodes as $node) {
|
||||||
|
$node->compile($compiler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLine()
|
||||||
|
{
|
||||||
|
return $this->lineno;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNodeTag()
|
||||||
|
{
|
||||||
|
return $this->tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the attribute is defined.
|
||||||
|
*
|
||||||
|
* @param string The attribute name
|
||||||
|
*
|
||||||
|
* @return Boolean true if the attribute is defined, false otherwise
|
||||||
|
*/
|
||||||
|
public function hasAttribute($name)
|
||||||
|
{
|
||||||
|
return array_key_exists($name, $this->attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an attribute.
|
||||||
|
*
|
||||||
|
* @param string The attribute name
|
||||||
|
*
|
||||||
|
* @return mixed The attribute value
|
||||||
|
*/
|
||||||
|
public function getAttribute($name)
|
||||||
|
{
|
||||||
|
if (!array_key_exists($name, $this->attributes)) {
|
||||||
|
throw new Twig_Error_Runtime(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->attributes[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an attribute.
|
||||||
|
*
|
||||||
|
* @param string The attribute name
|
||||||
|
* @param mixed The attribute value
|
||||||
|
*/
|
||||||
|
public function setAttribute($name, $value)
|
||||||
|
{
|
||||||
|
$this->attributes[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an attribute.
|
||||||
|
*
|
||||||
|
* @param string The attribute name
|
||||||
|
*/
|
||||||
|
public function removeAttribute($name)
|
||||||
|
{
|
||||||
|
unset($this->attributes[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the node with the given identifier exists.
|
||||||
|
*
|
||||||
|
* @param string The node name
|
||||||
|
*
|
||||||
|
* @return Boolean true if the node with the given name exists, false otherwise
|
||||||
|
*/
|
||||||
|
public function hasNode($name)
|
||||||
|
{
|
||||||
|
return array_key_exists($name, $this->nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a node by name.
|
||||||
|
*
|
||||||
|
* @param string The node name
|
||||||
|
*
|
||||||
|
* @return Twig_Node A Twig_Node instance
|
||||||
|
*/
|
||||||
|
public function getNode($name)
|
||||||
|
{
|
||||||
|
if (!array_key_exists($name, $this->nodes)) {
|
||||||
|
throw new Twig_Error_Runtime(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->nodes[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a node.
|
||||||
|
*
|
||||||
|
* @param string The node name
|
||||||
|
* @param Twig_Node A Twig_Node instance
|
||||||
|
*/
|
||||||
|
public function setNode($name, $node = null)
|
||||||
|
{
|
||||||
|
$this->nodes[$name] = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a node by name.
|
||||||
|
*
|
||||||
|
* @param string The node name
|
||||||
|
*/
|
||||||
|
public function removeNode($name)
|
||||||
|
{
|
||||||
|
unset($this->nodes[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return count($this->nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return new ArrayIterator($this->nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
vendor/Twig/Node/AutoEscape.php
vendored
Normal file
40
vendor/Twig/Node/AutoEscape.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an autoescape node.
|
||||||
|
*
|
||||||
|
* The value is the escaping strategy (can be html, js, ...)
|
||||||
|
*
|
||||||
|
* The true value is equivalent to html.
|
||||||
|
*
|
||||||
|
* If autoescaping is disabled, then the value is false.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node_AutoEscape extends Twig_Node
|
||||||
|
{
|
||||||
|
public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
|
||||||
|
{
|
||||||
|
parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler->subcompile($this->getNode('body'));
|
||||||
|
}
|
||||||
|
}
|
||||||
45
vendor/Twig/Node/Block.php
vendored
Normal file
45
vendor/Twig/Node/Block.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a block node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node_Block extends Twig_Node
|
||||||
|
{
|
||||||
|
public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null)
|
||||||
|
{
|
||||||
|
parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->addDebugInfo($this)
|
||||||
|
->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n")
|
||||||
|
->indent()
|
||||||
|
;
|
||||||
|
|
||||||
|
$compiler
|
||||||
|
->subcompile($this->getNode('body'))
|
||||||
|
->outdent()
|
||||||
|
->write("}\n\n")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
vendor/Twig/Node/BlockReference.php
vendored
Normal file
38
vendor/Twig/Node/BlockReference.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a block call node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
|
||||||
|
{
|
||||||
|
public function __construct($name, $lineno, $tag = null)
|
||||||
|
{
|
||||||
|
parent::__construct(array(), array('name' => $name), $lineno, $tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->addDebugInfo($this)
|
||||||
|
->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
vendor/Twig/Node/Body.php
vendored
Normal file
20
vendor/Twig/Node/Body.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2011 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a body node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node_Body extends Twig_Node
|
||||||
|
{
|
||||||
|
}
|
||||||
39
vendor/Twig/Node/Do.php
vendored
Normal file
39
vendor/Twig/Node/Do.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2011 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a do node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node_Do extends Twig_Node
|
||||||
|
{
|
||||||
|
public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
|
||||||
|
{
|
||||||
|
parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->addDebugInfo($this)
|
||||||
|
->write('')
|
||||||
|
->subcompile($this->getNode('expr'))
|
||||||
|
->raw(";\n")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
vendor/Twig/Node/Embed.php
vendored
Normal file
39
vendor/Twig/Node/Embed.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2012 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an embed node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node_Embed extends Twig_Node_Include
|
||||||
|
{
|
||||||
|
// we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module)
|
||||||
|
public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
|
||||||
|
{
|
||||||
|
parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
|
||||||
|
|
||||||
|
$this->setAttribute('filename', $filename);
|
||||||
|
$this->setAttribute('index', $index);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addGetTemplate(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->write("\$this->env->loadTemplate(")
|
||||||
|
->string($this->getAttribute('filename'))
|
||||||
|
->raw(', ')
|
||||||
|
->string($this->getAttribute('index'))
|
||||||
|
->raw(")")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
vendor/Twig/Node/Expression.php
vendored
Normal file
21
vendor/Twig/Node/Expression.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class for all nodes that represents an expression.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
abstract class Twig_Node_Expression extends Twig_Node
|
||||||
|
{
|
||||||
|
}
|
||||||
86
vendor/Twig/Node/Expression/Array.php
vendored
Normal file
86
vendor/Twig/Node/Expression/Array.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Array extends Twig_Node_Expression
|
||||||
|
{
|
||||||
|
protected $index;
|
||||||
|
|
||||||
|
public function __construct(array $elements, $lineno)
|
||||||
|
{
|
||||||
|
parent::__construct($elements, array(), $lineno);
|
||||||
|
|
||||||
|
$this->index = -1;
|
||||||
|
foreach ($this->getKeyValuePairs() as $pair) {
|
||||||
|
if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) {
|
||||||
|
$this->index = $pair['key']->getAttribute('value');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getKeyValuePairs()
|
||||||
|
{
|
||||||
|
$pairs = array();
|
||||||
|
|
||||||
|
foreach (array_chunk($this->nodes, 2) as $pair) {
|
||||||
|
$pairs[] = array(
|
||||||
|
'key' => $pair[0],
|
||||||
|
'value' => $pair[1],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasElement(Twig_Node_Expression $key)
|
||||||
|
{
|
||||||
|
foreach ($this->getKeyValuePairs() as $pair) {
|
||||||
|
// we compare the string representation of the keys
|
||||||
|
// to avoid comparing the line numbers which are not relevant here.
|
||||||
|
if ((string) $key == (string) $pair['key']) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null)
|
||||||
|
{
|
||||||
|
if (null === $key) {
|
||||||
|
$key = new Twig_Node_Expression_Constant(++$this->index, $value->getLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($this->nodes, $key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler->raw('array(');
|
||||||
|
$first = true;
|
||||||
|
foreach ($this->getKeyValuePairs() as $pair) {
|
||||||
|
if (!$first) {
|
||||||
|
$compiler->raw(', ');
|
||||||
|
}
|
||||||
|
$first = false;
|
||||||
|
|
||||||
|
$compiler
|
||||||
|
->subcompile($pair['key'])
|
||||||
|
->raw(' => ')
|
||||||
|
->subcompile($pair['value'])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
$compiler->raw(')');
|
||||||
|
}
|
||||||
|
}
|
||||||
28
vendor/Twig/Node/Expression/AssignName.php
vendored
Normal file
28
vendor/Twig/Node/Expression/AssignName.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('$context[')
|
||||||
|
->string($this->getAttribute('name'))
|
||||||
|
->raw(']')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
vendor/Twig/Node/Expression/Binary.php
vendored
Normal file
40
vendor/Twig/Node/Expression/Binary.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
|
||||||
|
{
|
||||||
|
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
||||||
|
{
|
||||||
|
parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('(')
|
||||||
|
->subcompile($this->getNode('left'))
|
||||||
|
->raw(' ')
|
||||||
|
;
|
||||||
|
$this->operator($compiler);
|
||||||
|
$compiler
|
||||||
|
->raw(' ')
|
||||||
|
->subcompile($this->getNode('right'))
|
||||||
|
->raw(')')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public function operator(Twig_Compiler $compiler);
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/Add.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/Add.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('+');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/And.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/And.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('&&');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/BitwiseAnd.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/BitwiseAnd.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('&');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/BitwiseOr.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/BitwiseOr.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('|');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/BitwiseXor.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/BitwiseXor.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('^');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/Concat.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/Concat.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/Div.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/Div.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('/');
|
||||||
|
}
|
||||||
|
}
|
||||||
17
vendor/Twig/Node/Expression/Binary/Equal.php
vendored
Normal file
17
vendor/Twig/Node/Expression/Binary/Equal.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('==');
|
||||||
|
}
|
||||||
|
}
|
||||||
29
vendor/Twig/Node/Expression/Binary/FloorDiv.php
vendored
Normal file
29
vendor/Twig/Node/Expression/Binary/FloorDiv.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler->raw('intval(floor(');
|
||||||
|
parent::compile($compiler);
|
||||||
|
$compiler->raw('))');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('/');
|
||||||
|
}
|
||||||
|
}
|
||||||
17
vendor/Twig/Node/Expression/Binary/Greater.php
vendored
Normal file
17
vendor/Twig/Node/Expression/Binary/Greater.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('>');
|
||||||
|
}
|
||||||
|
}
|
||||||
17
vendor/Twig/Node/Expression/Binary/GreaterEqual.php
vendored
Normal file
17
vendor/Twig/Node/Expression/Binary/GreaterEqual.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('>=');
|
||||||
|
}
|
||||||
|
}
|
||||||
33
vendor/Twig/Node/Expression/Binary/In.php
vendored
Normal file
33
vendor/Twig/Node/Expression/Binary/In.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('twig_in_filter(')
|
||||||
|
->subcompile($this->getNode('left'))
|
||||||
|
->raw(', ')
|
||||||
|
->subcompile($this->getNode('right'))
|
||||||
|
->raw(')')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('in');
|
||||||
|
}
|
||||||
|
}
|
||||||
17
vendor/Twig/Node/Expression/Binary/Less.php
vendored
Normal file
17
vendor/Twig/Node/Expression/Binary/Less.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('<');
|
||||||
|
}
|
||||||
|
}
|
||||||
17
vendor/Twig/Node/Expression/Binary/LessEqual.php
vendored
Normal file
17
vendor/Twig/Node/Expression/Binary/LessEqual.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('<=');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/Mod.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/Mod.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('%');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/Mul.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/Mul.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('*');
|
||||||
|
}
|
||||||
|
}
|
||||||
17
vendor/Twig/Node/Expression/Binary/NotEqual.php
vendored
Normal file
17
vendor/Twig/Node/Expression/Binary/NotEqual.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('!=');
|
||||||
|
}
|
||||||
|
}
|
||||||
33
vendor/Twig/Node/Expression/Binary/NotIn.php
vendored
Normal file
33
vendor/Twig/Node/Expression/Binary/NotIn.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('!twig_in_filter(')
|
||||||
|
->subcompile($this->getNode('left'))
|
||||||
|
->raw(', ')
|
||||||
|
->subcompile($this->getNode('right'))
|
||||||
|
->raw(')')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('not in');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/Or.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/Or.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('||');
|
||||||
|
}
|
||||||
|
}
|
||||||
33
vendor/Twig/Node/Expression/Binary/Power.php
vendored
Normal file
33
vendor/Twig/Node/Expression/Binary/Power.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('pow(')
|
||||||
|
->subcompile($this->getNode('left'))
|
||||||
|
->raw(', ')
|
||||||
|
->subcompile($this->getNode('right'))
|
||||||
|
->raw(')')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('**');
|
||||||
|
}
|
||||||
|
}
|
||||||
33
vendor/Twig/Node/Expression/Binary/Range.php
vendored
Normal file
33
vendor/Twig/Node/Expression/Binary/Range.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2010 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('range(')
|
||||||
|
->subcompile($this->getNode('left'))
|
||||||
|
->raw(', ')
|
||||||
|
->subcompile($this->getNode('right'))
|
||||||
|
->raw(')')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('..');
|
||||||
|
}
|
||||||
|
}
|
||||||
18
vendor/Twig/Node/Expression/Binary/Sub.php
vendored
Normal file
18
vendor/Twig/Node/Expression/Binary/Sub.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary
|
||||||
|
{
|
||||||
|
public function operator(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
return $compiler->raw('-');
|
||||||
|
}
|
||||||
|
}
|
||||||
52
vendor/Twig/Node/Expression/BlockReference.php
vendored
Normal file
52
vendor/Twig/Node/Expression/BlockReference.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a block call node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
||||||
|
{
|
||||||
|
public function __construct(Twig_NodeInterface $name, $asString = false, $lineno, $tag = null)
|
||||||
|
{
|
||||||
|
parent::__construct(array('name' => $name), array('as_string' => $asString, 'output' => false), $lineno, $tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
if ($this->getAttribute('as_string')) {
|
||||||
|
$compiler->raw('(string) ');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getAttribute('output')) {
|
||||||
|
$compiler
|
||||||
|
->addDebugInfo($this)
|
||||||
|
->write("\$this->displayBlock(")
|
||||||
|
->subcompile($this->getNode('name'))
|
||||||
|
->raw(", \$context, \$blocks);\n")
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
$compiler
|
||||||
|
->raw("\$this->renderBlock(")
|
||||||
|
->subcompile($this->getNode('name'))
|
||||||
|
->raw(", \$context, \$blocks)")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
vendor/Twig/Node/Expression/Conditional.php
vendored
Normal file
31
vendor/Twig/Node/Expression/Conditional.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Conditional extends Twig_Node_Expression
|
||||||
|
{
|
||||||
|
public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno)
|
||||||
|
{
|
||||||
|
parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw('((')
|
||||||
|
->subcompile($this->getNode('expr1'))
|
||||||
|
->raw(') ? (')
|
||||||
|
->subcompile($this->getNode('expr2'))
|
||||||
|
->raw(') : (')
|
||||||
|
->subcompile($this->getNode('expr3'))
|
||||||
|
->raw('))')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
vendor/Twig/Node/Expression/Constant.php
vendored
Normal file
23
vendor/Twig/Node/Expression/Constant.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Constant extends Twig_Node_Expression
|
||||||
|
{
|
||||||
|
public function __construct($value, $lineno)
|
||||||
|
{
|
||||||
|
parent::__construct(array(), array('value' => $value), $lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler->repr($this->getAttribute('value'));
|
||||||
|
}
|
||||||
|
}
|
||||||
34
vendor/Twig/Node/Expression/ExtensionReference.php
vendored
Normal file
34
vendor/Twig/Node/Expression/ExtensionReference.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an extension call node.
|
||||||
|
*
|
||||||
|
* @package twig
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
||||||
|
{
|
||||||
|
public function __construct($name, $lineno, $tag = null)
|
||||||
|
{
|
||||||
|
parent::__construct(array(), array('name' => $name), $lineno, $tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the node to PHP.
|
||||||
|
*
|
||||||
|
* @param Twig_Compiler A Twig_Compiler instance
|
||||||
|
*/
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
|
||||||
|
}
|
||||||
|
}
|
||||||
61
vendor/Twig/Node/Expression/Filter.php
vendored
Normal file
61
vendor/Twig/Node/Expression/Filter.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) 2009 Fabien Potencier
|
||||||
|
* (c) 2009 Armin Ronacher
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
class Twig_Node_Expression_Filter extends Twig_Node_Expression
|
||||||
|
{
|
||||||
|
public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
||||||
|
{
|
||||||
|
parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile(Twig_Compiler $compiler)
|
||||||
|
{
|
||||||
|
$name = $this->getNode('filter')->getAttribute('value');
|
||||||
|
|
||||||
|
if (false === $filter = $compiler->getEnvironment()->getFilter($name)) {
|
||||||
|
$message = sprintf('The filter "%s" does not exist', $name);
|
||||||
|
if ($alternatives = $compiler->getEnvironment()->computeAlternatives($name, array_keys($compiler->getEnvironment()->getFilters()))) {
|
||||||
|
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Twig_Error_Syntax($message, $this->getLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->compileFilter($compiler, $filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function compileFilter(Twig_Compiler $compiler, Twig_FilterInterface $filter)
|
||||||
|
{
|
||||||
|
$compiler
|
||||||
|
->raw($filter->compile().'(')
|
||||||
|
->raw($filter->needsEnvironment() ? '$this->env, ' : '')
|
||||||
|
->raw($filter->needsContext() ? '$context, ' : '')
|
||||||
|
;
|
||||||
|
|
||||||
|
foreach ($filter->getArguments() as $argument) {
|
||||||
|
$compiler
|
||||||
|
->string($argument)
|
||||||
|
->raw(', ')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
$compiler->subcompile($this->getNode('node'));
|
||||||
|
|
||||||
|
foreach ($this->getNode('arguments') as $node) {
|
||||||
|
$compiler
|
||||||
|
->raw(', ')
|
||||||
|
->subcompile($node)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
$compiler->raw(')');
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user