<?php

/**
 * TechDivision\Import\Repositories\EavAttributeRepository
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Repositories;

use TechDivision\Import\Utils\MemberNames;
use TechDivision\Import\Utils\SqlStatementKeys;

/**
 * Repository implementation to load EAV attribute data.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class EavAttributeRepository extends AbstractRepository implements EavAttributeRepositoryInterface
{

    /**
     * The prepared statement to load the attributes by the passed is user defined flag.
     *
     * @var \PDOStatement
     */
    protected $eavAttributesByUserDefinedStmt;

    /**
     * The prepared statement to load the attributes for a specifc option value and store ID.
     *
     * @var \PDOStatement
     */
    protected $eavAttributesByOptionValueAndStoreIdStmt;

    /**
     * The prepared statement to load a attribute by its entity type ID and name.
     *
     * @var \PDOStatement
     */
    protected $eavAttributeByEntityTypeIdAndAttributeCodeStmt;

    /**
     * The prepared statement to load the attributes for a specific entity type and the user defined flag.
     *
     * @var \PDOStatement
     */
    protected $eavAttributesByEntityTypeIdAndUserDefinedStmt;

    /**
     * The prepared statement to load the attributes for a specific entity type ID and name.
     *
     * @var \PDOStatement
     */
    protected $eavAttributesByEntityTypeIdAndAttributeSetNameStmt;

    /**
     * Initializes the repository's prepared statements.
     *
     * @return void
     */
    public function init()
    {

        // initialize the prepared statements
        $this->eavAttributesByUserDefinedStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::EAV_ATTRIBUTES_BY_IS_USER_DEFINED));
        $this->eavAttributesByOptionValueAndStoreIdStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::EAV_ATTRIBUTES_BY_OPTION_VALUE_AND_STORE_ID));
        $this->eavAttributeByEntityTypeIdAndAttributeCodeStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::EAV_ATTRIBUTE_BY_ENTITY_TYPE_ID_AND_ATTRIBUTE_CODE));
        $this->eavAttributesByEntityTypeIdAndUserDefinedStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::EAV_ATTRIBUTES_BY_ENTITY_TYPE_ID_AND_IS_USER_DEFINED));
        $this->eavAttributesByEntityTypeIdAndAttributeSetNameStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::EAV_ATTRIBUTES_BY_ENTITY_TYPE_ID_AND_ATTRIBUTE_SET_NAME));
    }

    /**
     * Return's the EAV attribute with the passed entity type ID and code.
     *
     * @param integer $entityTypeId  The entity type ID of the EAV attributes to return
     * @param string  $attributeCode The code of the EAV attribute to return
     *
     * @return array The EAV attribute
     */
    public function findOneByEntityTypeIdAndAttributeCode($entityTypeId, $attributeCode)
    {

        // initialize the params
        $params = array(
            MemberNames::ENTITY_TYPE_ID => $entityTypeId,
            MemberNames::ATTRIBUTE_CODE => $attributeCode
        );

        // execute the prepared statement and return the EAV attribute with the passed entity type ID and code
        $this->eavAttributeByEntityTypeIdAndAttributeCodeStmt->execute($params);
        return $this->eavAttributeByEntityTypeIdAndAttributeCodeStmt->fetch(\PDO::FETCH_ASSOC);
    }

    /**
     * Return's an array with the available EAV attributes for the passed entity type ID and attribute set name.
     *
     * @param integer $entityTypeId     The entity type ID of the EAV attributes to return
     * @param string  $attributeSetName The attribute set name of the EAV attributes to return
     *
     * @return array The array with all available EAV attributes
     */
    public function findAllByEntityTypeIdAndAttributeSetName($entityTypeId, $attributeSetName)
    {

        // initialize the params
        $params = array(
            MemberNames::ENTITY_TYPE_ID     => $entityTypeId,
            MemberNames::ATTRIBUTE_SET_NAME => $attributeSetName
        );

        // initialize the array for the EAV attributes
        $eavAttributes = array();

        // execute the prepared statement and return the array with the EAV attributes
        $this->eavAttributesByEntityTypeIdAndAttributeSetNameStmt->execute($params);

        // load the available EAV attributes
        $availableEavAttributes = $this->eavAttributesByEntityTypeIdAndAttributeSetNameStmt->fetchAll(\PDO::FETCH_ASSOC);
        foreach ($availableEavAttributes as $eavAttribute) {
            $eavAttributes[$eavAttribute[MemberNames::ATTRIBUTE_CODE]] = $eavAttribute;
        }

        // return the array with the EAV attributes
        return $eavAttributes;
    }

    /**
     * Return's an array with the available EAV attributes for the passed option value and store ID.
     *
     * @param string $optionValue The option value of the EAV attributes
     * @param string $storeId     The store ID of the EAV attribues
     *
     * @return array The array with all available EAV attributes
     */
    public function findAllByOptionValueAndStoreId($optionValue, $storeId)
    {

        // initialize the params
        $params = array(
            MemberNames::VALUE    => $optionValue,
            MemberNames::STORE_ID => $storeId
        );

        // execute the prepared statement and return the array with the EAV attributes
        $this->eavAttributesByOptionValueAndStoreIdStmt->execute($params);
        return $this->eavAttributesByOptionValueAndStoreIdStmt->fetchAll(\PDO::FETCH_ASSOC);
    }

    /**
     * Return's an array with the available EAV attributes for the passed is user defined flag.
     *
     * @param integer $isUserDefined The flag itself
     *
     * @return array The array with the EAV attributes matching the passed flag
     */
    public function findAllByIsUserDefined($isUserDefined = 1)
    {

        // initialize the array for the EAV attributes
        $eavAttributes = array();

        // initialize the params
        $params = array(MemberNames::ID_USER_DEFINED => $isUserDefined);

        // execute the prepared statement and return the array with the EAV attributes
        $this->eavAttributesByUserDefinedStmt->execute($params);

        // load the available EAV attributes
        $availableEavAttributes = $this->eavAttributesByUserDefinedStmt->fetchAll(\PDO::FETCH_ASSOC);
        foreach ($availableEavAttributes as $eavAttribute) {
            $eavAttributes[$eavAttribute[MemberNames::ATTRIBUTE_CODE]] = $eavAttribute;
        }

        // return the array with the EAV attributes
        return $eavAttributes;
    }

    /**
     * Return's an array with the available EAV attributes for the passed is entity type and
     * user defined flag.
     *
     * @param integer $entityTypeId  The entity type ID of the EAV attributes to return
     * @param integer $isUserDefined The flag itself
     *
     * @return array The array with the EAV attributes matching the passed entity type and user defined flag
     */
    public function findAllByEntityTypeIdAndIsUserDefined($entityTypeId, $isUserDefined = 1)
    {

        // initialize the array for the EAV attributes
        $eavAttributes = array();

        // initialize the params
        $params = array(
            MemberNames::ENTITY_TYPE_ID  => $entityTypeId,
            MemberNames::ID_USER_DEFINED => $isUserDefined
        );

        // execute the prepared statement and return the array with the EAV attributes
        $this->eavAttributesByEntityTypeIdAndUserDefinedStmt->execute($params);

        // load the available EAV attributes
        $availableEavAttributes = $this->eavAttributesByEntityTypeIdAndUserDefinedStmt->fetchAll(\PDO::FETCH_ASSOC);
        foreach ($availableEavAttributes as $eavAttribute) {
            $eavAttributes[$eavAttribute[MemberNames::ATTRIBUTE_CODE]] = $eavAttribute;
        }

        // return the array with the EAV attributes
        return $eavAttributes;
    }

    /**
     * Return's an array with the available EAV attributes for the passed is entity type.
     *
     * @param integer $entityTypeId The entity type ID of the EAV attributes to return
     *
     * @return array The array with the EAV attributes matching the passed entity type
     */
    public function findAllByEntityTypeId($entityTypeId)
    {

        // initialize the array for the EAV attributes
        $eavAttributes = array();

        // execute the prepared statement and return the array with the EAV attributes
        $this->eavAttributesByEntityTypeIdAndUserDefinedStmt->execute(array(MemberNames::ENTITY_TYPE_ID  => $entityTypeId));

        // load the available EAV attributes
        $availableEavAttributes = $this->eavAttributesByEntityTypeIdAndUserDefinedStmt->fetchAll(\PDO::FETCH_ASSOC);
        foreach ($availableEavAttributes as $eavAttribute) {
            $eavAttributes[$eavAttribute[MemberNames::ATTRIBUTE_CODE]] = $eavAttribute;
        }

        // return the array with the EAV attributes
        return $eavAttributes;
    }

    /**
     * Return's the first EAV attribute for the passed option value and store ID.
     *
     * @param string $optionValue The option value of the EAV attributes
     * @param string $storeId     The store ID of the EAV attribues
     *
     * @return array The array with the EAV attribute
     */
    public function findOneByOptionValueAndStoreId($optionValue, $storeId)
    {

        // execute the prepared statement and return the array with the fail EAV attributes
        if (sizeof($eavAttributes = $this->findAllByOptionValueAndStoreId($optionValue, $storeId)) > 0) {
            return reset($eavAttributes);
        }
    }
}


