Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
950c942
Moved provider tag from ProviderResource -> ImportSpecification.
Bilge Mar 17, 2017
b63a1e3
Refactored Porter to no longer be a repository of providers.
Bilge Jun 19, 2017
18f2758
Removed connector implementations from required packages.
Bilge Jun 21, 2017
456f521
Merge branch 'provider-tag-refactor' into 4.0
Bilge Jul 3, 2017
10b4bff
Merge branch 'remove-provider-tags' into 4.0
Bilge Jul 3, 2017
a4c52d3
Merge branch 'remove-connectors' into 4.0
Bilge Jul 3, 2017
557d694
Removed abstract provider.
Bilge Jul 4, 2017
c342d69
Added test case for importing foreign resource.
Bilge Jul 5, 2017
02a8131
Cloned ProviderOptions on import and added test case.
Bilge Jul 10, 2017
870d742
Added ConnectionContext and accompanying factory to fix caching and d…
Bilge Jul 12, 2017
b73f862
Fixed all tests pertaining to the addition of ConnectionContext and S…
Bilge Jul 13, 2017
6b0f016
Changed code coverage provider Coveralls -> Codecov.
Bilge Jul 15, 2017
5800e70
Added SuperConnector unit test.
Bilge Jul 16, 2017
e57f44f
Changed CachingConnector from abstract to concrete connector decorator.
Bilge Jul 22, 2017
b98eae5
Expanded Porter docblocks.
Bilge Jul 23, 2017
e754328
Fixed tests, and in particular, CachingConnectorTest.
Bilge Oct 25, 2017
22af158
Added ImportConnectorTest.
Bilge Oct 25, 2017
45bbb18
Fixed ImportSpecification method parameter naming.
Bilge Oct 25, 2017
61f6432
Added and updated docblocks for Connector and ConnectionContext.
Bilge Oct 26, 2017
653774c
Fixed mapping transformer package name in suggested packages.
Bilge Nov 10, 2017
0a80812
Removed EncapsulatedOptions parameter from Connector::fetch method.
Bilge Mar 30, 2018
6338dd5
Added ImportConnector::getWrappedConnector method so resources can co…
Bilge Mar 31, 2018
91ecee9
Removed ConnectorOptionsTrait.
Bilge Mar 31, 2018
c660577
Added provider fetch exception handler to ImportConnector.
Bilge Apr 2, 2018
1bae9b7
Moved ObjectType/StringType and accompanying tests to separate reposi…
Bilge Apr 3, 2018
3fd8a02
Added FetchExceptionHandler interface.
Bilge Apr 3, 2018
9c8af41
Finalized FetchExceptionHandler interface and added accompanying test.
Bilge Apr 4, 2018
76d3909
Added StatelessFetchExceptionHandler cloning optimization in Connecti…
Bilge Apr 5, 2018
e8e88d3
Changed ImportSpecification::setMaxFetchAttempts to throw exception i…
Bilge Apr 5, 2018
049e80e
Added StatelessFetchExceptionHandler test just for coverage.
Bilge Apr 5, 2018
54d9a3d
Changed StatelessFetchExceptionHandler to be non-final so inheritors can
Bilge Apr 5, 2018
07a2445
Added initial delay constructor parameter to ExponentialSleepFetchExc…
Bilge Apr 5, 2018
86d34a5
Added ConnectorWrapper interface.
Bilge Apr 8, 2018
821d2bd
Added test for ImportConnector::findBaseConnector.
Bilge Apr 8, 2018
23930ab
Changed RecordCollection to force array return type.
Bilge Apr 8, 2018
40c2815
Rewrote 4K word manual for 4.0 release.
Bilge Apr 9, 2018
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
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ php:
- 5.6
- 7.0
- 7.1
- 7.2

env:
matrix:
Expand All @@ -21,7 +22,7 @@ matrix:

cache:
directories:
- .composer/cache
- vendor

install:
- alias composer=composer\ -n && composer selfupdate
Expand All @@ -32,5 +33,4 @@ script:
- composer test -- --coverage-clover=build/logs/clover.xml

