Skip to content
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
43 changes: 25 additions & 18 deletions src/Query/QueryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,34 @@ protected function findQueryFilePathInDirectory(
string $directory,
string $name,
):?string {
$invalidMatchExtension = null;
$validQueryFilePath = null;

foreach(new DirectoryIterator($directory) as $fileInfo) {
if($fileInfo->isDot()
|| $fileInfo->isDir()) {
if(!$fileInfo->isFile()) {
continue;
}

$this->getExtensionIfValid($fileInfo);
$fileNameNoExtension = strtok($fileInfo->getFilename(), ".");
if($fileNameNoExtension !== $name) {
continue;
}

return $fileInfo->getRealPath();
try {
$this->getExtensionIfValid($fileInfo);
$validQueryFilePath ??= $fileInfo->getRealPath();
}
catch(QueryFileExtensionException) {
$invalidMatchExtension = strtolower($fileInfo->getExtension());
}
}

if(!is_null($validQueryFilePath)) {
return $validQueryFilePath;
}

if(!is_null($invalidMatchExtension)) {
throw new QueryFileExtensionException($invalidMatchExtension);
}

return null;
Expand All @@ -81,7 +96,7 @@ protected function findQueryFilePathInDirectory(
protected function locateOverrideDirectory(string $classFilePath):?string {
$baseName = pathinfo($classFilePath, PATHINFO_FILENAME);
foreach(new DirectoryIterator(dirname($classFilePath)) as $fileInfo) {
if($fileInfo->isDot() || !$fileInfo->isDir()) {
if(!$fileInfo->isDir()) {
continue;
}

Expand Down Expand Up @@ -207,20 +222,12 @@ protected function getExtensionIfValid(SplFileInfo $fileInfo):string {

protected function throwCorrectException(Exception $exception):void {
$message = $exception->getMessage();

switch(get_class($exception)) {
case InvalidArgumentException::class:
$matches = [];
if(1 !== preg_match(
"/Database \[(.+)\] not configured/", $message, $matches)) {
throw $exception;
}

$connectionName = $matches[1];
throw new ConnectionNotConfiguredException($connectionName);

default:
$matches = [];
if(1 !== preg_match("/Database \[(.+)\] not configured/", $message, $matches)) {
throw $exception;
}

$connectionName = $matches[1];
throw new ConnectionNotConfiguredException($connectionName);
}
}
147 changes: 147 additions & 0 deletions test/phpunit/Query/QueryFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Gt\Database\Connection\DefaultSettings;
use Gt\Database\Connection\Driver;
use Gt\Database\Connection\ConnectionNotConfiguredException;
use Gt\Database\Query\PhpQuery;
use Gt\Database\Query\Query;
use Gt\Database\Query\QueryFactory;
Expand Down Expand Up @@ -214,6 +215,52 @@ public function testCreatePhpPrefersOverrideDirectoryWhenClassIsLowerCase():void
}
}

public function testCreatePhpPrefersOverrideDirectoryWhenMethodIsNotPublic():void {
$basePath = Helper::getTmpDir();
$classPath = implode(DIRECTORY_SEPARATOR, [
$basePath,
"query",
"User.php",
]);
$overrideDirectory = implode(DIRECTORY_SEPARATOR, [
$basePath,
"query",
"User",
]);
mkdir($overrideDirectory, 0775, true);
file_put_contents(
$classPath,
<<<PHP
<?php
namespace App\Query;

class User {
protected function getById():string {
return "select 1";
}
}
PHP
);
file_put_contents(
"$overrideDirectory/getById.sql",
"select :id as id"
);

try {
$sut = new QueryFactory($classPath, new Driver(new DefaultSettings()));
$query = $sut->create("getById");

self::assertInstanceOf(SqlQuery::class, $query);
self::assertSame(
realpath("$overrideDirectory/getById.sql"),
$query->getFilePath()
);
}
finally {
Helper::deleteDir($basePath);
}
}

public function testCreatePhpThrowsWhenOverrideConflictsWithPublicMethod():void {
$basePath = Helper::getTmpDir();
$classPath = implode(DIRECTORY_SEPARATOR, [
Expand Down Expand Up @@ -255,4 +302,104 @@ public function getById():string {
Helper::deleteDir($basePath);
}
}

public function testCreateTranslatesConnectionNotConfiguredException():void {
$basePath = Helper::getTmpDir();
$queryDirectory = implode(DIRECTORY_SEPARATOR, [
$basePath,
"query",
]);
mkdir($queryDirectory, 0775, true);
file_put_contents("$queryDirectory/users.sql", "select 1");

$driver = $this->createMock(Driver::class);
$driver->method("getConnection")
->willThrowException(
new \InvalidArgumentException("Database [reporting] not configured")
);

try {
$sut = new QueryFactory($queryDirectory, $driver);

self::expectException(ConnectionNotConfiguredException::class);
self::expectExceptionMessage("reporting");
$sut->create("users");
}
finally {
Helper::deleteDir($basePath);
}
}

public function testCreateRethrowsUnexpectedInvalidArgumentException():void {
$basePath = Helper::getTmpDir();
$queryDirectory = implode(DIRECTORY_SEPARATOR, [
$basePath,
"query",
]);
mkdir($queryDirectory, 0775, true);
file_put_contents("$queryDirectory/users.sql", "select 1");

$driver = $this->createMock(Driver::class);
$driver->method("getConnection")
->willThrowException(new \InvalidArgumentException("Unexpected error"));

try {
$sut = new QueryFactory($queryDirectory, $driver);

self::expectException(\InvalidArgumentException::class);
self::expectExceptionMessage("Unexpected error");
$sut->create("users");
}
finally {
Helper::deleteDir($basePath);
}
}

public function testFindQueryFilePathIgnoresUnrelatedInvalidExtensions():void {
$basePath = Helper::getTmpDir();
$queryDirectory = implode(DIRECTORY_SEPARATOR, [
$basePath,
"query",
]);
mkdir($queryDirectory, 0775, true);
file_put_contents("$queryDirectory/valid.sql", "select 1");
file_put_contents("$queryDirectory/other.sql~", "select 2");

try {
$sut = new QueryFactory($queryDirectory, new Driver(new DefaultSettings()));
$queryFilePath = $sut->findQueryFilePath("valid");

self::assertSame(
realpath("$queryDirectory/valid.sql"),
$queryFilePath
);
}
finally {
Helper::deleteDir($basePath);
}
}

public function testFindQueryFilePathPrefersSupportedExtensionOverEditorBackup():void {
$basePath = Helper::getTmpDir();
$queryDirectory = implode(DIRECTORY_SEPARATOR, [
$basePath,
"query",
]);
mkdir($queryDirectory, 0775, true);
file_put_contents("$queryDirectory/report.sql", "select 1");
file_put_contents("$queryDirectory/report.sql~", "select 2");

try {
$sut = new QueryFactory($queryDirectory, new Driver(new DefaultSettings()));
$queryFilePath = $sut->findQueryFilePath("report");

self::assertSame(
realpath("$queryDirectory/report.sql"),
$queryFilePath
);
}
finally {
Helper::deleteDir($basePath);
}
}
}
Loading