Commit 7ea4f1fc authored by Thorsten Buss's avatar Thorsten Buss

Add RepositoryLinker with tests and some doc and test changes

parent e1dd2c27
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 13:19
*/
namespace BNRepo\Repository\Adapter;
......@@ -19,10 +14,10 @@ interface AdapterDownloadable {
* @param string $sourceKey
* @param string $localTargetFile
*
* @return boolean TRUE if the rename was successful
* @return boolean TRUE if the download was successful
* @throws FileNotFound when sourceKey does not exist
* @throws UnexpectedFile when targetKey exists
* @throws \RuntimeException when cannot rename
* @throws \RuntimeException when cannot download
*/
public function download($sourceKey, $localTargetFile);
......
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 13:19
*/
namespace BNRepo\Repository\Adapter;
......
......@@ -18,10 +18,10 @@ interface AdapterUploadable {
* @param string $localFile
* @param string $targetKey
*
* @return boolean TRUE if the rename was successful
* @return boolean TRUE if the upload was successful
* @throws FileNotFound when sourceKey does not exist
* @throws UnexpectedFile when targetKey exists
* @throws \RuntimeException when cannot rename
* @throws \RuntimeException when cannot upload
*/
public function upload($localFile, $targetKey);
}
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 11:24
*/
namespace BNRepo\Repository;
......@@ -15,6 +10,11 @@ use Gaufrette\Filesystem;
use BNRepo\Repository\Adapter\AdapterDownloadable;
use BNRepo\Repository\Adapter\AdapterUploadable;
/**
* Class Repository
* BaseClass for the different Repositories
* @package BNRepo\Repository
*/
class Repository extends Filesystem {
public function __construct($cfg) {
......
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 11:25
*/
namespace BNRepo\Repository;
......
<?php
namespace BNRepo\Repository;
use BNRepo\Repository\Adapter\AdapterDownloadable;
use BNRepo\Repository\Adapter\AdapterUploadable;
use Gaufrette\Exception\FileNotFound;
use Gaufrette\Exception\UnexpectedFile;
use Gaufrette\File;
use Gaufrette\Stream;
/**
* Class RepositoryLinker
* designed to interact with more Repositories (copy, move)
* or simpler usage with URIs instead of filePaths (bnrepo://REPO_ID/path/to/file.ext)
* @package BNRepo\Repository
*/
class RepositoryLinker {
/**
* @var RepositoryLinker
*/
static $instance;
/**
* scheme for Links: $scheme://REPO-ID/Path/to/file.ext
* @var string
*/
public $scheme = 'bnrepo';
/**
* UriCache, so every uri schould parse once
* @var array
*/
protected $uri_cache = array();
/**
* @return RepositoryLinker
*/
public static function getInstance() {
if (!isset(static::$instance)) {
static::$instance = new static();
}
return static::$instance;
}
// /**
// * Parse the URI and returns an Obj with Repo, RepoID und Dir
// * Alternative concept to getRepositoryFromUri() with $uri as ReferenceParam
// * @param $uri
// * @return \ArrayObject
// * @throws NoValidLinkerScheme
// */
// public function parseRepositoryUri($uri) {
// if (!isset($this->uri_cache[$uri])) {
// $arr = parse_url($uri);
// if ($arr['scheme'] != $this->scheme)
// throw new NoValidLinkerScheme(sprintf('%s is not a valid linker scheme - need %s', $arr['scheme'], $this->scheme));
// $this->uri_cache[$uri] = new \ArrayObject(array(
// 'repo' => $arr['host'],
// 'dir' => $arr['path'],
// 'obj' => RepositoryManager::getRepository($arr['repo'])
// ));
// }
// return $this->uri_cache[$uri];
// }
/**
* return Repo, parsed from repoUlr (bnrepo://REPO_ID/path/to/file.ext)
* ATTENION: $uri would change to the real Path - the scheme and host was striped from the uri
* @param $uri
* @return Repository
* @throws NoValidLinkerScheme
*/
protected function getRepositoryFromUri(&$uri) {
// Validate and Cache Uri
if (!isset($this->uri_cache[$uri])) {
$c = parse_url($uri);
if (!isset($c['scheme']))
throw new NoValidLinkerScheme('linker scheme is missed');
if ($c['scheme'] != $this->scheme)
throw new NoValidLinkerScheme(sprintf('%s is not a valid linker scheme - need %s', $c['scheme'], $this->scheme));
$this->uri_cache[$uri] = $c;
}
$c = &$this->uri_cache[$uri];
// change $uri to the path, so the var could use to work with the repo
$uri = $c['path'];
return RepositoryManager::getRepository($c['host']);
}
/**
* copies a file
*
* @param string $sourceKey
* @param string $targetKey
*
* @return boolean TRUE if the copy was successful
* @throws FileNotFound when sourceKey does not exist
* @throws UnexpectedFile when targetKey exists
* @throws \RuntimeException when cannot copy
*/
public function copy($sourceKey, $targetKey) {
return $this->write($targetKey, $this->read($sourceKey)) !== false;
}
/**
* Indicates whether the file matching the specified key exists
*
* @param string $key
*
* @return boolean TRUE if the file exists, FALSE otherwise
*/
public function has($key) {
return $this->getRepositoryFromUri($key)->has($key);
}
/**
* moves a file
*
* @param string $sourceKey
* @param string $targetKey
*
* @return boolean TRUE if the move was successful
* @throws FileNotFound when sourceKey does not exist
* @throws UnexpectedFile when targetKey exists
* @throws \RuntimeException when cannot move
*/
public function move($sourceKey, $targetKey) {
if ($this->copy($sourceKey, $targetKey)) {
return $this->delete($sourceKey);
}
return false;
}
/**
* Returns the file matching the specified key
*
* @param string $key Key of the file
* @param boolean $create Whether to create the file if it does not exist
*
* @throws FileNotFound
* @return File
*/
public function get($key, $create = false) {
return $this->getRepositoryFromUri($key)->get($key, $create);
}
/**
* Deletes the file matching the specified key
*
* @param string $key
*
* @return boolean
*/
public function delete($key) {
return $this->getRepositoryFromUri($key)->delete($key);
}
/**
* Returns an array of all keys
*
* @return array
*/
public function keys($uri) {
return $this->getRepositoryFromUri($uri)->keys();
}
/**
* Lists keys beginning with given prefix
* (no wildcard / regex matching)
*
* if adapter implements ListKeysAware interface, adapter's implementation will be used,
* in not, ALL keys will be requested and iterated through.
*
* @param string $prefix
* @return array
*/
public function listKeys($uri, $prefix = '') {
return $this->getRepositoryFromUri($uri)->listKeys($prefix);
}
/**
* Returns the last modified time of the specified file
*
* @param string $key
*
* @return integer An UNIX like timestamp
*/
public function mtime($key) {
return $this->getRepositoryFromUri($key)->mtime($key);
}
/**
* Returns the checksum of the specified file's content
*
* @param string $key
*
* @return string A MD5 hash
*/
public function checksum($key) {
return $this->getRepositoryFromUri($key)->checksum($key);
}
/**
* Creates a new stream instance of the specified file
*
* @param string $key
*
* @return Stream
*/
public function createStream($key) {
return $this->getRepositoryFromUri($key)->createFile($key);
}
/**
* Creates a new File instance and returns it
*
* @param string $key
*
* @return File
*/
public function createFile($key) {
return $this->getRepositoryFromUri($key)->createFile($key);
}
/**
* Reads the content from the file
*
* @param string $key Key of the file
* @throws FileNotFound when file does not exist
* @throws \RuntimeException when cannot read file
*
* @return string
*/
public function read($key) {
return $this->getRepositoryFromUri($key)->read($key);
}
/**
* Writes the given content into the file
*
* @param string $key Key of the file
* @param string $content Content to write in the file
* @param boolean $overwrite Whether to overwrite the file if exists
*
* @return integer The number of bytes that were written into the file
*/
public function write($key, $content, $overwrite = false) {
return $this->getRepositoryFromUri($key)->write($key, $content, $overwrite);
}
/**
* Uploads a Local file
*
* @param string $localFile
* @param string $targetKey
* @param boolean $overwriteLocalFile
*
* @return boolean TRUE if the upload was successful
* @throws FileNotFound when sourceKey does not exist
* @throws UnexpectedFile when targetKey exists
* @throws \RuntimeException when cannot upload
*/
public function upload($localFile, $targetKey, $overwriteRemoteFile = false) {
return $this->getRepositoryFromUri($targetKey)->upload($localFile, $targetKey, $overwriteRemoteFile);
}
/**
* Downloads a file to Local
*
* @param string $sourceKey
* @param string $localTargetFile
* @param boolean $overwriteLocalFile
*
* @return boolean TRUE if the download was successful
* @throws FileNotFound when sourceKey does not exist
* @throws UnexpectedFile when targetKey exists
* @throws \RuntimeException when cannot download
*/
public function download($sourceKey, $localTargetFile, $overwriteLocalFile = false) {
return $this->getRepositoryFromUri($sourceKey)->download($sourceKey, $localTargetFile, $overwriteLocalFile);
}
}
class NoValidLinkerScheme extends \Exception {}
class AdapterDontSupportThisMethod extends \Exception {}
\ No newline at end of file
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 11:25
*/
namespace BNRepo\Repository;
use Gaufrette\Exception\FileNotFound;
use Gaufrette\Exception\UnexpectedFile;
use BNRepo\Repository\Adapter\AdapterLocal;
class RepositoryLocal extends Repository {
......
<?php
/**
* User: thorsten
* Date: 13.04.13
* Time: 12:29
*/
namespace BNRepo\Repository;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Exception\ParseException;
/**
* Class RepositoryManager
* Manage Repositories in a lazy way
* @package BNRepo\Repository
*/
class RepositoryManager {
static $config = array();
......@@ -107,6 +107,13 @@ class RepositoryManager {
self::$repositories = array();
}
/**
* Gets the Linker, which can work over all repositories
* @return RepositoryLinker
*/
public static function getLinker() {
return RepositoryLinker::getInstance();
}
}
class InvalidResourceException extends \Exception {}
......
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 11:25
*/
namespace BNRepo\Repository;
......
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 11:25
*/
namespace BNRepo\Repository;
......
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 12:22
*/
namespace BNRepo\Tests\Repository;
......@@ -19,7 +14,6 @@ class RepositoryAmazonS3Test extends RepositoryTest {
parent::tearDown();
if ($this->repo()->has('public.txt'))
$this->repo()->delete('public.txt');
$this->_tearDown($this->repo());
}
public function testUploadFileSuccessfully() {
......
<?php
/**
* User: thorsten
* Date: 15.04.13
* Time: 12:22
*/
namespace BNRepo\Tests\Repository;
......@@ -14,11 +9,6 @@ class RepositoryFtpTest extends RepositoryTest {
protected $cfg_id = 'bnrepo-test-ftp';
protected function tearDown() {
parent::tearDown();
$this->_tearDown($this->repo());
}
public function testUploadFileSuccessfully() {
$this->_testUploadFileSuccessfully($this->repo());
}
......
<?php
namespace BNRepo\Tests\Repository;
use BNRepo\Repository\Repository;
use BNRepo\Repository\RepositoryLinker;
use BNRepo\Repository\RepositoryManager;
use Symfony\Component\Yaml\Yaml;
/**
* Generated by PHPUnit_SkeletonGenerator 1.2.0 on 2013-04-17 at 11:34:26.
*/
class RepositoryLinkerTest extends RepositoryTest {
public $cfg_id = 'bnrepo-test-local';
public $cfg_id2;
public function __construct($name = NULL, array $data = array(), $dataName = '') {
parent::__construct($name, $data, $dataName);
// find another Repository to test with
foreach (RepositoryManager::$config as $k => $v) {
if ('bnrepo-test-local' != $k && strstr($k, '-test-') >= 0) {
$this->cfg_id2 = $k;
break;
}
}
}
/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*/
protected function tearDown() {
parent::tearDown();
$this->_tearDown($this->repo2());
}
protected function setUp() {
if (empty($this->cfg_id2)) {
$this->markTestSkipped('need local and another repo to test the RepositoryLinker');
return false;
}
return parent::setUp();
}
/**
* builds an exmaple uri
* @param string $key
* @param null $repo
* @return string
*/
public function uri($key = 'src.txt', $repo = null) {
return sprintf('bnrepo://%s/%s', $repo ? : $this->cfg_id, $key);
}
public function uri2($key = 'src.txt') {
return $this->uri($key, $this->cfg_id2);
}
/**
* @return Repository
*/
protected function repo2() {
return RepositoryManager::getRepository($this->cfg_id2);
}
/**
* @covers BNRepo\Repository\RepositoryLinker::copy
*/
public function testCopy() {
$key = 'src.txt';
$uri = $this->uri($key);
$to = $this->uri2($key);
$this->repo()->write($key, $this->test_content);
$this->assertTrue(RepositoryLinker::getInstance()->has($uri), 'file exists');
$this->assertFalse(RepositoryLinker::getInstance()->has($to), 'file not exists');
// Copy
$this->assertTrue(RepositoryLinker::getInstance()->copy($uri, $to), 'copy successfull');
$this->assertTrue(RepositoryLinker::getInstance()->has($uri), 'file exists after copy SRC');
$this->assertTrue(RepositoryLinker::getInstance()->has($to), 'file exists after copy TRG');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::has
*/
public function testHas() {
$key = 'src.txt';
$uri = $this->uri($key);
$this->assertFalse(RepositoryLinker::getInstance()->has($uri), 'file not exists');
$this->repo()->write($key, $this->test_content);
$this->assertTrue(RepositoryLinker::getInstance()->has($uri), 'file exists');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::getRepositoryFromUri
*/
public function testUriParsingWithoutScheme() {
$this->setExpectedException('\BNRepo\Repository\NoValidLinkerScheme');
$uri = '/path/to/test';
RepositoryLinker::getInstance()->has($uri);
}
/**
* @covers BNRepo\Repository\RepositoryLinker::getRepositoryFromUri
*/
public function testUriParsingWithWrongScheme() {
$this->setExpectedException('\BNRepo\Repository\NoValidLinkerScheme');
$uri = 'http://server/path/to/test';
RepositoryLinker::getInstance()->has($uri);
}
/**
* @covers BNRepo\Repository\RepositoryLinker::move
*/
public function testMove() {
$key = 'src.txt';
$uri = $this->uri($key);
$to = $this->uri2($key);
$this->repo()->write($key, $this->test_content);
$this->assertTrue(RepositoryLinker::getInstance()->has($uri), 'file exists');
$this->assertFalse(RepositoryLinker::getInstance()->has($to), 'file not exists');
// Move
$this->assertTrue(RepositoryLinker::getInstance()->move($uri, $to), 'moved successfull');
$this->assertFalse(RepositoryLinker::getInstance()->has($uri), 'file not exists after moved SRC');
$this->assertTrue(RepositoryLinker::getInstance()->has($to), 'file exists after copy TRG');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::get
*/
public function testGet() {
$key = 'src.txt';
$uri = $this->uri($key);
$this->assertFalse(RepositoryLinker::getInstance()->has($uri), 'file not exists');
$this->repo()->write($key, $this->test_content);
$this->assertInstanceOf('\Gaufrette\File', RepositoryLinker::getInstance()->get($uri), 'file exists');
$this->assertEquals('/'.$key, RepositoryLinker::getInstance()->get($uri)->getKey(), 'name matches');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::delete
*/
public function testDelete() {
$key = 'src.txt';
$uri = $this->uri($key);
$this->assertFalse(RepositoryLinker::getInstance()->has($uri), 'file not exists');
$this->repo()->write($key, $this->test_content);
$this->assertTrue(RepositoryLinker::getInstance()->has($uri), 'file exists');
$this->assertTrue(RepositoryLinker::getInstance()->delete($uri), 'delete file');
$this->assertFalse(RepositoryLinker::getInstance()->has($uri), 'file not exists after deleted');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::keys
*/
public function testKeys() {
// the validity of the error checks the repositoryTest semself
$this->repo()->write('src.txt', $this->test_content);
$this->assertTrue(is_array(RepositoryLinker::getInstance()->keys($this->uri())), 'call OK, value returned');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::listKeys
*/
public function testListKeys() {
// the validity of the error checks the repositoryTest semself
$this->repo()->write('src.txt', $this->test_content);
$this->assertTrue(is_array(RepositoryLinker::getInstance()->listKeys($this->uri())), 'call OK, value returned');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::mtime
*/
public function testMtime() {
// the validity of the error checks the repositoryTest semself
$this->repo()->write('src.txt', $this->test_content);
$this->assertTrue(is_numeric(RepositoryLinker::getInstance()->mtime($this->uri())), 'call OK, value returned');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::checksum
*/
public function testChecksum() {
// the validity of the error checks the repositoryTest semself
$this->repo()->write('src.txt', $this->test_content);
$this->assertNotEmpty(RepositoryLinker::getInstance()->checksum($this->uri()), 'call OK, value returned');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::createStream
* @todo Implement testCreateStream().
*/
public function testCreateStream() {
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers BNRepo\Repository\RepositoryLinker::createFile
* @todo Implement testCreateFile().
*/
public function testCreateFile() {
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers BNRepo\Repository\RepositoryLinker::read
*/
public function testRead() {
$key = 'src.txt';
$uri = $this->uri($key);
$this->assertFalse(RepositoryLinker::getInstance()->has($uri), 'file not exists');
$this->repo()->write($key, $this->test_content);
$this->assertEquals($this->test_content, RepositoryLinker::getInstance()->read($uri), 'content matches');
}
/**
* @covers BNRepo\Repository\RepositoryLinker::write
*/
public function testWrite() {
$key = 'src.txt';
$uri = $this->uri($key);
$this->assertFalse(RepositoryLinker::getInstance()->has($uri), 'file not exists');
$this->assertEquals(mb_strlen($this->test_content), RepositoryLinker::getInstance()->write($uri, $this->test_content), 'content writes');
$this->assertTrue(RepositoryLinker::getInstance()->has($uri), 'file exists');