<?php

/**
 * TechDivision\Import\Attribute\Observers\AbstractAttributeExportObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

/**
 * Observer that exports the attribute options to an additional CSV file for further processing.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
abstract class AbstractAttributeExportObserver extends AbstractAttributeImportObserver
{

    /**
     * Return's the artefact type used for export.
     *
     * @return string The artefact type
     */
    abstract protected function getArtefactType();

    /**
     * Create's and return's a new empty artefact entity.
     *
     * @param array $columns             The array with the column data
     * @param array $originalColumnNames The array with a mapping from the old to the new column names
     *
     * @return array The new artefact entity
     */
    protected function newArtefact(array $columns, array $originalColumnNames)
    {
        return $this->getSubject()->newArtefact($columns, $originalColumnNames);
    }

    /**
     * Add the passed product type artefacts to the product with the
     * last entity ID.
     *
     * @param array   $artefacts The product type artefacts
     * @param boolean $override  Whether or not the artefacts for the actual entity ID has to be overwritten
     *
     * @return void
     * @uses \TechDivision\Import\Product\Bundle\Subjects\BunchSubject::getLastEntityId()
     */
    protected function addArtefacts(array $artefacts, $override = true)
    {
        $this->getSubject()->addArtefacts($this->getArtefactType(), $artefacts, $override);
    }

    /**
     * Return the artefacts for the passed type and entity ID.
     *
     * @param string $type     The artefact type, e. g. configurable
     * @param string $entityId The entity ID to return the artefacts for
     *
     * @return array The array with the artefacts
     * @throws \Exception Is thrown, if no artefacts are available
     */
    protected function getArtefactsByTypeAndEntityId($type, $entityId)
    {
        return $this->getSubject()->getArtefactsByTypeAndEntityId($type, $entityId);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Actions\Processors\AttributeOptionCreateProcessor
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Actions\Processors;

use TechDivision\Import\Attribute\Utils\SqlStatementKeys;
use TechDivision\Import\Actions\Processors\AbstractCreateProcessor;

/**
 * The EAV attribute option create 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-attribute
 * @link      http://www.techdivision.com
 */
class AttributeOptionCreateProcessor extends AbstractCreateProcessor
{

    /**
     * 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 the array with the SQL statements that has to be prepared
        return array(
            SqlStatementKeys::CREATE_ATTRIBUTE_OPTION => $this->loadStatement(SqlStatementKeys::CREATE_ATTRIBUTE_OPTION)
        );
    }

    /**
     * Persist's the passed row.
     *
     * @param array       $row  The row to persist
     * @param string|null $name The name of the prepared statement that has to be executed
     *
     * @return string The last inserted ID
     */
    public function execute($row, $name = null)
    {
        parent::execute($row, $name);
        return $this->getConnection()->lastInsertId();
    }
}


<?php

namespace StatonLab\TripalTestSuite\Database;

class Factory
{
    /**
     * An array of all defined factories.
     *
     * @var array[Factory]
     */
    public static $factories = [];

    /**
     * Table to use.
     *
     * @var string
     */
    protected $table;

    /**
     * Number of times to run the create function.
     *
     * @var int
     */
    protected $times;

    /**
     * Table primary key.
     *
     * @var string
     */
    protected $primary_key;

    /**
     * Faker locale.
     *
     * @var string
     */
    protected $locale;

    /**
     * Create a new Factory instance.
     *
     * @param string $table Table name preceded by the schema if not public.
     *                       Example: "node", "public.node" or "chado.feature"
     * @param int $times The number of times to repeat the operation.
     * @return void
     * @throws \Exception
     */
    public function __construct($table, $times = 1)
    {
        if (! isset(static::$factories[$table])) {
            throw new \Exception("Attempt to use an undefined factory of type $table.");
        }

        $this->table = $table;
        $this->times = $times;
        $this->primary_key = $this->extractPrimaryKey();
        $this->locale = getenv('FAKER_LOCALE');
        if ($this->locale === false) {
            $this->locale = 'en_US';
        }
    }

    /**
     * Define and register a new factory.
     *
     * @param string $table Table name preceded by the schema if not public.
     *                       Example: "node", "public.node" or "chado.feature"
     * @param callable $callback
     * @param string $primary_key The primary key in the table. If provided,
     *                            will be used to retrieve the inserted record.
     *                            For Chado tables, chado_get_schema will be used
     *                            to retrieve the primary key if non provided.
     */
    public static function define($table, callable $callback, $primary_key = null)
    {
        static::$factories[$table] = [
            'primary_key' => $primary_key,
            'callback' => $callback,
        ];
    }

    /**
     * Check if a table factory is defined.
     *
     * @param string $table Table name. For chado tables, precede with `chado.`
     * @return bool
     */
    public static function exists($table)
    {
        return isset(static::$factories[$table]);
    }

    /**
     * Create the data.
     *
     * @param array $overrides
     * @throws \Exception
     * @return \stdClass|array If only one item was inserted, an object will be returned.
     *                         Otherwise, an array of objects will be returned.
     */
    public function create(array $overrides = [])
    {
        $factory = static::$factories[$this->table]['callback'];
        $data = [];

        for ($i = 0; $i < $this->times; $i++) {
            $values = $this->override($factory(\Faker\Factory::create($this->locale)), $overrides);

            $data[] = $this->insert($values);
        }

        if (count($data) === 1) {
            return $data[0];
        }

        return $data;
    }

    /**
     * Override array.
     *
     * @param array $values
     * @param array $overrides
     * @return array
     */
    protected function override(array $values, array $overrides)
    {
        if (count($overrides) === 0) {
            return $values;
        }

        foreach ($overrides as $key => $value) {
            $values[$key] = $overrides[$key];
        }

        return $values;
    }

    /**
     * Insert data into the db and obtain the inserted records.
     *
     * @param $values
     * @throws \Exception
     * @return \stdClass
     */
    protected function insert($values)
    {
        $id = db_insert($this->table)->fields($values)->execute();

        $query = db_select($this->table, 'T');
        $query->fields('T');
        $query->condition($this->primary_key, $id);

        return $query->execute()->fetchObject();
    }

    /**
     * Get the primary key of a table.
     *
     * @throws \Exception
     * @return string
     */
    protected function extractPrimaryKey()
    {
        if (static::$factories[$this->table]['primary_key'] !== null) {
            return static::$factories[$this->table]['primary_key'];
        }

        if (preg_match('/^chado\./', $this->table)) {
            $schema = chado_get_schema(str_replace('chado.', '', $this->table));
            if ($schema) {
                if (isset($schema['primary key'])) {
                    return $schema['primary key'][0];
                } elseif (isset($schema['primary keys'])) {
                    return $schema['primary keys'][0];
                }
            }
        }

        throw new \Exception("Unable to determine primary key for $this->table factory. Please provide the primary key such as `nid` as a third argument in Factory::define().");
    }

    /**
     * Get the primary key.
     *
     * @return string
     */
    public function primaryKey()
    {
        return $this->primary_key;
    }
}


<?php

namespace StatonLab\TripalTestSuite\Concerns;

trait InteractsWithAuthSystem
{
    /**
     * Set the active user.
     *
     * @param int|object $user Either a user object or simply a user id.
     * @return $this
     */
    public function actingAs($uid)
    {
        global $user;

        // Load the new requested user
        if (is_object($uid)) {
            if($uid->uid === 0) {
                $user = drupal_anonymous_user();
            } else{
                $user = user_load($uid->uid);
            }
        } else {
            if($uid === 0) {
                $user = drupal_anonymous_user();
            } else {
                $user = user_load($uid);
            }
        }

        $this->_cookies = [
            session_name() => session_id()
        ];

        return $this;
    }

    /**
     * Restore session data.
     */
    public function authSystemTearDown()
    {
        global $user;
        _drupal_session_destroy(session_id());
        $user = drupal_anonymous_user();
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\AttributeLabelUpdateObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Attribute\Utils\ColumnKeys;
use TechDivision\Import\Attribute\Utils\MemberNames;

/**
 * Observer that update's the EAV attribute label.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class AttributeLabelUpdateObserver extends AttributeLabelObserver
{

    /**
     * Initialize the attribute with the passed attributes and returns an instance.
     *
     * @param array $attr The attribute attributes
     *
     * @return array The initialized attribute
     */
    protected function initializeAttribute(array $attr)
    {

        // load the entity type ID for the value from the system configuration
        $entityTypeId = $this->getEntityTypeId();

        // load value, store ID
        $storeId = $attr[MemberNames::STORE_ID];

        // load the attribute code from the row
        $attributeCode = $this->getValue(ColumnKeys::ATTRIBUTE_CODE);

        // query whether or not an attribute label
        if ($attributeLabel = $this->loadAttributeLabelByEntityTypeIdAndAttributeCodeAndStoreId($entityTypeId, $attributeCode, $storeId)) {
            return $this->mergeEntity($attributeLabel, $attr);
        }

        // simply return the attributes
        return $attr;
    }

    /**
     * Return's the EAV attribute label with the passed attribute code and store ID.
     *
     * @param integer $entityTypeId  The ID of the EAV entity attribute to return the label for
     * @param string  $attributeCode The attribute code of the EAV attribute label to return
     * @param integer $storeId       The store ID of the EAV attribute label to return
     *
     * @return array The EAV attribute label
     */
    public function loadAttributeLabelByEntityTypeIdAndAttributeCodeAndStoreId($entityTypeId, $attributeCode, $storeId)
    {
        return $this->getAttributeBunchProcessor()->loadAttributeLabelByEntityTypeIdAndAttributeCodeAndStoreId($entityTypeId, $attributeCode, $storeId);
    }
}


<?php

namespace StatonLab\TripalTestSuite\Console\Commands;

use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class InitCommand extends BaseCommand
{
    /**
     * Path to module.
     *
     * @var string
     */
    protected $path;

    /**
     * Stubs directory.
     *
     * @var string
     */
    protected $stubsDir;

    /**
     * Set command configuration.
     */
    protected function configure()
    {
        $this->setName('init')
            ->setDescription('Setup testing environment along with Travis CI')
            ->setHelp('This command creates the tests folder, .travis.yml and phpunit.xml');

        // Add arguments
        $this->addArgument('name', InputArgument::OPTIONAL,
            'Specifies the module name (for example, tripal_awesome_extension).', $this->getModuleName());

        $this->addOption('force', 'f', InputOption::VALUE_NONE,
            'Force replacement of existing files such as phpunit.xml, .travis.yml, DataFactory.php, example.env, ExampleTest.php and bootstrap.php');
    }

    /**
     * Execute the command.
     */
    protected function handle()
    {
        $this->stubsDir = __DIR__.'/../../../stubs';
        $this->path = getcwd();

        if ($this->getOption('force') !== false) {
            $value = $this->ask("<info>Are you sure you want to force replacing files (y/N)?</info> ");

            if (! $value) {
                $this->info('Aborting');

                return;
            }
        }

        $this->createTestsFolder();

        $this->copyStubs([
            'bootstrap.php' => 'tests/bootstrap.php',
            'example.env' => 'tests/example.env',
            'travis.yml' => '.travis.yml',
            'phpunit.xml' => 'phpunit.xml',
            'ExampleTest.php' => 'tests/ExampleTest.php',
            'UsersTableSeeder.php' => 'tests/DatabaseSeeders/examples/UsersTableSeeder.php',
            'DataFactory.php' => 'tests/DataFactory.php',
            'DevSeedSeeder.php' => 'tests/DatabaseSeeders/examples/DevSeedSeeder.php',
        ]);

        try {
            $this->configureVariables([
                '.travis.yml' => [
                    '$$MODULE_NAME$$' => $this->getArgument('name'),
                ],
            ]);
        } catch (\Exception $exception) {
            $this->error($exception->getMessage());
        }

        // Done! Print success message and .gitignore instructions
        $this->info('Set up completed successfully. Please add the following lines to your .gitignore file.');
        $this->info('.env');
        $this->info('vendor/');
    }

    /**
     * Get a default module name.
     *
     * @return string
     */
    function getModuleName()
    {
        return basename(getcwd());
    }

    /**
     * Copy stubs to their paths.
     *
     * @param array $files List of files in the following structure: [STUB_FILENAME => NEW_PATH]
     */
    protected function copyStubs(array $files)
    {
        foreach ($files as $file => $to) {
            $to = "{$this->path}/{$to}";
            if (! file_exists($to) || $this->getOption('force') !== false) {
                copy("{$this->stubsDir}/{$file}", $to);
            } else {
                $this->line("TRIPALTEST: $to already exists.");
            }
        }
    }

    /**
     * Create tests folder.
     */
    protected function createTestsFolder()
    {
        if (! file_exists($this->path.'/tests')) {
            mkdir($this->path.'/tests');
        } else {
            $this->line('TRIPALTEST: tests folder already exists.');
        }

        if (! file_exists($this->path.'/tests/DatabaseSeeders')) {
            mkdir($this->path.'/tests/DatabaseSeeders');
        } else {
            $this->line('TRIPALTEST: tests/DatabaseSeeders folder already exists.');
        }

  if (! file_exists($this->path.'/tests/DatabaseSeeders/examples')) {
            mkdir($this->path.'/tests/DatabaseSeeders/examples');
        } else {
            $this->line('TRIPALTEST: tests/DatabaseSeeders/examples folder already exists.');
        }

    }

    /**
     * Finds a replaces variables in given files.
     *
     * @param array $files List of files and values in the following structure:
     *                        ['FILE_NAME' => [
     *                             "VARIABLE" => "NEW_VALUE"
     *                           ]
     *                        ]
     * @throws \Exception
     */
    protected function configureVariables(array $files)
    {
        foreach ($files as $file => $values) {
            $file = "{$this->path}/{$file}";
            if (! file_exists($file)) {
                throw new \Exception("TRIPALTEST: Unable to configure variables. $file does not exist!");
            }

            $content = file_get_contents($file);
            foreach ($values as $search => $replace) {
                $content = str_replace($search, $replace, $content);
            }

            file_put_contents($file, $content);
        }
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\CatalogAttributeObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Attribute\Utils\ColumnKeys;
use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface;

/**
 * Observer that create's the EAV catalog attribute itself.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class CatalogAttributeObserver extends AbstractAttributeImportObserver
{

    /**
     * The key for the additional data containing the swatch type.
     *
     * @var string
     */
    const SWATCH_INPUT_TYPE = 'swatch_input_type';

    /**
     * The available swatch types.
     *
     * @var array
     */
    protected $swatchTypes = array('text', 'visual');

    /**
     * The attribute processor instance.
     *
     * @var \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface
     */
    protected $attributeBunchProcessor;

    /**
     * The array with the possible column names.
     *
     * @var array
     */
    protected $columnNames = array(
        ColumnKeys::FRONTEND_INPUT_RENDERER,
        ColumnKeys::IS_GLOBAL,
        ColumnKeys::IS_VISIBLE,
        ColumnKeys::IS_SEARCHABLE,
        ColumnKeys::IS_FILTERABLE,
        ColumnKeys::IS_COMPARABLE,
        ColumnKeys::IS_VISIBLE_ON_FRONT,
        ColumnKeys::IS_HTML_ALLOWED_ON_FRONT,
        ColumnKeys::IS_USED_FOR_PRICE_RULES,
        ColumnKeys::IS_FILTERABLE_IN_SEARCH,
        ColumnKeys::USED_IN_PRODUCT_LISTING,
        ColumnKeys::USED_FOR_SORT_BY,
        ColumnKeys::APPLY_TO,
        ColumnKeys::IS_VISIBLE_IN_ADVANCED_SEARCH,
        ColumnKeys::POSITION,
        ColumnKeys::IS_WYSIWYG_ENABLED,
        ColumnKeys::IS_USED_FOR_PROMO_RULES,
        ColumnKeys::IS_REQUIRED_IN_ADMIN_STORE,
        ColumnKeys::IS_USED_IN_GRID,
        ColumnKeys::IS_VISIBLE_IN_GRID,
        ColumnKeys::IS_FILTERABLE_IN_GRID,
        ColumnKeys::SEARCH_WEIGHT,
        ColumnKeys::ADDITIONAL_DATA
    );

    /**
     * Initializes the observer with the passed subject instance.
     *
     * @param \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface $attributeBunchProcessor The attribute bunch processor instance
     */
    public function __construct(AttributeBunchProcessorInterface $attributeBunchProcessor)
    {
        $this->attributeBunchProcessor = $attributeBunchProcessor;
    }

    /**
     * Process the observer's business logic.
     *
     * @return void
     */
    protected function process()
    {

        // query whether or not, we've found a new attribute code => means we've found a new attribute
        if ($this->hasBeenProcessed($this->getValue(ColumnKeys::ATTRIBUTE_CODE))) {
            return;
        }

        // initialize and persist the EAV catalog attribute
        $this->persistCatalogAttribute($this->initializeAttribute($this->prepareAttributes()));
    }

    /**
     * Prepare the attributes of the entity that has to be persisted.
     *
     * @return array The prepared attributes
     * @throws \Exception Is thrown, if the size of the option values doesn't equals the size of swatch values, in case
     */
    protected function prepareAttributes()
    {

        // load the recently created EAV attribute ID
        $attributeId = $this->getLastAttributeId();

        // initialize the attributes
        $attr = array(MemberNames::ATTRIBUTE_ID => $attributeId);

        // iterate over the possible columns and handle the data
        foreach ($this->columnNames as $columnName) {
            // query whether or not, the column is available in the CSV file
            if ($this->getSubject()->hasHeader($columnName)) {
                // custom handling for the additional_data column
                if ($columnName === ColumnKeys::ADDITIONAL_DATA) {
                    // load the raw additional data
                    $explodedAdditionalData = $this->getValue(ColumnKeys::ADDITIONAL_DATA, array(), array($this->getSubject(), 'explode'));

                    // query whether or not additional data has been set
                    if (sizeof($explodedAdditionalData) > 0) {
                        // load and extract the additional data
                        $additionalData = array();
                        foreach ($explodedAdditionalData as $value) {
                            list ($key, $val) = $this->getSubject()->explode($value, '=');
                            $additionalData[$key] = $val;
                        }

                        // set the additional data
                        $attr[$columnName] = $additionalData;

                        // query whether or not the attribute is a text or a visual swatch
                        if ($this->isSwatchType($additionalData)) {
                            // load the attribute option values for the custom store views
                            $attributeOptionValues = $this->getValue(ColumnKeys::ATTRIBUTE_OPTION_VALUES, array(), array($this, 'explode'));
                            $attributeOptionSwatch = $this->getSubject()->explode($this->getValue(ColumnKeys::ATTRIBUTE_OPTION_SWATCH), $this->getSubject()->getMultipleValueDelimiter());

                            // query whether or not the size of the option values equals the size of the swatch values
                            if (($sizeOfSwatchValues = sizeof($attributeOptionSwatch)) !== ($sizeOfOptionValues = sizeof($attributeOptionValues))) {
                                throw new \Exception(
                                    sprintf(
                                        'Size of option values "%d" doesn\'t equals size of swatch values "%d"',
                                        $sizeOfOptionValues,
                                        $sizeOfSwatchValues
                                    )
                                );
                            }
                        }
                    }
                } else {
                    // query whether or not a column contains a value
                    if ($this->hasValue($columnName)) {
                        $attr[$columnName] = $this->getValue($columnName);
                    }
                }
            }
        }

        // return the prepared product
        return $this->initializeEntity($attr);
    }

    /**
     * Serialize the additional_data attribute of the passed array.
     *
     * @param array $attr The attribute with the data to serialize
     *
     * @return array The attribute with the serialized additional_data
     */
    protected function serializeAdditionalData(array $attr)
    {

        // serialize the additional data value if available
        if (isset($attr[MemberNames::ADDITIONAL_DATA]) && $attr[MemberNames::ADDITIONAL_DATA] !== null) {
            $attr[MemberNames::ADDITIONAL_DATA] = json_encode($attr[MemberNames::ADDITIONAL_DATA]);
        }

        // return the attribute
        return $attr;
    }

    /**
     * Initialize the attribute with the passed attributes and returns an instance.
     *
     * @param array $attr The attribute attributes
     *
     * @return array The initialized attribute
     */
    protected function initializeAttribute(array $attr)
    {
        return $this->serializeAdditionalData($attr);
    }

    /**
     * Return's the attribute bunch processor instance.
     *
     * @return \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface The attribute bunch processor instance
     */
    protected function getAttributeBunchProcessor()
    {
        return $this->attributeBunchProcessor;
    }

    /**
     * Map's the passed attribute code to the attribute ID that has been created recently.
     *
     * @param string $attributeCode The attribute code that has to be mapped
     *
     * @return void
     */
    protected function addAttributeCodeIdMapping($attributeCode)
    {
        $this->getSubject()->addAttributeCodeIdMapping($attributeCode);
    }

    /**
     * Queries whether or not the attribute with the passed code has already been processed.
     *
     * @param string $attributeCode The attribute code to check
     *
     * @return boolean TRUE if the path has been processed, else FALSE
     */
    protected function hasBeenProcessed($attributeCode)
    {
        return $this->getSubject()->hasBeenProcessed($attributeCode);
    }

    /**
     * Return's the ID of the attribute that has been created recently.
     *
     * @return integer The attribute ID
     */
    protected function getLastAttributeId()
    {
        return $this->getSubject()->getLastAttributeId();
    }

    /**
     * Return's TRUE if the additional data contains a swatch type.
     *
     * @param array $additionalData The additional data to query for a valid swatch type
     *
     * @return boolean TRUE if the data contains a swatch type, else FALSE
     */
    protected function isSwatchType(array $additionalData)
    {
        return isset($additionalData[CatalogAttributeObserver::SWATCH_INPUT_TYPE]) && in_array($additionalData[CatalogAttributeObserver::SWATCH_INPUT_TYPE], $this->swatchTypes);
    }

    /**
     * Persist the passed EAV catalog attribute.
     *
     * @param array $catalogAttribute The EAV catalog attribute to persist
     *
     * @return void
     */
    protected function persistCatalogAttribute(array $catalogAttribute)
    {
        return $this->getAttributeBunchProcessor()->persistCatalogAttribute($catalogAttribute);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\EntityAttributeUpdateObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Attribute\Utils\MemberNames;

/**
 * Observer that update's the EAV entity attribute itself.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class EntityAttributeUpdateObserver extends EntityAttributeObserver
{

    /**
     * Initialize the attribute with the passed attributes and returns an instance.
     *
     * @param array $attr The attribute attributes
     *
     * @return array The initialized attribute
     */
    protected function initializeAttribute(array $attr)
    {

        // load the attribute + attribute set ID
        $attributeId = $attr[MemberNames::ATTRIBUTE_ID];
        $attributeSetId = $attr[MemberNames::ATTRIBUTE_SET_ID];

        // try to load the entity attribute with the IDs
        if ($entityAttribute = $this->loadEntityAttributeByAttributeIdAndAttributeSetId($attributeId, $attributeSetId)) {
            return $this->mergeEntity($entityAttribute, $attr);
        }

        // simply return the attributes
        return $attr;
    }

    /**
     * Return's the EAV entity attribute with the passed attribute and attribute set ID.
     *
     * @param integer $attributeId    The ID of the EAV entity attribute's attribute to return
     * @param integer $attributeSetId The ID of the EAV entity attribute's attribute set to return
     *
     * @return array The EAV entity attribute
     */
    protected function loadEntityAttributeByAttributeIdAndAttributeSetId($attributeId, $attributeSetId)
    {
        return $this->getAttributeBunchProcessor()->loadEntityAttributeByAttributeIdAndAttributeSetId($attributeId, $attributeSetId);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\AttributeOptionValueExportObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Attribute\Utils\ColumnKeys;

/**
 * Observer that exports the attribute option swatch values to an additional CSV file for further processing.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class AttributeOptionSwatchExportObserver extends AbstractAttributeExportObserver
{

    /**
     * The artefact type.
     *
     * @var string
     */
    const ARTEFACT_TYPE = 'option-swatch-import';

    /**
     * Process the observer's business logic.
     *
     * @return void
     */
    protected function process()
    {

        // do NOT export the value if we're NOT in the admin store view
        if ($this->isAdminStore()) {
            return;
        }

        // prepare the store view code
        $this->prepareStoreViewCode();

        // initialize the array with the artefacts
        $artefacts = array();

        // load the attribute option values for the custom store views
        $attributeOptionValues = $this->getValue(ColumnKeys::ATTRIBUTE_OPTION_VALUES, array(), array($this, 'explode'));
        $attributeOptionSwatch = $this->explode($this->getValue(ColumnKeys::ATTRIBUTE_OPTION_SWATCH), $this->getMultipleValueDelimiter());

        // load the option value keys
        $optionValueKeys = array_keys($attributeOptionValues);

        // iterate over the attribute option values and export them
        foreach ($optionValueKeys as $key) {
            // load the artefacts with the admin store values
            $adminValueArtefacts = $this->getArtefactsByTypeAndEntityId(AttributeOptionExportObserver::ARTEFACT_TYPE, $this->getLastEntityId());

            // initialize the attribute option swatch data
            $optionSwatch = array();
            if (isset($attributeOptionSwatch[$key])) {
                // prepare the EAV attribute option swatch values
                foreach ($this->explode($attributeOptionSwatch[$key]) as $value) {
                    $explodedSwatch = $this->explode($value, '=');
                    if (isset($explodedSwatch[0]) && isset($explodedSwatch[1])) {
                        $optionSwatch[$explodedSwatch[0]] = $explodedSwatch[1];
                    }
                }

                // initialize and add the new artefact
                $artefacts[] = $this->newArtefact(
                    array(
                        ColumnKeys::STORE_VIEW_CODE   => $this->getValue(ColumnKeys::STORE_VIEW_CODE),
                        ColumnKeys::ATTRIBUTE_CODE    => $this->getValue(ColumnKeys::ATTRIBUTE_CODE),
                        ColumnKeys::ADMIN_STORE_VALUE => $adminValueArtefacts[$key][ColumnKeys::VALUE],
                        ColumnKeys::SWATCH_TYPE       => isset($optionSwatch[ColumnKeys::TYPE]) ? $optionSwatch[ColumnKeys::TYPE] : null,
                        ColumnKeys::SWATCH_VALUE      => isset($optionSwatch[ColumnKeys::VALUE]) ? $optionSwatch[ColumnKeys::VALUE] : null
                    ),
                    array(
                        ColumnKeys::STORE_VIEW_CODE   => ColumnKeys::STORE_VIEW_CODE,
                        ColumnKeys::ATTRIBUTE_CODE    => ColumnKeys::ATTRIBUTE_CODE,
                        ColumnKeys::ADMIN_STORE_VALUE => $adminValueArtefacts[$key][ColumnKeys::VALUE],
                        ColumnKeys::SWATCH_TYPE       => ColumnKeys::ATTRIBUTE_OPTION_SWATCH,
                        ColumnKeys::SWATCH_VALUE      => ColumnKeys::ATTRIBUTE_OPTION_SWATCH
                    )
                );
            }
        }

        // add the array with the artefacts
        $this->addArtefacts($artefacts, false);
    }

    /**
     * Return's the artefact type used for export.
     *
     * @return string The artefact type
     */
    protected function getArtefactType()
    {
        return AttributeOptionSwatchExportObserver::ARTEFACT_TYPE;
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\AttributeObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Utils\BackendTypeKeys;
use TechDivision\Import\Attribute\Utils\ColumnKeys;
use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface;

/**
 * Observer that create's the EAV attribute itself.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class AttributeObserver extends AbstractAttributeImportObserver
{

    /**
     * The attribute processor instance.
     *
     * @var \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface
     */
    protected $attributeBunchProcessor;

    /**
     * Initializes the observer with the passed subject instance.
     *
     * @param \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface $attributeBunchProcessor The attribute bunch processor instance
     */
    public function __construct(AttributeBunchProcessorInterface $attributeBunchProcessor)
    {
        $this->attributeBunchProcessor = $attributeBunchProcessor;
    }

    /**
     * Process the observer's business logic.
     *
     * @return void
     */
    protected function process()
    {

        // query whether or not, we've found a new attribute code => means we've found a new attribute
        if ($this->hasBeenProcessed($this->getValue(ColumnKeys::ATTRIBUTE_CODE))) {
            return;
        }

        // prepare the attribue values
        $attribute = $this->initializeAttribute($this->prepareAttributes());

        // insert the entity and set the entity ID
        $this->setLastAttributeId($this->persistAttribute($attribute));
    }

    /**
     * Prepare the attributes of the entity that has to be persisted.
     *
     * @return array The prepared attributes
     */
    protected function prepareAttributes()
    {

        // map the entity type code to the ID
        $entityType = $this->getEntityType($this->getValue(ColumnKeys::ENTITY_TYPE_CODE));
        $entityTypeId = $entityType[MemberNames::ENTITY_TYPE_ID];

        // load the data from the row
        $attributeCode = $this->getValue(ColumnKeys::ATTRIBUTE_CODE);
        $attributeModel = $this->getValue(ColumnKeys::ATTRIBUTE_MODEL);
        $backendModel = $this->getValue(ColumnKeys::BACKEND_MODEL);
        $backendType = $this->getValue(ColumnKeys::BACKEND_TYPE, BackendTypeKeys::BACKEND_TYPE_STATIC);
        $backendTable = $this->getValue(ColumnKeys::BACKEND_TABLE);
        $frontendModel = $this->getValue(ColumnKeys::FRONTEND_MODEL);
        $frontendInput = $this->getValue(ColumnKeys::FRONTEND_INPUT);
        $frontendLabel = $this->getValue(ColumnKeys::FRONTEND_LABEL);
        $frontendClass = $this->getValue(ColumnKeys::FRONTEND_CLASS);
        $sourceModel = $this->getValue(ColumnKeys::SOURCE_MODEL);
        $isRequired = $this->getValue(ColumnKeys::IS_REQUIRED, 0);
        $isUserDefined = $this->getValue(ColumnKeys::IS_USER_DEFINED, 1);
        $isUnique = $this->getValue(ColumnKeys::IS_UNIQUE, 0);
        $note = $this->getValue(ColumnKeys::NOTE);

        // return the prepared product
        return $this->initializeEntity(
            array(
                MemberNames::ENTITY_TYPE_ID  => $entityTypeId,
                MemberNames::ATTRIBUTE_CODE  => $attributeCode,
                MemberNames::ATTRIBUTE_MODEL => $attributeModel,
                MemberNames::BACKEND_MODEL   => $backendModel,
                MemberNames::BACKEND_TYPE    => $backendType,
                MemberNames::BACKEND_TABLE   => $backendTable,
                MemberNames::FRONTEND_MODEL  => $frontendModel,
                MemberNames::FRONTEND_INPUT  => $frontendInput,
                MemberNames::FRONTEND_LABEL  => $frontendLabel,
                MemberNames::FRONTEND_CLASS  => $frontendClass,
                MemberNames::SOURCE_MODEL    => $sourceModel,
                MemberNames::IS_REQUIRED     => $isRequired,
                MemberNames::IS_USER_DEFINED => $isUserDefined,
                MemberNames::DEFAULT_VALUE   => null,
                MemberNames::IS_UNIQUE       => $isUnique,
                MemberNames::NOTE            => $note
            )
        );
    }

    /**
     * Initialize the attribute with the passed attributes and returns an instance.
     *
     * @param array $attr The attribute attributes
     *
     * @return array The initialized attribute
     */
    protected function initializeAttribute(array $attr)
    {
        return $attr;
    }

    /**
     * Return's the attribute bunch processor instance.
     *
     * @return \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface The attribute bunch processor instance
     */
    protected function getAttributeBunchProcessor()
    {
        return $this->attributeBunchProcessor;
    }

    /**
     * Map's the passed attribute code to the attribute ID that has been created recently.
     *
     * @param string $attributeCode The attribute code that has to be mapped
     *
     * @return void
     */
    protected function addAttributeCodeIdMapping($attributeCode)
    {
        $this->getSubject()->addAttributeCodeIdMapping($attributeCode);
    }

    /**
     * Queries whether or not the attribute with the passed code has already been processed.
     *
     * @param string $attributeCode The attribute code to check
     *
     * @return boolean TRUE if the path has been processed, else FALSE
     */
    protected function hasBeenProcessed($attributeCode)
    {
        return $this->getSubject()->hasBeenProcessed($attributeCode);
    }

    /**
     * Set's the ID of the attribute that has been created recently.
     *
     * @param integer $lastAttributeId The attribute ID
     *
     * @return void
     */
    protected function setLastAttributeId($lastAttributeId)
    {
        $this->getSubject()->setLastAttributeId($lastAttributeId);
    }

    /**
     * Persist the passed attribute.
     *
     * @param array $attribute The attribute to persist
     *
     * @return void
     */
    protected function persistAttribute(array $attribute)
    {
        return $this->getAttributeBunchProcessor()->persistAttribute($attribute);
    }

    /**
     * Return's the entity type for the passed code.
     *
     * @param string $entityTypeCode The entity type code
     *
     * @return array The requested entity type
     * @throws \Exception Is thrown, if the entity type with the passed code is not available
     */
    protected function getEntityType($entityTypeCode)
    {
        return $this->getSubject()->getEntityType($entityTypeCode);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\AttributeOptionValueObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Utils\StoreViewCodes;
use TechDivision\Import\Attribute\Utils\ColumnKeys;
use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface;

/**
 * Observer that create's the attribute option values found in the additional CSV file.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class AttributeOptionValueObserver extends AbstractAttributeImportObserver
{

    /**
     * The attribute processor instance.
     *
     * @var \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface
     */
    protected $attributeBunchProcessor;

    /**
     * Initializes the observer with the passed subject instance.
     *
     * @param \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface $attributeBunchProcessor The attribute bunch processor instance
     */
    public function __construct(AttributeBunchProcessorInterface $attributeBunchProcessor)
    {
        $this->attributeBunchProcessor = $attributeBunchProcessor;
    }

    /**
     * Process the observer's business logic.
     *
     * @return void
     */
    protected function process()
    {

        // prepare the store view code
        $this->prepareStoreViewCode();

        // prepare and insert the attribute option value
        $this->persistAttributeOptionValue($this->initializeAttribute($this->prepareAttributes()));
    }

    /**
     * Prepare the attributes of the entity that has to be persisted.
     *
     * @return array The prepared attributes
     */
    protected function prepareAttributes()
    {

        // load the option ID
        $optionId = $this->getLastOptionId();

        // load the store ID
        $storeId = $this->getRowStoreId(StoreViewCodes::ADMIN);

        // load the attribute option value
        $value = $this->getValue(ColumnKeys::VALUE);

        // return the prepared attribute option
        return $this->initializeEntity(
            array(
                MemberNames::OPTION_ID  => $optionId,
                MemberNames::STORE_ID   => $storeId,
                MemberNames::VALUE      => $value
            )
        );
    }

    /**
     * Initialize the EAV attribute option value with the passed attributes and returns an instance.
     *
     * @param array $attr The EAV attribute option value attributes
     *
     * @return array The initialized EAV attribute option value
     */
    protected function initializeAttribute(array $attr)
    {
        return $attr;
    }

    /**
     * Return's the attribute bunch processor instance.
     *
     * @return \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface The attribute bunch processor instance
     */
    protected function getAttributeBunchProcessor()
    {
        return $this->attributeBunchProcessor;
    }

    /**
     * Return's the ID of the option that has been created recently.
     *
     * @return integer The option ID
     */
    protected function getLastOptionId()
    {
        return $this->getSubject()->getLastOptionId();
    }

    /**
     * Persist the passed attribute option value.
     *
     * @param array $attributeOptionValue The attribute option value to persist
     *
     * @return void
     */
    protected function persistAttributeOptionValue(array $attributeOptionValue)
    {
        return $this->getAttributeBunchProcessor()->persistAttributeOptionValue($attributeOptionValue);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\EntityAttributeObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Attribute\Utils\ColumnKeys;
use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface;

/**
 * Observer that create's the EAV entity attribute itself.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class EntityAttributeObserver extends AbstractAttributeImportObserver
{

    /**
     * The attribute processor instance.
     *
     * @var \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface
     */
    protected $attributeBunchProcessor;

    /**
     * Initializes the observer with the passed subject instance.
     *
     * @param \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface $attributeBunchProcessor The attribute bunch processor instance
     */
    public function __construct(AttributeBunchProcessorInterface $attributeBunchProcessor)
    {
        $this->attributeBunchProcessor = $attributeBunchProcessor;
    }

    /**
     * Process the observer's business logic.
     *
     * @return void
     */
    protected function process()
    {

        // query whether or not, we've found a new attribute code => means we've found a new attribute
        if ($this->hasBeenProcessed($this->getValue(ColumnKeys::ATTRIBUTE_CODE))) {
            return;
        }

        // load the last attribute ID
        $this->attributeId = $this->getLastAttributeId();

        // map the entity type code to the ID
        $entityType = $this->getEntityType($this->entityTypeCode = $this->getValue(ColumnKeys::ENTITY_TYPE_CODE));
        $this->entityTypeId = $entityType[MemberNames::ENTITY_TYPE_ID];

        // load the sort order for the attribute
        $this->sortOrder = $this->getValue(ColumnKeys::SORT_ORDER, 0);

        // explode the attribute set + group names
        $attributeSetNames = $this->getValue(ColumnKeys::ATTRIBUTE_SET_NAME, array(), array($this, 'explode'));
        $attributeGroupNames = $this->getValue(ColumnKeys::ATTRIBUTE_GROUP_NAME, array(), array($this, 'explode'));

        // make sure we've the same number of attribute sets/gropus
        if (sizeof($attributeSetNames) !== sizeof($attributeGroupNames)) {
            throw new \Exception(sprintf('Size of attribute names doesn\'t match size of attribute groups'));
        }

        // iterate over the attribute names and create the attribute entities therefore
        foreach ($attributeSetNames as $key => $attributeSetName) {
            // load the attribute set ID
            $attributeSet = $this->getAttributeSetByAttributeSetNameAndEntityTypeCode($attributeSetName, $this->entityTypeCode);

            // initialize the values to create the attribute entity
            $this->attributeSetId = $attributeSet[MemberNames::ATTRIBUTE_SET_ID];
            $this->attributeSetName = $attributeSetName;
            $this->attributeGroupName = $attributeGroupNames[$key];

            // prepare the EAV entity attribue values
            $entityAttribute = $this->initializeAttribute($this->prepareAttributes());

            // insert the EAV entity attribute
            $this->persistEntityAttribute($entityAttribute);
        }
    }

    /**
     * Prepare the attributes of the entity that has to be persisted.
     *
     * @return array The prepared attributes
     */
    protected function prepareAttributes()
    {

        // load the attribute group ID
        $attributeGroup = $this->getAttributeGroupByEntityTypeCodeAndAttributeSetNameAndAttributeGroupName(
            $this->entityTypeCode,
            $this->attributeSetName,
            $this->attributeGroupName
        );

        // load the attribute group ID
        $attributeGroupId = $attributeGroup[MemberNames::ATTRIBUTE_GROUP_ID];

        // return the prepared product
        return $this->initializeEntity(
            array(
                MemberNames::ATTRIBUTE_ID       => $this->attributeId,
                MemberNames::ENTITY_TYPE_ID     => $this->entityTypeId,
                MemberNames::ATTRIBUTE_SET_ID   => $this->attributeSetId,
                MemberNames::SORT_ORDER         => $this->sortOrder,
                MemberNames::ATTRIBUTE_GROUP_ID => $attributeGroupId
            )
        );
    }

    /**
     * Initialize the attribute with the passed attributes and returns an instance.
     *
     * @param array $attr The attribute attributes
     *
     * @return array The initialized attribute
     */
    protected function initializeAttribute(array $attr)
    {
        return $attr;
    }

    /**
     * Return's the attribute bunch processor instance.
     *
     * @return \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface The attribute bunch processor instance
     */
    protected function getAttributeBunchProcessor()
    {
        return $this->attributeBunchProcessor;
    }

    /**
     * Queries whether or not the attribute with the passed code has already been processed.
     *
     * @param string $attributeCode The attribute code to check
     *
     * @return boolean TRUE if the path has been processed, else FALSE
     */
    protected function hasBeenProcessed($attributeCode)
    {
        return $this->getSubject()->hasBeenProcessed($attributeCode);
    }

    /**
     * Return's the ID of the attribute that has been created recently.
     *
     * @return integer The attribute ID
     */
    protected function getLastAttributeId()
    {
        return $this->getSubject()->getLastAttributeId();
    }

    /**
     * Return's the entity type for the passed code.
     *
     * @param string $entityTypeCode The entity type code
     *
     * @return array The requested entity type
     * @throws \Exception Is thrown, if the entity type with the passed code is not available
     */
    protected function getEntityType($entityTypeCode)
    {
        return $this->getSubject()->getEntityType($entityTypeCode);
    }

    /**
     * Return's the attribute set with the passed attribute set name.
     *
     * @param string $attributeSetName The name of the requested attribute set
     * @param string $entityTypeCode   The entity type code of the requested attribute set
     *
     * @return array The EAV attribute set
     * @throws \Exception Is thrown, if the attribute set with the passed name is not available
     */
    protected function getAttributeSetByAttributeSetNameAndEntityTypeCode($attributeSetName, $entityTypeCode)
    {
        return $this->getSubject()->getAttributeSetByAttributeSetNameAndEntityTypeCode($attributeSetName, $entityTypeCode);
    }

    /**
     * Return's the attribute group with the passed attribute set/group name.
     *
     * @param string $entityTypeCode     The entity type code of the requested attribute group
     * @param string $attributeSetName   The name of the requested attribute group's attribute set
     * @param string $attributeGroupName The name of the requested attribute group
     *
     * @return array The EAV attribute group
     * @throws \Exception Is thrown, if the attribute group with the passed attribute set/group name is not available
     */
    protected function getAttributeGroupByEntityTypeCodeAndAttributeSetNameAndAttributeGroupName($entityTypeCode, $attributeSetName, $attributeGroupName)
    {
        return $this->getSubject()->getAttributeGroupByEntityTypeCodeAndAttributeSetNameAndAttributeGroupName($entityTypeCode, $attributeSetName, $attributeGroupName);
    }

    /**
     * Persist the passed entity attribute.
     *
     * @param array $entityAttribute The entity attribute to persist
     *
     * @return void
     */
    protected function persistEntityAttribute(array $entityAttribute)
    {
        return $this->getAttributeBunchProcessor()->persistEntityAttribute($entityAttribute);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Callbacks\SwatchTypeLoader
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Callbacks;

use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Observers\CatalogAttributeObserver;
use TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface;

/**
 * A loader implementation that loads the swatch type for the attribute with the given code.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class SwatchTypeLoader implements SwatchTypeLoaderInterface
{

    /**
     * The attribute bunch processor instance.
     *
     * @var \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface
     */
    protected $attributeBunchProcessor;

    /**
     * The swatch type of the actual attribute handled by the callback.
     *
     * @var array
     */
    protected $swatchType = array();

    /**
     * Initialize the callback with the passed attribute bunch processor instance.
     *
     * @param \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface $attributeProcessor The attribute bunch processor instance
     */
    public function __construct(AttributeBunchProcessorInterface $attributeProcessor)
    {
        $this->attributeBunchProcessor = $attributeProcessor;
    }

    /**
     * Returns the attribute bunch processor instance.
     *
     * @return \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface The attribute bunch processor instance
     */
    protected function getAttributeBunchProcessor()
    {
        return $this->attributeBunchProcessor;
    }

    /**
     * Query whether or not a swatch type for the attribute with the given key has already been loaded.
     *
     * @param string $key The key to query for
     *
     * @return boolean TRUE if the swatch type has been loaded, else FALSE
     */
    protected function hasSwatchType($key)
    {
        return isset($this->swatchType[$key]);
    }

    /**
     * Set the swatch type for the given attribute key.
     *
     * @param string $key        The attribute key to set the swatch type for
     * @param string $swatchType The swatch type of the attribute with the given code
     *
     * @return void
     */
    protected function setSwatchType($key, $swatchType)
    {
        $this->swatchType[$key] = $swatchType;
    }

    /**
     * Returns the swatch type for the passed attribute key.
     *
     * @param string $key The attribute key to return the swatch type for
     *
     * @return string|null The swatch type of the attribute with the passed key or NULL
     */
    protected function getSwatchType($key)
    {

        // reutrn the swatch type, if available
        if (isset($this->swatchType[$key])) {
            return $this->swatchType[$key];
        }
    }

    /**
     * Returns the swatch type for the attribute with the passed code and entity type ID.
     *
     * @param integer $entityTypeId  The entity type ID of the EAV attribute to return the swatch type for
     * @param string  $attributeCode The attribute code
     *
     * @return string|null The swatch type (either one of 'text' or 'visual') or NULL, if the attribute is NOT a swatch type
     */
    public function loadSwatchType($entityTypeId, $attributeCode)
    {

        // prepare a unique key for the swatch type from the given code and entity type ID
        $key = sprintf('%d-%s', $entityTypeId, $attributeCode);

        // query whether or not a swatch type has been set
        if ($this->hasSwatchType($key) === false) {
            // load the attribute and the catalog attribute data
            $attribute = $this->loadAttributeByEntityTypeIdAndAttributeCode($entityTypeId, $attributeCode);
            $catalogAttribute = $this->loadCatalogAttribute($attribute[MemberNames::ATTRIBUTE_ID]);

            // query whether or not additional data is available (to figure out if the attribute is a swatch type or not)
            if (is_array($catalogAttribute[MemberNames::ADDITIONAL_DATA]) && $catalogAttribute[MemberNames::ADDITIONAL_DATA] !== null) {
                // unserialize the additional data
                $additionalData = json_decode($catalogAttribute[MemberNames::ADDITIONAL_DATA]);
                // load and return the swatch type (can be either one of 'text' or 'visual')
                return $this->setSwatchType($key, $additionalData[CatalogAttributeObserver::SWATCH_INPUT_TYPE]);
            }
        }

        // return the actual swatch type
        return $this->getSwatchType($key);
    }

    /**
     * Return's the EAV attribute with the passed entity type ID and code.
     *
     * @param integer $entityTypeId  The entity type ID of the EAV attribute to return
     * @param string  $attributeCode The code of the EAV attribute to return
     *
     * @return array The EAV attribute
     */
    protected function loadAttributeByEntityTypeIdAndAttributeCode($entityTypeId, $attributeCode)
    {
        return $this->getAttributeBunchProcessor()->loadAttributeByEntityTypeIdAndAttributeCode($entityTypeId, $attributeCode);
    }

    /**
     * Load's and retur's the EAV catalog attribute with the passed ID.
     *
     * @param string $attributeId The ID of the EAV catalog attribute to return
     *
     * @return array The EAV catalog attribute
     */
    protected function loadCatalogAttribute($attributeId)
    {
        return $this->getAttributeBunchProcessor()->loadCatalogAttribute($attributeId);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\PreLoadAttributeOptionIdObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Utils\StoreViewCodes;
use TechDivision\Import\Attribute\Utils\ColumnKeys;
use TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface;

/**
 * Observer that pre-loads the option ID of the EAV attribute option with the attribute code/value found in the CSV file.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
class PreLoadAttributeOptionIdObserver extends AbstractAttributeImportObserver
{

    /**
     * The attribute processor instance.
     *
     * @var \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface
     */
    protected $attributeBunchProcessor;

    /**
     * Initializes the observer with the passed subject instance.
     *
     * @param \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface $attributeBunchProcessor The attribute bunch processor instance
     */
    public function __construct(AttributeBunchProcessorInterface $attributeBunchProcessor)
    {
        $this->attributeBunchProcessor = $attributeBunchProcessor;
    }

    /**
     * Return's the attribute bunch processor instance.
     *
     * @return \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface The attribute bunch processor instance
     */
    protected function getAttributeBunchProcessor()
    {
        return $this->attributeBunchProcessor;
    }

    /**
     * Process the observer's business logic.
     *
     * @return array The processed row
     */
    protected function process()
    {

        // load the store value and the attribute code
        $value = $this->getValue(ColumnKeys::ADMIN_STORE_VALUE);
        $attributeCode = $this->getValue(ColumnKeys::ATTRIBUTE_CODE);

        // query whether or not, we've found a new attribute code => means we've found a new EAV attribute
        if ($this->hasBeenProcessed($attributeCode, $value)) {
            return;
        }

        // load the entity type ID for the value from the system configuration
        $entityTypeId = $this->getEntityTypeId();

        // load the ID of the admin store
        $storeId = $this->getStoreId(StoreViewCodes::ADMIN);

        // load the EAV attribute option with the passed value
        $attributeOption = $this->loadAttributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndValue($entityTypeId, $attributeCode, $storeId, $value);

        // preserve the attribute ID for the passed EAV attribute option
        $this->preLoadOptionId($attributeOption);
    }

    /**
     * Queries whether or not the option with the passed code/value has already been processed.
     *
     * @param string $attributeCode The attribute code to check
     * @param string $value         The option value to check
     *
     * @return boolean TRUE if the path has been processed, else FALSE
     */
    protected function hasBeenProcessed($attributeCode, $value)
    {
        return $this->getSubject()->hasBeenProcessed($attributeCode, $value);
    }

    /**
     * Pre-load the option ID for the passed EAV attribute option.
     *
     * @param array $attributeOption The EAV attribute option with the ID that has to be pre-loaded
     *
     * @return void
     */
    protected function preLoadOptionId(array $attributeOption)
    {
        return $this->getSubject()->preLoadOptionId($attributeOption);
    }

    /**
     * Load's and return's the EAV attribute option with the passed entity type ID, code, store ID and value.
     *
     * @param string  $entityTypeId  The entity type ID of the EAV attribute to load the option for
     * @param string  $attributeCode The code of the EAV attribute option to load
     * @param integer $storeId       The store ID of the attribute option to load
     * @param string  $value         The value of the attribute option to load
     *
     * @return array The EAV attribute option
     */
    protected function loadAttributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndValue($entityTypeId, $attributeCode, $storeId, $value)
    {
        return $this->getAttributeBunchProcessor()->loadAttributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndValue($entityTypeId, $attributeCode, $storeId, $value);
    }
}


<?php

namespace StatonLab\TripalTestSuite\Console\Commands;

use StatonLab\TripalTestSuite\Database\LoadsDatabaseSeeders;
use StatonLab\TripalTestSuite\Database\Seeder;
use StatonLab\TripalTestSuite\TripalTestBootstrap;
use Symfony\Component\Console\Input\InputArgument;

class DBSeedCommand extends BaseCommand
{
    use LoadsDatabaseSeeders;

    /**
     * Configure the command.
     */
    public function configure()
    {
        $this->setName('db:seed')
            ->setHelp('db:seed [ExampleTableSeeder]')
            ->setDescription('Runs all seeders or a specific seeder class if provided');

        $this->addArgument('name', InputArgument::OPTIONAL, 'The name of the seeder to run such as ExampleTableSeeder');
    }

    /**
     * Seed the database.
     *
     * @throws \Exception
     */
    public function handle()
    {
        // Let's bootstrap first
        new TripalTestBootstrap(false);

        $this->loadDatabaseSeeders();

        $seeder = $this->getArgument('name');

        if ($seeder) {
            $this->runSeeder($seeder);
            $this->success($seeder);

            return;
        }

        if (empty($this->seeders)) {
            $this->error('No database seeders found!');

            return;
        }

        foreach ($this->seeders as $seeder) {
            $this->runSeeder($seeder);
            $this->success($seeder);
        }
    }

    /**
     * Prints success message.
     *
     * @param $seeder
     */
    protected function success($seeder)
    {
        $this->info("Ran $seeder successfully!");
    }

    /**
     * Get the fully qualified seeder name.
     *
     * @param $name
     * @return string
     */
    protected function prepSeeder($name)
    {
        $name = trim($name, '\\');
        if (strstr($name, 'Tests\\DatabaseSeeders') !== false) {
            return $name;
        }

        return 'Tests\\DatabaseSeeders\\'.$name;
    }

    /**
     * Run a given seeder.
     *
     * @param string $class
     * @return \StatonLab\TripalTestSuite\Database\Seeder
     * @throws \Exception
     */
    protected function runSeeder($class)
    {
        /** @var Seeder $class */
        $class = $this->prepSeeder($class);

        if (! in_array($class, $this->seeders)) {
            throw new \Exception("Seeder $class Not Found!");
        }

        return $class::seed();
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Repositories\AttributeOptionSwatchRepository
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Repositories;

use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Utils\SqlStatementKeys;
use TechDivision\Import\Repositories\AbstractRepository;

/**
 * Repository implementation to load EAV attribute option swatch 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-attribute
 * @link      http://www.techdivision.com
 */
class AttributeOptionSwatchRepository extends AbstractRepository implements AttributeOptionSwatchRepositoryInterface
{

    /**
     * The prepared statement to load an existing EAV attribute option swatch by its option ID and store ID
     *
     * @var \PDOStatement
     */
    protected $attributeOptionSwatchByOptionIdAndStoreIdStmt;

    /**
     * The prepared statement to load an existing EAV attribute option swatch by its attribute code, store ID. value and type.
     *
     * @var \PDOStatement
     */
    protected $attributeOptionSwatchByAttributeCodeAndStoreIdAndValueAndTypeStmt;

    /**
     * The prepared statement to load an existing EAV attribute option swatch by its attribute code, store ID. value and type.
     *
     * @var \PDOStatement
     */
    protected $attributeOptionSwatchByEntityTypeIdAndAttributeCodeAndStoreIdAndValueAndTypeStmt;

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

        // initialize the prepared statements
        $this->attributeOptionSwatchByOptionIdAndStoreIdStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_OPTION_SWATCH_BY_OPTION_ID_AND_STORE_ID));

        // initialize the prepared statements
        $this->attributeOptionSwatchByAttributeCodeAndStoreIdAndValueAndTypeStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_OPTION_SWATCH_BY_ATTRIBUTE_CODE_AND_STORE_ID_AND_VALUE_AND_TYPE));

        // initialize the prepared statements
        $this->attributeOptionSwatchByEntityTypeIdAndAttributeCodeAndStoreIdAndValueAndTypeStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_OPTION_SWATCH_BY_ENTITY_TYPE_ID_AND_ATTRIBUTE_CODE_AND_STORE_ID_AND_VALUE_AND_TYPE));
    }

    /**
     * Load's and return's the EAV attribute option swatch with the passed option ID and store ID
     *
     * @param string  $optionId The option ID of the attribute option swatch to load
     * @param integer $storeId  The store ID of the attribute option swatch to load
     *
     * @return array The EAV attribute option swatch
     */
    public function findOneByOptionIdAndStoreId($optionId, $storeId)
    {

        // the parameters of the EAV attribute option to load
        $params = array(
            MemberNames::OPTION_ID => $optionId,
            MemberNames::STORE_ID  => $storeId,
        );

        // load and return the EAV attribute option swatch with the passed parameters
        $this->attributeOptionSwatchByOptionIdAndStoreIdStmt->execute($params);
        return $this->attributeOptionSwatchByOptionIdAndStoreIdStmt->fetch(\PDO::FETCH_ASSOC);
    }

    /**
     * Load's and return's the EAV attribute option swatch with the passed code, store ID, value and type.
     *
     * @param string  $attributeCode The code of the EAV attribute option swatch to load
     * @param integer $storeId       The store ID of the attribute option swatch to load
     * @param string  $value         The value of the attribute option swatch to load
     * @param string  $type          The type of the attribute option swatch to load
     *
     * @return array The EAV attribute option swatch
     * @deprecated Since 2.0.2
     * @see \TechDivision\Import\Attribute\Repositories\AttributeOptionSwatchRepositoryInterface::findOneByEntityTypeIdAndAttributeCodeAndStoreIdAndValueAndType()
     */
    public function findOneByAttributeCodeAndStoreIdAndValue($attributeCode, $storeId, $value, $type)
    {

        // the parameters of the EAV attribute option to load
        $params = array(
            MemberNames::ATTRIBUTE_CODE => $attributeCode,
            MemberNames::STORE_ID       => $storeId,
            MemberNames::VALUE          => $value,
            MemberNames::TYPE           => $type
        );

        // load and return the EAV attribute option swatch with the passed parameters
        $this->attributeOptionSwatchByAttributeCodeAndStoreIdAndValueAndTypeStmt->execute($params);
        return $this->attributeOptionSwatchByAttributeCodeAndStoreIdAndValueAndTypeStmt->fetch(\PDO::FETCH_ASSOC);
    }

    /**
     * Load's and return's the EAV attribute option swatch with the passed entity type ID, code, store ID, value and type.
     *
     * @param string  $entityTypeId  The entity type ID of the EAV attribute to load the option swatch for
     * @param string  $attributeCode The code of the EAV attribute option swatch to load
     * @param integer $storeId       The store ID of the attribute option swatch to load
     * @param string  $value         The value of the attribute option swatch to load
     * @param string  $type          The type of the attribute option swatch to load
     *
     * @return array The EAV attribute option swatch
     */
    public function findOneByEntityTypeIdAndAttributeCodeAndStoreIdAndValueAndType($entityTypeId, $attributeCode, $storeId, $value, $type)
    {

        // the parameters of the EAV attribute option to load
        $params = array(
            MemberNames::ENTITY_TYPE_ID => $entityTypeId,
            MemberNames::ATTRIBUTE_CODE => $attributeCode,
            MemberNames::STORE_ID       => $storeId,
            MemberNames::VALUE          => $value,
            MemberNames::TYPE           => $type
        );

        // load and return the EAV attribute option swatch with the passed parameters
        $this->attributeOptionSwatchByEntityTypeIdAndAttributeCodeAndStoreIdAndValueAndTypeStmt->execute($params);
        return $this->attributeOptionSwatchByEntityTypeIdAndAttributeCodeAndStoreIdAndValueAndTypeStmt->fetch(\PDO::FETCH_ASSOC);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Repositories\EntityAttributeRepository
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Repositories;

use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Utils\SqlStatementKeys;
use TechDivision\Import\Repositories\AbstractRepository;

/**
 * Repository implementation to load EAV entity 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-attribute
 * @link      http://www.techdivision.com
 */
class EntityAttributeRepository extends AbstractRepository implements EntityAttributeRepositoryInterface
{

    /**
     * The prepared statement to load an existing EAV entity attribute by its attribut and attribut set ID.
     *
     * @var \PDOStatement
     */
    protected $entityAttributeByAttributeIdAndAttributeSetIdStmt;

    /**
     * The prepared statement to load an existing EAV entity attribute by its entity type, attribute, attribut set and attribute group ID.
     *
     * @var \PDOStatement
     */
    protected $entityAttributeByEntityTypeIdAndAttributeIdAndAttributeSetIdAndAttributeGroupIdStmt;

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

        // initialize the prepared statements
        $this->entityAttributeByAttributeIdAndAttributeSetIdStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ENTITY_ATTRIBUTE_BY_ATTRIBUTE_ID_AND_ATTRIBUTE_SET_ID));
        $this->entityAttributeByEntityTypeIdAndAttributeIdAndAttributeSetIdAndAttributeGroupIdStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ENTITY_ATTRIBUTE_BY_ENTITY_TYPE_ID_AND_ATTRIBUTE_ID_AND_ATTRIBUTE_SET_ID_AND_ATTRIBUTE_GROUP_ID));
    }

    /**
     * Return's the EAV entity attribute with the passed attribute + attribute set ID.
     *
     * @param integer $attributeId    The ID of the EAV entity attribute's attribute to return
     * @param integer $attributeSetId The ID of the EAV entity attribute's attribute set to return
     *
     * @return array The EAV entity attribute
     */
    public function findOneByAttributeIdAndAttributeSetId($attributeId, $attributeSetId)
    {

        // initialize the params
        $params = array(
            MemberNames::ATTRIBUTE_ID       => $attributeId,
            MemberNames::ATTRIBUTE_SET_ID   => $attributeSetId
        );

        // load and return the EAV entity attribute with the passed params
        $this->entityAttributeByAttributeIdAndAttributeSetIdStmt->execute($params);
        return $this->entityAttributeByAttributeIdAndAttributeSetIdStmt->fetch(\PDO::FETCH_ASSOC);
    }

    /**
     * Return's the EAV entity attribute with the passed entity type, attribute, attribute set and attribute group ID.
     *
     * @param integer $entityTypeId     The ID of the EAV entity attribute's entity type to return
     * @param integer $attributeId      The ID of the EAV entity attribute's attribute to return
     * @param integer $attributeSetId   The ID of the EAV entity attribute's attribute set to return
     * @param integer $attributeGroupId The ID of the EAV entity attribute's attribute group to return
     *
     * @return array The EAV entity attribute
     */
    public function findOneByEntityTypeIdAndAttributeIdAndAttributeSetIdAndAttributeGroupId($entityTypeId, $attributeId, $attributeSetId, $attributeGroupId)
    {

        // initialize the params
        $params = array(
            MemberNames::ENTITY_TYPE_ID     => $entityTypeId,
            MemberNames::ATTRIBUTE_ID       => $attributeId,
            MemberNames::ATTRIBUTE_SET_ID   => $attributeSetId,
            MemberNames::ATTRIBUTE_GROUP_ID => $attributeGroupId
        );

        // load and return the EAV entity attribute with the passed params
        $this->entityAttributeByEntityTypeIdAndAttributeIdAndAttributeSetIdAndAttributeGroupIdStmt->execute($params);
        return $this->entityAttributeByEntityTypeIdAndAttributeIdAndAttributeSetIdAndAttributeGroupIdStmt->fetch(\PDO::FETCH_ASSOC);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Repositories\AttributeOptionRepository
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Repositories;

use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Utils\SqlStatementKeys;
use TechDivision\Import\Repositories\AbstractRepository;

/**
 * Repository implementation to load EAV attribute option 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-attribute
 * @link      http://www.techdivision.com
 */
class AttributeOptionRepository extends AbstractRepository implements AttributeOptionRepositoryInterface
{

    /**
     * The prepared statement to load an existing EAV attribute option by its attribute code, store ID and value.
     *
     * @var \PDOStatement
     */
    protected $attributeOptionByAttributeCodeAndStoreIdAndValueStmt;

    /**
     * The prepared statement to load an existing EAV attribute option by its entity type ID, attribute code, store ID and value.
     *
     * @var \PDOStatement
     */
    protected $attributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndValueStmt;

    /**
     * The prepared statement to load an existing EAV attribute option by its entity type ID, attribute code, store ID and swatch.
     *
     * @var \PDOStatement
     */
    protected $attributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndSwatchAndTypeStmt;

    /**
     * The prepared statement to load the EAV attribute option with the given attribute ID and the highest sort order.
     *
     * @var \PDOStatement
     */
    protected $attributeOptionByAttributeIdOrderBySortOrderDescStmt;

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

        // initialize the prepared statements
        $this->attributeOptionByAttributeCodeAndStoreIdAndValueStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_OPTION_BY_ATTRIBUTE_CODE_AND_STORE_ID_AND_VALUE));
        $this->attributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndValueStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_OPTION_BY_ENTITY_TYPE_ID_AND_ATTRIBUTE_CODE_AND_STORE_ID_AND_VALUE));
        $this->attributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndSwatchAndTypeStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_OPTION_BY_ENTITY_TYPE_ID_AND_ATTRIBUTE_CODE_AND_STORE_ID_AND_SWATCH_AND_TYPE));
        $this->attributeOptionByAttributeIdOrderBySortOrderDescStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_OPTION_BY_ATTRIBUTE_ID_ORDER_BY_SORT_ORDER_DESC));
    }

    /**
     * Load's and return's the EAV attribute option with the passed code, store ID and value.
     *
     * @param string  $attributeCode The code of the EAV attribute option to load
     * @param integer $storeId       The store ID of the attribute option to load
     * @param string  $value         The value of the attribute option to load
     *
     * @return array The EAV attribute option
     * @deprecated Since 2.0.2
     * @see \TechDivision\Import\Attribute\Repositories\AttributeOptionRepositoryInterface::findOneByEntityTypeIdAndAttributeCodeAndStoreIdAndValue()
     */
    public function findOneByAttributeCodeAndStoreIdAndValue($attributeCode, $storeId, $value)
    {

        // the parameters of the EAV attribute option to load
        $params = array(
            MemberNames::ATTRIBUTE_CODE => $attributeCode,
            MemberNames::STORE_ID       => $storeId,
            MemberNames::VALUE          => $value
        );

        // load and return the EAV attribute option with the passed parameters
        $this->attributeOptionByAttributeCodeAndStoreIdAndValueStmt->execute($params);
        return $this->attributeOptionByAttributeCodeAndStoreIdAndValueStmt->fetch(\PDO::FETCH_ASSOC);
    }

    /**
     * Load's and return's the EAV attribute option with the passed entity type ID and code, store ID and value.
     *
     * @param string  $entityTypeId  The entity type ID of the EAV attribute to load the option for
     * @param string  $attributeCode The code of the EAV attribute option to load
     * @param integer $storeId       The store ID of the attribute option to load
     * @param string  $value         The value of the attribute option to load
     *
     * @return array The EAV attribute option
     */
    public function findOneByEntityTypeIdAndAttributeCodeAndStoreIdAndValue($entityTypeId, $attributeCode, $storeId, $value)
    {

        // the parameters of the EAV attribute option to load
        $params = array(
            MemberNames::ENTITY_TYPE_ID => $entityTypeId,
            MemberNames::ATTRIBUTE_CODE => $attributeCode,
            MemberNames::STORE_ID       => $storeId,
            MemberNames::VALUE          => $value
        );

        // load and return the EAV attribute option with the passed parameters
        $this->attributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndValueStmt->execute($params);
        return $this->attributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndValueStmt->fetch(\PDO::FETCH_ASSOC);
    }

    /**
     * Load's and return's the EAV attribute option with the passed entity type ID and code, store ID, swatch and type.
     *
     * @param string  $entityTypeId  The entity type ID of the EAV attribute to load the option for
     * @param string  $attributeCode The code of the EAV attribute option to load
     * @param integer $storeId       The store ID of the attribute option to load
     * @param string  $swatch        The swatch of the attribute option to load
     * @param string  $type          The swatch type of the attribute option to load
     *
     * @return array The EAV attribute option
     */
    public function findOneByEntityTypeIdAndAttributeCodeAndStoreIdAndSwatchAndType($entityTypeId, $attributeCode, $storeId, $swatch, $type)
    {

        // the parameters of the EAV attribute option to load
        $params = array(
            MemberNames::ENTITY_TYPE_ID => $entityTypeId,
            MemberNames::ATTRIBUTE_CODE => $attributeCode,
            MemberNames::STORE_ID       => $storeId,
            MemberNames::VALUE          => $swatch,
            MemberNames::TYPE           => $type
        );

        // load and return the EAV attribute option with the passed parameters
        $this->attributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndSwatchAndTypeStmt->execute($params);
        return $this->attributeOptionByEntityTypeIdAndAttributeCodeAndStoreIdAndSwatchAndTypeStmt->fetch(\PDO::FETCH_ASSOC);
    }

    /**
     * Returns the EAV attribute option of attribute with the passed ID with the highest sort order.
     *
     * @param integer $attributeId The ID of the attribute to return the EAV option with the highest sort order for
     *
     * @return array|null The EAV attribute option with the highest sort order
     */
    public function findOneByAttributeIdAndHighestSortOrder($attributeId)
    {

        // load and return the EAV attribute option with the passed parameters
        $this->attributeOptionByAttributeIdOrderBySortOrderDescStmt->execute(array(MemberNames::ATTRIBUTE_ID => $attributeId));
        return $this->attributeOptionByAttributeIdOrderBySortOrderDescStmt->fetch(\PDO::FETCH_ASSOC);
    }
}