<?php

/**
 * TechDivision\Import\Observers\ObserverVisitor
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Observers;

use TechDivision\Import\Subjects\SubjectInterface;
use Symfony\Component\DependencyInjection\TaggedContainerInterface;

/**
 * Visitor implementation for a subject's observers.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class ObserverVisitor implements ObserverVisitorInterface
{

    /**
     * The DI container builder instance.
     *
     * @var \Symfony\Component\DependencyInjection\TaggedContainerInterface
     */
    protected $container;

    /**
     * The constructor to initialize the instance.
     *
     * @param \Symfony\Component\DependencyInjection\TaggedContainerInterface $container The container instance
     */
    public function __construct(TaggedContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Visitor implementation that initializes the observers of the passed subject.
     *
     * @param \TechDivision\Import\Subjects\SubjectInterface $subject The subject to initialize the observers for
     *
     * @return void
     */
    public function visit(SubjectInterface $subject)
    {

        // load the observers from the configuration
        $availableObservers = $subject->getConfiguration()->getObservers();

        // prepare the observers
        foreach ($availableObservers as $observers) {
            $this->prepareObservers($subject, $observers);
        }
    }

    /**
     * Prepare the observers defined in the system configuration.
     *
     * @param \TechDivision\Import\Subjects\SubjectInterface $subject   The subject to prepare the observers for
     * @param array                                          $observers The array with the observers
     * @param string                                         $type      The actual observer type
     *
     * @return void
     */
    protected function prepareObservers(SubjectInterface $subject, array $observers, $type = null)
    {

        // iterate over the array with observers and prepare them
        foreach ($observers as $key => $observer) {
            // we have to initialize the type only on the first level
            if ($type == null) {
                $type = $key;
            }

            // query whether or not we've an subarry or not
            if (is_array($observer)) {
                $this->prepareObservers($subject, $observer, $type);
            } else {
                $subject->registerObserver($this->container->get($observer), $type);
            }
        }
    }
}


<?php

