Initial commit with Symfony 2.1+Vendors

Signed-off-by: Gergely POLONKAI (W00d5t0ck) <polesz@w00d5t0ck.info>
This commit is contained in:
Polonkai Gergely 2012-07-01 09:52:20 +02:00
commit 082a0130c2
5381 changed files with 416709 additions and 0 deletions

19
LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2004-2012 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

174
README.md Normal file
View File

@ -0,0 +1,174 @@
Symfony Standard Edition
========================
Welcome to the Symfony Standard Edition - a fully-functional Symfony2
application that you can use as the skeleton for your new applications.
This document contains information on how to download, install, and start
using Symfony. For a more detailed explanation, see the [Installation][1]
chapter of the Symfony Documentation.
1) Installing the Standard Edition
----------------------------------
When it comes to installing the Symfony Standard Edition, you have the
following options.
### Use Composer (*recommended*)
As Symfony uses [Composer][2] to manage its dependencies, the recommended way
to create a new project is to use it.
If you don't have Composer yet, download it following the instructions on
http://getcomposer.org/ or just run the following command:
curl -s http://getcomposer.org/installer | php
Then, use the `create-project` command to generate a new Symfony application:
composer.phar create-project symfony/framework-standard-edition path/to/install
Composer will install Symfony and all its dependencies under the
`path/to/install` directory.
### Download an Archive File
To quickly test Symfony, you can also download an [archive][3] of the Standard
Edition and unpack it somewhere under your web server root directory.
If you downloaded an archive "without vendors", you also need to install all
the necessary dependencies. Download composer (see above) and run the
following command:
php composer.phar install
2) Checking your System Configuration
-------------------------------------
Before starting coding, make sure that your local system is properly
configured for Symfony.
Execute the `check.php` script from the command line:
php app/check.php
Access the `config.php` script from a browser:
http://localhost/path/to/symfony/app/web/config.php
If you get any warnings or recommendations, fix them before moving on.
3) Browsing the Demo Application
--------------------------------
Congratulations! You're now ready to use Symfony.
From the `config.php` page, click the "Bypass configuration and go to the
Welcome page" link to load up your first Symfony page.
You can also use a web-based configurator by clicking on the "Configure your
Symfony Application online" link of the `config.php` page.
To see a real-live Symfony page in action, access the following page:
web/app_dev.php/demo/hello/Fabien
3) Getting started with Symfony
-------------------------------
This distribution is meant to be the starting point for your Symfony
applications, but it also contains some sample code that you can learn from
and play with.
A great way to start learning Symfony is via the [Quick Tour][4], which will
take you through all the basic features of Symfony2.
Once you're feeling good, you can move onto reading the official
[Symfony2 book][5].
A default bundle, `AcmeDemoBundle`, shows you Symfony2 in action. After
playing with it, you can remove it by following these steps:
* delete the `src/Acme` directory;
* remove the routing entries referencing AcmeBundle in
`app/config/routing_dev.yml`;
* remove the AcmeBundle from the registered bundles in `app/AppKernel.php`;
* remove the `web/bundles/acmedemo` directory;
* remove the inclusion of the security configuration in
`app/config/config.yml` (remove the `- { resource: security.yml }` line)
or tweak the security configuration to fit your needs.
What's inside?
---------------
The Symfony Standard Edition is configured with the following defaults:
* Twig is the only configured template engine;
* Doctrine ORM/DBAL is configured;
* Swiftmailer is configured;
* Annotations for everything are enabled.
It comes pre-configured with the following bundles:
* **FrameworkBundle** - The core Symfony framework bundle
* [**SensioFrameworkExtraBundle**][6] - Adds several enhancements, including
template and routing annotation capability
* [**DoctrineBundle**][7] - Adds support for the Doctrine ORM
* [**TwigBundle**][8] - Adds support for the Twig templating engine
* [**SecurityBundle**][9] - Adds security by integrating Symfony's security
component
* [**SwiftmailerBundle**][10] - Adds support for Swiftmailer, a library for
sending emails
* [**MonologBundle**][11] - Adds support for Monolog, a logging library
* [**AsseticBundle**][12] - Adds support for Assetic, an asset processing
library
* [**JMSSecurityExtraBundle**][13] - Allows security to be added via
annotations
* [**JMSDiExtraBundle**][14] - Adds more powerful dependency injection
features
* **WebProfilerBundle** (in dev/test env) - Adds profiling functionality and
the web debug toolbar
* **SensioDistributionBundle** (in dev/test env) - Adds functionality for
configuring and working with Symfony distributions
* [**SensioGeneratorBundle**][15] (in dev/test env) - Adds code generation
capabilities
* **AcmeDemoBundle** (in dev/test env) - A demo bundle with some example
code
Enjoy!
[1]: http://symfony.com/doc/2.1/book/installation.html
[2]: http://getcomposer.org/
[3]: http://symfony.com/download
[4]: http://symfony.com/doc/2.1/quick_tour/the_big_picture.html
[5]: http://symfony.com/doc/2.1/
[6]: http://symfony.com/doc/2.1/bundles/SensioFrameworkExtraBundle/index.html
[7]: http://symfony.com/doc/2.1/book/doctrine.html
[8]: http://symfony.com/doc/2.1/book/templating.html
[9]: http://symfony.com/doc/2.1/book/security.html
[10]: http://symfony.com/doc/2.1/cookbook/email.html
[11]: http://symfony.com/doc/2.1/cookbook/logging/monolog.html
[12]: http://symfony.com/doc/2.1/cookbook/assetic/asset_management.html
[13]: http://jmsyst.com/bundles/JMSSecurityExtraBundle/1.1
[14]: http://jmsyst.com/bundles/JMSDiExtraBundle/1.0
[15]: http://symfony.com/doc/2.1/bundles/SensioGeneratorBundle/index.html

1
app/.htaccess Normal file
View File

@ -0,0 +1 @@
deny from all

9
app/AppCache.php Normal file
View File

@ -0,0 +1,9 @@
<?php
require_once __DIR__.'/AppKernel.php';
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
class AppCache extends HttpCache
{
}

38
app/AppKernel.php Normal file
View File

@ -0,0 +1,38 @@
<?php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new JMS\AopBundle\JMSAopBundle(),
new JMS\DiExtraBundle\JMSDiExtraBundle($this),
new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
);
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
$bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
}
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
}

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>

580
app/SymfonyRequirements.php Normal file
View File

@ -0,0 +1,580 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a single PHP requirement, e.g. an installed extension.
* It can be a mandatory requirement or an optional recommendation.
* There is a special subclass, named PhpIniRequirement, to check a php.ini configuration.
*
* @author Tobias Schultze <http://tobion.de>
*/
class Requirement
{
private $fulfilled;
private $testMessage;
private $helpText;
private $helpHtml;
private $optional;
/**
* Constructor that initializes the requirement.
*
* @param Boolean $fulfilled Whether the requirement is fulfilled
* @param string $testMessage The message for testing the requirement
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement
*/
public function __construct($fulfilled, $testMessage, $helpHtml, $helpText = null, $optional = false)
{
$this->fulfilled = (Boolean) $fulfilled;
$this->testMessage = (string) $testMessage;
$this->helpHtml = (string) $helpHtml;
$this->helpText = null === $helpText ? strip_tags($this->helpHtml) : (string) $helpText;
$this->optional = (Boolean) $optional;
}
/**
* Returns whether the requirement is fulfilled.
*
* @return Boolean true if fulfilled, otherwise false
*/
public function isFulfilled()
{
return $this->fulfilled;
}
/**
* Returns the message for testing the requirement.
*
* @return string The test message
*/
public function getTestMessage()
{
return $this->testMessage;
}
/**
* Returns the help text for resolving the problem
*
* @return string The help text
*/
public function getHelpText()
{
return $this->helpText;
}
/**
* Returns the help text formatted in HTML.
*
* @return string The HTML help
*/
public function getHelpHtml()
{
return $this->helpHtml;
}
/**
* Returns whether this is only an optional recommendation and not a mandatory requirement.
*
* @return Boolean true if optional, false if mandatory
*/
public function isOptional()
{
return $this->optional;
}
}
/**
* Represents a PHP requirement in form of a php.ini configuration.
*
* @author Tobias Schultze <http://tobion.de>
*/
class PhpIniRequirement extends Requirement
{
/**
* Constructor that initializes the requirement.
*
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement
*/
public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null, $optional = false)
{
$cfgValue = ini_get($cfgName);
if (is_callable($evaluation)) {
if (null === $testMessage || null === $helpHtml) {
throw new InvalidArgumentException('You must provide the parameters testMessage and helpHtml for a callback evaluation.');
}
$fulfilled = call_user_func($evaluation, $cfgValue);
} else {
if (null === $testMessage) {
$testMessage = sprintf('%s %s be %s in php.ini',
$cfgName,
$optional ? 'should' : 'must',
$evaluation ? 'enabled' : 'disabled'
);
}
if (null === $helpHtml) {
$helpHtml = sprintf('Set <strong>%s</strong> to <strong>%s</strong> in php.ini<a href="#phpini">*</a>.',
$cfgName,
$evaluation ? 'on' : 'off'
);
}
$fulfilled = $evaluation == $cfgValue;
}
parent::__construct($fulfilled || ($approveCfgAbsence && false === $cfgValue), $testMessage, $helpHtml, $helpText, $optional);
}
}
/**
* A RequirementCollection represents a set of Requirement instances.
*
* Users of PHP 5.2 should be able to run the requirements checks.
* This is why the class must be compatible with PHP 5.2
* (e.g. not using namespaces and closures).
*
* @author Tobias Schultze <http://tobion.de>
*/
class RequirementCollection implements IteratorAggregate
{
private $requirements = array();
/**
* Gets the current RequirementCollection as an Iterator.
*
* @return Traversable A Traversable interface
*/
public function getIterator()
{
return new ArrayIterator($this->requirements);
}
/**
* Adds a Requirement.
*
* @param Requirement $requirement A Requirement instance
*/
public function add(Requirement $requirement)
{
$this->requirements[] = $requirement;
}
/**
* Adds a mandatory requirement.
*
* @param Boolean $fulfilled Whether the requirement is fulfilled
* @param string $testMessage The message for testing the requirement
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
*/
public function addRequirement($fulfilled, $testMessage, $helpHtml, $helpText = null)
{
$this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, false));
}
/**
* Adds an optional recommendation.
*
* @param Boolean $fulfilled Whether the recommendation is fulfilled
* @param string $testMessage The message for testing the recommendation
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
*/
public function addRecommendation($fulfilled, $testMessage, $helpHtml, $helpText = null)
{
$this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, true));
}
/**
* Adds a mandatory requirement in form of a php.ini configuration.
*
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
*/
public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null)
{
$this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, false));
}
/**
* Adds an optional recommendation in form of a php.ini configuration.
*
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
*/
public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null)
{
$this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, true));
}
/**
* Adds a requirement collection to the current set of requirements.
*
* @param RequirementCollection $collection A RequirementCollection instance
*/
public function addCollection(RequirementCollection $collection)
{
$this->requirements = array_merge($this->requirements, $collection->all());
}
/**
* Returns both requirements and recommendations.
*
* @return array Array of Requirement instances
*/
public function all()
{
return $this->requirements;
}
/**
* Returns all mandatory requirements.
*
* @return array Array of Requirement instances
*/
public function getRequirements()
{
$array = array();
foreach ($this->requirements as $req) {
if (!$req->isOptional()) {
$array[] = $req;
}
}
return $array;
}
/**
* Returns the mandatory requirements that were not met.
*
* @return array Array of Requirement instances
*/
public function getFailedRequirements()
{
$array = array();
foreach ($this->requirements as $req) {
if (!$req->isFulfilled() && !$req->isOptional()) {
$array[] = $req;
}
}
return $array;
}
/**
* Returns all optional recommmendations.
*
* @return array Array of Requirement instances
*/
public function getRecommendations()
{
$array = array();
foreach ($this->requirements as $req) {
if ($req->isOptional()) {
$array[] = $req;
}
}
return $array;
}
/**
* Returns the recommendations that were not met.
*
* @return array Array of Requirement instances
*/
public function getFailedRecommendations()
{
$array = array();
foreach ($this->requirements as $req) {
if (!$req->isFulfilled() && $req->isOptional()) {
$array[] = $req;
}
}
return $array;
}
/**
* Returns whether a php.ini configuration is not correct.
*
* @return Boolean php.ini configuration problem?
*/
public function hasPhpIniConfigIssue()
{
foreach ($this->requirements as $req) {
if (!$req->isFulfilled() && $req instanceof PhpIniRequirement) {
return true;
}
}
return false;
}
/**
* Returns the PHP configuration file (php.ini) path.
*
* @return string|false php.ini file path
*/
public function getPhpIniConfigPath()
{
return get_cfg_var('cfg_file_path');
}
}
/**
* This class specifies all requirements and optional recommendations that
* are necessary to run the Symfony Standard Edition.
*
* @author Tobias Schultze <http://tobion.de>
*/
class SymfonyRequirements extends RequirementCollection
{
const REQUIRED_PHP_VERSION = '5.3.3';
/**
* Constructor that initializes the requirements.
*/
public function __construct()
{
/* mandatory requirements follow */
$installedPhpVersion = phpversion();
$this->addRequirement(
version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>='),
sprintf('PHP version must be at least %s (%s installed)', self::REQUIRED_PHP_VERSION, $installedPhpVersion),
sprintf('You are running PHP version "<strong>%s</strong>", but Symfony needs at least PHP "<strong>%s</strong>" to run.
Before using Symfony, upgrade your PHP installation, preferably to the latest version.',
$installedPhpVersion, self::REQUIRED_PHP_VERSION),
sprintf('Install PHP %s or newer (installed version is %s)', self::REQUIRED_PHP_VERSION, $installedPhpVersion)
);
$this->addRequirement(
is_dir(__DIR__.'/../vendor/symfony'),
'Vendor libraries must be installed',
'Vendor libraries are missing. Install composer following instructions from <a href="http://getcomposer.org/">http://getcomposer.org/</a>. ' .
'Then run "<strong>php composer.phar install</strong>" to install them.'
);
$baseDir = basename(__DIR__);
$this->addRequirement(
is_writable(__DIR__.'/cache'),
"$baseDir/cache/ directory must be writable",
"Change the permissions of the \"<strong>$baseDir/cache/</strong>\" directory so that the web server can write into it."
);
$this->addRequirement(
is_writable(__DIR__.'/logs'),
"$baseDir/logs/ directory must be writable",
"Change the permissions of the \"<strong>$baseDir/logs/</strong>\" directory so that the web server can write into it."
);
$this->addPhpIniRequirement(
'date.timezone', true, false,
'date.timezone setting must be set',
'Set the "<strong>date.timezone</strong>" setting in php.ini<a href="#phpini">*</a> (like Europe/Paris).'
);
if (version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>=')) {
$this->addRequirement(
(in_array(date_default_timezone_get(), \DateTimeZone::listIdentifiers())),
sprintf('Default timezone is deprecated (%s)', date_default_timezone_get()),
'Fix your <strong>php.ini</strong> file (list of deprecated timezones http://us.php.net/manual/en/timezones.others.php).'
);
}
$this->addRequirement(
function_exists('json_encode'),
'json_encode() must be available',
'Install and enable the <strong>JSON</strong> extension.'
);
$this->addRequirement(
function_exists('session_start'),
'session_start() must be available',
'Install and enable the <strong>session</strong> extension.'
);
$this->addRequirement(
function_exists('ctype_alpha'),
'ctype_alpha() must be available',
'Install and enable the <strong>ctype</strong> extension.'
);
$this->addRequirement(
function_exists('token_get_all'),
'token_get_all() must be available',
'Install and enable the <strong>Tokenizer</strong> extension.'
);
$this->addRequirement(
function_exists('simplexml_import_dom'),
'simplexml_import_dom() must be available',
'Install and enable the <strong>SimpleXML</strong> extension.'
);
$this->addRequirement(
!(function_exists('apc_store') && ini_get('apc.enabled')) || version_compare(phpversion('apc'), '3.0.17', '>='),
'APC version must be at least 3.0.17',
'Upgrade your <strong>APC</strong> extension (3.0.17+)'
);
$this->addPhpIniRequirement('detect_unicode', false);
$this->addPhpIniRequirement(
'suhosin.executor.include.whitelist',
create_function('$cfgValue', 'return false !== stripos($cfgValue, "phar");'),
true,
'suhosin.executor.include.whitelist must be configured correctly in php.ini',
'Add "<strong>phar</strong>" to <strong>suhosin.executor.include.whitelist</strong> in php.ini<a href="#phpini">*</a>.'
);
$pcreVersion = defined('PCRE_VERSION') ? (float) PCRE_VERSION : null;
$this->addRequirement(
null !== $pcreVersion && $pcreVersion > 8.0,
sprintf('PCRE extension must be available and at least 8.0 (%s installed)', $pcreVersion ? $pcreVersion : 'not'),
'Upgrade your <strong>PCRE</strong> extension (8.0+)'
);
/* optional recommendations follow */
$this->addRecommendation(
version_compare($installedPhpVersion, '5.3.8', '>='),
sprintf('Annotations might not work properly due to the PHP bug #55156 before PHP 5.3.8 (%s installed)', $installedPhpVersion),
'Install PHP 5.3.8 or newer if your project uses annotations'
);
$this->addRecommendation(
class_exists('DomDocument'),
'PHP-XML module should be installed',
'Install and enable the <strong>PHP-XML</strong> module.'
);
$this->addRecommendation(
function_exists('mb_strlen'),
'mb_strlen() should be available',
'Install and enable the <strong>mbstring</strong> extension.'
);
$this->addRecommendation(
function_exists('iconv'),
'iconv() should be available',
'Install and enable the <strong>iconv</strong> extension.'
);
$this->addRecommendation(
function_exists('utf8_decode'),
'utf8_decode() should be available',
'Install and enable the <strong>XML</strong> extension.'
);
if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
$this->addRecommendation(
function_exists('posix_isatty'),
'posix_isatty() should be available',
'Install and enable the <strong>php_posix</strong> extension (used to colorize the CLI output).'
);
}
$this->addRecommendation(
class_exists('Locale'),
'intl extension should be available',
'Install and enable the <strong>intl</strong> extension (used for validators).'
);
if (class_exists('Locale')) {
if (defined('INTL_ICU_VERSION')) {
$version = INTL_ICU_VERSION;
} else {
$reflector = new ReflectionExtension('intl');
ob_start();
$reflector->info();
$output = strip_tags(ob_get_clean());
preg_match('/^ICU version +(?:=> )?(.*)$/m', $output, $matches);
$version = $matches[1];
}
$this->addRecommendation(
version_compare($version, '4.0', '>='),
'intl ICU version should be at least 4+',
'Upgrade your <strong>intl</strong> extension with a newer ICU version (4+).'
);
}
$accelerator =
(function_exists('apc_store') && ini_get('apc.enabled'))
||
function_exists('eaccelerator_put') && ini_get('eaccelerator.enable')
||
function_exists('xcache_set')
;
$this->addRecommendation(
$accelerator,
'a PHP accelerator should be installed',
'Install and enable a <strong>PHP accelerator</strong> like APC (highly recommended).'
);
$this->addPhpIniRecommendation('short_open_tag', false);
$this->addPhpIniRecommendation('magic_quotes_gpc', false, true);
$this->addPhpIniRecommendation('register_globals', false, true);
$this->addPhpIniRecommendation('session.auto_start', false);
$this->addRecommendation(
class_exists('PDO'),
'PDO should be installed',
'Install <strong>PDO</strong> (mandatory for Doctrine).'
);
if (class_exists('PDO')) {
$drivers = PDO::getAvailableDrivers();
$this->addRecommendation(
count($drivers),
sprintf('PDO should have some drivers installed (currently available: %s)', count($drivers) ? implode(', ', $drivers) : 'none'),
'Install <strong>PDO drivers</strong> (mandatory for Doctrine).'
);
}
}
}