<?php

/**
 * TechDivision\Import\Attribute\Observers\AbstractAttributeImportObserver
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Observers;

use TechDivision\Import\Attribute\Utils\ColumnKeys;
use TechDivision\Import\Observers\AbstractObserver;
use TechDivision\Import\Subjects\SubjectInterface;

/**
 * Abstract attribute observer that handles the process to import attribute bunches.
 *
 * @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-attribute
 * @link      http://www.techdivision.com
 */
abstract class AbstractAttributeImportObserver extends AbstractObserver implements AttributeImportObserverInterface
{

    /**
     * Will be invoked by the action on the events the listener has been registered for.
     *
     * @param \TechDivision\Import\Subjects\SubjectInterface $subject The subject instance
     *
     * @return array The modified row
     * @see \TechDivision\Import\Observers\ObserverInterface::handle()
     */
    public function handle(SubjectInterface $subject)
    {

        // initialize the row
        $this->setSubject($subject);
        $this->setRow($subject->getRow());

        // process the functionality and return the row
        $this->process();

        // return the processed row
        return $this->getRow();
    }

    /**
     * Return's whether or not this is the admin store view.
     *
     * @return boolean TRUE if we're in admin store view, else FALSE
     */
    protected function isAdminStore()
    {
        return $this->getValue(ColumnKeys::STORE_VIEW_CODE) === null;
    }

