second commit

This commit is contained in:
sujitprasad
2015-08-21 11:22:12 +05:30
parent 50fcb7bbe0
commit 69e622e472
7220 changed files with 1184612 additions and 3 deletions

View File

@@ -1,3 +0,0 @@
/vendor
/node_modules
.env

7
code/code/vendor/autoload.php vendored Normal file
View File

@@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInit5a4036999a1163a0cf7d39bc88c9c382::getLoader();

View File

@@ -0,0 +1,7 @@
#!/usr/bin/env sh
SRC_DIR="`pwd`"
cd "`dirname "$0"`"
cd "../classpreloader/classpreloader"
BIN_TARGET="`pwd`/classpreloader.php"
cd "$SRC_DIR"
"$BIN_TARGET" "$@"

View File

@@ -0,0 +1,3 @@
@ECHO OFF
SET BIN_TARGET=%~dp0/../classpreloader/classpreloader/classpreloader.php
php "%BIN_TARGET%" %*

7
code/code/vendor/bin/phpspec vendored Normal file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env sh
SRC_DIR="`pwd`"
cd "`dirname "$0"`"
cd "../phpspec/phpspec/bin"
BIN_TARGET="`pwd`/phpspec"
cd "$SRC_DIR"
"$BIN_TARGET" "$@"

3
code/code/vendor/bin/phpspec.bat vendored Normal file
View File

@@ -0,0 +1,3 @@
@ECHO OFF
SET BIN_TARGET=%~dp0/../phpspec/phpspec/bin/phpspec
php "%BIN_TARGET%" %*

7
code/code/vendor/bin/phpunit vendored Normal file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env sh
SRC_DIR="`pwd`"
cd "`dirname "$0"`"
cd "../phpunit/phpunit"
BIN_TARGET="`pwd`/phpunit"
cd "$SRC_DIR"
"$BIN_TARGET" "$@"

3
code/code/vendor/bin/phpunit.bat vendored Normal file
View File

@@ -0,0 +1,3 @@
@ECHO OFF
SET BIN_TARGET=%~dp0/../phpunit/phpunit/phpunit
php "%BIN_TARGET%" %*

7
code/code/vendor/bin/psysh vendored Normal file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env sh
SRC_DIR="`pwd`"
cd "`dirname "$0"`"
cd "../psy/psysh/bin"
BIN_TARGET="`pwd`/psysh"
cd "$SRC_DIR"
"$BIN_TARGET" "$@"

3
code/code/vendor/bin/psysh.bat vendored Normal file
View File

@@ -0,0 +1,3 @@
@ECHO OFF
SET BIN_TARGET=%~dp0/../psy/psysh/bin/psysh
php "%BIN_TARGET%" %*

View File

@@ -0,0 +1,3 @@
example/ export-ignore
tests/ export-ignore
phpunit.xml export-ignore

View File

@@ -0,0 +1,4 @@
/vendor
composer.phar
composer.lock
.DS_Store

View File

@@ -0,0 +1,18 @@
language: php
php:
- 5.3
- 5.4
- 5.5
- 5.6
before_script:
- travis_retry composer install --no-interaction --prefer-source
script:
- phpunit
notifications:
hipchat:
rooms:
secure: h9501ANwjT/oDK9YM1fmLV9+1WuhEWpRu35VCqJrOHEHpDQjk7W0LZw4xJo/kK10AKCN861U5VT1U5ncxujFLBZ2HnrKGraTCvXRss/dC2wn+fG2P+T4hsQGWAyU/rU/A8uPwZT71gqCmNtt1Xo/uGHt1UHT+H59J3d3GoFjgBY=

View File

@@ -0,0 +1,102 @@
Changelog
=========
1.6.1
-----
- Fix array syntax for older php
1.6.0
-----
- Move to using .env for api key in laravel 5+
- Support for artisan vendor:publish
1.5.1
-----
- Lumen Service Provider use statement
1.5.0
-----
- Lumen support
- Fix bug in instructions
- Fix bug with reading settings from service file
1.4.2
-----
- Try/catch for missing/nonstandard auth service
1.4.1
-----
- Default severity to 'error'
1.4.0
-----
- Better laravel 5 support!
1.3.0
-----
- Laravel 5 support!
1.2.1
-----
- Protect against missing configuration variables (thanks @jasonlfunk!)
1.2.0
-----
- Update `bugsnag-php` dependency to enable support for code snippets on
your Bugsnag dashboard
- Allow configuring of more Bugsnag settings from your `config.php`
(thanks @jacobmarshall!)
1.1.1
-----
- Fix issue where sending auth information with complex users could fail (thanks @hannesvdvreken!)
1.1.0
-----
- Send user/auth information if available (thanks @hannesvdvreken!)
1.0.10
------
- Laravel 5 support
1.0.9
------
- Split strip paths from `inProject`
1.0.8
-----
- Bump the bugsnag-php dependency to include recent fixes
1.0.7
-----
- Fix major notification bug introduced in 1.0.6
1.0.6
-----
- Fix incompatibility with PHP 5.3
1.0.5
-----
- Identify as Laravel notifier instead of PHP
1.0.4
-----
- Allow configuration of notify_release_stages from config file
1.0.3
-----
- Fix bug when setting releaseStage in the ServiceProvider
1.0.2
-----
- Fix laravel requirement to work with 4.1
- Add a `Bugsnag` facade for quick access to $app["bugsnag"]
1.0.1
-----
- Fixed fatal error handling
- Set release stage based on laravel's `App::environment` setting
1.0.0
-----
- Initial release

View File