32
app/autoload.php Normal file
View File

@ -0,0 +1,32 @@
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
if (!$loader = @include __DIR__.'/../vendor/autoload.php') {
$message = <<< EOF
<p>You must set up the project dependencies by running the following commands:</p>
<pre>
curl -s http://getcomposer.org/installer | php
php composer.phar install
</pre>
EOF;
if (PHP_SAPI === 'cli') {
$message = strip_tags($message);
}
die($message);
}
// intl
if (!function_exists('intl_get_error_code')) {
require_once __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';
$loader->add('', __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs');
}
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
return $loader;

1455
app/bootstrap.php.cache Normal file

File diff suppressed because it is too large Load Diff

0
app/cache/.gitkeep vendored Normal file
View File

55
app/check.php Normal file
View File

@ -0,0 +1,55 @@
<?php
require_once dirname(__FILE__).'/SymfonyRequirements.php';
$symfonyRequirements = new SymfonyRequirements();
$iniPath = $symfonyRequirements->getPhpIniConfigPath();
echo "********************************\n";
echo "* *\n";
echo "* Symfony requirements check *\n";
echo "* *\n";
echo "********************************\n\n";
echo $iniPath ? sprintf("* Configuration file used by PHP: %s\n\n", $iniPath) : "* WARNING: No configuration file (php.ini) used by PHP!\n\n";
echo "** ATTENTION **\n";
echo "* The PHP CLI can use a different php.ini file\n";
echo "* than the one used with your web server.\n";
if ('\\' == DIRECTORY_SEPARATOR) {
echo "* (especially on the Windows platform)\n";
}
echo "* To be on the safe side, please also launch the requirements check\n";
echo "* from your web server using the web/config.php script.\n";
echo_title('Mandatory requirements');
foreach ($symfonyRequirements->getRequirements() as $req) {
echo_requirement($req);
}
echo_title('Optional recommendations');
foreach ($symfonyRequirements->getRecommendations() as $req) {
echo_requirement($req);
}
/**
* Prints a Requirement instance
*/
function echo_requirement(Requirement $requirement)
{
$result = $requirement->isFulfilled() ? 'OK' : ($requirement->isOptional() ? 'WARNING' : 'ERROR');
echo ' ' . str_pad($result, 9);
echo $requirement->getTestMessage() . "\n";
if (!$requirement->isFulfilled()) {
echo sprintf(" %s\n\n", $requirement->getHelpText());
}
}
function echo_title($title)
{
echo "\n** $title **\n\n";
}

60
app/config/config.yml Normal file
View File

@ -0,0 +1,60 @@
imports:
- { resource: parameters.yml }
- { resource: security.yml }
framework:
#esi: ~
#translator: { fallback: %locale% }
secret: %secret%
charset: UTF-8
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_parameters: %kernel.debug%
form: true
csrf_protection: true
validation: { enable_annotations: true }
templating: { engines: ['twig'] } #assets_version: SomeVersionScheme
default_locale: %locale%
session:
auto_start: true
# Twig Configuration
twig:
debug: %kernel.debug%
strict_variables: %kernel.debug%
# Assetic Configuration
assetic:
debug: %kernel.debug%
use_controller: false
bundles: [ ]
#java: /usr/bin/java
filters:
cssrewrite: ~
#closure:
# jar: %kernel.root_dir%/Resources/java/compiler.jar
#yui_css:
# jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar
# Doctrine Configuration
doctrine:
dbal:
driver: %database_driver%
host: %database_host%
port: %database_port%
dbname: %database_name%
user: %database_user%
password: %database_password%
charset: UTF8
orm:
auto_generate_proxy_classes: %kernel.debug%
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: %mailer_transport%
host: %mailer_host%
username: %mailer_user%
password: %mailer_password%
spool: { type: memory }

26
app/config/config_dev.yml Normal file
View File

@ -0,0 +1,26 @@
imports:
- { resource: config.yml }
framework:
router: { resource: "%kernel.root_dir%/config/routing_dev.yml" }
profiler: { only_exceptions: false }
web_profiler:
toolbar: true
intercept_redirects: false
monolog:
handlers:
main:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.log
level: debug
firephp:
type: firephp
level: info
assetic:
use_controller: true
#swiftmailer:
# delivery_address: me@example.com

View File

@ -0,0 +1,19 @@
imports:
- { resource: config.yml }
#doctrine:
# orm:
# metadata_cache_driver: apc
# result_cache_driver: apc
# query_cache_driver: apc
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
nested:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.log
level: debug

View File

@ -0,0 +1,14 @@
imports:
- { resource: config_dev.yml }
framework:
test: ~
session:
storage_id: session.storage.mock_file
web_profiler:
toolbar: false
intercept_redirects: false
swiftmailer:
disable_delivery: true

15
app/config/parameters.yml Normal file
View File

@ -0,0 +1,15 @@
parameters:
database_driver: pdo_mysql
database_host: localhost
database_port: ~
database_name: symfony
database_user: root
database_password: ~
mailer_transport: smtp
mailer_host: localhost
mailer_user: ~
mailer_password: ~
locale: en
secret: ThisTokenIsNotSoSecretChangeIt

4
app/config/routing.yml Normal file
View File

@ -0,0 +1,4 @@
# Internal routing configuration to handle ESI
#_internal:
# resource: "@FrameworkBundle/Resources/config/routing/internal.xml"
# prefix: /_internal

View File

@ -0,0 +1,27 @@
_welcome:
pattern: /
defaults: { _controller: AcmeDemoBundle:Welcome:index }
_demo_secured:
resource: "@AcmeDemoBundle/Controller/SecuredController.php"
type: annotation
_demo:
resource: "@AcmeDemoBundle/Controller/DemoController.php"
type: annotation
prefix: /demo
_wdt:
resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
prefix: /_wdt
_profiler:
resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
prefix: /_profiler
_configurator:
resource: "@SensioDistributionBundle/Resources/config/routing/webconfigurator.xml"
prefix: /_configurator
_main:
resource: routing.yml

43
app/config/security.yml Normal file
View File

@ -0,0 +1,43 @@
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/demo/secured/login$
security: false
secured_area:
pattern: ^/demo/secured/
form_login:
check_path: /demo/secured/login_check
login_path: /demo/secured/login
logout:
path: /demo/secured/logout
target: /demo/
#anonymous: ~
#http_basic:
# realm: "Secured Demo Area"
access_control:
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
#- { path: ^/_internal/secure, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }

22
app/console Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
// if you don't want to setup permissions the proper way, just uncomment the following PHP line
// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
//umask(0000);
set_time_limit(0);
require_once __DIR__.'/bootstrap.php.cache';
require_once __DIR__.'/AppKernel.php';
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
$input = new ArgvInput();
$env = $input->getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod';
$kernel = new AppKernel($env, $debug);
$application = new Application($kernel);
$application->run($input);

0
app/logs/.gitkeep Executable file
View File

41
app/phpunit.xml.dist Normal file
View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit
backupGlobals = "false"
backupStaticAttributes = "false"
colors = "true"
convertErrorsToExceptions = "true"
convertNoticesToExceptions = "true"
convertWarningsToExceptions = "true"
processIsolation = "false"
stopOnFailure = "false"
syntaxCheck = "false"
bootstrap = "bootstrap.php.cache" >
<testsuites>
<testsuite name="Project Test Suite">
<directory>../src/*/*Bundle/Tests</directory>
<directory>../src/*/Bundle/*Bundle/Tests</directory>
</testsuite>
</testsuites>
<!--
<php>
<server name="KERNEL_DIR" value="/path/to/your/app/" />
</php>
-->
<filter>
<whitelist>
<directory>../src</directory>
<exclude>
<directory>../src/*/*Bundle/Resources</directory>
<directory>../src/*/*Bundle/Tests</directory>
<directory>../src/*/Bundle/*Bundle/Resources</directory>
<directory>../src/*/Bundle/*Bundle/Tests</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

41
composer.json Normal file
View File

@ -0,0 +1,41 @@
{
"name": "symfony/framework-standard-edition",
"description": "The \"Symfony Standard Edition\" distribution",
"autoload": {
"psr-0": { "": "src/" }
},
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.1.*",
"doctrine/orm": "2.2.*",
"doctrine/doctrine-bundle": "dev-master",
"twig/extensions": "dev-master",
"symfony/assetic-bundle": "dev-master",
"symfony/swiftmailer-bundle": "dev-master",
"symfony/monolog-bundle": "dev-master",
"sensio/distribution-bundle": "dev-master",
"sensio/framework-extra-bundle": "dev-master",
"sensio/generator-bundle": "dev-master",
"jms/security-extra-bundle": "1.1.*",
"jms/di-extra-bundle": "1.0.*"
},
"scripts": {
"post-install-cmd": [
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets"
],
"post-update-cmd": [
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets"
]
},
"config": {
"bin-dir": "bin"
},
"extra": {
"symfony-app-dir": "app",
"symfony-web-dir": "web"
}
}

144
composer.lock generated Normal file
View File

@ -0,0 +1,144 @@
{
"hash": "60f09c83d9f0891b51ac51941970dcd5",
"packages": [
{
"package": "doctrine/common",
"version": "2.2.2"
},
{
"package": "doctrine/dbal",
"version": "2.2.x-dev",
"source-reference": "8cc129aa64a8de6447056bce20f0a274fe2a340b"
},
{
"package": "doctrine/doctrine-bundle",
"version": "dev-master",
"source-reference": "94951737d6c692500d6b13bb92871935568a4ba5"
},
{
"package": "doctrine/orm",
"version": "2.2.x-dev",
"source-reference": "5f66c65c9a8d984899903b54215d0249a45b92d6"
},
{
"package": "jms/aop-bundle",
"version": "1.0.0"
},
{
"package": "jms/cg",
"version": "1.0.0"
},
{
"package": "jms/di-extra-bundle",
"version": "1.0.1"
},
{
"package": "jms/metadata",
"version": "1.1.1"
},
{
"package": "jms/security-extra-bundle",
"version": "1.1.0"
},
{
"package": "kriswallsmith/assetic",
"version": "dev-master",
"alias-pretty-version": "1.1.x-dev",
"alias-version": "1.1.9999999.9999999-dev"
},
{
"package": "kriswallsmith/assetic",
"version": "dev-master",
"source-reference": "d6f89a3170c5280ad554347dc113eb25fdf00ad7"
},
{
"package": "monolog/monolog",
"version": "1.1.0"
},
{
"package": "sensio/distribution-bundle",
"version": "dev-master",
"source-reference": "a360ad61fe34206a7295c1ef00b5455b2b2e1071"
},
{
"package": "sensio/framework-extra-bundle",
"version": "dev-master",
"source-reference": "62e41b85947034b0f1dfe31bb8e76920e1488571"
},
{
"package": "sensio/generator-bundle",
"version": "dev-master",
"source-reference": "43ed45c48db18e4a0e48aec0c098f42e56e22d36"
},
{
"package": "swiftmailer/swiftmailer",
"version": "dev-master",
"alias-pretty-version": "4.1.x-dev",
"alias-version": "4.1.9999999.9999999-dev"
},
{
"package": "swiftmailer/swiftmailer",
"version": "dev-master",
"source-reference": "d57ffdeed664d6061cef0047e1f5d3fc3ee3fb99"
},
{
"package": "symfony/assetic-bundle",
"version": "dev-master",
"source-reference": "8fe7b898b08103c1d6fce64c3e279a7afd61adfc"
},
{
"package": "symfony/monolog-bundle",
"version": "dev-master",
"source-reference": "0b5046d3d1ef93cd59ceabfa37de2665f5118c7f"
},
{
"package": "symfony/swiftmailer-bundle",
"version": "dev-master",
"source-reference": "d05c9c514a631ee688c53c4cc5505da757bd50d3"
},
{
"package": "symfony/symfony",
"version": "dev-master",
"alias-pretty-version": "2.1.x-dev",
"alias-version": "2.1.9999999.9999999-dev"
},
{
"package": "symfony/symfony",
"version": "dev-master",
"source-reference": "v2.1.0-BETA1"
},
{
"package": "twig/extensions",
"version": "dev-master",
"source-reference": "feb6d3f10c411e2631997c0a905aa581c80305c1"
},
{
"package": "twig/twig",
"version": "dev-master",
"alias-pretty-version": "1.8.x-dev",
"alias-version": "1.8.9999999.9999999-dev"
},
{
"package": "twig/twig",
"version": "dev-master",
"source-reference": "4679ad51c5390648b7ea4c8f0ecd2c0c344145ba"
}
],
"packages-dev": [
],
"aliases": [
],
"minimum-stability": "dev",
"stability-flags": {
"doctrine/doctrine-bundle": 20,
"twig/extensions": 20,
"symfony/assetic-bundle": 20,
"symfony/swiftmailer-bundle": 20,
"symfony/monolog-bundle": 20,
"sensio/distribution-bundle": 20,
"sensio/framework-extra-bundle": 20,
"sensio/generator-bundle": 20
}
}

1
src/.htaccess Normal file
View File

@ -0,0 +1 @@
deny from all

View File

@ -0,0 +1,9 @@
<?php
namespace Acme\DemoBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AcmeDemoBundle extends Bundle
{
}

View File

@ -0,0 +1,57 @@
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Acme\DemoBundle\Form\ContactType;
// these import the "@Route" and "@Template" annotations
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DemoController extends Controller
{
/**
* @Route("/", name="_demo")
* @Template()
*/
public function indexAction()
{
return array();
}
/**
* @Route("/hello/{name}", name="_demo_hello")
* @Template()
*/
public function helloAction($name)
{
return array('name' => $name);
}
/**
* @Route("/contact", name="_demo_contact")
* @Template()
*/
public function contactAction()
{
$form = $this->get('form.factory')->create(new ContactType());
$request = $this->get('request');
if ('POST' == $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
$mailer = $this->get('mailer');
// .. setup a message and send it
// http://symfony.com/doc/current/cookbook/email.html
$this->get('session')->setFlash('notice', 'Message sent!');
return new RedirectResponse($this->generateUrl('_demo'));
}
}
return array('form' => $form->createView());
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\SecurityExtraBundle\Annotation\Secure;
/**
* @Route("/demo/secured")
*/
class SecuredController extends Controller
{
/**
* @Route("/login", name="_demo_login")
* @Template()
*/
public function loginAction()
{
if ($this->get('request')->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $this->get('request')->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $this->get('request')->getSession()->get(SecurityContext::AUTHENTICATION_ERROR);
}
return array(
'last_username' => $this->get('request')->getSession()->get(SecurityContext::LAST_USERNAME),
'error' => $error,
);
}
/**
* @Route("/login_check", name="_security_check")
*/
public function securityCheckAction()
{
// The security layer will intercept this request
}
/**
* @Route("/logout", name="_demo_logout")
*/
public function logoutAction()
{
// The security layer will intercept this request
}
/**
* @Route("/hello", defaults={"name"="World"}),
* @Route("/hello/{name}", name="_demo_secured_hello")
* @Template()
*/
public function helloAction($name)
{
return array('name' => $name);
}
/**
* @Route("/hello/admin/{name}", name="_demo_secured_hello_admin")
* @Secure(roles="ROLE_ADMIN")
* @Template()
*/
public function helloadminAction($name)
{
return array('name' => $name);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class WelcomeController extends Controller
{
public function indexAction()
{
/*
* The action's view can be rendered using render() method
* or @Template annotation as demonstrated in DemoController.
*
*/
return $this->render('AcmeDemoBundle:Welcome:index.html.twig');
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace Acme\DemoBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\Config\FileLocator;
class AcmeDemoExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.xml');
}
public function getAlias()
{
return 'acme_demo';
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace Acme\DemoBundle\EventListener;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Acme\DemoBundle\Twig\Extension\DemoExtension;
class ControllerListener
{
protected $extension;
public function __construct(DemoExtension $extension)
{
$this->extension = $extension;
}
public function onKernelController(FilterControllerEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
$this->extension->setController($event->getController());
}
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Acme\DemoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ContactType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('email', 'email');
$builder->add('message', 'textarea');
}
public function getName()
{
return 'contact';
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="twig.extension.acme.demo" class="Acme\DemoBundle\Twig\Extension\DemoExtension" public="false">
<tag name="twig.extension" />
<argument type="service" id="twig.loader" />
</service>
<service id="acme.demo.listener" class="Acme\DemoBundle\EventListener\ControllerListener">
<tag name="kernel.event_listener" event="kernel.controller" method="onKernelController" />
<argument type="service" id="twig.extension.acme.demo" />
</service>
</services>
</container>

View File

@ -0,0 +1,294 @@
/*
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 2.8.2r1
Reset
*/
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
html, body
{
background-color: #EFEFEF;
}
body
{
font-size: 14px;
font-family: "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
color: #313131;
}
a
{
color: #08C;
text-decoration: none;
}
a:hover
{
text-decoration: underline;
}
strong
{
font-weight: bold;
}
em
{
font-style: italic;
}
h1, h2, h3
{
font-family: Georgia, "Times New Roman", Times, serif;
color: #404040;
}
h1
{
font-size: 45px;
padding-bottom: 30px;
}
h2
{
font-weight: bold;
color: #FFFFFF;
/* Font is duplicated of body (sans-serif) */
font-family: "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
margin-bottom: 10px;
background-color: #aacd4e;
padding: 2px 4px;
display: inline-block;
text-transform: uppercase;
}
p
{
line-height: 20px;
padding-bottom: 20px;
}
ul#demo-list a
{
background: url(../images/blue-arrow.png) no-repeat right 6px;
padding-right: 10px;
margin-right: 30px;
}
ul, ol
{
padding-left: 20px;
}
li
{
padding-bottom: 18px;
}
ol li
{
list-style-type: decimal;
}
ul li
{
list-style-type: none;
}
#symfony-header
{
position: relative;
padding: 30px 30px 20px 30px;
}
#symfony-wrapper
{
width: 970px;
margin: 0 auto;
}
.symfony-content
{
background-color: white;
border: 1px solid #DFDFDF;
padding: 50px;
-moz-border-radius: 16px;
-webkit-border-radius: 16px;
border-radius: 16px;
margin-bottom: 20px;
word-wrap: break-word;
}
#symfony-search
{
position: absolute;
top: 50px;
right: 30px;
}
#symfony-search input[type="search"]
{
-webkit-appearance: textfield;
}
#symfony-search-field
{
width: 190px;
}
#symfony-search label
{
display: block;
float: left;
width: 20px;
height: 25px;
background: url(../images/search.png) no-repeat left 5px;
}
#symfony-search label span
{
display: none;
}
input[type=text], input[type=password]
{
border: 1px solid #DADADA;
background: white url(../images/field-background.gif) repeat-x left top;
padding: 5px 6px;
color: #565656;
font-family: 'Lucida Sans Unicode', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif;
font-size: 12px;
}
.symfony-button-grey,
.symfony-button-green
{
font-size: 0.85em;
font-weight: bold;
cursor: pointer;
display: inline-block;
outline: none;
text-align: center;
text-transform: uppercase;
padding: 3px 10px;
text-shadow: 0 1px 1px rgba(0,0,0,.3);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.symfony-button-grey
{
color: #868686;
font-weight: normal;
padding: 5px 10px;
border: solid 1px #d7d7d7;
background: #ffffff;
background: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#d7d7d7));
background: -moz-linear-gradient(top, #ffffff, #d7d7d7);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#d7d7d7');
}
.symfony-button-green
{
padding: 5px 12px;
color: white;
border: solid 1px #a7da39;
background: #a7da39;
background: -webkit-gradient(linear, left top, left bottom, from(#a7da39), to(#6a9211));
background: -moz-linear-gradient(top, #a7da39, #6a9211);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#a7da39', endColorstr='#6a9211');
}
.symfony-blocks-welcome
{
overflow: hidden;
}
.symfony-blocks-welcome > div
{
background-color: whitesmoke;
float: left;
width: 240px;
margin-right: 14px;
text-align: center;
padding: 26px 20px;
}
.symfony-blocks-welcome > div.block-demo
{
margin-right: 0;
}
.symfony-blocks-welcome .illustration
{
padding-bottom: 20px;
}
.symfony-blocks-help
{
overflow: hidden;
}
.symfony-blocks-help
{
margin-top: 30px;
padding: 18px;
border: 1px solid #E6E6E6;
}
.symfony-blocks-help > div
{
width: 254px;
float: left;
}
.flash-message
{
padding: 10px;
margin: 5px;
margin-top: 15px;
background-color: #ffe;
}
.error
{
color: red;
}
#login label, #contact_form label
{
display: block;
float: left;
width: 90px;
}
ul#menu
{
float: right;
margin-bottom: 20px;
padding-left: 0;
}
#menu li
{
padding-left: 0;
margin-right: 10px;
display: inline;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,15 @@
{% extends "AcmeDemoBundle::layout.html.twig" %}
{% block title "Symfony - Contact form" %}
{% block content %}
<form action="{{ path('_demo_contact') }}" method="POST" id="contact_form">
{{ form_errors(form) }}
{{ form_row(form.email) }}
{{ form_row(form.message) }}
{{ form_rest(form) }}
<input type="submit" value="Send" class="symfony-button-grey" />
</form>
{% endblock %}

View File

@ -0,0 +1,9 @@
{% extends "AcmeDemoBundle::layout.html.twig" %}
{% block title "Hello " ~ name %}
{% block content %}
<h1>Hello {{ name }}!</h1>
{% endblock %}
{% set code = code(_self) %}

View File

@ -0,0 +1,14 @@
{% extends "AcmeDemoBundle::layout.html.twig" %}
{% block title "Symfony - Demos" %}
{% block content_header '' %}
{% block content %}
<h1>Available demos</h1>
<ul id="demo-list">
<li><a href="{{ path('_demo_hello', {'name': 'World'}) }}">Hello World</a></li>
<li><a href="{{ path('_demo_secured_hello', {'name': 'World'}) }}">Access the secured area</a> <a href="{{ path('_demo_login') }}">Go to the login page</a></li>
{# <li><a href="{{ path('_demo_contact') }}">Send a Message</a></li> #}
</ul>
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends "AcmeDemoBundle:Secured:layout.html.twig" %}
{% block title "Hello " ~ name %}
{% block content %}
<h1>Hello {{ name }}!</h1>
<a href="{{ path('_demo_secured_hello_admin', { 'name': name }) }}">Hello resource secured for <strong>admin</strong> only.</a>
{% endblock %}
{% set code = code(_self) %}

View File

@ -0,0 +1,9 @@
{% extends "AcmeDemoBundle:Secured:layout.html.twig" %}
{% block title "Hello " ~ name %}
{% block content %}
<h1>Hello {{ name }} secured for Admins only!</h1>
{% endblock %}
{% set code = code(_self) %}

View File

@ -0,0 +1,6 @@
{% extends "AcmeDemoBundle::layout.html.twig" %}
{% block content_header_more %}
{{ parent() }}
<li>logged in as <strong>{{ app.user ? app.user.username : 'Anonymous' }}</strong> - <a href="{{ path('_demo_logout') }}">Logout</a></li>
{% endblock %}

View File

@ -0,0 +1,29 @@
{% extends 'AcmeDemoBundle::layout.html.twig' %}
{% block content %}
<h1>Login</h1>
<p>
Choose between two default users: <em>user/userpass</em> <small>(ROLE_USER)</small> or <em>admin/adminpass</em> <small>(ROLE_ADMIN)</small>
</p>
{% if error %}
<div class="error">{{ error.message }}</div>
{% endif %}
<form action="{{ path("_security_check") }}" method="post" id="login">
<div>
<label for="username">Username</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" name="_password" />
</div>
<input type="submit" class="symfony-button-grey" value="LOGIN" />
</form>
{% endblock %}
{% set code = code(_self) %}

View File

@ -0,0 +1,63 @@
{% extends 'AcmeDemoBundle::layout.html.twig' %}
{% block title %}Symfony - Welcome{% endblock %}
{% block content_header '' %}
{% block content %}
<h1>Welcome!</h1>
<p>Congratulations! You have successfully installed a new Symfony application.</p>
<div class="symfony-blocks-welcome">
<div class="block-quick-tour">
<div class="illustration">
<img src="{{ asset('bundles/acmedemo/images/welcome-quick-tour.gif') }}" alt="Quick tour" />
</div>
<a class="symfony-button-green" href="http://symfony.com/doc/current/quick_tour/index.html">Read the Quick Tour</a>
</div>
{% if app.environment == 'dev' %}
<div class="block-configure">
<div class="illustration">
<img src="{{ asset('bundles/acmedemo/images/welcome-configure.gif') }}" alt="Configure your application" />
</div>
<a class="symfony-button-green" href="{{ path('_configurator_home') }}">Configure</a>
</div>
{% endif %}
<div class="block-demo">
<div class="illustration">
<img src="{{ asset('bundles/acmedemo/images/welcome-demo.gif') }}" alt="Demo" />
</div>
<a class="symfony-button-green" href="{{ path('_demo') }}">Run The Demo</a>
</div>
</div>
<div class="symfony-blocks-help">
<div class="block-documentation">
<ul>
<li><strong>Documentation</strong></li>
<li><a href="http://symfony.com/doc/current/book/index.html">The Book</a></li>
<li><a href="http://symfony.com/doc/current/cookbook/index.html">The Cookbook</a></li>
<li><a href="http://symfony.com/doc/current/components/index.html">The Components</a></li>
<li><a href="http://symfony.com/doc/current/reference/index.html">Reference</a></li>
<li><a href="http://symfony.com/doc/current/glossary.html">Glossary</a></li>
</ul>
</div>
<div class="block-documentation-more">
<ul>
<li><strong>Sensio</strong></li>
<li><a href="http://trainings.sensiolabs.com">Trainings</a></li>
<li><a href="http://books.sensiolabs.com">Books</a></li>
</ul>
</div>
<div class="block-community">
<ul>
<li><strong>Community</strong></li>
<li><a href="http://symfony.com/irc">IRC channel</a></li>
<li><a href="http://symfony.com/mailing-lists">Mailing lists</a></li>
<li><a href="http://forum.symfony-project.org">Forum</a></li>
<li><a href="http://symfony.com/doc/current/contributing/index.html">Contributing</a></li>
</ul>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{% block title %}Demo Bundle{% endblock %}</title>
<link rel="icon" sizes="16x16" href="{{ asset('favicon.ico') }}" />
<link rel="stylesheet" href="{{ asset('bundles/acmedemo/css/demo.css') }}" />
</head>
<body>
<div id="symfony-wrapper">
<div id="symfony-header">
<a href="{{ path('_welcome') }}">
<img src="{{ asset('bundles/acmedemo/images/logo.gif') }}" alt="Symfony logo" />
</a>
<form id="symfony-search" method="GET" action="http://symfony.com/search">
<label for="symfony-search-field"><span>Search on Symfony Website</span></label>
<input name="q" id="symfony-search-field" type="search" placeholder="Search on Symfony website" class="medium_txt" />
<input type="submit" class="symfony-button-grey" value="OK" />
</form>
</div>
{% for flashMessage in app.session.flashbag.get('notice') %}
<div class="flash-message">
<em>Notice</em>: {{ flashMessage }}
</div>
{% endfor %}
{% block content_header %}
<ul id="menu">
{% block content_header_more %}
<li><a href="{{ path('_demo') }}">Demo Home</a></li>
{% endblock %}
</ul>
<div style="clear: both"></div>
{% endblock %}
<div class="symfony-content">
{% block content %}
{% endblock %}
</div>
{% if code is defined %}
<h2>Code behind this page</h2>
<div class="symfony-content">{{ code|raw }}</div>
{% endif %}
</div>
</body>
</html>

View File

@ -0,0 +1,17 @@
<?php
namespace Acme\DemoBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DemoControllerTest extends WebTestCase
{
public function testIndex()
{
$client = static::createClient();
$crawler = $client->request('GET', '/demo/hello/Fabien');
$this->assertTrue($crawler->filter('html:contains("Hello Fabien")')->count() > 0);
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace Acme\DemoBundle\Twig\Extension;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Bundle\TwigBundle\Loader\FilesystemLoader;
use CG\Core\ClassUtils;
class DemoExtension extends \Twig_Extension
{
protected $loader;
protected $controller;
public function __construct(FilesystemLoader $loader)
{
$this->loader = $loader;
}
public function setController($controller)
{
$this->controller = $controller;
}
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return array(
'code' => new \Twig_Function_Method($this, 'getCode', array('is_safe' => array('html'))),
);
}
public function getCode($template)
{
$controller = htmlspecialchars($this->getControllerCode(), ENT_QUOTES, 'UTF-8');
$template = htmlspecialchars($this->getTemplateCode($template), ENT_QUOTES, 'UTF-8');
// remove the code block
$template = str_replace('{% set code = code(_self) %}', '', $template);
return <<<EOF
<p><strong>Controller Code</strong></p>
<pre>$controller</pre>
<p><strong>Template Code</strong></p>
<pre>$template</pre>
EOF;
}
protected function getControllerCode()
{
$class = get_class($this->controller[0]);
if (class_exists('CG\Core\ClassUtils')) {
$class = ClassUtils::getUserClass($class);
}
$r = new \ReflectionClass($class);
$m = $r->getMethod($this->controller[1]);
$code = file($r->getFilename());
return ' '.$m->getDocComment()."\n".implode('', array_slice($code, $m->getStartline() - 1, $m->getEndLine() - $m->getStartline() + 1));
}
protected function getTemplateCode($template)
{
return $this->loader->getSource($template->getTemplateName());
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'demo';
}
}

203
vendor/ClassLoader.php vendored Normal file
View File

@ -0,0 +1,203 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements an PSR-0 class loader
*
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
*
* $loader = new ComposerClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class ClassLoader
{
private $prefixes = array();
private $fallbackDirs = array();
private $useIncludePath = false;
private $classMap = array();
public function getPrefixes()
{
return $this->prefixes;
}
public function getFallbackDirs()
{
return $this->fallbackDirs;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of classes
*
* @param string $prefix The classes prefix
* @param array|string $paths The location(s) of the classes
*/
public function add($prefix, $paths)
{
if (!$prefix) {
foreach ((array) $paths as $path) {
$this->fallbackDirs[] = $path;
}
return;
}
if (isset($this->prefixes[$prefix])) {
$this->prefixes[$prefix] = array_merge(
$this->prefixes[$prefix],
(array) $paths
);
} else {
$this->prefixes[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include for class files.
*
* @param Boolean $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return Boolean
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Registers this instance as an autoloader.
*
* @param Boolean $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return Boolean|null True, if loaded
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
require $file;
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|null The path, if found
*/
public function findFile($class)
{
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ('\\' == $class[0]) {
$class = substr($class, 1);
}
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR;
$className = substr($class, $pos + 1);
} else {
// PEAR-like class name
$classPath = null;
$className = $class;
}
$classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
foreach ($this->prefixes as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
return $dir . DIRECTORY_SEPARATOR . $classPath;
}
}
}
}
foreach ($this->fallbackDirs as $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
return $dir . DIRECTORY_SEPARATOR . $classPath;
}
}
if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) {
return $file;
}
}
}

27
vendor/autoload.php vendored Normal file
View File

@ -0,0 +1,27 @@
<?php
// autoload.php generated by Composer
if (!class_exists('Composer\\Autoload\\ClassLoader', false)) {
require __DIR__ . '/composer' . '/ClassLoader.php';
}
require __DIR__ . '/swiftmailer/swiftmailer/lib/swift_required.php';
return call_user_func(function() {
$loader = new \Composer\Autoload\ClassLoader();
$composerDir = __DIR__ . '/composer';
$map = require $composerDir . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->add($namespace, $path);
}
$classMap = require $composerDir . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
$loader->register();
return $loader;
});

9
vendor/autoload_classmap.php vendored Normal file
View File

@ -0,0 +1,9 @@
<?php
// autoload_classmap.php generated by Composer
$vendorDir = __DIR__;
$baseDir = dirname($vendorDir);
return array(
);

32
vendor/autoload_namespaces.php vendored Normal file
View File

@ -0,0 +1,32 @@
<?php
// autoload_namespace.php generated by Composer
$vendorDir = __DIR__;
$baseDir = dirname($vendorDir);
return array(
'Twig_Extensions_' => $vendorDir . '/twig/extensions/lib/',
'Twig_' => $vendorDir . '/twig/twig/lib/',
'Symfony\\Bundle\\SwiftmailerBundle' => $vendorDir . '/symfony/swiftmailer-bundle/',
'Symfony\\Bundle\\MonologBundle' => $vendorDir . '/symfony/monolog-bundle/',
'Symfony\\Bundle\\AsseticBundle' => $vendorDir . '/symfony/assetic-bundle/',
'Symfony\\Bridge\\Swiftmailer' => $vendorDir . '/symfony/swiftmailer-bridge/',
'Symfony' => $vendorDir . '/symfony/symfony/src/',
'SessionHandlerInterface' => $vendorDir . '/symfony/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs',
'Sensio\\Bundle\\GeneratorBundle' => $vendorDir . '/sensio/generator-bundle/',
'Sensio\\Bundle\\FrameworkExtraBundle' => $vendorDir . '/sensio/framework-extra-bundle/',
'Sensio\\Bundle\\DistributionBundle' => $vendorDir . '/sensio/distribution-bundle/',
'Monolog' => $vendorDir . '/monolog/monolog/src/',
'Metadata\\' => $vendorDir . '/jms/metadata/src/',
'JMS\\SecurityExtraBundle' => $vendorDir . '/jms/security-extra-bundle/',
'JMS\\DiExtraBundle' => $vendorDir . '/jms/di-extra-bundle/',
'JMS\\AopBundle' => $vendorDir . '/jms/aop-bundle/',
'Doctrine\\ORM' => $vendorDir . '/doctrine/orm/lib/',
'Doctrine\\DBAL' => $vendorDir . '/doctrine/dbal/lib/',
'Doctrine\\Common' => $vendorDir . '/doctrine/common/lib/',
'Doctrine\\Bundle\\DoctrineBundle' => $vendorDir . '/doctrine/doctrine-bundle/',
'CG\\' => $vendorDir . '/jms/cg/src/',
'Assetic' => $vendorDir . '/kriswallsmith/assetic/src/',
'' => $baseDir . '/src/',
);

205
vendor/composer/ClassLoader.php vendored Normal file
View File

@ -0,0 +1,205 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0 class loader
*
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class ClassLoader
{
private $prefixes = array();
private $fallbackDirs = array();
private $useIncludePath = false;
private $classMap = array();
public function getPrefixes()
{
return $this->prefixes;
}
public function getFallbackDirs()
{
return $this->fallbackDirs;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of classes
*
* @param string $prefix The classes prefix
* @param array|string $paths The location(s) of the classes
*/
public function add($prefix, $paths)
{
if (!$prefix) {
foreach ((array) $paths as $path) {
$this->fallbackDirs[] = $path;
}
return;
}
if (isset($this->prefixes[$prefix])) {
$this->prefixes[$prefix] = array_merge(
$this->prefixes[$prefix],
(array) $paths
);
} else {
$this->prefixes[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param Boolean $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return Boolean
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Registers this instance as an autoloader.
*
* @param Boolean $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return Boolean|null True, if loaded
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
include $file;
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|null The path, if found
*/
public function findFile($class)
{
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ('\\' == $class[0]) {
$class = substr($class, 1);
}
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR;
$className = substr($class, $pos + 1);
} else {
// PEAR-like class name
$classPath = null;
$className = $class;
}
$classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
foreach ($this->prefixes as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
return $dir . DIRECTORY_SEPARATOR . $classPath;
}
}
}
}
foreach ($this->fallbackDirs as $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
return $dir . DIRECTORY_SEPARATOR . $classPath;
}
}
if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) {
return $file;
}
}
}

9
vendor/composer/autoload_classmap.php vendored Normal file
View File

@ -0,0 +1,9 @@
<?php
// autoload_classmap.php generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

31
vendor/composer/autoload_namespaces.php vendored Normal file
View File

@ -0,0 +1,31 @@
<?php
// autoload_namespace.php generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Twig_Extensions_' => $vendorDir . '/twig/extensions/lib/',
'Twig_' => $vendorDir . '/twig/twig/lib/',
'Symfony\\Bundle\\SwiftmailerBundle' => $vendorDir . '/symfony/swiftmailer-bundle/',
'Symfony\\Bundle\\MonologBundle' => $vendorDir . '/symfony/monolog-bundle/',
'Symfony\\Bundle\\AsseticBundle' => $vendorDir . '/symfony/assetic-bundle/',
'Symfony' => $vendorDir . '/symfony/symfony/src/',
'SessionHandlerInterface' => $vendorDir . '/symfony/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs',
'Sensio\\Bundle\\GeneratorBundle' => $vendorDir . '/sensio/generator-bundle/',
'Sensio\\Bundle\\FrameworkExtraBundle' => $vendorDir . '/sensio/framework-extra-bundle/',
'Sensio\\Bundle\\DistributionBundle' => $vendorDir . '/sensio/distribution-bundle/',
'Monolog' => $vendorDir . '/monolog/monolog/src/',
'Metadata\\' => $vendorDir . '/jms/metadata/src/',
'JMS\\SecurityExtraBundle' => $vendorDir . '/jms/security-extra-bundle/',
'JMS\\DiExtraBundle' => $vendorDir . '/jms/di-extra-bundle/',
'JMS\\AopBundle' => $vendorDir . '/jms/aop-bundle/',
'Doctrine\\ORM' => $vendorDir . '/doctrine/orm/lib/',
'Doctrine\\DBAL' => $vendorDir . '/doctrine/dbal/lib/',
'Doctrine\\Common' => $vendorDir . '/doctrine/common/lib/',
'Doctrine\\Bundle\\DoctrineBundle' => $vendorDir . '/doctrine/doctrine-bundle/',
'CG\\' => $vendorDir . '/jms/cg/src/',
'Assetic' => $vendorDir . '/kriswallsmith/assetic/src/',
'' => $baseDir . '/src/',
);

1171
vendor/composer/installed.json vendored Normal file

File diff suppressed because it is too large Load Diff

3
vendor/composer/installed_dev.json vendored Normal file
View File

@ -0,0 +1,3 @@
[
]

5
vendor/doctrine/common/.travis.yml vendored Normal file
View File

@ -0,0 +1,5 @@
language: php
php:
- 5.3
- 5.4

504
vendor/doctrine/common/LICENSE vendored Normal file
View File

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

12
vendor/doctrine/common/README.md vendored Normal file
View File

@ -0,0 +1,12 @@
# Doctrine Common
[![Build Status](https://secure.travis-ci.org/doctrine/common.png)](http://travis-ci.org/doctrine/common)
The Doctrine Common project is a library that provides extensions to core PHP functionality.
## More resources:
* [Website](http://www.doctrine-project.org)
* [Documentation](http://www.doctrine-project.org/projects/common/current/docs/en)
* [Issue Tracker](http://www.doctrine-project.org/jira/browse/DCOM)
* [Downloads](http://github.com/doctrine/common/downloads)

39
vendor/doctrine/common/UPGRADE_TO_2_1 vendored Normal file
View File

@ -0,0 +1,39 @@
This document details all the possible changes that you should investigate when updating
your project from Doctrine Common 2.0.x to 2.1
## AnnotationReader changes
The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory the operation of the new reader should be backwards compatible, but it has to be setup differently to work that way:
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
// new code necessary starting here
$reader->setIgnoreNotImportedAnnotations(true);
$reader->setEnableParsePhpImports(false);
$reader = new \Doctrine\Common\Annotations\CachedReader(
new \Doctrine\Common\Annotations\IndexedReader($reader), new ArrayCache()
);
## Annotation Base class or @Annotation
Beginning after 2.1-RC2 you have to either extend ``Doctrine\Common\Annotations\Annotation`` or add @Annotation to your annotations class-level docblock, otherwise the class will simply be ignored.
## Removed methods on AnnotationReader
* AnnotationReader::setAutoloadAnnotations()
* AnnotationReader::getAutoloadAnnotations()
* AnnotationReader::isAutoloadAnnotations()
## AnnotationRegistry
Autoloading through the PHP autoloader is removed from the 2.1 AnnotationReader. Instead you have to use the global AnnotationRegistry for loading purposes:
\Doctrine\Common\Annotations\AnnotationRegistry::registerFile($fileWithAnnotations);
\Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace($namespace, $dirs = null);
\Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespaces($namespaces);
\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader($callable);
The $callable for registering a loader accepts a class as first and only parameter and must try to silently autoload it. On success true has to be returned.
The registerAutoloadNamespace function registers a PSR-0 compatible silent autoloader for all classes with the given namespace in the given directories.
If null is passed as directory the include path will be used.

61
vendor/doctrine/common/UPGRADE_TO_2_2 vendored Normal file
View File

@ -0,0 +1,61 @@
This document details all the possible changes that you should investigate when
updating your project from Doctrine Common 2.1 to 2.2:
## Annotation Changes
- AnnotationReader::setIgnoreNotImportedAnnotations has been removed, you need to
add ignore annotation names which are supposed to be ignored via
AnnotationReader::addGlobalIgnoredName
- AnnotationReader::setAutoloadAnnotations was deprecated by the AnnotationRegistry
in 2.1 and has been removed in 2.2
- AnnotationReader::setEnableParsePhpImports was added to ease transition to the new
annotation mechanism in 2.1 and is removed in 2.2
- AnnotationReader::isParsePhpImportsEnabled is removed (see above)
- AnnotationReader::setDefaultAnnotationNamespace was deprecated in favor of explicit
configuration in 2.1 and will be removed in 2.2 (for isolated projects where you
have full-control over _all_ available annotations, we offer a dedicated reader
class ``SimpleAnnotationReader``)
- AnnotationReader::setAnnotationCreationFunction was deprecated in 2.1 and will be
removed in 2.2. We only offer two creation mechanisms which cannot be changed
anymore to allow the same reader instance to work with all annotations regardless
of which library they are coming from.
- AnnotationReader::setAnnotationNamespaceAlias was deprecated in 2.1 and will be
removed in 2.2 (see setDefaultAnnotationNamespace)
- If you use a class as annotation which has not the @Annotation marker in it's
class block, we will now throw an exception instead of silently ignoring it. You
can however still achieve the previous behavior using the @IgnoreAnnotation, or
AnnotationReader::addGlobalIgnoredName (the exception message will contain detailed
instructions when you run into this problem).
## Cache Changes
- Renamed old AbstractCache to CacheProvider
- Dropped the support to the following functions of all cache providers:
- CacheProvider::deleteByWildcard
- CacheProvider::deleteByRegEx
- CacheProvider::deleteByPrefix
- CacheProvider::deleteBySuffix
- CacheProvider::deleteAll will not remove ALL entries, it will only mark them as invalid
- CacheProvider::flushAll will remove ALL entries, namespaced or not
- Added support to MemcachedCache
- Added support to WincacheCache
## ClassLoader Changes
- ClassLoader::fileExistsInIncludePath() no longer exists. Use the native stream_resolve_include_path() PHP function

21
vendor/doctrine/common/composer.json vendored Normal file
View File

@ -0,0 +1,21 @@
{
"name": "doctrine/common",
"type": "library","version":"2.2.2",
"description": "Common Library for Doctrine projects",
"keywords": ["collections", "spl", "eventmanager", "annotations", "persistence"],
"homepage": "http://www.doctrine-project.org",
"license": "LGPL",
"authors": [
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
{"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
],
"require": {
"php": ">=5.3.2"
},
"autoload": {
"psr-0": { "Doctrine\\Common": "lib/" }
}
}

View File

@ -0,0 +1,75 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
/**
* Annotations class
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Annotation
{
/**
* Value property. Common among all derived classes.
*
* @var string
*/
public $value;
/**
* Constructor
*
* @param array $data Key-value for properties to be defined in this class
*/
public final function __construct(array $data)
{
foreach ($data as $key => $value) {
$this->$key = $value;
}
}
/**
* Error handler for unknown property accessor in Annotation class.
*
* @param string $name Unknown property name
*/
public function __get($name)
{
throw new \BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
);
}
/**
* Error handler for unknown property mutator in Annotation class.
*
* @param string $name Unkown property name
* @param mixed $value Property value
*/
public function __set($name, $value)
{
throw new \BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
);
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check the attribute type during the parsing process.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*
* @Annotation
*/
final class Attribute
{
/**
* @var string
*/
public $name;
/**
* @var string
*/
public $type;
/**
* @var boolean
*/
public $required = false;
}

View File

@ -0,0 +1,37 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check the types of all declared attributes during the parsing process.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*
* @Annotation
*/
final class Attributes
{
/**
* @var array<Doctrine\Common\Annotations\Annotation\Attribute>
*/
public $value;
}

View File

@ -0,0 +1,44 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser to ignore specific
* annotations during the parsing process.
*
* @Annotation
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
final class IgnoreAnnotation
{
public $names;
public function __construct(array $values)
{
if (is_string($values['value'])) {
$values['value'] = array($values['value']);
}
if (!is_array($values['value'])) {
throw new \RuntimeException(sprintf('@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', json_encode($values['value'])));
}
$this->names = $values['value'];
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check if that attribute is required during the parsing process.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*
* @Annotation
*/
final class Required
{
}

View File

@ -0,0 +1,105 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check the annotation target during the parsing process.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*
* @Annotation
*/
final class Target
{
const TARGET_CLASS = 1;
const TARGET_METHOD = 2;
const TARGET_PROPERTY = 4;
const TARGET_ANNOTATION = 8;
const TARGET_ALL = 15;
/**
* @var array
*/
private static $map = array(
'ALL' => self::TARGET_ALL,
'CLASS' => self::TARGET_CLASS,
'METHOD' => self::TARGET_METHOD,
'PROPERTY' => self::TARGET_PROPERTY,
'ANNOTATION' => self::TARGET_ANNOTATION,
);
/**
* @var array
*/
public $value;
/**
* Targets as bitmask.
*
* @var integer
*/
public $targets;
/**
* Literal target declaration.
*
* @var integer
*/
public $literal;
/**
* Annotation construct
*
* @param array $values
*/
public function __construct(array $values)
{
if (!isset($values['value'])){
$values['value'] = null;
}
if (is_string($values['value'])){
$values['value'] = array($values['value']);
}
if (!is_array($values['value'])){
throw new \InvalidArgumentException(
sprintf('@Target expects either a string value, or an array of strings, "%s" given.',
is_object($values['value']) ? get_class($values['value']) : gettype($values['value'])
)
);
}
$bitmask = 0;
foreach ($values['value'] as $literal) {
if(!isset(self::$map[$literal])){
throw new \InvalidArgumentException(
sprintf('Invalid Target "%s". Available targets: [%s]',
$literal, implode(', ', array_keys(self::$map)))
);
}
$bitmask += self::$map[$literal];
}
$this->targets = $bitmask;
$this->value = $values['value'];
$this->literal = implode(', ', $this->value);
}
}

View File

@ -0,0 +1,111 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
/**
* Description of AnnotationException
*
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class AnnotationException extends \Exception
{
/**
* Creates a new AnnotationException describing a Syntax error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function syntaxError($message)
{
return new self('[Syntax Error] ' . $message);
}
/**
* Creates a new AnnotationException describing a Semantical error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function semanticalError($message)
{
return new self('[Semantical Error] ' . $message);
}
/**
* Creates a new AnnotationException describing an error which occurred during
* the creation of the annotation.
*
* @since 2.2
* @param string $message
* @return AnnotationException
*/
public static function creationError($message)
{
return new self('[Creation Error] ' . $message);
}
/**
* Creates a new AnnotationException describing an type error of an attribute.
*
* @since 2.2
* @param string $attributeName
* @param string $annotationName
* @param string $context
* @param string $expected
* @param mixed $actual
* @return AnnotationException
*/
public static function typeError($attributeName, $annotationName, $context, $expected, $actual)
{
return new self(sprintf(
'[Type Error] Attribute "%s" of @%s declared on %s expects %s, but got %s.',
$attributeName,
$annotationName,
$context,
$expected,
is_object($actual) ? 'an instance of '.get_class($actual) : gettype($actual)
));
}
/**
* Creates a new AnnotationException describing an required error of an attribute.
*
* @since 2.2
* @param string $attributeName
* @param string $annotationName
* @param string $context
* @param string $expected
* @return AnnotationException
*/
public static function requiredError($attributeName, $annotationName, $context, $expected)
{
return new self(sprintf(
'[Type Error] Attribute "%s" of @%s declared on %s expects %s. This value should not be null.',
$attributeName,
$annotationName,
$context,
$expected
));
}
}

View File

@ -0,0 +1,301 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
use Doctrine\Common\Annotations\Annotation\Target;
use Closure;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
/**
* A reader for docblock annotations.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
final class AnnotationReader implements Reader
{
/**
* Global map for imports.
*
* @var array
*/
private static $globalImports = array(
'ignoreannotation' => 'Doctrine\Common\Annotations\Annotation\IgnoreAnnotation',
);
/**
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
*
* The names are case sensitive.
*
* @var array
*/
private static $globalIgnoredNames = array(
'access'=> true, 'author'=> true, 'copyright'=> true, 'deprecated'=> true,
'example'=> true, 'ignore'=> true, 'internal'=> true, 'link'=> true, 'see'=> true,
'since'=> true, 'tutorial'=> true, 'version'=> true, 'package'=> true,
'subpackage'=> true, 'name'=> true, 'global'=> true, 'param'=> true,
'return'=> true, 'staticvar'=> true, 'category'=> true, 'staticVar'=> true,
'static'=> true, 'var'=> true, 'throws'=> true, 'inheritdoc'=> true,
'inheritDoc'=> true, 'license'=> true, 'todo'=> true, 'deprecated'=> true,
'deprec'=> true, 'author'=> true, 'property' => true, 'method' => true,
'abstract'=> true, 'exception'=> true, 'magic' => true, 'api' => true,
'final'=> true, 'filesource'=> true, 'throw' => true, 'uses' => true,
'usedby'=> true, 'private' => true, 'Annotation' => true, 'override' => true,
'codeCoverageIgnore' => true, 'codeCoverageIgnoreStart' => true, 'codeCoverageIgnoreEnd' => true,
'Required' => true, 'Attribute' => true, 'Attributes' => true,
'Target' => true, 'SuppressWarnings' => true,
);
/**
* Add a new annotation to the globally ignored annotation names with regard to exception handling.
*
* @param string $name
*/
static public function addGlobalIgnoredName($name)
{
self::$globalIgnoredNames[$name] = true;
}
/**
* Annotations Parser
*
* @var Doctrine\Common\Annotations\DocParser
*/
private $parser;
/**
* Annotations Parser used to collect parsing metadata
*
* @var Doctrine\Common\Annotations\DocParser
*/
private $preParser;
/**
* PHP Parser used to collect imports.
*
* @var Doctrine\Common\Annotations\PhpParser
*/
private $phpParser;
/**
* In-memory cache mechanism to store imported annotations per class.
*
* @var array
*/
private $imports = array();
/**
* In-memory cache mechanism to store ignored annotations per class.
*
* @var array
*/
private $ignoredAnnotationNames = array();
/**
* Constructor.
*
* Initializes a new AnnotationReader.
*/
public function __construct()
{
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/IgnoreAnnotation.php');
$this->parser = new DocParser;
$this->preParser = new DocParser;
$this->preParser->setImports(self::$globalImports);
$this->preParser->setIgnoreNotImportedAnnotations(true);
$this->phpParser = new PhpParser;
}
/**
* Gets the annotations applied to a class.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
* @return array An array of Annotations.
*/
public function getClassAnnotations(ReflectionClass $class)
{
$this->parser->setTarget(Target::TARGET_CLASS);
$this->parser->setImports($this->getImports($class));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
}
/**
* Gets a class annotation.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
$annotations = $this->getClassAnnotations($class);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Gets the annotations applied to a property.
*
* @param ReflectionProperty $property The ReflectionProperty of the property
* from which the annotations should be read.
* @return array An array of Annotations.
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$context = 'property ' . $class->getName() . "::\$" . $property->getName();
$this->parser->setTarget(Target::TARGET_PROPERTY);
$this->parser->setImports($this->getImports($class));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
return $this->parser->parse($property->getDocComment(), $context);
}
/**
* Gets a property annotation.
*
* @param ReflectionProperty $property
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
$annotations = $this->getPropertyAnnotations($property);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Gets the annotations applied to a method.
*
* @param ReflectionMethod $property The ReflectionMethod of the method from which
* the annotations should be read.
* @return array An array of Annotations.
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$context = 'method ' . $class->getName() . '::' . $method->getName() . '()';
$this->parser->setTarget(Target::TARGET_METHOD);
$this->parser->setImports($this->getImports($class));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
return $this->parser->parse($method->getDocComment(), $context);
}
/**
* Gets a method annotation.
*
* @param ReflectionMethod $method
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
$annotations = $this->getMethodAnnotations($method);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Returns the ignored annotations for the given class.
*
* @param ReflectionClass $class
* @return array
*/
private function getIgnoredAnnotationNames(ReflectionClass $class)
{
if (isset($this->ignoredAnnotationNames[$name = $class->getName()])) {
return $this->ignoredAnnotationNames[$name];
}
$this->collectParsingMetadata($class);
return $this->ignoredAnnotationNames[$name];
}
private function getImports(ReflectionClass $class)
{
if (isset($this->imports[$name = $class->getName()])) {
return $this->imports[$name];
}
$this->collectParsingMetadata($class);
return $this->imports[$name];
}
/**
* Collects parsing metadata for a given class
*
* @param ReflectionClass $class
*/
private function collectParsingMetadata(ReflectionClass $class)
{
$ignoredAnnotationNames = self::$globalIgnoredNames;
$annotations = $this->preParser->parse($class->getDocComment(), 'class '.$class->name);
foreach ($annotations as $annotation) {
if ($annotation instanceof IgnoreAnnotation) {
foreach ($annotation->names AS $annot) {
$ignoredAnnotationNames[$annot] = true;
}
}
}
$name = $class->getName();
$this->imports[$name] = array_merge(
self::$globalImports,
$this->phpParser->parseClass($class),
array('__NAMESPACE__' => $class->getNamespaceName())
);
$this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames;
}
}

View File

@ -0,0 +1,129 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
final class AnnotationRegistry
{
/**
* A map of namespaces to use for autoloading purposes based on a PSR-0 convention.
*
* Contains the namespace as key and an array of directories as value. If the value is NULL
* the include path is used for checking for the corresponding file.
*
* This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own.
*
* @var array
*/
static private $autoloadNamespaces = array();
/**
* A map of autoloader callables.
*
* @var array
*/
static private $loaders = array();
static public function reset()
{
self::$autoloadNamespaces = array();
self::$loaders = array();
}
static public function registerFile($file)
{
require_once $file;
}
/**
* Add a namespace with one or many directories to look for files or null for the include path.
*
* Loading of this namespaces will be done with a PSR-0 namespace loading algorithm.
*
* @param string $namespace
* @param string|array|null $dirs
*/
static public function registerAutoloadNamespace($namespace, $dirs = null)
{
self::$autoloadNamespaces[$namespace] = $dirs;
}
/**
* Register multiple namespaces
*
* Loading of this namespaces will be done with a PSR-0 namespace loading algorithm.
*
* @param array $namespaces
*/
static public function registerAutoloadNamespaces(array $namespaces)
{
self::$autoloadNamespaces = array_merge(self::$autoloadNamespaces, $namespaces);
}
/**
* Register an autoloading callabale for annotations, much like spl_autoload_register().
*
* NOTE: These class loaders HAVE to be silent when a class was not found!
* IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class.
*
* @param callabale $callabale
*/
static public function registerLoader($callabale)
{
if (!is_callable($callabale)) {
throw new \InvalidArgumentException("A callable is expected in AnnotationRegistry::registerLoader().");
}
self::$loaders[] = $callabale;
}
/**
* Autoload an annotation class silently.
*
* @param string $class
* @return void
*/
static public function loadAnnotationClass($class)
{
foreach (self::$autoloadNamespaces AS $namespace => $dirs) {
if (strpos($class, $namespace) === 0) {
$file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php";
if ($dirs === null) {
if ($path = stream_resolve_include_path($file)) {
require $path;
return true;
}
} else {
foreach((array)$dirs AS $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $file)) {
require $dir . DIRECTORY_SEPARATOR . $file;
return true;
}
}
}
}
}
foreach (self::$loaders AS $loader) {
if (call_user_func($loader, $class) === true) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,179 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Cache\Cache;
/**
* A cache aware annotation reader.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
final class CachedReader implements Reader
{
private static $CACHE_SALT = '@[Annot]';
/**
* @var Reader
*/
private $delegate;
/**
* @var Cache
*/
private $cache;
/**
* @var boolean
*/
private $debug;
/**
* @var array
*/
private $loadedAnnotations;
/**
* @param Reader $reader
* @param Cache $cache
*/
public function __construct(Reader $reader, Cache $cache, $debug = false)
{
$this->delegate = $reader;
$this->cache = $cache;
$this->debug = $debug;
}
public function getClassAnnotations(\ReflectionClass $class)
{
$cacheKey = $class->getName() . self::$CACHE_SALT;
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
// Attempt to grab data from cache
if (($data = $this->cache->fetch($cacheKey)) !== false) {
if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
return $data;
}
}
$annots = $this->delegate->getClassAnnotations($class);
$this->cache->save($cacheKey, $annots);
$this->cache->save('[C]'.$cacheKey, time());
return $this->loadedAnnotations[$cacheKey] = $annots;
}
public function getClassAnnotation(\ReflectionClass $class, $annotationName)
{
foreach ($this->getClassAnnotations($class) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
public function getPropertyAnnotations(\ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$cacheKey = $class->getName().'$'.$property->getName().self::$CACHE_SALT;
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
// Attempt to grab data from cache
if (($data = $this->cache->fetch($cacheKey)) !== false) {
if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
return $data;
}
}
$annots = $this->delegate->getPropertyAnnotations($property);
$this->cache->save($cacheKey, $annots);
$this->cache->save('[C]'.$cacheKey, time());
return $this->loadedAnnotations[$cacheKey] = $annots;
}
public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
{
foreach ($this->getPropertyAnnotations($property) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
public function getMethodAnnotations(\ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$cacheKey = $class->getName().'#'.$method->getName().self::$CACHE_SALT;
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
// Attempt to grab data from cache
if (($data = $this->cache->fetch($cacheKey)) !== false) {
if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
return $data;
}
}
$annots = $this->delegate->getMethodAnnotations($method);
$this->cache->save($cacheKey, $annots);
$this->cache->save('[C]'.$cacheKey, time());
return $this->loadedAnnotations[$cacheKey] = $annots;
}
public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
{
foreach ($this->getMethodAnnotations($method) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
public function clearLoadedAnnotations()
{
$this->loadedAnnotations = array();
}
private function isCacheFresh($cacheKey, \ReflectionClass $class)
{
if (false === $filename = $class->getFilename()) {
return true;
}
return $this->cache->fetch('[C]'.$cacheKey) >= filemtime($filename);
}
}

View File

@ -0,0 +1,140 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Lexer;
/**
* Simple lexer for docblock annotations.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
final class DocLexer extends Lexer
{
const T_NONE = 1;
const T_IDENTIFIER = 2;
const T_INTEGER = 3;
const T_STRING = 4;
const T_FLOAT = 5;
const T_AT = 101;
const T_CLOSE_CURLY_BRACES = 102;
const T_CLOSE_PARENTHESIS = 103;
const T_COMMA = 104;
const T_EQUALS = 105;
const T_FALSE = 106;
const T_NAMESPACE_SEPARATOR = 107;
const T_OPEN_CURLY_BRACES = 108;
const T_OPEN_PARENTHESIS = 109;
const T_TRUE = 110;
const T_NULL = 111;
const T_COLON = 112;
/**
* @inheritdoc
*/
protected function getCatchablePatterns()
{
return array(
'[a-z_][a-z0-9_:]*',
'(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?',
'"(?:[^"]|"")*"',
);
}
/**
* @inheritdoc
*/
protected function getNonCatchablePatterns()
{
return array('\s+', '\*+', '(.)');
}
/**
* @inheritdoc
*/
protected function getType(&$value)
{
$type = self::T_NONE;
// Checking numeric value
if (is_numeric($value)) {
return (strpos($value, '.') !== false || stripos($value, 'e') !== false)
? self::T_FLOAT : self::T_INTEGER;
}
if ($value[0] === '"') {
$value = str_replace('""', '"', substr($value, 1, strlen($value) - 2));
return self::T_STRING;
} else {
switch (strtolower($value)) {
case '@':
return self::T_AT;
case ',':
return self::T_COMMA;
case '(':
return self::T_OPEN_PARENTHESIS;
case ')':
return self::T_CLOSE_PARENTHESIS;
case '{':
return self::T_OPEN_CURLY_BRACES;
case '}':
return self::T_CLOSE_CURLY_BRACES;
case '=':
return self::T_EQUALS;
case '\\':
return self::T_NAMESPACE_SEPARATOR;
case 'true':
return self::T_TRUE;
case 'false':
return self::T_FALSE;
case 'null':
return self::T_NULL;
case ':':
return self::T_COLON;
default:
if (ctype_alpha($value[0]) || $value[0] === '_') {
return self::T_IDENTIFIER;
}
break;
}
}
return $type;
}
}

View File

@ -0,0 +1,891 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use Closure;
use ReflectionClass;
use Doctrine\Common\Annotations\Annotation\Target;
use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Attributes;
/**
* A parser for docblock annotations.
*
* It is strongly discouraged to change the default annotation parsing process.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
final class DocParser
{
/**
* An array of all valid tokens for a class name.
*
* @var array
*/
private static $classIdentifiers = array(DocLexer::T_IDENTIFIER, DocLexer::T_TRUE, DocLexer::T_FALSE, DocLexer::T_NULL);
/**
* The lexer.
*
* @var Doctrine\Common\Annotations\DocLexer
*/
private $lexer;
/**
* Current target context
*
* @var string
*/
private $target;
/**
* Doc Parser used to collect annotation target
*
* @var Doctrine\Common\Annotations\DocParser
*/
private static $metadataParser;
/**
* Flag to control if the current annotation is nested or not.
*
* @var boolean
*/
private $isNestedAnnotation = false;
/**
* Hashmap containing all use-statements that are to be used when parsing
* the given doc block.
*
* @var array
*/
private $imports = array();
/**
* This hashmap is used internally to cache results of class_exists()
* look-ups.
*
* @var array
*/
private $classExists = array();
/**
* Whether annotations that have not been imported should be ignored.
*
* @var boolean
*/
private $ignoreNotImportedAnnotations = false;
/**
* An array of default namespaces if operating in simple mode.
*
* @var array
*/
private $namespaces = array();
/**
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
*
* The names must be the raw names as used in the class, not the fully qualified
* class names.
*
* @var array
*/
private $ignoredAnnotationNames = array();
/**
* @var string
*/
private $context = '';
/**
* Hash-map for caching annotation metadata
* @var array
*/
private static $annotationMetadata = array(
'Doctrine\Common\Annotations\Annotation\Target' => array(
'is_annotation' => true,
'has_constructor' => true,
'properties' => array(),
'targets_literal' => 'ANNOTATION_CLASS',
'targets' => Target::TARGET_CLASS,
'default_property' => 'value',
'attribute_types' => array(
'value' => array(
'required' => false,
'type' =>'array',
'array_type'=>'string',
'value' =>'array<string>'
)
),
),
'Doctrine\Common\Annotations\Annotation\Attribute' => array(
'is_annotation' => true,
'has_constructor' => false,
'targets_literal' => 'ANNOTATION_ANNOTATION',
'targets' => Target::TARGET_ANNOTATION,
'default_property' => 'name',
'properties' => array(
'name' => 'name',
'type' => 'type',
'required' => 'required'
),
'attribute_types' => array(
'value' => array(
'required' => true,
'type' =>'string',
'value' =>'string'
),
'type' => array(
'required' =>true,
'type' =>'string',
'value' =>'string'
),
'required' => array(
'required' =>false,
'type' =>'boolean',
'value' =>'boolean'
)
),
),
'Doctrine\Common\Annotations\Annotation\Attributes' => array(
'is_annotation' => true,
'has_constructor' => false,
'targets_literal' => 'ANNOTATION_CLASS',
'targets' => Target::TARGET_CLASS,
'default_property' => 'value',
'properties' => array(
'value' => 'value'
),
'attribute_types' => array(
'value' => array(
'type' =>'array',
'required' =>true,
'array_type'=>'Doctrine\Common\Annotations\Annotation\Attribute',
'value' =>'array<Doctrine\Common\Annotations\Annotation\Attribute>'
)
),
),
);
/**
* Hash-map for handle types declaration
*
* @var array
*/
private static $typeMap = array(
'float' => 'double',
'bool' => 'boolean',
// allow uppercase Boolean in honor of George Boole
'Boolean' => 'boolean',
'int' => 'integer',
);
/**
* Constructs a new DocParser.
*/
public function __construct()
{
$this->lexer = new DocLexer;
}
/**
* Sets the annotation names that are ignored during the parsing process.
*
* The names are supposed to be the raw names as used in the class, not the
* fully qualified class names.
*
* @param array $names
*/
public function setIgnoredAnnotationNames(array $names)
{
$this->ignoredAnnotationNames = $names;
}
public function setIgnoreNotImportedAnnotations($bool)
{
$this->ignoreNotImportedAnnotations = (Boolean) $bool;
}
/**
* Sets the default namespaces.
* @param array $namespaces
*/
public function addNamespace($namespace)
{
if ($this->imports) {
throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.');
}
$this->namespaces[] = $namespace;
}
public function setImports(array $imports)
{
if ($this->namespaces) {
throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.');
}
$this->imports = $imports;
}
/**
* Sets current target context as bitmask.
*
* @param integer $target
*/
public function setTarget($target)
{
$this->target = $target;
}
/**
* Parses the given docblock string for annotations.
*
* @param string $input The docblock string to parse.
* @param string $context The parsing context.
* @return array Array of annotations. If no annotations are found, an empty array is returned.
*/
public function parse($input, $context = '')
{
if (false === $pos = strpos($input, '@')) {
return array();
}
// also parse whatever character is before the @
if ($pos > 0) {
$pos -= 1;
}
$this->context = $context;
$this->lexer->setInput(trim(substr($input, $pos), '* /'));
$this->lexer->moveNext();
return $this->Annotations();
}
/**
* Attempts to match the given token with the current lookahead token.
* If they match, updates the lookahead token; otherwise raises a syntax error.
*
* @param int Token type.
* @return bool True if tokens match; false otherwise.
*/
private function match($token)
{
if ( ! $this->lexer->isNextToken($token) ) {
$this->syntaxError($this->lexer->getLiteral($token));
}
return $this->lexer->moveNext();
}
/**
* Attempts to match the current lookahead token with any of the given tokens.
*
* If any of them matches, this method updates the lookahead token; otherwise
* a syntax error is raised.
*
* @param array $tokens
* @return bool
*/
private function matchAny(array $tokens)
{
if ( ! $this->lexer->isNextTokenAny($tokens)) {
$this->syntaxError(implode(' or ', array_map(array($this->lexer, 'getLiteral'), $tokens)));
}
return $this->lexer->moveNext();
}
/**
* Generates a new syntax error.
*
* @param string $expected Expected string.
* @param array $token Optional token.
* @throws SyntaxException
*/
private function syntaxError($expected, $token = null)
{
if ($token === null) {
$token = $this->lexer->lookahead;
}
$message = "Expected {$expected}, got ";
if ($this->lexer->lookahead === null) {
$message .= 'end of string';
} else {
$message .= "'{$token['value']}' at position {$token['position']}";
}
if (strlen($this->context)) {
$message .= ' in ' . $this->context;
}
$message .= '.';
throw AnnotationException::syntaxError($message);
}
/**
* Attempt to check if a class exists or not. This never goes through the PHP autoloading mechanism
* but uses the {@link AnnotationRegistry} to load classes.
*
* @param string $fqcn
* @return boolean
*/
private function classExists($fqcn)
{
if (isset($this->classExists[$fqcn])) {
return $this->classExists[$fqcn];
}
// first check if the class already exists, maybe loaded through another AnnotationReader
if (class_exists($fqcn, false)) {
return $this->classExists[$fqcn] = true;
}
// final check, does this class exist?
return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn);
}
/**
* Collects parsing metadata for a given annotation class
*
* @param string $name The annotation name
*/
private function collectAnnotationMetadata($name)
{
if (self::$metadataParser == null){
self::$metadataParser = new self();
self::$metadataParser->setTarget(Target::TARGET_CLASS);
self::$metadataParser->setIgnoreNotImportedAnnotations(true);
self::$metadataParser->setImports(array(
'target' => 'Doctrine\Common\Annotations\Annotation\Target',
'attribute' => 'Doctrine\Common\Annotations\Annotation\Attribute',
'attributes' => 'Doctrine\Common\Annotations\Annotation\Attributes'
));
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Target.php');
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attribute.php');
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attributes.php');
}
$class = new \ReflectionClass($name);
$docComment = $class->getDocComment();
// Sets default values for annotation metadata
$metadata = array(
'default_property' => null,
'has_constructor' => (null !== $constructor = $class->getConstructor()) && $constructor->getNumberOfParameters() > 0,
'properties' => array(),
'property_types' => array(),
'attribute_types' => array(),
'targets_literal' => null,
'targets' => Target::TARGET_ALL,
'is_annotation' => false !== strpos($docComment, '@Annotation'),
);
// verify that the class is really meant to be an annotation
if ($metadata['is_annotation']) {
foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) {
if ($annotation instanceof Target) {
$metadata['targets'] = $annotation->targets;
$metadata['targets_literal'] = $annotation->literal;
} elseif ($annotation instanceof Attributes) {
foreach ($annotation->value as $attrib) {
// handle internal type declaration
$type = isset(self::$typeMap[$attrib->type]) ? self::$typeMap[$attrib->type] : $attrib->type;
// handle the case if the property type is mixed
if ('mixed' !== $type) {
// Checks if the property has array<type>
if (false !== $pos = strpos($type, '<')) {
$arrayType = substr($type, $pos+1, -1);
$type = 'array';
if (isset(self::$typeMap[$arrayType])) {
$arrayType = self::$typeMap[$arrayType];
}
$metadata['attribute_types'][$attrib->name]['array_type'] = $arrayType;
}
$metadata['attribute_types'][$attrib->name]['type'] = $type;
$metadata['attribute_types'][$attrib->name]['value'] = $attrib->type;
$metadata['attribute_types'][$attrib->name]['required'] = $attrib->required;
}
}
}
}
// if not has a constructor will inject values into public properties
if (false === $metadata['has_constructor']) {
// collect all public properties
foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
$metadata['properties'][$property->name] = $property->name;
// checks if the property has @var annotation
if ((false !== $propertyComment = $property->getDocComment())
&& false !== strpos($propertyComment, '@var')
&& preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches)) {
// literal type declaration
$value = $matches[1];
// handle internal type declaration
$type = isset(self::$typeMap[$value]) ? self::$typeMap[$value] : $value;
// handle the case if the property type is mixed
if ('mixed' !== $type) {
// Checks if the property has @var array<type> annotation
if (false !== $pos = strpos($type, '<')) {
$arrayType = substr($type, $pos+1, -1);
$type = 'array';
if (isset(self::$typeMap[$arrayType])) {
$arrayType = self::$typeMap[$arrayType];
}
$metadata['attribute_types'][$property->name]['array_type'] = $arrayType;
}
$metadata['attribute_types'][$property->name]['type'] = $type;
$metadata['attribute_types'][$property->name]['value'] = $value;
$metadata['attribute_types'][$property->name]['required'] = false !== strpos($propertyComment, '@Required');
}
}
}
// choose the first property as default property
$metadata['default_property'] = reset($metadata['properties']);
}
}
self::$annotationMetadata[$name] = $metadata;
}
/**
* Annotations ::= Annotation {[ "*" ]* [Annotation]}*
*
* @return array
*/
private function Annotations()
{
$annotations = array();
while (null !== $this->lexer->lookahead) {
if (DocLexer::T_AT !== $this->lexer->lookahead['type']) {
$this->lexer->moveNext();
continue;
}
// make sure the @ is preceded by non-catchable pattern
if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) {
$this->lexer->moveNext();
continue;
}
// make sure the @ is followed by either a namespace separator, or
// an identifier token
if ((null === $peek = $this->lexer->glimpse())
|| (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true))
|| $peek['position'] !== $this->lexer->lookahead['position'] + 1) {
$this->lexer->moveNext();
continue;
}
$this->isNestedAnnotation = false;
if (false !== $annot = $this->Annotation()) {
$annotations[] = $annot;
}
}
return $annotations;
}
/**
* Annotation ::= "@" AnnotationName ["(" [Values] ")"]
* AnnotationName ::= QualifiedName | SimpleName
* QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName
* NameSpacePart ::= identifier | null | false | true
* SimpleName ::= identifier | null | false | true
*
* @return mixed False if it is not a valid annotation.
*/
private function Annotation()
{
$this->match(DocLexer::T_AT);
// check if we have an annotation
if ($this->lexer->isNextTokenAny(self::$classIdentifiers)) {
$this->lexer->moveNext();
$name = $this->lexer->token['value'];
} else if ($this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)) {
$name = '';
} else {
$this->syntaxError('namespace separator or identifier');
}
while ($this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value']) && $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)) {
$this->match(DocLexer::T_NAMESPACE_SEPARATOR);
$this->matchAny(self::$classIdentifiers);
$name .= '\\'.$this->lexer->token['value'];
}
// only process names which are not fully qualified, yet
// fully qualified names must start with a \
$originalName = $name;
if ('\\' !== $name[0]) {
$alias = (false === $pos = strpos($name, '\\'))? $name : substr($name, 0, $pos);
$found = false;
if ($this->namespaces) {
foreach ($this->namespaces as $namespace) {
if ($this->classExists($namespace.'\\'.$name)) {
$name = $namespace.'\\'.$name;
$found = true;
break;
}
}
} elseif (isset($this->imports[$loweredAlias = strtolower($alias)])) {
if (false !== $pos) {
$name = $this->imports[$loweredAlias].substr($name, $pos);
} else {
$name = $this->imports[$loweredAlias];
}
$found = true;
} elseif (isset($this->imports['__NAMESPACE__']) && $this->classExists($this->imports['__NAMESPACE__'].'\\'.$name)) {
$name = $this->imports['__NAMESPACE__'].'\\'.$name;
$found = true;
} elseif ($this->classExists($name)) {
$found = true;
}
if (!$found) {
if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) {
return false;
}
throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context));
}
}
if (!$this->classExists($name)) {
throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context));
}
// at this point, $name contains the fully qualified class name of the
// annotation, and it is also guaranteed that this class exists, and
// that it is loaded
// collects the metadata annotation only if there is not yet
if (!isset(self::$annotationMetadata[$name])) {
$this->collectAnnotationMetadata($name);
}
// verify that the class is really meant to be an annotation and not just any ordinary class
if (self::$annotationMetadata[$name]['is_annotation'] === false) {
if (isset($this->ignoredAnnotationNames[$originalName])) {
return false;
}
throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context));
}
//if target is nested annotation
$target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target;
// Next will be nested
$this->isNestedAnnotation = true;
//if annotation does not support current target
if (0 === (self::$annotationMetadata[$name]['targets'] & $target) && $target) {
throw AnnotationException::semanticalError(
sprintf('Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s.',
$originalName, $this->context, self::$annotationMetadata[$name]['targets_literal'])
);
}
$values = array();
if ($this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) {
$this->match(DocLexer::T_OPEN_PARENTHESIS);
if ( ! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) {
$values = $this->Values();
}
$this->match(DocLexer::T_CLOSE_PARENTHESIS);
}
// checks all declared attributes
foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) {
if ($property === self::$annotationMetadata[$name]['default_property']
&& !isset($values[$property]) && isset($values['value'])) {
$property = 'value';
}
// handle a not given attribute or null value
if (!isset($values[$property])) {
if ($type['required']) {
throw AnnotationException::requiredError($property, $originalName, $this->context, 'a(n) '.$type['value']);
}
continue;
}
if ($type['type'] === 'array') {
// handle the case of a single value
if (!is_array($values[$property])) {
$values[$property] = array($values[$property]);
}
// checks if the attribute has array type declaration, such as "array<string>"
if (isset($type['array_type'])) {
foreach ($values[$property] as $item) {
if (gettype($item) !== $type['array_type'] && !$item instanceof $type['array_type']) {
throw AnnotationException::typeError($property, $originalName, $this->context, 'either a(n) '.$type['array_type'].', or an array of '.$type['array_type'].'s', $item);
}
}
}
} elseif (gettype($values[$property]) !== $type['type'] && !$values[$property] instanceof $type['type']) {
throw AnnotationException::typeError($property, $originalName, $this->context, 'a(n) '.$type['value'], $values[$property]);
}
}
// check if the annotation expects values via the constructor,
// or directly injected into public properties
if (self::$annotationMetadata[$name]['has_constructor'] === true) {
return new $name($values);
}
$instance = new $name();
foreach ($values as $property => $value) {
if (!isset(self::$annotationMetadata[$name]['properties'][$property])) {
if ('value' !== $property) {
throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not have a property named "%s". Available properties: %s', $originalName, $this->context, $property, implode(', ', self::$annotationMetadata[$name]['properties'])));
}
// handle the case if the property has no annotations
if (!$property = self::$annotationMetadata[$name]['default_property']) {
throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not accept any values, but got %s.', $originalName, $this->context, json_encode($values)));
}
}
$instance->{$property} = $value;
}
return $instance;
}
/**
* Values ::= Array | Value {"," Value}*
*
* @return array
*/
private function Values()
{
$values = array();
// Handle the case of a single array as value, i.e. @Foo({....})
if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) {
$values['value'] = $this->Value();
return $values;
}
$values[] = $this->Value();
while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
$this->match(DocLexer::T_COMMA);
$token = $this->lexer->lookahead;
$value = $this->Value();
if ( ! is_object($value) && ! is_array($value)) {
$this->syntaxError('Value', $token);
}
$values[] = $value;
}
foreach ($values as $k => $value) {
if (is_object($value) && $value instanceof \stdClass) {
$values[$value->name] = $value->value;
} else if ( ! isset($values['value'])){
$values['value'] = $value;
} else {
if ( ! is_array($values['value'])) {
$values['value'] = array($values['value']);
}
$values['value'][] = $value;
}
unset($values[$k]);
}
return $values;
}
/**
* Value ::= PlainValue | FieldAssignment
*
* @return mixed
*/
private function Value()
{
$peek = $this->lexer->glimpse();
if (DocLexer::T_EQUALS === $peek['type']) {
return $this->FieldAssignment();
}
return $this->PlainValue();
}
/**
* PlainValue ::= integer | string | float | boolean | Array | Annotation
*
* @return mixed
*/
private function PlainValue()
{
if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) {
return $this->Arrayx();
}
if ($this->lexer->isNextToken(DocLexer::T_AT)) {
return $this->Annotation();
}
switch ($this->lexer->lookahead['type']) {
case DocLexer::T_STRING:
$this->match(DocLexer::T_STRING);
return $this->lexer->token['value'];
case DocLexer::T_INTEGER:
$this->match(DocLexer::T_INTEGER);
return (int)$this->lexer->token['value'];
case DocLexer::T_FLOAT:
$this->match(DocLexer::T_FLOAT);
return (float)$this->lexer->token['value'];
case DocLexer::T_TRUE:
$this->match(DocLexer::T_TRUE);
return true;
case DocLexer::T_FALSE:
$this->match(DocLexer::T_FALSE);
return false;
case DocLexer::T_NULL:
$this->match(DocLexer::T_NULL);
return null;
default:
$this->syntaxError('PlainValue');
}
}
/**
* FieldAssignment ::= FieldName "=" PlainValue
* FieldName ::= identifier
*
* @return array
*/
private function FieldAssignment()
{
$this->match(DocLexer::T_IDENTIFIER);
$fieldName = $this->lexer->token['value'];
$this->match(DocLexer::T_EQUALS);
$item = new \stdClass();
$item->name = $fieldName;
$item->value = $this->PlainValue();
return $item;
}
/**
* Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}"
*
* @return array
*/
private function Arrayx()
{
$array = $values = array();
$this->match(DocLexer::T_OPEN_CURLY_BRACES);
$values[] = $this->ArrayEntry();
while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
$this->match(DocLexer::T_COMMA);
// optional trailing comma
if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) {
break;
}
$values[] = $this->ArrayEntry();
}
$this->match(DocLexer::T_CLOSE_CURLY_BRACES);
foreach ($values as $value) {
list ($key, $val) = $value;
if ($key !== null) {
$array[$key] = $val;
} else {
$array[] = $val;
}
}
return $array;
}
/**
* ArrayEntry ::= Value | KeyValuePair
* KeyValuePair ::= Key ("=" | ":") PlainValue
* Key ::= string | integer
*
* @return array
*/
private function ArrayEntry()
{
$peek = $this->lexer->glimpse();
if (DocLexer::T_EQUALS === $peek['type']
|| DocLexer::T_COLON === $peek['type']) {
$this->matchAny(array(DocLexer::T_INTEGER, DocLexer::T_STRING));
$key = $this->lexer->token['value'];
$this->matchAny(array(DocLexer::T_EQUALS, DocLexer::T_COLON));
return array($key, $this->PlainValue());
}
return array(null, $this->Value());
}
}