    /**
     * Returns the entity type ID for the passed code, or if no entity type code has
     * been passed, the default one from the configuration will be used.
     *
     * @param string|null $entityTypeCode The entity type code
     *
     * @return integer The actual entity type ID
     */
    protected function getEntityTypeId($entityTypeCode = null)
    {
        return $this->getSubject()->getEntityTypeId($entityTypeCode);
    }

    /**
     * Process the observer's business logic.
     *
     * @return void
     */
    abstract protected function process();
}


<?php

/**
 * TechDivision\Import\Attribute\Repositories\AttributeLabelRepository
 *
 * 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-attribute
 * @link      http://www.techdivision.com
 */

namespace TechDivision\Import\Attribute\Repositories;

use TechDivision\Import\Attribute\Utils\MemberNames;
use TechDivision\Import\Attribute\Utils\SqlStatementKeys;
use TechDivision\Import\Repositories\AbstractRepository;

/**
 * Repository implementation to load EAV attribute label 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-attribute
 * @link      http://www.techdivision.com
 */
class AttributeLabelRepository extends AbstractRepository implements AttributeLabelRepositoryInterface
{

    /**
     * The prepared statement to load an existing EAV attribute label by its attribute code and store ID.
     *
     * @var \PDOStatement
     */
    protected $attributeLabelByAttributeCodeAndStoreIdStmt;

