Skip to content

Commit

Permalink
Merge pull request #70 from cybex-gmbh/master
Browse files Browse the repository at this point in the history
v2.0.0
  • Loading branch information
gael-connan-cybex authored Feb 23, 2023
2 parents 227b904 + fffb024 commit b2b0f73
Show file tree
Hide file tree
Showing 16 changed files with 520 additions and 404 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ jobs:
strategy:
fail-fast: true
matrix:
php: [ 8.0, 8.1 ]
laravel: [ 8.*, 9.* ]
php: [ 8.1, 8.2 ]
laravel: [ 9.*, 10.* ]
dependency-version: [ prefer-stable ]

name: PHP ${{ matrix.php }} with Laravel ${{ matrix.laravel }} (${{ matrix.dependency-version }})
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,13 @@ See [cybex-gmbh/collector](https://github.com/cybex-gmbh/collector) for an examp

## Migration guide from Protector v1.x to v2.x

Likelihood of impact: high

- If your app does not explicitly require the laravel/sanctum package, upgrading Protector to version 2.x may also
upgrade Sanctum to version 3.x. This will require you to follow its
[upgrade guide](https://github.com/laravel/sanctum/blob/3.x/UPGRADE.md). Alternatively you can explicitly require
laravel/sanctum ^2.4 in your app to lock its version.

Likelihood of impact: low

- Access to the formerly public methods getGitRevision(), getGitHeadDate() or getGitBranch() is now protected.
Expand Down
14 changes: 1 addition & 13 deletions Tests/ExportDumpTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,10 @@ public function failGeneratingDumpWhenTryingToConnectToDatabase()
]);

// Configure protector to the invalid database connection.
$this->protector->configure('invalid');
$this->protector->withConnectionName('invalid');

// Expect an exception when trying to connect and determine if the connected database is a MariaDB database.
$this->expectException(PDOException::class);
$this->runProtectedMethod('generateDump', [['no-data' => true]]);
}

/**
* @test
*/
public function failOnDumpHasNoConnectionConfigured()
{
Config::set('database.connections', null);
$this->protector->configure();

$this->expectException(InvalidConnectionException::class);
$this->protector->createDump();
}
}
2 changes: 1 addition & 1 deletion Tests/ImportDumpCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function failSettingConnectionNameOnNoConnectionsAreConfigured()
{
Config::set('database.connections', null);

$this->expectException(InvalidConfigurationException::class);
$this->expectException(InvalidConnectionException::class);

$this->artisan('protector:import');
}
Expand Down
6 changes: 2 additions & 4 deletions Tests/ImportDumpTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,8 @@ public function failOnProductionEnvironment()
public function failOnInvalidConnectionConfig()
{
Config::set('database.connections', null);
$this->protector->configure();

$this->expectException(InvalidConnectionException::class);
$this->protector->importDump($this->filePath);
$this->protector->withConnectionName(null);
}

/**
Expand All @@ -178,7 +176,7 @@ public function throwsExceptionOnMysqlFailedShellCommand()
Config::set('database.default', 'mysql');
Config::set('database.connections.mysql.host', 'protector.invalid');

$this->protector->configure();
$this->protector->withConnectionName(null);

$this->expectException(FailedMysqlCommandException::class);
$this->protector->importDump($this->filePath);
Expand Down
24 changes: 7 additions & 17 deletions Tests/RemoteDumpTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public function failWhenPrivateKeyIsNotSet()
{
Config::set('protector.routeMiddleware', ['auth:sanctum']);

$this->protector->setPrivateKeyName('NON_EXISTENT_PRIVATE_KEY_NAME');
$this->protector->withPrivateKeyName('NON_EXISTENT_PRIVATE_KEY_NAME');

Http::fake([
$this->serverUrl => Http::response(),
Expand Down Expand Up @@ -318,23 +318,11 @@ public function addBasicAuthToRequestWhenHtaccessIsUsed()
public function canReturnDatabaseName()
{
Config::set('database.connections.mysql.database', __FUNCTION__);
$this->protector->configure();
$this->protector->withConnectionName();

$this->assertEquals(__FUNCTION__, $this->protector->getDatabaseName());
}

/**
* @test
*/
public function failOnNoDatabaseConnectionIsSet()
{
Config::set('database.connections', null);

$result = $this->protector->configure();

$this->assertFalse($result);
}