/**
 * TechDivision\Import\Subjects\FilesystemTrait
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Subjects;

use TechDivision\Import\Adapter\FilesystemAdapterInterface;

/**
 * The trait implementation that provides filesystem handling functionality.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
trait FilesystemTrait
{

    /**
     * The filesystem adapter instance.
     *
     * @return \TechDivision\Import\Adapter\FilesystemAdapterInterface
     */
    protected $filesystemAdapater;

    /**
     * Set's the virtual filesystem instance.
     *
     * @param \TechDivision\Import\Adapter\FilesystemAdapterInterface $filesystemAdapter The filesystem adapter instance
     *
     * @return void
     */
    public function setFilesystemAdapter(FilesystemAdapterInterface $filesystemAdapter)
    {
        $this->filesystemAdapater = $filesystemAdapter;
    }

    /**
     * Return's the filesystem adapater instance.
     *
     * @return \TechDivision\Import\Adapter\FilesystemAdapterInterface The filesystem adapter instance
     */
    public function getFilesystemAdapter()
    {
        return $this->filesystemAdapater;
    }

    /**
     * This method tries to resolve the passed path and returns it. If the path
     * is relative, the actual working directory will be prepended.
     *
     * @param string $path The path to be resolved
     *
     * @return string The resolved path
     * @throws \InvalidArgumentException Is thrown, if the path can not be resolved
     */
    public function resolvePath($path)
    {

        // if we've an absolute path, return it immediately
        if ($this->getFilesystemAdapter()->isDir($path)) {
            return $path;
        }

        // temporarily save the path
        $originalPath = $path;

        // try to prepend the actual working directory, assuming we've a relative path
        if ($this->getFilesystemAdapter()->isDir($path = getcwd() . DIRECTORY_SEPARATOR . ltrim($path, '/'))) {
            return $path;
        }

        // throw an exception if the passed directory doesn't exists
        throw new \InvalidArgumentException(
            sprintf('Directory %s doesn\'t exist', $originalPath)
        );
    }

    /**
     * Creates a new directroy.
     *
     * @param string  $pathname  The directory path
     * @param integer $mode      The mode is 0777 by default, which means the widest possible access
     * @param string  $recursive Allows the creation of nested directories specified in the pathname
     *
     * @return boolean TRUE on success, else FALSE
     * @link http://php.net/mkdir
     */
    public function mkdir($pathname, $mode = 0700, $recursive = false)
    {
        return $this->getFilesystemAdapter()->mkdir($pathname, $mode, $recursive);
    }

    /**
     * Query whether or not the passed filename exists.
     *
     * @param string $filename The filename to query
     *
     * @return boolean TRUE if the passed filename exists, else FALSE
     * @link http://php.net/is_file
     */
    public function isFile($filename)
    {
        return $this->getFilesystemAdapter()->isFile($filename);
    }

    /**
     * Tells whether the filename is a directory.
     *
     * @param string $filename Path to the file
     *
     * @return TRUE if the filename exists and is a directory, else FALSE
     * @link http://php.net/is_dir
     */
    public function isDir($filename)
    {
        return $this->getFilesystemAdapter()->isDir($filename);
    }

    /**
     * Creates an empty file with the passed filename.
     *
     * @param string $filename The name of the file to create
     *
     * @return boolean TRUE if the file can be created, else FALSE
     */
    public function touch($filename)
    {
        return $this->getFilesystemAdapter()->touch($filename);
    }

    /**
     * Renames a file or directory.
     *
     * @param string $oldname The old name
     * @param string $newname The new name
     *
     * @return boolean TRUE on success, else FALSE
     * @link http://php.net/rename
     */
    public function rename($oldname, $newname)
    {
        return $this->getFilesystemAdapter()->rename($oldname, $newname);
    }

    /**
     * Writes the passed data to file with the passed name.
     *
     * @param string $filename The name of the file to write the data to
     * @param string $data     The data to write to the file
     *
     * @return number The number of bytes written to the file
     * @link http://php.net/file_put_contents
     */
    public function write($filename, $data)
    {
        return $this->getFilesystemAdapter()->write($filename, $data);
    }
}


<?php

/**
 * TechDivision\Import\Utils\Filter\ConvertLiteralUrl
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Utils\Filter;

/**
 * Filter to convert URLs.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class ConvertLiteralUrl extends ConvertLiteral
{
    /**
     * Filter and return the value.
     *
     * @param string $string The value to filter
     *
     * @return string The filtered value
     */
    public function filter($string)
    {

        // replace all characters that are not numbers or simple chars
        $string = preg_replace('#[^0-9a-z]+#i', '-', parent::filter($string));
        $string = strtolower($string);
        $string = trim($string, '-');

        // return the converted URL
        return $string;
    }
}


<?php

/**
 * TechDivision\Import\Services\RegistryProcessor
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Services;

/**
 * Array based implementation of a registry.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class RegistryProcessor implements RegistryProcessorInterface
{

    /**
     * A storage for the attributes.
     *
     * @var array
     */
    protected $attributes = array();

    /**
     * Register the passed attribute under the specified key in the registry.
     *
     * @param mixed $key   The key to register the value with
     * @param mixed $value The value to be registered
     *
     * @return void
     * @throws \Exception Is thrown, if the key has already been used
     */
    public function setAttribute($key, $value)
    {

        // query whether or not the key has already been used
        if (isset($this->attributes[$key])) {
            throw new \Exception(sprintf('Try to override data with key %s', $key));
        }

        // set the attribute in the registry
        $this->attributes[$key] = $value;
    }

    /**
     * Return's the attribute with the passed key from the registry.
     *
     * @param mixed $key The key to return the attribute for
     *
     * @return mixed The requested attribute
     */
    public function getAttribute($key)
    {
        if (isset($this->attributes[$key])) {
            return $this->attributes[$key];
        }
    }

    /**
     * Query whether or not an attribute with the passed key has already been registered.
     *
     * @param mixed $key The key to query for
     *
     * @return boolean TRUE if the attribute has already been registered, else FALSE
     */
    public function hasAttribute($key)
    {
        return isset($this->attributes[$key]);
    }

    /**
     * Remove the attribute with the passed key from the registry.
     *
     * @param mixed $key The key of the attribute to return
     *
     * @return void
     */
    public function removeAttribute($key)
    {
        if (isset($this->attributes[$key])) {
            unset($this->attributes[$key]);
        }
    }

    /**
     * Raises the value for the attribute with the passed key by one.
     *
     * @param mixed $key         The key of the attribute to raise the value for
     * @param mixed $counterName The name of the counter to raise
     *
     * @return integer The counter's new value
     */
    public function raiseCounter($key, $counterName)
    {

        // raise/initialize the value
        if (isset($this->attributes[$key][$counterName])) {
            $this->attributes[$key][$counterName]++;
        } else {
            $this->attributes[$key][$counterName] = 1;
        }

        // return the new value
        return $this->attributes[$key][$counterName];
    }

    /**
     * This method merges the passed attributes with an array that
     * has already been added under the passed key.
     *
     * If no value will be found under the passed key, the attributes
     * will simply be registered.
     *
     * @param mixed $key        The key of the attributes that has to be merged with the passed ones
     * @param array $attributes The attributes that has to be merged with the exising ones
     *
     * @return void
     * @throws \Exception Is thrown, if the already registered value is no array
     * @link http://php.net/array_replace_recursive
     */
    public function mergeAttributesRecursive($key, array $attributes)
    {

        // if the key not exists, simply add the new attributes
        if (!isset($this->attributes[$key])) {
            $this->attributes[$key] = $attributes;
            return;
        }

        // if the key exists and the value is an array, merge it with the passed array
        if (isset($this->attributes[$key]) && is_array($this->attributes[$key])) {
            $this->attributes[$key] = array_replace_recursive($this->attributes[$key], $attributes);
            return;
        }

        // throw an exception if the key exists, but the found value is not of type array
        throw new \Exception(sprintf('Can\'t merge attributes, because value for key %s already exists, but is not of type array', $key));
    }
}


<?php

/**
 * TechDivision\Import\Adapter\LeagueFilesystemAdapterFactory
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Adapter;

use League\Flysystem\Filesystem;
use TechDivision\Import\Utils\ConfigurationKeys;
use TechDivision\Import\Utils\ConfigurationUtil;
use TechDivision\Import\Configuration\SubjectConfigurationInterface;

/**
 * A generic filesystem adapter factory implementation.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class LeagueFilesystemAdapterFactory implements FilesystemAdapterFactoryInterface
{

    /**
     * Factory method to create new filesystem adapter instance.
     *
     * @param \TechDivision\Import\Configuration\SubjectConfigurationInterface $subjectConfiguration The subject configuration
     *
     * @return \TechDivision\Import\Adapter\FilesystemAdapterInterface The filesystem adapter instance
     */
    public function createFilesystemAdapter(SubjectConfigurationInterface $subjectConfiguration)
    {

        // the filesystem adapter configuration
        $filesystemAdapterConfiguration = $subjectConfiguration->getFilesystemAdapter();

        // load the filesystem adapter's adapter configuration (FS specific)
        $adapterConfiguration = $filesystemAdapterConfiguration->getAdapter();

        // load the adapter parameters
        $adapterParams = $adapterConfiguration->getParams();

        // initialize the root directory, if not specified in the adapter parameters
        if (!isset($adapterParams[ConfigurationKeys::ROOT])) {
            $adapterParams[ConfigurationKeys::ROOT] = getcwd();
        }

        // load the adapter to use
        $reflectionClass = new \ReflectionClass($adapterConfiguration->getType());
        $adapter =  $reflectionClass->newInstanceArgs(ConfigurationUtil::prepareConstructorArgs($reflectionClass, $adapterParams));

        // create a new filesystem instance
        return new LeagueFilesystemAdapter(new Filesystem($adapter));
    }
}


<?php

/**
 * TechDivision\Import\Repositories\CategoryRepository
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Repositories;

use TechDivision\Import\Utils\MemberNames;
use TechDivision\Import\Utils\SqlStatementKeys;

/**
 * Repository implementation to load category data.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class CategoryRepository extends AbstractRepository implements CategoryRepositoryInterface
{

    /**
     * The statement to load the categories.
     *
     * @var \PDOStatement
     */
    protected $categoriesStmt;

    /**
     * The statement to load the root categories.
     *
     * @var \PDOStatement
     */
    protected $rootCategoriesStmt;

    /**
     * Initializes the repository's prepared statements.
     *
     * @return void
     */
    public function init()
    {

        // initialize the prepared statements
        $this->categoriesStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::CATEGORIES));
        $this->rootCategoriesStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ROOT_CATEGORIES));
        $this->categoriesByStoreViewStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::CATEGORIES_BY_STORE_VIEW));
    }

    /**
     * Return's an array with all available categories.
     *
     * @return array The available categories
     */
    public function findAll()
    {
        // try to load the categories
        $this->categoriesStmt->execute();
        return $this->categoriesStmt->fetchAll(\PDO::FETCH_ASSOC);
    }

    /**
     * Return's an array with all available categories by store view ID.
     *
     * @param integer $storeViewId The store view ID to return the categories for
     *
     * @return array The available categories for the passed store view ID
     */
    public function findAllByStoreView($storeViewId)
    {
        // try to load the categories and return them
        $this->categoriesByStoreViewStmt->execute(array(MemberNames::STORE_ID => $storeViewId));
        return $this->categoriesByStoreViewStmt->fetchAll(\PDO::FETCH_ASSOC);
    }

    /**
     * Return's an array with the root categories with the store code as key.
     *
     * @return array The root categories
     */
    public function findAllRootCategories()
    {

        // try to load the categories
        $this->rootCategoriesStmt->execute();

        // initialize the array with the store code as key
        $rootCategories = array();

        // load the available root categories
        $availableRootCategories = $this->rootCategoriesStmt->fetchAll(\PDO::FETCH_ASSOC);

        // prepare the array with the root categories
        foreach ($availableRootCategories as $category) {
            $rootCategories[$category[MemberNames::CODE]] = $category;
        }

        // append the root categories to the cache
        return $rootCategories;
    }
}


<?php