after_success:
- composer require satooshi/php-coveralls
- vendor/bin/coveralls -v
- bash <(curl -s https://codecov.io/bash)
323 changes: 200 additions & 123 deletions README.md

Large diffs are not rendered by default.

14 changes: 4 additions & 10 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,19 @@
"license": "LGPL-3.0",
"require": {
"php": "^5.5|^7",
"connectors/http": "^1",
"connectors/soap": "^1",
"scriptfusion/static-class": "^1",
"scriptfusion/retry": "^1.1",
"scriptfusion/retry-exception-handlers": "^1",
"eloquent/enumeration": "^5",
"scriptfusion/retry-exception-handlers": "^1.1",
"psr/container": "^1",
"psr/cache": "^1"
},
"require-dev": {
"phpunit/phpunit": "^4.8",
"mockery/mockery": "^0.9.4"
},
"suggest" : {
"transformers/mapping": "Transforms array collections using Mappings."
"connectors/http": "Provides an HTTP connector for Porter providers.",
"transformers/mapping-transformer": "Transforms records using Mappings."
},
"autoload": {
"psr-4": {
Expand All @@ -37,10 +36,5 @@
},
"scripts": {
"test": "phpunit -c test"
},
"extra": {
"branch-alias": {
"dev-master": "3-dev"
}
}
}
35 changes: 0 additions & 35 deletions src/Cache/CacheAdvice.php

This file was deleted.

2 changes: 2 additions & 0 deletions src/Cache/CacheKeyGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

interface CacheKeyGenerator
{
const RESERVED_CHARACTERS = '{}()/\@:';

/**
* @param string $source
* @param array $sortedOptions Options sorted by key.
Expand Down
29 changes: 0 additions & 29 deletions src/Cache/CacheToggle.php

This file was deleted.

6 changes: 3 additions & 3 deletions src/Cache/CacheUnavailableException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
/**
* The exception that is thrown when cache is unavailable.
*/
class CacheUnavailableException extends \RuntimeException implements CacheException
final class CacheUnavailableException extends \RuntimeException implements CacheException
{
public static function modify()
public static function createUnsupported()
{
return new self('Cannot modify cache: cache unavailable.');
return new self('Cannot cache: connector does not support caching.');
}
}
4 changes: 1 addition & 3 deletions src/Cache/JsonCacheKeyGenerator.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
<?php
namespace ScriptFUSION\Porter\Cache;

use ScriptFUSION\Porter\Connector\CachingConnector;

class JsonCacheKeyGenerator implements CacheKeyGenerator
{
public function generateCacheKey($source, array $sortedOptions)
{
return str_replace(
str_split(CachingConnector::RESERVED_CHARACTERS),
str_split(self::RESERVED_CHARACTERS),
'.',
json_encode([$source, $sortedOptions], JSON_UNESCAPED_SLASHES)
);
Expand Down
26 changes: 24 additions & 2 deletions src/Collection/RecordCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,54 @@ abstract class RecordCollection implements \Iterator

private $previousCollection;

public function __construct(\Iterator $records, RecordCollection $previousCollection = null)
public function __construct(\Iterator $records, self $previousCollection = null)
{
$this->records = $records;
$this->previousCollection = $previousCollection;
}

/**
* @return array
*/
public function current()
{
return $this->records->current();
$current = $this->records->current();

// TODO: Consider removing when dropping PHP 5 support (replace with type hint).
if (!is_array($current)) {
throw new \RuntimeException('Record collection did not return an array.');
}

return $current;
}

/**
* @return void
*/
public function next()
{
$this->records->next();
}

/**
* @return mixed
*/
public function key()
{
return $this->records->key();
}

/**
* @return bool
*/
public function valid()
{
return $this->records->valid();
}

/**
* @return void
*/
public function rewind()
{
$this->records->rewind();
Expand Down
96 changes: 35 additions & 61 deletions src/Connector/CachingConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,127 +3,101 @@

use Psr\Cache\CacheItemPoolInterface;
use ScriptFUSION\Porter\Cache\CacheKeyGenerator;
use ScriptFUSION\Porter\Cache\CacheToggle;
use ScriptFUSION\Porter\Cache\InvalidCacheKeyException;
use ScriptFUSION\Porter\Cache\JsonCacheKeyGenerator;
use ScriptFUSION\Porter\Cache\MemoryCache;
use ScriptFUSION\Porter\Options\EncapsulatedOptions;

/**
* Caches remote data using PSR-6-compliant objects.
* Wraps a connector to cache fetched data using PSR-6-compliant objects.
*/
abstract class CachingConnector implements Connector, CacheToggle
class CachingConnector implements Connector, ConnectorWrapper
{
const RESERVED_CHARACTERS = '{}()/\@:';

/**
* @var CacheItemPoolInterface
* @var Connector
*/
private $cache;
private $connector;

/**
* @var bool
* @var CacheItemPoolInterface
*/
private $cacheEnabled = true;
private $cache;

/**
* @var CacheKeyGenerator
*/
private $cacheKeyGenerator;

public function __construct(CacheItemPoolInterface $cache = null, CacheKeyGenerator $cacheKeyGenerator = null)
{
public function __construct(
Connector $connector,
CacheItemPoolInterface $cache = null,
CacheKeyGenerator $cacheKeyGenerator = null
) {
$this->connector = $connector;
$this->cache = $cache ?: new MemoryCache;
$this->cacheKeyGenerator = $cacheKeyGenerator ?: new JsonCacheKeyGenerator;
}

public function __clone()
{
$this->connector = clone $this->connector;

/* It doesn't make sense to clone the cache because we want cache state to be shared between imports.
We're also not cloning the CacheKeyGenerator because they're expected to be stateless algorithms. */
}

/**
* @param ConnectionContext $context
* @param string $source
* @param EncapsulatedOptions|null $options
*
* @return mixed
*
* @throws InvalidCacheKeyException
*/
public function fetch($source, EncapsulatedOptions $options = null)
public function fetch(ConnectionContext $context, $source)
{
if ($this->isCacheEnabled()) {
$optionsCopy = $options ? $options->copy() : [];

ksort($optionsCopy);
if ($context->mustCache()) {
$options = $this->connector instanceof ConnectorOptions ? $this->connector->getOptions()->copy() : [];
ksort($options);

$key = $this->validateCacheKey($this->getCacheKeyGenerator()->generateCacheKey($source, $optionsCopy));
$this->validateCacheKey($key = $this->cacheKeyGenerator->generateCacheKey($source, $options));

if ($this->cache->hasItem($key)) {
return $this->cache->getItem($key)->get();
}
}

$data = $this->fetchFreshData($source, $options);
$data = $this->connector->fetch($context, $source);

isset($key) && $this->cache->save($this->cache->getItem($key)->set($data));

return $data;
}

abstract public function fetchFreshData($source, EncapsulatedOptions $options = null);

public function getCache()
{
return $this->cache;
}

public function setCache(CacheItemPoolInterface $cache)
{
$this->cache = $cache;
}

public function enableCache()
{
$this->cacheEnabled = true;
}

public function disableCache()
{
$this->cacheEnabled = false;
}

public function isCacheEnabled()
{
return $this->cacheEnabled;
}

public function getCacheKeyGenerator()
{
return $this->cacheKeyGenerator;
}

public function setCacheKeyGenerator(CacheKeyGenerator $cacheKeyGenerator)
{
$this->cacheKeyGenerator = $cacheKeyGenerator;
}

/**
* @param mixed $key
*
* @return string
* @return void
*
* @throws InvalidCacheKeyException Cache key contains invalid data.
*/
private function validateCacheKey($key)
{
// TODO: Remove when PHP 5 support dropped and replace with string hint.
if (!is_string($key)) {
throw new InvalidCacheKeyException('Cache key must be a string.');
}

if (strpbrk($key, self::RESERVED_CHARACTERS) !== false) {
if (strpbrk($key, CacheKeyGenerator::RESERVED_CHARACTERS) !== false) {
throw new InvalidCacheKeyException(sprintf(
'Cache key "%s" contains one or more reserved characters: "%s".',
$key,
self::RESERVED_CHARACTERS
CacheKeyGenerator::RESERVED_CHARACTERS
));
}
}

return $key;
public function getWrappedConnector()
{
return $this->connector;
}
}
Loading