View File

@ -0,0 +1,209 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
/**
* File cache reader for annotations.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class FileCacheReader implements Reader
{
/**
* @var Reader
*/
private $reader;
private $dir;
private $debug;
private $loadedAnnotations = array();
public function __construct(Reader $reader, $cacheDir, $debug = false)
{
$this->reader = $reader;
if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true)) {
throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir));
}
if (!is_writable($cacheDir)) {
throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable. Both, the webserver and the console user need access. You can manage access rights for multiple users with "chmod +a". If your system does not support this, check out the acl package.', $cacheDir));
}
$this->dir = rtrim($cacheDir, '\\/');
$this->debug = $debug;
}
public function getClassAnnotations(\ReflectionClass $class)
{
$key = $class->getName();
if (isset($this->loadedAnnotations[$key])) {
return $this->loadedAnnotations[$key];
}
$path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
if (!file_exists($path)) {
$annot = $this->reader->getClassAnnotations($class);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
if ($this->debug
&& (false !== $filename = $class->getFilename())
&& filemtime($path) < filemtime($filename)) {
@unlink($path);
$annot = $this->reader->getClassAnnotations($class);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
return $this->loadedAnnotations[$key] = include $path;
}
public function getPropertyAnnotations(\ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$key = $class->getName().'$'.$property->getName();
if (isset($this->loadedAnnotations[$key])) {
return $this->loadedAnnotations[$key];
}
$path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
if (!file_exists($path)) {
$annot = $this->reader->getPropertyAnnotations($property);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
if ($this->debug
&& (false !== $filename = $class->getFilename())
&& filemtime($path) < filemtime($filename)) {
unlink($path);
$annot = $this->reader->getPropertyAnnotations($property);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
return $this->loadedAnnotations[$key] = include $path;
}
public function getMethodAnnotations(\ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$key = $class->getName().'#'.$method->getName();
if (isset($this->loadedAnnotations[$key])) {
return $this->loadedAnnotations[$key];
}
$path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
if (!file_exists($path)) {
$annot = $this->reader->getMethodAnnotations($method);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
if ($this->debug
&& (false !== $filename = $class->getFilename())
&& filemtime($path) < filemtime($filename)) {
unlink($path);
$annot = $this->reader->getMethodAnnotations($method);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
return $this->loadedAnnotations[$key] = include $path;
}
private function saveCacheFile($path, $data)
{
file_put_contents($path, '<?php return unserialize('.var_export(serialize($data), true).');');
}
/**
* Gets a class annotation.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getClassAnnotation(\ReflectionClass $class, $annotationName)
{
$annotations = $this->getClassAnnotations($class);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Gets a method annotation.
*
* @param ReflectionMethod $method
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
{
$annotations = $this->getMethodAnnotations($method);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Gets a property annotation.
*
* @param ReflectionProperty $property
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
{
$annotations = $this->getPropertyAnnotations($property);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
public function clearLoadedAnnotations()
{
$this->loadedAnnotations = array();
}
}

View File

@ -0,0 +1,94 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Annotations\Reader;
/**
* Allows the reader to be used in-place of Doctrine's reader.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class IndexedReader implements Reader
{
private $delegate;
public function __construct(Reader $reader)
{
$this->delegate = $reader;
}
public function getClassAnnotations(\ReflectionClass $class)
{
$annotations = array();
foreach ($this->delegate->getClassAnnotations($class) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
public function getClassAnnotation(\ReflectionClass $class, $annotation)
{
return $this->delegate->getClassAnnotation($class, $annotation);
}
public function getMethodAnnotations(\ReflectionMethod $method)
{
$annotations = array();
foreach ($this->delegate->getMethodAnnotations($method) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
public function getMethodAnnotation(\ReflectionMethod $method, $annotation)
{
return $this->delegate->getMethodAnnotation($method, $annotation);
}
public function getPropertyAnnotations(\ReflectionProperty $property)
{
$annotations = array();
foreach ($this->delegate->getPropertyAnnotations($property) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
public function getPropertyAnnotation(\ReflectionProperty $property, $annotation)
{
return $this->delegate->getPropertyAnnotation($property, $annotation);
}
/**
* Proxy all methods to the delegate.
*
* @param type $method
* @param type $args
* @return type
*/
public function __call($method, $args)
{
return call_user_func_array(array($this->delegate, $method), $args);
}
}

View File

@ -0,0 +1,203 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use SplFileObject;
/**
* Parses a file for namespaces/use/class declarations.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Christian Kaps <christian.kaps@mohiva.com>
*/
final class PhpParser
{
/**
* The token list.
*
* @var array
*/
private $tokens;
/**
* The number of tokens.
*
* @var int
*/
private $numTokens = 0;
/**
* The current array pointer.
*
* @var int
*/
private $pointer = 0;
/**
* Parses a class.
*
* @param \ReflectionClass $class A <code>ReflectionClass</code> object.
* @return array A list with use statements in the form (Alias => FQN).
*/
public function parseClass(\ReflectionClass $class)
{
if (false === $filename = $class->getFilename()) {
return array();
}
$content = $this->getFileContent($filename, $class->getStartLine());
$namespace = str_replace('\\', '\\\\', $class->getNamespaceName());
$content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
$this->tokens = token_get_all('<?php ' . $content);
$this->numTokens = count($this->tokens);
$this->pointer = 0;
$statements = $this->parseUseStatements($class->getNamespaceName());
return $statements;
}
/**
* Get the content of the file right up to the given line number.
*
* @param string $filename The name of the file to load.
* @param int $lineNumber The number of lines to read from file.
* @return string The content of the file.
*/
private function getFileContent($filename, $lineNumber)
{
$content = '';
$lineCnt = 0;
$file = new SplFileObject($filename);
while(!$file->eof()) {
if ($lineCnt++ == $lineNumber) {
break;
}
$content .= $file->fgets();
}
return $content;
}
/**
* Gets the next non whitespace and non comment token.
*
* @return array The token if exists, null otherwise.
*/
private function next()
{
for ($i = $this->pointer; $i < $this->numTokens; $i++) {
$this->pointer++;
if ($this->tokens[$i][0] === T_WHITESPACE ||
$this->tokens[$i][0] === T_COMMENT ||
$this->tokens[$i][0] === T_DOC_COMMENT) {
continue;
}
return $this->tokens[$i];
}
return null;
}
/**
* Get all use statements.
*
* @param string $namespaceName The namespace name of the reflected class.
* @return array A list with all found use statements.
*/
private function parseUseStatements($namespaceName)
{
$statements = array();
while (($token = $this->next())) {
if ($token[0] === T_USE) {
$statements = array_merge($statements, $this->parseUseStatement());
continue;
} else if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) {
continue;
}
// Get fresh array for new namespace. This is to prevent the parser to collect the use statements
// for a previous namespace with the same name. This is the case if a namespace is defined twice
// or if a namespace with the same name is commented out.
$statements = array();
}
return $statements;
}
/**
* Get the namespace name.
*
* @return string The found namespace name.
*/
private function parseNamespace()
{
$namespace = '';
while (($token = $this->next())){
if ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR) {
$namespace .= $token[1];
} else {
break;
}
}
return $namespace;
}
/**
* Parse a single use statement.
*
* @return array A list with all found class names for a use statement.
*/
private function parseUseStatement()
{
$class = '';
$alias = '';
$statements = array();
$explicitAlias = false;
while (($token = $this->next())) {
$isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR;
if (!$explicitAlias && $isNameToken) {
$class .= $token[1];
$alias = $token[1];
} else if ($explicitAlias && $isNameToken) {
$alias .= $token[1];
} else if ($token[0] === T_AS) {
$explicitAlias = true;
$alias = '';
} else if ($token === ',') {
$statements[strtolower($alias)] = $class;
$class = '';
$alias = '';
$explicitAlias = false;
} else if ($token === ';') {
$statements[strtolower($alias)] = $class;
break;
} else {
break;
}
}
return $statements;
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
/**
* Interface for annotation readers.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface Reader
{
function getClassAnnotations(\ReflectionClass $class);
function getClassAnnotation(\ReflectionClass $class, $annotationName);
function getMethodAnnotations(\ReflectionMethod $method);
function getMethodAnnotation(\ReflectionMethod $method, $annotationName);
function getPropertyAnnotations(\ReflectionProperty $property);
function getPropertyAnnotation(\ReflectionProperty $property, $annotationName);
}

View File

@ -0,0 +1,152 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Annotations\Annotation\Target;
/**
* Simple Annotation Reader.
*
* This annotation reader is intended to be used in projects where you have
* full-control over all annotations that are available.
*
* @since 2.2
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
class SimpleAnnotationReader implements Reader
{
/**
* @var DocParser
*/
private $parser;
/**
* Constructor.
*
* Initializes a new SimpleAnnotationReader.
*/
public function __construct()
{
$this->parser = new DocParser();
$this->parser->setIgnoreNotImportedAnnotations(true);
}
/**
* Adds a namespace in which we will look for annotations.
*
* @param string $namespace
*/
public function addNamespace($namespace)
{
$this->parser->addNamespace($namespace);
}
/**
* Gets the annotations applied to a class.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
* @return array An array of Annotations.
*/
public function getClassAnnotations(\ReflectionClass $class)
{
return $this->parser->parse($class->getDocComment(), 'class '.$class->getName());
}
/**
* Gets the annotations applied to a method.
*
* @param ReflectionMethod $property The ReflectionMethod of the method from which
* the annotations should be read.
* @return array An array of Annotations.
*/
public function getMethodAnnotations(\ReflectionMethod $method)
{
return $this->parser->parse($method->getDocComment(), 'method '.$method->getDeclaringClass()->name.'::'.$method->getName().'()');
}
/**
* Gets the annotations applied to a property.
*
* @param ReflectionProperty $property The ReflectionProperty of the property
* from which the annotations should be read.
* @return array An array of Annotations.
*/
public function getPropertyAnnotations(\ReflectionProperty $property)
{
return $this->parser->parse($property->getDocComment(), 'property '.$property->getDeclaringClass()->name.'::$'.$property->getName());
}
/**
* Gets a class annotation.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getClassAnnotation(\ReflectionClass $class, $annotationName)
{
foreach ($this->getClassAnnotations($class) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* Gets a method annotation.
*
* @param ReflectionMethod $method
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
{
foreach ($this->getMethodAnnotations($method) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* Gets a property annotation.
*
* @param ReflectionProperty $property
* @param string $annotationName The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
{
foreach ($this->getPropertyAnnotations($property) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
}

View File

@ -0,0 +1,97 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* APC cache provider.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class ApcCache extends CacheProvider
{
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
return apc_fetch($id);
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
$found = false;
apc_fetch($id, $found);
return $found;
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
return (bool) apc_store($id, $data, (int) $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function doDelete($id)
{
return apc_delete($id);
}
/**
* {@inheritdoc}
*/
protected function doFlush()
{
return apc_clear_cache() && apc_clear_cache('user');
}
/**
* {@inheritdoc}
*/
protected function doGetStats()
{
$info = apc_cache_info();
$sma = apc_sma_info();
return array(
Cache::STATS_HITS => $info['num_hits'],
Cache::STATS_MISSES => $info['num_misses'],
Cache::STATS_UPTIME => $info['start_time'],
Cache::STATS_MEMORY_USAGE => $info['mem_size'],
Cache::STATS_MEMORY_AVAILIABLE => $sma['avail_mem'],
);
}
}

View File

@ -0,0 +1,96 @@
<?php
/*
* $Id$
*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Array cache driver.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class ArrayCache extends CacheProvider
{
/**
* @var array $data
*/
private $data = array();
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
return (isset($this->data[$id])) ? $this->data[$id] : false;
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
return isset($this->data[$id]);
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
$this->data[$id] = $data;
return true;
}
/**
* {@inheritdoc}
*/
protected function doDelete($id)
{
unset($this->data[$id]);
return true;
}
/**
* {@inheritdoc}
*/
protected function doFlush()
{
$this->data = array();
return true;
}
/**
* {@inheritdoc}
*/
protected function doGetStats()
{
return null;
}
}

View File

@ -0,0 +1,102 @@
<?php
/*
* $Id$
*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Interface for cache drivers.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
interface Cache
{
const STATS_HITS = 'hits';
const STATS_MISSES = 'misses';
const STATS_UPTIME = 'uptime';
const STATS_MEMORY_USAGE = 'memory_usage';
const STATS_MEMORY_AVAILIABLE = 'memory_available';
/**
* Fetches an entry from the cache.
*
* @param string $id cache id The id of the cache entry to fetch.
* @return string The cached data or FALSE, if no cache entry exists for the given id.
*/
function fetch($id);
/**
* Test if an entry exists in the cache.
*
* @param string $id cache id The cache id of the entry to check for.
* @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise.
*/
function contains($id);
/**
* Puts data into the cache.
*
* @param string $id The cache id.
* @param string $data The cache entry/data.
* @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this cache entry (0 => infinite lifeTime).
* @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise.
*/
function save($id, $data, $lifeTime = 0);
/**
* Deletes a cache entry.
*
* @param string $id cache id
* @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise.
*/
function delete($id);
/**
* Retrieves cached information from data store
*
* The server's statistics array has the following values:
*
* - <b>hits</b>
* Number of keys that have been requested and found present.
*
* - <b>misses</b>
* Number of items that have been requested and not found.
*
* - <b>uptime</b>
* Time that the server is running.
*
* - <b>memory_usage</b>
* Memory used by this server to store items.
*
* - <b>memory_available</b>
* Memory allowed to use for storage.
*
* @since 2.2
* @var array Associative array with server's statistics if available, NULL otherwise.
*/
function getStats();
}

View File

@ -0,0 +1,188 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Base class for cache provider implementations.
*
* @since 2.2
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
*/
abstract class CacheProvider implements Cache
{
const DOCTRINE_NAMESPACE_CACHEKEY = 'DoctrineNamespaceCacheKey[%s]';
/**
* @var string The namespace to prefix all cache ids with
*/
private $namespace = '';
/**
* Set the namespace to prefix all cache ids with.
*
* @param string $namespace
* @return void
*/
public function setNamespace($namespace)
{
$this->namespace = (string) $namespace;
}
/**
* Retrieve the namespace that prefixes all cache ids.
*
* @return string
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* {@inheritdoc}
*/
public function fetch($id)
{
return $this->doFetch($this->getNamespacedId($id));
}
/**
* {@inheritdoc}
*/
public function contains($id)
{
return $this->doContains($this->getNamespacedId($id));
}
/**
* {@inheritdoc}
*/
public function save($id, $data, $lifeTime = 0)
{
return $this->doSave($this->getNamespacedId($id), $data, $lifeTime);
}
/**
* {@inheritdoc}
*/
public function delete($id)
{
return $this->doDelete($this->getNamespacedId($id));
}
/**
* {@inheritdoc}
*/
public function getStats()
{
return $this->doGetStats();
}
/**
* Deletes all cache entries.
*
* @return boolean TRUE if the cache entries were successfully flushed, FALSE otherwise.
*/
public function flushAll()
{
return $this->doFlush();
}
/**
* Delete all cache entries.
*
* @return boolean TRUE if the cache entries were successfully deleted, FALSE otherwise.
*/
public function deleteAll()
{
$namespaceCacheKey = sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
$namespaceVersion = ($this->doContains($namespaceCacheKey)) ? $this->doFetch($namespaceCacheKey) : 1;
return $this->doSave($namespaceCacheKey, $namespaceVersion + 1);
}
/**
* Prefix the passed id with the configured namespace value
*
* @param string $id The id to namespace
* @return string $id The namespaced id
*/
private function getNamespacedId($id)
{
$namespaceCacheKey = sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);
$namespaceVersion = ($this->doContains($namespaceCacheKey)) ? $this->doFetch($namespaceCacheKey) : 1;
return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion);
}
/**
* Fetches an entry from the cache.
*
* @param string $id cache id The id of the cache entry to fetch.
* @return string The cached data or FALSE, if no cache entry exists for the given id.
*/
abstract protected function doFetch($id);
/**
* Test if an entry exists in the cache.
*
* @param string $id cache id The cache id of the entry to check for.
* @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise.
*/
abstract protected function doContains($id);
/**
* Puts data into the cache.
*
* @param string $id The cache id.
* @param string $data The cache entry/data.
* @param int $lifeTime The lifetime. If != false, sets a specific lifetime for this cache entry (null => infinite lifeTime).
* @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise.
*/
abstract protected function doSave($id, $data, $lifeTime = false);
/**
* Deletes a cache entry.
*
* @param string $id cache id
* @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise.
*/
abstract protected function doDelete($id);
/**
* Deletes all cache entries.
*
* @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise.
*/
abstract protected function doFlush();
/**
* Retrieves cached information from data store
*
* @since 2.2
* @return array An associative array with server's statistics if available, NULL otherwise.
*/
abstract protected function doGetStats();
}

View File

@ -0,0 +1,121 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
use \Memcache;
/**
* Memcache cache provider.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class MemcacheCache extends CacheProvider
{
/**
* @var Memcache
*/
private $memcache;
/**
* Sets the memcache instance to use.
*
* @param Memcache $memcache
*/
public function setMemcache(Memcache $memcache)
{
$this->memcache = $memcache;
}
/**
* Gets the memcache instance used by the cache.
*
* @return Memcache
*/
public function getMemcache()
{
return $this->memcache;
}
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
return $this->memcache->get($id);
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
return (bool) $this->memcache->get($id);
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
if ($lifeTime > 30 * 24 * 3600) {
$lifeTime = time() + $lifeTime;
}
return $this->memcache->set($id, $data, 0, (int) $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function doDelete($id)
{
return $this->memcache->delete($id);
}
/**
* {@inheritdoc}
*/
protected function doFlush()
{
return $this->memcache->flush();
}
/**
* {@inheritdoc}
*/
protected function doGetStats()
{
$stats = $this->memcache->getStats();
return array(
Cache::STATS_HITS => $stats['get_hits'],
Cache::STATS_MISSES => $stats['get_misses'],
Cache::STATS_UPTIME => $stats['uptime'],
Cache::STATS_MEMORY_USAGE => $stats['bytes'],
Cache::STATS_MEMORY_AVAILIABLE => $stats['limit_maxbytes'],
);
}
}

View File

@ -0,0 +1,124 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
use \Memcached;
/**
* Memcached cache provider.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.2
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class MemcachedCache extends CacheProvider
{
/**
* @var Memcached
*/
private $memcached;
/**
* Sets the memcache instance to use.
*
* @param Memcached $memcached
*/
public function setMemcached(Memcached $memcached)
{
$this->memcached = $memcached;
}
/**
* Gets the memcached instance used by the cache.
*
* @return Memcached
*/
public function getMemcached()
{
return $this->memcached;
}
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
return $this->memcached->get($id);
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
return (false !== $this->memcached->get($id));
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
if ($lifeTime > 30 * 24 * 3600) {
$lifeTime = time() + $lifeTime;
}
return $this->memcached->set($id, $data, (int) $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function doDelete($id)
{
return $this->memcached->delete($id);
}
/**
* {@inheritdoc}
*/
protected function doFlush()
{
return $this->memcached->flush();
}
/**
* {@inheritdoc}
*/
protected function doGetStats()
{
$stats = $this->memcached->getStats();
$servers = $this->memcached->getServerList();
$key = $servers[0]['host'] . ':' . $servers[0]['port'];
$stats = $stats[$key];
return array(
Cache::STATS_HITS => $stats['get_hits'],
Cache::STATS_MISSES => $stats['get_misses'],
Cache::STATS_UPTIME => $stats['uptime'],
Cache::STATS_MEMORY_USAGE => $stats['bytes'],
Cache::STATS_MEMORY_AVAILIABLE => $stats['limit_maxbytes'],
);
}
}

View File

@ -0,0 +1,92 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* WinCache cache provider.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.2
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class WincacheCache extends CacheProvider
{
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
return wincache_ucache_get($id);
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
return wincache_ucache_exists($id);
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
return (bool) wincache_ucache_set($id, $data, (int) $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function doDelete($id)
{
return wincache_ucache_delete($id);
}
/**
* {@inheritdoc}
*/
protected function doFlush()
{
return wincache_ucache_clear();
}
/**
* {@inheritdoc}
*/
protected function doGetStats()
{
$info = wincache_ucache_info();
$meminfo= wincache_ucache_meminfo();
return array(
Cache::STATS_HITS => $info['total_hit_count'],
Cache::STATS_MISSES => $info['total_miss_count'],
Cache::STATS_UPTIME => $info['total_cache_uptime'],
Cache::STATS_MEMORY_USAGE => $meminfo['memory_total'],
Cache::STATS_MEMORY_AVAILIABLE => $meminfo['memory_free'],
);
}
}

View File

@ -0,0 +1,110 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Xcache cache driver.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class XcacheCache extends CacheProvider
{
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
return $this->doContains($id) ? unserialize(xcache_get($id)) : false;
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
return xcache_isset($id);
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
return xcache_set($id, serialize($data), (int) $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function doDelete($id)
{
return xcache_unset($id);
}
/**
* {@inheritdoc}
*/
protected function doFlush()
{
$this->checkAuthorization();
xcache_clear_cache(XC_TYPE_VAR, 0);
return true;
}
/**
* Checks that xcache.admin.enable_auth is Off
*
* @throws \BadMethodCallException When xcache.admin.enable_auth is On
* @return void
*/
protected function checkAuthorization()
{
if (ini_get('xcache.admin.enable_auth')) {
throw new \BadMethodCallException('To use all features of \Doctrine\Common\Cache\XcacheCache, you must set "xcache.admin.enable_auth" to "Off" in your php.ini.');
}
}
/**
* {@inheritdoc}
*/
protected function doGetStats()
{
$this->checkAuthorization();
$info = xcache_info(XC_TYPE_VAR, 0);
return array(
Cache::STATS_HITS => $info['hits'],
Cache::STATS_MISSES => $info['misses'],
Cache::STATS_UPTIME => null,
Cache::STATS_MEMORY_USAGE => $info['size'],
Cache::STATS_MEMORY_AVAILIABLE => $info['avail'],
);
}
}

View File

@ -0,0 +1,84 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Zend Data Cache cache driver.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Ralph Schindler <ralph.schindler@zend.com>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
*/
class ZendDataCache extends CacheProvider
{
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
return zend_shm_cache_fetch($id);
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
return (false !== zend_shm_cache_fetch($id));
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
return zend_shm_cache_store($id, $data, $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function doDelete($id)
{
return zend_shm_cache_delete($id);
}
/**
* {@inheritdoc}
*/
protected function doFlush()
{
$namespace = $this->getNamespace();
if (empty($namespace)) {
return zend_shm_cache_clear();
}
return zend_shm_cache_clear($namespace);
}
/**
* {@inheritdoc}
*/
protected function doGetStats()
{
return null;
}
}

View File

@ -0,0 +1,262 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* A <tt>ClassLoader</tt> is an autoloader for class files that can be
* installed on the SPL autoload stack. It is a class loader that either loads only classes
* of a specific namespace or all namespaces and it is suitable for working together
* with other autoloaders in the SPL autoload stack.
*
* If no include path is configured through the constructor or {@link setIncludePath}, a ClassLoader
* relies on the PHP <code>include_path</code>.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
class ClassLoader
{
/**
* @var string PHP file extension
*/
protected $fileExtension = '.php';
/**
* @var string Current namespace
*/
protected $namespace;
/**
* @var string Current include path
*/
protected $includePath;
/**
* @var string PHP namespace separator
*/
protected $namespaceSeparator = '\\';
/**
* Creates a new <tt>ClassLoader</tt> that loads classes of the
* specified namespace from the specified include path.
*
* If no include path is given, the ClassLoader relies on the PHP include_path.
* If neither a namespace nor an include path is given, the ClassLoader will
* be responsible for loading all classes, thereby relying on the PHP include_path.
*
* @param string $ns The namespace of the classes to load.
* @param string $includePath The base include path to use.
*/
public function __construct($ns = null, $includePath = null)
{
$this->namespace = $ns;
$this->includePath = $includePath;
}
/**
* Sets the namespace separator used by classes in the namespace of this ClassLoader.
*
* @param string $sep The separator to use.
*/
public function setNamespaceSeparator($sep)
{
$this->namespaceSeparator = $sep;
}
/**
* Gets the namespace separator used by classes in the namespace of this ClassLoader.
*
* @return string
*/
public function getNamespaceSeparator()
{
return $this->namespaceSeparator;
}
/**
* Sets the base include path for all class files in the namespace of this ClassLoader.
*
* @param string $includePath
*/
public function setIncludePath($includePath)
{
$this->includePath = $includePath;
}
/**
* Gets the base include path for all class files in the namespace of this ClassLoader.
*
* @return string
*/
public function getIncludePath()
{
return $this->includePath;
}
/**
* Sets the file extension of class files in the namespace of this ClassLoader.
*
* @param string $fileExtension
*/
public function setFileExtension($fileExtension)
{
$this->fileExtension = $fileExtension;
}
/**
* Gets the file extension of class files in the namespace of this ClassLoader.
*
* @return string
*/
public function getFileExtension()
{
return $this->fileExtension;
}
/**
* Registers this ClassLoader on the SPL autoload stack.
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}
/**
* Removes this ClassLoader from the SPL autoload stack.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $classname The name of the class to load.
* @return boolean TRUE if the class has been successfully loaded, FALSE otherwise.
*/
public function loadClass($className)
{
if ($this->namespace !== null && strpos($className, $this->namespace.$this->namespaceSeparator) !== 0) {
return false;
}
require ($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '')
. str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className)
. $this->fileExtension;
return true;
}
/**
* Asks this ClassLoader whether it can potentially load the class (file) with
* the given name.
*
* @param string $className The fully-qualified name of the class.
* @return boolean TRUE if this ClassLoader can load the class, FALSE otherwise.
*/
public function canLoadClass($className)
{
if ($this->namespace !== null && strpos($className, $this->namespace.$this->namespaceSeparator) !== 0) {
return false;
}
$file = str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension;
if ($this->includePath !== null) {
return file_exists($this->includePath . DIRECTORY_SEPARATOR . $file);
}
return (false !== stream_resolve_include_path($file));
}
/**
* Checks whether a class with a given name exists. A class "exists" if it is either
* already defined in the current request or if there is an autoloader on the SPL
* autoload stack that is a) responsible for the class in question and b) is able to
* load a class file in which the class definition resides.
*
* If the class is not already defined, each autoloader in the SPL autoload stack
* is asked whether it is able to tell if the class exists. If the autoloader is
* a <tt>ClassLoader</tt>, {@link canLoadClass} is used, otherwise the autoload
* function of the autoloader is invoked and expected to return a value that
* evaluates to TRUE if the class (file) exists. As soon as one autoloader reports
* that the class exists, TRUE is returned.
*
* Note that, depending on what kinds of autoloaders are installed on the SPL
* autoload stack, the class (file) might already be loaded as a result of checking
* for its existence. This is not the case with a <tt>ClassLoader</tt>, who separates
* these responsibilities.
*
* @param string $className The fully-qualified name of the class.
* @return boolean TRUE if the class exists as per the definition given above, FALSE otherwise.
*/
public static function classExists($className)
{
if (class_exists($className, false) || interface_exists($className, false)) {
return true;
}
foreach (spl_autoload_functions() as $loader) {
if (is_array($loader)) { // array(???, ???)
if (is_object($loader[0])) {
if ($loader[0] instanceof ClassLoader) { // array($obj, 'methodName')
if ($loader[0]->canLoadClass($className)) {
return true;
}
} else if ($loader[0]->{$loader[1]}($className)) {
return true;
}
} else if ($loader[0]::$loader[1]($className)) { // array('ClassName', 'methodName')
return true;
}
} else if ($loader instanceof \Closure) { // function($className) {..}
if ($loader($className)) {
return true;
}
} else if (is_string($loader) && $loader($className)) { // "MyClass::loadClass"
return true;
}
}
return class_exists($className, false) || interface_exists($className, false);
}
/**
* Gets the <tt>ClassLoader</tt> from the SPL autoload stack that is responsible
* for (and is able to load) the class with the given name.
*
* @param string $className The name of the class.
* @return The <tt>ClassLoader</tt> for the class or NULL if no such <tt>ClassLoader</tt> exists.
*/
public static function getClassLoader($className)
{
foreach (spl_autoload_functions() as $loader) {
if (is_array($loader)
&& $loader[0] instanceof ClassLoader
&& $loader[0]->canLoadClass($className)
) {
return $loader[0];
}
}
return null;
}
}

View File

@ -0,0 +1,447 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Collections;
use Closure, ArrayIterator;
/**
* An ArrayCollection is a Collection implementation that wraps a regular PHP array.
*
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class ArrayCollection implements Collection
{
/**
* An array containing the entries of this collection.
*
* @var array
*/
private $_elements;
/**
* Initializes a new ArrayCollection.
*
* @param array $elements
*/
public function __construct(array $elements = array())
{
$this->_elements = $elements;
}
/**
* Gets the PHP array representation of this collection.
*
* @return array The PHP array representation of this collection.
*/
public function toArray()
{
return $this->_elements;
}
/**
* Sets the internal iterator to the first element in the collection and
* returns this element.
*
* @return mixed
*/
public function first()
{
return reset($this->_elements);
}
/**
* Sets the internal iterator to the last element in the collection and
* returns this element.
*
* @return mixed
*/
public function last()
{
return end($this->_elements);
}
/**
* Gets the current key/index at the current internal iterator position.
*
* @return mixed
*/
public function key()
{
return key($this->_elements);
}
/**
* Moves the internal iterator position to the next element.
*
* @return mixed
*/
public function next()
{
return next($this->_elements);
}
/**
* Gets the element of the collection at the current internal iterator position.
*
* @return mixed
*/
public function current()
{
return current($this->_elements);
}
/**
* Removes an element with a specific key/index from the collection.
*
* @param mixed $key
* @return mixed The removed element or NULL, if no element exists for the given key.
*/
public function remove($key)
{
if (isset($this->_elements[$key])) {
$removed = $this->_elements[$key];
unset($this->_elements[$key]);
return $removed;
}
return null;
}
/**
* Removes the specified element from the collection, if it is found.
*
* @param mixed $element The element to remove.
* @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeElement($element)
{
$key = array_search($element, $this->_elements, true);
if ($key !== false) {
unset($this->_elements[$key]);
return true;
}
return false;
}
/**
* ArrayAccess implementation of offsetExists()
*
* @see containsKey()
*/
public function offsetExists($offset)
{
return $this->containsKey($offset);
}
/**
* ArrayAccess implementation of offsetGet()
*
* @see get()
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* ArrayAccess implementation of offsetGet()
*
* @see add()
* @see set()
*/
public function offsetSet($offset, $value)
{
if ( ! isset($offset)) {
return $this->add($value);
}
return $this->set($offset, $value);
}
/**
* ArrayAccess implementation of offsetUnset()
*
* @see remove()
*/
public function offsetUnset($offset)
{
return $this->remove($offset);
}
/**
* Checks whether the collection contains a specific key/index.
*
* @param mixed $key The key to check for.
* @return boolean TRUE if the given key/index exists, FALSE otherwise.
*/
public function containsKey($key)
{
return isset($this->_elements[$key]);
}
/**
* Checks whether the given element is contained in the collection.
* Only element values are compared, not keys. The comparison of two elements
* is strict, that means not only the value but also the type must match.
* For objects this means reference equality.
*
* @param mixed $element
* @return boolean TRUE if the given element is contained in the collection,
* FALSE otherwise.
*/
public function contains($element)
{
foreach ($this->_elements as $collectionElement) {
if ($element === $collectionElement) {
return true;
}
}
return false;
}
/**
* Tests for the existance of an element that satisfies the given predicate.
*
* @param Closure $p The predicate.
* @return boolean TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
*/
public function exists(Closure $p)
{
foreach ($this->_elements as $key => $element) {
if ($p($key, $element)) {
return true;
}
}
return false;
}
/**
* Searches for a given element and, if found, returns the corresponding key/index
* of that element. The comparison of two elements is strict, that means not
* only the value but also the type must match.
* For objects this means reference equality.
*
* @param mixed $element The element to search for.
* @return mixed The key/index of the element or FALSE if the element was not found.
*/
public function indexOf($element)
{
return array_search($element, $this->_elements, true);
}
/**
* Gets the element with the given key/index.
*
* @param mixed $key The key.
* @return mixed The element or NULL, if no element exists for the given key.
*/
public function get($key)
{
if (isset($this->_elements[$key])) {
return $this->_elements[$key];
}
return null;
}
/**
* Gets all keys/indexes of the collection elements.
*
* @return array
*/
public function getKeys()
{
return array_keys($this->_elements);
}
/**
* Gets all elements.
*
* @return array
*/
public function getValues()
{
return array_values($this->_elements);
}
/**
* Returns the number of elements in the collection.
*
* Implementation of the Countable interface.
*
* @return integer The number of elements in the collection.
*/
public function count()
{
return count($this->_elements);
}
/**
* Adds/sets an element in the collection at the index / with the specified key.
*
* When the collection is a Map this is like put(key,value)/add(key,value).
* When the collection is a List this is like add(position,value).
*
* @param mixed $key
* @param mixed $value
*/
public function set($key, $value)
{
$this->_elements[$key] = $value;
}
/**
* Adds an element to the collection.
*
* @param mixed $value
* @return boolean Always TRUE.
*/
public function add($value)
{
$this->_elements[] = $value;
return true;
}
/**
* Checks whether the collection is empty.
*
* Note: This is preferrable over count() == 0.
*
* @return boolean TRUE if the collection is empty, FALSE otherwise.
*/
public function isEmpty()
{
return ! $this->_elements;
}
/**
* Gets an iterator for iterating over the elements in the collection.
*
* @return ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->_elements);
}
/**
* Applies the given function to each element in the collection and returns
* a new collection with the elements returned by the function.
*
* @param Closure $func
* @return Collection
*/
public function map(Closure $func)
{
return new static(array_map($func, $this->_elements));
}
/**
* Returns all the elements of this collection that satisfy the predicate p.
* The order of the elements is preserved.
*
* @param Closure $p The predicate used for filtering.
* @return Collection A collection with the results of the filter operation.
*/
public function filter(Closure $p)
{
return new static(array_filter($this->_elements, $p));
}
/**
* Applies the given predicate p to all elements of this collection,
* returning true, if the predicate yields true for all elements.
*
* @param Closure $p The predicate.
* @return boolean TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
*/
public function forAll(Closure $p)
{
foreach ($this->_elements as $key => $element) {
if ( ! $p($key, $element)) {
return false;
}
}
return true;
}
/**
* Partitions this collection in two collections according to a predicate.
* Keys are preserved in the resulting collections.
*
* @param Closure $p The predicate on which to partition.
* @return array An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
*/
public function partition(Closure $p)
{
$coll1 = $coll2 = array();
foreach ($this->_elements as $key => $element) {
if ($p($key, $element)) {
$coll1[$key] = $element;
} else {
$coll2[$key] = $element;
}
}
return array(new static($coll1), new static($coll2));
}
/**
* Returns a string representation of this object.
*
* @return string
*/
public function __toString()
{
return __CLASS__ . '@' . spl_object_hash($this);
}
/**
* Clears the collection.
*/
public function clear()
{
$this->_elements = array();
}
/**
* Extract a slice of $length elements starting at position $offset from the Collection.
*
* If $length is null it returns all elements from $offset to the end of the Collection.
* Keys have to be preserved by this method. Calling this method will only return the
* selected slice and NOT change the elements contained in the collection slice is called on.
*
* @param int $offset
* @param int $length
* @return array
*/
public function slice($offset, $length = null)
{
return array_slice($this->_elements, $offset, $length, true);
}
}

View File

@ -0,0 +1,243 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Collections;
use Closure, Countable, IteratorAggregate, ArrayAccess;
/**
* The missing (SPL) Collection/Array/OrderedMap interface.
*
* A Collection resembles the nature of a regular PHP array. That is,
* it is essentially an <b>ordered map</b> that can also be used
* like a list.
*
* A Collection has an internal iterator just like a PHP array. In addition,
* a Collection can be iterated with external iterators, which is preferrable.
* To use an external iterator simply use the foreach language construct to
* iterate over the collection (which calls {@link getIterator()} internally) or
* explicitly retrieve an iterator though {@link getIterator()} which can then be
* used to iterate over the collection.
* You can not rely on the internal iterator of the collection being at a certain
* position unless you explicitly positioned it before. Prefer iteration with
* external iterators.
*
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
interface Collection extends Countable, IteratorAggregate, ArrayAccess
{
/**
* Adds an element at the end of the collection.
*
* @param mixed $element The element to add.
* @return boolean Always TRUE.
*/
function add($element);
/**
* Clears the collection, removing all elements.
*/
function clear();
/**
* Checks whether an element is contained in the collection.
* This is an O(n) operation, where n is the size of the collection.
*
* @param mixed $element The element to search for.
* @return boolean TRUE if the collection contains the element, FALSE otherwise.
*/
function contains($element);
/**
* Checks whether the collection is empty (contains no elements).
*
* @return boolean TRUE if the collection is empty, FALSE otherwise.
*/
function isEmpty();
/**
* Removes the element at the specified index from the collection.
*
* @param string|integer $key The kex/index of the element to remove.
* @return mixed The removed element or NULL, if the collection did not contain the element.
*/
function remove($key);
/**
* Removes the specified element from the collection, if it is found.
*
* @param mixed $element The element to remove.
* @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
function removeElement($element);
/**
* Checks whether the collection contains an element with the specified key/index.
*
* @param string|integer $key The key/index to check for.
* @return boolean TRUE if the collection contains an element with the specified key/index,
* FALSE otherwise.
*/
function containsKey($key);
/**
* Gets the element at the specified key/index.
*
* @param string|integer $key The key/index of the element to retrieve.
* @return mixed
*/
function get($key);
/**
* Gets all keys/indices of the collection.
*
* @return array The keys/indices of the collection, in the order of the corresponding
* elements in the collection.
*/
function getKeys();
/**
* Gets all values of the collection.
*
* @return array The values of all elements in the collection, in the order they
* appear in the collection.
*/
function getValues();
/**
* Sets an element in the collection at the specified key/index.
*
* @param string|integer $key The key/index of the element to set.
* @param mixed $value The element to set.
*/
function set($key, $value);
/**
* Gets a native PHP array representation of the collection.
*
* @return array
*/
function toArray();
/**
* Sets the internal iterator to the first element in the collection and
* returns this element.
*
* @return mixed
*/
function first();
/**
* Sets the internal iterator to the last element in the collection and
* returns this element.
*
* @return mixed
*/
function last();
/**
* Gets the key/index of the element at the current iterator position.
*
*/
function key();
/**
* Gets the element of the collection at the current iterator position.
*
*/
function current();
/**
* Moves the internal iterator position to the next element.
*
*/
function next();
/**
* Tests for the existence of an element that satisfies the given predicate.
*
* @param Closure $p The predicate.
* @return boolean TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
*/
function exists(Closure $p);
/**
* Returns all the elements of this collection that satisfy the predicate p.
* The order of the elements is preserved.
*
* @param Closure $p The predicate used for filtering.
* @return Collection A collection with the results of the filter operation.
*/
function filter(Closure $p);
/**
* Applies the given predicate p to all elements of this collection,
* returning true, if the predicate yields true for all elements.
*
* @param Closure $p The predicate.
* @return boolean TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
*/
function forAll(Closure $p);
/**
* Applies the given function to each element in the collection and returns
* a new collection with the elements returned by the function.
*
* @param Closure $func
* @return Collection
*/
function map(Closure $func);
/**
* Partitions this collection in two collections according to a predicate.
* Keys are preserved in the resulting collections.
*
* @param Closure $p The predicate on which to partition.
* @return array An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
*/
function partition(Closure $p);
/**
* Gets the index/key of a given element. The comparison of two elements is strict,
* that means not only the value but also the type must match.
* For objects this means reference equality.
*
* @param mixed $element The element to search for.
* @return mixed The key/index of the element or FALSE if the element was not found.
*/
function indexOf($element);
/**
* Extract a slice of $length elements starting at position $offset from the Collection.
*
* If $length is null it returns all elements from $offset to the end of the Collection.
* Keys have to be preserved by this method. Calling this method will only return the
* selected slice and NOT change the elements contained in the collection slice is called on.
*
* @param int $offset
* @param int $length
* @return array
*/
function slice($offset, $length = null);
}

