Commit 715ba450 by Bartosz Kubicki

Repository init

parents
<?php
declare(strict_types=1);
/**
* File: MysqlConnectionPoolInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource;
use LizardMedia\AbstractDataMigration\Exception\Blocking\CouldNotLaunchMigrationException;
use Magento\Framework\DB\Adapter\AdapterInterface;
/**
* Interface MysqlConnectionPoolInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource
*/
interface MysqlConnectionPoolInterface
{
/**
* @param string $name
* @return AdapterInterface
* @throws CouldNotLaunchMigrationException
*/
public function getConnectionByName(string $name): AdapterInterface;
}
<?php
declare(strict_types=1);
/**
* File: MysqlModifierInjectorInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2019 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource;
use LizardMedia\AbstractDataMigration\Api\Data\DataSource\ModifierInjectorInterface;
/**
* Interface MysqlModifierInjectorInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource
*/
interface MysqlModifierInjectorInterface extends ModifierInjectorInterface
{
}
<?php
declare(strict_types=1);
/**
* File: SelectDecoratorInterface.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource;
use Magento\Framework\DB\Select;
/**
* Interface SelectDecoratorInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource
*/
interface SelectDecoratorInterface
{
/**
* @param Select $select
* @return void
*/
public function decorate(Select $select): void;
}
<?php
declare(strict_types=1);
/**
* File: ManagerInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session;
use LizardMedia\AbstractDataMigration\Exception\Blocking\NoContextException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\SessionVariableInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use LizardMedia\MysqlDataMigration\Exception\Blocking\SessionVariablesManipulationException;
/**
* Interface ManagerInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session
*/
interface ManagerInterface
{
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param SessionVariableInterface $sessionVariable
* @return void
* @throws SessionVariablesManipulationException
*/
public function setSessionVariable(
MysqlDataSourceInterface $mysqlDataSource,
SessionVariableInterface $sessionVariable
): void;
/**
* @return void
* @throws NoContextException
* @throws SessionVariablesManipulationException
*/
public function setSessionVariablesByRegistry(): void;
}
<?php
declare(strict_types=1);
/**
* File: RegistryInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\SessionVariableInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
/**
* Interface RegistryInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session
*/
interface RegistryInterface extends \Traversable
{
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param SessionVariableInterface $sessionVariable
* @return void
*/
public function add(MysqlDataSourceInterface $mysqlDataSource, SessionVariableInterface $sessionVariable): void;
}
<?php
declare(strict_types=1);
/**
* File: SessionVariableArrayInterface.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\SessionVariableInterface;
/**
* Interface SessionVariableArrayInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session
*/
interface SessionVariableArrayInterface extends \Traversable
{
/**
* @param SessionVariableInterface $sessionVariable
* @return void
*/
public function add(SessionVariableInterface $sessionVariable): void;
}
<?php
declare(strict_types=1);
/**
* File: SessionVariableInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb;
/**
* Interface SessionVariableInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb
*/
interface SessionVariableInterface
{
/**
* @return string
*/
public function getName(): string;
/**
* @return string
*/
public function getValue(): string;
}
<?php
declare(strict_types=1);
/**
* File: ManagerInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndexInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use LizardMedia\MysqlDataMigration\Exception\TemporaryIndexManipulationException;
/**
* Class ManagerInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex
*/
interface ManagerInterface
{
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param TemporaryIndexInterface $temporaryIndex
* @return void
*/
public function addIndex(
MysqlDataSourceInterface $mysqlDataSource,
TemporaryIndexInterface $temporaryIndex
): void;
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param TemporaryIndexInterface $temporaryIndex
* @return void
*/
public function removeIndex(
MysqlDataSourceInterface $mysqlDataSource,
TemporaryIndexInterface $temporaryIndex
): void;
/**
* @return void
* @throws TemporaryIndexManipulationException
*/
public function addIndexesBasingOnRegistry(): void;
/**
* @return void
* @throws TemporaryIndexManipulationException
*/
public function removeIndexBasingRegistry(): void;
}
<?php
declare(strict_types=1);
/**
* File: RegistryInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndexInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use Traversable;
/**
* Interface RegistryInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex
*/
interface RegistryInterface extends Traversable
{
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param TemporaryIndexInterface $temporaryIndex
* @return void
*/
public function register(MysqlDataSourceInterface $mysqlDataSource, TemporaryIndexInterface $temporaryIndex): void;
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param TemporaryIndexInterface $temporaryIndex
* @return void
*/
public function unregister(
MysqlDataSourceInterface $mysqlDataSource,
TemporaryIndexInterface $temporaryIndex
): void;
}
<?php
declare(strict_types=1);
/**
* File: TemporaryIndexInterface.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb;
/**
* Interface TemporaryIndexInterface
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb
*/
interface TemporaryIndexInterface
{
/**
* @return string
*/
public function getTableName(): string;
/**
* @return array
*/
public function getColumns(): array;
/**
* @return string
*/
public function getType(): string;
}
<?php
declare(strict_types=1);
/**
* File: MysqlDataSourceInterface.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Api\Data;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceInterface;
use Magento\Framework\DB\Select;
/**
* Interface MysqlDataSourceInterface
* @package LizardMedia\MysqlDataMigration\Api\Data
*/
interface MysqlDataSourceInterface extends DataSourceInterface
{
/**
* @var string
*/
public const TYPE_CODE = 'mysql';
/**
* @var string
*/
public const ORIGIN_INTERNAL = 'default';
/**
* @var string
*/
public const ORIGIN_EXTERNAL = 'migration';
/**
* @return Select
*/
public function getSelect(): Select;
/**
* @return string
*/
public function getOrigin(): string;
}
<?php
declare(strict_types=1);
/**
* File: MysqlDataSourceReaderFactoryInterface.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Api\Data;
use LizardMedia\AbstractDataMigration\Api\Data\DataConsumptionStrategyInterface;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceReaderInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\Parser\ParserArrayInterface;
use Magento\Framework\DB\Select;
/**
* Interface MysqlDataSourceReaderFactoryInterface
* @package LizardMedia\MysqlDataMigration\Api\Data
*/
interface MysqlDataSourceReaderFactoryInterface
{
/**
* @param DataConsumptionStrategyInterface $dataConsumptionStrategy
* @param ParserArrayInterface $parserArray
* @param MysqlDataSourceInterface $mysqlDataSource
* @param Select $select
* @param string $origin
* @return DataSourceReaderInterface
*/
public function create(
DataConsumptionStrategyInterface $dataConsumptionStrategy,
ParserArrayInterface $parserArray,
MysqlDataSourceInterface $mysqlDataSource,
Select $select,
string $origin
): DataSourceReaderInterface;
}
<?php
declare(strict_types=1);
/**
* File: SessionVariablesManipulationException.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Exception\Blocking;
use LizardMedia\AbstractDataMigration\Api\Exception\Blocking;
use Magento\Framework\Exception\LocalizedException;
/**
* Class SessionVariablesManipulationException
* @package LizardMedia\MysqlDataMigration\Exception\Blocking
*/
class SessionVariablesManipulationException extends LocalizedException implements Blocking
{
}
<?php
declare(strict_types=1);
/**
* File: TemporaryIndexManagerException.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Exception;
use LizardMedia\AbstractDataMigration\Api\Exception\Blocking;
use Magento\Framework\Exception\AbstractAggregateException;
/**
* Class TemporaryIndexManagerException
* @package LizardMedia\MysqlDataMigration\Exception
*/
class TemporaryIndexManipulationException extends AbstractAggregateException implements Blocking
{
}
<?php
declare(strict_types=1);
/**
* File: AbstractMysqlModifier.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier;
use LizardMedia\AbstractDataMigration\Api\Data\DataSource\ModifierInterface;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
/**
* TODO: Abstract unit test
* Class AbstractMysqlModifier
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier
*/
abstract class AbstractMysqlModifier implements ModifierInterface
{
/**
* @param DataSourceInterface $dataSource
*
* @return bool
*/
public function isApplicable(DataSourceInterface $dataSource): bool
{
return $dataSource->getType() === MysqlDataSourceInterface::TYPE_CODE;
}
}
<?php
declare(strict_types=1);
/**
* File: Condition.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use Magento\Framework\Exception\NoSuchEntityException;
/**
* TODO: Unit test
* Class Condition
* @package LizardMedia\MysqlDataMigration\Model\MigrationProcessor\Task\Modifier
*/
class Condition extends AbstractMysqlModifier
{
/**
* @var string
*/
private $modification;
/**
* Condition constructor.
* @param string $modification
*/
public function __construct(string $modification)
{
$this->modification = $modification;
}
/**
* @param DataSourceInterface|MysqlDataSourceInterface $dataSource
* @return void
* @throws NoSuchEntityException
*/
public function modify(DataSourceInterface $dataSource): void
{
if (empty($this->modification)) {
throw new NoSuchEntityException(__('No modification provided'));
}
if ($this->isApplicable($dataSource)) {
$select = $dataSource->getSelect();
$select->where($this->modification);
}
}
}
<?php
declare(strict_types=1);
/**
* File: Limit.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use Magento\Framework\DB\Select;
use Magento\Framework\Exception\NoSuchEntityException;
/**
* TODO: Unit test
* Class Limit
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier
*/
class Limit extends AbstractMysqlModifier
{
/**
* @var string
*/
private $modification;
/**
* Condition constructor.
* @param string $modification
*/
public function __construct(string $modification)
{
$this->modification = $modification;
}
/**
* @param DataSourceInterface|MysqlDataSourceInterface $dataSource
* @return void
* @throws NoSuchEntityException
*/
public function modify(DataSourceInterface $dataSource): void
{
if (empty($this->modification)) {
throw new NoSuchEntityException(__('No modification provided'));
}
if ($this->isApplicable($dataSource)) {
$select = $dataSource->getSelect();
$parts = $this->extractParts($this->modification);
$this->applyParts($select, $parts);
}
}
/**
* @param string $modification
* @return array
*/
private function extractParts(string $modification): array
{
return explode(',', $modification);
}
/**
* @param Select $select
* @param array $parts
* @return void
*/
private function applyParts(Select $select, array $parts): void
{
$limit = reset($parts);
next($parts);
$offset = current($parts);
empty($offset) ? $select->limit($limit) : $select->limit($limit, $offset);
}
}
<?php
declare(strict_types=1);
/**
* File: MysqlConnectionPool.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource;
use DomainException;
use LizardMedia\AbstractDataMigration\Exception\Blocking\CouldNotLaunchMigrationException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlConnectionPoolInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Adapter\AdapterInterface;
/**
* Class MysqlConnectionPool
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource
*/
class MysqlConnectionPool implements MysqlConnectionPoolInterface
{
/**
* @var array
*/
private $connections = [];
/**
* @var ResourceConnection
*/
private $resourceConnection;
/**
* MysqlConnectionPool constructor.
* @param ResourceConnection $resourceConnection
* @param array $connections
*/
public function __construct(ResourceConnection $resourceConnection, array $connections = [])
{
$this->connections = $connections;
$this->resourceConnection = $resourceConnection;
}
/**
* @param string $name
* @return AdapterInterface
* @throws CouldNotLaunchMigrationException
*/
public function getConnectionByName(string $name): AdapterInterface
{
if (isset($this->connections[$name]) && $this->connections instanceof AdapterInterface) {
return $this->connections[$name];
} else {
$this->connections[$name] = $this->instantiateConnection($name);
return $this->connections[$name];
}
}
/**
* @param string $name
* @return AdapterInterface
* @throws CouldNotLaunchMigrationException
*/
private function instantiateConnection(string $name): AdapterInterface
{
try {
return $this->resourceConnection->getConnection($name);
} catch (DomainException $exception) {
$this->throwCouldNotLaunchMigrationException($exception);
}
}
/**
* @param DomainException $exception
* @return void
* @throws CouldNotLaunchMigrationException
*/
private function throwCouldNotLaunchMigrationException(DomainException $exception): void
{
throw new CouldNotLaunchMigrationException(
__('Could not connect to external db: %1', $exception->getMessage())
);
}
}
<?php
declare(strict_types=1);
/**
* File: MysqlModifierInjector.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2019 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlModifierInjectorInterface;
use LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier\Condition;
use LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier\Limit;
use Magento\Framework\Api\ObjectFactory;
use function is_array;
/**
* TODO: Unit test
* Class MysqlModifierInjector
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource
*/
class MysqlModifierInjector implements MysqlModifierInjectorInterface
{
/**
* @var array
*/
private $modificationsMap = [
'where' => Condition::class,
'limit' => Limit::class
];
/**
* @var ObjectFactory
*/
private $objectFactory;
/**
* ModifierInjector constructor.
* @param ObjectFactory $objectFactory
*/
public function __construct(ObjectFactory $objectFactory)
{
$this->objectFactory = $objectFactory;
}
/**
* @param DataSourceInterface $dataSource
* @param array $modifications
* @return void
*/
public function inject(DataSourceInterface $dataSource, array $modifications): void
{
foreach ($modifications as $modificationType => $modification) {
if (!empty($this->modificationsMap[$modificationType])) {
$class = (string) $this->modificationsMap[$modificationType];
if (is_array($modification)) {
foreach ($modification as $singleModification) {
$modifier = $this->objectFactory->create($class, ['modification' => $singleModification]);
$dataSource->modify($modifier);
}
} else {
$modifier = $this->objectFactory->create($class, ['modification' => $modification]);
$dataSource->modify($modifier);
}
}
}
}
}
<?php
declare(strict_types=1);
/**
* File: Manager.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\Session;
use Exception;
use LizardMedia\AbstractDataMigration\Api\Context\RegistryInterface as ContextRegistryInterface;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourcePoolInterface;
use LizardMedia\AbstractDataMigration\Exception\Blocking\NoContextException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlConnectionPoolInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session\ManagerInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session\RegistryInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\SessionVariableInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use LizardMedia\MysqlDataMigration\Exception\Blocking\SessionVariablesManipulationException;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Exception\NoSuchEntityException;
/**
* TODO: Unit test
* Class Manager
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\Session
*/
class Manager implements ManagerInterface
{
/**
* @var ContextRegistryInterface
*/
private $contextRegistry;
/**
* @var MysqlConnectionPoolInterface
*/
private $mysqlConnectionPool;
/**
* @var RegistryInterface
*/
private $registry;
/**
* Manager constructor.
* @param ContextRegistryInterface $contextRegistry
* @param MysqlConnectionPoolInterface $mysqlConnectionPool
* @param RegistryInterface $registry
*/
public function __construct(
ContextRegistryInterface $contextRegistry,
MysqlConnectionPoolInterface $mysqlConnectionPool,
RegistryInterface $registry
) {
$this->contextRegistry = $contextRegistry;
$this->mysqlConnectionPool = $mysqlConnectionPool;
$this->registry = $registry;
}
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param SessionVariableInterface $sessionVariable
* @return void
* @throws SessionVariablesManipulationException
*/
public function setSessionVariable(
MysqlDataSourceInterface $mysqlDataSource,
SessionVariableInterface $sessionVariable
): void {
try {
$dbAdapter = $this->mysqlConnectionPool->getConnectionByName($mysqlDataSource->getOrigin());
$sessionVariableQuery = sprintf(
'SET SESSION %s = %s',
$sessionVariable->getName(),
$sessionVariable->getValue()
);
$dbAdapter->query($sessionVariableQuery);
} catch (Exception $exception) {
throw new SessionVariablesManipulationException(__($exception->getMessage()));
}
}
/**
* @return void
* @throws NoContextException
* @throws SessionVariablesManipulationException
*/
public function setSessionVariablesByRegistry(): void
{
foreach ($this->registry as $dataSourceName => $sessionVariables) {
try {
$context = $this->contextRegistry->get();
$dataSource = $context->getDataSourcePool()->getByName($dataSourceName);
} catch (NoSuchEntityException $exception) {
continue;
}
foreach ($sessionVariables as $sessionVariable) {
$this->setSessionVariable($dataSource, $sessionVariable);
}
}
}
}
<?php
declare(strict_types=1);
/**
* File: Registry.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\Session;
use Iterator;
use IteratorAggregate;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session\RegistryInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\SessionVariableInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use MSlwk\TypeSafeArray\ObjectArray;
use MSlwk\TypeSafeArray\ObjectArrayFactory;
/**
* TODO: Unit test
* Class Registry
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\Session
*/
class Registry implements IteratorAggregate, RegistryInterface
{
/**
* @var ObjectArray
*/
private $variables;
/**
* Registry constructor.
* @param ObjectArrayFactory $objectArrayFactory
* @param array $variables
*/
public function __construct(ObjectArrayFactory $objectArrayFactory, array $variables = [])
{
$this->variables = $objectArrayFactory->create(SessionVariableInterface::class, $variables);
}
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param SessionVariableInterface $sessionVariable
* @return void
*/
public function add(MysqlDataSourceInterface $mysqlDataSource, SessionVariableInterface $sessionVariable): void
{
$mysqlDataSourceName = $mysqlDataSource->getName();
if ($this->variables->offsetExists($mysqlDataSourceName)) {
$exitingVariables = $this->variables->offsetGet($mysqlDataSourceName);
$exitingVariables[spl_object_hash($sessionVariable)] = $sessionVariable;
$this->variables->offsetSet($mysqlDataSourceName, $exitingVariables);
} else {
$this->variables->offsetSet(
$mysqlDataSource->getName(),
[spl_object_hash($sessionVariable) => $sessionVariable]
);
}
}
/**
* @return Iterator
*/
public function getIterator(): Iterator
{
return $this->variables;
}
}
<?php
declare(strict_types=1);
/**
* File: SessionVariable.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\SessionVariableInterface;
/**
* TODO: Unit test
* Class SessionVariable
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb
*/
class SessionVariable implements SessionVariableInterface
{
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $value;
/**
* SessionVariable constructor.
* @param string $name
* @param string $value
*/
public function __construct(string $name, string $value)
{
$this->name = $name;
$this->value = $value;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}
}
<?php
declare(strict_types=1);
/**
* File: TemporaryIndex.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndexInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;
/**
* TODO: Unit test
* Class TemporaryIndex
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb
*/
class TemporaryIndex implements TemporaryIndexInterface
{
/**
* @var string
*/
private $tableName;
/**
* @var array
*/
private $columns;
/**
* @var string
*/
private $type;
/**
* TemporaryIndex constructor.
* @param string $tableName
* @param array $columns
* @param string $type
*/
public function __construct(string $tableName, array $columns, string $type = AdapterInterface::INDEX_TYPE_INDEX)
{
$this->tableName = $tableName;
$this->columns = $columns;
$this->type = $type;
}
/**
* @return string
*/
public function getTableName(): string
{
return $this->tableName;
}
/**
* @return array
*/
public function getColumns(): array
{
return $this->columns;
}
/**
* @return string
*/
public function getType(): string
{
return $this->type;
}
}
<?php
declare(strict_types=1);
/**
* File: Manager.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\TemporaryIndex;
use LizardMedia\AbstractDataMigration\Api\Context\RegistryInterface as ContextRegistryInterface;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceInterface;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourcePoolInterface;
use LizardMedia\AbstractDataMigration\Exception\Blocking\NoContextException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlConnectionPoolInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex\ManagerInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex\RegistryInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndexInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use LizardMedia\MysqlDataMigration\Exception\TemporaryIndexManipulationException;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Phrase;
/**
* TODO: Unit test
* Class Manager
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\TemporaryIndex
*/
class Manager implements ManagerInterface
{
/**
* @var array
*/
private $errors = [];
/**
* @var ContextRegistryInterface
*/
private $contextRegistry;
/**
* @var MysqlConnectionPoolInterface
*/
private $mysqlConnectionPool;
/**
* @var RegistryInterface
*/
private $registry;
/**
* Manager constructor.
* @param ContextRegistryInterface $contextRegistry
* @param MysqlConnectionPoolInterface $mysqlConnectionPool
* @param RegistryInterface $registry
*/
public function __construct(
ContextRegistryInterface $contextRegistry,
MysqlConnectionPoolInterface $mysqlConnectionPool,
RegistryInterface $registry
) {
$this->contextRegistry = $contextRegistry;
$this->mysqlConnectionPool = $mysqlConnectionPool;
$this->registry = $registry;
}
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param TemporaryIndexInterface $temporaryIndex
* @return void
* @throws \Exception
*/
public function addIndex(
MysqlDataSourceInterface $mysqlDataSource,
TemporaryIndexInterface $temporaryIndex
): void {
$tableName = $temporaryIndex->getTableName();
$columns = $temporaryIndex->getColumns();
$type = $temporaryIndex->getType();
$dbAdapter = $this->mysqlConnectionPool->getConnectionByName($mysqlDataSource->getOrigin());
$indexName = $this->generateIndexName(
$dbAdapter,
$tableName,
$columns,
$type
);
if (!array_key_exists($indexName, $dbAdapter->getIndexList($tableName))) {
$dbAdapter->addIndex(
$tableName,
$indexName,
$columns,
$type
);
}
}
/**
* @param TemporaryIndexInterface $temporaryIndex
* @param MysqlDataSourceInterface $mysqlDataSource
* @return void
* @throws \Exception
*/
public function removeIndex(
MysqlDataSourceInterface $mysqlDataSource,
TemporaryIndexInterface $temporaryIndex
) : void {
$tableName = $temporaryIndex->getTableName();
$columns = $temporaryIndex->getColumns();
$type = $temporaryIndex->getType();
$dbAdapter = $this->mysqlConnectionPool->getConnectionByName($mysqlDataSource->getOrigin());
$indexName = $this->generateIndexName(
$dbAdapter,
$tableName,
$columns,
$type
);
if (array_key_exists($indexName, $dbAdapter->getIndexList($tableName))) {
$dbAdapter->dropIndex(
$tableName,
$indexName
);
}
}
/**
* @return void
* @throws TemporaryIndexManipulationException
*/
public function addIndexesBasingOnRegistry(): void
{
$this->errors = [];
foreach ($this->registry as $dataSourceName => $indexesForDataSource) {
/** @var $index TemporaryIndexInterface */
try {
$context = $this->contextRegistry->get();
$dataSource = $context->getDataSourcePool()->getByName($dataSourceName);
} catch (NoContextException $exception) {
$this->errors[] = $exception->getMessage();
throw $this->generateAggregateException();
} catch (NoSuchEntityException $exception) {
continue;
}
$this->iterateAndAddIndexes($dataSource, $indexesForDataSource);
}
if (count($this->errors) > 0) {
throw $this->generateAggregateException();
}
}
/**
* @return void
* @throws TemporaryIndexManipulationException
*/
public function removeIndexBasingRegistry(): void
{
$this->errors = [];
foreach ($this->registry as $dataSourceName => $indexesForDataSource) {
/** @var $index TemporaryIndexInterface */
try {
$context = $this->contextRegistry->get();
$dataSource = $context->getDataSourcePool()->getByName($dataSourceName);
} catch (NoContextException $exception) {
$this->errors[] = $exception->getMessage();
throw $this->generateAggregateException();
} catch (NoSuchEntityException $exception) {
continue;
}
$this->iterateAndRemoveIndexes($dataSource, $indexesForDataSource);
}
if (count($this->errors) > 0) {
throw $this->generateAggregateException();
}
}
/**
* @param DataSourceInterface $dataSource
* @param array $indexes
* @return void
*/
private function iterateAndAddIndexes(DataSourceInterface $dataSource, array $indexes): void
{
foreach ($indexes as $index) {
try {
$this->addIndex($dataSource, $index);
} catch (\Exception $exception) {
$this->errors[] = $exception->getMessage();
continue;
}
}
}
/**
* @param DataSourceInterface $dataSource
* @param array $indexes
* @return void
*/
private function iterateAndRemoveIndexes(DataSourceInterface $dataSource, array $indexes): void
{
foreach ($indexes as $index) {
try {
$this->removeIndex($dataSource, $index);
$this->registry->unregister($dataSource, $index);
} catch (\Exception $exception) {
$this->registry->unregister($dataSource, $index);
$this->errors[] = $exception->getMessage();
continue;
}
}
}
/**
* @param AdapterInterface $dbAdapter
* @param string $tableName
* @param array $columns
* @param string $type
* @return string
*/
private function generateIndexName(
AdapterInterface $dbAdapter,
string $tableName,
array $columns,
string $type
): string {
return $dbAdapter->getIndexName($tableName, $columns, $type);
}
/**
* @return TemporaryIndexManipulationException
*/
private function generateAggregateException(): TemporaryIndexManipulationException
{
$exception = new TemporaryIndexManipulationException(
__('Errors occurred during temporary indexeses operations: ')
);
foreach ($this->errors as $error) {
$exception->addError(new Phrase($error));
}
return $exception;
}
}
<?php
declare(strict_types=1);
/**
* File: Registry.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\TemporaryIndex;
use Iterator;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndexInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex\RegistryInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use MSlwk\TypeSafeArray\ObjectArray;
use MSlwk\TypeSafeArray\ObjectArrayFactory;
/**
* TODO: Unit test
* Class Registry
* @package LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\TemporaryIndex
*/
class Registry implements \IteratorAggregate, RegistryInterface
{
/**
* @var ObjectArray
*/
private $temporaryIndexes;
/**
* Registry constructor.
* @param ObjectArrayFactory $objectArrayFactory
* @param array $temporaryIndexes
*/
public function __construct(ObjectArrayFactory $objectArrayFactory, array $temporaryIndexes = [])
{
$this->temporaryIndexes = $objectArrayFactory->create(TemporaryIndexInterface::class, $temporaryIndexes);
}
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param TemporaryIndexInterface $temporaryIndex
* @return void
*/
public function register(MysqlDataSourceInterface $mysqlDataSource, TemporaryIndexInterface $temporaryIndex): void
{
$mysqlDataSourceName = $mysqlDataSource->getName();
if ($this->temporaryIndexes->offsetExists($mysqlDataSourceName)) {
$exitingVariables = $this->temporaryIndexes->offsetGet($mysqlDataSourceName);
$exitingVariables[spl_object_hash($temporaryIndex)] = $temporaryIndex;
$this->temporaryIndexes->offsetSet($mysqlDataSourceName, $exitingVariables);
} else {
$this->temporaryIndexes->offsetSet(
$mysqlDataSource->getName(),
[spl_object_hash($temporaryIndex) => $temporaryIndex]
);
}
}
/**
* @param MysqlDataSourceInterface $mysqlDataSource
* @param TemporaryIndexInterface $temporaryIndex
* @return void
*/
public function unregister(MysqlDataSourceInterface $mysqlDataSource, TemporaryIndexInterface $temporaryIndex): void
{
$mysqlDataSourceName = $mysqlDataSource->getName();
$temporaryIndexHash = spl_object_hash($temporaryIndex);
if ($this->temporaryIndexes->offsetExists($mysqlDataSourceName)) {
$mysqlDataSourceTemporaryIndexes = $this->temporaryIndexes->offsetGet($mysqlDataSourceName);
unset($mysqlDataSourceTemporaryIndexes[$temporaryIndexHash]);
$this->temporaryIndexes->offsetSet($mysqlDataSourceName, $mysqlDataSourceTemporaryIndexes);
}
}
/**
* @return Iterator
*/
public function getIterator(): Iterator
{
return $this->temporaryIndexes;
}
}
<?php
declare(strict_types=1);
/**
* File: MysqlDataSource.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Model\Data;
use LizardMedia\AbstractDataMigration\Api\Data\DataConsumptionStrategyInterface;
use LizardMedia\AbstractDataMigration\Api\Data\DataSource\ModifierArrayInterfaceFactory;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceReaderInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\Parser\ParserArrayInterfaceFactory;
use LizardMedia\AbstractDataMigration\Model\Data\AbstractDataSource;
use LizardMedia\AbstractDataMigration\Exception\Blocking\CouldNotLaunchMigrationException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlConnectionPoolInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SelectDecoratorInterface;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session\RegistryInterface as SessionVariablesRegistry;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex\RegistryInterface
as TemporaryIndexRegistry;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceReaderFactoryInterface;
use Magento\Framework\DB\Select;
use MSlwk\TypeSafeArray\ObjectArray;
use MSlwk\TypeSafeArray\ObjectArrayFactory;
use Zend_Db_Exception;
/**
* Class MysqlDataSource
* @package LizardMedia\MysqlDataMigration\Api\Data\DataSource
*/
class MysqlDataSource extends AbstractDataSource implements MysqlDataSourceInterface
{
/**
* @var MysqlConnectionPoolInterface
*/
private $mysqlConnectionPool;
/**
* @var SessionVariablesRegistry
*/
private $sessionVariablesRegistry;
/**
* @var TemporaryIndexRegistry
*/
private $temporaryIndexRegistry;
/**
* @var MysqlDataSourceReaderFactory
*/
private $mysqlDataSourceReaderFactory;
/**
* @var null|Select
*/
private $select = null;
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $origin;
/**
* @var ObjectArray
*/
private $selectDecorators;
/**
* MysqlDataSource constructor.
*
* @param ModifierArrayInterfaceFactory $modifierArrayFactory
* @param DataConsumptionStrategyInterface $dataConsumptionStrategy
* @param ParserArrayInterfaceFactory $parserArrayFactory
* @param MysqlConnectionPoolInterface $mysqlConnectionPool
* @param SessionVariablesRegistry $sessionVariablesRegistry
* @param TemporaryIndexRegistry $temporaryIndexRegistry
* @param MysqlDataSourceReaderFactoryInterface $mysqlDataSourceReaderFactory
* @param ObjectArrayFactory $objectArrayFactory
* @param string $name
* @param string $origin
* @param array $selectDecorators
*/
public function __construct(
ModifierArrayInterfaceFactory $modifierArrayFactory,
DataConsumptionStrategyInterface $dataConsumptionStrategy,
ParserArrayInterfaceFactory $parserArrayFactory,
MysqlConnectionPoolInterface $mysqlConnectionPool,
SessionVariablesRegistry $sessionVariablesRegistry,
TemporaryIndexRegistry $temporaryIndexRegistry,
MysqlDataSourceReaderFactoryInterface $mysqlDataSourceReaderFactory,
ObjectArrayFactory $objectArrayFactory,
string $name,
string $origin = MysqlDataSourceInterface::ORIGIN_INTERNAL,
array $selectDecorators = []
) {
parent::__construct($modifierArrayFactory, $dataConsumptionStrategy, $parserArrayFactory);
$this->mysqlConnectionPool = $mysqlConnectionPool;
$this->sessionVariablesRegistry = $sessionVariablesRegistry;
$this->temporaryIndexRegistry = $temporaryIndexRegistry;
$this->mysqlDataSourceReaderFactory = $mysqlDataSourceReaderFactory;
$this->name = $name;
$this->origin = $origin;
$this->selectDecorators = $objectArrayFactory->create(SelectDecoratorInterface::class, $selectDecorators);
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getType(): string
{
return MysqlDataSourceInterface::TYPE_CODE;
}
/**
* @return Select
* @throws CouldNotLaunchMigrationException
*/
public function getSelect(): Select
{
if (!$this->select instanceof Select) {
$adapter = $this->mysqlConnectionPool->getConnectionByName($this->origin);
$select = $adapter->select();
foreach ($this->selectDecorators as $selectDecorator) {
/** @var $selectDecorator SelectDecoratorInterface */
$this->decorate($select, $selectDecorator);
}
$this->select = $select;
}
return $this->select;
}
/**
* @return string
*/
public function getOrigin(): string
{
return $this->origin;
}
/**
* @param DataConsumptionStrategyInterface $dataConsumptionStrategy
* @return DataSourceReaderInterface
* @throws CouldNotLaunchMigrationException
*/
protected function instantiateDataSourceReader(
DataConsumptionStrategyInterface $dataConsumptionStrategy
): DataSourceReaderInterface {
return $this->mysqlDataSourceReaderFactory->create(
$this->dataConsumptionStrategy,
$this->parserArray,
$this,
$this->getSelect(),
$this->getOrigin()
);
}
/**
* @param Select $select
* @param SelectDecoratorInterface $decorator
* @return void
* @throws CouldNotLaunchMigrationException
*/
private function decorate(Select $select, SelectDecoratorInterface $decorator): void
{
try {
$decorator->decorate($select);
} catch (Zend_Db_Exception $exception) {
throw new CouldNotLaunchMigrationException(__('Could not decorate select'), $exception);
}
}
}
<?php
declare(strict_types=1);
/**
* File: MysqlDataSourceCachingReader.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Model\Data;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\FetchStrategy\ConditionInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\FetchStrategyInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\Parser\ParserArrayInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\Parser\ParserRunnerInterface;
use LizardMedia\AbstractDataMigration\Api\Data\EntityInterface;
use LizardMedia\AbstractDataMigration\Api\Data\EntityInterfaceFactory;
use LizardMedia\AbstractDataMigration\Exception\Blocking\CouldNotLaunchMigrationException;
use LizardMedia\AbstractDataMigration\Exception\Blocking\TransportationException;
use LizardMedia\AbstractDataMigration\Model\Data\AbstractDataSourceReader;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlConnectionPoolInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\DB\Select;
use React\Cache\ArrayCache;
use React\Cache\ArrayCacheFactory;
use Zend_Db_Select_Exception;
use Zend_Db_Statement_Exception;
/**
* TODO: Unit test
* Class MysqlDataSourceReader
* @package LizardMedia\MysqlDataMigration\Model\Data
*/
class MysqlDataSourceCachingReader extends AbstractDataSourceReader
{
/**
* @var array
*/
private $baseConditions;
/**
* @var EntityInterfaceFactory
*/
private $entityInterfaceFactory;
/**
* @var MysqlConnectionPoolInterface
*/
private $mysqlConnectionPool;
/**
* @var AdapterInterface
*/
private $adapter;
/**
* @var Select
*/
private $select;
/**
* @var ArrayCache
*/
private $cache;
/**
* MysqlDataSourceReader constructor.
*
* @param DataSourceInterface $dataSource
* @param ParserArrayInterface $parserArray
* @param ParserRunnerInterface $parserRunner
* @param EntityInterfaceFactory $entityInterfaceFactory
* @param MysqlConnectionPoolInterface $mysqlConnectionPool
* @param Select $select
* @param ArrayCacheFactory $cacheFactory
* @param string $mysqlDataSourceOrigin
* @throws CouldNotLaunchMigrationException
* @SuppressWarnings(PHPMD.LongVariable)
*/
public function __construct(
DataSourceInterface $dataSource,
ParserArrayInterface $parserArray,
ParserRunnerInterface $parserRunner,
EntityInterfaceFactory $entityInterfaceFactory,
MysqlConnectionPoolInterface $mysqlConnectionPool,
Select $select,
ArrayCacheFactory $cacheFactory,
string $mysqlDataSourceOrigin
) {
parent::__construct($dataSource, $parserArray, $parserRunner);
$this->entityInterfaceFactory = $entityInterfaceFactory;
$this->mysqlConnectionPool = $mysqlConnectionPool;
$this->select = $select;
$this->cache = $cacheFactory->create();
$this->resolveDbConnection($mysqlDataSourceOrigin);
}
/**
* @return int
* @throws TransportationException
*/
public function countEntities(): int
{
try {
return (int) count($this->adapter->fetchAll($this->select));
} catch (Zend_Db_Statement_Exception $exception) {
$this->throwTransportationException($exception);
}
}
/**
* @param FetchStrategyInterface $fetchStrategy
* @return EntityInterface
* @throws TransportationException
*/
public function fetch(FetchStrategyInterface $fetchStrategy = null): EntityInterface
{
$fetchStrategy
? $condition = $fetchStrategy->getCondition()
: $condition = null;
$entity = $this->readFromDbUsingCache($condition);
$this->parserRunner->runParsing($entity, $this->parserArray);
return $entity;
}
/**
* @param string $origin
* @return void
* @throws CouldNotLaunchMigrationException
*/
private function resolveDbConnection(string $origin): void
{
$this->adapter = $this->mysqlConnectionPool->getConnectionByName($origin);
}
/**
* @param ConditionInterface|null $condition
* @return EntityInterface
* @throws TransportationException
*/
private function readFromDbUsingCache(ConditionInterface $condition = null): EntityInterface
{
try {
//TODO: Optimize to not create $entity object two times
$entity = $this->entityInterfaceFactory->create();
$condition
? $instruction = $condition->getInstruction()
: $instruction = null;
$this->cache->get($instruction)
->then(function (?array $data) use ($condition, &$entity) {
if ($data === null) {
$this->writeDownBaseConditions($this->select);
$this->applyFilteringConditions($this->select, $condition->getInstruction());
$data = $this->adapter->fetchAll($this->select);
$this->applyDefaultConditionsBack($this->select);
}
$entity = $this->entityInterfaceFactory->create(['data' => $data]);
$this->cache->set($condition->getInstruction(), $entity);
return $entity;
});
return $entity;
} catch (Zend_Db_Statement_Exception $exception) {
$this->throwTransportationException($exception);
}
}
/**
* @param Select $select
* @return void
* @throws Zend_Db_Select_Exception
*/
private function writeDownBaseConditions(Select $select) : void
{
$this->baseConditions = $select->getPart(\Zend_Db_Select::WHERE);
}
/**
* @param Select $select
* @param string $condition
* @return void
*/
private function applyFilteringConditions(Select $select, string $condition) : void
{
$select->where($condition);
}
/**
* @param Zend_Db_Statement_Exception $exception
* @return void
* @throws TransportationException
*/
private function throwTransportationException(Zend_Db_Statement_Exception $exception): void
{
throw new TransportationException(__($exception->getMessage()));
}
/**
* @param Select $select
* @return void
*/
private function applyDefaultConditionsBack(Select $select) : void
{
$select->reset(\Zend_Db_Select::WHERE);
foreach ($this->baseConditions as $condition) {
$select->where($condition);
}
$this->baseConditions = null;
}
}
<?php
declare(strict_types=1);
/**
* File: MysqlDataSourceReader.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Model\Data;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\FetchStrategyInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\Parser\ParserArrayInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\Parser\ParserRunnerInterface;
use LizardMedia\AbstractDataMigration\Api\Data\EntityInterface;
use LizardMedia\AbstractDataMigration\Api\Data\EntityInterfaceFactory;
use LizardMedia\AbstractDataMigration\Exception\Blocking\TransportationException;
use LizardMedia\AbstractDataMigration\Exception\NotBlocking\DataSourceConsumedException;
use LizardMedia\AbstractDataMigration\Model\Data\AbstractDataSourceReader;
use LizardMedia\AbstractDataMigration\Exception\Blocking\CouldNotLaunchMigrationException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlConnectionPoolInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\DB\Select;
use Zend_Db_Statement_Exception;
use Zend_Db_Statement_Interface;
/**
* TODO: Unit test
* Class MysqlDataSourceReader
* @package LizardMedia\MysqlDataMigration\Model\Data
*/
class MysqlDataSourceReader extends AbstractDataSourceReader
{
/**
* @var EntityInterfaceFactory
*/
private $entityInterfaceFactory;
/**
* @var MysqlConnectionPoolInterface
*/
private $mysqlConnectionPool;
/**
* @var AdapterInterface
*/
private $adapter;
/**
* @var Select
*/
private $select;
/**
* @var Zend_Db_Statement_Interface
*/
private $dbStatement;
/**
* MysqlDataSourceReader constructor.
*
* @param DataSourceInterface $dataSource
* @param ParserArrayInterface $parserArray
* @param ParserRunnerInterface $parserRunner
* @param EntityInterfaceFactory $entityInterfaceFactory
* @param MysqlConnectionPoolInterface $mysqlConnectionPool
* @param Select $select
* @param string $mysqlDataSourceOrigin
* @throws CouldNotLaunchMigrationException
*/
public function __construct(
DataSourceInterface $dataSource,
ParserArrayInterface $parserArray,
ParserRunnerInterface $parserRunner,
EntityInterfaceFactory $entityInterfaceFactory,
MysqlConnectionPoolInterface $mysqlConnectionPool,
Select $select,
string $mysqlDataSourceOrigin
) {
parent::__construct($dataSource, $parserArray, $parserRunner);
$this->entityInterfaceFactory = $entityInterfaceFactory;
$this->mysqlConnectionPool = $mysqlConnectionPool;
$this->select = $select;
$this->resolveDbConnection($mysqlDataSourceOrigin);
$this->createDbStatement();
}
/**
* @return int
* @throws TransportationException
*/
public function countEntities(): int
{
try {
return (int) $this->dbStatement->rowCount();
} catch (Zend_Db_Statement_Exception $exception) {
$this->throwTransportationException($exception);
}
}
/**
* @param FetchStrategyInterface $fetchStrategy
* @return EntityInterface
* @throws TransportationException
* @throws DataSourceConsumedException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function fetch(FetchStrategyInterface $fetchStrategy = null): EntityInterface
{
$entity = $this->readFromDb();
$this->parserRunner->runParsing($entity, $this->parserArray);
return $entity;
}
/**
* @return EntityInterface
* @throws TransportationException
* @throws DataSourceConsumedException
*/
protected function readFromDb(): EntityInterface
{
try {
$data = $this->dbStatement->fetch();
if ($data === false) {
$this->throwDataSourceConsumedException();
}
return $this->entityInterfaceFactory->create(['data' => $data]);
} catch (Zend_Db_Statement_Exception $exception) {
$this->throwTransportationException($exception);
}
}
/**
* @param string $origin
* @return void
* @throws CouldNotLaunchMigrationException
*/
private function resolveDbConnection(string $origin): void
{
$this->adapter = $this->mysqlConnectionPool->getConnectionByName($origin);
}
/**
* @return void
*/
private function createDbStatement(): void
{
$this->dbStatement = $this->adapter->query($this->select);
}
/**
* @param Zend_Db_Statement_Exception $exception
* @return void
* @throws TransportationException
*/
private function throwTransportationException(Zend_Db_Statement_Exception $exception): void
{
throw new TransportationException(__($exception->getMessage()));
}
/**
* @return void
* @throws DataSourceConsumedException
*/
private function throwDataSourceConsumedException(): void
{
throw new DataSourceConsumedException(__('No more entities to be iterated'));
}
}
<?php
declare(strict_types=1);
/**
* File: MysqlDataSourceReaderFactory.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Model\Data;
use LizardMedia\AbstractDataMigration\Api\Data\DataConsumptionStrategyInterface;
use LizardMedia\AbstractDataMigration\Api\Data\DataSourceReaderInterface;
use LizardMedia\AbstractDataMigration\Api\Data\Entity\Parser\ParserArrayInterface;
use LizardMedia\AbstractDataMigration\Model\Data\DataConsumptionStrategy\SelfConsuming;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface;
use LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceReaderFactoryInterface;
use Magento\Framework\DB\Select;
use Magento\Framework\ObjectManagerInterface;
/**
* TODO: Unit test
* Class MysqlDataSourceReaderFactory
* @package LizardMedia\MysqlDataMigration\Model\Data
*/
class MysqlDataSourceReaderFactory implements MysqlDataSourceReaderFactoryInterface
{
/**
* @var ObjectManagerInterface
*/
private $objectManager;
/**
* MysqlDataSourceReaderFactory constructor.
* @param ObjectManagerInterface $objectManager
*/
public function __construct(ObjectManagerInterface $objectManager)
{
$this->objectManager = $objectManager;
}
/**
* @param DataConsumptionStrategyInterface $dataConsumptionStrategy
* @param ParserArrayInterface $parserArray
* @param MysqlDataSourceInterface $mysqlDataSource
* @param Select $select
* @param string $origin
* @return DataSourceReaderInterface
*/
public function create(
DataConsumptionStrategyInterface $dataConsumptionStrategy,
ParserArrayInterface $parserArray,
MysqlDataSourceInterface $mysqlDataSource,
Select $select,
string $origin
): DataSourceReaderInterface {
$arguments = [
'dataSource' => $mysqlDataSource,
'parserArray' => $parserArray,
'select' => $select,
'mysqlDataSourceOrigin' => $origin
];
return $dataConsumptionStrategy->getType() === SelfConsuming::STRATEGY_SELF_CONSUMING
? $this->objectManager->create(MysqlDataSourceReader::class, $arguments)
: $this->objectManager->create(MysqlDataSourceCachingReader::class, $arguments);
}
}
<?php
declare(strict_types=1);
/**
* File: SessionVariablesSetUpTask.php
*
* @author Bartosz Kubicki bartosz.kubicki@lizardmedia.pl>
* @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
*/
namespace LizardMedia\MysqlDataMigration\Model\Migration\Processor\Task;
use LizardMedia\AbstractDataMigration\Api\Migration\Processor\TaskInterface;
use LizardMedia\AbstractDataMigration\Exception\Blocking\NoContextException;
use LizardMedia\AbstractDataMigration\Exception\NotBlocking\TaskException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session\ManagerInterface;
use LizardMedia\MysqlDataMigration\Exception\Blocking\SessionVariablesManipulationException;
/**
* TODO: Unit test
* Class SessionVariablesSetUpTask
* @package LizardMedia\MysqlDataMigration\Model\Migration\Processor\Worker\Task
*/
class SessionVariablesSetUpTask implements TaskInterface
{
/**
* @var ManagerInterface
*/
private $manager;
/**
* SessionVariablesTask constructor.
*
* @param ManagerInterface $manager
*/
public function __construct(ManagerInterface $manager)
{
$this->manager = $manager;
}
/**
* @return void
* @throws TaskException
*/
public function taskInstructions(): void
{
try {
$this->manager->setSessionVariablesByRegistry();
} catch (SessionVariablesManipulationException | NoContextException $exception) {
throw new TaskException(__('Some session variable could not be set'), $exception);
}
}
}
<?php
declare(strict_types=1);
/**
* File: TemporaryIndexSetUpTask.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Model\Migration\Processor\Task;
use LizardMedia\AbstractDataMigration\Api\Exception\Blocking;
use LizardMedia\AbstractDataMigration\Api\Migration\Processor\TaskInterface;
use LizardMedia\AbstractDataMigration\Exception\NotBlocking\TaskException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex\ManagerInterface;
use LizardMedia\MysqlDataMigration\Exception\TemporaryIndexManipulationException;
/**
* Class TemporaryIndexSetUpTask
* @package LizardMedia\MysqlDataMigration\Model\Migration\Processor\Task
*/
class TemporaryIndexSetUpTask implements TaskInterface
{
/**
* @var ManagerInterface
*/
private $manager;
/**
* TemporaryIndexSetUpTask constructor.
*
* @param ManagerInterface $manager
*/
public function __construct(ManagerInterface $manager)
{
$this->manager = $manager;
}
/**
* @return void
* @throws TemporaryIndexManipulationException
*/
public function taskInstructions(): void
{
$this->manager->addIndexesBasingOnRegistry();
}
}
<?php
declare(strict_types=1);
/**
* File: TemporaryIndexTearDownTask.php
*
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
namespace LizardMedia\MysqlDataMigration\Model\Migration\Processor\Task;
use LizardMedia\AbstractDataMigration\Api\Migration\Processor\TaskInterface;
use LizardMedia\AbstractDataMigration\Exception\NotBlocking\TaskException;
use LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex\ManagerInterface;
use LizardMedia\MysqlDataMigration\Exception\TemporaryIndexManipulationException;
/**
* TODO: Unit test
* Class TemporaryIndexTearDownTask
* @package LizardMedia\MysqlDataMigration\Model\Migration\Processor\Worker\Task
*/
class TemporaryIndexTearDownTask implements TaskInterface
{
/**
* @var ManagerInterface
*/
private $manager;
/**
* TemporaryIndexSetUpTask constructor.
*
* @param ManagerInterface $manager
*/
public function __construct(ManagerInterface $manager)
{
$this->manager = $manager;
}
/**
* @return void
* @throws TemporaryIndexManipulationException
*/
public function taskInstructions(): void
{
$this->manager->removeIndexBasingRegistry();
}
}
# Lizard Media Mysql Data Migration
## Overview
Module implements data migration from mysql data source.
\ No newline at end of file
{
"name": "lizardmedia/module-mysql-data-migration",
"description": "Implementation for data migration from mysql data source",
"require": {
"php": "~7.1.0",
"magento/framework": "102.0.*",
"lizardmedia/module-abstract-data-migration": "1.0.*",
"mslwk/php-typesafe-array": "1.0.*",
"react/cache": "^0.5.0"
},
"require-dev": {
"phpunit/phpunit": "~6.5.0"
},
"type": "magento2-module",
"version": "2.0.0",
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"LizardMedia\\MysqlDataMigration\\": ""
}
}
}
<?xml version="1.0"?>
<!--
/**
* @author Bartosz Kubicki <b.w.kubicki@gmail.com>
* Github https://github.com/bartoszkubicki
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- API section -->
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\Modifier\ConditionInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier\Condition" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\Modifier\LimitInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\Modifier\Limit" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session\ManagerInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\Session\Manager" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\Session\RegistryInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\Session\Registry" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex\ManagerInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\TemporaryIndex\Manager" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndex\RegistryInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\TemporaryIndex\Registry" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\SessionVariableInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\SessionVariable" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\SourceDb\TemporaryIndexInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\SourceDb\TemporaryIndex" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlModifierInjectorInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\MysqlModifierInjector" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlConnectionPoolInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\DataSource\MysqlConnectionPool" />
<preference for="LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceReaderFactoryInterface"
type="LizardMedia\MysqlDataMigration\Model\Data\MysqlDataSourceReaderFactory"/>
<!-- End of API section -->
<!-- Constructor arguments injection section -->
<type name="LizardMedia\AbstractDataMigration\Model\Data\DataSourceTypeList">
<arguments>
<argument name="allowedDataSourceTypes" xsi:type="array">
<item name="mysql" xsi:type="const">LizardMedia\MysqlDataMigration\Api\Data\MysqlDataSourceInterface::TYPE_CODE</item>
</argument>
</arguments>
</type>
<type name="LizardMedia\AbstractDataMigration\Model\Data\DataSource\ModifierInjectorPool">
<arguments>
<argument name="modifierInjectors" xsi:type="array">
<item name="mysql" xsi:type="object">LizardMedia\MysqlDataMigration\Api\Data\DataSource\MysqlModifierInjectorInterface</item>
</argument>
</arguments>
</type>
<!-- End of constructor arguments injection section -->
<!-- Basic configuration section -->
<virtualType name="Virtual\MysqlDataMigration\Model\Migration\MysqlEnvironmentSetUpProcessor\TaskArray"
type="LizardMedia\AbstractDataMigration\Model\Migration\Processor\TaskArray">
<arguments>
<argument name="tasks" xsi:type="array">
<item name="sessionVariablesSetUpTask" xsi:type="object">LizardMedia\MysqlDataMigration\Model\Migration\Processor\Task\SessionVariablesSetUpTask</item>
<item name="temporaryIndexSetUpTask" xsi:type="object">LizardMedia\MysqlDataMigration\Model\Migration\Processor\Task\TemporaryIndexSetUpTask</item>
</argument>
</arguments>
</virtualType>
<virtualType name="Virtual\MysqlDataMigration\Model\Migration\MysqlEnvironmentTearDownProcessor\TaskArray"
type="LizardMedia\AbstractDataMigration\Model\Migration\Processor\TaskArray">
<arguments>
<argument name="tasks" xsi:type="array">
<item name="temporaryIndexTearDownTask" xsi:type="object">LizardMedia\MysqlDataMigration\Model\Migration\Processor\Task\TemporaryIndexTearDownTask</item>
</argument>
</arguments>
</virtualType>
<virtualType name="Virtual\MysqlDataMigration\Model\Migration\MysqlEnvironmentSetUpProcessor"
type="LizardMedia\AbstractDataMigration\Model\Migration\Processor">
<arguments>
<argument name="taskArray" xsi:type="object">Virtual\MysqlDataMigration\Model\Migration\MysqlEnvironmentSetUpProcessor\TaskArray</argument>
</arguments>
</virtualType>
<virtualType name="Virtual\MysqlDataMigration\Model\Migration\MysqlEnvironmentTearDownProcessor"
type="LizardMedia\AbstractDataMigration\Model\Migration\Processor">
<arguments>
<argument name="taskArray" xsi:type="object">Virtual\MysqlDataMigration\Model\Migration\MysqlEnvironmentTearDownProcessor\TaskArray</argument>
</arguments>
</virtualType>
<virtualType name="Virtual\MysqlDataMigration\Model\Migration\ProcessorArray"
type="LizardMedia\AbstractDataMigration\Model\Migration\ProcessorArray">
<arguments>
<argument name="processors" xsi:type="array">
<item name="mysqlEnvironmentSetUpProcessor" xsi:type="object">Virtual\MysqlDataMigration\Model\Migration\MysqlEnvironmentSetUpProcessor</item>
<item name="migrationProcessor" xsi:type="object">Virtual\AbstractDataMigration\Model\Migration\MigrationProcessor</item>
<item name="mysqlEnvironmentTearDownProcessor" xsi:type="object">Virtual\MysqlDataMigration\Model\Migration\MysqlEnvironmentTearDownProcessor</item>
</argument>
</arguments>
</virtualType>
<virtualType name="Virtual\CustomerDataMigration\Model\Migration"
type="LizardMedia\AbstractDataMigration\Model\Migration">
<arguments>
<argument name="processorArray" xsi:type="object">Virtual\MysqlDataMigration\Model\Migration\ProcessorArray</argument>
</arguments>
</virtualType>
<!-- End of basic configuration section -->
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* @author Bartosz Kubicki <b.w.kubicki@gmail.com>
* Github https://github.com/bartoszkubicki
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="LizardMedia_MysqlDataMigration" setup_version="2.0.0">
<sequence>
<module name="LizardMedia_AbstractDataMigration" />
</sequence>
</module>
</config>
\ No newline at end of file
<?php
declare(strict_types=1);
/**
* @author Bartosz Kubicki b.w.kubicki@gmail.com>
* Github: https://github.com/bartoszkubicki
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'LizardMedia_MysqlDataMigration',
__DIR__
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment