Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.5] Add user accounts to import/export #7306

Merged
merged 1 commit into from Jan 23, 2018
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Nut/DatabaseExport.php
Expand Up @@ -32,6 +32,7 @@ protected function configure()
->addOption('file', 'f', InputOption::VALUE_REQUIRED, 'A YAML or JSON file to use for export data. Must end with .yml, .yaml or .json')
->addOption('directory', 'd', InputOption::VALUE_REQUIRED, 'A destination directory. The command will automatically generate file names.')
->addOption('contenttype', 'c', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'ContentType name to export records for (can be used multiple times).')
->addOption('users', 'u', InputOption::VALUE_NONE, 'Also export users table.')
;
}

Expand All @@ -55,9 +56,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
$exportContentTypes = (array) $input->getOption('contenttype') ?: array_keys($this->app['config']->get('contenttypes'));
// Response bag
$responseBag = MutableBag::fromRecursive(['error' => [], 'warning' => [], 'success' => []]);
$includeUsers = $input->getOption('users');

$migration = new Migration\Export($this->app['storage'], $this->app['query']);
$exportData = $migration->run($exportContentTypes, $responseBag);
$exportData = $migration->run($exportContentTypes, $responseBag, $includeUsers);

// Dump the file
$file->dump($exportData->toArrayRecursive(), ['inline' => 4]);
Expand Down
7 changes: 6 additions & 1 deletion src/Nut/DatabaseImport.php
Expand Up @@ -57,6 +57,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$responseBag = MutableBag::fromRecursive(['error' => [], 'warning' => [], 'success' => []]);

$importData = [];
$importUsers = MutableBag::of();
foreach ($fileNames as $fileName) {
/** @var JsonFile|YamlFile $file */
$file = $filesystem->getFile($fileName);
Expand All @@ -78,14 +79,18 @@ protected function execute(InputInterface $input, OutputInterface $output)
throw new \RuntimeException('Provided data version not supported');
}

// Users if exists/supported
$users = $bag->remove('__users', Bag::of());

// Merge file data and unset
$importData = array_merge_recursive($importData, $bag->toArray());
$importUsers = $importUsers->merge($users);
unset($bag);
}

// Perform the import
$importData = Bag::fromRecursive($importData);
$migration->run($importData, $responseBag, $input->getOption('overwrite'));
$migration->run($importData, $responseBag, $input->getOption('overwrite'), $importUsers);

if ($responseBag->get('error')->count() > 0) {
$this->io->error($responseBag->get('error')->toArray());
Expand Down
35 changes: 34 additions & 1 deletion src/Storage/Migration/Export.php
Expand Up @@ -2,9 +2,11 @@

namespace Bolt\Storage\Migration;

use Bolt\Collection\Bag;
use Bolt\Collection\MutableBag;
use Bolt\Storage\Entity\Content;
use Bolt\Storage\Entity\Entity;
use Bolt\Storage\Entity\Users;
use Bolt\Storage\EntityManager;
use Bolt\Storage\Mapping\ClassMetadata;
use Bolt\Storage\Query\Query;
Expand Down Expand Up @@ -43,15 +45,21 @@ public function __construct(EntityManager $em, Query $query)
*
* @param array $exportContentTypes
* @param MutableBag $responseBag
* @param bool $includeUsers
*
* @throws \Bolt\Exception\InvalidRepositoryException
*
* @return MutableBag
*/
public function run(array $exportContentTypes, MutableBag $responseBag)
public function run(array $exportContentTypes, MutableBag $responseBag, $includeUsers = false)
{
// Get initial data object
$exportData = MutableBag::from([]);
// Add the meta header
$this->addExportMeta($exportData);
if ($includeUsers) {
$this->addExportUsers($exportData);
}

// Add records for each ContentType
foreach ($exportContentTypes as $contentTypeName) {
Expand All @@ -76,12 +84,37 @@ private function addExportMeta(MutableBag $exportData)
]);
}

/**
* Add the user table to the export.
*
* @param MutableBag $exportData
*
* @throws \Bolt\Exception\InvalidRepositoryException
*/
private function addExportUsers(MutableBag $exportData)
{
$repo = $this->em->getRepository(Users::class);
$users = $repo->findAll();
$export = [];
/** @var Entity $user */
foreach ($users as $user) {
$export[] = Bag::from($user->toArray())
->filter(function ($k) {
return \in_array($k, ['id', 'username', 'displayname', 'password', 'email', 'enabled', 'roles']);
}
);
}
$exportData->set('__users', $export);
}

/**
* Get the records for a given ContentType.
*
* @param string $contentTypeName
* @param MutableBag $exportData
* @param MutableBag $responseBag
*
* @throws \Bolt\Exception\InvalidRepositoryException
*/
private function getRecords($contentTypeName, MutableBag $exportData, MutableBag $responseBag)
{
Expand Down
34 changes: 33 additions & 1 deletion src/Storage/Migration/Import.php
Expand Up @@ -12,6 +12,7 @@
use Bolt\Storage\Field\Type\TaxonomyType;
use Bolt\Storage\Query\Query;
use Bolt\Storage\Repository;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use RuntimeException;

/**
Expand Down Expand Up @@ -48,13 +49,19 @@ public function __construct(EntityManager $em, Query $query, Bag $contentTypes)
* @param Bag $importData
* @param MutableBag $responseBag
* @param bool $overwrite
* @param Bag $importUsers
*
* @throws \Bolt\Exception\InvalidRepositoryException
*
* @return MutableBag
*/
public function run(Bag $importData, MutableBag $responseBag, $overwrite = false)
public function run(Bag $importData, MutableBag $responseBag, $overwrite = false, Bag $importUsers = null)
{
$this->validateContentTypes($importData);
$relationQueue = MutableBag::from([]);
if ($importUsers) {
$this->importUsers($importUsers, $responseBag);
}

foreach ($importData as $contentTypeName => $recordsData) {
$this->importContentType($contentTypeName, $recordsData, $relationQueue, $responseBag, $overwrite);
Expand All @@ -64,6 +71,29 @@ public function run(Bag $importData, MutableBag $responseBag, $overwrite = false
return $responseBag;
}

/**
* @param Bag $importUsers
* @param MutableBag $responseBag
*
* @throws \Bolt\Exception\InvalidRepositoryException
*/
private function importUsers(Bag $importUsers, MutableBag $responseBag)
{
/** @var Repository\UsersRepository $repo */
$repo = $this->em->getRepository(Entity\Users::class);

foreach ($importUsers as $user) {
$entity = new Entity\Users($user->toArrayRecursive());
$entity->setId(null);
try {
$repo->save($entity);
$responseBag->get('success')->add(sprintf('Added user "%s".', $entity->getUsername()));
} catch (UniqueConstraintViolationException $e) {
$responseBag->get('warning')->add(sprintf('Skipping user "%s" as it already exists.', $entity->getUsername()));
}
}
}

/**
* Perform an import for records under a single ContentType key.
*
Expand All @@ -72,6 +102,8 @@ public function run(Bag $importData, MutableBag $responseBag, $overwrite = false
* @param MutableBag $relationQueue
* @param MutableBag $responseBag
* @param bool $overwrite
*
* @throws \Bolt\Exception\InvalidRepositoryException
*/
private function importContentType(
$contentTypeName,
Expand Down