Skip to content

Use Puli discovery #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 30, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.puli/
build/
vendor/
composer.lock
phpspec.yml
phpunit.xml
puli.json

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you not commit the puli.json file by intention? Just like composer.json, this file should usually be committed and distributed with the package.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I generally agree, but this package is supposed to be installed in other packages or an application. There are no bindings or binding types in this package, so only the "lock" functionality would be generated into the json file, which IMO doesn't make sense here, but would make sense in the application.

Why is the package list generated in the json file in the first place? I though the json file is some kind of configuration and I expect it doesn't contain anything else. The generated package list could be part of some kind of lock file, couldn't it?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, makes sense then.

The package list is in there since, at least in principle, Puli is independent of Composer. You could install additional packages manually or generally use Puli without Composer, if that makes sense for your project. So puli.json duplicates some parts of composer.json, however those parts are synchronized by the Composer plugin.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I was thinking about a puli.lock file. In cases like this, a puli.json might not even be necessary in a project/application, only a puli.lock where non-configuration stuff can go. Even if you add stuff manually there, it is rather an "environmental" (aka. project dependent) thing, which depends on external resources, while you might change a configuration based on internal project changes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puli works differently than Composer. There's no need for a lock file in Puli.

You are right that in this case, a puli.json is not needed (but neither is a lock file).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, calling it lock is probably not straightforward and multiple configuration can be confusing. Also, packages for composer are only generated when the composer plugin is installed and it should only be done in an application, am right? With other words: package configuration, like composer packages should only be in an application, but not in reusable packages. Am I correct?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily. If your packages contain integration tests that require f.i. Puli's Discovery service and certain binding types/bindings to be loaded from other packages, then those packages must be loaded into Puli as well, otherwise the binding types/bindings are not found.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Are those packages loaded into the application where the package is installed afterwards? Because I probably don't want integration testing binding in the application where I use the package.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. Thanks for clarification.

7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Change Log


## Unreleased

### Changed

- Use [Puli](http://puli.io) for discovery


## 0.5.0 - 2015-12-25

### Changed
Expand Down
20 changes: 11 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,33 @@
],
"require": {
"php": ">=5.4",
"php-http/message-factory": "^1.0"
"puli/composer-plugin": "1.0.0-beta8",
"puli/discovery": "1.0.0-beta8"
},
"require-dev": {
"php-http/message": "^0.1",
"zendframework/zend-diactoros": "^1.0",
"guzzlehttp/psr7": "^1.0",
"php-http/guzzle6-adapter": "^0.2",
"php-http/httplug": "1.0.0-beta",
"php-http/message-factory": "^1.0",
"puli/cli": "1.0.0-beta9",
"phpspec/phpspec": "^2.4",
"henrikbjorn/phpspec-code-coverage" : "^1.0"
},
"suggest": {
"php-http/utils": "To use Guzzle or Diactoros factories"
},
"autoload": {
"psr-4": {
"Http\\Discovery\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"spec\\Http\\Discovery\\": "spec/"
}
},
"scripts": {
"test": "vendor/bin/phpspec run",
"test-ci": "vendor/bin/phpspec run -c phpspec.yml.ci"
},
"extra": {
"branch-alias": {
"dev-master": "0.5-dev"
"dev-master": "0.6-dev"
}
},
"prefer-stable": true,
Expand Down
170 changes: 45 additions & 125 deletions spec/ClassDiscoverySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,163 +3,83 @@
namespace spec\Http\Discovery;

use Http\Discovery\ClassDiscovery;
use Puli\Discovery\Binding\ClassBinding;
use Puli\GeneratedPuliFactory;
use Puli\Discovery\Api\Discovery;
use Puli\Repository\Api\ResourceRepository;
use PhpSpec\ObjectBehavior;