    /**
     * The prepared statement to load an existing EAV attribute label by its entity type ID, attribute code and store ID.
     *
     * @var \PDOStatement
     */
    protected $attributeLabelByEntityTypeIdAndAttributeCodeAndStoreIdStmt;

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

        // initialize the prepared statements
        $this->attributeLabelByAttributeCodeAndStoreIdStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_LABEL_BY_ATTRIBUTE_CODE_AND_STORE_ID));

        // initialize the prepared statements
        $this->attributeLabelByEntityTypeIdAndAttributeCodeAndStoreIdStmt =
            $this->getConnection()->prepare($this->loadStatement(SqlStatementKeys::ATTRIBUTE_LABEL_BY_ENTITY_TYPE_ID_AND_ATTRIBUTE_CODE_AND_STORE_ID));
    }

    /**
     * Return's the EAV attribute label with the passed attribute code and store ID.
     *
     * @param string  $attributeCode The attribute code of the EAV attribute label to return
     * @param integer $storeId       The store ID of the EAV attribute label to return
     *
     * @return array The EAV attribute label
     * @deprecated Since 2.0.2
     * @see \TechDivision\Import\Attribute\Repositories\AttributeLabelRepositoryInterface::findOneByEntityTypeIdAndAttributeCodeAndStoreId()
     */
    public function findOneByAttributeCodeAndStoreId($attributeCode, $storeId)
    {

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

        // load and return the EAV attribute label with the passed params
        $this->attributeLabelByAttributeCodeAndStoreIdStmt->execute($params);
        return $this->attributeLabelByAttributeCodeAndStoreIdStmt->fetch(\PDO::FETCH_ASSOC);
    }

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

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

        // load and return the EAV attribute label with the passed params
        $this->attributeLabelByEntityTypeIdAndAttributeCodeAndStoreIdStmt->execute($params);
        return $this->attributeLabelByEntityTypeIdAndAttributeCodeAndStoreIdStmt->fetch(\PDO::FETCH_ASSOC);
    }
}