Skip to content
This repository has been archived by the owner on Oct 28, 2020. It is now read-only.

Commit

Permalink
Merge 827c832 into b175695
Browse files Browse the repository at this point in the history
  • Loading branch information
kbond committed Feb 1, 2016
2 parents b175695 + 827c832 commit 495dc37
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 191 deletions.
31 changes: 8 additions & 23 deletions README.md
Expand Up @@ -9,9 +9,8 @@

Provides a httpcache warmup command for Symfony2. The command simply executes a `GET` request on a list of urls.
One or more url providers must be registered. This bundle requires an implementation of
[php-http/adapter](https://packagist.org/packages/php-http/adapter) and
[php-http/message-factory](https://packagist.org/packages/php-http/message-factory). The bundle will try and
auto-discover these if not configured directly.
[php-http/httplug](https://packagist.org/packages/php-http/httplug) and
[php-http/message-factory](https://packagist.org/packages/php-http/message-factory).

## Installation

Expand All @@ -38,29 +37,15 @@ auto-discover these if not configured directly.

## Configuration

An `http_adapter` (class or service implementing `Http\Adapter\HttpAdapter`) and `message_factory`
An `http_client` (class or service implementing `Http\Client\HttpClient`) and `message_factory`
(class or service implementing `Http\Message\MessageFactory`) must be configured.

```yaml
zenstruck_cache:
http_adapter: Acme\MyHttpAdapter # or a service (acme.my_http_adapter)
http_client: Acme\MyHttpClient # or a service (acme.my_http_client)
message_factory: Acme\MyMessageFactory # or a service (acme.my_message_factory)
```

If left blank, the bundle will try and auto-discover these classes. The following HTTP adapters and
are message factories are currently auto-discoverable:

* [guzzle6-adapter](https://packagist.org/packages/php-http/guzzle6-adapter) (Provides HttpAdapter
and allows discovery of MessageFactory)

composer require php-http/guzzle6-adapter


* [guzzle5-adapter](https://packagist.org/packages/php-http/guzzle5-adapter) (Provides HttpAdapter)
and [guzzlehttp/psr7](https://packagist.org/packages/guzzlehttp/psr7) (allows discovery of MessageFactory)

composer require php-http/guzzle5-adapter guzzlephp/psr7

## HttpCache Warmup Command

Usage:
Expand Down Expand Up @@ -128,11 +113,11 @@ zenstruck_cache:

```yaml
zenstruck_cache:
# Either a class or a service that implements Http\Adapter\HttpAdapter. Leave blank to attempt auto discovery.
http_adapter: ~
# Either a class or a service that implements Http\Client\HttpClient.
http_client: ~ # Required

# Either a class or a service that implements Http\Message\MessageFactory. Leave blank to attempt auto discovery.
message_factory: ~
# Either a class or a service that implements Http\Message\MessageFactory.
message_factory: ~ # Required

sitemap_provider:
enabled: false
Expand Down
21 changes: 10 additions & 11 deletions composer.json
Expand Up @@ -12,20 +12,19 @@
}
],
"require": {
"symfony/framework-bundle": "~2.5|~3.0",
"symfony/console": "~2.5|~3.0",
"php-http/adapter": "~0.1.0",
"php-http/message-factory": "~0.1.0",
"php-http/discovery": "^0.1.1"
"symfony/framework-bundle": "^2.5|^3.0",
"symfony/console": "^2.5|^3.0",
"php-http/httplug": "^1.0",
"php-http/message-factory": "^1.0",
"php-http/client-implementation": "^1.0"
},
"require-dev": {
"symfony/dom-crawler": "~2.5|~3.0",
"symfony/css-selector": "~2.5|~3.0",
"phpunit/phpunit": "^4.8.16",
"symfony/dom-crawler": "^2.5|^3.0",
"symfony/css-selector": "^2.5|^3.0",
"matthiasnoback/symfony-dependency-injection-test": "^0.7.4",
"php-http/guzzle5-adapter": "~0.1.0",
"guzzlehttp/psr7": "~1.0",
"sllh/php-cs-fixer-styleci-bridge": "~1.4"
"php-http/guzzle5-adapter": "^0.4@dev",
"guzzlehttp/psr7": "^1.0",
"sllh/php-cs-fixer-styleci-bridge": "^1.4"
},
"autoload": {
"psr-4": { "Zenstruck\\CacheBundle\\": "src/" }
Expand Down
10 changes: 5 additions & 5 deletions src/DependencyInjection/Configuration.php
Expand Up @@ -17,13 +17,13 @@ public function getConfigTreeBuilder()

$rootNode
->children()
->scalarNode('http_adapter')
->info('Either a class or a service that implements Http\Adapter\HttpAdapter. Leave blank to attempt auto discovery.')
->defaultNull()
->scalarNode('http_client')
->info('Either a class or a service that implements Http\Client\HttpClient.')
->isRequired()
->end()
->scalarNode('message_factory')
->info('Either a class or a service that implements Http\Message\MessageFactory. Leave blank to attempt auto discovery.')
->defaultNull()
->info('Either a class or a service that implements Http\Message\MessageFactory.')
->isRequired()
->end()
->arrayNode('sitemap_provider')
->canBeEnabled()
Expand Down
59 changes: 14 additions & 45 deletions src/DependencyInjection/ZenstruckCacheExtension.php
Expand Up @@ -2,9 +2,6 @@

namespace Zenstruck\CacheBundle\DependencyInjection;

use Http\Discovery\HttpAdapterDiscovery;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Discovery\NotFoundException;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand All @@ -25,7 +22,7 @@ protected function loadInternal(array $mergedConfig, ContainerBuilder $container
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.xml');

$this->configureHttpAdapter($mergedConfig['http_adapter'], $container);
$this->configureHttpClient($mergedConfig['http_client'], $container);
$this->configureMessageFactory($mergedConfig['message_factory'], $container);

if ($mergedConfig['sitemap_provider']['enabled']) {
Expand All @@ -35,47 +32,43 @@ protected function loadInternal(array $mergedConfig, ContainerBuilder $container
}

/**
* @param string|null $httpAdapter
* @param string $httpClient
* @param ContainerBuilder $container
*/
private function configureHttpAdapter($httpAdapter, ContainerBuilder $container)
private function configureHttpClient($httpClient, ContainerBuilder $container)
{
$httpAdapter = $httpAdapter ?: $this->autoDiscoverHttpAdapter();

if (!class_exists($httpAdapter)) {
if (!class_exists($httpClient)) {
// is a service
$container->setAlias('zenstruck_cache.http_adapter', $httpAdapter);
$container->setAlias('zenstruck_cache.http_client', $httpClient);

return;
}

$r = new \ReflectionClass($httpAdapter);
$r = new \ReflectionClass($httpClient);

if (!$r->implementsInterface('Http\Adapter\HttpAdapter')) {
throw new InvalidConfigurationException('HttpAdapter class must implement "Http\Adapter\HttpAdapter".');
if (!$r->implementsInterface('Http\Client\HttpClient')) {
throw new InvalidConfigurationException('HttpClient class must implement "Http\Client\HttpClient".');
}

if ($r->isAbstract()) {
throw new InvalidConfigurationException('HttpAdapter class must not be abstract.');
throw new InvalidConfigurationException('HttpClient class must not be abstract.');
}

if (null !== $r->getConstructor() && 0 !== $r->getConstructor()->getNumberOfRequiredParameters()) {
throw new InvalidConfigurationException('HttpAdapter class must not have required constructor arguments.');
throw new InvalidConfigurationException('HttpClient class must not have required constructor arguments.');
}

$httpAdapter = new Definition($httpAdapter);
$httpAdapter->setPublic(false);
$container->setDefinition('zenstruck_cache.http_adapter', $httpAdapter);
$httpClient = new Definition($httpClient);
$httpClient->setPublic(false);
$container->setDefinition('zenstruck_cache.http_client', $httpClient);
}

/**
* @param string|null $messageFactory
* @param string $messageFactory
* @param ContainerBuilder $container
*/
private function configureMessageFactory($messageFactory, ContainerBuilder $container)
{
$messageFactory = $messageFactory ?: $this->autoDiscoverMessageFactory();

if (!class_exists($messageFactory)) {
// is a service
$container->setAlias('zenstruck_cache.message_factory', $messageFactory);
Expand All @@ -101,28 +94,4 @@ private function configureMessageFactory($messageFactory, ContainerBuilder $cont
$messageFactory->setPublic(false);
$container->setDefinition('zenstruck_cache.message_factory', $messageFactory);
}

/**
* @return string
*/
private function autoDiscoverHttpAdapter()
{
try {
return get_class(HttpAdapterDiscovery::find());
} catch (NotFoundException $e) {
throw new InvalidConfigurationException('A HttpAdapter was not found, please define one in your configuration.', 0, $e);
}
}

/**
* @return string
*/
private function autoDiscoverMessageFactory()
{
try {
return get_class(MessageFactoryDiscovery::find());
} catch (NotFoundException $e) {
throw new InvalidConfigurationException('A MessageFactory was not found, please define one in your configuration.', 0, $e);
}
}
}
2 changes: 1 addition & 1 deletion src/Resources/config/services.xml
Expand Up @@ -10,7 +10,7 @@

<services>
<service id="zenstruck_cache.crawler" class="%zenstruck_cache.crawler.class%">
<argument type="service" id="zenstruck_cache.http_adapter" />
<argument type="service" id="zenstruck_cache.http_client" />
<argument type="service" id="zenstruck_cache.message_factory" />
<argument type="service" id="logger" on-invalid="null" />
<tag name="monolog.logger" channel="httpcache_warmup" />
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/config/sitemap_provider.xml
Expand Up @@ -11,7 +11,7 @@
<services>
<service id="zenstruck_cache.sitemap_provider" class="%zenstruck_cache.sitemap_provider.class%" public="false">
<argument>%zenstruck_cache.sitemap_provider.sitemaps%</argument>
<argument type="service" id="zenstruck_cache.http_adapter" />
<argument type="service" id="zenstruck_cache.http_client" />
<argument type="service" id="zenstruck_cache.message_factory" />
<tag name="zenstruck_cache.url_provider" />
</service>
Expand Down
18 changes: 7 additions & 11 deletions src/Url/Crawler.php
Expand Up @@ -2,7 +2,7 @@

namespace Zenstruck\CacheBundle\Url;

use Http\Adapter\HttpAdapter;
use Http\Client\HttpClient;
use Http\Message\MessageFactory;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
Expand All @@ -13,20 +13,20 @@
*/
class Crawler implements \Countable
{
private $httpAdapter;
private $httpClient;
private $messageFactory;
private $logger;
private $urlProviders;

/**
* @param HttpAdapter $httpAdapter
* @param HttpClient $httpClient
* @param MessageFactory $messageFactory
* @param LoggerInterface $logger
* @param UrlProvider[] $urlProviders
*/
public function __construct(HttpAdapter $httpAdapter, MessageFactory $messageFactory, LoggerInterface $logger = null, array $urlProviders = [])
public function __construct(HttpClient $httpClient, MessageFactory $messageFactory, LoggerInterface $logger = null, array $urlProviders = [])
{
$this->httpAdapter = $httpAdapter;
$this->httpClient = $httpClient;
$this->messageFactory = $messageFactory;
$this->logger = $logger;
$this->urlProviders = $urlProviders;
Expand Down Expand Up @@ -57,14 +57,10 @@ public function count()
/**
* @param callable $callback Response as first argument, calling URL as second
*/
public function crawl($callback = null)
public function crawl(callable $callback = null)
{
if (null !== $callback && !is_callable($callback)) {
throw new \InvalidArgumentException('Valid callback required.');
}

foreach ($this->getUrls() as $url) {
$response = $this->httpAdapter->sendRequest($this->messageFactory->createRequest('GET', $url));
$response = $this->httpClient->sendRequest($this->messageFactory->createRequest('GET', $url));

$this->log($response, $url);

Expand Down
13 changes: 6 additions & 7 deletions src/Url/SitemapUrlProvider.php
Expand Up @@ -2,7 +2,7 @@

namespace Zenstruck\CacheBundle\Url;

use Http\Adapter\HttpAdapter;
use Http\Client\HttpClient;
use Http\Message\MessageFactory;
use Symfony\Component\DomCrawler\Crawler as DomCrawler;

Expand All @@ -12,23 +12,22 @@
class SitemapUrlProvider implements UrlProvider
{
private $sitemaps;
private $httpAdapter;
private $httpClient;
private $messageFactory;
private $urls;

/**
* @param array $sitemaps
* @param HttpAdapter $httpAdapter
* @param HttpClient $httpClient
* @param MessageFactory $messageFactory
*/
public function __construct(array $sitemaps, HttpAdapter $httpAdapter, MessageFactory $messageFactory)
public function __construct(array $sitemaps, HttpClient $httpClient, MessageFactory $messageFactory)
{
if (!class_exists('Symfony\\Component\\DomCrawler\\Crawler')) {
throw new \RuntimeException('symfony/dom-crawler and symfony/css-selector must be installed to use SitemapUrlProvider.');
}

$this->sitemaps = $sitemaps;
$this->httpAdapter = $httpAdapter;
$this->httpClient = $httpClient;
$this->messageFactory = $messageFactory;
}

Expand Down Expand Up @@ -99,7 +98,7 @@ private function tryDefaultSitemapUrls($host)
*/
private function parseUrl($url)
{
$response = $this->httpAdapter->sendRequest($this->messageFactory->createRequest('GET', $url));
$response = $this->httpClient->sendRequest($this->messageFactory->createRequest('GET', $url));

if (200 !== $response->getStatusCode()) {
return [];
Expand Down
10 changes: 5 additions & 5 deletions tests/Command/HttpCacheWarmupCommandTest.php
Expand Up @@ -46,26 +46,26 @@ public function testExecute()
->with('GET', 'baz.com')
->willReturn($request);

$httpAdapter = $this->mockHttpAdapter();
$httpAdapter
$httpClient = $this->mockHttpClient();
$httpClient
->expects($this->at(0))
->method('sendRequest')
->with($request)
->willReturn($this->mockResponse('', 200));

$httpAdapter
$httpClient
->expects($this->at(1))
->method('sendRequest')
->with($request)
->willReturn($this->mockResponse('', 200));

$httpAdapter
$httpClient
->expects($this->at(2))
->method('sendRequest')
->with($request)
->willReturn($this->mockResponse('', 404));

$crawler = new Crawler($httpAdapter, $messageFactory, null, [$provider]);
$crawler = new Crawler($httpClient, $messageFactory, null, [$provider]);

$application = new Application();
$application->add($this->createCommand($crawler));
Expand Down

0 comments on commit 495dc37

Please sign in to comment.