Commit d812816e by 叶明星

添加日志上报

parent 72b348e9
Showing with 1919 additions and 1475 deletions

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

<?php
use Bschmitt\Amqp\LumenServiceProvider;
use Common\Exceptions\Handler;
use ScmWmsCommon\Log\LogMiddleware;
require_once __DIR__.'/../vendor/autoload.php';
......@@ -63,6 +65,7 @@ $app->singleton(
$app->middleware([
// App\Http\Middleware\ExampleMiddleware::class
App\Http\Middleware\UniqueMiddleware::class,
ScmWmsCommon\Log\LogMiddleware::class
]);
// $app->routeMiddleware([
......@@ -85,6 +88,7 @@ $app->middleware([
// $app->register(App\Providers\EventServiceProvider::class);
$app->register(Illuminate\Redis\RedisServiceProvider::class);
$app->register(Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class);
$app->register(Bschmitt\Amqp\LumenServiceProvider::class);
$app->withEloquent();
/*
|--------------------------------------------------------------------------
......@@ -99,6 +103,7 @@ $app->withEloquent();
$app->configure('website');
$app->configure('database');
$app->configure('errmsg');
$app->configure('amqp');
LogReport::$suffix = '_'.env('LARAVELS_LISTEN_PORT', '');
LogReport::$app_name = env('ELK_NAME','');
LogReport::$log_path = realpath(__DIR__ . '/../').'/storage/logs/LogReport/';
......
......@@ -10,7 +10,8 @@
"vlucas/phpdotenv": "~2.2",
"predis/predis": "^1.1",
"illuminate/redis": "^5.5",
"hhxsv5/laravel-s": "~3.4.0"
"hhxsv5/laravel-s": "~3.4.0",
"bschmitt/laravel-amqp": "^2.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
......
<?php
return [
/*
|--------------------------------------------------------------------------
| Define which configuration should be used
|--------------------------------------------------------------------------
*/
'use' => 'production',
/*
|--------------------------------------------------------------------------
| AMQP properties separated by key
|--------------------------------------------------------------------------
*/
'properties' => [
'production' => [
'host' => env('RABBITMQ_HOST'),
'port' => 5672,
'username' => env('RABBITMQ_LOGIN'),
'password' => env('RABBITMQ_PASSWORD'),
'vhost' => '/',
'connect_options' => [],
'ssl_options' => [],
'exchange' => 'amq.topic',
'exchange_type' => 'topic',
'exchange_passive' => false,
'exchange_durable' => true,
'exchange_auto_delete' => false,
'exchange_internal' => false,
'exchange_nowait' => false,
'exchange_properties' => [],
'queue_force_declare' => false,
'queue_passive' => false,
'queue_durable' => true,
'queue_exclusive' => false,
'queue_auto_delete' => false,
'queue_nowait' => false,
'queue_properties' => [],
'consumer_tag' => '',
'consumer_no_local' => false,
'consumer_no_ack' => false,
'consumer_exclusive' => false,
'consumer_nowait' => false,
'timeout' => 0,
'persistent' => false,
'qos' => false,
'qos_prefetch_size' => 0,
'qos_prefetch_count' => 1,
'qos_a_global' => false
],
],
];
scm_wms_common @ b7a43f3b
Subproject commit 65e023eb6471c8502f3306414c8982f58be7255b
Subproject commit b7a43f3b5c302da482e01750ff029be3d00d069e
/.idea
/vendor
composer.lock
\ No newline at end of file
language: php
php:
- 7.0
- 7.1
before_script:
- composer self-update
- composer install --prefer-source --no-interaction --dev
# script: build.sh
# script: phpunit --configuration phpunit.xml --coverage-text
The MIT License (MIT)
Copyright (c) 2015 Björn Schmitt
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.
# bschmitt/laravel-amqp
AMQP wrapper for Laravel and Lumen to publish and consume messages especially from RabbitMQ
[![Build Status](https://travis-ci.org/bschmitt/laravel-amqp.svg?branch=master)](https://travis-ci.org/bschmitt/laravel-amqp)
[![Latest Stable Version](https://poser.pugx.org/bschmitt/laravel-amqp/v/stable.svg)](https://packagist.org/packages/bschmitt/laravel-amqp)
[![License](https://poser.pugx.org/bschmitt/laravel-amqp/license.svg)](https://packagist.org/packages/bschmitt/laravel-amqp)
## Features
- Advanced queue configuration
- Add message to queues easily
- Listen queues with useful options
## Installation
### Composer
Add the following to your require part within the composer.json:
```js
"bschmitt/laravel-amqp": "2.*" (Laravel >= 5.5)
"bschmitt/laravel-amqp": "1.*" (Laravel < 5.5)
```
```batch
$ php composer update
```
or
```
$ php composer require bschmitt/laravel-amqp
```
## Integration
### Lumen
Create a **config** folder in the root directory of your Lumen application and copy the content
from **vendor/bschmitt/laravel-amqp/config/amqp.php** to **config/amqp.php**.
Adjust the properties to your needs.
```php
return [
'use' => 'production',
'properties' => [
'production' => [
'host' => 'localhost',
'port' => 5672,
'username' => 'username',
'password' => 'password',
'vhost' => '/',
'exchange' => 'amq.topic',
'exchange_type' => 'topic',
'consumer_tag' => 'consumer',
'ssl_options' => [], // See https://secure.php.net/manual/en/context.ssl.php
'connect_options' => [], // See https://github.com/php-amqplib/php-amqplib/blob/master/PhpAmqpLib/Connection/AMQPSSLConnection.php
'queue_properties' => ['x-ha-policy' => ['S', 'all']],
'exchange_properties' => [],
'timeout' => 0
],
],
];
```
Register the Lumen Service Provider in **bootstrap/app.php**:
```php
/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
*/
//...
$app->configure('amqp');
$app->register(Bschmitt\Amqp\LumenServiceProvider::class);
//...
```
Add Facade Support for Lumen 5.2+
```php
//...
$app->withFacades();
class_alias(\Illuminate\Support\Facades\App::class, 'App');
//...
```
### Laravel
Open **config/app.php** and add the service provider and alias:
```php
'Bschmitt\Amqp\AmqpServiceProvider',
```
```php
'Amqp' => 'Bschmitt\Amqp\Facades\Amqp',
```
## Publishing a message
### Push message with routing key
```php
Amqp::publish('routing-key', 'message');
```
### Push message with routing key and create queue
```php
Amqp::publish('routing-key', 'message' , ['queue' => 'queue-name']);
```
### Push message with routing key and overwrite properties
```php
Amqp::publish('routing-key', 'message' , ['exchange' => 'amq.direct']);
```
## Consuming messages
### Consume messages, acknowledge and stop when no message is left
```php
Amqp::consume('queue-name', function ($message, $resolver) {
var_dump($message->body);
$resolver->acknowledge($message);
$resolver->stopWhenProcessed();
});
```
### Consume messages forever
```php
Amqp::consume('queue-name', function ($message, $resolver) {
var_dump($message->body);
$resolver->acknowledge($message);
});
```
### Consume messages, with custom settings
```php
Amqp::consume('queue-name', function ($message, $resolver) {
var_dump($message->body);
$resolver->acknowledge($message);
}, [
'timeout' => 2,
'vhost' => 'vhost3'
]);
```
## Fanout example
### Publishing a message
```php
\Amqp::publish('', 'message' , [
'exchange_type' => 'fanout',
'exchange' => 'amq.fanout',
]);
```
### Consuming messages
```php
\Amqp::consume('', function ($message, $resolver) {
var_dump($message->body);
$resolver->acknowledge($message);
}, [
'exchange' => 'amq.fanout',
'exchange_type' => 'fanout',
'queue_force_declare' => true,
'queue_exclusive' => true,
'persistent' => true// required if you want to listen forever
]);
```
## Credits
* Some concepts were used from https://github.com/mookofe/tail
## License
This package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
{
"name": "bschmitt/laravel-amqp",
"description": "AMQP wrapper for Laravel and Lumen to publish and consume messages",
"keywords": [
"laravel",
"lumen",
"laravel5",
"rabbitmq",
"amqp",
"queue",
"package",
"message queue",
"Björn Schmitt",
"bschmitt"
],
"license": "MIT",
"support": {
"issues": "https://github.com/bschmitt/laravel-amqp/issues",
"source": "https://github.com/bschmitt/laravel-amqp"
},
"authors": [
{
"name": "Björn Schmitt",
"email": "code@bjoern.io"
}
],
"require": {
"php": ">=7.0",
"php-amqplib/php-amqplib": ">=2.9",
"illuminate/support": ">=v5.5.28"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"mockery/mockery": "~0.9",
"squizlabs/php_codesniffer": "^3.0@dev"
},
"autoload": {
"psr-4": {
"Bschmitt\\Amqp\\": "src/",
"Bschmitt\\Amqp\\Test\\": "test/"
}
},
"extra": {
"laravel": {
"providers": [
"Bschmitt\\Amqp\\AmqpServiceProvider"
],
"aliases": {
"Amqp": "Bschmitt\\Amqp\\Facades\\Amqp"
}
}
},
"minimum-stability": "dev"
}
<?php
return [
/*
|--------------------------------------------------------------------------
| Define which configuration should be used
|--------------------------------------------------------------------------
*/
'use' => 'production',
/*
|--------------------------------------------------------------------------
| AMQP properties separated by key
|--------------------------------------------------------------------------
*/
'properties' => [
'production' => [
'host' => 'localhost',
'port' => 5672,
'username' => '',
'password' => '',
'vhost' => '/',
'connect_options' => [],
'ssl_options' => [],
'exchange' => 'amq.topic',
'exchange_type' => 'topic',
'exchange_passive' => false,
'exchange_durable' => true,
'exchange_auto_delete' => false,
'exchange_internal' => false,
'exchange_nowait' => false,
'exchange_properties' => [],
'queue_force_declare' => false,
'queue_passive' => false,
'queue_durable' => true,
'queue_exclusive' => false,
'queue_auto_delete' => false,
'queue_nowait' => false,
'queue_properties' => ['x-ha-policy' => ['S', 'all']],
'consumer_tag' => '',
'consumer_no_local' => false,
'consumer_no_ack' => false,
'consumer_exclusive' => false,
'consumer_nowait' => false,
'timeout' => 0,
'persistent' => false,
'qos' => false,
'qos_prefetch_size' => 0,
'qos_prefetch_count' => 1,
'qos_a_global' => false
],
],
];
<?xml version="1.0"?>
<phpunit
bootstrap="./vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
verbose="true"
stopOnFailure="false"
processIsolation="false"
backupGlobals="false"
syntaxCheck="true"
>
<testsuite name="Doctrine\Instantiator tests">
<directory>./tests/DoctrineTest/InstantiatorTest</directory>
</testsuite>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
</phpunit>
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Package Test Suite">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
</phpunit>
\ No newline at end of file
<?php
namespace Bschmitt\Amqp;
use Closure;
use Bschmitt\Amqp\Request;
use Bschmitt\Amqp\Message;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Amqp
{
/**
* @param string $routing
* @param mixed $message
* @param array $properties
*/
public function publish($routing, $message, array $properties = [])
{
$properties['routing'] = $routing;
/* @var Publisher $publisher */
$publisher = app()->make('Bschmitt\Amqp\Publisher');
$publisher
->mergeProperties($properties)
->setup();
if (is_string($message)) {
$message = new Message($message, ['content_type' => 'text/plain', 'delivery_mode' => 2]);
}
$publisher->publish($routing, $message);
Request::shutdown($publisher->getChannel(), $publisher->getConnection());
}
/**
* @param string $queue
* @param Closure $callback
* @param array $properties
* @throws Exception\Configuration
*/
public function consume($queue, Closure $callback, $properties = [])
{
$properties['queue'] = $queue;
/* @var Consumer $consumer */
$consumer = app()->make('Bschmitt\Amqp\Consumer');
$consumer
->mergeProperties($properties)
->setup();
$consumer->consume($queue, $callback);
Request::shutdown($consumer->getChannel(), $consumer->getConnection());
}
/**
* @param string $body
* @param array $properties
* @return \Bschmitt\Amqp\Message
*/
public function message($body, $properties = [])
{
return new Message($body, $properties);
}
}
<?php
namespace Bschmitt\Amqp;
use Bschmitt\Amqp\Consumer;
use Bschmitt\Amqp\Publisher;
use Illuminate\Support\ServiceProvider;
class AmqpServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = true;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->app->bind('Amqp', 'Bschmitt\Amqp\Amqp');
if (!class_exists('Amqp')) {
class_alias('Bschmitt\Amqp\Facades\Amqp', 'Amqp');
}
$this->publishes([
__DIR__.'/../config/amqp.php' => config_path('amqp.php'),
]);
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->app->singleton('Bschmitt\Amqp\Publisher', function ($app) {
return new Publisher(config());
});
$this->app->singleton('Bschmitt\Amqp\Consumer', function ($app) {
return new Consumer(config());
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return ['Amqp', 'Bschmitt\Amqp\Publisher', 'Bschmitt\Amqp\Consumer'];
}
}
<?php
namespace Bschmitt\Amqp;
use Illuminate\Config\Repository;
use Closure;
use PhpAmqpLib\Exception\AMQPTimeoutException;
use PhpAmqpLib\Message\AMQPMessage;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Consumer extends Request
{
/**
* @var int
*/
protected $messageCount = 0;
/**
* @param string $queue
* @param Closure $closure
* @return bool
* @throws \Exception
*/
public function consume($queue, Closure $closure)
{
try {
$this->messageCount = $this->getQueueMessageCount();
if (!$this->getProperty('persistent') && $this->messageCount == 0) {
throw new Exception\Stop();
}
/*
queue: Queue from where to get the messages
consumer_tag: Consumer identifier
no_local: Don't receive messages published by this consumer.
no_ack: Tells the server if the consumer will acknowledge the messages.
exclusive: Request exclusive consumer access, meaning only this consumer can access the queue
nowait:
qos: The consumer-prefetch make it possible to limit the number of unacknowledged messages on a channel (or connection) when consuming.
Or, in other words, don't dispatch a new message to a worker
until it has processed and acknowledged the previous one
callback: A PHP Callback
*/
$object = $this;
if ($this->getProperty('qos')) {
$this->getChannel()->basic_qos(
$this->getProperty('qos_prefetch_size'),
$this->getProperty('qos_prefetch_count'),
$this->getProperty('qos_a_global')
);
}
$this->getChannel()->basic_consume(
$queue,
$this->getProperty('consumer_tag'),
$this->getProperty('consumer_no_local'),
$this->getProperty('consumer_no_ack'),
$this->getProperty('consumer_exclusive'),
$this->getProperty('consumer_nowait'),
function ($message) use ($closure, $object) {
$closure($message, $object);
}
);
// consume
while (count($this->getChannel()->callbacks)) {
$this->getChannel()->wait(null, false,
$this->getProperty('timeout') ? $this->getProperty('timeout') : 0
);
}
} catch (\Exception $e) {
if ($e instanceof Exception\Stop) {
return true;
}
if ($e instanceof AMQPTimeoutException) {
return true;
}
throw $e;
}
return true;
}
/**
* Acknowledges a message
*
* @param AMQPMessage $message
*/
public function acknowledge(AMQPMessage $message)
{
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
/**
* Rejects a message and requeues it if wanted (default: false)
*
* @param AMQPMessage $message
* @param bool $requeue
*/
public function reject(AMQPMessage $message, $requeue = false)
{
$message->delivery_info['channel']->basic_reject($message->delivery_info['delivery_tag'], $requeue);
}
/**
* Stops consumer when no message is left
*
* @throws Exception\Stop
*/
public function stopWhenProcessed()
{
if (--$this->messageCount <= 0) {
throw new Exception\Stop();
}
}
}
<?php
namespace Bschmitt\Amqp;
use Illuminate\Config\Repository;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
abstract class Context
{
const REPOSITORY_KEY = 'amqp';
/**
* @var array
*/
protected $properties = [];
/**
* Context constructor.
*
* @param Repository $config
*/
public function __construct(Repository $config)
{
$this->extractProperties($config);
}
/**
* @param Repository $config
*/
protected function extractProperties(Repository $config)
{
if ($config->has(self::REPOSITORY_KEY)) {
$data = $config->get(self::REPOSITORY_KEY);
$this->properties = $data['properties'][$data['use']];
}
}
/**
* @param array $properties
* @return $this
*/
public function mergeProperties(array $properties)
{
$this->properties = array_merge($this->properties, $properties);
return $this;
}
/**
* @return array
*/
public function getProperties()
{
return $this->properties;
}
/**
* @param string $key
* @return mixed
*/
public function getProperty($key)
{
return array_key_exists($key, $this->properties) ? $this->properties[$key] : null;
}
/**
* @param string $key
* @param mixed $default
* @return mixed
*/
public function getConnectOption($key, $default = null)
{
$options = $this->getProperty('connect_options');
if (!is_array($options)) {
return $default;
}
return array_key_exists($key, $options) ? $options[$key] : $default;
}
/**
* @return mixed
*/
abstract public function setup();
}
<?php
namespace Bschmitt\Amqp\Exception;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Configuration extends \Exception
{
}
<?php
namespace Bschmitt\Amqp\Exception;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Stop extends \Exception
{
}
<?php
namespace Bschmitt\Amqp\Facades;
use Illuminate\Support\Facades\Facade;
/**
* @author Björn Schmitt <code@bjoern.io>
* @see Bschmitt\Amqp\Amqp
*/
class Amqp extends Facade
{
/**
* @return string
*/
protected static function getFacadeAccessor()
{
return 'Amqp';
}
}
<?php
namespace Bschmitt\Amqp;
use Illuminate\Support\ServiceProvider;
/**
* Lumen Service Provider
*
* @author Björn Schmitt <code@bjoern.io>
*/
class LumenServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
$this->app->bind('Bschmitt\Amqp\Publisher', function ($app) {
return new Publisher($app->config);
});
$this->app->bind('Bschmitt\Amqp\Consumer', function ($app) {
return new Consumer($app->config);
});
$this->app->bind('Amqp', 'Bschmitt\Amqp\Amqp');
if (!class_exists('Amqp')) {
class_alias('Bschmitt\Amqp\Facades\Amqp', 'Amqp');
}
}
}
<?php
namespace Bschmitt\Amqp;
use PhpAmqpLib\Message\AMQPMessage;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Message extends AMQPMessage
{
}
<?php
namespace Bschmitt\Amqp;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Publisher extends Request
{
/**
* @param string $routing
* @param Message $message
* @throws Exception\Configuration
*/
public function publish($routing, $message)
{
$this->getChannel()->basic_publish($message, $this->getProperty('exchange'), $routing);
}
}
<?php
namespace Bschmitt\Amqp;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Connection\AMQPSSLConnection;
use PhpAmqpLib\Channel\AMQPChannel;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Request extends Context
{
/**
* @var AMQPStreamConnection
*/
protected $connection;
/**
* @var AMQPChannel
*/
protected $channel;
/**
* @var array
*/
protected $queueInfo;
/**
*
*/
public function connect()
{
if ($this->getProperty('ssl_options')) {
$this->connection = new AMQPSSLConnection(
$this->getProperty('host'),
$this->getProperty('port'),
$this->getProperty('username'),
$this->getProperty('password'),
$this->getProperty('vhost'),
$this->getProperty('ssl_options'),
$this->getProperty('connect_options')
);
} else {
$this->connection = new AMQPStreamConnection(
$this->getProperty('host'),
$this->getProperty('port'),
$this->getProperty('username'),
$this->getProperty('password'),
$this->getProperty('vhost'),
$this->getConnectOption('insist', false),
$this->getConnectOption('login_method', 'AMQPLAIN'),
$this->getConnectOption('login_response', null),
$this->getConnectOption('locale', 3),
$this->getConnectOption('connection_timeout', 3.0),
$this->getConnectOption('read_write_timeout', 130),
$this->getConnectOption('context', null),
$this->getConnectOption('keepalive', false),
$this->getConnectOption('heartbeat', 60),
$this->getConnectOption('channel_rpc_timeout', 0.0),
$this->getConnectOption('ssl_protocol', null)
);
}
$this->channel = $this->connection->channel();
}
/**
* @throws Exception\Configuration
*/
public function setup()
{
$this->connect();
$exchange = $this->getProperty('exchange');
if (empty($exchange)) {
throw new Exception\Configuration('Please check your settings, exchange is not defined.');
}
/*
name: $exchange
type: topic
passive: false
durable: true // the exchange will survive server restarts
auto_delete: false //the exchange won't be deleted once the channel is closed.
*/
$this->channel->exchange_declare(
$exchange,
$this->getProperty('exchange_type'),
$this->getProperty('exchange_passive'),
$this->getProperty('exchange_durable'),
$this->getProperty('exchange_auto_delete'),
$this->getProperty('exchange_internal'),
$this->getProperty('exchange_nowait'),
$this->getProperty('exchange_properties')
);
$queue = $this->getProperty('queue');
if (!empty($queue) || $this->getProperty('queue_force_declare')) {
/*
name: $queue
passive: false
durable: true // the queue will survive server restarts
exclusive: false // queue is deleted when connection closes
auto_delete: false //the queue won't be deleted once the channel is closed.
nowait: false // Doesn't wait on replies for certain things.
parameters: array // Extra data, like high availability params
*/
/** @var ['queue name', 'message count',] queueInfo */
$this->queueInfo = $this->channel->queue_declare(
$queue,
$this->getProperty('queue_passive'),
$this->getProperty('queue_durable'),
$this->getProperty('queue_exclusive'),
$this->getProperty('queue_auto_delete'),
$this->getProperty('queue_nowait'),
$this->getProperty('queue_properties')
);
$this->channel->queue_bind(
$queue ?: $this->queueInfo[0],
$exchange,
$this->getProperty('routing')
);
}
// clear at shutdown
$this->connection->set_close_on_destruct(true);
}
/**
* @return \PhpAmqpLib\Channel\AMQPChannel
*/
public function getChannel()
{
return $this->channel;
}
/**
* @return AMQPStreamConnection
*/
public function getConnection()
{
return $this->connection;
}
/**
* @return int
*/
public function getQueueMessageCount()
{
if (is_array($this->queueInfo)) {
return $this->queueInfo[1];
}
return 0;
}
/**
* @param AMQPChannel $channel
* @param AMQPStreamConnection $connection
*/
public static function shutdown(AMQPChannel $channel, AMQPStreamConnection $connection)
{
$channel->close();
$connection->close();
}
}
<?php
namespace Bschmitt\Amqp\Test;
use \Mockery;
use Illuminate\Config\Repository;
class BaseTestCase extends \PHPUnit_Framework_TestCase
{
const REPOSITORY_KEY = 'amqp';
protected $configRepository;
protected $defaultConfig;
protected function setUp()
{
$amqpConfig = include dirname(__FILE__).'/../config/amqp.php';
$this->defaultConfig = $amqpConfig['properties'][$amqpConfig['use']];
$config = Mockery::mock('\Illuminate\Config\Repository');
$config->shouldReceive('has')->with(self::REPOSITORY_KEY)->andReturn(true);
$config->shouldReceive('get')->with(self::REPOSITORY_KEY)->andReturn($amqpConfig);
$this->configRepository = $config;
}
protected function tearDown()
{
// necessary for Mockery to check if methods were called and with what arguments
Mockery::close();
}
protected function setProtectedProperty($class, $mock, $propertyName, $value)
{
$reflectionClass = new \ReflectionClass($class);
$channelProperty = $reflectionClass->getProperty($propertyName);
$channelProperty->setAccessible(true);
$channelProperty->setValue($mock, $value);
$channelProperty->setAccessible(false);
}
}
<?php
namespace Bschmitt\Amqp\Test;
use \Mockery;
use Bschmitt\Amqp\Publisher;
use Illuminate\Config\Repository;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class PublisherTest extends BaseTestCase
{
private $publisherMock;
private $connectionMock;
private $channelMock;
protected function setUp()
{
parent::setUp();
// partial mock of \Bschmitt\Amqp\Publisher
// we want all methods except [connect] to be real
$this->publisherMock = Mockery::mock('\Bschmitt\Amqp\Publisher[connect]', [$this->configRepository]);
// set connection and channel properties
$this->channelMock = Mockery::mock('\PhpAmqpLib\Channel\AMQPChannel');
$this->connectionMock = Mockery::mock('\PhpAmqpLib\Connection\AMQPSSLConnection');
// channel and connection are both protected and without changing the source this was the only way to mock them
$this->setProtectedProperty('\Bschmitt\Amqp\Publisher', $this->publisherMock, 'channel', $this->channelMock);
$this->setProtectedProperty('\Bschmitt\Amqp\Publisher', $this->publisherMock, 'connection', $this->connectionMock);
}
public function testSetupPublisher()
{
$this->connectionMock->shouldReceive('set_close_on_destruct')->with(true)->times(1);
$this->channelMock->shouldReceive('exchange_declare')->with(
$this->defaultConfig['exchange'],
$this->defaultConfig['exchange_type'],
$this->defaultConfig['exchange_passive'],
$this->defaultConfig['exchange_durable'],
$this->defaultConfig['exchange_auto_delete'],
$this->defaultConfig['exchange_internal'],
$this->defaultConfig['exchange_nowait'],
$this->defaultConfig['exchange_properties']
)->times(1);
$this->publisherMock->shouldReceive('connect')->times(1);
$this->publisherMock->setup();
}
public function testPublishShouldAChannelMethodWithProperParams()
{
$routing = 'routing-key';
$message = 'sample-message';
$this->channelMock->shouldReceive('basic_publish')
->with(
$message,
$this->defaultConfig['exchange'],
$routing
)->times(1);
$this->publisherMock->publish($routing, $message);
}
public function testPublishShouldCallAChannelMethodWithCustomExchangeValue()
{
$routing = 'routing-key';
$message = 'sample-message';
$exchange = 'custom-exchange';
$this->publisherMock->mergeProperties(['exchange' => $exchange]);
$this->channelMock->shouldReceive('basic_publish')
->with(
$message,
$exchange,
$routing
)->times(1);
$this->publisherMock->publish($routing, $message);
}
}
<?php
namespace Bschmitt\Amqp\Test;
use \Mockery;
use Bschmitt\Amqp\Request;
use Bschmitt\Amqp\Context;
class RequestTest extends BaseTestCase
{
private $connectionMock;
private $channelMock;
private $requestMock;
protected function setUp()
{
parent::setUp();
$this->channelMock = Mockery::mock('\PhpAmqpLib\Channel\AMQPChannel');
$this->connectionMock = Mockery::mock('\PhpAmqpLib\Connection\AMQPSSLConnection');
// partial mock of \Bschmitt\Amqp\Publisher
// we want all methods except [connect,getChannel] to be real
$this->requestMock = Mockery::mock('\Bschmitt\Amqp\Request[connect,getChannel]', [$this->configRepository]);
// channel and connection are both protected and without changing the source this was the only way to mock them
$this->setProtectedProperty('\Bschmitt\Amqp\Request', $this->requestMock, 'channel', $this->channelMock);
$this->setProtectedProperty('\Bschmitt\Amqp\Request', $this->requestMock, 'connection', $this->connectionMock);
}
/**
* @expectedException Bschmitt\Amqp\Exception\Configuration
*/
public function testIfEmptyExchangeThrowsAnException()
{
$this->requestMock->mergeProperties(['exchange' => '']);
$this->requestMock->shouldReceive('connect');
$this->requestMock->setup();
}
public function testIfQueueGetsDeclaredAndBoundIfInConfig()
{
$queueName = 'amqp-test';
$routing = 'routing-test';
$this->requestMock->mergeProperties([
'queue' => $queueName,
'queue_force_declare' => true,
'routing' => $routing
]);
$this->channelMock->shouldReceive('exchange_declare');
$this->requestMock->shouldReceive('connect');
$this->channelMock->shouldReceive('queue_declare')
->with(
$queueName,
$this->defaultConfig['queue_passive'],
$this->defaultConfig['queue_durable'],
$this->defaultConfig['queue_exclusive'],
$this->defaultConfig['queue_auto_delete'],
$this->defaultConfig['queue_nowait'],
$this->defaultConfig['queue_properties']
)
->andReturn([$queueName, 4])
->times(1);
$this->channelMock->shouldReceive('queue_bind')
->with(
$queueName,
$this->defaultConfig['exchange'],
$routing
)
->times(1);
$this->connectionMock->shouldReceive('set_close_on_destruct')->with(true)->times(1);
$this->requestMock->setup();
}
public function testQueueMessageCountShouldBeZeroIfQueueinfoIsNotSet()
{
$this->assertEquals($this->requestMock->getQueueMessageCount(), 0);
}
public function testQueueMessageCountShouldReturnMessageCount()
{
$messageCount = 4;
$queueInfo = ['queue-name', $messageCount];
$this->setProtectedProperty('\Bschmitt\Amqp\Request', $this->requestMock, 'queueInfo', $queueInfo);
$this->assertEquals($this->requestMock->getQueueMessageCount(), $messageCount);
}
public function testIfChannelAndConnectionAreClosedWhenShutdownIsInvoked()
{
$this->channelMock->shouldReceive('close')->times(1);
$this->connectionMock->shouldReceive('close')->times(1);
$this->requestMock::shutDown($this->channelMock, $this->connectionMock);
}
}
......@@ -279,7 +279,7 @@ class ClassLoader
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
......@@ -377,7 +377,7 @@ class ClassLoader
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath.'\\';
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
......
......@@ -9,8 +9,10 @@ return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'1d1b89d124cc9cb8219922c9d5569199' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php',
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
'bee9632da3ca00a99623b9c35d0c4f8b' => $vendorDir . '/laravel/lumen-framework/src/helpers.php',
......
......@@ -7,6 +7,5 @@ $baseDir = dirname($vendorDir);
return array(
'UpdateHelper\\' => array($vendorDir . '/kylekatarnls/update-helper/src'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'),
'Mockery' => array($vendorDir . '/mockery/mockery/library'),
);
......@@ -6,12 +6,16 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
'Symfony\\Polyfill\\Util\\' => array($vendorDir . '/symfony/polyfill-util'),
'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'),
'Symfony\\Polyfill\\Php56\\' => array($vendorDir . '/symfony/polyfill-php56'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
......@@ -24,7 +28,9 @@ return array(
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
'Predis\\' => array($vendorDir . '/predis/predis/src'),
'PhpAmqpLib\\' => array($vendorDir . '/php-amqplib/php-amqplib/PhpAmqpLib'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'Laravel\\Lumen\\' => array($vendorDir . '/laravel/lumen-framework/src'),
'Illuminate\\View\\' => array($vendorDir . '/illuminate/view'),
......@@ -59,6 +65,8 @@ return array(
'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
'Cron\\' => array($vendorDir . '/mtdowling/cron-expression/src/Cron'),
'Common\\' => array($baseDir . '/common'),
'Bschmitt\\Amqp\\Test\\' => array($vendorDir . '/bschmitt/laravel-amqp/test'),
'Bschmitt\\Amqp\\' => array($vendorDir . '/bschmitt/laravel-amqp/src'),
'App\\' => array($baseDir . '/app'),
'' => array($vendorDir . '/nesbot/carbon/src'),
);
......@@ -10,8 +10,10 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php',
'72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
'1d1b89d124cc9cb8219922c9d5569199' => __DIR__ . '/..' . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php',
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
'bee9632da3ca00a99623b9c35d0c4f8b' => __DIR__ . '/..' . '/laravel/lumen-framework/src/helpers.php',
......@@ -22,6 +24,7 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
public static $prefixLengthsPsr4 = array (
'p' =>
array (
'phpseclib\\' => 10,
'phpDocumentor\\Reflection\\' => 25,
),
'W' =>
......@@ -30,10 +33,13 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
),
'S' =>
array (
'Symfony\\Polyfill\\Util\\' => 22,
'Symfony\\Polyfill\\Php70\\' => 23,
'Symfony\\Polyfill\\Php56\\' => 23,
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Ctype\\' => 23,
'Symfony\\Contracts\\Translation\\' => 30,
'Symfony\\Contracts\\EventDispatcher\\' => 34,
'Symfony\\Component\\Translation\\' => 30,
'Symfony\\Component\\Process\\' => 26,
'Symfony\\Component\\HttpKernel\\' => 29,
......@@ -49,7 +55,9 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
'Psr\\SimpleCache\\' => 16,
'Psr\\Log\\' => 8,
'Psr\\Container\\' => 14,
'Prophecy\\' => 9,
'Predis\\' => 7,
'PhpAmqpLib\\' => 11,
),
'M' =>
array (
......@@ -106,6 +114,11 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
'Cron\\' => 5,
'Common\\' => 7,
),
'B' =>
array (
'Bschmitt\\Amqp\\Test\\' => 19,
'Bschmitt\\Amqp\\' => 14,
),
'A' =>
array (
'App\\' => 4,
......@@ -113,6 +126,10 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
);
public static $prefixDirsPsr4 = array (
'phpseclib\\' =>
array (
0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
),
'phpDocumentor\\Reflection\\' =>
array (
0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src',
......@@ -123,10 +140,18 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
array (
0 => __DIR__ . '/..' . '/webmozart/assert/src',
),
'Symfony\\Polyfill\\Util\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-util',
),
'Symfony\\Polyfill\\Php70\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php70',
),
'Symfony\\Polyfill\\Php56\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php56',
),
'Symfony\\Polyfill\\Mbstring\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
......@@ -139,6 +164,10 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
array (
0 => __DIR__ . '/..' . '/symfony/translation-contracts',
),
'Symfony\\Contracts\\EventDispatcher\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts',
),
'Symfony\\Component\\Translation\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/translation',
......@@ -187,10 +216,18 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
array (
0 => __DIR__ . '/..' . '/psr/container/src',
),
'Prophecy\\' =>
array (
0 => __DIR__ . '/..' . '/phpspec/prophecy/src/Prophecy',
),
'Predis\\' =>
array (
0 => __DIR__ . '/..' . '/predis/predis/src',
),
'PhpAmqpLib\\' =>
array (
0 => __DIR__ . '/..' . '/php-amqplib/php-amqplib/PhpAmqpLib',
),
'Monolog\\' =>
array (
0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
......@@ -327,6 +364,14 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
array (
0 => __DIR__ . '/../..' . '/common',
),
'Bschmitt\\Amqp\\Test\\' =>
array (
0 => __DIR__ . '/..' . '/bschmitt/laravel-amqp/test',
),
'Bschmitt\\Amqp\\' =>
array (
0 => __DIR__ . '/..' . '/bschmitt/laravel-amqp/src',
),
'App\\' =>
array (
0 => __DIR__ . '/../..' . '/app',
......@@ -345,13 +390,6 @@ class ComposerStaticInit5c9707cde9ea4e3942300fe24293f04f
0 => __DIR__ . '/..' . '/kylekatarnls/update-helper/src',
),
),
'P' =>
array (
'Prophecy\\' =>
array (
0 => __DIR__ . '/..' . '/phpspec/prophecy/src',
),
),
'M' =>
array (
'Mockery' =>
......
{
"active": true,
"name": "Instantiator",
"slug": "instantiator",
"docsSlug": "doctrine-instantiator",
"codePath": "/src",
"versions": [
{
"name": "1.1",
"branchName": "master",
"slug": "latest",
"aliases": [
"current",
"stable"
],
"maintained": true,
"current": true
},
{
"name": "1.0",
"branchName": "1.0.x",
"slug": "1.0"
}
]
}
patreon: phpdoctrine
tidelift: packagist/doctrine%2Finstantiator
custom: https://www.doctrine-project.org/sponsorship.html
#!/bin/sh
set -x
if [ "$TRAVIS_PHP_VERSION" = 'hhvm' ] || [ "$TRAVIS_PHP_VERSION" = 'hhvm-nightly' ] ; then
curl -sS https://getcomposer.org/installer > composer-installer.php
hhvm composer-installer.php
hhvm -v ResourceLimit.SocketDefaultTimeout=30 -v Http.SlowQueryThreshold=30000 composer.phar update --prefer-source
elif [ "$TRAVIS_PHP_VERSION" = '5.3.3' ] ; then
composer self-update
composer update --prefer-source --no-dev
composer dump-autoload
else
composer self-update
composer update --prefer-source
fi
language: php
php:
- 5.3.3
- 5.3
- 5.4
- 5.5
- 5.6
- hhvm
before_script:
- ./.travis.install.sh
- if [ $TRAVIS_PHP_VERSION = '5.6' ]; then PHPUNIT_FLAGS="--coverage-clover coverage.clover"; else PHPUNIT_FLAGS=""; fi
script:
- if [ $TRAVIS_PHP_VERSION = '5.3.3' ]; then phpunit; fi
- if [ $TRAVIS_PHP_VERSION != '5.3.3' ]; then ./vendor/bin/phpunit $PHPUNIT_FLAGS; fi
- if [ $TRAVIS_PHP_VERSION != '5.3.3' ]; then ./vendor/bin/phpcs --standard=PSR2 ./src/ ./tests/; fi
- if [[ $TRAVIS_PHP_VERSION != '5.3.3' && $TRAVIS_PHP_VERSION != '5.4.29' && $TRAVIS_PHP_VERSION != '5.5.13' ]]; then php -n ./vendor/bin/athletic -p ./tests/DoctrineTest/InstantiatorPerformance/ -f GroupedFormatter; fi
after_script:
- if [ $TRAVIS_PHP_VERSION = '5.6' ]; then wget https://scrutinizer-ci.com/ocular.phar; php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi
# Contributing
* Coding standard for the project is [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
* Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard)
* The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)
* Any contribution must provide tests for additional introduced conditions
* Any un-confirmed issue needs a failing test case before being accepted
......
......@@ -6,7 +6,6 @@ This library provides a way of avoiding usage of constructors when instantiating
[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master)
[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator)
[![HHVM Status](http://hhvm.h4cc.de/badge/doctrine/instantiator.png)](http://hhvm.h4cc.de/package/doctrine/instantiator)
[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator)
[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator)
......@@ -27,7 +26,7 @@ itself:
```php
$instantiator = new \Doctrine\Instantiator\Instantiator();
$instance = $instantiator->instantiate('My\\ClassName\\Here');
$instance = $instantiator->instantiate(\My\ClassName\Here::class);
```
## Contributing
......
......@@ -3,7 +3,7 @@
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"type": "library",
"license": "MIT",
"homepage": "https://github.com/doctrine/instantiator",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"instantiate",
"constructor"
......@@ -16,14 +16,16 @@
}
],
"require": {
"php": ">=5.3,<8.0-DEV"
"php": "^7.1"
},
"require-dev": {
"ext-phar": "*",
"ext-pdo": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0",
"athletic/athletic": "~0.1.8"
"doctrine/coding-standard": "^6.0",
"phpbench/phpbench": "^0.13",
"phpstan/phpstan-phpunit": "^0.11",
"phpstan/phpstan-shim": "^0.11",
"phpunit/phpunit": "^7.0"
},
"autoload": {
"psr-4": {
......@@ -39,7 +41,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.2.x-dev"
}
}
}
Introduction
============
This library provides a way of avoiding usage of constructors when instantiating PHP classes.
Installation
============
The suggested installation method is via `composer`_:
.. code-block:: console
$ composer require doctrine/instantiator
Usage
=====
The instantiator is able to create new instances of any class without
using the constructor or any API of the class itself:
.. code-block:: php
<?php
use Doctrine\Instantiator\Instantiator;
use App\Entities\User;
$instantiator = new Instantiator();
$user = $instantiator->instantiate(User::class);
Contributing
============
- Follow the `Doctrine Coding Standard`_
- The project will follow strict `object calisthenics`_
- Any contribution must provide tests for additional introduced
conditions
- Any un-confirmed issue needs a failing test case before being
accepted
- Pull requests must be sent from a new hotfix/feature branch, not from
``master``.
Testing
=======
The PHPUnit version to be used is the one installed as a dev- dependency
via composer:
.. code-block:: console
$ ./vendor/bin/phpunit
Accepted coverage for new contributions is 80%. Any contribution not
satisfying this requirement won’t be merged.
Credits
=======
This library was migrated from `ocramius/instantiator`_, which has been
donated to the doctrine organization, and which is now deprecated in
favour of this package.
.. _composer: https://getcomposer.org/
.. _CONTRIBUTING.md: CONTRIBUTING.md
.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator
.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard
.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php
{
"bootstrap": "vendor/autoload.php",
"path": "tests/DoctrineTest/InstantiatorPerformance"
}
<?xml version="1.0"?>
<ruleset>
<arg name="basepath" value="."/>
<arg name="extensions" value="php"/>
<arg name="parallel" value="80"/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<!-- Ignore warnings, show progress of the run and show sniff names -->
<arg value="nps"/>
<file>src</file>
<file>tests</file>
<rule ref="Doctrine">
<exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes"/>
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint"/>
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint"/>
<exclude name="SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException"/>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming">
<exclude-pattern>tests/DoctrineTest/InstantiatorTestAsset/AbstractClassAsset.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming">
<exclude-pattern>src/Doctrine/Instantiator/Exception/UnexpectedValueException.php</exclude-pattern>
<exclude-pattern>src/Doctrine/Instantiator/Exception/InvalidArgumentException.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming">
<exclude-pattern>src/Doctrine/Instantiator/Exception/ExceptionInterface.php</exclude-pattern>
<exclude-pattern>src/Doctrine/Instantiator/InstantiatorInterface.php</exclude-pattern>
</rule>
</ruleset>
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
parameters:
level: max
paths:
- src
- tests
ignoreErrors:
-
message: '#::__construct\(\) does not call parent constructor from#'
path: '*/tests/DoctrineTest/InstantiatorTestAsset/*.php'
# dynamic properties confuse static analysis
-
message: '#Access to an undefined property object::\$foo\.#'
path: '*/tests/DoctrineTest/InstantiatorTest/InstantiatorTest.php'
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
use Throwable;
/**
* Base exception marker interface for the instantiator component
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
interface ExceptionInterface
interface ExceptionInterface extends Throwable
{
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
use ReflectionClass;
use const PHP_VERSION_ID;
use function interface_exists;
use function sprintf;
use function trait_exists;
/**
* Exception for invalid arguments provided to the instantiator
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
{
/**
* @param string $className
*
* @return self
*/
public static function fromNonExistingClass($className)
public static function fromNonExistingClass(string $className) : self
{
if (interface_exists($className)) {
return new self(sprintf('The provided type "%s" is an interface, and can not be instantiated', $className));
......@@ -47,12 +27,7 @@ class InvalidArgumentException extends BaseInvalidArgumentException implements E
return new self(sprintf('The provided class "%s" does not exist', $className));
}
/**
* @param ReflectionClass $reflectionClass
*
* @return self
*/
public static function fromAbstractClass(ReflectionClass $reflectionClass)
public static function fromAbstractClass(ReflectionClass $reflectionClass) : self
{
return new self(sprintf(
'The provided class "%s" is abstract, and can not be instantiated',
......
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator\Exception;
use Exception;
use ReflectionClass;
use UnexpectedValueException as BaseUnexpectedValueException;
use function sprintf;
/**
* Exception for given parameters causing invalid/unexpected state on instantiation
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface
{
/**
* @param ReflectionClass $reflectionClass
* @param Exception $exception
*
* @return self
*/
public static function fromSerializationTriggeredException(ReflectionClass $reflectionClass, Exception $exception)
{
public static function fromSerializationTriggeredException(
ReflectionClass $reflectionClass,
Exception $exception
) : self {
return new self(
sprintf(
'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
......@@ -48,22 +26,13 @@ class UnexpectedValueException extends BaseUnexpectedValueException implements E
);
}
/**
* @param ReflectionClass $reflectionClass
* @param string $errorString
* @param int $errorCode
* @param string $errorFile
* @param int $errorLine
*
* @return UnexpectedValueException
*/
public static function fromUncleanUnSerialization(
ReflectionClass $reflectionClass,
$errorString,
$errorCode,
$errorFile,
$errorLine
) {
string $errorString,
int $errorCode,
string $errorFile,
int $errorLine
) : self {
return new self(
sprintf(
'Could not produce an instance of "%s" via un-serialization, since an error was triggered '
......
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Instantiator;
use Doctrine\Instantiator\Exception\ExceptionInterface;
/**
* Instantiator provides utility methods to build objects without invoking their constructors
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
interface InstantiatorInterface
{
......@@ -31,7 +14,7 @@ interface InstantiatorInterface
*
* @return object
*
* @throws \Doctrine\Instantiator\Exception\ExceptionInterface
* @throws ExceptionInterface
*/
public function instantiate($className);
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorPerformance;
use Athletic\AthleticEvent;
use Doctrine\Instantiator\Instantiator;
/**
* Performance tests for {@see \Doctrine\Instantiator\Instantiator}
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class InstantiatorPerformanceEvent extends AthleticEvent
{
/**
* @var \Doctrine\Instantiator\Instantiator
*/
private $instantiator;
/**
* {@inheritDoc}
*/
protected function setUp()
{
$this->instantiator = new Instantiator();
$this->instantiator->instantiate(__CLASS__);
$this->instantiator->instantiate('ArrayObject');
$this->instantiator->instantiate('DoctrineTest\\InstantiatorTestAsset\\SimpleSerializableAsset');
$this->instantiator->instantiate('DoctrineTest\\InstantiatorTestAsset\\SerializableArrayObjectAsset');
$this->instantiator->instantiate('DoctrineTest\\InstantiatorTestAsset\\UnCloneableAsset');
}
/**
* @iterations 20000
* @baseline
* @group instantiation
*/
public function testInstantiateSelf()
{
$this->instantiator->instantiate(__CLASS__);
}
/**
* @iterations 20000
* @group instantiation
*/
public function testInstantiateInternalClass()
{
$this->instantiator->instantiate('ArrayObject');
}
/**
* @iterations 20000
* @group instantiation
*/
public function testInstantiateSimpleSerializableAssetClass()
{
$this->instantiator->instantiate('DoctrineTest\\InstantiatorTestAsset\\SimpleSerializableAsset');
}
/**
* @iterations 20000
* @group instantiation
*/
public function testInstantiateSerializableArrayObjectAsset()
{
$this->instantiator->instantiate('DoctrineTest\\InstantiatorTestAsset\\SerializableArrayObjectAsset');
}
/**
* @iterations 20000
* @group instantiation
*/
public function testInstantiateUnCloneableAsset()
{
$this->instantiator->instantiate('DoctrineTest\\InstantiatorTestAsset\\UnCloneableAsset');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTest\Exception;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use PHPUnit_Framework_TestCase;
use ReflectionClass;
/**
* Tests for {@see \Doctrine\Instantiator\Exception\InvalidArgumentException}
*
* @author Marco Pivetta <ocramius@gmail.com>
*
* @covers \Doctrine\Instantiator\Exception\InvalidArgumentException
*/
class InvalidArgumentExceptionTest extends PHPUnit_Framework_TestCase
{
public function testFromNonExistingTypeWithNonExistingClass()
{
$className = __CLASS__ . uniqid();
$exception = InvalidArgumentException::fromNonExistingClass($className);
$this->assertInstanceOf('Doctrine\\Instantiator\\Exception\\InvalidArgumentException', $exception);
$this->assertSame('The provided class "' . $className . '" does not exist', $exception->getMessage());
}
public function testFromNonExistingTypeWithTrait()
{
if (PHP_VERSION_ID < 50400) {
$this->markTestSkipped('Need at least PHP 5.4.0, as this test requires traits support to run');
}
$exception = InvalidArgumentException::fromNonExistingClass(
'DoctrineTest\\InstantiatorTestAsset\\SimpleTraitAsset'
);
$this->assertSame(
'The provided type "DoctrineTest\\InstantiatorTestAsset\\SimpleTraitAsset" is a trait, '
. 'and can not be instantiated',
$exception->getMessage()
);
}
public function testFromNonExistingTypeWithInterface()
{
$exception = InvalidArgumentException::fromNonExistingClass('Doctrine\\Instantiator\\InstantiatorInterface');
$this->assertSame(
'The provided type "Doctrine\\Instantiator\\InstantiatorInterface" is an interface, '
. 'and can not be instantiated',
$exception->getMessage()
);
}
public function testFromAbstractClass()
{
$reflection = new ReflectionClass('DoctrineTest\\InstantiatorTestAsset\\AbstractClassAsset');
$exception = InvalidArgumentException::fromAbstractClass($reflection);
$this->assertSame(
'The provided class "DoctrineTest\\InstantiatorTestAsset\\AbstractClassAsset" is abstract, '
. 'and can not be instantiated',
$exception->getMessage()
);
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTest\Exception;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Exception;
use PHPUnit_Framework_TestCase;
use ReflectionClass;
/**
* Tests for {@see \Doctrine\Instantiator\Exception\UnexpectedValueException}
*
* @author Marco Pivetta <ocramius@gmail.com>
*
* @covers \Doctrine\Instantiator\Exception\UnexpectedValueException
*/
class UnexpectedValueExceptionTest extends PHPUnit_Framework_TestCase
{
public function testFromSerializationTriggeredException()
{
$reflectionClass = new ReflectionClass($this);
$previous = new Exception();
$exception = UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $previous);
$this->assertInstanceOf('Doctrine\\Instantiator\\Exception\\UnexpectedValueException', $exception);
$this->assertSame($previous, $exception->getPrevious());
$this->assertSame(
'An exception was raised while trying to instantiate an instance of "'
. __CLASS__ . '" via un-serialization',
$exception->getMessage()
);
}
public function testFromUncleanUnSerialization()
{
$reflection = new ReflectionClass('DoctrineTest\\InstantiatorTestAsset\\AbstractClassAsset');
$exception = UnexpectedValueException::fromUncleanUnSerialization($reflection, 'foo', 123, 'bar', 456);
$this->assertInstanceOf('Doctrine\\Instantiator\\Exception\\UnexpectedValueException', $exception);
$this->assertSame(
'Could not produce an instance of "DoctrineTest\\InstantiatorTestAsset\\AbstractClassAsset" '
. 'via un-serialization, since an error was triggered in file "bar" at line "456"',
$exception->getMessage()
);
$previous = $exception->getPrevious();
$this->assertInstanceOf('Exception', $previous);
$this->assertSame('foo', $previous->getMessage());
$this->assertSame(123, $previous->getCode());
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTest;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Doctrine\Instantiator\Instantiator;
use PHPUnit_Framework_TestCase;
use ReflectionClass;
/**
* Tests for {@see \Doctrine\Instantiator\Instantiator}
*
* @author Marco Pivetta <ocramius@gmail.com>
*
* @covers \Doctrine\Instantiator\Instantiator
*/
class InstantiatorTest extends PHPUnit_Framework_TestCase
{
/**
* @var Instantiator
*/
private $instantiator;
/**
* {@inheritDoc}
*/
protected function setUp()
{
$this->instantiator = new Instantiator();
}
/**
* @param string $className
*
* @dataProvider getInstantiableClasses
*/
public function testCanInstantiate($className)
{
$this->assertInstanceOf($className, $this->instantiator->instantiate($className));
}
/**
* @param string $className
*
* @dataProvider getInstantiableClasses
*/
public function testInstantiatesSeparateInstances($className)
{
$instance1 = $this->instantiator->instantiate($className);
$instance2 = $this->instantiator->instantiate($className);
$this->assertEquals($instance1, $instance2);
$this->assertNotSame($instance1, $instance2);
}
public function testExceptionOnUnSerializationException()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped(
'As of facebook/hhvm#3432, HHVM has no PDORow, and therefore '
. ' no internal final classes that cannot be instantiated'
);
}
$className = 'DoctrineTest\\InstantiatorTestAsset\\UnserializeExceptionArrayObjectAsset';
if (\PHP_VERSION_ID >= 50600) {
$className = 'PDORow';
}
if (\PHP_VERSION_ID === 50429 || \PHP_VERSION_ID === 50513) {
$className = 'DoctrineTest\\InstantiatorTestAsset\\SerializableArrayObjectAsset';
}
$this->setExpectedException('Doctrine\\Instantiator\\Exception\\UnexpectedValueException');
$this->instantiator->instantiate($className);
}
public function testNoticeOnUnSerializationException()
{
if (\PHP_VERSION_ID >= 50600) {
$this->markTestSkipped(
'PHP 5.6 supports `ReflectionClass#newInstanceWithoutConstructor()` for some internal classes'
);
}
try {
$this->instantiator->instantiate('DoctrineTest\\InstantiatorTestAsset\\WakeUpNoticesAsset');
$this->fail('No exception was raised');
} catch (UnexpectedValueException $exception) {
$wakeUpNoticesReflection = new ReflectionClass('DoctrineTest\\InstantiatorTestAsset\\WakeUpNoticesAsset');
$previous = $exception->getPrevious();
$this->assertInstanceOf('Exception', $previous);
// in PHP 5.4.29 and PHP 5.5.13, this case is not a notice, but an exception being thrown
if (! (\PHP_VERSION_ID === 50429 || \PHP_VERSION_ID === 50513)) {
$this->assertSame(
'Could not produce an instance of "DoctrineTest\\InstantiatorTestAsset\WakeUpNoticesAsset" '
. 'via un-serialization, since an error was triggered in file "'
. $wakeUpNoticesReflection->getFileName() . '" at line "36"',
$exception->getMessage()
);
$this->assertSame('Something went bananas while un-serializing this instance', $previous->getMessage());
$this->assertSame(\E_USER_NOTICE, $previous->getCode());
}
}
}
/**
* @param string $invalidClassName
*
* @dataProvider getInvalidClassNames
*/
public function testInstantiationFromNonExistingClass($invalidClassName)
{
$this->setExpectedException('Doctrine\\Instantiator\\Exception\\InvalidArgumentException');
$this->instantiator->instantiate($invalidClassName);
}
public function testInstancesAreNotCloned()
{
$className = 'TemporaryClass' . uniqid();
eval('namespace ' . __NAMESPACE__ . '; class ' . $className . '{}');
$instance = $this->instantiator->instantiate(__NAMESPACE__ . '\\' . $className);
$instance->foo = 'bar';
$instance2 = $this->instantiator->instantiate(__NAMESPACE__ . '\\' . $className);
$this->assertObjectNotHasAttribute('foo', $instance2);
}
/**
* Provides a list of instantiable classes (existing)
*
* @return string[][]
*/
public function getInstantiableClasses()
{
$classes = array(
array('stdClass'),
array(__CLASS__),
array('Doctrine\\Instantiator\\Instantiator'),
array('Exception'),
array('PharException'),
array('DoctrineTest\\InstantiatorTestAsset\\SimpleSerializableAsset'),
array('DoctrineTest\\InstantiatorTestAsset\\ExceptionAsset'),
array('DoctrineTest\\InstantiatorTestAsset\\FinalExceptionAsset'),
array('DoctrineTest\\InstantiatorTestAsset\\PharExceptionAsset'),
array('DoctrineTest\\InstantiatorTestAsset\\UnCloneableAsset'),
array('DoctrineTest\\InstantiatorTestAsset\\XMLReaderAsset'),
);
if (\PHP_VERSION_ID === 50429 || \PHP_VERSION_ID === 50513) {
return $classes;
}
$classes = array_merge(
$classes,
array(
array('PharException'),
array('ArrayObject'),
array('DoctrineTest\\InstantiatorTestAsset\\ArrayObjectAsset'),
array('DoctrineTest\\InstantiatorTestAsset\\SerializableArrayObjectAsset'),
)
);
if (\PHP_VERSION_ID >= 50600) {
$classes[] = array('DoctrineTest\\InstantiatorTestAsset\\WakeUpNoticesAsset');
$classes[] = array('DoctrineTest\\InstantiatorTestAsset\\UnserializeExceptionArrayObjectAsset');
}
return $classes;
}
/**
* Provides a list of instantiable classes (existing)
*
* @return string[][]
*/
public function getInvalidClassNames()
{
$classNames = array(
array(__CLASS__ . uniqid()),
array('Doctrine\\Instantiator\\InstantiatorInterface'),
array('DoctrineTest\\InstantiatorTestAsset\\AbstractClassAsset'),
);
if (\PHP_VERSION_ID >= 50400) {
$classNames[] = array('DoctrineTest\\InstantiatorTestAsset\\SimpleTraitAsset');
}
return $classNames;
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
/**
* A simple asset for an abstract class
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
abstract class AbstractClassAsset
{
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayObject;
use BadMethodCallException;
/**
* Test asset that extends an internal PHP class
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class ArrayObjectAsset extends ArrayObject
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use Exception;
/**
* Test asset that extends an internal PHP base exception
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class ExceptionAsset extends Exception
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use Exception;
/**
* Test asset that extends an internal PHP base exception
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
final class FinalExceptionAsset extends Exception
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use Phar;
/**
* Test asset that extends an internal PHP class
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class PharAsset extends Phar
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use PharException;
/**
* Test asset that extends an internal PHP class
* This class should be serializable without problems
* and without getting the "Erroneous data format for unserializing"
* error
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class PharExceptionAsset extends PharException
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayObject;
use BadMethodCallException;
use Serializable;
/**
* Serializable test asset that also extends an internal class
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class SerializableArrayObjectAsset extends ArrayObject implements Serializable
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
/**
* {@inheritDoc}
*/
public function serialize()
{
return '';
}
/**
* {@inheritDoc}
*
* Should not be called
*
* @throws BadMethodCallException
*/
public function unserialize($serialized)
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use Serializable;
/**
* Base serializable test asset
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class SimpleSerializableAsset implements Serializable
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
/**
* {@inheritDoc}
*/
public function serialize()
{
return '';
}
/**
* {@inheritDoc}
*
* Should not be called
*
* @throws BadMethodCallException
*/
public function unserialize($serialized)
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
/**
* A simple trait with no attached logic
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
trait SimpleTraitAsset
{
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
/**
* Base un-cloneable asset
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class UnCloneableAsset
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
/**
* Magic `__clone` - should not be invoked
*
* @throws BadMethodCallException
*/
public function __clone()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayObject;
use BadMethodCallException;
/**
* A simple asset for an abstract class
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class UnserializeExceptionArrayObjectAsset extends ArrayObject
{
/**
* {@inheritDoc}
*/
public function __wakeup()
{
throw new BadMethodCallException();
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayObject;
/**
* A simple asset for an abstract class
*
* @author Marco Pivetta <ocramius@gmail.com>
*/
class WakeUpNoticesAsset extends ArrayObject
{
/**
* Wakeup method called after un-serialization
*/
public function __wakeup()
{
trigger_error('Something went bananas while un-serializing this instance');
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use XMLReader;
/**
* Test asset that extends an internal PHP class
*
* @author Dave Marshall <dave@atst.io>
*/
class XMLReaderAsset extends XMLReader
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
### Summary
<!-- provide a summary here -->
### Versions
<!-- Please provide the versions of PHP as well as `fzaninotto/faker` on which the issue has been observed -->
| | Version |
|:--------------------|:--------|
| PHP | x.y.z |
| `fzaninotto/faker` | x.y.z |
### Self-enclosed code snippet for reproduction
```php
<!-- please replace this with a self-enclosed usage example -->
```
### Expected output
```txt
<!-- please replace this with the expected output of your self-enclosed example -->
```
### Actual output
```txt
<!-- please replace this with the actual output of your self-enclosed example -->
```
language: php
dist: precise
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- nightly
sudo: false
cache:
directories:
- $HOME/.composer/cache
before_script:
- travis_retry composer self-update
- travis_retry composer install --no-interaction --prefer-dist
script: make sniff test
#!/usr/bin/env bash
# The problem is that we do not want to remove the configuration file, just disable it for a few tasks, then enable it
#
# For reference, see
#
# - https://docs.travis-ci.com/user/languages/php#Disabling-preinstalled-PHP-extensions
# - https://docs.travis-ci.com/user/languages/php#Custom-PHP-configuration
config="/home/travis/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini"
function xdebug-disable() {
if [[ -f $config ]]; then
mv $config "$config.bak"
fi
}
function xdebug-enable() {
if [[ -f "$config.bak" ]]; then
mv "$config.bak" $config
fi
}
Contributing
============
If you've written a new formatter, adapted Faker to a new locale, or fixed a bug, your contribution is welcome!
Before proposing a pull request, check the following:
* Your code should follow the [PSR-2 coding standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). Run `make sniff` to check that the coding standards are followed, and use [php-cs-fixer](https://github.com/fabpot/PHP-CS-Fixer) to fix inconsistencies.
* Unit tests should still pass after your patch. Run the tests on your dev server (with `make test`) or check the continuous integration status for your pull request.
* As much as possible, add unit tests for your code
* Never use `rand()` in your providers. Faker uses the Mersenne Twister Randomizer, so use `mt_rand()` or any of the base generators (`randomNumber`, `randomElement`, etc.) instead.
* If you add new providers (or new locales) and that they embed a lot of data for random generation (e.g. first names in a new language), please add a `@link` to the reference you used for this list (example [in the ru_RU locale](https://github.com/fzaninotto/Faker/blob/master/src/Faker/Provider/ru_RU/Person.php#L13)). This will ease future updates of the list and debates about the most relevant data for this provider.
* If you add long list of random data, please split the list into several lines. This makes diffs easier to read, and facilitates core review.
* If you add new formatters, please include documentation for it in the README. Don't forget to add a line about new formatters in the `@property` or `@method` phpDoc entries in [Generator.php](https://github.com/fzaninotto/Faker/blob/master/src/Faker/Generator.php#L6-L118) to help IDEs auto-complete your formatters.
* If your new formatters are specific to a certain locale, document them in the [Language-specific formatters](https://github.com/fzaninotto/Faker#language-specific-formatters) list instead.
* Avoid changing existing sets of data. Some developers use Faker with seeding for unit tests ; changing the data makes their tests fail.
* Speed is important in all Faker usages. Make sure your code is optimized to generate thousands of fake items in no time, without consuming too much memory or CPU.
* If you commit a new feature, be prepared to help maintaining it. Watch the project on GitHub, and please comment on issues or PRs regarding the feature you contributed.
Once your code is merged, it is available for free to everybody under the MIT License. Publishing your Pull Request on the Faker GitHub repository means that you agree with this license for your contribution.
Thank you for your contribution! Faker wouldn't be so great without you.
vendor/autoload.php:
composer install --no-interaction --prefer-dist
.PHONY: sniff
sniff: vendor/autoload.php
vendor/bin/phpcs --standard=PSR2 src -n
.PHONY: test
test: vendor/autoload.php
vendor/bin/phpunit --verbose
......@@ -2,7 +2,11 @@
"name": "fzaninotto/faker",
"type": "library",
"description": "Faker is a PHP library that generates fake data for you.",
"keywords": ["faker", "fixtures", "data"],
"keywords": [
"faker",
"fixtures",
"data"
],
"license": "MIT",
"authors": [
{
......@@ -13,9 +17,9 @@
"php": "^5.3.3 || ^7.0"
},
"require-dev": {
"ext-intl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7",
"squizlabs/php_codesniffer": "^1.5",
"ext-intl": "*"
"squizlabs/php_codesniffer": "^2.9.2"
},
"autoload": {
"psr-4": {
......@@ -29,7 +33,10 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.8-dev"
"dev-master": "1.9-dev"
}
},
"config": {
"sort-packages": true
}
}
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Faker Test Suite">
<directory>./test/Faker/</directory>
</testsuite>
</testsuites>
</phpunit>
<?php
namespace Faker\Calculator;
/**
* Utility class for validating EAN-8 and EAN-13 numbers
*
* @package Faker\Calculator
*/
class Ean
{
/** @var string EAN validation pattern */
const PATTERN = '/^(?:\d{8}|\d{13})$/';
/**
* Computes the checksum of an EAN number.
*
* @see https://en.wikipedia.org/wiki/International_Article_Number
*
* @param string $digits
* @return int
*/
public static function checksum($digits)
{
$length = strlen($digits);
$even = 0;
for ($i = $length - 1; $i >= 0; $i -= 2) {
$even += $digits[$i];
}
$odd = 0;
for ($i = $length - 2; $i >= 0; $i -= 2) {
$odd += $digits[$i];
}
return (10 - ((3 * $even + $odd) % 10)) % 10;
}
/**
* Checks whether the provided number is an EAN compliant number and that
* the checksum is correct.
*
* @param string $ean An EAN number
* @return boolean
*/
public static function isValid($ean)
{
if (!preg_match(self::PATTERN, $ean)) {
return false;
}
return self::checksum(substr($ean, 0, -1)) === intval(substr($ean, -1));
}
}
......@@ -24,10 +24,10 @@ class Luhn
$length = strlen($number);
$sum = 0;
for ($i = $length - 1; $i >= 0; $i -= 2) {
$sum += $number{$i};
$sum += $number[$i];
}
for ($i = $length - 2; $i >= 0; $i -= 2) {
$sum += array_sum(str_split($number{$i} * 2));
$sum += array_sum(str_split($number[$i] * 2));
}
return $sum % 10;
......
......@@ -21,8 +21,10 @@ namespace Faker;
* @property string $city
* @property string $streetName
* @property string $streetAddress
* @property string $secondaryAddress
* @property string $postcode
* @property string $address
* @property string $state
* @property string $country
* @property float $latitude
* @property float $longitude
......@@ -33,6 +35,7 @@ namespace Faker;
* @property string $isbn10
*
* @property string $phoneNumber
* @property string $e164PhoneNumber
*
* @property string $company
* @property string $companySuffix
......@@ -52,6 +55,7 @@ namespace Faker;
* @property string $word
* @property string|array $words
* @method string|array words($nb = 3, $asText = false)
* @method string word()
* @property string $sentence
* @method string sentence($nbWords = 6, $variableNbWords = true)
* @property string|array $sentences
......@@ -113,7 +117,7 @@ namespace Faker;
* @method string year($max = 'now')
* @method \DateTime dateTime($max = 'now', $timezone = null)
* @method \DateTime dateTimeAd($max = 'now', $timezone = null)
* @method \DateTime dateTimeBetween($startDate = '-30 years', $endDate = 'now')
* @method \DateTime dateTimeBetween($startDate = '-30 years', $endDate = 'now', $timezone = null)
* @method \DateTime dateTimeInInterval($date = '-30 years', $interval = '+5 days', $timezone = null)
* @method \DateTime dateTimeThisCentury($max = 'now', $timezone = null)
* @method \DateTime dateTimeThisDecade($max = 'now', $timezone = null)
......@@ -132,6 +136,7 @@ namespace Faker;
* @method boolean boolean($chanceOfGettingTrue = 50)
*
* @property int $randomDigit
* @property int $randomDigitNot
* @property int $randomDigitNotNull
* @property string $randomLetter
* @property string $randomAscii
......@@ -154,6 +159,7 @@ namespace Faker;
* @method Generator optional($weight = 0.5, $default = null)
* @method Generator unique($reset = false, $maxRetries = 10000)
* @method Generator valid($validator = null, $maxRetries = 10000)
* @method mixed passthrough($passthrough)
*
* @method integer biasedNumberBetween($min = 0, $max = 100, $function = 'sqrt')
*
......@@ -278,4 +284,9 @@ class Generator
{
return $this->format($method, $attributes);
}
public function __destruct()
{
$this->seed();
}
}
......@@ -42,7 +42,11 @@ class ColumnTypeGuesser
return $generator->uuid();
};
case 'string':
$columnData = $schema->column($column);
if (method_exists($schema, 'getColumn')) {
$columnData = $schema->getColumn($column);
} else {
$columnData = $schema->column($column);
}
$length = $columnData['length'];
return function () use ($generator, $length) {
return $generator->text($length);
......
......@@ -67,6 +67,12 @@ class ColumnTypeGuesser
return function () use ($generator) {
return $generator->datetime;
};
case 'datetime_immutable':
case 'date_immutable':
case 'time_immutable':
return function () use ($generator) {
return \DateTimeImmutable::createFromMutable($generator->datetime);
};
default:
// no smart way to guess what the user expects here
return null;
......
......@@ -3,6 +3,7 @@
namespace Faker\ORM\Doctrine;
use Doctrine\Common\Persistence\ObjectManager;
use Faker\Generator;
/**
* Service class for populating a database using the Doctrine ORM or ODM.
......@@ -10,20 +11,35 @@ use Doctrine\Common\Persistence\ObjectManager;
*/
class Populator
{
/** @var int */
protected $batchSize;
/** @var Generator */
protected $generator;
/** @var ObjectManager|null */
protected $manager;
/** @var array */
protected $entities = array();
/** @var array */
protected $quantities = array();
/** @var array */
protected $generateId = array();
/**
* @param \Faker\Generator $generator
* Populator constructor.
* @param Generator $generator
* @param ObjectManager|null $manager
* @param int $batchSize
*/
public function __construct(\Faker\Generator $generator, ObjectManager $manager = null)
public function __construct(Generator $generator, ObjectManager $manager = null, $batchSize = 1000)
{
$this->generator = $generator;
$this->manager = $manager;
$this->batchSize = $batchSize;
}
/**
......@@ -55,6 +71,9 @@ class Populator
/**
* Populate the database using all the Entity classes previously added.
*
* Please note that large amounts of data will result in more memory usage since the the Populator will return
* all newly created primary keys after executing.
*
* @param null|EntityManager $entityManager A Doctrine connection object
*
* @return array A list of the inserted PKs
......@@ -72,9 +91,18 @@ class Populator
foreach ($this->quantities as $class => $number) {
$generateId = $this->generateId[$class];
for ($i=0; $i < $number; $i++) {
$insertedEntities[$class][]= $this->entities[$class]->execute($entityManager, $insertedEntities, $generateId);
$insertedEntities[$class][]= $this->entities[$class]->execute(
$entityManager,
$insertedEntities,
$generateId
);
if (count($insertedEntities) % $this->batchSize === 0) {
$entityManager->flush();
$entityManager->clear($class);
}
}
$entityManager->flush();
$entityManager->clear($class);
}
return $insertedEntities;
......
......@@ -141,7 +141,6 @@ class EntityPopulator
foreach ($relations as $relation) {
// We don't need any other relation here.
if ($relation instanceof BelongsTo) {
$fieldName = $relation->localKey();
$entityName = $relation->entityName();
$field = $fields[$fieldName];
......@@ -162,14 +161,12 @@ class EntityPopulator
if (empty($records)) {
return null;
}
$id = $records[mt_rand(0, count($records) - 1)]['id'];
return $id;
return $records[mt_rand(0, count($records) - 1)]['id'];
}
return null;
};
}
}
......
......@@ -173,7 +173,7 @@ class Base
/**
* Returns randomly ordered subsequence of $count elements from a provided array
*
* @param array $array Array to take elements from. Defaults to a-f
* @param array $array Array to take elements from. Defaults to a-c
* @param integer $count Number of elements to take.
* @param boolean $allowDuplicates Allow elements to be picked several times. Defaults to false
* @throws \LengthException When requesting more elements than provided
......@@ -492,7 +492,7 @@ class Base
// All A-F inside of [] become ABCDEF
$regex = preg_replace_callback('/\[([^\]]+)\]/', function ($matches) {
return '[' . preg_replace_callback('/(\w|\d)\-(\w|\d)/', function ($range) {
return implode(range($range[1], $range[2]), '');
return implode('', range($range[1], $range[2]));
}, $matches[1]) . ']';
}, $regex);
// All [ABC] become B (or A or C)
......@@ -590,10 +590,10 @@ class Base
* <code>
* $values = array();
* $evenValidator = function ($digit) {
* return $digit % 2 === 0;
* return $digit % 2 === 0;
* };
* for ($i=0; $i < 10; $i++) {
* $values []= $faker->valid($evenValidator)->randomDigit;
* $values []= $faker->valid($evenValidator)->randomDigit;
* }
* print_r($values); // [0, 4, 8, 4, 2, 6, 0, 8, 8, 6]
* </code>
......
......@@ -26,7 +26,7 @@ class Biased extends Base
$y = mt_rand() / (mt_getrandmax() + 1);
} while (call_user_func($function, $x) < $y);
return floor($x * ($max - $min + 1) + $min);
return (int) floor($x * ($max - $min + 1) + $min);
}
/**
......
......@@ -113,4 +113,31 @@ class Color extends Base
{
return static::randomElement(static::$allColorNames);
}
/**
* @example '340,50,20'
* @return string
*/
public static function hslColor()
{
return sprintf(
'%s,%s,%s',
static::numberBetween(0, 360),
static::numberBetween(0, 100),
static::numberBetween(0, 100)
);
}
/**
* @example array(340, 50, 20)
* @return array
*/
public static function hslColorAsArray()
{
return array(
static::numberBetween(0, 360),
static::numberBetween(0, 100),
static::numberBetween(0, 100)
);
}
}
......@@ -16,6 +16,8 @@ class Company extends Base
/**
* @example 'Acme Ltd'
*
* @return string
*/
public function company()
{
......@@ -26,6 +28,8 @@ class Company extends Base
/**
* @example 'Ltd'
*
* @return string
*/
public static function companySuffix()
{
......@@ -34,6 +38,8 @@ class Company extends Base
/**
* @example 'Job'
*
* @return string
*/
public function jobTitle()
{
......
......@@ -9,7 +9,7 @@ class DateTime extends Base
protected static $defaultTimezone = null;
/**
* @param string|float|int $max
* @param \DateTime|string|float|int $max
* @return int|false
*/
protected static function getMaxTimestamp($max = 'now')
......@@ -147,7 +147,7 @@ class DateTime extends Base
* an interval
* Accepts date string that can be recognized by strtotime().
*
* @param string $date Defaults to 30 years ago
* @param \DateTime|string $date Defaults to 30 years ago
* @param string $interval Defaults to 5 days after
* @param string|null $timezone time zone in which the date time should be set, default to DateTime::$defaultTimezone, if set, otherwise the result of `date_default_timezone_get`
* @example dateTimeInInterval('1999-02-02 11:42:52', '+ 5 days')
......
......@@ -83,14 +83,14 @@ class HtmlLorem extends Base
$this->addRandomAttribute($sibling);
$this->addRandomSubTree($sibling, mt_rand(0, $maxDepth), $maxWidth);
}
};
}
return $root;
}
private function addRandomLeaf(\DOMElement $node)
{
$rand = mt_rand(1, 10);
switch($rand){
switch ($rand) {
case 1:
$this->addRandomP($node);
break;
......@@ -172,7 +172,6 @@ class HtmlLorem extends Base
$node = $element->ownerDocument->createElement($h);
$node->appendChild($text);
$element->appendChild($node);
}
private function addRandomB(\DOMElement $element, $maxLength = 10)
......
......@@ -61,7 +61,7 @@ class Image extends Base
*
* @example '/path/to/dir/13b73edae8443990be1aa8f1a483bc27.jpg'
*/
public static function image($dir = null, $width = 640, $height = 480, $category = null, $fullPath = true, $randomize = true, $word = null)
public static function image($dir = null, $width = 640, $height = 480, $category = null, $fullPath = true, $randomize = true, $word = null, $gray = false)
{
$dir = is_null($dir) ? sys_get_temp_dir() : $dir; // GNU/Linux / OS X / Windows compatible
// Validate directory path
......@@ -75,7 +75,7 @@ class Image extends Base
$filename = $name .'.jpg';
$filepath = $dir . DIRECTORY_SEPARATOR . $filename;
$url = static::imageUrl($width, $height, $category, $randomize, $word);
$url = static::imageUrl($width, $height, $category, $randomize, $word, $gray);
// save file
if (function_exists('curl_exec')) {
......
......@@ -175,7 +175,7 @@ class Internet extends Base
}
$words = $this->generator->words($nbWords);
return join($words, '-');
return join('-', $words);
}
/**
......@@ -233,7 +233,7 @@ class Internet extends Base
}
$transId = 'Any-Latin; Latin-ASCII; NFD; [:Nonspacing Mark:] Remove; NFC;';
if (class_exists('Transliterator') && $transliterator = \Transliterator::create($transId)) {
if (class_exists('Transliterator', false) && $transliterator = \Transliterator::create($transId)) {
$transString = $transliterator->transliterate($string);
} else {
$transString = static::toAscii($string);
......
......@@ -92,7 +92,7 @@ class Lorem extends Base
$words = static::words($nbWords);
$words[0] = ucwords($words[0]);
return implode($words, ' ') . '.';
return implode(' ', $words) . '.';
}
/**
......@@ -131,7 +131,7 @@ class Lorem extends Base
$nbSentences = self::randomizeNbElements($nbSentences);
}
return implode(static::sentences($nbSentences), ' ');
return implode(' ', static::sentences($nbSentences));
}
/**
......@@ -193,7 +193,7 @@ class Lorem extends Base
$text[count($text) - 1] .= '.';
}
return implode($text, '');
return implode('', $text);
}
protected static function randomizeNbElements($nbElements)
......
......@@ -61,28 +61,28 @@ class Miscellaneous extends Base
'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AQ', 'AR',
'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE',
'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ',
'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD',
'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR',
'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM',
'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'FI',
'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF',
'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS',
'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR', 'HT', 'HU',
'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT',
'JE', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN',
'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK',
'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME',
'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ',
'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA',
'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU',
'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM',
'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS',
'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI',
'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV',
'SX', 'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK',
'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA',
'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI',
'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'ZA', 'ZM', 'ZW',
'BR', 'BS', 'BT', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF',
'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU',
'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO',
'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'FI', 'FJ',
'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG',
'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT',
'GU', 'GW', 'GY', 'HK', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE',
'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JE', 'JM',
'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR',
'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS',
'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG',
'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS',
'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE',
'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM',
'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR',
'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW',
'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK',
'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY',
'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM',
'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM',
'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU',
'WF', 'WS', 'YE', 'YT', 'ZA', 'ZM', 'ZW',
);
/**
......@@ -202,7 +202,7 @@ class Miscellaneous extends Base
/**
* @link https://en.wikipedia.org/wiki/ISO_4217
* On date of 2017-07-07
* On date of 2019-09-27
*
* With the following exceptions:
* SVC has been replaced by the USD in 2001: https://en.wikipedia.org/wiki/Salvadoran_col%C3%B3n
......@@ -218,12 +218,12 @@ class Miscellaneous extends Base
'ILS', 'INR', 'IQD', 'IRR', 'ISK', 'JMD', 'JOD', 'JPY', 'KES', 'KGS',
'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', 'KZT', 'LAK', 'LBP', 'LKR',
'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD', 'MMK', 'MNT', 'MOP',
'MRO', 'MUR', 'MVR', 'MWK', 'MXN', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO',
'MRU', 'MUR', 'MVR', 'MWK', 'MXN', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO',
'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN',
'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR', 'SBD', 'SCR', 'SDG',
'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SRD', 'SSP', 'STD', 'SYP', 'SZL',
'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SRD', 'SSP', 'STN', 'SYP', 'SZL',
'THB', 'TJS', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TWD', 'TZS', 'UAH',
'UGX', 'USD', 'UYU', 'UZS', 'VEF', 'VND', 'VUV', 'WST', 'XAF', 'XCD',
'UGX', 'USD', 'UYU', 'UZS', 'VES', 'VND', 'VUV', 'WST', 'XAF', 'XCD',
'XOF', 'XPF', 'YER', 'ZAR', 'ZMW',
);
......
......@@ -21,7 +21,7 @@ abstract class Text extends Base
* @example 'Alice, swallowing down her flamingo, and began by taking the little golden key'
* @param integer $maxNbChars Maximum number of characters the text should contain (minimum: 10)
* @param integer $indexSize Determines how many words are considered for the generation of the next word.
* The minimum is 1, and it produces the higher level of randomness, although the
* The minimum is 1, and it produces a higher level of randomness, although the
* generated text usually doesn't make sense. Higher index sizes (up to 5)
* produce more correct text, at the price of less randomness.
* @return string
......
......@@ -10,7 +10,8 @@ class Uuid extends Base
*/
public static function uuid()
{
// fix for compatibility with 32bit architecture; seed range restricted to 62bit
// fix for compatibility with 32bit architecture; each mt_rand call is restricted to 32bit
// two such calls will cause 64bits of randomness regardless of architecture
$seed = mt_rand(0, 2147483647) . '#' . mt_rand(0, 2147483647);
// Hash the seed and convert to a byte array
......
......@@ -45,7 +45,7 @@ class Company extends \Faker\Provider\Company
$result[] = static::randomElement($word);
}
return join($result, ' ');
return join(' ', $result);
}
/**
......@@ -58,6 +58,6 @@ class Company extends \Faker\Provider\Company
$result[] = static::randomElement($word);
}
return join($result, ' ');
return join(' ', $result);
}
}
......@@ -47,7 +47,7 @@ class Company extends \Faker\Provider\Company
$result[] = static::randomElement($word);
}
return join($result, ' ');
return join(' ', $result);
}
/**
......@@ -60,7 +60,7 @@ class Company extends \Faker\Provider\Company
$result[] = static::randomElement($word);
}
return join($result, ' ');
return join(' ', $result);
}
/**
......
......@@ -24,7 +24,7 @@ class Payment extends \Faker\Provider\Payment
*/
public static function vat($spacedNationalPrefix = true)
{
$prefix = ($spacedNationalPrefix) ? "AT U" : "ATU";
$prefix = $spacedNationalPrefix ? "AT U" : "ATU";
return sprintf("%s%d", $prefix, self::randomNumber(8, true));
}
......
......@@ -31,7 +31,7 @@ class Payment extends \Faker\Provider\Payment
*/
public static function vat($spacedNationalPrefix = true)
{
$prefix = ($spacedNationalPrefix) ? "BG " : "BG";
$prefix = $spacedNationalPrefix ? "BG " : "BG";
return sprintf(
"%s%d%d",
......
......@@ -13,7 +13,18 @@ class Address extends \Faker\Provider\Address
'gasse', 'platz', 'ring', 'straße', 'weg',
);
protected static $postcode = array('####');
// As per https://en.wikipedia.org/wiki/List_of_postal_codes_in_Austria (@todo implement more strict postal code values according to wikipedia)
protected static $postcode = array(
'1###',
'2###',
'3###',
'4###',
'5###',
'6###',
'7###',
'8###',
'9###',
);
protected static $cityNames = array(
'Allentsteig', 'Altheim', 'Althofen', 'Amstetten', 'Ansfelden', 'Attnang-Puchheim',
......
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment