Skip to content

Commit

Permalink
Merge pull request #24 from clue-labs/relative-paths
Browse files Browse the repository at this point in the history
Resolve relative paths to SQLite database files in Factory
  • Loading branch information
clue authored May 11, 2019
2 parents 6fbb033 + 5075fb3 commit a8c8d26
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 1 deletion.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ $factory->open('users.db')->then(function (DatabaseInterface $db) {
});
```

The `$filename` parameter is the path to the SQLite database file or
`:memory:` to create a temporary in-memory database. As of PHP 7.0.10, an
empty string can be given to create a private, temporary on-disk database.
Relative paths will be resolved relative to the current working directory,
so it's usually recommended to pass absolute paths instead to avoid any
ambiguity.

```php
$promise = $factory->open(__DIR__ . '/users.db');
```

The optional `$flags` parameter is used to determine how to open the
SQLite database. By default, open uses `SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE`.

Expand Down Expand Up @@ -145,6 +156,17 @@ Depending on your particular use case, you may prefer this method or the
underlying `open()` method which resolves with a promise. For many
simple use cases it may be easier to create a lazy connection.

The `$filename` parameter is the path to the SQLite database file or
`:memory:` to create a temporary in-memory database. As of PHP 7.0.10, an
empty string can be given to create a private, temporary on-disk database.
Relative paths will be resolved relative to the current working directory,
so it's usually recommended to pass absolute paths instead to avoid any
ambiguity.

```php
$$db = $factory->openLazy(__DIR__ . '/users.db');
```

The optional `$flags` parameter is used to determine how to open the
SQLite database. By default, open uses `SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE`.

Expand Down
37 changes: 36 additions & 1 deletion src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ public function __construct(LoopInterface $loop)
* });
* ```
*
* The `$filename` parameter is the path to the SQLite database file or
* `:memory:` to create a temporary in-memory database. As of PHP 7.0.10, an
* empty string can be given to create a private, temporary on-disk database.
* Relative paths will be resolved relative to the current working directory,
* so it's usually recommended to pass absolute paths instead to avoid any
* ambiguity.
*
* ```php
* $promise = $factory->open(__DIR__ . '/users.db');
* ```
*
* The optional `$flags` parameter is used to determine how to open the
* SQLite database. By default, open uses `SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE`.
*
Expand All @@ -85,6 +96,7 @@ public function __construct(LoopInterface $loop)
*/
public function open($filename, $flags = null)
{
$filename = $this->resolve($filename);
return $this->useSocket ? $this->openSocketIo($filename, $flags) : $this->openProcessIo($filename, $flags);
}

Expand Down Expand Up @@ -135,6 +147,17 @@ public function open($filename, $flags = null)
* underlying `open()` method which resolves with a promise. For many
* simple use cases it may be easier to create a lazy connection.
*
* The `$filename` parameter is the path to the SQLite database file or
* `:memory:` to create a temporary in-memory database. As of PHP 7.0.10, an
* empty string can be given to create a private, temporary on-disk database.
* Relative paths will be resolved relative to the current working directory,
* so it's usually recommended to pass absolute paths instead to avoid any
* ambiguity.
*
* ```php
* $db = $factory->openLazy(__DIR__ . '/users.db');
* ```
*
* The optional `$flags` parameter is used to determine how to open the
* SQLite database. By default, open uses `SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE`.
*
Expand Down Expand Up @@ -162,7 +185,7 @@ public function open($filename, $flags = null)
*/
public function openLazy($filename, $flags = null, array $options = [])
{
return new LazyDatabase($filename, $flags, $options, $this, $this->loop);
return new LazyDatabase($this->resolve($filename), $flags, $options, $this, $this->loop);
}

private function openProcessIo($filename, $flags = null)
Expand Down Expand Up @@ -318,4 +341,16 @@ private function which($bin)
}
return null;
}

/**
* @param string $filename
* @return string
*/
private function resolve($filename)
{
if ($filename !== '' && $filename !== ':memory:' && !\preg_match('/^\/|\w+\:\\\\/', $filename)) {
$filename = \getcwd() . \DIRECTORY_SEPARATOR . $filename;
}
return $filename;
}
}
65 changes: 65 additions & 0 deletions tests/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,69 @@ public function testLoadLazyWithIdleOptionsReturnsDatabaseWithIdleTimeApplied()

$this->assertEquals(10.0, $value);
}

public function testLoadLazyWithAbsolutePathWillBeUsedAsIs()
{
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$factory = new Factory($loop);

$db = $factory->openLazy(__DIR__ . '/users.db');

$ref = new ReflectionProperty($db, 'filename');
$ref->setAccessible(true);
$value = $ref->getValue($db);

$this->assertEquals(__DIR__ . '/users.db', $value);
}

public function testLoadLazyWithMemoryPathWillBeUsedAsIs()
{
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$factory = new Factory($loop);

$db = $factory->openLazy(':memory:');

$ref = new ReflectionProperty($db, 'filename');
$ref->setAccessible(true);
$value = $ref->getValue($db);

$this->assertEquals(':memory:', $value);
}

public function testLoadLazyWithEmptyPathWillBeUsedAsIs()
{
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$factory = new Factory($loop);

$db = $factory->openLazy('');

$ref = new ReflectionProperty($db, 'filename');
$ref->setAccessible(true);
$value = $ref->getValue($db);

$this->assertEquals('', $value);
}

public function testLoadLazyWithRelativePathWillBeResolvedWhenConstructingAndWillNotBeAffectedByChangingDirectory()
{
$original = getcwd();
if ($original === false) {
$this->markTestSkipped('Unable to detect current working directory');
}

$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$factory = new Factory($loop);

$db = $factory->openLazy('users.db');

chdir('../');

$ref = new ReflectionProperty($db, 'filename');
$ref->setAccessible(true);
$value = $ref->getValue($db);

chdir($original);

$this->assertEquals($original . DIRECTORY_SEPARATOR . 'users.db', $value);
}
}

0 comments on commit a8c8d26

Please sign in to comment.