/**
 * TechDivision\Import\Events\EmitterFactory
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Events;

use League\Event\Emitter;
use League\Event\EmitterInterface;
use TechDivision\Import\ConfigurationInterface;
use Symfony\Component\DependencyInjection\TaggedContainerInterface;

/**
 * A factory implementation to create a new event emitter instance.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class EmitterFactory implements EmitterFactoryInterface
{

    /**
     * The configuration instance.
     *
     * @var \TechDivision\Import\ConfigurationInterface
     */
    protected $configuration;

    /**
     * The DI container builder instance.
     *
     * @var \Symfony\Component\DependencyInjection\TaggedContainerInterface
     */
    protected $container;

    /**
     * The constructor to initialize the instance.
     *
     * @param \TechDivision\Import\ConfigurationInterface                     $configuration The configuration instance
     * @param \Symfony\Component\DependencyInjection\TaggedContainerInterface $container     The container instance
     */
    public function __construct(ConfigurationInterface $configuration, TaggedContainerInterface $container)
    {
        $this->container = $container;
        $this->configuration = $configuration;
    }

    /**
     * The factory method that creates a new emitter instance.
     *
     * @return void
     */
    public function createEmitter()
    {

        // initialize the event emitter
        $emitter = new Emitter();

        // load the listener configuration from the configuration
        $availableListeners = $this->configuration->getListeners();

        // load, initialize and add the configured listeners to the emitter
        foreach ($availableListeners as $listeners) {
            $this->prepareListeners($emitter, $listeners);
        }

        // load the available operations from the configuration
        $availableOperations = $this->configuration->getOperations();

        // load, initialize and add the configured listeners for the actual operation
        /** @var \TechDivision\Import\Configuration\OperationConfigurationInterface $operation */
        foreach ($availableOperations as $operation) {
            if ($operation->equals($this->configuration->getOperation())) {
                // load the operation's listeners
                $operationListeners = $operation->getListeners();
                // prepare the operation's listeners
                foreach ($operationListeners as $listeners) {
                    $this->prepareListeners($emitter, $listeners);
                }
            }
        }

        // return the initialized emitter instance
        return $emitter;
    }

    /**
     * Prepare the listeners defined in the system configuration.
     *
     * @param \League\Event\EmitterInterface $emitter   The event emitter to prepare the listeners for
     * @param array                          $listeners The array with the listeners
     * @param string                         $eventName The actual event name
     *
     * @return void
     */
    protected function prepareListeners(EmitterInterface $emitter, array $listeners, $eventName = null)
    {

        // iterate over the array with listeners and prepare them
        foreach ($listeners as $key => $listener) {
            // we have to initialize the event name only on the first level
            if ($eventName == null) {
                $eventName = $key;
            }
            // query whether or not we've an subarray or not
            if (is_array($listener)) {
                $this->prepareListeners($emitter, $listener, $eventName);
            } else {
                $emitter->addListener($eventName, $this->container->get($listener));
            }
        }
    }
}


<?php

/**
 * TechDivision\Import\Plugins\AbstractPlugin
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Plugins;

use TechDivision\Import\Utils\LoggerKeys;
use TechDivision\Import\ApplicationInterface;
use TechDivision\Import\Configuration\PluginConfigurationInterface;

/**
 * Abstract plugin implementation.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
abstract class AbstractPlugin implements PluginInterface
{

    /**
     * The appliation instance.
     *
     * @var \TechDivision\Import\ApplicationInterface
     */
    protected $application;

    /**
     * The plugin configuration instance.
     *
     * @var \TechDivision\Import\Configuration\PluginConfigurationInterface
     */
    protected $pluginConfiguration;

    /**
     * Initializes the plugin with the application instance.
     *
     * @param \TechDivision\Import\ApplicationInterface $application The application instance
     */
    public function __construct(ApplicationInterface $application)
    {
        $this->application = $application;
    }

    /**
     *  Set's the plugin configuration instance.
     *
     * @param \TechDivision\Import\Configuration\PluginConfigurationInterface $pluginConfiguration The plugin configuration instance
     *
     * @return void
     */
    public function setPluginConfiguration(PluginConfigurationInterface $pluginConfiguration)
    {
        $this->pluginConfiguration = $pluginConfiguration;
    }

    /**
     * Return's the plugin configuration instance.
     *
     * @return \TechDivision\Import\Configuration\PluginConfigurationInterface The plugin configuration instance
     */
    protected function getPluginConfiguration()
    {
        return $this->pluginConfiguration;
    }

    /**
     * Return's the application instance.
     *
     * @return \TechDivision\Import\ApplicationInterface The application instance
     */
    protected function getApplication()
    {
        return $this->application;
    }

    /**
     * Return's the RegistryProcessor instance to handle the running threads.
     *
     * @return \TechDivision\Import\Services\RegistryProcessor The registry processor instance
     */
    protected function getRegistryProcessor()
    {
        return $this->getApplication()->getRegistryProcessor();
    }

    /**
     * Return's the import processor instance.
     *
     * @return \TechDivision\Import\Services\ImportProcessorInterface The import processor instance
     */
    protected function getImportProcessor()
    {
        return $this->getApplication()->getImportProcessor();
    }

    /**
     * Return's the unique serial for this import process.
     *
     * @return string The unique serial
     */
    protected function getSerial()
    {
        return $this->getApplication()->getSerial();
    }

    /**
     * Return's the logger with the passed name, by default the system logger.
     *
     * @param string $name The name of the requested system logger
     *
     * @return \Psr\Log\LoggerInterface The logger instance
     * @throws \Exception Is thrown, if the requested logger is NOT available
     */
    protected function getSystemLogger($name = LoggerKeys::SYSTEM)
    {
        return $this->getApplication()->getSystemLogger($name);
    }

    /**
     * Query whether or not the system logger with the passed name is available.
     *
     * @param string $name The name of the requested system logger
     *
     * @return boolean TRUE if the logger with the passed name exists, else FALSE
     */
    protected function hasSystemLogger($name = LoggerKeys::SYSTEM)
    {
        return $this->getApplication()->hasSystemLogger($name);
    }

    /**
     * Return's the array with the system logger instances.
     *
     * @return array The logger instance
     */
    protected function getSystemLoggers()
    {
        return $this->getApplication()->getSystemLoggers();
    }

    /**
     * Persist the UUID of the actual import process to the PID file.
     *
     * @return void
     * @throws \Exception Is thrown, if the PID can not be added
     */
    protected function lock()
    {
        $this->getApplication()->lock();
    }

    /**
     * Remove's the UUID of the actual import process from the PID file.
     *
     * @return void
     * @throws \Exception Is thrown, if the PID can not be removed
     */
    protected function unlock()
    {
        $this->getApplication()->unlock();
    }

    /**
     * Remove's the passed line from the file with the passed name.
     *
     * @param string $line     The line to be removed
     * @param string $filename The name of the file the line has to be removed
     *
     * @return void
     * @throws \Exception Is thrown, if the file doesn't exists, the line is not found or can not be removed
     */
    protected function removeLineFromFile($line, $filename)
    {
        $this->getApplication()->removeLineFromFile($line, $filename);
    }

    /**
     * Return's the system configuration.
     *
     * @return \TechDivision\Import\ConfigurationInterface The system configuration
     */
    protected function getConfiguration()
    {
        return $this->getApplication()->getConfiguration();
    }

    /**
     * Return's the PID filename to use.
     *
     * @return string The PID filename
     */
    protected function getPidFilename()
    {
        return $this->getConfiguration()->getPidFilename();
    }

    /**
     * Return's the source directory that has to be watched for new files.
     *
     * @return string The source directory
     */
    protected function getSourceDir()
    {
        return $this->getConfiguration()->getSourceDir();
    }

    /**
     * Removes the passed directory recursively.
     *
     * @param string $src Name of the directory to remove
     *
     * @return void
     * @throws \Exception Is thrown, if the directory can not be removed
     */
    protected function removeDir($src)
    {

        // open the directory
        $dir = opendir($src);

        // remove files/folders recursively
        while (false !== ($file = readdir($dir))) {
            if (($file != '.') && ($file != '..')) {
                $full = $src . '/' . $file;
                if (is_dir($full)) {
                    $this->removeDir($full);
                } else {
                    if (!unlink($full)) {
                        throw new \Exception(sprintf('Can\'t remove file %s', $full));
                    }
                }
            }
        }

        // close handle and remove directory itself
        closedir($dir);
        if (!rmdir($src)) {
            throw new \Exception(sprintf('Can\'t remove directory %s', $src));
        }
    }

    /**
     * Return's the configured swift mailer instance.
     *
     * @return \Swift_Mailer|null The mailer instance
     */
    protected function getSwiftMailer()
    {

        // the swift mailer configuration
        if ($swiftMailerConfiguration = $this->getPluginConfiguration()->getSwiftMailer()) {
            // load the factory that creates the swift mailer instance
            $factory = $swiftMailerConfiguration->getFactory();
            // create the swift mailer instance
            return $factory::factory($swiftMailerConfiguration);
        }
    }
}


<?php

/**
 * TechDivision\Import\Adapter\CsvExportAdapter
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Adapter;

use Goodby\CSV\Export\Protocol\ExporterInterface;
use TechDivision\Import\Configuration\Subject\ExportAdapterConfigurationInterface;
use TechDivision\Import\Serializers\ConfigurationAwareSerializerFactoryInterface;

/**
 * CSV export adapter implementation.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class CsvExportAdapter implements ExportAdapterInterface, SerializerAwareAdapterInterface
{

    /**
     * The trait that provides serializer functionality.
     *
     * @var \TechDivision\Import\Adapter\SerializerTrait
     */
    use SerializerTrait;

    /**
     * The exporter instance.
     *
     * @var \Goodby\CSV\Export\Protocol\ExporterInterface
     */
    protected $exporter;

    /**
     * The array with the names of the exported files.
     *
     * @var array
     */
    protected $exportedFilenames = array();

    /**
     * Initialize the adapter with the configuration.
     *
     * @param \Goodby\CSV\Export\Protocol\ExporterInterface $exporter The exporter instance
     */
    public function __construct(ExporterInterface $exporter)
    {
        $this->exporter = $exporter;
    }

    /**
     * Overwrites the default CSV configuration values with the one from the passed configuration.
     *
     * @param \TechDivision\Import\Configuration\Subject\ExportAdapterConfigurationInterface $exportAdapterConfiguration The configuration to use the values from
     * @param \TechDivision\Import\Serializers\ConfigurationAwareSerializerFactoryInterface  $serializerFactory          The serializer factory instance
     *
     * @return void
     */
    public function init(
        ExportAdapterConfigurationInterface $exportAdapterConfiguration,
        ConfigurationAwareSerializerFactoryInterface $serializerFactory
    ) {

        // load the exporter configuration and overwrite the values
        /** @var \Goodby\CSV\Export\Standard\ExporterConfig $config */
        $config = $this->exporter->getConfig();

        // query whether or not a delimiter character has been configured
        if ($delimiter = $exportAdapterConfiguration->getDelimiter()) {
            $config->setDelimiter($delimiter);
        }

        // query whether or not a custom escape character has been configured
        if ($escape = $exportAdapterConfiguration->getEscape()) {
            $config->setEscape($escape);
        }

        // query whether or not a custom enclosure character has been configured
        if ($enclosure = $exportAdapterConfiguration->getEnclosure()) {
            $config->setEnclosure($enclosure);
        }

        // query whether or not a custom source charset has been configured
        if ($fromCharset = $exportAdapterConfiguration->getFromCharset()) {
            $config->setFromCharset($fromCharset);
        }

        // query whether or not a custom target charset has been configured
        if ($toCharset = $exportAdapterConfiguration->getToCharset()) {
            $config->setToCharset($toCharset);
        }

        // query whether or not a custom file mode has been configured
        if ($fileMode = $exportAdapterConfiguration->getFileMode()) {
            $config->setFileMode($fileMode);
        }

        // load the serializer instance from the DI container and set it on the subject instance
        $this->setSerializer($serializerFactory->createSerializer($exportAdapterConfiguration));
    }

    /**
     * Imports the content of the CSV file with the passed filename.
     *
     * @param array   $artefacts The artefacts to be exported
     * @param string  $targetDir The target dir to export the artefacts to
     * @param integer $timestamp The timestamp part of the original import file
     * @param string  $counter   The counter part of the origin import file
     *
     * @return void
     */
    public function export(array $artefacts, $targetDir, $timestamp, $counter)
    {

        // reset the array with the exported filename
        $this->exportedFilenames = array();

        // iterate over the artefacts and export them
        foreach ($artefacts as $artefactType => $artefacts) {
            // initialize the bunch and the exporter
            $bunch = array();

            // iterate over the artefact types artefacts
            foreach ($artefacts as $entityArtefacts) {
                // prepend the bunch header first
                if (sizeof($bunch) === 0) {
                    $bunch[] = array_keys(reset($entityArtefacts));
                }

                // export the artefacts
                foreach ($entityArtefacts as $entityArtefact) {
                    array_push($bunch, $entityArtefact);
                }
            }

            // prepare the name of the export file
            $filename = sprintf(
                '%s/%s_%s_%s.csv',
                $targetDir,
                $artefactType,
                $timestamp,
                $counter
            );

            // export the artefact (bunch)
            $this->exporter->export($filename, $bunch);

            // add the filename to the array with the exported filenames
            $this->exportedFilenames[] = $filename;
        }
    }

    /**
     * Return's the array with the names of the exported files.
     *
     * @return array The array with the exported filenames
     */
    public function getExportedFilenames()
    {
        return $this->exportedFilenames;
    }
}


<?php

/**
 * TechDivision\Import\Subjects\FileResolver\AbstractFileResolver
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Subjects\FileResolver;

use TechDivision\Import\ApplicationInterface;
use TechDivision\Import\Utils\RegistryKeys;
use TechDivision\Import\Services\RegistryProcessorInterface;
use TechDivision\Import\Configuration\SubjectConfigurationInterface;

/**
 * Abstract file resolver implementation.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
abstract class AbstractFileResolver implements FileResolverInterface
{

    /**
     * The registry processor instance.
     *
     * @var \TechDivision\Import\Services\RegistryProcessorInterface
     */
    private $registryProcessor;

    /**
     * The appliation instance.
     *
     * @var \TechDivision\Import\ApplicationInterface
     */
    private $application;

    /**
     * The actual source directory to load the files from.
     *
     * @var string
     */
    private $sourceDir;

    /**
     * The OK file suffix to use.
     *
     * @var string
     */
    private $okFileSuffix = 'ok';

    /**
     * The subject configuraiton instance.
     *
     * @var \TechDivision\Import\Configuration\SubjectConfigurationInterface
     */
    private $subjectConfiguration;

    /**
     * Initializes the file resolver with the application and the registry instance.
     *
     * @param \TechDivision\Import\ApplicationInterface                $application       The application instance
     * @param \TechDivision\Import\Services\RegistryProcessorInterface $registryProcessor The registry instance
     */
    public function __construct(ApplicationInterface $application, RegistryProcessorInterface $registryProcessor)
    {
        $this->application = $application;
        $this->registryProcessor = $registryProcessor;
    }

    /**
     * Returns the registry processor instance.
     *
     * @return \TechDivision\Import\Services\RegistryProcessorInterface The processor instance
     */
    protected function getRegistryProcessor()
    {
        return $this->registryProcessor;
    }

    /**
     * Return's the application instance.
     *
     * @return \TechDivision\Import\ApplicationInterface The application instance
     */
    protected function getApplication()
    {
        return $this->application;
    }

    /**
     * Sets the actual source directory to load the files from.
     *
     * @param string $sourceDir The actual source directory
     *
     * @return void
     */
    protected function setSourceDir($sourceDir)
    {
        $this->sourceDir = $sourceDir;
    }

    /**
     * Returns the actual source directory to load the files from.
     *
     * @return string The actual source directory
     */
    protected function getSourceDir()
    {
        return $this->sourceDir;
    }

    /**
     * Returns the file resolver configuration instance.
     *
     * @return \TechDivision\Import\Configuration\Subject\FileResolverConfigurationInterface The configuration instance
     */
    protected function getFileResolverConfiguration()
    {
        return $this->getSubjectConfiguration()->getFileResolver();
    }

    /**
     * Returns the delement separator char.
     *
     *  @return string The element separator char
     */
    protected function getElementSeparator()
    {
        return $this->getFileResolverConfiguration()->getElementSeparator();
    }

    /**
     * Returns the elements the filenames consists of.
     *
     * @return array The array with the filename elements
     */
    protected function getPatternElements()
    {
        return $this->getFileResolverConfiguration()->getPatternElements();
    }

    /**
     * Returns the suffix for the import files.
     *
     * @return string The suffix
     */
    protected function getSuffix()
    {
        return $this->getFileResolverConfiguration()->getSuffix();
    }

    /**
     * Returns the OK file suffix to use.
     *
     * @return string The OK file suffix
     */
    protected function getOkFileSuffix()
    {
        return $this->getFileResolverConfiguration()->getOkFileSuffix();
    }

    /**
     * Initializes the file resolver for the import process with the passed serial.
     *
     * @param string $serial The unique identifier of the actual import process
     *
     * @return void
     * @throws \Exception Is thrown if the configured source directory is not available
     */
    protected function initialize($serial)
    {

        // load the actual status
        $status = $this->getRegistryProcessor()->getAttribute($serial);

        // query whether or not the configured source directory is available
        if (!is_dir($sourceDir = $status[RegistryKeys::SOURCE_DIRECTORY])) {
            throw new \Exception(sprintf('Configured source directory "%s" is not available!', $sourceDir));
        }

        // set the source directory
        $this->setSourceDir($sourceDir);
    }

    /**
     * Sets the subject configuration instance.
     *
     * @param \TechDivision\Import\Configuration\SubjectConfigurationInterface $subjectConfiguration The subject configuration
     *
     * @return void
     */
    public function setSubjectConfiguration(SubjectConfigurationInterface $subjectConfiguration)
    {
        $this->subjectConfiguration = $subjectConfiguration;
    }

    /**
     * Returns the subject configuration instance.
     *
     * @return \TechDivision\Import\Configuration\SubjectConfigurationInterface The subject configuration
     */
    public function getSubjectConfiguration()
    {
        return $this->subjectConfiguration;
    }

    /**
     * Loads the files from the source directory and return's them sorted.
     *
     * @param string $serial The unique identifier of the actual import process
     *
     * @return array The array with the files matching the subjects suffix
     * @throws \Exception Is thrown, when the source directory is NOT available
     */
    public function loadFiles($serial)
    {

        // clear the filecache
        clearstatcache();

        // initialize the resolver
        $this->initialize($serial);

        // initialize the array with the files matching the suffix found in the source directory
        $files = glob(sprintf('%s/*.%s', $this->getSourceDir(), $this->getSuffix()));

        // sort the files for the apropriate order
        usort($files, function ($a, $b) {
            return strcmp($a, $b);
        });

        // return the sorted files
        return $files;
    }
}