class ClassDiscoverySpec extends ObjectBehavior
{
function let()
{
$this->beAnInstanceOf('spec\Http\Discovery\DiscoveryStub');
function let(
GeneratedPuliFactory $puliFactory,
ResourceRepository $repository,
Discovery $discovery
) {
$puliFactory->createRepository()->willReturn($repository);
$puliFactory->createDiscovery($repository)->willReturn($discovery);

$this->beAnInstanceOf('spec\Http\Discovery\ClassDiscoveryStub');
$this->setPuliFactory($puliFactory);
}

function it_is_initializable()
function letgo()
{
$this->shouldHaveType('Http\Discovery\ClassDiscovery');
$this->resetPuliFactory();
}

function it_registers_a_class()
function it_is_initializable()
{
$this->reset();

$this->register('spec\Http\Discovery\AnotherClassToFind');

$this->find()->shouldHaveType('spec\Http\Discovery\AnotherClassToFind');
$this->shouldHaveType('Http\Discovery\ClassDiscovery');
}

function it_registers_a_class_with_a_condition()
function it_has_a_puli_factory(GeneratedPuliFactory $puliFactory)
{
$this->reset();

$this->register('spec\Http\Discovery\AnotherClassToFind', 'spec\Http\Discovery\TestClass');
$this->register('spec\Http\Discovery\ClassToFind', false);

$this->find()->shouldHaveType('spec\Http\Discovery\AnotherClassToFind');
$this->getPuliFactory()->shouldReturn($puliFactory);
}

function it_registers_a_class_with_a_callable_condition()
function it_has_a_puli_discovery(Discovery $discovery)
{
$this->reset();

$this->register('spec\Http\Discovery\AnotherClassToFind', function() { return true; });
$this->register('spec\Http\Discovery\ClassToFind', false);

$this->find()->shouldHaveType('spec\Http\Discovery\AnotherClassToFind');
$this->getPuliDiscovery()->shouldReturn($discovery);
}

function it_registers_a_class_with_a_boolean_condition()
function it_throws_an_exception_when_binding_not_found(Discovery $discovery)
{
$this->reset();

$this->register('spec\Http\Discovery\AnotherClassToFind', true);
$this->register('spec\Http\Discovery\ClassToFind', false);
$discovery->findBindings('InvalidBinding')->willReturn([]);

$this->find()->shouldHaveType('spec\Http\Discovery\AnotherClassToFind');
}

function it_registers_a_class_with_an_array_condition()
{
$this->reset();

$this->register(
'spec\Http\Discovery\AnotherClassToFind',
[
true,
'spec\Http\Discovery\AnotherClassToFind',
]
);
$this->register(
'spec\Http\Discovery\ClassToFind',
[
false,
'spec\Http\Discovery\ClassToFind',
]
);

$this->find()->shouldHaveType('spec\Http\Discovery\AnotherClassToFind');
$this->shouldThrow('Http\Discovery\NotFoundException')->duringFindOneByType('InvalidBinding');
}

function it_registers_a_class_with_an_invalid_condition()
function it_returns_a_class_binding(Discovery $discovery, ClassBinding $binding)
{
$this->reset();
$binding->hasParameterValue('depends')->willReturn(false);
$binding->getClassName()->willReturn('ClassName');

$this->register('spec\Http\Discovery\AnotherClassToFind', true);
$this->register('spec\Http\Discovery\ClassToFind', new \stdClass);
$discovery->findBindings('Binding')->willReturn([$binding]);

$this->find()->shouldHaveType('spec\Http\Discovery\AnotherClassToFind');
$this->findOneByType('Binding')->shouldReturn('ClassName');
}

function it_resets_cache_when_a_class_is_registered()
{
$this->reset();
function it_returns_a_class_binding_with_dependency(
Discovery $discovery,
ClassBinding $binding1,
ClassBinding $binding2
) {
$binding1->hasParameterValue('depends')->willReturn(true);
$binding1->getParameterValue('depends')->willReturn(false);

$this->find()->shouldHaveType('spec\Http\Discovery\ClassToFind');
$binding2->hasParameterValue('depends')->willReturn(false);
$binding2->getClassName()->willReturn('ClassName');

$this->register('spec\Http\Discovery\AnotherClassToFind');
$discovery->findBindings('Binding')->willReturn([
$binding1,
$binding2,
]);

$this->find()->shouldHaveType('spec\Http\Discovery\AnotherClassToFind');
}

function it_caches_a_found_class()
{
$this->reset();

$this->find()->shouldHaveType('spec\Http\Discovery\ClassToFind');

$this->registerWithoutCacheReset('spec\Http\Discovery\AnotherClassToFind');

$this->find()->shouldhaveType('spec\Http\Discovery\ClassToFind');
}

function it_throws_an_exception_when_no_class_is_found()
{
$this->resetEmpty();

$this->shouldThrow('Http\Discovery\NotFoundException')->duringFind();
$this->findOneByType('Binding')->shouldReturn('ClassName');
}
}

class DiscoveryStub extends ClassDiscovery
class ClassDiscoveryStub extends ClassDiscovery
{
protected static $cache;

/**
* @var array
*/
protected static $classes;

/**
* Reset classes
*/
public function reset()
{
static::$cache = null;

static::$classes = [
[
'class' => 'spec\Http\Discovery\ClassToFind',
'condition' => 'spec\Http\Discovery\ClassToFind'
],
];
}

public function registerWithoutCacheReset($class, $condition = null)
{
$definition = [
'class' => $class,
'condition' => isset($condition) ? $condition : $class,
];

array_unshift(static::$classes, $definition);
}

public function resetEmpty()
{
static::$cache = null;

static::$classes = [];
}
}

class ClassToFind {}
class AnotherClassToFind {}
class TestClass {}
31 changes: 29 additions & 2 deletions spec/HttpAsyncClientDiscoverySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@

namespace spec\Http\Discovery;

use Puli\GeneratedPuliFactory;
use Puli\Discovery\Api\Discovery;
use Puli\Discovery\Binding\ClassBinding;
use Puli\Repository\Api\ResourceRepository;
use PhpSpec\ObjectBehavior;

class HttpAsyncClientDiscoverySpec extends ObjectBehavior
{
function let(
GeneratedPuliFactory $puliFactory,
ResourceRepository $repository,
Discovery $discovery
) {
$puliFactory->createRepository()->willReturn($repository);
$puliFactory->createDiscovery($repository)->willReturn($discovery);

$this->setPuliFactory($puliFactory);
}

function letgo()
{
$this->resetPuliFactory();
}

function it_is_initializable()
{
$this->shouldHaveType('Http\Discovery\HttpAsyncClientDiscovery');
Expand All @@ -16,8 +36,15 @@ function it_is_a_class_discovery()
$this->shouldHaveType('Http\Discovery\ClassDiscovery');
}

function it_finds_an_http_client()
{
function it_finds_an_async_http_client(
Discovery $discovery,
ClassBinding $binding
) {
$binding->hasParameterValue('depends')->willReturn(false);
$binding->getClassName()->willReturn('spec\Http\Discovery\Stub\HttpAsyncClientStub');

$discovery->findBindings('Http\Client\HttpAsyncClient')->willReturn([$binding]);

$this->find()->shouldImplement('Http\Client\HttpAsyncClient');
}
}
31 changes: 29 additions & 2 deletions spec/HttpClientDiscoverySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@

namespace spec\Http\Discovery;

use Puli\GeneratedPuliFactory;
use Puli\Discovery\Api\Discovery;
use Puli\Discovery\Binding\ClassBinding;
use Puli\Repository\Api\ResourceRepository;
use PhpSpec\ObjectBehavior;

class HttpClientDiscoverySpec extends ObjectBehavior
{
function let(
GeneratedPuliFactory $puliFactory,
ResourceRepository $repository,
Discovery $discovery
) {
$puliFactory->createRepository()->willReturn($repository);
$puliFactory->createDiscovery($repository)->willReturn($discovery);

$this->setPuliFactory($puliFactory);
}

function letgo()
{
$this->resetPuliFactory();
}

function it_is_initializable()
{
$this->shouldHaveType('Http\Discovery\HttpClientDiscovery');
Expand All @@ -16,8 +36,15 @@ function it_is_a_class_discovery()
$this->shouldHaveType('Http\Discovery\ClassDiscovery');
}

function it_finds_an_http_client()
{
function it_finds_an_http_client(
Discovery $discovery,
ClassBinding $binding
) {
$binding->hasParameterValue('depends')->willReturn(false);
$binding->getClassName()->willReturn('spec\Http\Discovery\Stub\HttpClientStub');

$discovery->findBindings('Http\Client\HttpClient')->willReturn([$binding]);

$this->find()->shouldImplement('Http\Client\HttpClient');
}
}
Loading