/**
* @test
*/
Expand Down Expand Up @@ -367,7 +355,7 @@ public function canResolveBaseDirectoryFromClosure()
*/
public function validateUsersPrivateKeyName()
{
$this->protector->setPrivateKeyName(__FUNCTION__);
$this->protector->withPrivateKeyName(__FUNCTION__);
$privateKeyName = $this->protector->getPrivateKeyName();

$this->assertEquals(__FUNCTION__, $privateKeyName);
Expand Down Expand Up @@ -409,7 +397,8 @@ public function canGetAuthToken()
*/
public function setAuthToken()
{
$this->runProtectedMethod('setAuthToken', [__FUNCTION__]);
$this->protector->withAuthToken(__FUNCTION__);

$authToken = $this->runProtectedMethod('getAuthToken');

$this->assertEquals(__FUNCTION__, $authToken);
Expand All @@ -420,7 +409,8 @@ public function setAuthToken()
*/
public function setAuthTokenKeyName()
{
$this->runProtectedMethod('setAuthTokenKeyName', [__FUNCTION__]);
$this->protector->withAuthTokenKeyName(__FUNCTION__);

$authTokenKeyName = $this->runProtectedMethod('getAuthTokenKeyName');

$this->assertEquals(__FUNCTION__, $authTokenKeyName);
Expand Down
14 changes: 7 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@
}
],
"require": {
"php": "^8.0",
"php": "^8.1",
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo": "*",
"ext-sodium": "*",
"guzzlehttp/guzzle": "^7.4",
"illuminate/support": "^8.0|^9.0",
"laravel/framework": "^8.0|^9.0",
"laravel/sanctum": "^2.4",
"ext-pdo": "*"
"illuminate/support": "^9.0|^10.0",
"laravel/framework": "^9.0|^10.0",
"laravel/sanctum": "^3.2"
},
"require-dev": {
"laravel/sail": "^1.15",
"orchestra/testbench": "^6.23|^7.0",
"laravel/sail": "^1.18",
"orchestra/testbench": "^7.0|^8.0",
"phpunit/phpunit": "^9.5"
},
"autoload": {
Expand Down
15 changes: 4 additions & 11 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
testdox="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false"
colors="true" testdox="true" processIsolation="false" stopOnFailure="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" cacheDirectory=".phpunit.cache"
backupStaticProperties="false">
<testsuites>
<testsuite name="Test Suite">
<directory>Tests</directory>
Expand Down
61 changes: 61 additions & 0 deletions src/Classes/AbstractMySqlSchemaStateProxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Cybex\Protector\Classes;

use Cybex\Protector\Protector;
use Exception;
use Illuminate\Database\Connection;
use Illuminate\Database\Schema\MySqlSchemaState;
use Illuminate\Database\Schema\SchemaState;
use Symfony\Component\Process\Process;

/**
* This abstract class provides proxies to protected methods within the related MySqlSchemaState.
*/
abstract class AbstractMySqlSchemaStateProxy extends MySqlSchemaState
{
public function __construct(protected MySqlSchemaState $schemaState, protected Protector $protector)
{
}

/**
* @inheritDoc
*/
public function dump(Connection $connection, $path)
{
$this->schemaState->dump(...func_get_args());
}

/**
* @inheritDoc
*/
public function load($path)
{
$this->schemaState->load(...func_get_args());
}

protected function executeDumpProcess(Process $process, $output, array $variables): Process
{
return $this->schemaState->executeDumpProcess(...func_get_args());
}

protected function baseDumpCommand(): string
{
return $this->schemaState->baseDumpCommand();
}

protected function baseVariables(mixed $config): array
{
return $this->schemaState->baseVariables(...func_get_args());
}

protected function removeAutoIncrementingState(string $path): void
{
$this->schemaState->removeAutoIncrementingState(...func_get_args());
}

protected function appendMigrationData(string $path): void
{
$this->schemaState->appendMigrationData(...func_get_args());
}
}
71 changes: 71 additions & 0 deletions src/Classes/MySqlSchemaStateProxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace Cybex\Protector\Classes;

use Illuminate\Database\Connection;

/**
* This is a proxy to the MySqlSchemaState class which allows us to override methods to match our own requirements.
* Unfortunately, the class is not bound to the IOC container and thus cannot be switched out at framework level.
* However, you may extend this proxy, and override its app container binding with your custom implementation.
*/
class MySqlSchemaStateProxy extends AbstractMySqlSchemaStateProxy
{
/**
* @inheritDoc
*/
public function dump(Connection $connection, $path)
{
$this->executeDumpProcess(
$this->schemaState->makeProcess(
$this->getCommandString()
),
$this->schemaState->output,
array_merge(
$this->baseVariables($this->schemaState->connection->getConfig()),
['LARAVEL_LOAD_PATH' => $path,]
)
);

if ($this->protector->shouldRemoveAutoIncrementingState()) {
$this->removeAutoIncrementingState($path);
}
}

/**
* @inheritDoc
*/
public function load($path)
{
$this->schemaState->load(...func_get_args());
}

/**
* Get the dump command for MySQL as a string.
*/
protected function getCommandString(): string
{
$command = 'mysqldump '.$this->schemaState->connectionString().' ';

$conditionalParameters = [
'--set-gtid-purged=OFF' => !$this->schemaState->connection->isMaria(),
'--no-create-db' => !$this->protector->shouldCreateDb(),
'--skip-comments' => !$this->protector->shouldDumpComments(),
'--skip-set-charset' => !$this->protector->shouldDumpCharsets(),
'--no-data' => !$this->protector->shouldDumpData(),
];

$parameters = [
'--add-locks',
'--routines',
'--tz-utc',
'--column-statistics=0',
'--result-file="${:LARAVEL_LOAD_PATH}"',
'--max-allowed-packet='.$this->protector->getMaxPacketLength(),
...array_keys(array_filter($conditionalParameters)),
'"${:LARAVEL_LOAD_DATABASE}"',
];

return $command.implode(' ', $parameters);
}
}
16 changes: 6 additions & 10 deletions src/Commands/ExportDump.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,15 @@ public function handle(): int
$options = [];
$options['no-data'] = $this->option('no-data') ?: false;

if ($this->protector->configure($connectionName ?? null)) {
$tempFilePath = $this->protector->createDump($options);
$this->protector->withConnectionName($connectionName ?? null);

$this->protector->getDisk()->putFileAs($directory, new File($tempFilePath), $fileName);
unlink($tempFilePath);
$tempFilePath = $this->protector->createDump($options);

$this->info(sprintf('Dump %s was created in %s', $fileName, $directory));
$this->protector->getDisk()->putFileAs($directory, new File($tempFilePath), $fileName);
unlink($tempFilePath);

return self::SUCCESS;
}

$this->error('Configuration is invalid.');
$this->info(sprintf('Dump %s was created in %s', $fileName, $directory));

return self::FAILURE;
return self::SUCCESS;
}
}
Loading

0 comments on commit b2b0f73

Please sign in to comment.