Skip to content

Commit

Permalink
Merge pull request #6 from naitsirch/use_doctrine_config
Browse files Browse the repository at this point in the history
Reuse doctrine's connection params
  • Loading branch information
TheCadien authored Mar 1, 2023
2 parents e701e2c + 07efcae commit 6d6824d
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 29 deletions.
51 changes: 51 additions & 0 deletions DependencyInjection/Compiler/DbConnectionPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

/*
* This file is part of TheCadien/SuluImportExportBundle.
*
* (c) Oliver Kossin
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace TheCadien\Bundle\SuluImportExportBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
* This compiler pass is responsible for fetching the connection params
* of the DBAL and passes them to our export and import service.
*/
class DbConnectionPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
$connectionName = $container->getParameter('sulu_import_export_bundle.dbal_connection');

if (!$connectionName) {
$connectionName = $container->getParameter('doctrine.default_connection');
}

$connections = $container->getParameter('doctrine.connections');

if (!isset($connections[$connectionName])) {
throw new \InvalidArgumentException(sprintf('There is no doctrine connection configured which is named "%s". Available names are "%s".', $connectionName, implode('", "', array_keys($connections))));
}

$connectionId = $connections[$connectionName];
$connectionParams = $container->getDefinition($connectionId)->getArgument(0);

$exportService = $container->getDefinition('sulu.service.export');
$exportService->setArgument('$databaseParams', $connectionParams);

$importService = $container->getDefinition('sulu.service.import');
$importService->setArgument('$databaseParams', $connectionParams);
}
}
8 changes: 8 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('import_export_bundle');

$rootNode = $treeBuilder->getRootNode();
$rootNode
->children()
->scalarNode('dbal_connection')
->defaultNull()
->end()
->end();

return $treeBuilder;
}
}
2 changes: 2 additions & 0 deletions DependencyInjection/SuluImportExportExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public function load(array $configs, ContainerBuilder $container)
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$container->setParameter('sulu_import_export_bundle.dbal_connection', $config['dbal_connection']);

$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('command.xml');
$loader->load('services.xml');
Expand Down
63 changes: 63 additions & 0 deletions Helper/DbConnectionParamsNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

/*
* This file is part of TheCadien/SuluImportExportBundle.
*
* (c) Oliver Kossin
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace TheCadien\Bundle\SuluImportExportBundle\Helper;

class DbConnectionParamsNormalizer
{
/**
* Normalizes the array with the connection params to a defined structure.
*
* @param array $connectionParams
* The database connection params for the connection. Should be passed
* as an associative array with the key 'url' or with the keys 'host',
* 'user', 'dbname' and 'password'.
* If an URL is used, it should follow the format
* 'mysql://<user>:<password>@<host>/<dbname>'.
*
* @throws \InvalidArgumentException if the passed array does not contain the required fields
*
* @return array Returns an array with the keys 'host', 'user', 'dbname' and 'password'.
* The latter may be null.
*/
public static function normalize(array $connectionParams): array
{
if (empty($connectionParams['url'])) {
$diff = array_diff_key(['user', 'dbname'], $connectionParams);

if (\count($diff) > 0) {
throw new \InvalidArgumentException(sprintf('The following keys are missing from the $connectionParams: ', implode(', ', $diff)));
}

return [
'host' => $connectionParams['host'] ?? 'localhost',
'user' => $connectionParams['user'],
'dbname' => $connectionParams['dbname'],
'password' => $connectionParams['password'] ?? null,
];
}

$urlParts = parse_url($connectionParams['url']);

if (false === $urlParts) {
throw new \InvalidArgumentException('The connection URL is not a valid URL that follows the format "<schema>://<user>:<password>@<host>/<dbname>');
}

return [
'host' => $urlParts['host'] ?? 'localhost',
'user' => $urlParts['user'],
'dbname' => substr($urlParts['path'], 1),
'password' => $urlParts['pass'] ?? null,
];
}
}
10 changes: 2 additions & 8 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,13 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="sulu.service.export" class="TheCadien\Bundle\SuluImportExportBundle\Service\ExportService">
<argument key="$databaseHost">%env(DATABASE_HOST)%</argument>
<argument key="$databaseUser">%env(DATABASE_USER)%</argument>
<argument key="$databaseName">%env(DATABASE_NAME)%</argument>
<argument key="$databasePassword">%env(DATABASE_PASSWORD)%</argument>
<argument key="$databaseParams"><!-- dynamically set per DbConnectionPass --></argument>
<argument key="$exportDirectory">%kernel.project_dir%/%env(EXPORT_DIR)%</argument>
<argument key="$uploadsDirectory">%env(MEDIA_PATH)%</argument>
<argument key="$executeService" type="service" id="sulu.service.execute"/>
</service>
<service id="sulu.service.import" class="TheCadien\Bundle\SuluImportExportBundle\Service\ImportService">
<argument key="$databaseHost">%env(DATABASE_HOST)%</argument>
<argument key="$databaseUser">%env(DATABASE_USER)%</argument>
<argument key="$databaseName">%env(DATABASE_NAME)%</argument>
<argument key="$databasePassword">%env(DATABASE_PASSWORD)%</argument>
<argument key="$databaseParams"><!-- dynamically set per DbConnectionPass --></argument>
<argument key="$importDirectory">%kernel.project_dir%/%env(IMPORT_DIR)%</argument>
<argument key="$uploadsDirectory">%env(MEDIA_PATH)%</argument>
<argument key="$executeService" type="service" id="sulu.service.execute"/>
Expand Down
25 changes: 17 additions & 8 deletions Service/ExportService.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
use TheCadien\Bundle\SuluImportExportBundle\Helper\DbConnectionParamsNormalizer;
use TheCadien\Bundle\SuluImportExportBundle\Helper\ImportExportDefaultMap;