@@ -0,0 +1,39 @@
Contributing
============
- [Fork](https://help.github.com/articles/fork-a-repo) the [notifier on github](https://github.com/bugsnag/bugsnag-laravel)
- Build and test your changes
- Commit and push until you are happy with your contribution
- [Make a pull request](https://help.github.com/articles/using-pull-requests)
- Thanks!
Example apps
============
Bugsnag supports both Laravel 4 and Laravel 5. You can test these out by running the locally.
brew tap josegonzalez/homebrew-php
brew install php56 php56-mcrypt composer
Then cd into `example/laravel-4` and start the server:
composer install
php56 artisan serve --port 8004
The same works for `example/laravel-5` and start the server:
composer install
php56 artisan serve --port 8005
Releasing
=========
1. Commit all outstanding changes
1. Bump the version in `src/Bugsnag/BugsnagLaravel/BugsnagLaravelServiceProvider.php` and `src/Bugsnag/BugsnagLaravel/BugsnagLumenServiceProvider.php`
2. Update the CHANGELOG.md, and README if appropriate.
3. Commit, tag push
git commit -am v1.x.x
git tag v1.x.x
git push origin master v1.x.x

View File

@@ -0,0 +1,20 @@
Copyright (c) 2013 Bugsnag
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.

View File

@@ -0,0 +1,287 @@
Bugsnag Notifier for Laravel and Lumen
=====================================
The Bugsnag Notifier for Laravel gives you instant notification of errors and
exceptions in your Laravel PHP applications. We support Laravel 5, Laravel 4, Laravel 3, and Lumen.
[Bugsnag](https://bugsnag.com) captures errors in real-time from your web,
mobile and desktop applications, helping you to understand and resolve them
as fast as possible. [Create a free account](https://bugsnag.com) to start
capturing errors from your applications.
Check out this excellent [Laracasts screencast](https://laracasts.com/lessons/better-error-tracking-with-bugsnag) for a quick overview of how to use Bugsnag with your Laravel apps.
How to Install
---------------
### Laravel 5.0 +
1. Install the `bugsnag/bugsnag-laravel` package
```shell
$ composer require bugsnag/bugsnag-laravel:1.*
```
1. Update `config/app.php` to activate Bugsnag
```php
# Add `BugsnagLaravelServiceProvider` to the `providers` array
'providers' => array(
...
Bugsnag\BugsnagLaravel\BugsnagLaravelServiceProvider::class,
)
# Add the `BugsnagFacade` to the `aliases` array
'aliases' => array(
...
'Bugsnag' => Bugsnag\BugsnagLaravel\BugsnagFacade::class,
)
```
1. Use the Bugsnag exception handler from `App/Exceptions/Handler.php`.
```php
# DELETE this line
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
```
```php
# ADD this line instead
use Bugsnag\BugsnagLaravel\BugsnagExceptionHandler as ExceptionHandler;
```
After this change, your file should look like this:
```php
<?php namespace App\Exceptions;
use Exception;
use Bugsnag\BugsnagLaravel\BugsnagExceptionHandler as ExceptionHandler;
class Handler extends ExceptionHandler {
...
}
```
1. Create the configuration file `config/bugsnag.php`:
```shell
$ php artisan vendor:publish
```
1. Configure your `api_key` in your `.env` file:
```shell
BUGSNAG_API_KEY=YOUR-API-KEY-HERE
```
1. Optionally, you can add the `notify_release_stages` key to the `config/bugsnag.php` file
to define which Laravel environments will send Exceptions to Bugsnag.
```php
return array(
'api_key' => env('BUGSNAG_API_KEY'),
'notify_release_stages' => ['production', 'staging']
);
```
### Laravel < 5.0
1. Install the `bugsnag/bugsnag-laravel` package
```shell
$ composer require bugsnag/bugsnag-laravel:1.*
```
1. Update app/config/app.php` to activate Bugsnag
```php
# Add `BugsnagLaravelServiceProvider` to the `providers` array
'providers' => array(
...
'Bugsnag\BugsnagLaravel\BugsnagLaravelServiceProvider',
)
# Add the `BugsnagFacade` to the `aliases` array
'aliases' => array(
...
'Bugsnag' => 'Bugsnag\BugsnagLaravel\BugsnagFacade',
)
```
1. Generate a template Bugsnag config file
```shell
$ php artisan config:publish bugsnag/bugsnag-laravel
```
1. Update `app/config/packages/bugsnag/bugsnag-laravel/config.php` with your
Bugsnag API key:
```php
return array(
'api_key' => 'YOUR-API-KEY-HERE'
);
```
1. Optionally, you can add the `notify_release_stages` key to the same file
above to define which Laravel environments will send Exceptions to Bugsnag.
```php
return array(
'api_key' => 'YOUR-API-KEY-HERE',
'notify_release_stages' => ['production', 'staging']
);
```
### Lumen
1. In `bootstrap/app.php` add the line
```php
$app->register('Bugsnag\BugsnagLaravel\BugsnagLumenServiceProvider');
```
just before the line
```php
require __DIR__ . '/../app/Http/routes.php';
```
2. Change the function `report` in `app/Exceptions/Handler.php` to look like this:
```php
public function report(Exception $e) {
app('bugsnag')->notifyException($e, []);
return parent::report($e);
}
```
3. Create a file `config/bugsnag.php` that contains your API key
```php
<?php # config/bugsnag.php
return array(
'api_key' => 'YOUR-API-KEY-HERE'
);
```
Sending Custom Data With Exceptions
-----------------------------------
It is often useful to send additional meta-data about your app, such as
information about the currently logged in user, along with any
error or exceptions, to help debug problems.
To send custom data, you should define a *before-notify* function,
adding an array of "tabs" of custom data to the $metaData parameter. For example:
```php
Bugsnag::setBeforeNotifyFunction("before_bugsnag_notify");
function before_bugsnag_notify($error) {
// Do any custom error handling here
// Also add some meta data to each error
$error->setMetaData(array(
"user" => array(
"name" => "James",
"email" => "james@example.com"
)
));
}
```
See the [setBeforeNotifyFunction](https://bugsnag.com/docs/notifiers/php#setbeforenotifyfunction)
documentation on the `bugsnag-php` library for more information.
Sending Custom Errors or Non-Fatal Exceptions
---------------------------------------------
You can easily tell Bugsnag about non-fatal or caught exceptions by
calling `Bugsnag::notifyException`:
```php
Bugsnag::notifyException(new Exception("Something bad happened"));
```
You can also send custom errors to Bugsnag with `Bugsnag::notifyError`:
```php
Bugsnag::notifyError("ErrorType", "Something bad happened here too");
```
Both of these functions can also be passed an optional `$metaData` parameter,
which should take the following format:
```php
$metaData = array(
"user" => array(
"name" => "James",
"email" => "james@example.com"
)
);
```
Error Reporting Levels
----------------------
By default we'll use the value of `error_reporting` from your `php.ini`
or any value you set at runtime using the `error_reporting(...)` function.
If you'd like to send different levels of errors to Bugsnag, you can call
`setErrorReportingLevel`, for example:
```php
Bugsnag::setErrorReportingLevel(E_ALL & ~E_NOTICE);
```
Additional Configuration
------------------------
The [Bugsnag PHP Client](https://bugsnag.com/docs/notifiers/php)
is available as `Bugsnag`, which allows you to set various
configuration options, for example:
```php
Bugsnag::setReleaseStage("production");
```
See the [Bugsnag Notifier for PHP documentation](https://bugsnag.com/docs/notifiers/php#additional-configuration)
for full configuration details.
Reporting Bugs or Feature Requests
----------------------------------
Please report any bugs or feature requests on the github issues page for this
project here:
<https://github.com/bugsnag/bugsnag-laravel/issues>
Contributing
------------
- [Fork](https://help.github.com/articles/fork-a-repo) the [notifier on github](https://github.com/bugsnag/bugsnag-laravel)
- Commit and push until you are happy with your contribution
- Run the tests to make sure they all pass: `composer install && ./vendor/bin/phpunit`
- [Make a pull request](https://help.github.com/articles/using-pull-requests)
- Thanks!
License
-------
The Bugsnag Laravel notifier is free software released under the MIT License.
See [LICENSE.txt](https://github.com/bugsnag/bugsnag-laravel/blob/master/LICENSE.txt) for details.

View File

@@ -0,0 +1,23 @@
{
"name": "bugsnag/bugsnag-laravel",
"description": "Official Bugsnag notifier for Laravel applications.",
"keywords": ["bugsnag", "exceptions", "errors", "logging", "tracking", "laravel"],
"homepage": "https://github.com/bugsnag/bugsnag-laravel",
"license": "MIT",
"authors": [
{
"name": "James Smith",
"email": "notifiers@bugsnag.com"
}
],
"require": {
"php": ">=5.3.0",
"illuminate/support": "4.*|5.*",
"bugsnag/bugsnag": ">=2.5.0"
},
"autoload": {
"psr-0": {
"Bugsnag\\BugsnagLaravel\\": "src/"
}
}
}

View File

@@ -0,0 +1,11 @@
{
"providers": [
"Bugsnag\BugsnagLaravel\BugsnagLaravelServiceProvider"
],
"aliases": [
{
"alias": "Bugsnag",
"facade": "Bugsnag\BugsnagLaravel\BugsnagFacade"
}
]
}

View File

@@ -0,0 +1,31 @@
<?php namespace Bugsnag\BugsnagLaravel;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class BugsnagExceptionHandler extends ExceptionHandler {
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $e
* @return void
*/
public function report(Exception $e)
{
foreach ($this->dontReport as $type) {
if ($e instanceof $type) {
return parent::report($e);
}
}
$bugsnag = app('bugsnag');
if ($bugsnag) {
$bugsnag->notifyException($e, null, "error");
}
return parent::report($e);
}
}

View File

@@ -0,0 +1,11 @@
<?php namespace Bugsnag\BugsnagLaravel;
use Illuminate\Support\Facades\Facade;
class BugsnagFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'bugsnag';
}
}

View File

@@ -0,0 +1,115 @@
<?php namespace Bugsnag\BugsnagLaravel;
use Illuminate\Support\ServiceProvider;
class BugsnagLaravelServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
$app = $this->app;
if (version_compare($app::VERSION, '5.0') < 0) {
$this->package('bugsnag/bugsnag-laravel', 'bugsnag');
// Register for exception handling
$app->error(function (\Exception $exception) use ($app) {
if ('Symfony\Component\Debug\Exception\FatalErrorException'
!== get_class($exception)
) {
$app['bugsnag']->notifyException($exception, null, "error");
}
});
// Register for fatal error handling
$app->fatal(function ($exception) use ($app) {
$app['bugsnag']->notifyException($exception, null, "error");
});
} else {
$this->publishes(array(
__DIR__.'/config.php' => config_path('bugsnag.php'),
));
}
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->singleton('bugsnag', function ($app) {
$config = isset($app['config']['services']['bugsnag']) ? $app['config']['services']['bugsnag'] : null;
if (is_null($config)) {
$config = $app['config']['bugsnag'] ?: $app['config']['bugsnag::config'];
}
$client = new \Bugsnag_Client($config['api_key']);
$client->setStripPath(base_path());
$client->setProjectRoot(app_path());
$client->setAutoNotify(false);
$client->setBatchSending(false);
$client->setReleaseStage($app->environment());
$client->setNotifier(array(
'name' => 'Bugsnag Laravel',
'version' => '1.6.1',
'url' => 'https://github.com/bugsnag/bugsnag-laravel'
));
if (isset($config['notify_release_stages']) && is_array($config['notify_release_stages'])) {
$client->setNotifyReleaseStages($config['notify_release_stages']);
}
if (isset($config['endpoint'])) {
$client->setEndpoint($config['endpoint']);
}
if (isset($config['filters']) && is_array($config['filters'])) {
$client->setFilters($config['filters']);
}
if (isset($config['proxy']) && is_array($config['proxy'])) {
$client->setProxySettings($config['proxy']);
}
// Check if someone is logged in.
try {
if ($app['auth']->check()) {
// User is logged in.
$user = $app['auth']->user();
// If these attributes are available: pass them on.
$client->setUser(array('id' => $user->getAuthIdentifier()));
}
} catch (\Exception $e) {
// Do nothing.
}
return $client;
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array("bugsnag");
}
}

View File

@@ -0,0 +1,91 @@
<?php namespace Bugsnag\BugsnagLaravel;
use Illuminate\Support\ServiceProvider;
class BugsnagLumenServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
$this->app->configure('bugsnag');
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->singleton('bugsnag', function ($app) {
$config = isset($app['config']['services']['bugsnag']) ? $app['config']['services']['bugsnag'] : null;
if (is_null($config)) {
$config = $app['config']['bugsnag'] ?: $app['config']['bugsnag::config'];
}
$client = new \Bugsnag_Client($config['api_key']);
$client->setStripPath(base_path());
$client->setProjectRoot(base_path() . '/app');
$client->setAutoNotify(false);
$client->setBatchSending(false);
$client->setReleaseStage($app->environment());
$client->setNotifier(array(
'name' => 'Bugsnag Lumen',
'version' => '1.6.1',
'url' => 'https://github.com/bugsnag/bugsnag-laravel'
));
if (isset($config['notify_release_stages']) && is_array($config['notify_release_stages'])) {
$client->setNotifyReleaseStages($config['notify_release_stages']);
}
if (isset($config['endpoint'])) {
$client->setEndpoint($config['endpoint']);
}
if (isset($config['filters']) && is_array($config['filters'])) {
$client->setFilters($config['filters']);
}
if (isset($config['proxy']) && is_array($config['proxy'])) {
$client->setProxySettings($config['proxy']);
}
// Check if someone is logged in.
try {
if ($app['auth']->check()) {
// User is logged in.
$user = $app['auth']->user();
// If these attributes are available: pass them on.
$client->setUser(array('id' => $user->getAuthIdentifier()));
}
} catch (\Exception $e) {
// Do nothing.
}
return $client;
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array("bugsnag");
}
}

View File

@@ -0,0 +1,77 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| API Key
|--------------------------------------------------------------------------
|
| You can find your API key on your Bugsnag dashboard.
|
| This api key points the Bugsnag notifier to the project in your account
| which should receive your application's uncaught exceptions.
|
*/
'api_key' => env('BUGSNAG_API_KEY'),
/*
|--------------------------------------------------------------------------
| Notify Release Stages
|--------------------------------------------------------------------------
|
| Set which release stages should send notifications to Bugsnag.
|
| Example: array('development', 'production')
|
*/
'notify_release_stages' => null,
/*
|--------------------------------------------------------------------------
| Endpoint
|--------------------------------------------------------------------------
|
| Set what server the Bugsnag notifier should send errors to. By default
| this is set to 'https://notify.bugsnag.com', but for Bugsnag Enterprise
| this should be the URL to your Bugsnag instance.
|
*/
'endpoint' => null,
/*
|--------------------------------------------------------------------------
| Filters
|--------------------------------------------------------------------------
|
| Use this if you want to ensure you don't send sensitive data such as
| passwords, and credit card numbers to our servers. Any keys which
| contain these strings will be filtered.
|
*/
'filters' => array('password'),
/*
|--------------------------------------------------------------------------
| Proxy
|--------------------------------------------------------------------------
|
| If your server is behind a proxy server, you can configure this as well.
| Other than the host, none of these settings are mandatory.
|
| Note: Proxy configuration is only possible if the PHP cURL extension
| is installed.
|
| Example:
|
| 'proxy' => array(
| 'host' => 'bugsnag.com',
| 'port' => 42,
| 'user' => 'username',
| 'password' => 'password123'
| )
|
*/
'proxy' => null
);

View File

@@ -0,0 +1,77 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| API Key
|--------------------------------------------------------------------------
|
| You can find your API key on your Bugsnag dashboard.
|
| This api key points the Bugsnag notifier to the project in your account
| which should receive your application's uncaught exceptions.
|
*/
'api_key' => 'YOUR-API-KEY-HERE',
/*
|--------------------------------------------------------------------------
| Notify Release Stages
|--------------------------------------------------------------------------
|
| Set which release stages should send notifications to Bugsnag.
|
| Example: array('development', 'production')
|
*/
'notify_release_stages' => null,
/*
|--------------------------------------------------------------------------
| Endpoint
|--------------------------------------------------------------------------
|
| Set what server the Bugsnag notifier should send errors to. By default
| this is set to 'https://notify.bugsnag.com', but for Bugsnag Enterprise
| this should be the URL to your Bugsnag instance.
|
*/
'endpoint' => null,
/*
|--------------------------------------------------------------------------
| Filters
|--------------------------------------------------------------------------
|
| Use this if you want to ensure you don't send sensitive data such as
| passwords, and credit card numbers to our servers. Any keys which
| contain these strings will be filtered.
|
*/
'filters' => array('password'),
/*
|--------------------------------------------------------------------------
| Proxy
|--------------------------------------------------------------------------
|
| If your server is behind a proxy server, you can configure this as well.
| Other than the host, none of these settings are mandatory.
|
| Note: Proxy configuration is only possible if the PHP cURL extension
| is installed.
|
| Example:
|
| 'proxy' => array(
| 'host' => 'bugsnag.com',
| 'port' => 42,
| 'user' => 'username',
| 'password' => 'password123'
| )
|
*/
'proxy' => null
);

View File

@@ -0,0 +1,13 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@@ -0,0 +1,2 @@
vendor
composer.lock

View File

@@ -0,0 +1,12 @@
language: php
php:
- 5.6
- 5.5
- 5.4
- 5.3
- 5.2
- hhvm
notifications:
hipchat:
rooms:
secure: CP1Pqa5TRwHtft3UQRZpnnw/mRCAVtXAn5S/Am45uk4fpGGFLf3F/mHKOgjDeALB/aVyJQvHV/Lr2KrgY7FWOjOdzXVVwLDtGoXXimvqxGEjvSFQMiJGKiwm7Thw41EqwHOZUxIKLtJBByP36bqvx4zXxUeNbCTc4T2f92eiZps=

View File

@@ -0,0 +1,182 @@
Changelog
=========
2.5.5
-----
- Ensure no unnecessary code is executed when errors should be skipped
2.5.4
-----
- Fix HHVM support for release 2.5.3
2.5.3
-----
- Add support for custom curl options
2.5.2
-----
- Add support for setHostname
2.5.1
-----
- Extract file and line numbers better for crashes in eval'd code
2.5.0
-----
- Collect and send snippets of source code to Bugsnag for easier debugging
- Update `setEndpoint` to accept full URLs
- Add support for `Error#setGroupingHash` to customize error grouping in
`setBeforeNotify` functions
2.4.0
-----
- Don't send $_ENV by default
2.3.1
-----
- Warn if neither curl or fopen are available
2.3.0
-----
- Remove cURL requirement, fallback to using fopen() if cURL not available
2.2.10
------
- Remove default for `setProjectRoot` since it was sometimes overzealous
2.2.9
-----
- Fix boolean metadata handling
2.2.8
-----
- Fix various metadata-encoding bugs
2.2.7
-----
- Allow configuration of projectRoot stripping from stacktraces
2.2.6
-----
- Fix calling `mb_detect_encoding` on non-objects
2.2.5
-----
- Remove deprecated "fatal" severity state
2.2.4
-----
- Prepare 'severity' feature for release
2.2.3
-----
- Fix invalid utf-8 errors for people using iso-8859-1 by default.
2.2.2
-----
- Make frames public on the stacktrace.
2.2.1
-----
- Log any curl errors to the command line, increase default timeout to 10s
2.2.0
-----
- Support previous exceptions on PHP >= 5.3.0
- Allow overriding notifier
- Use manual loading in place of custom autoloading
2.1.4
-----
- Make cURL timeout configurable (thanks pauloschilling)
2.1.3
-----
- Fix crash during stacktrace generation that happened when a closure was
the first stackframe.
2.1.2
-----
- Add `ErrorTypes::getLevelsForSeverity` function to fetch an
`error_reporting` bitmask for a particular Bugsnag severity
2.1.1
-----
- Fix crash during stacktrace generation for frameworks that have their own
`shutdown_handler` method (eg. Laravel)
2.1.0
-----
- Add `setAppType` for sending app type (script, request, resque, etc)
- Add `setUser` for sending structured user data
- Automatically send the severity level of each PHP error
- Added ability to chain setters (eg $bugsnag->setUser(...)->setReleaseStage(...))
2.0.4
-----
- Add hostname collection to help with debugging
2.0.3
-----
- Add `setBatchSending` function to disable batch sending of errors at the
end of each request
2.0.2
-----
- Fix bug which caused `setNotifyReleaseStages` being ignored
2.0.1
-----
- Fix minor request meta-data issues introduced in 2.0.0
2.0.0
-----
- Backwards-incompatible rewrite (using non-static access)
- Full suite of tests and Travis CI testing on PHP 5.2+
- Add `setBeforeNotify` functionality to add meta-data or execute code
before each error is sent to Bugsnag
1.0.9
-----
- Add `setAutoNotify` function to allow disabling of automatic error handling
- Fix bug where error reporting level was being ignored for fatal errors
1.0.8
-----
- Added a `setMetaData` function for sending custom data with every error
1.0.7
-----
- Don't default `notifyReleaseStages` to anything to reduce confusion
1.0.6
-----
- Fix PHP 5.2 bug with missing constants
1.0.5
-----
- Protect against missing $_SERVER variables
1.0.4
-----
- Send JSON POST params to Bugsnag if available
- Send HTTP headers to Bugsnag if available
1.0.3
-----
- Remove unnecessary post to Bugsnag when error list is empty
1.0.2
-----
- Fix bug with 'internal' stacktrace lines (missing line/file)
1.0.1
-----
- Renamed default error classes for clarity
- Batch-send errors at the end of each request
- `Bugsnag::errorHandler` now respects PHP's `error_reporting` settings
- Added `setErrorReportingLevel` function to override PHP's error_reporting settings
1.0.0
-----
- First public release

View File

@@ -0,0 +1,36 @@
Contributing
============
- [Fork](https://help.github.com/articles/fork-a-repo) the [notifier on github](https://github.com/bugsnag/bugsnag-laravel)
- Build and test your changes
- Commit and push until you are happy with your contribution
- [Make a pull request](https://help.github.com/articles/using-pull-requests)
- Thanks!
Example apps
============
Test the notifier by running the application locally.
[Install composer](http://getcomposer.org/doc/01-basic-usage.md), and then cd into `example/php` and start the server:
composer install
php index.php
Releasing
=========
1. Commit all outstanding changes
1. Bump the version in `src/Bugsnag/Configuration.php`.
2. Update the CHANGELOG.md, and README if appropriate.
3. Build a new phar package
composer install
php pharbuilder.php
4. Commit, tag push
git commit -am v1.x.x
git tag v1.x.x
git push origin master v1.x.x

View File

@@ -0,0 +1,20 @@
Copyright (c) 2013 Bugsnag
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.

View File

@@ -0,0 +1,483 @@
Bugsnag Notifier for PHP
========================
The Bugsnag Notifier for PHP gives you instant notification of errors and
exceptions in your PHP applications.
[Bugsnag](https://bugsnag.com) captures errors in real-time from your web,
mobile and desktop applications, helping you to understand and resolve them
as fast as possible. [Create a free account](https://bugsnag.com) to start
capturing errors from your applications.
The Bugsnag Notifier for PHP supports PHP 5.2+.
How to Install
--------------
### Using [Composer](http://getcomposer.org/) (Recommended)
1. Install the `bugsnag/bugsnag-php` package:
```shell
$ composer require "bugsnag/bugsnag:2.*"
```
### Using Phar Package
1. Download the latest [bugsnag.phar](https://raw.github.com/bugsnag/bugsnag-php/master/build/bugsnag.phar)
to your PHP project.
2. Require it in your app.
```php
require_once "/path/to/bugsnag.phar";
```
### Manual Installation
1. Download and extract the [latest Bugsnag source code](https://github.com/bugsnag/bugsnag-php/archive/master.zip)
to your PHP project.
2. Require it in your app using the provided autoloader.
```php
require_once "/path/to/Bugsnag/Autoload.php";
```
Configuration
-------------
1. Configure Bugsnag with your API key:
```php
$bugsnag = new Bugsnag_Client('YOUR-API-KEY-HERE');
```
2. Enable automatic error and exception notification by attaching Bugsnag's
error and exception handlers:
```php
set_error_handler(array($bugsnag, 'errorHandler'));
set_exception_handler(array($bugsnag, 'exceptionHandler'));
```
If you app or PHP framework already has error handling functions, you can
also call `$bugsnag->errorHandler` and `$bugsnag->exceptionHandler`
directly from your existing functions, simply pass all parameters through.
Sending Custom Data With Exceptions
-----------------------------------
It is often useful to send additional meta-data about your app, such as
information about the currently logged in user, along with any
error or exceptions, to help debug problems.
Bugsnag supports sending user information, such as the user's name or email
address, by calling the [setUser](#setUser) function.
To send other custom data, you should define a *before-notify* function,
adding an array of "tabs" of custom data to the $metaData parameter.
For an example, see the [setBeforeNotifyFunction](#setbeforenotifyfunction)
documentation below.
Sending Custom Errors or Non-Fatal Exceptions
---------------------------------------------
You can easily tell Bugsnag about non-fatal or caught exceptions by
calling `notifyException`:
```php
$bugsnag->notifyException(new Exception('Something bad happened'));
```
You can also send custom errors to Bugsnag with `notifyError`:
```php
$bugsnag->notifyError('ErrorType', 'Something bad happened here too');
```
Both of these functions can also be passed an optional `$metaData` parameter,
which should take the following format:
```php
$metaData = array(
'account' => array(
'paying' => true,
'name' => 'Acme Co'
)
);
```
### Severity
You can set the severity of an error in Bugsnag by including the severity option as the fourth parameter when
notifying bugsnag of the error,
```php
$bugsnag->notifyError('ErrorType', 'Something bad happened here too', NULL, "error")
```
Valid severities are `error`, `warning` and `info`.
Severity is displayed in the dashboard and can be used to filter the error list.
By default all crashes (or unhandled exceptions) are set to `error` and all
`$bugsnag->notify` calls default to `warning`.
Additional Configuration
------------------------
###setUser
Bugsnag helps you understand how many of your users are affected by each
error, and allows you to search for which errors affect a particular user
using your Bugsnag dashboard. To send useful user-specific information you can
call `setUser`:
```php
$bugsnag->setUser(array(
'name' => 'Leeroy Jenkins',
'email' => 'leeeeroy@jenkins.com'
));
```
The `name`, `email` and `id` fields are searchable, and everything you send in
this array will be displayed on your Bugsnag dashboard.
The `id` field is used also used by Bugsnag to determine the number of
impacted users. By default, we use the IP address of the request as the `id`.
###setReleaseStage
If you would like to distinguish between errors that happen in different
stages of the application release process (development, production, etc)
you can set the `releaseStage` that is reported to Bugsnag.
```php
$bugsnag->setReleaseStage('development');
```
By default this is set to be "production".
> Note: If you would like errors from stages other than production to be sent
to Bugsnag, you'll also have to call `setNotifyReleaseStages`.
###setNotifyReleaseStages
By default, we will notify Bugsnag of errors that happen in any
`releaseStage` If you would like to change which release stages notify
Bugsnag of errors you can call `setNotifyReleaseStages`:
```php
$bugsnag->setNotifyReleaseStages(array('development', 'production'));
```
###setMetaData
Sets additional meta-data to send with every bugsnag notification,
for example:
```php
$bugsnag->setMetaData(array(
'account' => array(
'paying' => true,
'name' => 'Acme Co'
)
));
```
###setContext
Bugsnag uses the concept of "contexts" to help display and group your
errors. Contexts represent what was happening in your application at the
time an error occurs. By default this will be set to the current request
URL and HTTP method, eg "GET /pages/documentation".
If you would like to set the bugsnag context manually, you can call
`setContext`:
```php
$bugsnag->setContext('Backport Job');
```
###setType
You can set the type of application executing the current code by using
`setType`:
```php
$bugsnag->setType('resque');
```
This is usually used to represent if you are running plain PHP code "php", via
a framework, eg "laravel", or executing through delayed worker code,
eg "resque". By default this is `NULL`.
###setFilters
Sets the strings to filter out from the `metaData` arrays before sending
them to Bugsnag. Use this if you want to ensure you don't send
sensitive data such as passwords, and credit card numbers to our
servers. Any keys which contain these strings will be filtered.
```php
$bugsnag->setFilters(array('password', 'credit_card'));
```
By default, this is set to be `array("password")`.
###setEndpoint
Set the endpoint to send error reports to. By default we'll send reports to
the standard `https://notify.bugsnag.com` endpoint, but you can override this
if you are using [Bugsnag Enterprise](https://bugsnag.com/enterprise), to
point to your own Bugsnag endpoint:
```php
$bugsnag->setEndpoint("http://bugsnag.internal.example.com");
```
###setTimeout
> Note: Timeout configuration is only possible if the PHP cURL extension is installed.
Define a custom timeout, in seconds, for cURL connection when notifying bugsnag.com.
```php
$bugsnag->setTimeout(2);
```
By default, this is set to be `2`.
###setBeforeNotifyFunction
Set a custom function to call before notifying Bugsnag of an error.
You can use this to call your own error handling functions, to add custom
tabs of data to each error on your Bugsnag dashboard, or to modify the
stacktrace.
To add custom tabs of meta-data, simply add to the `$metaData` array
that is passed as the first parameter to your function, for example:
```php
$bugsnag->setBeforeNotifyFunction('before_bugsnag_notify');
function before_bugsnag_notify(Bugsnag_Error $error) {
// Do any custom error handling here
// Also add some meta data to each error
$error->setMetaData(array(
"user" => array(
"name" => "James",
"email" => "james@example.com"
)
));
}
```
If Bugsnag is called by a wrapper library, you can remove stack frames from the
back-trace. For example:
```php
function before_bugsnag_notify(Bugsnag_Error $error) {
$firstFrame = $error->stacktrace->frames[0];
if ($firstFrame && $firstFrame['file'] === 'My_Logger.php') {
array_splice($error->stacktrace->frames, 0, 1);
}
}
```
You can also return `FALSE` from your beforeNotifyFunction to stop this error
from being sent to bugsnag.
###setAutoNotify
Controls whether bugsnag should automatically notify about any errors it detects in
the PHP error handlers.
```php
$bugsnag->setAutoNotify(FALSE);
```
By default, this is set to `TRUE`.
###setErrorReportingLevel
Set the levels of PHP errors to report to Bugsnag, by default we'll use
the value of `error_reporting` from your `php.ini` or any value you set
at runtime using the `error_reporting(...)` function.
If you'd like to send different levels of errors to Bugsnag, you can call
`setErrorReportingLevel`:
```php
$bugsnag->setErrorReportingLevel(E_ALL & ~E_NOTICE);
```
See PHP's [error reporting documentation](http://php.net/manual/en/errorfunc.configuration.php#ini.error-reporting)
for allowed values.
<!-- Custom anchor for linking from alerts -->
<div id="set-project-root"></div>
###setProjectRoot
We mark stacktrace lines as in-project if they come from files inside your
`projectRoot`. By default this value is automatically set to be
`$_SERVER['DOCUMENT_ROOT']` but sometimes this can cause problems with
stacktrace highlighting. You can set this manually by calling `setProjectRoot`:
```php
$bugsnag->setProjectRoot('/path/to/your/app');
```
If your app has files in many different locations, you should consider using
[setProjectRootRegex](#setprojectrootregex) instead.
###setProjectRootRegex
If your app has files in many different locations, you can set the a regular
expression for matching filenames in stacktrace lines that are part of your
application:
```php
$bugsnag->setProjectRootRegex('('.preg_quote('/app').'|'.preg_quote('/libs').')');
```
###setProxySettings
> Note: Proxy configuration is only possible if the PHP cURL extension is installed.
If your server is behind a proxy server, you can configure this as well:
```php
$bugsnag->setProxySettings(array(
'host' => 'bugsnag.com',
'port' => 42,
'user' => 'username',
'password' => 'password123'
));
```
Other than the host, none of these settings are mandatory.
###setAppVersion
If you tag your app releases with version numbers, Bugsnag can display these
on your dashboard if you call `setAppVersion`:
```php
$bugsnag->setAppVersion('1.2.3');
```
###setSendEnvironment
Bugsnag can transmit your `$_ENV` environment to help diagnose issues. This can
contain private/sensitive information, so we do not transmit this by default. To
send your environment, you can call `setSendEnvironment`:
```php
$bugsnag->setSendEnvironment(true);
```
###setSendCode
Bugsnag automatically sends a small snippet of the code that crashed to help
you diagnose even faster from within your dashboard. If you don't want to send
this snippet, you can call `setSendCode`:
```php
$bugsnag->setSendCode(false);
```
###setGroupingHash
Sets the grouping hash of the error report. All errors with the same grouping hash are grouped together. This is an advanced usage of the library and mis-using it will cause your errors not to group properly in your dashboard.
```php
$error->setGroupingHash($exception->message . $exception->class);
```
PHP Frameworks
--------------
### Laravel
Check out the [bugsnag-laravel](https://github.com/bugsnag/bugsnag-laravel) plugin.
### WordPress
Check out the [WordPress Error Monitoring by Bugsnag](http://wordpress.org/plugins/bugsnag/) plugin.
### CakePHP
Check out the third-party [Label305/bugsnag-cakephp](https://github.com/Label305/bugsnag-cakephp) plugin.
### Magento
Check out the official [Bugsnag Magento Extension](http://www.magentocommerce.com/magento-connect/bugsnag-notifier.html).
### Symfony2
Check out the third-party [evolution7/Evolution7BugsnagBundle](https://github.com/evolution7/Evolution7BugsnagBundle) or [wrep/bugsnag-php-symfony](https://github.com/wrep/bugsnag-php-symfony) bundles.
### Monolog
Check out the 3rd party log handler for monolog: [meadsteve/MonoSnag/](https://github.com/meadsteve/MonoSnag/)
### Silverstripe
Check out the third-party [evolution7/silverstripe-bugsnag-logger](https://github.com/evolution7/silverstripe-bugsnag-logger) plugin.
### Zend Framework 2
Check out the third-party [nickurt/bugsnag-php](https://github.com/nickurt/zf-bugsnag) plugin.
Building a Phar from Source
---------------------------
- Install the composer dependencies
```shell
$ composer install
```
- Build the phar using `pharbuilder.php`. You may need to set `phar.readonly = Off` in your `php.ini`.
```shell
php pharbuilder.php
```
A new `bugsnag.phar` will be generated in the `build` folder.
Reporting Bugs or Feature Requests
----------------------------------
Please report any bugs or feature requests on the github issues page for this
project here:
<https://github.com/bugsnag/bugsnag-php/issues>
Contributing
------------
- [Fork](https://help.github.com/articles/fork-a-repo) the [notifier on github](https://github.com/bugsnag/bugsnag-php)
- Commit and push until you are happy with your contribution
- Run the tests to make sure they all pass: `composer install && vendor/bin/phpunit`
- [Make a pull request](https://help.github.com/articles/using-pull-requests)
- Thanks!
License
-------
The Bugsnag PHP notifier is free software released under the MIT License.
See [LICENSE.txt](https://github.com/bugsnag/bugsnag-php/blob/master/LICENSE.txt) for details.

Binary file not shown.

View File

@@ -0,0 +1,27 @@
{
"name": "bugsnag/bugsnag",
"type": "library",
"description": "Official Bugsnag notifier for PHP applications.",
"keywords": ["bugsnag", "exceptions", "errors", "logging", "tracking"],
"homepage": "https://github.com/bugsnag/bugsnag-php",
"license": "MIT",
"authors": [{
"name": "James Smith",
"email": "notifiers@bugsnag.com",
"homepage": "https://bugsnag.com"
}],
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
},
"autoload": {
"psr-0" : {
"Bugsnag_" : "src/"
}
}
}

View File

@@ -0,0 +1,15 @@
- Install composer
<http://getcomposer.org/doc/01-basic-usage.md>
- Install bugsnag using composer
```shell
composer install
```
- Run the example script
```shell
php index.php
```

View File

@@ -0,0 +1,5 @@
{
"require": {
"bugsnag/bugsnag": "1.*"
}
}

View File

@@ -0,0 +1,8 @@
<?php
require_once "../../build/bugsnag.phar";
$bugsnag = new Bugsnag_Client("066f5ad3590596f9aa8d601ea89af845");
$bugsnag->notifyError("Broken", "Something broke", array("tab" => array("paying" => true, "object" => (object)array("key" => "value"), "null" => NULL, "string" => "test", "int" => 4)));
?>

View File

@@ -0,0 +1,12 @@
<?php
function build_phar()
{
$phar = new Phar('build/bugsnag.phar');
$phar->buildFromDirectory(dirname(__FILE__) . '/src','/\.php$/');
$phar->compressFiles(Phar::GZ);
$phar->stopBuffering();
$phar->setStub($phar->createDefaultStub('Bugsnag/Autoload.php'));
}
build_phar();

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<phpunit
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
bootstrap="./src/Bugsnag/Autoload.php">
<testsuites>
<testsuite name="Bugsnag tests">
<directory>./tests</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,15 @@
<?php
# We used to have an autoloader, but it caused problems in some
# environments. So now we manually load the entire library upfront.
#
# The file is still called Autoload so that existing integration
# instructions continue to work.
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Client.php";
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Configuration.php";
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Diagnostics.php";
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Error.php";
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."ErrorTypes.php";
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Notification.php";
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Request.php";
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."Stacktrace.php";

View File

@@ -0,0 +1,488 @@
<?php
class Bugsnag_Client
{
private $config;
private $notification;
/**
* Initialize Bugsnag
*
* @param String $apiKey your Bugsnag API key
*/
public function __construct($apiKey)
{
// Check API key has been passed
if (!is_string($apiKey)) {
throw new Exception('Bugsnag Error: Invalid API key');
}
// Create a configuration object
$this->config = new Bugsnag_Configuration();
$this->config->apiKey = $apiKey;
// Build a Diagnostics object
$this->diagnostics = new Bugsnag_Diagnostics($this->config);
// Register a shutdown function to check for fatal errors
// and flush any buffered errors
register_shutdown_function(array($this, 'shutdownHandler'));
}
/**
* Set your release stage, eg "production" or "development"
*
* @param String $releaseStage the app's current release stage
*/
public function setReleaseStage($releaseStage)
{
$this->config->releaseStage = $releaseStage;
return $this;
}
/**
* Set your app's semantic version, eg "1.2.3"
*
* @param String $appVersion the app's version
*/
public function setAppVersion($appVersion)
{
$this->config->appVersion = $appVersion;
return $this;
}
/**
* Set the host name
*
* @param String $hostname the host name
*/
public function setHostname($hostname)
{
$this->config->hostname = $hostname;
return $this;
}
/**
* Set which release stages should be allowed to notify Bugsnag
* eg array("production", "development")
*
* @param Array $notifyReleaseStages array of release stages to notify for
*/
public function setNotifyReleaseStages(array $notifyReleaseStages)
{
$this->config->notifyReleaseStages = $notifyReleaseStages;
return $this;
}
/**
* Set which Bugsnag endpoint to send errors to.
*
* @param String $endpoint endpoint URL
*/
public function setEndpoint($endpoint)
{
$this->config->endpoint = $endpoint;
return $this;
}
/**
* Set whether or not to use SSL when notifying bugsnag
*
* @param Boolean $useSSL whether to use SSL
* @deprecated you can now pass full URLs to setEndpoint
*/
public function setUseSSL($useSSL)
{
$this->config->useSSL = $useSSL;
return $this;
}
/**
* Set the desired timeout for cURL connection when notifying bugsnag
*
* @param Integer $timeout the desired timeout in seconds
*/
public function setTimeout($timeout)
{
$this->config->timeout = $timeout;
return $this;
}
/**
* Set the absolute path to the root of your application.
* We use this to help with error grouping and to highlight "in project"
* stacktrace lines.
*
* @param String $projectRoot the root path for your application
*/
public function setProjectRoot($projectRoot)
{
$this->config->setProjectRoot($projectRoot);
return $this;
}
/**
* Set the path that should be stripped from the beginning of
* any stacktrace file line. This helps to normalise filenames
* for grouping and reduces the noise in stack traces.
*
* @param String $stripPath the path to strip from filenames
*/
public function setStripPath($stripPath)
{
$this->config->setStripPath($stripPath);
return $this;
}
/**
* Set the a regular expression for matching filenames in stacktrace lines
* that are part of your application.
*
* @param String $projectRootRegex regex matching paths belong to your project
*/
public function setProjectRootRegex($projectRootRegex)
{
$this->config->projectRootRegex = $projectRootRegex;
return $this;
}
/**
* Set the strings to filter out from metaData arrays before sending then
* to Bugsnag. Eg. array("password", "credit_card")
*
* @param Array $filters an array of metaData filters
*/
public function setFilters(array $filters)
{
$this->config->filters = $filters;
return $this;
}
/**
* Set information about the current user of your app, including
* id, name and email.
*
* @param Array $user an array of user information. Eg:
* array(
* 'name' => 'Bob Hoskins',
* 'email' => 'bob@hoskins.com'
* )
*/
public function setUser(array $user)
{
$this->config->user = $user;
return $this;
}
/**
* @deprecated deprecated since version 2.1
*/
public function setUserId($userId)
{
if (!is_array($this->config->user)) {
$this->config->user = array();
}
$this->config->user['id'] = $userId;
return $this;
}
/**
* Set a context representing the current type of request, or location in code.
*
* @param String $context the current context
*/
public function setContext($context)
{
$this->config->context = $context;
return $this;
}
/**
* Set the type of application executing the code. This is usually used to
* represent if you are running plain PHP code "php", via a framework,
* eg "laravel", or executing through delayed worker code, eg "resque".
*
* @param String $type the current type
*/
public function setType($type)
{
$this->config->type = $type;
return $this;
}
/**
* Set custom metadata to send to Bugsnag with every error. You can use
* this to add custom tabs of data to each error on your Bugsnag dashboard
*
* @param Array $metaData an array of arrays of custom data. Eg:
* array(
* "user" => array(
* "name" => "James",
* "email" => "james@example.com"
* )
* )
*/
public function setMetaData(array $metaData)
{
$this->config->metaData = $metaData;
return $this;
}
/**
* Set proxy configuration
*
* @param Array $proxySettings an array with proxy settings. Eg:
* array(
* 'host' => "bugsnag.com",
* 'port' => 42,
* 'user' => "username"
* 'password' => "password123"
* )
*/
public function setProxySettings(array $proxySettings)
{
$this->config->proxySettings = $proxySettings;
return $this;
}
/**
* Set custom curl options
*
* @param Array $curlOptions an array with curl options. Eg:
* array(
* CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4
* )
*/
public function setCurlOptions(array $curlOptions)
{
$this->config->curlOptions = $curlOptions;
return $this;
}
/**
* Set a custom function to call before notifying Bugsnag of an error.
* You can use this to call your own error handling functions, or to add
* custom tabs of data to each error on your Bugsnag dashboard.
*
* // Adding meta-data example
* function before_bugsnag_notify($error) {
* $error->addMetaData(array(
* "user" => array(
* "name" => "James"
* )
* ));
* }
* $bugsnag->setBeforeNotifyFunction("before_bugsnag_notify");
*
*/
public function setBeforeNotifyFunction($beforeNotifyFunction)
{
$this->config->beforeNotifyFunction = $beforeNotifyFunction;
return $this;
}
/**
* Set Bugsnag's error reporting level.
* If this is not set, we'll use your current PHP error_reporting value
* from your ini file or error_reporting(...) calls.
*
* @param Integer $errorReportingLevel the error reporting level integer
* exactly as you would pass to PHP's error_reporting
*/
public function setErrorReportingLevel($errorReportingLevel)
{
$this->config->errorReportingLevel = $errorReportingLevel;
return $this;
}
/**
* Sets whether Bugsnag should be automatically notified of unhandled
* exceptions and errors.
*
* @param Boolean $autoNotify whether to auto notify or not
*/
public function setAutoNotify($autoNotify)
{
$this->config->autoNotify = $autoNotify;
return $this;
}
/**
* Sets whether errors should be batched together and send at the end of
* each request.
*
* @param Boolean $batchSending whether to batch together errors
*/
public function setBatchSending($batchSending)
{
$this->config->batchSending = $batchSending;
return $this;
}
/**
* Sets the notifier to report as to Bugsnag. This should only be
* set by other notifier libraries.
*
* @param Array $notifier an array of name, version, url.
*/
public function setNotifier($notifier)
{
$this->config->notifier = $notifier;
return $this;
}
/**
* Sets whether Bugsnag should send $_ENV with each error.
*
* @param Boolean $sendEnvironment whether to send the environment
*/
public function setSendEnvironment($sendEnvironment)
{
$this->config->sendEnvironment = $sendEnvironment;
return $this;
}
/**
* Should we send a small snippet of the code that crashed to help you
* diagnose even faster from within your dashboard.
*
* @param Boolean $setSendCode whether to send code to Bugsnag
*/
public function setSendCode($sendCode)
{
$this->config->sendCode = $sendCode;
return $this;
}
/**
* Notify Bugsnag of a non-fatal/handled exception
*
* @param Exception $exception the exception to notify Bugsnag about
* @param Array $metaData optional metaData to send with this error
* @param String $severity optional severity of this error (fatal/error/warning/info)
*/
public function notifyException(Exception $exception, array $metaData = null, $severity = null)
{
$error = Bugsnag_Error::fromPHPException($this->config, $this->diagnostics, $exception);
$error->setSeverity($severity);
$this->notify($error, $metaData);
}
/**
* Notify Bugsnag of a non-fatal/handled error
*
* @param String $errorName the name of the error, a short (1 word) string
* @param String $errorMessage the error message
* @param Array $metaData optional metaData to send with this error
* @param String $severity optional severity of this error (fatal/error/warning/info)
*/
public function notifyError($name, $message, array $metaData = null, $severity = null)
{
$error = Bugsnag_Error::fromNamedError($this->config, $this->diagnostics, $name, $message);
$error->setSeverity($severity);
$this->notify($error, $metaData);
}
// Exception handler callback, should only be called internally by PHP's set_exception_handler
public function exceptionHandler($exception)
{
if(!$this->config->autoNotify) {
return;
}
$error = Bugsnag_Error::fromPHPException($this->config, $this->diagnostics, $exception);
$error->setSeverity("error");
$this->notify($error);
}
// Exception handler callback, should only be called internally by PHP's set_error_handler
public function errorHandler($errno, $errstr, $errfile = '', $errline = 0)
{
if(!$this->config->autoNotify || $this->config->shouldIgnoreErrorCode($errno)) {
return;
}
$error = Bugsnag_Error::fromPHPError($this->config, $this->diagnostics, $errno, $errstr, $errfile, $errline);
$this->notify($error);
}
// Shutdown handler callback, called when the PHP process has finished running
// Should only be called internally by PHP's register_shutdown_function
public function shutdownHandler()
{
// Get last error
$lastError = error_get_last();
// Check if a fatal error caused this shutdown
if (!is_null($lastError) && Bugsnag_ErrorTypes::isFatal($lastError['type']) && $this->config->autoNotify && !$this->config->shouldIgnoreErrorCode($lastError['type'])) {
$error = Bugsnag_Error::fromPHPError($this->config, $this->diagnostics, $lastError['type'], $lastError['message'], $lastError['file'], $lastError['line'], true);
$error->setSeverity("error");
$this->notify($error);
}
// Flush any buffered errors
if ($this->notification) {
$this->notification->deliver();
$this->notification = null;
}
}
/**
* Batches up errors into notifications for later sending
*
* @param Bugsnag_Error $error the error to batch up
* @param array $metaData optional meta data to send with the error
*/
public function notify(Bugsnag_Error $error, $metaData = array())
{
// Queue or send the error
if ($this->sendErrorsOnShutdown()) {
// Create a batch notification unless we already have one
if (is_null($this->notification)) {
$this->notification = new Bugsnag_Notification($this->config);
}
// Add this error to the notification
$this->notification->addError($error, $metaData);
} else {
// Create and deliver notification immediately
$notif = new Bugsnag_Notification($this->config);
$notif->addError($error, $metaData);
$notif->deliver();
}
}
// Should we send errors immediately or on shutdown
private function sendErrorsOnShutdown()
{
return $this->config->batchSending && Bugsnag_Request::isRequest();
}
}

View File

@@ -0,0 +1,99 @@
<?php
class Bugsnag_Configuration
{
public static $DEFAULT_TIMEOUT = 10;
public static $DEFAULT_ENDPOINT = 'https://notify.bugsnag.com';
public static $DEFAULT_NON_SSL_ENDPOINT = 'http://notify.bugsnag.com';
public $apiKey;
public $autoNotify = true;
public $batchSending = true;
public $useSSL = true;
public $endpoint;
public $notifyReleaseStages;
public $filters = array('password');
public $projectRoot;
public $projectRootRegex;
public $proxySettings = array();
public $notifier = array(
'name' => 'Bugsnag PHP (Official)',
'version' => '2.5.5',
'url' => 'https://bugsnag.com',
);
public $sendEnvironment = false;
public $sendCode = true;
public $stripPath;
public $stripPathRegex;
public $context;
public $type;
public $user;
public $releaseStage = 'production';
public $appVersion;
public $hostname;
public $metaData;
public $beforeNotifyFunction;
public $errorReportingLevel;
public $curlOptions = array();
public function __construct()
{
$this->timeout = Bugsnag_Configuration::$DEFAULT_TIMEOUT;
}
public function getNotifyEndpoint()
{
if (is_null($this->endpoint)) {
return $this->useSSL ? Bugsnag_Configuration::$DEFAULT_ENDPOINT : Bugsnag_Configuration::$DEFAULT_NON_SSL_ENDPOINT;
} elseif (preg_match('/^(http:\/\/|https:\/\/)/', $this->endpoint)) {
return $this->endpoint;
} else {
return ($this->useSSL ? "https" : "http")."://".$this->endpoint;
}
}
public function shouldNotify()
{
return is_null($this->notifyReleaseStages) || (is_array($this->notifyReleaseStages) && in_array($this->releaseStage, $this->notifyReleaseStages));
}
public function shouldIgnoreErrorCode($code)
{
if (isset($this->errorReportingLevel)) {
return !($this->errorReportingLevel & $code);
} else {
return !(error_reporting() & $code);
}
return false;
}
public function setProjectRoot($projectRoot)
{
$this->projectRoot = $projectRoot;
$this->projectRootRegex = '/'.preg_quote($projectRoot, '/')."[\\/]?/i";
if (is_null($this->stripPath)) {
$this->setStripPath($projectRoot);
}
}
public function setStripPath($stripPath)
{
$this->stripPath = $stripPath;
$this->stripPathRegex = '/'.preg_quote($stripPath, '/')."[\\/]?/i";
}
public function get($prop, $default = null)
{
$configured = $this->$prop;
if (is_array($configured) && is_array($default)) {
return array_merge($default, $configured);
} else {
return $configured ? $configured : $default;
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
class Bugsnag_Diagnostics
{
private $config;
public function __construct(Bugsnag_Configuration $config)
{
$this->config = $config;
}
public function getAppData()
{
$appData = array();
if (!is_null($this->config->appVersion)) {
$appData['version'] = $this->config->appVersion;
}
if (!is_null($this->config->releaseStage)) {
$appData['releaseStage'] = $this->config->releaseStage;
}
if (!is_null($this->config->type)) {
$appData['type'] = $this->config->type;
}
return $appData;
}
public function getDeviceData()
{
return array(
'hostname' => $this->config->get('hostname', php_uname('n')),
);
}
public function getContext()
{
return $this->config->get('context', Bugsnag_Request::getContext());
}
public function getUser()
{
$defaultUser = array();
$userId = Bugsnag_Request::getUserId();
if (!is_null($userId)) {
$defaultUser['id'] = $userId;
}
return $this->config->get('user', $defaultUser);
}
}

View File

@@ -0,0 +1,231 @@
<?php
class Bugsnag_Error
{
private static $VALID_SEVERITIES = array(
'error',
'warning',
'info',
);
public $name;
public $payloadVersion = "2";
public $message;
public $severity = "warning";
public $stacktrace;
public $metaData = array();
public $config;
public $diagnostics;
public $previous;
public $groupingHash;
// Static error creation methods, to ensure that Error object is always complete
public static function fromPHPError(Bugsnag_Configuration $config, Bugsnag_Diagnostics $diagnostics, $code, $message, $file, $line, $fatal = false)
{
$error = new Bugsnag_Error($config, $diagnostics);
$error->setPHPError($code, $message, $file, $line, $fatal);
return $error;
}
public static function fromPHPException(Bugsnag_Configuration $config, Bugsnag_Diagnostics $diagnostics, Exception $exception)
{
$error = new Bugsnag_Error($config, $diagnostics);
$error->setPHPException($exception);
return $error;
}
public static function fromNamedError(Bugsnag_Configuration $config, Bugsnag_Diagnostics $diagnostics, $name, $message = null)
{
$error = new Bugsnag_Error($config, $diagnostics);
$error->setName($name)
->setMessage($message)
->setStacktrace(Bugsnag_Stacktrace::generate($config));
return $error;
}
// Private constructor (for use only by the static methods above)
private function __construct(Bugsnag_Configuration $config, Bugsnag_Diagnostics $diagnostics)
{
$this->config = $config;
$this->diagnostics = $diagnostics;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function setMessage($message)
{
$this->message = $message;
return $this;
}
public function setGroupingHash($groupingHash)
{
$this->groupingHash = $groupingHash;
return $this;
}
public function setStacktrace($stacktrace)
{
$this->stacktrace = $stacktrace;
return $this;
}
public function setSeverity($severity)
{
if (!is_null($severity)) {
if (in_array($severity, Bugsnag_Error::$VALID_SEVERITIES)) {
$this->severity = $severity;
} else {
error_log('Bugsnag Warning: Tried to set error severity to '.$severity.' which is not allowed.');
}
}
return $this;
}
public function setPHPException(Exception $exception)
{
$this->setName(get_class($exception))
->setMessage($exception->getMessage())
->setStacktrace(Bugsnag_Stacktrace::fromBacktrace($this->config, $exception->getTrace(), $exception->getFile(), $exception->getLine()));
if (method_exists($exception, 'getPrevious')) {
$this->setPrevious($exception->getPrevious());
}
return $this;
}
public function setPHPError($code, $message, $file, $line, $fatal = false)
{
if ($fatal) {
// Generating stacktrace for PHP fatal errors is not possible,
// since this code executes when the PHP process shuts down,
// rather than at the time of the crash.
//
// In these situations, we generate a "stacktrace" containing only
// the line and file number where the crash occurred.
$stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, $file, $line);
} else {
$stacktrace = Bugsnag_Stacktrace::generate($this->config);
}
$this->setName(Bugsnag_ErrorTypes::getName($code))
->setMessage($message)
->setSeverity(Bugsnag_ErrorTypes::getSeverity($code))
->setStacktrace($stacktrace);
return $this;
}
public function setMetaData($metaData)
{
if (is_array($metaData)) {
$this->metaData = array_merge_recursive($this->metaData, $metaData);
}
return $this;
}
public function setPrevious($exception)
{
if ($exception) {
$this->previous = Bugsnag_Error::fromPHPException($this->config, $this->diagnostics, $exception);
}
return $this;
}
public function toArray()
{
$errorArray = array(
'app' => $this->diagnostics->getAppData(),
'device' => $this->diagnostics->getDeviceData(),
'user' => $this->diagnostics->getUser(),
'context' => $this->diagnostics->getContext(),
'payloadVersion' => $this->payloadVersion,
'severity' => $this->severity,
'exceptions' => $this->exceptionArray(),
'metaData' => $this->cleanupObj($this->metaData),
);
if (isset($this->groupingHash)) {
$errorArray['groupingHash'] = $this->groupingHash;
}
return $errorArray;
}
public function exceptionArray()
{
if ($this->previous) {
$exceptionArray = $this->previous->exceptionArray();
} else {
$exceptionArray = array();
}
$exceptionArray[] = array(
'errorClass' => $this->name,
'message' => $this->message,
'stacktrace' => $this->stacktrace->toArray(),
);
return $exceptionArray;
}
private function cleanupObj($obj)
{
if (is_null($obj)) {
return;
}
if (is_array($obj)) {
$cleanArray = array();
foreach ($obj as $key => $value) {
// Apply filters if required
if (is_array($this->config->filters)) {
// Check if this key should be filtered
$shouldFilter = false;
foreach ($this->config->filters as $filter) {
if (strpos($key, $filter) !== false) {
$shouldFilter = true;
break;
}
}
// Apply filters
if ($shouldFilter) {
$cleanArray[$key] = '[FILTERED]';
} else {
$cleanArray[$key] = $this->cleanupObj($value);
}
}
}
return $cleanArray;
} elseif (is_string($obj)) {
// UTF8-encode if not already encoded
if (function_exists('mb_detect_encoding') && !mb_detect_encoding($obj, 'UTF-8', true)) {
return utf8_encode($obj);
} else {
return $obj;
}
} elseif (is_object($obj)) {
// json_encode -> json_decode trick turns an object into an array
return $this->cleanupObj(json_decode(json_encode($obj), true));
} else {
return $obj;
}
}
}

View File

@@ -0,0 +1,118 @@
<?php
class Bugsnag_ErrorTypes
{
private static $ERROR_TYPES = array(
E_ERROR => array(
'name' => 'PHP Fatal Error',
'severity' => 'error',
),
E_WARNING => array(
'name' => 'PHP Warning',
'severity' => 'warning',
),
E_PARSE => array(
'name' => 'PHP Parse Error',
'severity' => 'error',
),
E_NOTICE => array(
'name' => 'PHP Notice',
'severity' => 'info',
),
E_CORE_ERROR => array(
'name' => 'PHP Core Error',
'severity' => 'error',
),
E_CORE_WARNING => array(
'name' => 'PHP Core Warning',
'severity' => 'warning',
),
E_COMPILE_ERROR => array(
'name' => 'PHP Compile Error',
'severity' => 'error',
),
E_COMPILE_WARNING => array(
'name' => 'PHP Compile Warning',
'severity' => 'warning',
),
E_USER_ERROR => array(
'name' => 'User Error',
'severity' => 'error',
),
E_USER_WARNING => array(
'name' => 'User Warning',
'severity' => 'warning',
),
E_USER_NOTICE => array(
'name' => 'User Notice',
'severity' => 'info',
),
E_STRICT => array(
'name' => 'PHP Strict',
'severity' => 'info',
),
E_RECOVERABLE_ERROR => array(
'name' => 'PHP Recoverable Error',
'severity' => 'error',
),
// E_DEPRECATED (Since PHP 5.3.0)
8192 => array(
'name' => 'PHP Deprecated',
'severity' => 'info',
),
// E_USER_DEPRECATED (Since PHP 5.3.0)
16384 => array(
'name' => 'User Deprecated',
'severity' => 'info',
),
);
public static function isFatal($code)
{
return self::getSeverity($code) == 'error';
}
public static function getName($code)
{
if (array_key_exists($code, self::$ERROR_TYPES)) {
return self::$ERROR_TYPES[$code]['name'];
} else {
return "Unknown";
}
}
public static function getSeverity($code)
{
if (array_key_exists($code, self::$ERROR_TYPES)) {
return self::$ERROR_TYPES[$code]['severity'];
} else {
return "error";
}
}
public static function getLevelsForSeverity($severity)
{
$levels = 0;
foreach (Bugsnag_ErrorTypes::$ERROR_TYPES as $level => $info) {
if ($info['severity'] == $severity) {
$levels |= $level;
}
}
return $levels;
}
}

View File

@@ -0,0 +1,186 @@
<?php
class Bugsnag_Notification
{
private static $CONTENT_TYPE_HEADER = 'Content-type: application/json';
private $config;
private $errorQueue = array();
public function __construct(Bugsnag_Configuration $config)
{
$this->config = $config;
}
public function addError($error, $passedMetaData = array())
{
// Check if this error should be sent to Bugsnag
if (!$this->config->shouldNotify()) {
return false;
}
// Add global meta-data to error
$error->setMetaData($this->config->metaData);
// Add request meta-data to error
if (Bugsnag_Request::isRequest()) {
$error->setMetaData(Bugsnag_Request::getRequestMetaData());
}
// Add environment meta-data to error
if ($this->config->sendEnvironment && !empty($_ENV)) {
$error->setMetaData(array("Environment" => $_ENV));
}
// Add user-specified meta-data to error
$error->setMetaData($passedMetaData);
// Run beforeNotify function (can cause more meta-data to be merged)
if (isset($this->config->beforeNotifyFunction) && is_callable($this->config->beforeNotifyFunction)) {
$beforeNotifyReturn = call_user_func($this->config->beforeNotifyFunction, $error);
}
// Skip this error if the beforeNotify function returned FALSE
if (!isset($beforeNotifyReturn) || $beforeNotifyReturn !== false) {
$this->errorQueue[] = $error;
return true;
} else {
return false;
}
}
public function toArray()
{
$events = array();
foreach ($this->errorQueue as $error) {
$errorArray = $error->toArray();
if (!is_null($errorArray)) {
$events[] = $errorArray;
}
}
return array(
'apiKey' => $this->config->apiKey,
'notifier' => $this->config->notifier,
'events' => $events,
);
}
public function deliver()
{
if (!empty($this->errorQueue)) {
// Post the request to bugsnag
$this->postJSON($this->config->getNotifyEndpoint(), $this->toArray());
// Clear the error queue
$this->errorQueue = array();
}
}
public function postJSON($url, $data)
{
$body = json_encode($data);
// Prefer cURL if it is installed, otherwise fall back to fopen()
// cURL supports both timeouts and proxies
if (function_exists('curl_version')) {
$this->postWithCurl($url, $body);
} elseif (ini_get('allow_url_fopen')) {
$this->postWithFopen($url, $body);
} else {
error_log('Bugsnag Warning: Couldn\'t notify (neither cURL or allow_url_fopen are available on your PHP installation)');
}
}
private function postWithCurl($url, $body)
{
$http = curl_init($url);
// Default curl settings
curl_setopt($http, CURLOPT_HEADER, false);
curl_setopt($http, CURLOPT_RETURNTRANSFER, true);
curl_setopt($http, CURLOPT_POST, true);
curl_setopt($http, CURLOPT_HTTPHEADER, array(Bugsnag_Notification::$CONTENT_TYPE_HEADER));
curl_setopt($http, CURLOPT_POSTFIELDS, $body);
curl_setopt($http, CURLOPT_CONNECTTIMEOUT, $this->config->timeout);
curl_setopt($http, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($http, CURLOPT_VERBOSE, false);
if (defined('HHVM_VERSION')) {
curl_setopt($http, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
} else {
curl_setopt($http, CURL_IPRESOLVE_V4, true);
}
if (!empty($this->config->curlOptions)) {
foreach ($this->config->curlOptions as $option => $value) {
curl_setopt($http, $option, $value);
}
}
// Apply proxy settings (if present)
if (count($this->config->proxySettings)) {
if (isset($this->config->proxySettings['host'])) {
curl_setopt($http, CURLOPT_PROXY, $this->config->proxySettings['host']);
}
if (isset($this->config->proxySettings['port'])) {
curl_setopt($http, CURLOPT_PROXYPORT, $this->config->proxySettings['port']);
}
if (isset($this->config->proxySettings['user'])) {
$userPassword = $this->config->proxySettings['user'].':';
$userPassword .= isset($this->config->proxySettings['password']) ? $this->config->proxySettings['password'] : '';
curl_setopt($http, CURLOPT_PROXYUSERPWD, $userPassword);
}
}
// Execute the request and fetch the response
$responseBody = curl_exec($http);
$statusCode = curl_getinfo($http, CURLINFO_HTTP_CODE);
if ($statusCode > 200) {
error_log('Bugsnag Warning: Couldn\'t notify ('.$responseBody.')');
}
if (curl_errno($http)) {
error_log('Bugsnag Warning: Couldn\'t notify ('.curl_error($http).')');
}
curl_close($http);
}
private function postWithFopen($url, $body)
{
// Warn about lack of proxy support if we are using fopen()
if (count($this->config->proxySettings)) {
error_log('Bugsnag Warning: Can\'t use proxy settings unless cURL is installed');
}
// Warn about lack of timeout support if we are using fopen()
if ($this->config->timeout != Bugsnag_Configuration::$DEFAULT_TIMEOUT) {
error_log('Bugsnag Warning: Can\'t change timeout settings unless cURL is installed');
}
// Create the request context
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => Bugsnag_Notification::$CONTENT_TYPE_HEADER.'\r\n',
'content' => $body,
),
'ssl' => array(
'verify_peer' => false,
),
));
// Execute the request and fetch the response
if ($stream = fopen($url, 'rb', false, $context)) {
$response = stream_get_contents($stream);
if (!$response) {
error_log('Bugsnag Warning: Couldn\'t notify (no response)');
}
} else {
error_log('Bugsnag Warning: Couldn\'t notify (fopen failed)');
}
}
}

View File

@@ -0,0 +1,98 @@
<?php
class Bugsnag_Request
{
public static function isRequest()
{
return isset($_SERVER['REQUEST_METHOD']);
}
public static function getRequestMetaData()
{
$requestData = array();
// Request Tab
$requestData['request'] = array();
$requestData['request']['url'] = self::getCurrentUrl();
if (isset($_SERVER['REQUEST_METHOD'])) {
$requestData['request']['httpMethod'] = $_SERVER['REQUEST_METHOD'];
}
if (!empty($_POST)) {
$requestData['request']['params'] = $_POST;
} else {
if (isset($_SERVER['CONTENT_TYPE']) && stripos($_SERVER['CONTENT_TYPE'], 'application/json') === 0) {
$requestData['request']['params'] = json_decode(file_get_contents('php://input'));
}
}
$requestData['request']['ip'] = self::getRequestIp();
if (isset($_SERVER['HTTP_USER_AGENT'])) {
$requestData['request']['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
}
$headers = self::getRequestHeaders();
if (!empty($headers)) {
$requestData['request']['headers'] = $headers;
}
// Session Tab
if (!empty($_SESSION)) {
$requestData['session'] = $_SESSION;
}
// Cookies Tab
if (!empty($_COOKIE)) {
$requestData['cookies'] = $_COOKIE;
}
return $requestData;
}
public static function getContext()
{
if (self::isRequest() && isset($_SERVER['REQUEST_METHOD']) && isset($_SERVER["REQUEST_URI"])) {
return $_SERVER['REQUEST_METHOD'].' '.strtok($_SERVER["REQUEST_URI"], '?');
} else {
return;
}
}
public static function getUserId()
{
if (self::isRequest()) {
return self::getRequestIp();
} else {
return;
}
}
public static function getCurrentUrl()
{
$schema = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443) ? 'https://' : 'http://';
return $schema.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
}
public static function getRequestIp()
{
return isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
}
public static function getRequestHeaders()
{
if (function_exists('getallheaders')) {
return getallheaders();
}
$headers = array();
foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') {
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
}
}
return $headers;
}
}

View File

@@ -0,0 +1,145 @@
<?php
class Bugsnag_Stacktrace
{
private static $DEFAULT_NUM_LINES = 7;
private static $MAX_LINE_LENGTH = 200;
public $frames = array();
private $config;
public static function generate($config)
{
// Reduce memory usage by omitting args and objects from backtrace
if (version_compare(PHP_VERSION, '5.3.6') >= 0) {
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS & ~DEBUG_BACKTRACE_PROVIDE_OBJECT);
} elseif (version_compare(PHP_VERSION, '5.2.5') >= 0) {
$backtrace = debug_backtrace(false);
} else {
$backtrace = debug_backtrace();
}
return self::fromBacktrace($config, $backtrace, "[generator]", 0);
}
public static function fromFrame($config, $file, $line)
{
$stacktrace = new Bugsnag_Stacktrace($config);
$stacktrace->addFrame($file, $line, "[unknown]");
return $stacktrace;
}
public static function fromBacktrace($config, $backtrace, $topFile, $topLine)
{
$stacktrace = new Bugsnag_Stacktrace($config);
// PHP backtrace's are misaligned, we need to shift the file/line down a frame
foreach ($backtrace as $frame) {
if (!self::frameInsideBugsnag($frame)) {
$stacktrace->addFrame(
$topFile,
$topLine,
isset($frame['function']) ? $frame['function'] : null,
isset($frame['class']) ? $frame['class'] : null
);
}
if (isset($frame['file']) && isset($frame['line'])) {
$topFile = $frame['file'];
$topLine = $frame['line'];
} else {
$topFile = "[internal]";
$topLine = 0;
}
}
// Add a final stackframe for the "main" method
$stacktrace->addFrame($topFile, $topLine, '[main]');
return $stacktrace;
}
public static function frameInsideBugsnag($frame)
{
return isset($frame['class']) && strpos($frame['class'], 'Bugsnag_') === 0;
}
public function __construct($config)
{
$this->config = $config;
}
public function toArray()
{
return $this->frames;
}
public function addFrame($file, $line, $method, $class = null)
{
// Account for special "filenames" in eval'd code
$matches = array();
if (preg_match("/^(.*?)\((\d+)\) : (?:eval\(\)'d code|runtime-created function)$/", $file, $matches)) {
$file = $matches[1];
$line = $matches[2];
}
// Construct the frame
$frame = array(
'lineNumber' => $line,
'method' => $class ? "$class::$method" : $method,
);
// Attach some lines of code for context
if($this->config->sendCode) {
$frame['code'] = $this->getCode($file, $line, Bugsnag_Stacktrace::$DEFAULT_NUM_LINES);
}
// Check if this frame is inProject
$frame['inProject'] = !is_null($this->config->projectRootRegex) && preg_match($this->config->projectRootRegex, $file);
// Strip out projectRoot from start of file path
if (is_null($this->config->stripPathRegex)) {
$frame['file'] = $file;
} else {
$frame['file'] = preg_replace($this->config->stripPathRegex, '', $file);
}
$this->frames[] = $frame;
}
private function getCode($path, $line, $numLines)
{
if (empty($path) || empty($line) || !file_exists($path)) {
return NULL;
}
try {
// Get the number of lines in the file
$file = new SplFileObject($path);
$file->seek(PHP_INT_MAX);
$totalLines = $file->key() + 1;
// Work out which lines we should fetch
$start = max($line - floor($numLines / 2), 1);
$end = $start + ($numLines - 1);
if ($end > $totalLines) {
$end = $totalLines;
$start = max($end - ($numLines - 1), 1);
}
// Get the code for this range
$code = array();
$file->seek($start - 1);
while ($file->key() < $end) {
$code[$file->key() + 1] = rtrim(substr($file->current(), 0, Bugsnag_Stacktrace::$MAX_LINE_LENGTH));
$file->next();
}
return $code;
} catch (RuntimeException $ex) {
return null;
}
}
}

View File

@@ -0,0 +1,24 @@
<?php
abstract class Bugsnag_TestCase extends PHPUnit_Framework_TestCase
{
protected function getError($name = "Name", $message = "Message")
{
return Bugsnag_Error::fromNamedError($this->config, $this->diagnostics, $name, $message);
}
protected function getFixturePath($file)
{
return realpath(dirname(__FILE__)."/../fixtures/".$file);
}
protected function getFixture($file)
{
return file_get_contents($this->getFixturePath($file));
}
protected function getJsonFixture($file)
{
return json_decode($this->getFixture($file), true);
}
}

View File

@@ -0,0 +1,82 @@
<?php
class ClientTest extends PHPUnit_Framework_TestCase
{
protected $client;
protected function setUp()
{
// Mock the notify function
$this->client = $this->getMockBuilder('Bugsnag_Client')
->setMethods(array('notify'))
->setConstructorArgs(array('example-api-key'))
->getMock();
}
public function testErrorHandler()
{
$this->client->expects($this->once())
->method('notify');
$this->client->errorHandler(E_WARNING, "Something broke", "somefile.php", 123);
}
public function testExceptionHandler()
{
$this->client->expects($this->once())
->method('notify');
$this->client->exceptionHandler(new Exception("Something broke"));
}
public function testManualErrorNotification()
{
$this->client->expects($this->once())
->method('notify');
$this->client->notifyError("SomeError", "Some message");
}
public function testManualExceptionNotification()
{
$this->client->expects($this->once())
->method('notify');
$this->client->notifyException(new Exception("Something broke"));
}
public function testErrorReportingLevel()
{
$this->client->expects($this->once())
->method('notify');
$this->client->setErrorReportingLevel(E_NOTICE)
->errorHandler(E_NOTICE, "Something broke", "somefile.php", 123);
}
public function testErrorReportingLevelFails()
{
$this->client->expects($this->never())
->method('notify');
$this->client->setErrorReportingLevel(E_NOTICE)
->errorHandler(E_WARNING, "Something broke", "somefile.php", 123);
}
public function testErrorReportingWithoutNotice()
{
$this->client->expects($this->never())
->method('notify');
$this->client->setErrorReportingLevel(E_ALL & ~E_NOTICE)
->errorHandler(E_NOTICE, "Something broke", "somefile.php", 123);
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function testSetInvalidCurlOptions()
{
$return = $this->client->setCurlOptions("option");
}
}

View File

@@ -0,0 +1,73 @@
<?php
class ConfigurationTest extends PHPUnit_Framework_TestCase
{
protected $config;
protected function setUp()
{
$this->config = new Bugsnag_Configuration();
}
public function testDefaultEndpoint()
{
$this->assertEquals($this->config->getNotifyEndpoint(), "https://notify.bugsnag.com");
}
public function testNonSSLEndpoint()
{
$this->config->useSSL = false;
$this->assertEquals($this->config->getNotifyEndpoint(), "http://notify.bugsnag.com");
}
public function testCustomEndpoint()
{
$this->config->useSSL = false;
$this->config->endpoint = "localhost";
$this->assertEquals($this->config->getNotifyEndpoint(), "http://localhost");
}
public function testDefaultReleaseStageShouldNotify()
{
$this->assertTrue($this->config->shouldNotify());
}
public function testCustomReleaseStageShouldNotify()
{
$this->config->releaseStage = "staging";
$this->assertTrue($this->config->shouldNotify());
}
public function testCustomNotifyReleaseStagesShouldNotify()
{
$this->config->notifyReleaseStages = array("banana");
$this->assertFalse($this->config->shouldNotify());
}
public function testBothCustomShouldNotify()
{
$this->config->releaseStage = "banana";
$this->config->notifyReleaseStages = array("banana");
$this->assertTrue($this->config->shouldNotify());
}
public function testNotifier()
{
$this->assertEquals($this->config->notifier['name'], "Bugsnag PHP (Official)");
$this->assertEquals($this->config->notifier['url'], "https://bugsnag.com");
}
public function testShouldIgnore()
{
$this->config->errorReportingLevel = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED;
$this->assertTrue($this->config->shouldIgnoreErrorCode(E_NOTICE));
}
public function testShouldNotIgnore()
{
$this->config->errorReportingLevel = E_ALL;
$this->assertfalse($this->config->shouldIgnoreErrorCode(E_NOTICE));
}
}

View File

@@ -0,0 +1,51 @@
<?php
class DiagnosticsTest extends PHPUnit_Framework_TestCase
{
protected $config;
protected function setUp()
{
$this->config = new Bugsnag_Configuration();
$this->diagnostics = new Bugsnag_Diagnostics($this->config);
}
public function testDefaultAppData()
{
$this->config->releaseStage = 'qa1';
$this->config->appVersion = '1.2.3';
$this->config->type = "laravel";
$appData = $this->diagnostics->getAppData();
$this->assertEquals($appData['releaseStage'], 'qa1');
$this->assertEquals($appData['version'], '1.2.3');
$this->assertEquals($appData['type'], 'laravel');
}
public function testDefaultDeviceData()
{
$this->config->hostname = 'web1.example.com';
$deviceData = $this->diagnostics->getDeviceData();
$this->assertEquals($deviceData['hostname'], 'web1.example.com');
}
public function testDefaultContext()
{
$this->config->context = 'herp#derp';
$this->assertEquals($this->diagnostics->getContext(), 'herp#derp');
}
public function testDefaultUser()
{
$this->config->user = array('id' => 123, 'email' => "test@email.com", 'name' => "Bob Hoskins");
$userData = $this->diagnostics->getUser();
$this->assertEquals($userData['id'], 123);
$this->assertEquals($userData['email'], "test@email.com");
$this->assertEquals($userData['name'], "Bob Hoskins");
}
}

View File

@@ -0,0 +1,128 @@
<?php
require_once 'Bugsnag_TestCase.php';
class ErrorTest extends Bugsnag_TestCase
{
protected $config;
protected $diagnostics;
protected $error;
protected function setUp()
{
$this->config = new Bugsnag_Configuration();
$this->diagnostics = new Bugsnag_Diagnostics($this->config);
$this->error = $this->getError();
}
public function testMetaData()
{
$this->error->setMetaData(array("Testing" => array("globalArray" => "hi")));
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['metaData']["Testing"]["globalArray"], "hi");
}
public function testMetaDataMerging()
{
$this->error->setMetaData(array("Testing" => array("globalArray" => "hi")));
$this->error->setMetaData(array("Testing" => array("localArray" => "yo")));
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['metaData']["Testing"]["globalArray"], "hi");
$this->assertEquals($errorArray['metaData']["Testing"]["localArray"], "yo");
}
public function testFiltering()
{
$this->error->setMetaData(array("Testing" => array("password" => "123456")));
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['metaData']['Testing']['password'], '[FILTERED]');
}
public function testNoticeName()
{
$this->error->setPHPError(E_NOTICE, "Broken", "file", 123);
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['exceptions'][0]['errorClass'], 'PHP Notice');
}
public function testErrorName()
{
$this->error->setPHPError(E_ERROR, "Broken", "file", 123);
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['exceptions'][0]['errorClass'], 'PHP Fatal Error');
}
public function testErrorPayloadVersion()
{
$this->error->setPHPError(E_ERROR, "Broken", "file", 123);
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['payloadVersion'], '2');
}
public function testNoticeSeverity()
{
$this->error->setPHPError(E_NOTICE, "Broken", "file", 123);
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['severity'], 'info');
}
public function testErrorSeverity()
{
$this->error->setPHPError(E_ERROR, "Broken", "file", 123);
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['severity'], 'error');
}
public function testManualSeverity()
{
$this->error->setSeverity("error");
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['severity'], 'error');
}
public function testInvalidSeverity()
{
$this->error->setSeverity("bunk");
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['severity'], 'warning');
}
public function testPreviousException()
{
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$exception = new Exception("secondly", 65533, new Exception("firstly"));
$error = Bugsnag_Error::fromPHPException($this->config, $this->diagnostics, $exception);
$errorArray = $error->toArray();
$this->assertEquals(count($errorArray['exceptions']), 2);
$this->assertEquals($errorArray['exceptions'][0]['message'], 'firstly');
$this->assertEquals($errorArray['exceptions'][1]['message'], 'secondly');
}
}
public function testErrorGroupingHash()
{
$this->error->setGroupingHash('herp#derp');
$errorArray = $this->error->toArray();
$this->assertEquals($errorArray['groupingHash'], 'herp#derp');
}
public function testErrorGroupingHashNotSet()
{
$errorArray = $this->error->toArray();
$this->assertArrayNotHasKey('groupingHash', $errorArray);
}
}

View File

@@ -0,0 +1,11 @@
<?php
class ErrorTypesTest extends PHPUnit_Framework_TestCase
{
public function testGetLevelsForSeverity()
{
$this->assertEquals(Bugsnag_ErrorTypes::getLevelsForSeverity("error"), 4437);
$this->assertEquals(Bugsnag_ErrorTypes::getLevelsForSeverity("warning"), 674);
$this->assertEquals(Bugsnag_ErrorTypes::getLevelsForSeverity("info"), 27656);
}
}

View File

@@ -0,0 +1,126 @@
<?php
require_once 'Bugsnag_TestCase.php';
class NotificationTest extends Bugsnag_TestCase
{
protected $config;
protected $diagnostics;
protected $notification;
protected function setUp()
{
$this->config = new Bugsnag_Configuration();
$this->config->apiKey = "6015a72ff14038114c3d12623dfb018f";
$this->config->beforeNotifyFunction = "before_notify_skip_error";
$this->diagnostics = new Bugsnag_Diagnostics($this->config);
$this->notification = $this->getMockBuilder('Bugsnag_Notification')
->setMethods(array("postJSON"))
->setConstructorArgs(array($this->config))
->getMock();
}
public function testNotification()
{
// Create a mock notification object
$this->notification = $this->getMockBuilder('Bugsnag_Notification')
->setMethods(array("postJSON"))
->setConstructorArgs(array($this->config))
->getMock();
// Expect postJSON to be called
$this->notification->expects($this->once())
->method("postJSON")
->with($this->equalTo("https://notify.bugsnag.com"),
$this->anything());
// Add an error to the notification and deliver it
$this->notification->addError($this->getError());
$this->notification->deliver();
}
public function testBeforeNotifySkipsError()
{
$this->notification->expects($this->never())
->method("postJSON");
$this->notification->addError($this->getError("SkipMe", "Message"));
$this->notification->deliver();
}
/**
* Test for ensuring that the addError method calls shouldNotify
*
* If shouldNotify returns false, the error should not be added
*/
public function testAddErrorChecksShouldNotifyFalse()
{
$config = $this->getMockBuilder('Bugsnag_Configuration')
->setMethods(array("shouldNotify"))
->getMock();
$config->expects($this->once())
->method('shouldNotify')
->will($this->returnValue(false));
$notification = $this->getMockBuilder('Bugsnag_Notification')
->setMethods(array("postJSON"))
->setConstructorArgs(array($config))
->getMock();
$this->assertFalse($notification->addError($this->getError()));
}
/**
* Test for ensuring that the deliver method calls shouldNotify
*
* If shouldNotify returns false, the error should not be sent
*/
public function testDeliverChecksShouldNotify()
{
$config = $this->getMockBuilder('Bugsnag_Configuration')
->setMethods(array("shouldNotify"))
->getMock();
$config->expects($this->once())
->method('shouldNotify')
->will($this->returnValue(false));
$notification = $this->getMockBuilder('Bugsnag_Notification')
->setMethods(array("postJSON"))
->setConstructorArgs(array($config))
->getMock();
$notification->expects($this->never())
->method("postJSON");
$notification->addError($this->getError());
$notification->deliver();
}
public function testNoEnvironmentByDefault()
{
$_ENV["SOMETHING"] = "blah";
$notification = new Bugsnag_Notification($this->config);
$notification->addError($this->getError());
$notificationArray = $notification->toArray();
$this->assertArrayNotHasKey("Environment", $notificationArray["events"][0]["metaData"]);
}
public function testEnvironmentPresentWhenRequested()
{
$_ENV["SOMETHING"] = "blah";
$this->config->sendEnvironment = true;
$notification = new Bugsnag_Notification($this->config);
$notification->addError($this->getError());
$notificationArray = $notification->toArray();
$this->assertEquals($notificationArray["events"][0]["metaData"]["Environment"]["SOMETHING"], "blah");
}
}
function before_notify_skip_error($error)
{
return $error->name != "SkipMe";
}

View File

@@ -0,0 +1,37 @@
<?php
class RequestTest extends PHPUnit_Framework_TestCase
{
protected function setUp()
{
$_SERVER['REQUEST_METHOD'] = "GET";
$_SERVER['REQUEST_URI'] = "/blah/blah.php?some=param";
$_SERVER['REMOTE_ADDR'] = "123.45.67.8";
$_SERVER['SERVER_PORT'] = "80";
$_SERVER['HTTP_HOST'] = "example.com";
$_SERVER['HTTP_USER_AGENT'] = "Example Browser 1.2.3";
$_COOKIE = array("cookie" => "cookieval");
$_SESSION = array("session" => "sessionval");
}
public function testIsRequest()
{
$this->assertTrue(Bugsnag_Request::isRequest());
}
public function testGetContext()
{
$this->assertEquals(Bugsnag_Request::getContext(), "GET /blah/blah.php");
}
public function testGetCurrentUrl()
{
$this->assertEquals(Bugsnag_Request::getCurrentUrl(), "http://example.com/blah/blah.php?some=param");
}
public function testRequestIp()
{
$this->assertEquals(Bugsnag_Request::getRequestIp(), "123.45.67.8");
}
}

View File

@@ -0,0 +1,209 @@
<?php
require_once 'Bugsnag_TestCase.php';
class StacktraceTest extends Bugsnag_TestCase
{
protected $config;
protected $diagnostics;
protected function setUp()
{
$this->config = new Bugsnag_Configuration();
$this->diagnostics = new Bugsnag_Diagnostics($this->config);
}
protected function assertFrameEquals($frame, $method, $file, $line)
{
$this->assertEquals($frame["method"], $method);
$this->assertEquals($frame["file"], $file);
$this->assertEquals($frame["lineNumber"], $line);
}
protected function assertCodeEquals($expected, $actual)
{
$this->assertEquals(rtrim(substr($expected, 0, 200)), $actual);
}
public function testFromFrame()
{
$stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, "some_file.php", 123)->toarray();
$this->assertCount(1, $stacktrace);
$this->assertFrameEquals($stacktrace[0], "[unknown]", "some_file.php", 123);
}
public function testFrameInsideBugsnag()
{
$frame = $this->getJsonFixture('frames/non_bugsnag.json');
$bugsnagFrame = $this->getJsonFixture('frames/bugsnag.json');
$this->assertFalse(Bugsnag_Stacktrace::frameInsideBugsnag($frame));
$this->assertTrue(Bugsnag_Stacktrace::frameInsideBugsnag($bugsnagFrame));
}
public function testTriggeredErrorStacktrace()
{
$fixture = $this->getJsonFixture('backtraces/trigger_error.json');
$stacktrace = Bugsnag_Stacktrace::fromBacktrace($this->config, $fixture['backtrace'], $fixture['file'], $fixture['line'])->toArray();
$this->assertCount(4, $stacktrace);
$this->assertFrameEquals($stacktrace[0], "trigger_error", "[internal]", 0);
$this->assertFrameEquals($stacktrace[1], "crashy_function", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 17);
$this->assertFrameEquals($stacktrace[2], "parent_of_crashy_function", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 13);
$this->assertFrameEquals($stacktrace[3], "[main]", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 20);
}
public function testErrorHandlerStacktrace()
{
$fixture = $this->getJsonFixture('backtraces/error_handler.json');
$stacktrace = Bugsnag_Stacktrace::fromBacktrace($this->config, $fixture['backtrace'], $fixture['file'], $fixture['line'])->toArray();
$this->assertCount(3, $stacktrace);
$this->assertFrameEquals($stacktrace[0], "crashy_function", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 22);
$this->assertFrameEquals($stacktrace[1], "parent_of_crashy_function", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 13);
$this->assertFrameEquals($stacktrace[2], "[main]", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 25);
}
public function testExceptionHandlerStacktrace()
{
$fixture = $this->getJsonFixture('backtraces/exception_handler.json');
$stacktrace = Bugsnag_Stacktrace::fromBacktrace($this->config, $fixture['backtrace'], $fixture['file'], $fixture['line'])->toArray();
$this->assertCount(3, $stacktrace);
$this->assertFrameEquals($stacktrace[0], "crashy_function", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 25);
$this->assertFrameEquals($stacktrace[1], "parent_of_crashy_function", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 13);
$this->assertFrameEquals($stacktrace[2], "[main]", "/Users/james/src/bugsnag/bugsnag-php/testing.php", 28);
}
public function testAnonymousFunctionStackframes()
{
$fixture = $this->getJsonFixture('backtraces/anonymous_frame.json');
$stacktrace = Bugsnag_Stacktrace::fromBacktrace($this->config, $fixture['backtrace'], "somefile.php", 123)->toArray();
$this->assertCount(5, $stacktrace);
$this->assertFrameEquals($stacktrace[0], "Illuminate\\Support\\Facades\\Facade::__callStatic", "somefile.php", 123);
$this->assertFrameEquals($stacktrace[1], "Bugsnag\\BugsnagLaravel\\BugsnagFacade::notifyError", "controllers/ExampleController.php", 12);
$this->assertFrameEquals($stacktrace[2], "ExampleController::index", "controllers/ExampleController.php", 12);
$this->assertFrameEquals($stacktrace[3], "call_user_func_array", "[internal]", 0);
$this->assertFrameEquals($stacktrace[4], "[main]", "Routing/Controller.php", 194);
}
public function testXdebugErrorStackframes()
{
$fixture = $this->getJsonFixture('backtraces/xdebug_error.json');
$stacktrace = Bugsnag_Stacktrace::fromBacktrace($this->config, $fixture['backtrace'], $fixture['file'], $fixture['line'])->toArray();
$this->assertCount(7, $stacktrace);
$this->assertFrameEquals($stacktrace[0], null, "somefile.php", 123);
$this->assertFrameEquals($stacktrace[1], "Illuminate\\View\\Engines\\PhpEngine::evaluatePath", "/View/Engines/PhpEngine.php", 39);
$this->assertFrameEquals($stacktrace[2], "Illuminate\\View\\Engines\\CompilerEngine::get", "View/Engines/CompilerEngine.php", 57);
$this->assertFrameEquals($stacktrace[3], "Illuminate\\View\\View::getContents", "View/View.php", 136);
$this->assertFrameEquals($stacktrace[4], "Illuminate\\View\\View::renderContents", "View/View.php", 104);
$this->assertFrameEquals($stacktrace[5], "Illuminate\\View\\View::render", "View/View.php", 78);
$this->assertFrameEquals($stacktrace[6], "[main]", "storage/views/f2df2d6b49591efeb36fc46e6dc25e0e", 5);
}
public function testEvaledStackframes()
{
$evalFrame = $this->getJsonFixture('frames/eval.json');
$stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, $evalFrame["file"], $evalFrame["line"])->toArray();
$topFrame = $stacktrace[0];
$this->assertEquals($topFrame["file"], "path/some/file.php");
$this->assertEquals($topFrame["lineNumber"], 123);
$evalFrame = $this->getJsonFixture('frames/runtime_created.json');
$stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, $evalFrame["file"], $evalFrame["line"])->toArray();
$topFrame = $stacktrace[0];
$this->assertEquals($topFrame["file"], "path/some/file.php");
$this->assertEquals($topFrame["lineNumber"], 123);
}
public function testStrippingPaths()
{
$fixture = $this->getJsonFixture('backtraces/exception_handler.json');
$this->config->setStripPath("/Users/james/src/bugsnag/bugsnag-php/");
$stacktrace = Bugsnag_Stacktrace::fromBacktrace($this->config, $fixture['backtrace'], $fixture['file'], $fixture['line'])->toArray();
$this->assertCount(3, $stacktrace);
$this->assertFrameEquals($stacktrace[0], "crashy_function", "testing.php", 25);
$this->assertFrameEquals($stacktrace[1], "parent_of_crashy_function", "testing.php", 13);
$this->assertFrameEquals($stacktrace[2], "[main]", "testing.php", 28);
}
public function testCode()
{
$fileContents = explode("\n", $this->getFixture('code/File.php'));
$stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, $this->getFixturePath('code/File.php'), 12)->toArray();
$this->assertCount(1, $stacktrace);
$topFrame = $stacktrace[0];
$this->assertCount(7, $topFrame["code"]);
for ($i=9; $i<=15; $i++) {
$this->assertCodeEquals($fileContents[$i - 1], $topFrame["code"][$i]);
}
}
public function testCodeShortFile()
{
$fileContents = explode("\n", $this->getFixture('code/ShortFile.php'));
$stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, $this->getFixturePath('code/ShortFile.php'), 1)->toArray();
$this->assertCount(1, $stacktrace);
$topFrame = $stacktrace[0];
$this->assertCount(3, $topFrame["code"]);
for ($i=1; $i<=2; $i++) {
$this->assertCodeEquals($fileContents[$i - 1], $topFrame["code"][$i]);
}
}
public function testCodeEndOfFile()
{
$fileContents = explode("\n", $this->getFixture('code/File.php'));
$stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, $this->getFixturePath('code/File.php'), 22)->toArray();
$this->assertCount(1, $stacktrace);
$topFrame = $stacktrace[0];
$this->assertCount(7, $topFrame["code"]);
for ($i=16; $i<=22; $i++) {
$this->assertCodeEquals($fileContents[$i - 1], $topFrame["code"][$i]);
}
}
public function testCodeStartOfFile()
{
$fileContents = explode("\n", $this->getFixture('code/File.php'));
$stacktrace = Bugsnag_Stacktrace::fromFrame($this->config, $this->getFixturePath('code/File.php'), 1)->toArray();
$this->assertCount(1, $stacktrace);
$topFrame = $stacktrace[0];
$this->assertCount(7, $topFrame["code"]);
for ($i=1; $i<=7; $i++) {
$this->assertCodeEquals($fileContents[$i - 1], $topFrame["code"][$i]);
}
}
public function testCodeDisabled()
{
$config = new Bugsnag_Configuration();
$config->sendCode = false;
$stacktrace = Bugsnag_Stacktrace::fromFrame($config, $this->getFixturePath('code/File.php'), 1)->toArray();
$this->assertCount(1, $stacktrace);
$topFrame = $stacktrace[0];
$this->assertArrayNotHasKey('code', $topFrame);
}
}

View File

@@ -0,0 +1,25 @@
{
"backtrace": [
{
"file": "controllers/ExampleController.php",
"line": "12",
"class": "Illuminate\\Support\\Facades\\Facade",
"function": "__callStatic"
},
{
"file": "controllers/ExampleController.php",
"line": "12",
"class": "Bugsnag\\BugsnagLaravel\\BugsnagFacade",
"function": "notifyError"
},
{
"class": "ExampleController",
"function": "index"
},
{
"file": "Routing/Controller.php",
"line": "194",
"function": "call_user_func_array"
}
]
}

View File

@@ -0,0 +1,40 @@
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 22,
"backtrace": [
{
"file": "/Users/james/src/bugsnag/bugsnag-php/src/Bugsnag/Error.php",
"line": 116,
"function": "generate",
"class": "Bugsnag_Stacktrace"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/src/Bugsnag/Error.php",
"line": 25,
"function": "setPHPError",
"class": "Bugsnag_Error"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/src/Bugsnag/Client.php",
"line": 346,
"function": "fromPHPError",
"class": "Bugsnag_Error"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 22,
"function": "errorHandler",
"class": "Bugsnag_Client"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 13,
"function": "crashy_function"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 25,
"function": "parent_of_crashy_function"
}
]
}

View File

@@ -0,0 +1,16 @@
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 25,
"backtrace": [
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 13,
"function": "crashy_function"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 28,
"function": "parent_of_crashy_function"
}
]
}

View File

@@ -0,0 +1,43 @@
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 17,
"backtrace": [
{
"file": "/Users/james/src/bugsnag/bugsnag-php/src/Bugsnag/Error.php",
"line": 116,
"function": "generate",
"class": "Bugsnag_Stacktrace"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/src/Bugsnag/Error.php",
"line": 25,
"function": "setPHPError",
"class": "Bugsnag_Error"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/src/Bugsnag/Client.php",
"line": 346,
"function": "fromPHPError",
"class": "Bugsnag_Error"
},
{
"function": "errorHandler",
"class": "Bugsnag_Client"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 17,
"function": "trigger_error"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 13,
"function": "crashy_function"
},
{
"file": "/Users/james/src/bugsnag/bugsnag-php/testing.php",
"line": 20,
"function": "parent_of_crashy_function"
}
]
}

View File

@@ -0,0 +1,52 @@
{
"file": "somefile.php",
"line": 123,
"backtrace": [
{
"file": "/View/Engines/PhpEngine.php",
"line": 39,
"include_filename": "storage/framework/views/9159822bf9c110749a4f033b96974fef",
"args": []
},
{
"function": "evaluatePath",
"type": "->",
"class": "Illuminate\\View\\Engines\\PhpEngine",
"file": "View/Engines/CompilerEngine.php",
"line": 57,
"args": []
},
{
"function": "get",
"type": "->",
"class": "Illuminate\\View\\Engines\\CompilerEngine",
"file": "View/View.php",
"line": 136,
"args": []
},
{
"function": "getContents",
"type": "->",
"class": "Illuminate\\View\\View",
"file": "View/View.php",
"line": 104,
"args": []
},
{
"function": "renderContents",
"type": "->",
"class": "Illuminate\\View\\View",
"file": "View/View.php",
"line": 78,
"args": []
},
{
"function": "render",
"type": "->",
"class": "Illuminate\\View\\View",
"file": "storage/views/f2df2d6b49591efeb36fc46e6dc25e0e",
"line": 5,
"args": []
}
]
}

View File

@@ -0,0 +1,21 @@
<?
//
// Example PHP file
//
// Some variables
$a = 1;
$b = 2;
// Create an exception
$exception = new Exception("Exception!");
// Throw the exception
throw $exception;
// Some more variables
$c = 3;
$d = 4;
?>

View File

@@ -0,0 +1,2 @@
$a = 1;
$b = 2;

View File

@@ -0,0 +1,6 @@
{
"file": "Bugsnag/Client.php",
"line": "123",
"class": "Bugsnag_Client",
"function": "example_function"
}

View File

@@ -0,0 +1,5 @@
{
"file": "path/some/file.php(123) : eval()'d code",
"line": "12",
"function": "something"
}

View File

@@ -0,0 +1,6 @@
{
"file": "controllers/ExampleController.php",
"line": "12",
"class": "Illuminate\\Support\\Facades\\Facade",
"function": "__callStatic"
}

View File

@@ -0,0 +1,5 @@
{
"file": "path/some/file.php(123) : runtime-created function",
"line": "12",
"function": "something"
}

View File

@@ -0,0 +1,4 @@
preset: recommended
disabled:
- short_array_syntax

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2013-2014 Michael Dowling <mtdowling@gmail.com>
Copyright (c) 2014-2015 Graham Campbell <graham@cachethq.io>
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.

View File

@@ -0,0 +1,21 @@
#! /usr/bin/env php
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
if (file_exists($autoloadPath = __DIR__.'/../../autoload.php')) {
require_once $autoloadPath;
} else {
require_once __DIR__.'/vendor/autoload.php';
}
$application = new ClassPreloader\Application();
$application->run();

View File

@@ -0,0 +1,40 @@
{
"name": "classpreloader/classpreloader",
"description": "Helps class loading performance by generating a single PHP file containing all of the autoloaded files for a specific use case",
"keywords": ["autoload", "class", "preload"],
"license": "MIT",
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com"
},
{
"name": "Graham Campbell",
"email": "graham@cachethq.io"
}
],
"require":{
"php": ">=5.3.3",
"symfony/console": "~2.1",
"symfony/filesystem": "~2.1",
"symfony/finder": "~2.1",
"nikic/php-parser": "~1.3"
},
"require-dev":{
"phpunit/phpunit": "~4.0"
},
"autoload": {
"psr-4": {
"ClassPreloader\\": "src/"
}
},
"autoload-dev": {
"classmap": ["tests/stubs/"]
},
"bin": ["classpreloader.php"],
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
}
}

View File

@@ -0,0 +1,50 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Finder\Finder;
/**
* This is the application class.
*
* This is sets everything up for the CLI.
*/
class Application extends BaseApplication
{
/**
* Create a new application.
*
* @return void
*/
public function __construct()
{
parent::__construct('Class Preloader', '1.4');
// Create a finder to find each non-abstract command in the filesystem
$finder = new Finder();
$finder->files()
->in(__DIR__.'/Command')
->notName('Abstract*')
->name('*.php');
// Add each command to the CLI
foreach ($finder as $file) {
$filename = str_replace('\\', '/', $file->getRealpath());
$pos = strripos($filename, '/ClassPreloader/') + strlen('/ClassPreloader/src/');
$class = __NAMESPACE__.'\\'
.substr(str_replace('/', '\\', substr($filename, $pos)), 0, -4);
$this->add(new $class());
}
}
}

View File

@@ -0,0 +1,115 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader;
/**
* This is the class list class.
*
* This maintains a list of classes using a sort of doubly-linked list.
*/
class ClassList
{
/**
* The head node of the list.
*
* @var \ClassPreloader\ClassNode
*/
protected $head;
/**
* The current node of the list.
*
* @var \ClassPreloader\ClassNode
*/
protected $current;
/**
* Create a new class list.
*
* @return void
*/
public function __construct()
{
$this->clear();
}
/**
* Clear the contents of the list and reset the head node and current node.
*
* @return void
*/
public function clear()
{
$this->head = new ClassNode();
$this->current = $this->head;
}
/**
* Traverse to the next node in the list.
*
* @return void
*/
public function next()
{
if (isset($this->current->next)) {
$this->current = $this->current->next;
} else {
$this->current->next = new ClassNode(null, $this->current);
$this->current = $this->current->next;
}
}
/**
* Insert a value at the current position in the list.
*
* Any currently set value at this position will be pushed back in the list
* after the new value.
*
* @param mixed $value
*
* @return void
*/
public function push($value)
{
if (!$this->current->value) {
$this->current->value = $value;
} else {
$temp = $this->current;
$this->current = new ClassNode($value, $temp->prev);
$this->current->next = $temp;
$temp->prev = $this->current;
if ($temp === $this->head) {
$this->head = $this->current;
} else {
$this->current->prev->next = $this->current;
}
}
}
/**
* Traverse the ClassList and return a list of classes.
*
* @return array
*/
public function getClasses()
{
$classes = array();
$current = $this->head;
while ($current && $current->value) {
$classes[] = $current->value;
$current = $current->next;
}
return array_filter($classes);
}
}

View File

@@ -0,0 +1,161 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader;
require_once __DIR__.'/ClassNode.php';
require_once __DIR__.'/ClassList.php';
/**
* This is the class loader class.
*
* This creates an autoloader that intercepts and keeps track of each include
* in order that files must be included. This autoloader proxies to all other
* underlying autoloaders.
*/
class ClassLoader
{
/**
* The list of loaded classes.
*
* @var \ClassPreloader\ClassList
*/
public $classList;
/**
* Create a new class loader.
*
* @return void
*/
public function __construct()
{
$this->classList = new ClassList();
}
/**
* Destroy the class loader.
*
* This makes sure we're unregistered from the autoloader.
*
* @return void
*/
public function __destruct()
{
$this->unregister();
}
/**
* Wrap a block of code in the autoloader and get a list of loaded classes.
*
* @param callable $func
*
* @return \ClassPreloader\Config
*/
public static function getIncludes($func)
{
$loader = new static();
call_user_func($func, $loader);
$loader->unregister();
$config = new Config();
foreach ($loader->getFilenames() as $file) {
$config->addFile($file);
}
return $config;
}
/**
* Registers this instance as an autoloader.
*
* @return void
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'), true, true);
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class, interface or trait.
*
* We'll return true if it was loaded.
*
* @param string $class
*
* @return bool|null
*/
public function loadClass($class)
{
foreach (spl_autoload_functions() as $func) {
if (is_array($func) && $func[0] === $this) {
continue;
}
$this->classList->push($class);
if (call_user_func($func, $class)) {
break;
}
}
$this->classList->next();
return true;
}
/**
* Get an array of loaded file names in order of loading.
*
* @return array
*/
public function getFilenames()
{
$files = array();
foreach ($this->classList->getClasses() as $class) {
// Push interfaces before classes if not already loaded
try {
$r = new \ReflectionClass($class);
foreach ($r->getInterfaces() as $inf) {
$name = $inf->getFileName();
if ($name && !in_array($name, $files)) {
$files[] = $name;
}
}
if (!in_array($r->getFileName(), $files)) {
$files[] = $r->getFileName();
}
} catch (\ReflectionException $e) {
// We ignore all exceptions related to reflection,
// because in some cases class can't exists. This
// can be if you use in your code constructions like
//
// if (class_exists('SomeClass')) { // <-- here will trigger autoload
// class SomeSuperClass extends SomeClass {
// }
// }
//
// We ignore all problems with classes, interfaces and
// traits.
}
}
return $files;
}
}

View File

@@ -0,0 +1,56 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader;
/**
* This is the class node class.
*
* This class contains a value, and the previous/next pointers.
*/
class ClassNode
{
/**
* The next node pointer.
*
* @var \ClassPreloader\ClassNode|null
*/
public $next;
/**
* The previous node pointer.
*
* @var \ClassPreloader\ClassNode|null
*/
public $prev;
/**
* The value of the class node.
*
* @var mixed
*/
public $value;
/**
* Create a new class node.
*
* @param mixed $value
* @param \ClassPreloader\ClassNode|null $prev
*
* @return void
*/
public function __construct($value = null, $prev = null)
{
$this->value = $value;
$this->prev = $prev;
}
}

View File

@@ -0,0 +1,330 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader\Command;
use ClassPreloader\Config;
use ClassPreloader\Exception\SkipFileException;
use ClassPreloader\Parser\DirVisitor;
use ClassPreloader\Parser\FileVisitor;
use ClassPreloader\Parser\NodeTraverser;
use PhpParser\Lexer;
use PhpParser\Node\Stmt\Namespace_ as NamespaceNode;
use PhpParser\Parser;
use PhpParser\PrettyPrinter\Standard as PrettyPrinter;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
/**
* This is the pre-compile command class.
*
* This allows the user to communicate with class preloader.
*/
class PreCompileCommand extends Command
{
/**
* The printer.
*
* @var \PhpParser\PrettyPrinter\Standard
*/
protected $printer;
/**
* The parser.
*
* @var \PhpParser\Parser
*/
protected $parser;
/**
* The input.
*
* @var \Symfony\Component\Console\Input\InputInterface|null
*/
protected $input;
/**
* The output.
*
* @var \Symfony\Component\Console\Output\OutputInterface|null
*/
protected $output;
/**
* The traverser.
*
* @var \ClassPreloader\Parser\NodeTraverser|null
*/
protected $traverser;
/**
* Create a new pre-compile command.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->printer = new PrettyPrinter();
$this->parser = new Parser(new Lexer());
}
/**
* Configure the current command.
*
* @return void
*/
protected function configure()
{
parent::configure();
$this->setName('compile')
->setDescription('Compiles classes into a single file')
->addOption('config', null, InputOption::VALUE_REQUIRED, 'CSV of filenames to load, or the path to a PHP script that returns an array of file names')
->addOption('output', null, InputOption::VALUE_REQUIRED)
->addOption('skip_dir_file', null, InputOption::VALUE_NONE, 'Skip files with __DIR__ or __FILE__ to make the cache portable')
->addOption('fix_dir', null, InputOption::VALUE_REQUIRED, 'Convert __DIR__ constants to the original directory of a file', 1)
->addOption('fix_file', null, InputOption::VALUE_REQUIRED, 'Convert __FILE__ constants to the original path of a file', 1)
->addOption('strip_comments', null, InputOption::VALUE_REQUIRED, 'Set to 1 to strip comments from each source file', 0)
->setHelp(<<<EOF
The <info>%command.name%</info> command iterates over each script, normalizes
the file to be wrapped in namespaces, and combines each file into a single PHP
file.
EOF
);
}
/**
* Get the node traverser used by the command.
*
* @return \ClassPreloader\Parser\NodeTraverser
*/
protected function getTraverser()
{
if (!$this->traverser) {
$this->traverser = new NodeTraverser();
if ($this->input->getOption('fix_dir')) {
$this->traverser->addVisitor(new DirVisitor($this->input->getOption('skip_dir_file')));
}
if ($this->input->getOption('fix_file')) {
$this->traverser->addVisitor(new FileVisitor($this->input->getOption('skip_dir_file')));
}
}
return $this->traverser;
}
/**
* Get a pretty printed string of code from a file while applying visitors.
*
* @param string $file
*
* @throws \RuntimeException
*
* @return string
*/
protected function getCode($file)
{
if (!is_readable($file)) {
throw new \RuntimeException("Cannot open {$file} for reading");
}
if ($this->input->getOption('strip_comments')) {
$content = php_strip_whitespace($file);
} else {
$content = file_get_contents($file);
}
$parsed = $this->parser->parse($content);
$stmts = $this->getTraverser()->traverseFile($parsed, $file);
$pretty = $this->printer->prettyPrint($stmts);
// Remove the open PHP tag
if (substr($pretty, 5) === '<?php') {
$pretty = substr($pretty, 7);
}
return $this->getCodeWrappedIntoNamespace($parsed, $pretty);
}
/**
* Wrap the code into a namespace.
*
* @param array $parsed
* @param string $pretty
*
* @return string
*/
protected function getCodeWrappedIntoNamespace(array $parsed, $pretty)
{
if ($this->parsedCodeHasNamespaces($parsed)) {
$pretty = preg_replace('/^\s*(namespace.*);/i', '${1} {', $pretty, 1)."\n}\n";
} else {
$pretty = sprintf("namespace {\n%s\n}\n", $pretty);
}
return preg_replace('/(?<!.)[\r\n]+/', '', $pretty);
}
/**
* Check parsed code for having namespaces.
*
* @param array $parsed
*
* @return bool
*/
protected function parsedCodeHasNamespaces(array $parsed)
{
// Namespaces can only be on first level in the code,
// so we make only check on it.
$node = array_filter(
$parsed,
function ($value) {
return $value instanceof NamespaceNode;
}
);
return !empty($node);
}
/**
* Validate the command options.
*
* @throws \InvalidArgumentException
*
* @return void
*/
protected function validateCommand()
{
if (!$this->input->getOption('output')) {
throw new \InvalidArgumentException('An output option is required');
}
if (!$this->input->getOption('config')) {
throw new \InvalidArgumentException('A config option is required');
}
}
/**
* Get a list of files in order.
*
* @param mixed $config Configuration option
*
* @throws \InvalidArgumentException
*
* @return array
*/
protected function getFileList($config)
{
$this->output->writeln('> Loading configuration file');
$filesystem = new Filesystem();
if (strpos($config, ',')) {
return array_filter(explode(',', $config));
}
// Ensure absolute paths are resolved
if (!$filesystem->isAbsolutePath($config)) {
$config = getcwd().'/'.$config;
}
// Ensure that the config file exists
if (!file_exists($config)) {
throw new \InvalidArgumentException(sprintf('Configuration file "%s" does not exist.', $config));
}
$result = require $config;
if ($result instanceof Config) {
foreach ($result->getVisitors() as $visitor) {
$this->getTraverser()->addVisitor($visitor);
}
return $result;
} elseif (is_array($result)) {
return $result;
}
throw new \InvalidArgumentException('Config must return an array of filenames or a Config object');
}
/**
* Prepare the output file and directory.
*
* @param string $outputFile
*
* @throws \RuntimeException
*
* @return void
*/
protected function prepareOutput($outputFile)
{
$dir = dirname($outputFile);
if (!is_dir($dir) && !mkdir($dir, 0777, true)) {
throw new \RuntimeException('Unable to create directory '.$dir);
}
}
/**
* Executes the pre-compile command.
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
*
* @throws \RuntimeException
*
* @return null|int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->input = $input;
$this->output = $output;
$this->validateCommand();
$outputFile = $this->input->getOption('output');
$config = $this->input->getOption('config');
$files = $this->getFileList($config);
$output->writeLn('- Found '.count($files).' files');
// Make sure that the output dir can be used or create it
$this->prepareOutput($outputFile);
if (!$handle = fopen($input->getOption('output'), 'w')) {
throw new \RuntimeException("Unable to open {$outputFile} for writing");
}
// Write the first line of the output
fwrite($handle, "<?php\n");
$output->writeln('> Compiling classes');
$count = 0;
$countSkipped = 0;
foreach ($files as $file) {
$count++;
try {
$code = $this->getCode($file);
$this->output->writeln('- Writing '.$file);
fwrite($handle, $code."\n");
} catch (SkipFileException $ex) {
$countSkipped++;
$this->output->writeln('- Skipping '.$file);
}
}
fclose($handle);
$output->writeln("> Compiled loader written to {$outputFile}");
$output->writeln('- Files: '.($count - $countSkipped).'/'.$count.' (skipped: '.$countSkipped.')');
$output->writeln('- Filesize: '.(round(filesize($outputFile) / 1024)).' kb');
}
}

View File

@@ -0,0 +1,159 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader;
use ClassPreloader\Parser\AbstractNodeVisitor;
use IteratorAggregate;
/**
* This is the config class.
*
* This contains all the class preloader configuration.
*/
class Config implements IteratorAggregate
{
/**
* The array of AbstractNodeVisitor objects that visit nodes.
*
* @var array
*/
protected $visitors = array();
/**
* The array of file names.
*
* @var array
*/
protected $filenames = array();
/**
* The array of exclusive filters.
*
* @var array
*/
protected $exclusiveFilters = array();
/**
* The array of inclusive filters.
*
* @var array
*/
protected $inclusiveFilters = array();
/**
* Add the filename owned by the config.
*
* @param string $filename
*
* @return \ClassPreloader\Config
*/
public function addFile($filename)
{
$this->filenames[] = $filename;
return $this;
}
/**
* Get an array of file names that satisfy any added filters.
*
* @return array
*/
public function getFilenames()
{
$filenames = array();
foreach ($this->filenames as $f) {
foreach ($this->inclusiveFilters as $filter) {
if (!preg_match($filter, $f)) {
continue 2;
}
}
foreach ($this->exclusiveFilters as $filter) {
if (preg_match($filter, $f)) {
continue 2;
}
}
$filenames[] = $f;
}
return $filenames;
}
/**
* Get an iterator for the filenames.
*
* @return \ArrayIterator
*/
public function getIterator()
{
return new \ArrayIterator($this->getFilenames());
}
/**
* Add a filter used to filter out file names matching the pattern.
*
* We're filtering the classes using a regular expression.
*
* @param string $pattern
*
* @return \ClassPreloader\Config
*/
public function addExclusiveFilter($pattern)
{
$this->exclusiveFilters[] = $pattern;
return $this;
}
/**
* Add a filter used to grab only file names matching the pattern.
*
* We're filtering the classes using a regular expression.
*
* @param string $pattern Regular expression pattern
*
* @return \ClassPreloader\Config
*/
public function addInclusiveFilter($pattern)
{
$this->inclusiveFilters[] = $pattern;
return $this;
}
/**
* Add a visitor.
*
* It will visit each node when traversing the node list of each file.
*
* @param \ClassPreloader\Parser\AbstractNodeVisitor $visitor
*
* @return \ClassPreloader\Config
*/
public function addVisitor(AbstractNodeVisitor $visitor)
{
$this->visitors[] = $visitor;
return $this;
}
/**
* Get an array of node visitors.
*
* @return array
*/
public function getVisitors()
{
return $this->visitors;
}
}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader\Exception;
use Exception;
/**
* This is the skip file exception class.
*/
class SkipFileException extends Exception
{
//
}

View File

@@ -0,0 +1,64 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader\Parser;
use PhpParser\NodeVisitorAbstract;
/**
* This is the abstract node visitor class.
*
* This is used to track the filename.
*/
abstract class AbstractNodeVisitor extends NodeVisitorAbstract
{
/**
* The current file being parsed.
*
* @var string
*/
protected $filename = '';
/**
* Set the full path to the current file being parsed.
*
* @param string $filename
*
* @return \ClassPreloader\Parser\AbstractNodeVisitor
*/
public function setFilename($filename)
{
$this->filename = $filename;
return $this;
}
/**
* Get the full path to the current file being parsed.
*
* @return string
*/
public function getFilename()
{
return $this->filename;
}
/**
* Get the directory of the current file being parsed.
*
* @return string
*/
public function getDir()
{
return dirname($this->getFilename());
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader\Parser;
use ClassPreloader\Exception\SkipFileException;
use PhpParser\Node;
use PhpParser\Node\Scalar\MagicConst\Dir as DirNode;
use PhpParser\Node\Scalar\String_ as StringNode;
/**
* This is the directory node visitor class.
*
* This is used to replace all references to __DIR__ with the actual directory.
*/
class DirVisitor extends AbstractNodeVisitor
{
/**
* Should we skip the file if it contains a dir constant?
*
* @var bool
*/
protected $skip = false;
/**
* Create a new directory visitor.
*
* @param bool $skip
*
* @return void
*/
public function __construct($skip = false)
{
$this->skip = $skip;
}
/**
* Enter and modify the node.
*
* @param \PhpParser\Node $node
*
* @return void
*/
public function enterNode(Node $node)
{
if ($node instanceof DirNode) {
if ($this->skip) {
throw new SkipFileException('__DIR__ constant found, skipping...');
}
return new StringNode($this->getDir());
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader\Parser;
use ClassPreloader\Exception\SkipFileException;
use PhpParser\Node;
use PhpParser\Node\Scalar\MagicConst\File as FileNode;
use PhpParser\Node\Scalar\String_ as StringNode;
/**
* This is the file node visitor class.
*
* This is used to replace all references to __FILE__ with the actual file.
*/
class FileVisitor extends AbstractNodeVisitor
{
/**
* Should we skip the file if it contains a file constant?
*
* @var bool
*/
protected $skip = false;
/**
* Create a new file visitor.
*
* @param bool $skip
*
* @return void
*/
public function __construct($skip = false)
{
$this->skip = $skip;
}
/**
* Enter and modify the node.
*
* @param \PhpParser\Node $node
*
* @return void
*/
public function enterNode(Node $node)
{
if ($node instanceof FileNode) {
if ($this->skip) {
throw new SkipFileException('__FILE__ constant found, skipping...');
}
return new StringNode($this->getFilename());
}
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of Class Preloader.
*
* (c) Graham Campbell <graham@cachethq.io>
* (c) Michael Dowling <mtdowling@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace ClassPreloader\Parser;
use PhpParser\NodeTraverser as BaseTraverser;
/**
* This is the file node visitor class.
*
* This allows a filename to be set when visiting.
*/
class NodeTraverser extends BaseTraverser
{
/**
* Transverse the file.
*
* @param array $nodes
* @param string $filename
*
* @return void
*/
public function traverseFile(array $nodes, $filename)
{
// Set the correct state on each visitor
foreach ($this->visitors as $visitor) {
if ($visitor instanceof AbstractNodeVisitor) {
$visitor->setFilename($filename);
}
}
return $this->traverse($nodes);
}
}

View File

@@ -0,0 +1,413 @@
<?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
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
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 PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-0 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $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 bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $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 bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
if ('\\' == $class[0]) {
$class = substr($class, 1);
}
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative) {
return false;
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if ($file === null && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if ($file === null) {
// Remember that this class does not exist.
return $this->classMap[$class] = false;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
if (0 === strpos($class, $prefix)) {
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

View File

@@ -0,0 +1,595 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Absolute_Positioner' => $vendorDir . '/dompdf/dompdf/include/absolute_positioner.cls.php',
'Abstract_Renderer' => $vendorDir . '/dompdf/dompdf/include/abstract_renderer.cls.php',
'Adobe_Font_Metrics' => $vendorDir . '/phenx/php-font-lib/classes/Adobe_Font_Metrics.php',
'Attribute_Translator' => $vendorDir . '/dompdf/dompdf/include/attribute_translator.cls.php',
'Block_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/block_frame_decorator.cls.php',
'Block_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/block_frame_reflower.cls.php',
'Block_Positioner' => $vendorDir . '/dompdf/dompdf/include/block_positioner.cls.php',
'Block_Renderer' => $vendorDir . '/dompdf/dompdf/include/block_renderer.cls.php',
'CPDF_Adapter' => $vendorDir . '/dompdf/dompdf/include/cpdf_adapter.cls.php',
'CSS_Color' => $vendorDir . '/dompdf/dompdf/include/css_color.cls.php',
'Cached_PDF_Decorator' => $vendorDir . '/dompdf/dompdf/include/cached_pdf_decorator.cls.php',
'Canvas' => $vendorDir . '/dompdf/dompdf/include/canvas.cls.php',
'Canvas_Factory' => $vendorDir . '/dompdf/dompdf/include/canvas_factory.cls.php',
'Cellmap' => $vendorDir . '/dompdf/dompdf/include/cellmap.cls.php',
'CreateAccessTable' => $baseDir . '/database/migrations/2015_05_07_053704_create_access_table.php',
'CreateAlertNoticeTable' => $baseDir . '/database/migrations/2015_05_07_053318_create_alert_notice_table.php',
'CreateAutoResponseTable' => $baseDir . '/database/migrations/2015_05_07_052924_create_auto_response_table.php',
'CreateBanlistTable' => $baseDir . '/database/migrations/2015_05_07_052638_create_banlist_table.php',
'CreateCompanyTable' => $baseDir . '/database/migrations/2015_05_07_045611_create_company_table.php',
'CreateDateFormatTable' => $baseDir . '/database/migrations/2015_05_07_045158_create_date_format_table.php',
'CreateDateTimeFormatTable' => $baseDir . '/database/migrations/2015_05_07_044521_create_date_time_format_table.php',
'CreateDepartmentTable' => $baseDir . '/database/migrations/2015_05_07_044229_create_department_table.php',
'CreateEmailTable' => $baseDir . '/database/migrations/2015_05_07_043904_create_email_table.php',
'CreateEmailsTable' => $baseDir . '/database/migrations/2015_05_07_043529_create_emails_table.php',
'CreateFooter2sTable' => $baseDir . '/database/migrations/2015_05_06_082026_create_footer2s_table.php',
'CreateFooter3sTable' => $baseDir . '/database/migrations/2015_05_06_092125_create_footer3s_table.php',
'CreateFooter4sTable' => $baseDir . '/database/migrations/2015_05_06_092132_create_footer4s_table.php',
'CreateFootersTable' => $baseDir . '/database/migrations/2015_05_06_073651_create_footers_table.php',
'CreateFormDetailsTable' => $baseDir . '/database/migrations/2015_05_07_041509_create_form_details_table.php',
'CreateFormNameTable' => $baseDir . '/database/migrations/2015_05_07_041459_create_form_name_table.php',
'CreateFormValueTable' => $baseDir . '/database/migrations/2015_05_07_041448_create_form_value_table.php',
'CreateGroupAssignDepartmentTable' => $baseDir . '/database/migrations/2015_05_07_040647_create_group_assign_department_table.php',
'CreateGroupsTable' => $baseDir . '/database/migrations/2015_05_07_040934_create_groups_table.php',
'CreateGuestNoteTable' => $baseDir . '/database/migrations/2015_05_06_133346_create_guest_note_table.php',
'CreateHelpTopicTable' => $baseDir . '/database/migrations/2015_05_06_132844_create_help_topic_table.php',
'CreateLanguagesTable' => $baseDir . '/database/migrations/2015_05_06_131238_create_languages_table.php',
'CreateLogTable' => $baseDir . '/database/migrations/2015_05_06_130627_create_log_table.php',
'CreateMailboxProtocolTable' => $baseDir . '/database/migrations/2015_05_06_125817_create_mailbox_protocol_table.php',
'CreateOrganizationTable' => $baseDir . '/database/migrations/2015_05_06_125328_create_organization_table.php',
'CreatePasswordResetsTable' => $baseDir . '/database/migrations/2014_10_12_100000_create_password_resets_table.php',
'CreatePriorityTable' => $baseDir . '/database/migrations/2015_06_09_062121_create_priority_table.php',
'CreateSlaTable' => $baseDir . '/database/migrations/2015_05_06_123928_create_sla_table.php',
'CreateSmtpTable' => $baseDir . '/database/migrations/2015_08_10_114142_create_smtp_table.php',
'CreateSystemTable' => $baseDir . '/database/migrations/2015_05_06_123624_create_system_table.php',
'CreateTeamAssignAgentTable' => $baseDir . '/database/migrations/2015_05_06_122830_create_team_assign_agent_table.php',
'CreateTeamTable' => $baseDir . '/database/migrations/2015_05_06_123154_create_team_table.php',
'CreateTemplateTable' => $baseDir . '/database/migrations/2015_05_06_122431_create_template_table.php',
'CreateTicketAttachmentTable' => $baseDir . '/database/migrations/2015_05_06_115733_create_ticket_attachment_table.php',
'CreateTicketCollaboratorTable' => $baseDir . '/database/migrations/2015_05_06_115133_create_ticket_collaborator_table.php',
'CreateTicketPriorityTable' => $baseDir . '/database/migrations/2015_05_06_114327_create_ticket_priority_table.php',
'CreateTicketSettingsTable' => $baseDir . '/database/migrations/2015_05_06_112140_create_ticket_settings_table.php',
'CreateTicketStatusTable' => $baseDir . '/database/migrations/2015_05_06_110518_create_ticket_status_table.php',
'CreateTicketTable' => $baseDir . '/database/migrations/2015_05_06_120651_create_ticket_table.php',
'CreateTicketThreadTable' => $baseDir . '/database/migrations/2015_05_06_105005_create_ticket_thread_table.php',
'CreateTicketsourceTable' => $baseDir . '/database/migrations/2015_07_10_061107_create_ticketsource_table.php',
'CreateTimeFormatTable' => $baseDir . '/database/migrations/2015_05_07_063628_create_time_format_table.php',
'CreateTimezoneTable' => $baseDir . '/database/migrations/2015_05_06_103949_create_timezone_table.php',
'CreateUsersTable' => $baseDir . '/database/migrations/2014_10_12_000000_create_users_table.php',
'DOMPDF' => $vendorDir . '/dompdf/dompdf/include/dompdf.cls.php',
'DOMPDF_Exception' => $vendorDir . '/dompdf/dompdf/include/dompdf_exception.cls.php',
'DOMPDF_Image_Exception' => $vendorDir . '/dompdf/dompdf/include/dompdf_image_exception.cls.php',
'DatabaseSeeder' => $baseDir . '/database/seeds/DatabaseSeeder.php',
'Encoding_Map' => $vendorDir . '/phenx/php-font-lib/classes/Encoding_Map.php',
'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php',
'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php',
'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php',
'Fixed_Positioner' => $vendorDir . '/dompdf/dompdf/include/fixed_positioner.cls.php',
'Font' => $vendorDir . '/phenx/php-font-lib/classes/Font.php',
'Font_Binary_Stream' => $vendorDir . '/phenx/php-font-lib/classes/Font_Binary_Stream.php',
'Font_EOT' => $vendorDir . '/phenx/php-font-lib/classes/Font_EOT.php',
'Font_EOT_Header' => $vendorDir . '/phenx/php-font-lib/classes/Font_EOT_Header.php',
'Font_Glyph_Outline' => $vendorDir . '/phenx/php-font-lib/classes/Font_Glyph_Outline.php',
'Font_Glyph_Outline_Component' => $vendorDir . '/phenx/php-font-lib/classes/Font_Glyph_Outline_Component.php',
'Font_Glyph_Outline_Composite' => $vendorDir . '/phenx/php-font-lib/classes/Font_Glyph_Outline_Composite.php',
'Font_Glyph_Outline_Simple' => $vendorDir . '/phenx/php-font-lib/classes/Font_Glyph_Outline_Simple.php',
'Font_Header' => $vendorDir . '/phenx/php-font-lib/classes/Font_Header.php',
'Font_Metrics' => $vendorDir . '/dompdf/dompdf/include/font_metrics.cls.php',
'Font_OpenType' => $vendorDir . '/phenx/php-font-lib/classes/Font_OpenType.php',
'Font_OpenType_Table_Directory_Entry' => $vendorDir . '/phenx/php-font-lib/classes/Font_OpenType_Table_Directory_Entry.php',
'Font_Table' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table.php',
'Font_Table_Directory_Entry' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_Directory_Entry.php',
'Font_Table_cmap' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_cmap.php',
'Font_Table_glyf' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_glyf.php',
'Font_Table_head' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_head.php',
'Font_Table_hhea' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_hhea.php',
'Font_Table_hmtx' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_hmtx.php',
'Font_Table_kern' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_kern.php',
'Font_Table_loca' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_loca.php',
'Font_Table_maxp' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_maxp.php',
'Font_Table_name' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_name.php',
'Font_Table_name_Record' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_name_Record.php',
'Font_Table_os2' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_os2.php',
'Font_Table_post' => $vendorDir . '/phenx/php-font-lib/classes/Font_Table_post.php',
'Font_TrueType' => $vendorDir . '/phenx/php-font-lib/classes/Font_TrueType.php',
'Font_TrueType_Collection' => $vendorDir . '/phenx/php-font-lib/classes/Font_TrueType_Collection.php',
'Font_TrueType_Header' => $vendorDir . '/phenx/php-font-lib/classes/Font_TrueType_Header.php',
'Font_TrueType_Table_Directory_Entry' => $vendorDir . '/phenx/php-font-lib/classes/Font_TrueType_Table_Directory_Entry.php',
'Font_WOFF' => $vendorDir . '/phenx/php-font-lib/classes/Font_WOFF.php',
'Font_WOFF_Header' => $vendorDir . '/phenx/php-font-lib/classes/Font_WOFF_Header.php',
'Font_WOFF_Table_Directory_Entry' => $vendorDir . '/phenx/php-font-lib/classes/Font_WOFF_Table_Directory_Entry.php',
'Frame' => $vendorDir . '/dompdf/dompdf/include/frame.cls.php',
'FrameList' => $vendorDir . '/dompdf/dompdf/include/frame.cls.php',
'FrameListIterator' => $vendorDir . '/dompdf/dompdf/include/frame.cls.php',
'FrameTreeIterator' => $vendorDir . '/dompdf/dompdf/include/frame.cls.php',
'FrameTreeList' => $vendorDir . '/dompdf/dompdf/include/frame.cls.php',
'Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/frame_decorator.cls.php',
'Frame_Factory' => $vendorDir . '/dompdf/dompdf/include/frame_factory.cls.php',
'Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/frame_reflower.cls.php',
'Frame_Tree' => $vendorDir . '/dompdf/dompdf/include/frame_tree.cls.php',
'GD_Adapter' => $vendorDir . '/dompdf/dompdf/include/gd_adapter.cls.php',
'IlluminateQueueClosure' => $vendorDir . '/laravel/framework/src/Illuminate/Queue/IlluminateQueueClosure.php',
'Image_Cache' => $vendorDir . '/dompdf/dompdf/include/image_cache.cls.php',
'Image_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/image_frame_decorator.cls.php',
'Image_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/image_frame_reflower.cls.php',
'Image_Renderer' => $vendorDir . '/dompdf/dompdf/include/image_renderer.cls.php',
'Inline_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/inline_frame_decorator.cls.php',
'Inline_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/inline_frame_reflower.cls.php',
'Inline_Positioner' => $vendorDir . '/dompdf/dompdf/include/inline_positioner.cls.php',
'Inline_Renderer' => $vendorDir . '/dompdf/dompdf/include/inline_renderer.cls.php',
'Javascript_Embedder' => $vendorDir . '/dompdf/dompdf/include/javascript_embedder.cls.php',
'Line_Box' => $vendorDir . '/dompdf/dompdf/include/line_box.cls.php',
'List_Bullet_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/list_bullet_frame_decorator.cls.php',
'List_Bullet_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/list_bullet_frame_reflower.cls.php',
'List_Bullet_Image_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/list_bullet_image_frame_decorator.cls.php',
'List_Bullet_Positioner' => $vendorDir . '/dompdf/dompdf/include/list_bullet_positioner.cls.php',
'List_Bullet_Renderer' => $vendorDir . '/dompdf/dompdf/include/list_bullet_renderer.cls.php',
'Null_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/null_frame_decorator.cls.php',
'Null_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/null_frame_reflower.cls.php',
'Null_Positioner' => $vendorDir . '/dompdf/dompdf/include/null_positioner.cls.php',
'PDFLib_Adapter' => $vendorDir . '/dompdf/dompdf/include/pdflib_adapter.cls.php',
'PHPUnit_Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
'PHPUnit_Extensions_GroupTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/GroupTestSuite.php',
'PHPUnit_Extensions_PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestCase.php',
'PHPUnit_Extensions_PhptTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestSuite.php',
'PHPUnit_Extensions_RepeatedTest' => $vendorDir . '/phpunit/phpunit/src/Extensions/RepeatedTest.php',
'PHPUnit_Extensions_TestDecorator' => $vendorDir . '/phpunit/phpunit/src/Extensions/TestDecorator.php',
'PHPUnit_Extensions_TicketListener' => $vendorDir . '/phpunit/phpunit/src/Extensions/TicketListener.php',
'PHPUnit_Framework_Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php',
'PHPUnit_Framework_AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/AssertionFailedError.php',
'PHPUnit_Framework_BaseTestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/BaseTestListener.php',
'PHPUnit_Framework_CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/CodeCoverageException.php',
'PHPUnit_Framework_Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint.php',
'PHPUnit_Framework_Constraint_And' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/And.php',
'PHPUnit_Framework_Constraint_ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArrayHasKey.php',
'PHPUnit_Framework_Constraint_ArraySubset' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArraySubset.php',
'PHPUnit_Framework_Constraint_Attribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Attribute.php',
'PHPUnit_Framework_Constraint_Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php',
'PHPUnit_Framework_Constraint_ClassHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasAttribute.php',
'PHPUnit_Framework_Constraint_ClassHasStaticAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasStaticAttribute.php',
'PHPUnit_Framework_Constraint_Composite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Composite.php',
'PHPUnit_Framework_Constraint_Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Count.php',
'PHPUnit_Framework_Constraint_Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception.php',
'PHPUnit_Framework_Constraint_ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionCode.php',
'PHPUnit_Framework_Constraint_ExceptionMessage' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessage.php',
'PHPUnit_Framework_Constraint_ExceptionMessageRegExp' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessageRegExp.php',
'PHPUnit_Framework_Constraint_FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/FileExists.php',
'PHPUnit_Framework_Constraint_GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/GreaterThan.php',
'PHPUnit_Framework_Constraint_IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php',
'PHPUnit_Framework_Constraint_IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEmpty.php',
'PHPUnit_Framework_Constraint_IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEqual.php',
'PHPUnit_Framework_Constraint_IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsFalse.php',
'PHPUnit_Framework_Constraint_IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php',
'PHPUnit_Framework_Constraint_IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsInstanceOf.php',
'PHPUnit_Framework_Constraint_IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsJson.php',
'PHPUnit_Framework_Constraint_IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsNull.php',
'PHPUnit_Framework_Constraint_IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsTrue.php',
'PHPUnit_Framework_Constraint_IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsType.php',
'PHPUnit_Framework_Constraint_JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php',
'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches/ErrorMessageProvider.php',
'PHPUnit_Framework_Constraint_LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LessThan.php',
'PHPUnit_Framework_Constraint_Not' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Not.php',
'PHPUnit_Framework_Constraint_ObjectHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ObjectHasAttribute.php',
'PHPUnit_Framework_Constraint_Or' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Or.php',
'PHPUnit_Framework_Constraint_PCREMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/PCREMatch.php',
'PHPUnit_Framework_Constraint_SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/SameSize.php',
'PHPUnit_Framework_Constraint_StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringContains.php',
'PHPUnit_Framework_Constraint_StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringEndsWith.php',
'PHPUnit_Framework_Constraint_StringMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringMatches.php',
'PHPUnit_Framework_Constraint_StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringStartsWith.php',
'PHPUnit_Framework_Constraint_TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContains.php',
'PHPUnit_Framework_Constraint_TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsOnly.php',
'PHPUnit_Framework_Constraint_Xor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Xor.php',
'PHPUnit_Framework_Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Error.php',
'PHPUnit_Framework_Error_Deprecated' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Deprecated.php',
'PHPUnit_Framework_Error_Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Notice.php',
'PHPUnit_Framework_Error_Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Warning.php',
'PHPUnit_Framework_Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception.php',
'PHPUnit_Framework_ExceptionWrapper' => $vendorDir . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php',
'PHPUnit_Framework_ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/ExpectationFailedException.php',
'PHPUnit_Framework_IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTest.php',
'PHPUnit_Framework_IncompleteTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php',
'PHPUnit_Framework_IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestError.php',
'PHPUnit_Framework_InvalidCoversTargetError' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidCoversTargetError.php',
'PHPUnit_Framework_InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidCoversTargetException.php',
'PHPUnit_Framework_MockObject_BadMethodCallException' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/BadMethodCallException.php',
'PHPUnit_Framework_MockObject_Builder_Identity' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Identity.php',
'PHPUnit_Framework_MockObject_Builder_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/InvocationMocker.php',
'PHPUnit_Framework_MockObject_Builder_Match' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Match.php',
'PHPUnit_Framework_MockObject_Builder_MethodNameMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/MethodNameMatch.php',
'PHPUnit_Framework_MockObject_Builder_Namespace' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Namespace.php',
'PHPUnit_Framework_MockObject_Builder_ParametersMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/ParametersMatch.php',
'PHPUnit_Framework_MockObject_Builder_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Stub.php',
'PHPUnit_Framework_MockObject_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/Exception.php',
'PHPUnit_Framework_MockObject_Generator' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Generator.php',
'PHPUnit_Framework_MockObject_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation.php',
'PHPUnit_Framework_MockObject_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/InvocationMocker.php',
'PHPUnit_Framework_MockObject_Invocation_Object' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Object.php',
'PHPUnit_Framework_MockObject_Invocation_Static' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Static.php',
'PHPUnit_Framework_MockObject_Invokable' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invokable.php',
'PHPUnit_Framework_MockObject_Matcher' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher.php',
'PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyInvokedCount.php',
'PHPUnit_Framework_MockObject_Matcher_AnyParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyParameters.php',
'PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/ConsecutiveParameters.php',
'PHPUnit_Framework_MockObject_Matcher_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Invocation.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtIndex.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtMostCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedRecorder' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedRecorder.php',
'PHPUnit_Framework_MockObject_Matcher_MethodName' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/MethodName.php',
'PHPUnit_Framework_MockObject_Matcher_Parameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Parameters.php',
'PHPUnit_Framework_MockObject_Matcher_StatelessInvocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/StatelessInvocation.php',
'PHPUnit_Framework_MockObject_MockBuilder' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockBuilder.php',
'PHPUnit_Framework_MockObject_MockObject' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockObject.php',
'PHPUnit_Framework_MockObject_RuntimeException' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/RuntimeException.php',
'PHPUnit_Framework_MockObject_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub.php',
'PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ConsecutiveCalls.php',
'PHPUnit_Framework_MockObject_Stub_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Exception.php',
'PHPUnit_Framework_MockObject_Stub_MatcherCollection' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/MatcherCollection.php',
'PHPUnit_Framework_MockObject_Stub_Return' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Return.php',
'PHPUnit_Framework_MockObject_Stub_ReturnArgument' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnArgument.php',
'PHPUnit_Framework_MockObject_Stub_ReturnCallback' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnCallback.php',
'PHPUnit_Framework_MockObject_Stub_ReturnSelf' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnSelf.php',
'PHPUnit_Framework_MockObject_Stub_ReturnValueMap' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnValueMap.php',
'PHPUnit_Framework_MockObject_Verifiable' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Verifiable.php',
'PHPUnit_Framework_OutputError' => $vendorDir . '/phpunit/phpunit/src/Framework/OutputError.php',
'PHPUnit_Framework_RiskyTest' => $vendorDir . '/phpunit/phpunit/src/Framework/RiskyTest.php',
'PHPUnit_Framework_RiskyTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/RiskyTestError.php',
'PHPUnit_Framework_SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
'PHPUnit_Framework_SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTest.php',
'PHPUnit_Framework_SkippedTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestCase.php',
'PHPUnit_Framework_SkippedTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestError.php',
'PHPUnit_Framework_SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestSuiteError.php',
'PHPUnit_Framework_SyntheticError' => $vendorDir . '/phpunit/phpunit/src/Framework/SyntheticError.php',
'PHPUnit_Framework_Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php',
'PHPUnit_Framework_TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php',
'PHPUnit_Framework_TestFailure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestFailure.php',
'PHPUnit_Framework_TestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListener.php',
'PHPUnit_Framework_TestResult' => $vendorDir . '/phpunit/phpunit/src/Framework/TestResult.php',
'PHPUnit_Framework_TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php',
'PHPUnit_Framework_TestSuite_DataProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite/DataProvider.php',
'PHPUnit_Framework_UnintentionallyCoveredCodeError' => $vendorDir . '/phpunit/phpunit/src/Framework/UnintentionallyCoveredCodeError.php',
'PHPUnit_Framework_Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Warning.php',
'PHPUnit_Runner_BaseTestRunner' => $vendorDir . '/phpunit/phpunit/src/Runner/BaseTestRunner.php',
'PHPUnit_Runner_Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception.php',
'PHPUnit_Runner_Filter_Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php',
'PHPUnit_Runner_Filter_GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group.php',
'PHPUnit_Runner_Filter_Group_Exclude' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group/Exclude.php',
'PHPUnit_Runner_Filter_Group_Include' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group/Include.php',
'PHPUnit_Runner_Filter_Test' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Test.php',
'PHPUnit_Runner_StandardTestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php',
'PHPUnit_Runner_TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php',
'PHPUnit_Runner_Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php',
'PHPUnit_TextUI_Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command.php',
'PHPUnit_TextUI_ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/ResultPrinter.php',
'PHPUnit_TextUI_TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php',
'PHPUnit_Util_Blacklist' => $vendorDir . '/phpunit/phpunit/src/Util/Blacklist.php',
'PHPUnit_Util_Configuration' => $vendorDir . '/phpunit/phpunit/src/Util/Configuration.php',
'PHPUnit_Util_ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Util/ErrorHandler.php',
'PHPUnit_Util_Fileloader' => $vendorDir . '/phpunit/phpunit/src/Util/Fileloader.php',
'PHPUnit_Util_Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php',
'PHPUnit_Util_Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php',
'PHPUnit_Util_Getopt' => $vendorDir . '/phpunit/phpunit/src/Util/Getopt.php',
'PHPUnit_Util_GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php',
'PHPUnit_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/phpunit/src/Util/InvalidArgumentHelper.php',
'PHPUnit_Util_Log_JSON' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JSON.php',
'PHPUnit_Util_Log_JUnit' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JUnit.php',
'PHPUnit_Util_Log_TAP' => $vendorDir . '/phpunit/phpunit/src/Util/Log/TAP.php',
'PHPUnit_Util_PHP' => $vendorDir . '/phpunit/phpunit/src/Util/PHP.php',
'PHPUnit_Util_PHP_Default' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/Default.php',
'PHPUnit_Util_PHP_Windows' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/Windows.php',
'PHPUnit_Util_Printer' => $vendorDir . '/phpunit/phpunit/src/Util/Printer.php',
'PHPUnit_Util_Regex' => $vendorDir . '/phpunit/phpunit/src/Util/Regex.php',
'PHPUnit_Util_String' => $vendorDir . '/phpunit/phpunit/src/Util/String.php',
'PHPUnit_Util_Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php',
'PHPUnit_Util_TestDox_NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php',
'PHPUnit_Util_TestDox_ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php',
'PHPUnit_Util_TestDox_ResultPrinter_HTML' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/HTML.php',
'PHPUnit_Util_TestDox_ResultPrinter_Text' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/Text.php',
'PHPUnit_Util_TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Util/TestSuiteIterator.php',
'PHPUnit_Util_Type' => $vendorDir . '/phpunit/phpunit/src/Util/Type.php',
'PHPUnit_Util_XML' => $vendorDir . '/phpunit/phpunit/src/Util/XML.php',
'PHP_CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php',
'PHP_CodeCoverage_Driver' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver.php',
'PHP_CodeCoverage_Driver_HHVM' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/HHVM.php',
'PHP_CodeCoverage_Driver_PHPDBG' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/PHPDBG.php',
'PHP_CodeCoverage_Driver_Xdebug' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/Xdebug.php',
'PHP_CodeCoverage_Exception' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Exception.php',
'PHP_CodeCoverage_Exception_UnintentionallyCoveredCode' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Exception/UnintentionallyCoveredCode.php',
'PHP_CodeCoverage_Filter' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Filter.php',
'PHP_CodeCoverage_Report_Clover' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Clover.php',
'PHP_CodeCoverage_Report_Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Crap4j.php',
'PHP_CodeCoverage_Report_Factory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Factory.php',
'PHP_CodeCoverage_Report_HTML' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML.php',
'PHP_CodeCoverage_Report_HTML_Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer.php',
'PHP_CodeCoverage_Report_HTML_Renderer_Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Dashboard.php',
'PHP_CodeCoverage_Report_HTML_Renderer_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Directory.php',
'PHP_CodeCoverage_Report_HTML_Renderer_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/File.php',
'PHP_CodeCoverage_Report_Node' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node.php',
'PHP_CodeCoverage_Report_Node_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Directory.php',
'PHP_CodeCoverage_Report_Node_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/File.php',
'PHP_CodeCoverage_Report_Node_Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Iterator.php',
'PHP_CodeCoverage_Report_PHP' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/PHP.php',
'PHP_CodeCoverage_Report_Text' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Text.php',
'PHP_CodeCoverage_Report_XML' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML.php',
'PHP_CodeCoverage_Report_XML_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Directory.php',
'PHP_CodeCoverage_Report_XML_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File.php',
'PHP_CodeCoverage_Report_XML_File_Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Coverage.php',
'PHP_CodeCoverage_Report_XML_File_Method' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Method.php',
'PHP_CodeCoverage_Report_XML_File_Report' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Report.php',
'PHP_CodeCoverage_Report_XML_File_Unit' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Unit.php',
'PHP_CodeCoverage_Report_XML_Node' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Node.php',
'PHP_CodeCoverage_Report_XML_Project' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Project.php',
'PHP_CodeCoverage_Report_XML_Tests' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Tests.php',
'PHP_CodeCoverage_Report_XML_Totals' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Totals.php',
'PHP_CodeCoverage_Util' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Util.php',
'PHP_CodeCoverage_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Util/InvalidArgumentHelper.php',
'PHP_Evaluator' => $vendorDir . '/dompdf/dompdf/include/php_evaluator.cls.php',
'PHP_Timer' => $vendorDir . '/phpunit/php-timer/src/Timer.php',
'PHP_Token' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_TokenWithScope' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_TokenWithScopeAndVisibility' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ABSTRACT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AMPERSAND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AND_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ARRAY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ARRAY_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BACKTICK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BAD_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOLEAN_AND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOLEAN_OR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOL_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BREAK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CALLABLE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CARET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CASE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CATCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS_NAME_CONSTANT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLONE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_TAG' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COALESCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMMA' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMPILER_HALT_OFFSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONCAT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONSTANT_ENCAPSED_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONTINUE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CURLY_OPEN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DEC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DEFAULT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIV' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIV_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOC_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOLLAR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOLLAR_OPEN_CURLY_BRACES' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_QUOTES' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELLIPSIS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELSE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELSEIF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EMPTY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENCAPSED_AND_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDDECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDFOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDFOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDIF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDSWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDWHILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_END_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENUM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EVAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXCLAMATION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXTENDS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FINAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FINALLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FUNCTION' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FUNC_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GLOBAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GOTO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_HALT_COMPILER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IMPLEMENTS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INCLUDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INCLUDE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INLINE_HTML' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INSTANCEOF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INSTEADOF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INTERFACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ISSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_GREATER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_NOT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_NOT_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_SMALLER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_Includes' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_JOIN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_CP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_OP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LINE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LIST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_AND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_OR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_XOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_METHOD_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MINUS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MINUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MOD_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MULT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MUL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NAMESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NEW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NS_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NS_SEPARATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NUM_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OBJECT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OBJECT_OPERATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ONUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_TAG' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_TAG_WITH_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PAAMAYIM_NEKUDOTAYIM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PERCENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PIPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PLUS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PLUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_POW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_POW_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PRINT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PRIVATE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PROTECTED' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PUBLIC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_QUESTION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_REQUIRE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_REQUIRE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_RETURN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SEMICOLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SHAPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SPACESHIP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_START_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STATIC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING_VARNAME' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_Stream' => $vendorDir . '/phpunit/php-token-stream/src/Token/Stream.php',
'PHP_Token_Stream_CachingFactory' => $vendorDir . '/phpunit/php-token-stream/src/Token/Stream/CachingFactory.php',
'PHP_Token_THROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TILDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRAIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRAIT_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPELIST_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPELIST_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_UNSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_UNSET_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_USE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_VAR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_VARIABLE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_WHILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_ATTRIBUTE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CATEGORY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CATEGORY_LABEL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CHILDREN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_LABEL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_REQUIRED' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TAG_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TAG_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TEXT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XOR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_YIELD' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_YIELD_FROM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'Page_Cache' => $vendorDir . '/dompdf/dompdf/include/page_cache.cls.php',
'Page_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/page_frame_decorator.cls.php',
'Page_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/page_frame_reflower.cls.php',
'Positioner' => $vendorDir . '/dompdf/dompdf/include/positioner.cls.php',
'Renderer' => $vendorDir . '/dompdf/dompdf/include/renderer.cls.php',
'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php',
'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php',
'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php',
'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php',
'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php',
'SebastianBergmann\\Comparator\\DoubleComparator' => $vendorDir . '/sebastian/comparator/src/DoubleComparator.php',
'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php',
'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php',
'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php',
'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php',
'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php',
'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php',
'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php',
'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php',
'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php',
'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php',
'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php',
'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php',
'SebastianBergmann\\Diff\\LCS\\LongestCommonSubsequence' => $vendorDir . '/sebastian/diff/src/LCS/LongestCommonSubsequence.php',
'SebastianBergmann\\Diff\\LCS\\MemoryEfficientImplementation' => $vendorDir . '/sebastian/diff/src/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php',
'SebastianBergmann\\Diff\\LCS\\TimeEfficientImplementation' => $vendorDir . '/sebastian/diff/src/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php',
'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php',
'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php',
'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php',
'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php',
'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php',
'SebastianBergmann\\GlobalState\\Blacklist' => $vendorDir . '/sebastian/global-state/src/Blacklist.php',
'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/Exception.php',
'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php',
'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/RuntimeException.php',
'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php',
'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php',
'SebastianBergmann\\RecursionContext\\Exception' => $vendorDir . '/sebastian/recursion-context/src/Exception.php',
'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => $vendorDir . '/sebastian/recursion-context/src/InvalidArgumentException.php',
'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php',
'SessionHandlerInterface' => $vendorDir . '/symfony/http-foundation/Symfony/Component/HttpFoundation/Resources/stubs/SessionHandlerInterface.php',
'Style' => $vendorDir . '/dompdf/dompdf/include/style.cls.php',
'Stylesheet' => $vendorDir . '/dompdf/dompdf/include/stylesheet.cls.php',
'TCPDF_Adapter' => $vendorDir . '/dompdf/dompdf/include/tcpdf_adapter.cls.php',
'Table_Cell_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/table_cell_frame_decorator.cls.php',
'Table_Cell_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/table_cell_frame_reflower.cls.php',
'Table_Cell_Positioner' => $vendorDir . '/dompdf/dompdf/include/table_cell_positioner.cls.php',
'Table_Cell_Renderer' => $vendorDir . '/dompdf/dompdf/include/table_cell_renderer.cls.php',
'Table_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/table_frame_decorator.cls.php',
'Table_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/table_frame_reflower.cls.php',
'Table_Row_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/table_row_frame_decorator.cls.php',
'Table_Row_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/table_row_frame_reflower.cls.php',
'Table_Row_Group_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/table_row_group_frame_decorator.cls.php',
'Table_Row_Group_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/table_row_group_frame_reflower.cls.php',
'Table_Row_Group_Renderer' => $vendorDir . '/dompdf/dompdf/include/table_row_group_renderer.cls.php',
'Table_Row_Positioner' => $vendorDir . '/dompdf/dompdf/include/table_row_positioner.cls.php',
'TestCase' => $baseDir . '/tests/TestCase.php',
'Text_Frame_Decorator' => $vendorDir . '/dompdf/dompdf/include/text_frame_decorator.cls.php',
'Text_Frame_Reflower' => $vendorDir . '/dompdf/dompdf/include/text_frame_reflower.cls.php',
'Text_Renderer' => $vendorDir . '/dompdf/dompdf/include/text_renderer.cls.php',
'Text_Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php',
'Whoops\\Module' => $vendorDir . '/filp/whoops/src/deprecated/Zend/Module.php',
'Whoops\\Provider\\Zend\\ExceptionStrategy' => $vendorDir . '/filp/whoops/src/deprecated/Zend/ExceptionStrategy.php',
'Whoops\\Provider\\Zend\\RouteNotFoundStrategy' => $vendorDir . '/filp/whoops/src/deprecated/Zend/RouteNotFoundStrategy.php',
);

View File

@@ -0,0 +1,19 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
$vendorDir . '/nikic/php-parser/lib/bootstrap.php',
$vendorDir . '/symfony/var-dumper/Symfony/Component/VarDumper/Resources/functions/dump.php',
$vendorDir . '/ircmaxell/password-compat/lib/password.php',
$vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
$vendorDir . '/psy/psysh/src/Psy/functions.php',
$vendorDir . '/danielstjules/stringy/src/Create.php',
$vendorDir . '/illuminate/html/helpers.php',
$vendorDir . '/laravel/framework/src/Illuminate/Foundation/helpers.php',
$vendorDir . '/laravel/framework/src/Illuminate/Support/helpers.php',
$vendorDir . '/propaganistas/laravel-phone/src/helpers.php',
);

View File

@@ -0,0 +1,39 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'thomaswelton\\GravatarLib\\' => array($vendorDir . '/thomaswelton/gravatarlib'),
'phpDocumentor' => array($vendorDir . '/phpdocumentor/reflection-docblock/src'),
'libphonenumber' => array($vendorDir . '/giggsey/libphonenumber-for-php/src'),
'Whoops' => array($vendorDir . '/filp/whoops/src'),
'Thomaswelton\\LaravelGravatar' => array($vendorDir . '/thomaswelton/laravel-gravatar/src'),
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\Security\\Core\\' => array($vendorDir . '/symfony/security-core'),
'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
'Psy\\' => array($vendorDir . '/psy/psysh/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'),
'PhpSpec' => array($vendorDir . '/phpspec/phpspec/src'),
'PhpImap' => array($vendorDir . '/php-imap/php-imap/src'),
'JakubOnderka\\PhpConsoleHighlighter' => array($vendorDir . '/jakub-onderka/php-console-highlighter/src'),
'JakubOnderka\\PhpConsoleColor' => array($vendorDir . '/jakub-onderka/php-console-color/src'),
'ForceUTF8\\' => array($vendorDir . '/neitanod/forceutf8/src'),
'Dotenv' => array($vendorDir . '/vlucas/phpdotenv/src'),
'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib'),
'Diff' => array($vendorDir . '/phpspec/php-diff/lib'),
'Cron' => array($vendorDir . '/mtdowling/cron-expression/src'),
'Carbon' => array($vendorDir . '/nesbot/carbon/src'),
'Bugsnag_' => array($vendorDir . '/bugsnag/bugsnag/src'),
'Bugsnag\\BugsnagLaravel\\' => array($vendorDir . '/bugsnag/bugsnag-laravel/src'),
);

View File

@@ -0,0 +1,25 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'XdgBaseDir\\' => array($vendorDir . '/dnoegel/php-xdg-base-dir/src'),
'Vsmoraes\\Pdf\\' => array($vendorDir . '/vsmoraes/laravel-pdf/src'),
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
'SuperClosure\\' => array($vendorDir . '/jeremeamia/SuperClosure/src'),
'Stringy\\' => array($vendorDir . '/danielstjules/stringy/src'),
'Propaganistas\\LaravelPhone\\' => array($vendorDir . '/propaganistas/laravel-phone/src'),
'Nicolaslopezj\\Searchable\\' => array($vendorDir . '/nicolaslopezj/searchable/src'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
'Illuminate\\Html\\' => array($vendorDir . '/illuminate/html'),
'Illuminate\\' => array($vendorDir . '/laravel/framework/src/Illuminate'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
'ClassPreloader\\' => array($vendorDir . '/classpreloader/classpreloader/src'),
'App\\' => array($baseDir . '/app'),
);

View File

@@ -0,0 +1,55 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit5a4036999a1163a0cf7d39bc88c9c382
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit5a4036999a1163a0cf7d39bc88c9c382', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit5a4036999a1163a0cf7d39bc88c9c382', 'loadClassLoader'));
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
$loader->register(true);
$includeFiles = require __DIR__ . '/autoload_files.php';
foreach ($includeFiles as $file) {
composerRequire5a4036999a1163a0cf7d39bc88c9c382($file);
}
return $loader;
}
}
function composerRequire5a4036999a1163a0cf7d39bc88c9c382($file)
{
require $file;
}

View File

@@ -0,0 +1,11 @@
<?php
// include_paths.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
$vendorDir . '/phpunit/php-text-template',
$vendorDir . '/phpunit/php-timer',
);

3591
code/code/vendor/composer/installed.json vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
vendor/
composer.lock
.DS_Store

View File

@@ -0,0 +1,7 @@
language: php
php:
- 5.6
- 5.5
- 5.4
- 5.3
- hhvm

View File

@@ -0,0 +1,119 @@
### 1.10.0 (2015-07-22)
* Added trimLeft, trimRight
* Added support for unicode whitespace to trim
* Added delimit
* Added indexOf and indexOfLast
* Added htmlEncode and htmlDecode
* Added "Ç" in toAscii()
### 1.9.0 (2015-02-09)
* Added hasUpperCase and hasLowerCase
* Added $removeUnsupported parameter to toAscii()
* Improved toAscii support with additional Unicode spaces, Vietnamese chars,
and numerous other characters
* Separated the charsArray from toAscii as a protected method that may be
extended by inheriting classes
* Chars array is cached for better performance
### 1.8.1 (2015-01-08)
* Optimized chars()
* Added "ä Ä Ö Ü"" in toAscii()
* Added support for Unicode spaces in toAscii()
* Replaced instances of self::create() with static::create()
* Added missing test cases for safeTruncate() and longestCommonSuffix()
* Updated Stringy\create() to avoid collision when it already exists
### 1.8.0 (2015-01-03)
* Listed ext-mbstring in composer.json
* Added Stringy\create function for PHP 5.6
### 1.7.0 (2014-10-14)
* Added containsAll and containsAny
* Light cleanup
### 1.6.0 (2014-09-14)
* Added toTitleCase
### 1.5.2 (2014-07-09)
* Announced support for HHVM
### 1.5.1 (2014-04-19)
* Fixed toAscii() failing to remove remaining non-ascii characters
* Updated slugify() to treat dash and underscore as delimiters by default
* Updated slugify() to remove leading and trailing delimiter, if present
### 1.5.0 (2014-03-19)
* Made both str and encoding protected, giving property access to subclasses
* Added getEncoding()
* Fixed isJSON() giving false negatives
* Cleaned up and simplified: replace(), collapseWhitespace(), underscored(),
dasherize(), pad(), padLeft(), padRight() and padBoth()
* Fixed handling consecutive invalid chars in slugify()
* Removed conflicting hard sign transliteration in toAscii()
### 1.4.0 (2014-02-12)
* Implemented the IteratorAggregate interface, added chars()
* Renamed count() to countSubstr()
* Updated count() to implement Countable interface
* Implemented the ArrayAccess interface with positive and negative indices
* Switched from PSR-0 to PSR-4 autoloading
### 1.3.0 (2013-12-16)
* Additional Bulgarian support for toAscii
* str property made private
* Constructor casts first argument to string
* Constructor throws an InvalidArgumentException when given an array
* Constructor throws an InvalidArgumentException when given an object without
a __toString method
### 1.2.2 (2013-12-04)
* Updated create function to use late static binding
* Added optional $replacement param to slugify
### 1.2.1 (2013-10-11)
* Cleaned up tests
* Added homepage to composer.json
### 1.2.0 (2013-09-15)
* Fixed pad's use of InvalidArgumentException
* Fixed replace(). It now correctly treats regex special chars as normal chars
* Added additional Cyrillic letters to toAscii
* Added $caseSensitive to contains() and count()
* Added toLowerCase()
* Added toUpperCase()
* Added regexReplace()
### 1.1.0 (2013-08-31)
* Fix for collapseWhitespace()
* Added isHexadecimal()
* Added constructor to Stringy\Stringy
* Added isSerialized()
* Added isJson()
### 1.0.0 (2013-08-1)
* 1.0.0 release
* Added test coverage for Stringy::create and method chaining
* Added tests for returned type
* Fixed StaticStringy::replace(). It was returning a Stringy object instead of string
* Renamed standardize() to the more appropriate toAscii()
* Cleaned up comments and README
### 1.0.0-rc.1 (2013-07-28)
* Release candidate

View File

@@ -0,0 +1,19 @@
Copyright (C) 2013 Daniel St. Jules
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.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
{
"name": "danielstjules/stringy",
"description": "A string manipulation library with multibyte support",
"keywords": [
"multibyte", "string", "manipulation", "utility", "methods", "utf-8",
"helpers", "utils", "utf"
],
"homepage": "https://github.com/danielstjules/Stringy",
"license": "MIT",
"authors": [
{
"name": "Daniel St. Jules",
"email": "danielst.jules@gmail.com",
"homepage": "http://www.danielstjules.com"
}
],
"require": {
"php": ">=5.3.0",
"ext-mbstring": "*"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"support": {
"issues": "https://github.com/danielstjules/Stringy/issues",
"source": "https://github.com/danielstjules/Stringy"
},
"autoload": {
"psr-4": { "Stringy\\": "src/" },
"files": ["src/Create.php"]
},
"autoload-dev": {
"classmap": [ "tests" ]
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Stringy">
<file>tests/CommonTest.php</file>
<file>tests/StringyTest.php</file>
<file>tests/StaticStringyTest.php</file>
<file phpVersion="5.6.0">tests/CreateTest.php</file>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,19 @@
<?php
namespace Stringy;
if (!function_exists('Stringy\create')) {
/**
* Creates a Stringy object and returns it on success.
*
* @param mixed $str Value to modify, after being cast to string
* @param string $encoding The character encoding
* @return Stringy A Stringy object
* @throws \InvalidArgumentException if an array or object without a
* __toString method is passed as the first argument
*/
function create($str, $encoding = null)
{
return new Stringy($str, $encoding);
}
}

View File

@@ -0,0 +1,979 @@
<?php
namespace Stringy;
class StaticStringy
{
/**
* Returns an array consisting of the characters in the string.
*
* @param string $str String for which to return the chars
* @param string $encoding The character encoding
* @return array An array of string chars
*/
public static function chars($str, $encoding = null)
{
return Stringy::create($str, $encoding)->chars();
}
/**
* Converts the first character of the supplied string to upper case.
*
* @param string $str String to modify
* @param string $encoding The character encoding
* @return string String with the first character being upper case
*/
public static function upperCaseFirst($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->upperCaseFirst();
}
/**
* Converts the first character of the supplied string to lower case.
*
* @param string $str String to modify
* @param string $encoding The character encoding
* @return string String with the first character being lower case
*/
public static function lowerCaseFirst($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->lowerCaseFirst();
}
/**
* Returns a camelCase version of the string. Trims surrounding spaces,
* capitalizes letters following digits, spaces, dashes and underscores,
* and removes spaces, dashes, as well as underscores.
*
* @param string $str String to convert to camelCase
* @param string $encoding The character encoding
* @return string String in camelCase
*/
public static function camelize($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->camelize();
}
/**
* Returns an UpperCamelCase version of the supplied string. It trims
* surrounding spaces, capitalizes letters following digits, spaces, dashes
* and underscores, and removes spaces, dashes, underscores.
*
* @param string $str String to convert to UpperCamelCase
* @param string $encoding The character encoding
* @return string String in UpperCamelCase
*/
public static function upperCamelize($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->upperCamelize();
}
/**
* Returns a lowercase and trimmed string separated by dashes. Dashes are
* inserted before uppercase characters (with the exception of the first
* character of the string), and in place of spaces as well as underscores.
*
* @param string $str String to convert
* @param string $encoding The character encoding
* @return string Dasherized string
*/
public static function dasherize($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->dasherize();
}
/**
* Returns a lowercase and trimmed string separated by underscores.
* Underscores are inserted before uppercase characters (with the exception
* of the first character of the string), and in place of spaces as well as
* dashes.
*
* @param string $str String to convert
* @param string $encoding The character encoding
* @return string Underscored string
*/
public static function underscored($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->underscored();
}
/**
* Returns a lowercase and trimmed string separated by the given delimiter.
* Delimiters are inserted before uppercase characters (with the exception
* of the first character of the string), and in place of spaces, dashes,
* and underscores. Alpha delimiters are not converted to lowercase.
*
* @param string $str String to convert
* @param string $delimiter Sequence used to separate parts of the string
* @param string $encoding The character encoding
* @return string String with delimiter
*/
public static function delimit($str, $delimiter, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->delimit($delimiter);
}
/**
* Returns a case swapped version of the string.
*
* @param string $str String to swap case
* @param string $encoding The character encoding
* @return string String with each character's case swapped
*/
public static function swapCase($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->swapCase();
}
/**
* Returns a trimmed string with the first letter of each word capitalized.
* Ignores the case of other letters, preserving any acronyms. Also accepts
* an array, $ignore, allowing you to list words not to be capitalized.
*
* @param string $str String to titleize
* @param string $encoding The character encoding
* @param array $ignore An array of words not to capitalize
* @return string Titleized string
*/
public static function titleize($str, $ignore = null, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->titleize($ignore);
}
/**
* Capitalizes the first word of the string, replaces underscores with
* spaces, and strips '_id'.
*
* @param string $str String to humanize
* @param string $encoding The character encoding
* @return string A humanized string
*/
public static function humanize($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->humanize();
}
/**
* Returns a string with smart quotes, ellipsis characters, and dashes from
* Windows-1252 (commonly used in Word documents) replaced by their ASCII
* equivalents.
*
* @param string $str String to remove special chars
* @return string String with those characters removed
*/
public static function tidy($str)
{
return (string) Stringy::create($str)->tidy();
}
/**
* Trims the string and replaces consecutive whitespace characters with a
* single space. This includes tabs and newline characters, as well as
* multibyte whitespace such as the thin space and ideographic space.
*
* @param string $str The string to cleanup whitespace
* @param string $encoding The character encoding
* @return string The trimmed string with condensed whitespace
*/
public static function collapseWhitespace($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->collapseWhitespace();
}
/**
* Returns an ASCII version of the string. A set of non-ASCII characters are
* replaced with their closest ASCII counterparts, and the rest are removed
* unless instructed otherwise.
*
* @param string $str A string with non-ASCII characters
* @param bool $removeUnsupported Whether or not to remove the
* unsupported characters
* @return string A string containing only ASCII characters
*/
public static function toAscii($str, $removeUnsupported = true)
{
return (string) Stringy::create($str)->toAscii($removeUnsupported);
}
/**
* Pads the string to a given length with $padStr. If length is less than
* or equal to the length of the string, no padding takes places. The
* default string used for padding is a space, and the default type (one of
* 'left', 'right', 'both') is 'right'. Throws an InvalidArgumentException
* if $padType isn't one of those 3 values.
*
* @param string $str String to pad
* @param int $length Desired string length after padding
* @param string $padStr String used to pad, defaults to space
* @param string $padType One of 'left', 'right', 'both'
* @param string $encoding The character encoding
* @return string The padded string
* @throws \InvalidArgumentException If $padType isn't one of 'right',
* 'left' or 'both'
*/
public static function pad($str, $length, $padStr = ' ', $padType = 'right',
$encoding = null)
{
return (string) Stringy::create($str, $encoding)
->pad($length, $padStr, $padType);
}
/**
* Returns a new string of a given length such that the beginning of the
* string is padded. Alias for pad() with a $padType of 'left'.
*
* @param string $str String to pad
* @param int $length Desired string length after padding
* @param string $padStr String used to pad, defaults to space
* @param string $encoding The character encoding
* @return string The padded string
*/
public static function padLeft($str, $length, $padStr = ' ', $encoding = null)
{
return (string) Stringy::create($str, $encoding)
->padLeft($length, $padStr);
}
/**
* Returns a new string of a given length such that the end of the string
* is padded. Alias for pad() with a $padType of 'right'.
*
* @param string $str String to pad
* @param int $length Desired string length after padding
* @param string $padStr String used to pad, defaults to space
* @param string $encoding The character encoding
* @return string The padded string
*/
public static function padRight($str, $length, $padStr = ' ', $encoding = null)
{
return (string) Stringy::create($str, $encoding)
->padRight($length, $padStr);
}
/**
* Returns a new string of a given length such that both sides of the
* string are padded. Alias for pad() with a $padType of 'both'.
*
* @param string $str String to pad
* @param int $length Desired string length after padding
* @param string $padStr String used to pad, defaults to space
* @param string $encoding The character encoding
* @return string The padded string
*/
public static function padBoth($str, $length, $padStr = ' ', $encoding = null)
{
return (string) Stringy::create($str, $encoding)
->padBoth($length, $padStr);
}
/**
* Returns true if the string begins with $substring, false otherwise. By
* default, the comparison is case-sensitive, but can be made insensitive
* by setting $caseSensitive to false.
*
* @param string $str String to check the start of
* @param string $substring The substring to look for
* @param bool $caseSensitive Whether or not to enforce case-sensitivity
* @param string $encoding The character encoding
* @return bool Whether or not $str starts with $substring
*/
public static function startsWith($str, $substring, $caseSensitive = true,
$encoding = null)
{
return Stringy::create($str, $encoding)
->startsWith($substring, $caseSensitive);
}
/**
* Returns true if the string ends with $substring, false otherwise. By
* default, the comparison is case-sensitive, but can be made insensitive
* by setting $caseSensitive to false.
*
* @param string $str String to check the end of
* @param string $substring The substring to look for
* @param bool $caseSensitive Whether or not to enforce case-sensitivity
* @param string $encoding The character encoding
* @return bool Whether or not $str ends with $substring
*/
public static function endsWith($str, $substring, $caseSensitive = true,
$encoding = null)
{
return Stringy::create($str, $encoding)
->endsWith($substring, $caseSensitive);
}
/**
* Converts each tab in the string to some number of spaces, as defined by
* $tabLength. By default, each tab is converted to 4 consecutive spaces.
*
* @param string $str String to convert tabs to spaces
* @param int $tabLength Number of spaces to replace each tab with
* @return string String with tabs switched to spaces
*/
public static function toSpaces($str, $tabLength = 4)
{
return (string) Stringy::create($str)->toSpaces($tabLength);
}
/**
* Converts each occurrence of some consecutive number of spaces, as
* defined by $tabLength, to a tab. By default, each 4 consecutive spaces
* are converted to a tab.
*
* @param string $str String to convert spaces to tabs
* @param int $tabLength Number of spaces to replace with a tab
* @return string String with spaces switched to tabs
*/
public static function toTabs($str, $tabLength = 4)
{
return (string) Stringy::create($str)->toTabs($tabLength);
}
/**
* Converts all characters in the string to lowercase. An alias for PHP's
* mb_strtolower().
*
* @param string $str String to convert case
* @param string $encoding The character encoding
* @return string The lowercase string
*/
public static function toLowerCase($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->toLowerCase();
}
/**
* Converts the first character of each word in the string to uppercase.
*
* @param string $str String to convert case
* @param string $encoding The character encoding
* @return string The title-cased string
*/
public static function toTitleCase($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->toTitleCase();
}
/**
* Converts all characters in the string to uppercase. An alias for PHP's
* mb_strtoupper().
*
* @param string $str String to convert case
* @param string $encoding The character encoding
* @return string The uppercase string
*/
public static function toUpperCase($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->toUpperCase();
}
/**
* Converts the string into an URL slug. This includes replacing non-ASCII
* characters with their closest ASCII equivalents, removing remaining
* non-ASCII and non-alphanumeric characters, and replacing whitespace with
* $replacement. The replacement defaults to a single dash, and the string
* is also converted to lowercase.
*
* @param string $str Text to transform into an URL slug
* @param string $replacement The string used to replace whitespace
* @return string The corresponding URL slug
*/
public static function slugify($str, $replacement = '-')
{
return (string) Stringy::create($str)->slugify($replacement);
}
/**
* Returns true if the string contains $needle, false otherwise. By default,
* the comparison is case-sensitive, but can be made insensitive by setting
* $caseSensitive to false.
*
* @param string $haystack String being checked
* @param string $needle Substring to look for
* @param bool $caseSensitive Whether or not to enforce case-sensitivity
* @param string $encoding The character encoding
* @return bool Whether or not $haystack contains $needle
*/
public static function contains($haystack, $needle, $caseSensitive = true,
$encoding = null)
{
return Stringy::create($haystack, $encoding)
->contains($needle, $caseSensitive);
}
/**
* Returns true if the string contains any $needles, false otherwise. By
* default, the comparison is case-sensitive, but can be made insensitive
* by setting $caseSensitive to false.
*
* @param string $haystack String being checked
* @param array $needles Substrings to look for
* @param bool $caseSensitive Whether or not to enforce case-sensitivity
* @param string $encoding The character encoding
* @return bool Whether or not $haystack contains any $needles
*/
public static function containsAny($haystack, $needles,
$caseSensitive = true, $encoding = null)
{
return Stringy::create($haystack, $encoding)
->containsAny($needles, $caseSensitive);
}
/**
* Returns true if the string contains all $needles, false otherwise. By
* default, the comparison is case-sensitive, but can be made insensitive
* by setting $caseSensitive to false.
*
* @param string $haystack String being checked
* @param array $needles Substrings to look for
* @param bool $caseSensitive Whether or not to enforce case-sensitivity
* @param string $encoding The character encoding
* @return bool Whether or not $haystack contains all $needles
*/
public static function containsAll($haystack, $needles,
$caseSensitive = true, $encoding = null)
{
return Stringy::create($haystack, $encoding)
->containsAll($needles, $caseSensitive);
}
/**
* Returns the index of the first occurrence of $needle in the string,
* and false if not found. Accepts an optional offset from which to begin
* the search.
*
* @param string $haystack String to search
* @param string $needle Substring to look for
* @param int $offset Offset from which to search
* @return int|bool The occurrence's index if found, otherwise false
*/
public static function indexOf($haystack, $needle, $offset = 0,
$encoding = null)
{
return Stringy::create($haystack, $encoding)
->indexOf($needle, $offset);
}
/**
* Returns the index of the last occurrence of $needle in the string,
* and false if not found. Accepts an optional offset from which to begin
* the search.
*
* @param string $haystack String to search
* @param string $needle Substring to look for
* @param int $offset Offset from which to search
* @return int|bool The last occurrence's index if found, otherwise false
*/
public static function indexOfLast($haystack, $needle, $offset = 0,
$encoding = null)
{
return Stringy::create($haystack, $encoding)
->indexOfLast($needle, $offset);
}
/**
* Surrounds a string with the given substring.
*
* @param string $str The string to surround
* @param string $substring The substring to add to both sides
* @return string The string with the substring prepended and appended
*/
public static function surround($str, $substring)
{
return (string) Stringy::create($str)->surround($substring);
}
/**
* Inserts $substring into the string at the $index provided.
*
* @param string $str String to insert into
* @param string $substring String to be inserted
* @param int $index The index at which to insert the substring
* @param string $encoding The character encoding
* @return string The resulting string after the insertion
*/
public static function insert($str, $substring, $index, $encoding = null)
{
return (string) Stringy::create($str, $encoding)
->insert($substring, $index);
}
/**
* Truncates the string to a given length. If $substring is provided, and
* truncating occurs, the string is further truncated so that the substring
* may be appended without exceeding the desired length.
*
* @param string $str String to truncate
* @param int $length Desired length of the truncated string
* @param string $substring The substring to append if it can fit
* @param string $encoding The character encoding
* @return string The resulting string after truncating
*/
public static function truncate($str, $length, $substring = '',
$encoding = null)
{
return (string) Stringy::create($str, $encoding)
->truncate($length, $substring);
}
/**
* Truncates the string to a given length, while ensuring that it does not
* split words. If $substring is provided, and truncating occurs, the
* string is further truncated so that the substring may be appended without
* exceeding the desired length.
*
* @param string $str String to truncate
* @param int $length Desired length of the truncated string
* @param string $substring The substring to append if it can fit
* @param string $encoding The character encoding
* @return string The resulting string after truncating
*/
public static function safeTruncate($str, $length, $substring = '',
$encoding = null)
{
return (string) Stringy::create($str, $encoding)
->safeTruncate($length, $substring);
}
/**
* Returns a reversed string. A multibyte version of strrev().
*
* @param string $str String to reverse
* @param string $encoding The character encoding
* @return string The reversed string
*/
public static function reverse($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->reverse();
}
/**
* A multibyte str_shuffle() function. It returns a string with its
* characters in random order.
*
* @param string $str String to shuffle
* @param string $encoding The character encoding
* @return string The shuffled string
*/
public static function shuffle($str, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->shuffle();
}
/**
* Returns a string with whitespace removed from the start and end of the
* string. Supports the removal of unicode whitespace. Accepts an optional
* string of characters to strip instead of the defaults.
*
* @param string $str String to trim
* @param string $chars Optional string of characters to strip
* @param string $encoding The character encoding
* @return string Trimmed $str
*/
public static function trim($str, $chars = null, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->trim($chars);
}
/**
* Returns a string with whitespace removed from the start of the string.
* Supports the removal of unicode whitespace. Accepts an optional
* string of characters to strip instead of the defaults.
*
* @param string $str String to trim
* @param string $chars Optional string of characters to strip
* @param string $encoding The character encoding
* @return string Trimmed $str
*/
public static function trimLeft($str, $chars = null, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->trimLeft($chars);
}
/**
* Returns a string with whitespace removed from the end of the string.
* Supports the removal of unicode whitespace. Accepts an optional
* string of characters to strip instead of the defaults.
*
* @param string $str String to trim
* @param string $chars Optional string of characters to strip
* @param string $encoding The character encoding
* @return string Trimmed $str
*/
public static function trimRight($str, $chars = null, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->trimRight($chars);
}
/**
* Returns the longest common prefix between the string and $otherStr.
*
* @param string $str First string for comparison
* @param string $otherStr Second string for comparison
* @param string $encoding The character encoding
* @return string The longest common prefix
*/
public static function longestCommonPrefix($str, $otherStr, $encoding = null)
{
return (string) Stringy::create($str, $encoding)
->longestCommonPrefix($otherStr);
}
/**
* Returns the longest common suffix between the string and $otherStr.
*
* @param string $str First string for comparison
* @param string $otherStr Second string for comparison
* @param string $encoding The character encoding
* @return string The longest common suffix
*/
public static function longestCommonSuffix($str, $otherStr, $encoding = null)
{
return (string) Stringy::create($str, $encoding)
->longestCommonSuffix($otherStr);
}
/**
* Returns the longest common substring between the string and $otherStr.
* In the case of ties, it returns that which occurs first.
*
* @param string $str First string for comparison
* @param string $otherStr Second string for comparison
* @param string $encoding The character encoding
* @return string The longest common substring
*/
public static function longestCommonSubstring($str, $otherStr,
$encoding = null)
{
return (string) Stringy::create($str, $encoding)
->longestCommonSubstring($otherStr);
}
/**
* Returns the length of the string. An alias for PHP's mb_strlen() function.
*
* @param string $str The string to get the length of
* @param string $encoding The character encoding
* @return int The number of characters in $str given the encoding
*/
public static function length($str, $encoding = null)
{
return Stringy::create($str, $encoding)->length();
}
/**
* Returns the substring beginning at $start with the specified $length.
* It differs from the mb_substr() function in that providing a $length of
* null will return the rest of the string, rather than an empty string.
*
* @param string $str The string to get the length of
* @param int $start Position of the first character to use
* @param int $length Maximum number of characters used
* @param string $encoding The character encoding
* @return string The substring of $str
*/
public static function substr($str, $start, $length = null, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->substr($start, $length);
}
/**
* Returns the character at $index, with indexes starting at 0.
*
* @param string $str The string from which to get the char
* @param int $index Position of the character
* @param string $encoding The character encoding
* @return string The character at $index
*/
public static function at($str, $index, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->at($index);
}
/**
* Returns the first $n characters of the string.
*
* @param string $str The string from which to get the substring
* @param int $n Number of chars to retrieve from the start
* @param string $encoding The character encoding
* @return string The first $n characters
*/
public static function first($str, $n, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->first($n);
}
/**
* Returns the last $n characters of the string.
*
* @param string $str The string from which to get the substring
* @param int $n Number of chars to retrieve from the end
* @param string $encoding The character encoding
* @return string The last $n characters
*/
public static function last($str, $n, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->last($n);
}
/**
* Ensures that the string begins with $substring. If it doesn't, it's
* prepended.
*
* @param string $str The string to modify
* @param string $substring The substring to add if not present
* @param string $encoding The character encoding
* @return string The string prefixed by the $substring
*/
public static function ensureLeft($str, $substring, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->ensureLeft($substring);
}
/**
* Ensures that the string begins with $substring. If it doesn't, it's
* appended.
*
* @param string $str The string to modify
* @param string $substring The substring to add if not present
* @param string $encoding The character encoding
* @return string The string suffixed by the $substring
*/
public static function ensureRight($str, $substring, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->ensureRight($substring);
}
/**
* Returns a new string with the prefix $substring removed, if present.
*
* @param string $str String from which to remove the prefix
* @param string $substring The prefix to remove
* @param string $encoding The character encoding
* @return string The string without the prefix $substring
*/
public static function removeLeft($str, $substring, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->removeLeft($substring);
}
/**
* Returns a new string with the suffix $substring removed, if present.
*
* @param string $str String from which to remove the suffix
* @param string $substring The suffix to remove
* @param string $encoding The character encoding
* @return string The string without the suffix $substring
*/
public static function removeRight($str, $substring, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->removeRight($substring);
}
/**
* Returns true if the string contains a lower case char, false
* otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str contains a lower case character.
*/
public static function hasLowerCase($str, $encoding = null)
{
return Stringy::create($str, $encoding)->hasLowerCase();
}
/**
* Returns true if the string contains an upper case char, false
* otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str contains an upper case character.
*/
public static function hasUpperCase($str, $encoding = null)
{
return Stringy::create($str, $encoding)->hasUpperCase();
}
/**
* Returns true if the string contains only alphabetic chars, false
* otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str contains only alphabetic chars
*/
public static function isAlpha($str, $encoding = null)
{
return Stringy::create($str, $encoding)->isAlpha();
}
/**
* Returns true if the string contains only alphabetic and numeric chars,
* false otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str contains only alphanumeric chars
*/
public static function isAlphanumeric($str, $encoding = null)
{
return Stringy::create($str, $encoding)->isAlphanumeric();
}
/**
* Returns true if the string contains only whitespace chars, false
* otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str contains only whitespace characters
*/
public static function isBlank($str, $encoding = null)
{
return Stringy::create($str, $encoding)->isBlank();
}
/**
* Returns true if the string is JSON, false otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str is JSON
*/
public static function isJson($str, $encoding = null)
{
return Stringy::create($str, $encoding)->isJson();
}
/**
* Returns true if the string contains only lower case chars, false
* otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str contains only lower case characters
*/
public static function isLowerCase($str, $encoding = null)
{
return Stringy::create($str, $encoding)->isLowerCase();
}
/**
* Returns true if the string is serialized, false otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str is serialized
*/
public static function isSerialized($str, $encoding = null)
{
return Stringy::create($str, $encoding)->isSerialized();
}
/**
* Returns true if the string contains only upper case chars, false
* otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str contains only upper case characters
*/
public static function isUpperCase($str, $encoding = null)
{
return Stringy::create($str, $encoding)->isUpperCase();
}
/**
* Returns true if the string contains only hexadecimal chars, false
* otherwise.
*
* @param string $str String to check
* @param string $encoding The character encoding
* @return bool Whether or not $str contains only hexadecimal characters
*/
public static function isHexadecimal($str, $encoding = null)
{
return Stringy::create($str, $encoding)->isHexadecimal();
}
/**
* Returns the number of occurrences of $substring in the given string.
* By default, the comparison is case-sensitive, but can be made insensitive
* by setting $caseSensitive to false.
*
* @param string $str The string to search through
* @param string $substring The substring to search for
* @param bool $caseSensitive Whether or not to enforce case-sensitivity
* @param string $encoding The character encoding
* @return int The number of $substring occurrences
*/
public static function countSubstr($str, $substring, $caseSensitive = true,
$encoding = null)
{
return Stringy::create($str, $encoding)
->countSubstr($substring, $caseSensitive);
}
/**
* Replaces all occurrences of $search in $str by $replacement.
*
* @param string $str The haystack to search through
* @param string $search The needle to search for
* @param string $replacement The string to replace with
* @param string $encoding The character encoding
* @return string The resulting string after the replacements
*/
public static function replace($str, $search, $replacement, $encoding = null)
{
return (string) Stringy::create($str, $encoding)
->replace($search, $replacement);
}
/**
* Replaces all occurrences of $pattern in $str by $replacement. An alias
* for mb_ereg_replace(). Note that the 'i' option with multibyte patterns
* in mb_ereg_replace() requires PHP 5.4+. This is due to a lack of support
* in the bundled version of Oniguruma in PHP 5.3.
*
* @param string $str The haystack to search through
* @param string $pattern The regular expression pattern
* @param string $replacement The string to replace with
* @param string $options Matching conditions to be used
* @param string $encoding The character encoding
* @return string The resulting string after the replacements
*/
public static function regexReplace($str, $pattern, $replacement,
$options = 'msr', $encoding = null)
{
return (string) Stringy::create($str, $encoding)
->regexReplace($pattern, $replacement, $options, $encoding);
}
/**
* Convert all applicable characters to HTML entities.
*
* @param string $str The string to encode.
* @param int|null $flags See http://php.net/manual/en/function.htmlentities.php
* @param string $encoding The character encoding
* @return Stringy Object with the resulting $str after being html encoded.
*/
public static function htmlEncode($str, $flags = ENT_COMPAT, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->htmlEncode($flags);
}
/**
* Convert all HTML entities to their applicable characters.
*
* @param string $str The string to decode.
* @param int|null $flags See http://php.net/manual/en/function.html-entity-decode.php
* @param string $encoding The character encoding
* @return Stringy Object with the resulting $str after being html decoded.
*/
public static function htmlDecode($str, $flags = ENT_COMPAT, $encoding = null)
{
return (string) Stringy::create($str, $encoding)->htmlDecode($flags);
}
}

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