View File

@ -0,0 +1,28 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* Base exception class for package Doctrine\Common
* @author heinrich
*
*/
class CommonException extends \Exception {
}

View File

@ -0,0 +1,47 @@
<?php
/*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* Comparable interface that allows to compare two value objects to each other for similarity.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.2
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
*/
interface Comparable
{
/**
* Compare the current object to the passed $other.
*
* Returns 0 if they are semantically equal, 1 if the other object
* is less than the current one, or -1 if its more than the current one.
*
* This method should not check for identity using ===, only for semantical equality for example
* when two different DateTime instances point to the exact same Date + TZ.
*
* @return int
*/
public function compareTo($other);
}

View File

@ -0,0 +1,69 @@
<?php
/*
* $Id$
*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* EventArgs is the base class for classes containing event data.
*
* This class contains no event data. It is used by events that do not pass state
* information to an event handler when an event is raised. The single empty EventArgs
* instance can be obtained through {@link getEmptyInstance}.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EventArgs
{
/**
* @var EventArgs Single instance of EventArgs
* @static
*/
private static $_emptyEventArgsInstance;
/**
* Gets the single, empty and immutable EventArgs instance.
*
* This instance will be used when events are dispatched without any parameter,
* like this: EventManager::dispatchEvent('eventname');
*
* The benefit from this is that only one empty instance is instantiated and shared
* (otherwise there would be instances for every dispatched in the abovementioned form)
*
* @see EventManager::dispatchEvent
* @link http://msdn.microsoft.com/en-us/library/system.eventargs.aspx
* @static
* @return EventArgs
*/
public static function getEmptyInstance()
{
if ( ! self::$_emptyEventArgsInstance) {
self::$_emptyEventArgsInstance = new EventArgs;
}
return self::$_emptyEventArgsInstance;
}
}

View File

@ -0,0 +1,136 @@
<?php
/*
* $Id$
*
* 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
* OWNER 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.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* The EventManager is the central point of Doctrine's event listener system.
* Listeners are registered on the manager and events are dispatched through the
* manager.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EventManager
{
/**
* Map of registered listeners.
* <event> => <listeners>
*
* @var array
*/
private $_listeners = array();
/**
* Dispatches an event to all registered listeners.
*
* @param string $eventName The name of the event to dispatch. The name of the event is
* the name of the method that is invoked on listeners.
* @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners.
* If not supplied, the single empty EventArgs instance is used.
* @return boolean
*/
public function dispatchEvent($eventName, EventArgs $eventArgs = null)
{
if (isset($this->_listeners[$eventName])) {
$eventArgs = $eventArgs === null ? EventArgs::getEmptyInstance() : $eventArgs;
foreach ($this->_listeners[$eventName] as $listener) {
$listener->$eventName($eventArgs);
}
}
}
/**
* Gets the listeners of a specific event or all listeners.
*
* @param string $event The name of the event.
* @return array The event listeners for the specified event, or all event listeners.
*/
public function getListeners($event = null)
{
return $event ? $this->_listeners[$event] : $this->_listeners;
}
/**
* Checks whether an event has any registered listeners.
*
* @param string $event
* @return boolean TRUE if the specified event has any listeners, FALSE otherwise.
*/
public function hasListeners($event)
{
return isset($this->_listeners[$event]) && $this->_listeners[$event];
}
/**
* Adds an event listener that listens on the specified events.
*
* @param string|array $events The event(s) to listen on.
* @param object $listener The listener object.
*/
public function addEventListener($events, $listener)
{
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
foreach ((array) $events as $event) {
// Overrides listener if a previous one was associated already
// Prevents duplicate listeners on same event (same instance only)
$this->_listeners[$event][$hash] = $listener;
}
}
/**
* Removes an event listener from the specified events.
*
* @param string|array $events
* @param object $listener
*/
public function removeEventListener($events, $listener)
{
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
foreach ((array) $events as $event) {
// Check if actually have this listener associated
if (isset($this->_listeners[$event][$hash])) {
unset($this->_listeners[$event][$hash]);
}
}
}
/**
* Adds an EventSubscriber. The subscriber is asked for all the events he is
* interested in and added as a listener for these events.
*
* @param Doctrine\Common\EventSubscriber $subscriber The subscriber.
*/
public function addEventSubscriber(EventSubscriber $subscriber)
{
$this->addEventListener($subscriber->getSubscribedEvents(), $subscriber);
}
}

Some files were not shown because too many files have changed in this diff Show More