<?php

/**
 * TechDivision\Import\Actions\Processors\UrlRewriteDeleteProcessor
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Actions\Processors;

use TechDivision\Import\Utils\SqlStatementKeys;

/**
 * The URL rewrite delete processor implementation.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class UrlRewriteDeleteProcessor extends AbstractDeleteProcessor
{

    /**
     * Return's the array with the SQL statements that has to be prepared.
     *
     * @return array The SQL statements to be prepared
     * @see \TechDivision\Import\Actions\Processors\AbstractBaseProcessor::getStatements()
     */
    protected function getStatements()
    {
        return array(
            SqlStatementKeys::DELETE_URL_REWRITE => $this->loadStatement(SqlStatementKeys::DELETE_URL_REWRITE),
            SqlStatementKeys::DELETE_URL_REWRITE_BY_SKU => $this->loadStatement(SqlStatementKeys::DELETE_URL_REWRITE_BY_SKU),
            SqlStatementKeys::DELETE_URL_REWRITE_BY_PATH => $this->loadStatement(SqlStatementKeys::DELETE_URL_REWRITE_BY_PATH),
            SqlStatementKeys::DELETE_URL_REWRITE_BY_CATEGORY_ID => $this->loadStatement(SqlStatementKeys::DELETE_URL_REWRITE_BY_CATEGORY_ID)
        );
    }
}


<?php

/**
 * TechDivision\Import\Adapter\CsvImportAdapterFactory
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Adapter;

use Symfony\Component\DependencyInjection\ContainerInterface;
use TechDivision\Import\Configuration\SubjectConfigurationInterface;
use TechDivision\Import\Utils\DependencyInjectionKeys;

/**
 * Factory for all CSV import adapter implementations.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class CsvImportAdapterFactory implements ImportAdapterFactoryInterface
{

    /**
     * The DI container instance.
     *
     * @var \Symfony\Component\DependencyInjection\ContainerInterface
     */
    protected $container;

    /**
     * Initialize the factory with the DI container instance.
     *
     * @param \Symfony\Component\DependencyInjection\ContainerInterface $container The DI container instance
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Creates and returns the import adapter for the subject with the passed configuration.
     *
     * @param \TechDivision\Import\Configuration\SubjectConfigurationInterface $subjectConfiguration The subject configuration
     *
     * @return \TechDivision\Import\Adapter\ExportAdapterInterface The import adapter instance
     */
    public function createImportAdapter(SubjectConfigurationInterface $subjectConfiguration)
    {

        // load the import adapter configuration
        $importAdapterConfiguration = $subjectConfiguration->getImportAdapter();

        // load the serializer factory instance
        $serializerFactory = $this->container->get($importAdapterConfiguration->getSerializer()->getId());

        // create the instance and pass the import adapter configuration instance
        $importAdapter = $this->container->get(DependencyInjectionKeys::IMPORT_ADAPTER_IMPORT_CSV);
        $importAdapter->init($importAdapterConfiguration, $serializerFactory);

        // return the initialized import adapter instance
        return $importAdapter;
    }
}


<?php

/**
 * TechDivision\Import\Callbacks\CallbackVisitor
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 *
 * PHP version 5
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Callbacks;

use TechDivision\Import\Subjects\SubjectInterface;
use Symfony\Component\DependencyInjection\TaggedContainerInterface;

/**
 * Visitor implementation for a subject's callbacks.
 *
 * @author    Tim Wagner <t.wagner@techdivision.com>
 * @copyright 2016 TechDivision GmbH <info@techdivision.com>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/techdivision/import
 * @link      http://www.techdivision.com
 */
class CallbackVisitor implements CallbackVisitorInterface
{

    /**
     * The DI container builder instance.
     *
     * @var \Symfony\Component\DependencyInjection\TaggedContainerInterface
     */
    protected $container;

    /**
     * The constructor to initialize the instance.
     *
     * @param \Symfony\Component\DependencyInjection\TaggedContainerInterface $container The container instance
     */
    public function __construct(TaggedContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Visitor implementation that initializes the observers of the passed subject.
     *
     * @param \TechDivision\Import\Subjects\SubjectInterface $subject The subject to initialize the observers for
     *
     * @return void
     */
    public function visit(SubjectInterface $subject)
    {

        // load the callback mappings
        $callbackMappings = $subject->getCallbackMappings();

        // prepare the callbacks
        foreach ($callbackMappings as $type => $callbacks) {
            $this->prepareCallbacks($subject, $callbacks, $type);
        }
    }

    /**
     * Prepare the callbacks defined in the system configuration.
     *
     * @param \TechDivision\Import\Subjects\SubjectInterface $subject   The subject to prepare the callbacks for
     * @param array                                          $callbacks The array with the callbacks
     * @param string                                         $type      The actual callback type
     *
     * @return void
     */
    protected function prepareCallbacks(SubjectInterface $subject, array $callbacks, $type = null)
    {

        // iterate over the array with callbacks and prepare them
        foreach ($callbacks as $key => $callback) {
            // we have to initialize the type only on the first level
            if ($type == null) {
                $type = $key;
            }

            // query whether or not we've an subarry or not
            if (is_array($callback)) {
                $this->prepareCallbacks($subject, $callback, $type);
            } else {
                $subject->registerCallback($this->container->get($callback), $type);
            }
        }
    }
}