class ExportService implements ExportInterface
Expand All @@ -31,19 +32,27 @@ class ExportService implements ExportInterface
*/
private $executeService;

/**
* @param array $databaseParams
* The database connection params for the connection. Should be passed
* as an associative array with the key 'url' or with the keys 'host',
* 'user', 'dbname' and 'password'.
* If an URL is used, it should follow the format
* 'mysql://<user>:<password>@<host>/<dbname>'.
*/
public function __construct(
string $databaseHost,
string $databaseName,
string $databaseUser,
string $databasePassword,
array $databaseParams,
string $exportDirectory,
string $uploadsDirectory,
ExecuteService $executeService
) {
$this->databaseHost = $databaseHost;
$this->databaseUser = $databaseUser;
$this->databaseName = $databaseName;
$this->databasePassword = $databasePassword;
$databaseParams = DbConnectionParamsNormalizer::normalize($databaseParams);

$this->databaseHost = $databaseParams['host'];
$this->databaseUser = $databaseParams['user'];
$this->databaseName = $databaseParams['dbname'];
$this->databasePassword = $databaseParams['password'];

$this->exportDirectory = $exportDirectory;
$this->executeService = $executeService;
$this->uploadsDirectory = ($uploadsDirectory) ?: ImportExportDefaultMap::SULU_DEFAULT_MEDIA_PATH;
Expand Down
24 changes: 16 additions & 8 deletions Service/ImportService.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
use TheCadien\Bundle\SuluImportExportBundle\Helper\DbConnectionParamsNormalizer;
use TheCadien\Bundle\SuluImportExportBundle\Helper\ImportExportDefaultMap;

class ImportService implements ImportInterface
Expand All @@ -34,20 +35,27 @@ class ImportService implements ImportInterface

/**
* ImportCommand constructor.
*
* @param array $databaseParams
* The database connection params for the connection. Should be passed
* as an associative array with the key 'url' or with the keys 'host',
* 'user', 'dbname' and 'password'.
* If an URL is used, it should follow the format
* 'mysql://<user>:<password>@<host>/<dbname>'.
*/
public function __construct(
string $databaseHost,
string $databaseName,
string $databaseUser,
string $databasePassword,
array $databaseParams,
string $importDirectory,
string $uploadsDirectory,
ExecuteService $executeService
) {
$this->databaseHost = $databaseHost;
$this->databaseUser = $databaseUser;
$this->databaseName = $databaseName;
$this->databasePassword = $databasePassword;
$databaseParams = DbConnectionParamsNormalizer::normalize($databaseParams);

$this->databaseHost = $databaseParams['host'];
$this->databaseUser = $databaseParams['user'];
$this->databaseName = $databaseParams['dbname'];
$this->databasePassword = $databaseParams['password'];

$this->importDirectory = $importDirectory;
$this->executeService = $executeService;
$this->uploadsDirectory = ($uploadsDirectory) ?: ImportExportDefaultMap::SULU_DEFAULT_MEDIA_PATH;
Expand Down
9 changes: 9 additions & 0 deletions SuluImportExportBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,17 @@

namespace TheCadien\Bundle\SuluImportExportBundle;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use TheCadien\Bundle\SuluImportExportBundle\DependencyInjection\Compiler\DbConnectionPass;

class SuluImportExportBundle extends Bundle
{
/**
* {@inheritDoc}
*/
public function build(ContainerBuilder $container): void
{
$container->addCompilerPass(new DbConnectionPass());
}
}
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
],
"require": {
"php": "^7.3|^8.0",
"doctrine/doctrine-bundle": ">=1.0",
"sulu/sulu": "^2.0.1",
"symfony/config": "^4.3 || ^5.0 || ^6.0",
"symfony/dependency-injection": "^4.3 || ^5.0 || ^6.0",
Expand Down
16 changes: 11 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,19 @@ composer require thecadien/sulu-import-export-bundle

### Configure the bundle

Configure arguments in your `.env` with your Database Config like the following way.
If the doctrine database connection used by Sulu is not the 'default' DBAL
connection you have to specify the connection name in the bundle's configuration.

```yaml
# config/packages/sulu_import_export.yaml

sulu_import_export:
dbal_connection: default
```

Configure the import and export paths in your `.env` in the following way.

```dotenv
DATABASE_HOST='host'
DATABASE_USER='user'
DATABASE_PASSWORD='password'
DATABASE_NAME='db-name'
MEDIA_PATH='var/uploads/media'
IMPORT_DIR='var/import/'
Expand Down

0 comments on commit 6d6824d

Please sign in to comment.