diff --git a/Bootstrap.php b/Bootstrap.php index b0969cba..af03e521 100644 --- a/Bootstrap.php +++ b/Bootstrap.php @@ -13,6 +13,7 @@ use Shopware\Commands\SwagImportExport\ExportCommand; use Shopware\Commands\SwagImportExport\ImportCommand; use Shopware\Commands\SwagImportExport\ProfilesCommand; +use Shopware\Components\CacheManager; use Shopware\Components\Model\ModelManager; use Shopware\Components\SwagImportExport\Factories\DataFactory; use Shopware\Components\SwagImportExport\Factories\DataTransformerFactory; @@ -32,9 +33,11 @@ use Shopware\Setup\SwagImportExport\Install\MainMenuItemInstaller; use Shopware\Setup\SwagImportExport\Install\OldAdvancedMenuInstaller; use Shopware\Setup\SwagImportExport\SetupContext; +use Shopware\Setup\SwagImportExport\Update\DefaultProfileUpdater; use Shopware\Setup\SwagImportExport\Update\Update01MainMenuItem; use Shopware\Setup\SwagImportExport\Update\Update02RemoveForeignKeyConstraint; use Shopware\Setup\SwagImportExport\Update\Update03DefaultProfileSupport; +use Shopware\Setup\SwagImportExport\Update\Update04CreateColumns; use Shopware\Setup\SwagImportExport\Update\UpdaterInterface; /** @@ -144,8 +147,9 @@ public function install() if (!$this->assertMinimumVersion('5.2.0')) { throw new MinVersionException('This plugin requires Shopware 5.2.0 or a later version'); } - - $this->clearDoctrineMetaDataCache(); + /** @var CacheManager $cacheManager */ + $cacheManager = $this->get('shopware.cache_manager'); + $cacheManager->clearProxyCache(); $setupContext = new SetupContext( $this->get('config')->get('version'), @@ -191,7 +195,12 @@ public function update($oldVersion) if (version_compare($oldVersion, '2.0.0', '<=')) { $this->renameDuplicateProfileNames(); } - $this->clearDoctrineMetaDataCache(); + /** @var CacheManager $cacheManager */ + $cacheManager = $this->get('shopware.cache_manager'); + $cacheManager->clearProxyCache(); + + $connection = $this->get('dbal_connection'); + $connection->executeQuery('SET foreign_key_checks = 0;'); $setupContext = new SetupContext( $this->get('config')->get('version'), @@ -208,13 +217,19 @@ public function update($oldVersion) $this->get('dbal_connection')->getSchemaManager() ); $updaters[] = new Update03DefaultProfileSupport($setupContext, $this->get('dbal_connection'), $this->get('snippets')); + $updaters[] = new Update04CreateColumns($setupContext, $this->get('dbal_connection')); + $updaters[] = new DefaultProfileUpdater($setupContext, $this->get('dbal_connection'), $this->get('snippets')); $this->registerControllers(); $this->createAclResource(); $this->registerEvents(); $this->createDirectories(); $this->createConfiguration(); - $this->updateDatabase(); + + try { + $this->updateDatabase(); + } catch (\Exception $e) { + } /** @var UpdaterInterface $updater */ foreach ($updaters as $updater) { @@ -223,6 +238,10 @@ public function update($oldVersion) } $updater->update(); } + $connection->executeQuery('SET foreign_key_checks = 1;'); + + $defaultProfileInstaller = new DefaultProfileInstaller($setupContext, $this->get('dbal_connection')); + $defaultProfileInstaller->install(); return [ 'success' => true, @@ -321,7 +340,6 @@ public function getDataFactory() if ($this->dataFactory === null) { $this->dataFactory = Enlight_Class::Instance('Shopware\Components\SwagImportExport\Factories\DataFactory'); } - return $this->dataFactory; } @@ -768,18 +786,6 @@ private function removeTablePrefix(SchemaTool $tool, array $classes) return $tableNames; } - /** - * Clear doctrine meta data cache to generate classes from class meta data by using SchemaTool::updateSchema() - * and SchemaTool::createSchema(). - */ - private function clearDoctrineMetaDataCache() - { - $cacheDriver = $this->get('models')->getConfiguration()->getMetadataCacheImpl(); - if ($cacheDriver) { - $cacheDriver->deleteAll(); - } - } - /** * Rename duplicate profile names to prevent integrity constraint mysql exceptions. */ @@ -816,7 +822,7 @@ private function addSuffixToProfileNames($profiles) $dbalConnection->executeQuery( 'UPDATE s_import_export_profile SET name = :name WHERE id=:id', - [ 'name' => uniqid($profile['name'] . '_', true) , 'id' => $profile['id'] ] + [ 'name' => uniqid($profile['name'] . '_', true), 'id' => $profile['id'] ] ); } } diff --git a/Commands/SwagImportExport/ExportCommand.php b/Commands/SwagImportExport/ExportCommand.php index b326978d..5fcd3985 100644 --- a/Commands/SwagImportExport/ExportCommand.php +++ b/Commands/SwagImportExport/ExportCommand.php @@ -8,8 +8,8 @@ namespace Shopware\Commands\SwagImportExport; -use Exception; use Shopware\Commands\ShopwareCommand; +use Shopware\Components\Model\ModelManager; use Shopware\CustomModels\ImportExport\Profile; use Shopware\CustomModels\ImportExport\Repository; use Symfony\Component\Console\Input\InputArgument; @@ -20,18 +20,31 @@ class ExportCommand extends ShopwareCommand { + /** @var string */ protected $profile; - /** - * @var Profile - */ + /** @var Profile $profileEntity */ protected $profileEntity; + + /** @var string */ protected $exportVariants; + + /** @var int */ protected $limit; + + /** @var int */ protected $offset; + + /** @var string */ protected $format; + + /** @var string */ protected $filePath; + + /** @var string */ protected $category; + + /** @var int */ protected $sessionId; /** @@ -62,7 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->registerErrorHandler($output); $helper = new CommandHelper( - array( + [ 'profileEntity' => $this->profileEntity, 'filePath' => Shopware()->DocPath() . $this->filePath, 'format' => $this->format, @@ -70,8 +83,8 @@ protected function execute(InputInterface $input, OutputInterface $output) 'limit' => $this->limit, 'offset' => $this->offset, 'username' => 'Commandline', - 'category' => $this->category ? array( $this->category ) : null - ) + 'category' => $this->category ? [$this->category] : null + ] ); $output->writeln('' . sprintf("Using profile: %s.", $this->profile) . ''); @@ -81,13 +94,11 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln('' . sprintf("Using category as filter: %s.", $this->category) . ''); } - $return = $helper->prepareExport(); - $count = $return['count']; + $preparationData = $helper->prepareExport(); + $count = $preparationData['count']; $output->writeln('' . sprintf("Total count: %d.", $count) . ''); - $data = $helper->exportAction(); - $position = $data['position']; - $output->writeln('' . sprintf("Processed: %d.", $position) . ''); + $position = 0; while ($position < $count) { $data = $helper->exportAction(); @@ -98,15 +109,15 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * @param InputInterface $input - * @throws Exception + * @throws \Exception */ protected function prepareExportInputValidation(InputInterface $input) { $this->profile = $input->getOption('profile'); $this->format = $input->getOption('format'); $this->exportVariants = $input->getOption('exportVariants'); - $this->offset = $input->getOption('offset'); - $this->limit = $input->getOption('limit'); + $this->offset = (int) $input->getOption('offset'); + $this->limit = (int) $input->getOption('limit'); $this->filePath = $input->getArgument('filepath'); $this->category = $input->getOption('category'); @@ -116,7 +127,7 @@ protected function prepareExportInputValidation(InputInterface $input) $parts = explode('.', $this->filePath); - // get some service from container (formerly Shopware()->Bootstrap()->getResource()) + /** @var ModelManager $em */ $em = $this->container->get('models'); /** @var Repository $profileRepository */ @@ -126,14 +137,15 @@ protected function prepareExportInputValidation(InputInterface $input) if ($this->profile === null) { foreach ($parts as $part) { $part = strtolower($part); - $this->profileEntity = $profileRepository->findOneBy(array('name' => $part)); + $this->profileEntity = $profileRepository->findOneBy(['name' => $part]); if ($this->profileEntity !== null) { $this->profile = $part; break; } } } else { - $this->profileEntity = $profileRepository->findOneBy(array('name' => $this->profile)); + /** @var Profile profileEntity */ + $this->profileEntity = $profileRepository->findOneBy(['name' => $this->profile]); $this->validateProfiles($input); } @@ -146,8 +158,8 @@ protected function prepareExportInputValidation(InputInterface $input) $this->format = strtolower($this->format); // validate type - if (!in_array($this->format, array('csv', 'xml'))) { - throw new Exception(sprintf('Invalid format: \'%s\'! Valid formats are: CSV and XML.', $this->format)); + if (!in_array($this->format, ['csv', 'xml'])) { + throw new \Exception(sprintf('Invalid format: \'%s\'! Valid formats are: CSV and XML.', $this->format)); } } @@ -157,7 +169,7 @@ protected function prepareExportInputValidation(InputInterface $input) protected function validateProfiles(InputInterface $input) { if (!$this->profileEntity) { - throw new Exception(sprintf('Invalid profile: \'%s\'!', $this->profile)); + throw new \Exception(sprintf('Invalid profile: \'%s\'!', $this->profile)); } if ($this->profileEntity->getType() != 'articles' && $input->getOption('exportVariants')) { diff --git a/Commands/SwagImportExport/ImportCommand.php b/Commands/SwagImportExport/ImportCommand.php index 048c103f..25d19913 100644 --- a/Commands/SwagImportExport/ImportCommand.php +++ b/Commands/SwagImportExport/ImportCommand.php @@ -1,8 +1,15 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Shopware\Commands\SwagImportExport; use Shopware\Commands\ShopwareCommand; +use Shopware\Components\Model\ModelManager; use Shopware\Components\SwagImportExport\Profile\Profile; use Shopware\Components\SwagImportExport\UploadPathProvider; use Shopware\CustomModels\ImportExport\Profile as ProfileEntity; @@ -16,10 +23,19 @@ class ImportCommand extends ShopwareCommand { + /** @var string */ protected $profile; + + /** @var ProfileEntity */ protected $profileEntity; + + /** @var string */ protected $format; + + /** @var string */ protected $filePath; + + /** @var int */ protected $sessionId; /** @@ -46,9 +62,10 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->start($output, $this->profileEntity, $this->filePath, $this->format); - $profilesMapper = array('articles', 'articlesImages'); + $profilesMapper = ['articles', 'articlesImages']; - $uploadPathProvider = new UploadPathProvider(Shopware()->DocPath()); + /** @var UploadPathProvider $uploadPathProvider */ + $uploadPathProvider = $this->container->get('swag_import_export.upload_path_provider'); //loops the unprocessed data $pathInfo = pathinfo($this->filePath); @@ -80,29 +97,28 @@ protected function execute(InputInterface $input, OutputInterface $output) protected function start(OutputInterface $output, $profileModel, $file, $format) { $helper = new CommandHelper( - array( + [ 'profileEntity' => $profileModel, 'filePath' => $file, 'format' => $format, 'username' => 'Commandline' - ) + ] ); $output->writeln('' . sprintf("Using profile: %s.", $profileModel->getName()) . ''); $output->writeln('' . sprintf("Using format: %s.", $format) . ''); $output->writeln('' . sprintf("Using file: %s.", $file) . ''); - $return = $helper->prepareImport(); - $count = $return['count']; + $preparationData = $helper->prepareImport(); + $count = $preparationData['count']; $output->writeln('' . sprintf("Total count: %d.", $count) . ''); - $return = $helper->importAction(); - $position = $return['data']['position']; - $output->writeln('' . sprintf("Processed: %d.", $position) . ''); + $position = 0; while ($position < $count) { - $return = $helper->importAction(); - $position = $return['data']['position']; + $data = $helper->importAction(); + $this->container->get('models')->clear(); + $position = $data['data']['position']; $output->writeln('' . sprintf("Processed: %d.", $position) . ''); } } @@ -119,24 +135,24 @@ protected function prepareImportInputValidation(InputInterface $input) $parts = explode('.', $this->filePath); - // get some service from container (formerly Shopware()->Bootstrap()->getResource()) + /** @var ModelManager $em */ $em = $this->container->get('models'); /** @var Repository $profileRepository */ - $profileRepository = $em->getRepository('Shopware\CustomModels\ImportExport\Profile'); + $profileRepository = $em->getRepository(ProfileEntity::class); // if no profile is specified try to find it from the filename if ($this->profile === null) { foreach ($parts as $part) { $part = strtolower($part); - $this->profileEntity = $profileRepository->findOneBy(array('name' => $part)); + $this->profileEntity = $profileRepository->findOneBy(['name' => $part]); if ($this->profileEntity !== null) { $this->profile = $part; break; } } } else { - $this->profileEntity = $profileRepository->findOneBy(array('name' => $this->profile)); + $this->profileEntity = $profileRepository->findOneBy(['name' => $this->profile]); } // validate profile @@ -153,7 +169,7 @@ protected function prepareImportInputValidation(InputInterface $input) $this->format = strtolower($this->format); // validate type - if (!in_array($this->format, array('csv', 'xml'))) { + if (!in_array($this->format, ['csv', 'xml'])) { throw new \Exception(sprintf('Invalid format: \'%s\'! Valid formats are: CSV and XML.', $this->format)); } diff --git a/Components/SwagImportExport/DataManagers/ArticlePriceDataManager.php b/Components/SwagImportExport/DataManagers/ArticlePriceDataManager.php index 108c1a4f..3c3891e2 100644 --- a/Components/SwagImportExport/DataManagers/ArticlePriceDataManager.php +++ b/Components/SwagImportExport/DataManagers/ArticlePriceDataManager.php @@ -18,6 +18,7 @@ class ArticlePriceDataManager private $defaultFields = array( 'priceGroup', 'from', + 'to', 'percent' ); @@ -41,6 +42,9 @@ public function setDefaultFields($record) case 'from': $record[$key] = 1; break; + case 'to': + $record[$key] = 'beliebig'; + break; case 'percent': $record[$key] = 0.0; break; diff --git a/Components/SwagImportExport/DbAdapters/AddressDbAdapter.php b/Components/SwagImportExport/DbAdapters/AddressDbAdapter.php new file mode 100644 index 00000000..7b788652 --- /dev/null +++ b/Components/SwagImportExport/DbAdapters/AddressDbAdapter.php @@ -0,0 +1,435 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Shopware\Components\SwagImportExport\DbAdapters; + +use Doctrine\DBAL\Connection; +use Shopware\Components\Model\ModelManager; +use Shopware\Components\SwagImportExport\Exception\AdapterException; +use Shopware\Components\SwagImportExport\Utils\SnippetsHelper; +use Shopware\Components\SwagImportExport\Validators\AddressValidator; +use Shopware\Models\Attribute\CustomerAddress; +use Shopware\Models\Country\Country; +use Shopware\Models\Country\State; +use Shopware\Models\Customer\Address; +use Shopware\Models\Customer\Customer; + +class AddressDbAdapter implements DataDbAdapter +{ + /** + * @var ModelManager + */ + private $modelManager; + + /** + * @var AddressValidator + */ + private $addressValidator; + + /** + * @var array + */ + private $logMessages; + + /** + * @var string + */ + private $logState; + + public function __construct() + { + $this->modelManager = Shopware()->Container()->get('models'); + $this->addressValidator = new AddressValidator(); + } + + /** + * @inheritdoc + */ + public function read($ids, $columns) + { + $queryBuilder = $this->modelManager->createQueryBuilder(); + $queryBuilder->select($columns) + ->from(Address::class, 'address') + ->leftJoin('address.customer', 'customer') + ->leftJoin('address.state', 'state') + ->leftJoin('address.country', 'country') + ->leftJoin('address.attribute', 'attribute') + ->where('address.id IN (:ids)') + ->setParameter('ids', $ids, Connection::PARAM_INT_ARRAY); + + $addresses = $queryBuilder->getQuery()->getArrayResult(); + + return [ + 'address' => $addresses + ]; + } + + /** + * @inheritdoc + */ + public function readRecordIds($start = 0, $limit = 0, $filter = '') + { + $builder = $this->modelManager->createQueryBuilder(); + $builder->select('address.id') + ->from(Address::class, 'address') + ->orderBy('address.id'); + + if ($start > 0) { + $builder->setFirstResult($start); + } + + if ($limit > 0) { + $builder->setMaxResults($limit); + } + + $ids = $builder->getQuery()->getArrayResult(); + return array_column($ids, 'id'); + } + + /** + * @inheritdoc + */ + public function getDefaultColumns() + { + $defaultColumns = [ + 'address.id as id', + 'address.company as company', + 'address.department as department', + 'address.salutation as salutation', + 'address.title as title', + 'address.firstname as firstname', + 'address.lastname as lastname', + 'address.street as street', + 'address.zipcode as zipcode', + 'address.city as city', + 'address.vatId as vatId', + 'address.phone as phone', + 'address.additionalAddressLine1 as additional_address_line1', + 'address.additionalAddressLine2 as additional_address_line2', + 'customer.id as userID', + 'customer.email as email', + 'customer.number as customernumber', + 'country.id as countryID', + 'state.id as stateID' + ]; + + return array_merge($defaultColumns, $this->getAttributeColumns()); + } + + /** + * @inheritdoc + */ + public function getSections() + { + return []; + } + + /** + * @inheritdoc + */ + public function getColumns($section = []) + { + return $this->getDefaultColumns(); + } + + /** + * @inheritdoc + */ + public function write($records) + { + if (empty($records['address'])) { + throw new \Exception(SnippetsHelper::getNamespace()->get('adapters/address/no_records', 'Could not find address records.')); + } + + try { + foreach ($records['address'] as $addressRecord) { + $updateAddress = false; + + $addressModel = $this->getAddressModel($addressRecord); + if ($addressModel->getId()) { + $updateAddress = true; + } + + $addressRecord = $this->addressValidator->filterEmptyString($addressRecord); + $this->addressValidator->checkRequiredFields($addressRecord, $updateAddress); + + $addressRecord = $this->setCustomer($addressModel, $addressRecord); + $addressRecord = $this->setState($addressModel, $addressRecord); + + if (!$updateAddress && $addressRecord['id']) { + $addressModel = $this->createAddressWithId($addressRecord); + } + + $addressModel->fromArray($addressRecord); + + + $this->setCountry($addressModel, $addressRecord); + + $attributeModel = $this->getAttributeModel($addressRecord, $addressModel); + $addressModel->setAttribute($attributeModel); + + $this->modelManager->persist($addressModel); + } + $this->modelManager->flush(); + } catch (AdapterException $e) { + $this->saveErrorMessage($e->getMessage()); + } + } + + /** + * @inheritdoc + */ + public function getUnprocessedData() + { + return []; + } + + /** + * @param $logMessages + */ + public function setLogMessages($logMessages) + { + $this->logMessages[] = $logMessages; + } + + /** + * @inheritdoc + */ + public function getLogMessages() + { + return $this->logMessages; + } + + /** + * @inheritdoc + */ + public function getLogState() + { + return $this->logState; + } + + /** + * @param array $addressRecord + * @return null|Customer + */ + private function findCustomerByEmailAndNumber(array $addressRecord) + { + $customerRepository = $this->modelManager->getRepository(Customer::class); + + return $customerRepository->findOneBy([ + 'number' => $addressRecord['customernumber'], + 'email' => $addressRecord['email'] + ]); + } + + /** + * @param array $addressRecord + * @return null|Address + */ + private function getAddressModel(array $addressRecord) + { + $addressModel = null; + + if ($addressRecord['id']) { + $addressModel = $this->modelManager->find(Address::class, $addressRecord['id']); + } + + if (!$addressModel) { + $addressModel = new Address(); + } + return $addressModel; + } + + /** + * @param array $addressRecord + * @return null|State + */ + private function findStateById(array $addressRecord) + { + if ($addressRecord['stateID']) { + return $this->modelManager->find(State::class, $addressRecord['stateID']); + } + return null; + } + + /** + * @param array $addressRecord + * @return Customer + */ + private function getCustomer(array $addressRecord) + { + $customer = null; + if ($addressRecord['userID']) { + $customer = $this->modelManager->find(Customer::class, $addressRecord['userID']); + } + + if (null === $customer) { + $customer = $this->findCustomerByEmailAndNumber($addressRecord); + } + return $customer; + } + + /** + * @return array + */ + private function getAttributeColumns() + { + $classMetadata = $this->modelManager->getClassMetadata(CustomerAddress::class); + $fieldNames = $classMetadata->getFieldNames(); + + $attributeSelections = []; + foreach ($fieldNames as $fieldName) { + $attributeSelections[] = 'attribute.' . $fieldName . ' as attribute' . ucfirst($fieldName); + } + + return $attributeSelections; + } + + /** + * @param array $addressRecord + * @param Address $addressModel + * @return CustomerAddress + */ + private function getAttributeModel(array $addressRecord, Address $addressModel) + { + $attribute = []; + foreach ($addressRecord as $field => $value) { + if (false === strpos($field, 'attribute')) { + continue; + } + + $modelFieldName = str_replace('attribute', '', $field); + $modelFieldName = lcfirst($modelFieldName); + $attribute[$modelFieldName] = $value; + } + + $attributeModel = new CustomerAddress(); + if ($addressModel->getAttribute()) { + $attributeModel = $addressModel->getAttribute(); + } + + return $attributeModel->fromArray($attribute); + } + + /** + * @param string $message + * @throws \Exception + */ + private function saveErrorMessage($message) + { + $errorMode = Shopware()->Config()->get('SwagImportExportErrorMode'); + if ($errorMode === false) { + throw new \Exception($message); + } + + $this->setLogMessages($message); + $this->setLogState('true'); + } + + /** + * @param string $logState + */ + private function setLogState($logState) + { + $this->logState = $logState; + } + + /** + * @param Address $addressModel + * @param array $addressRecord + * @return Address + */ + protected function setCountry(Address $addressModel, array $addressRecord) + { + if (!$addressModel->getCountry() && $addressRecord['countryID']) { + $addressModel->setCountry($this->modelManager->find(Country::class, $addressRecord['countryID'])); + return $addressModel; + } + + if ($addressModel->getCountry()->getId() !== $addressRecord['countryID'] && $addressRecord['countryID'] > 0) { + $addressModel->setCountry($this->modelManager->find(Country::class, $addressRecord['countryID'])); + } + return $addressModel; + } + + /** + * @param array $addressRecord + * @return null|Address + */ + private function createAddressWithId(array $addressRecord) + { + $connection = $this->modelManager->getConnection(); + $connection->executeQuery( + 'INSERT INTO s_user_addresses + (id, user_id, country_id, zipcode, firstname, lastname) + VALUES + (:id, :userID, :countryID, :zipcode, :firstname, :lastname) + ', $addressRecord); + + $addressId = $connection->lastInsertId(); + return $this->modelManager->find(Address::class, $addressId); + } + + /** + * @param Address $addressModel + * @param array $addressRecord + * @return array + * @throws AdapterException + */ + private function setCustomer(Address $addressModel, array $addressRecord) + { + $errorMessage = SnippetsHelper::getNamespace()->get( + 'adapters/address/customer_not_found', + 'Could not find customer. Email: %s, Customernumber: %s, userID: %s' + ); + + if (!$addressModel->getCustomer()) { + $customer = $this->getCustomer($addressRecord); + if (!$customer) { + throw new AdapterException( + sprintf($errorMessage, $addressRecord['email'], $addressRecord['customernumber'], $addressRecord['userID']) + ); + } + + $addressRecord['userID'] = $customer->getId(); + $addressModel->setCustomer($customer); + } + + return $addressRecord; + } + + /** + * @param Address $addressModel + * @param array $addressRecord + * @return array|void + * @throws AdapterException + */ + private function setState(Address $addressModel, array $addressRecord) + { + if (!$addressRecord['stateID']) { + return $addressRecord; + } + + $errorMessage = SnippetsHelper::getNamespace()->get( + 'adapters/address/state_not_found', + 'Could not find state with stateID: %s' + ); + + $state = $this->findStateById($addressRecord); + if (!$state) { + throw new AdapterException( + sprintf($errorMessage, $addressRecord['stateID']) + ); + } + + $addressModel->setState($state); + $addressRecord['stateID'] = $state->getId(); + + return $addressRecord; + } +} diff --git a/Components/SwagImportExport/DbAdapters/Articles/PriceWriter.php b/Components/SwagImportExport/DbAdapters/Articles/PriceWriter.php index b0ba026b..c34ecbb3 100644 --- a/Components/SwagImportExport/DbAdapters/Articles/PriceWriter.php +++ b/Components/SwagImportExport/DbAdapters/Articles/PriceWriter.php @@ -14,6 +14,7 @@ use Shopware\Components\SwagImportExport\Utils\SnippetsHelper; use Shopware\Components\SwagImportExport\Validators\Articles\PriceValidator; use Shopware\Components\SwagImportExport\DataManagers\Articles\PriceDataManager; +use Shopware\Models\Article\Price; class PriceWriter { @@ -92,7 +93,7 @@ public function write($articleId, $articleDetailId, $prices) $price['articleDetailsId'] = $articleDetailId; $price['customerGroupKey'] = $price['priceGroup']; $price = $this->calculatePrice($price, $newPrice, $tax); - $builder = $this->dbalHelper->getQueryBuilderForEntity($price, 'Shopware\Models\Article\Price', $priceId); + $builder = $this->dbalHelper->getQueryBuilderForEntity($price, Price::class, $priceId); $builder->execute(); } } diff --git a/Components/SwagImportExport/DbAdapters/Articles/PropertyWriter.php b/Components/SwagImportExport/DbAdapters/Articles/PropertyWriter.php index acc09655..aa9144cf 100644 --- a/Components/SwagImportExport/DbAdapters/Articles/PropertyWriter.php +++ b/Components/SwagImportExport/DbAdapters/Articles/PropertyWriter.php @@ -132,10 +132,6 @@ public function writeUpdateCreatePropertyGroupsFilterAndValues($articleId, $orde $optionRelationInsertStatements[] = "($optionId, $filterGroupId)"; $valueRelationInsertStatements[] = "($valueId, $articleId)"; continue; - } else { - $message = $this->snippetsHelper->getNamespace() - ->get('adapters/articles/property_id_or_name_required', 'Article %s requires name or id for property value'); - throw new AdapterException(sprintf($message, $orderNumber)); } } diff --git a/Components/SwagImportExport/DbAdapters/ArticlesDbAdapter.php b/Components/SwagImportExport/DbAdapters/ArticlesDbAdapter.php index d37698e1..e0700eac 100644 --- a/Components/SwagImportExport/DbAdapters/ArticlesDbAdapter.php +++ b/Components/SwagImportExport/DbAdapters/ArticlesDbAdapter.php @@ -828,15 +828,7 @@ public function getArticleAttributes() $stmt = $this->db->query("SHOW COLUMNS FROM `s_articles_attributes`"); $columns = $stmt->fetchAll(); - $attributes = []; - foreach ($columns as $column) { - if ($column['Field'] !== 'id' - && $column['Field'] !== 'articleID' - && $column['Field'] !== 'articledetailsID' - ) { - $attributes[] = $column['Field']; - } - } + $attributes = $this->filterAttributeColumns($columns); $attributesSelect = []; if ($attributes) { @@ -969,6 +961,8 @@ public function getPriceColumns() 'prices.price as price', 'prices.pseudoPrice as pseudoPrice', 'prices.customerGroupKey as priceGroup', + 'prices.from', + 'prices.to' ]; } @@ -1564,4 +1558,22 @@ private function underscoreToCamelCase($underscoreString) { return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $underscoreString)))); } + + /** + * @param array $columns + * @return array + */ + private function filterAttributeColumns(array $columns) + { + $attributes = []; + foreach ($columns as $column) { + if ($column['Field'] !== 'id' + && $column['Field'] !== 'articleID' + && $column['Field'] !== 'articledetailsID' + ) { + $attributes[] = $column['Field']; + } + } + return $attributes; + } } diff --git a/Components/SwagImportExport/DbAdapters/ArticlesPricesDbAdapter.php b/Components/SwagImportExport/DbAdapters/ArticlesPricesDbAdapter.php index 87c5a806..cfe8de5b 100644 --- a/Components/SwagImportExport/DbAdapters/ArticlesPricesDbAdapter.php +++ b/Components/SwagImportExport/DbAdapters/ArticlesPricesDbAdapter.php @@ -14,48 +14,38 @@ use Shopware\Components\SwagImportExport\Exception\AdapterException; use Shopware\Components\SwagImportExport\Validators\ArticlePriceValidator; use Shopware\Components\SwagImportExport\DataManagers\ArticlePriceDataManager; -use Shopware\Models\Article\Detail as ArticleDetail; +use Shopware\Models\Article\Article; +use Shopware\Models\Article\Detail; use Shopware\Models\Article\Price as ArticlePrice; -use Shopware\Models\Article\Repository as ArticleRepository; use Shopware\Models\Customer\Group as CustomerGroup; -use Shopware\Models\Customer\Repository as CustomerRepository; class ArticlesPricesDbAdapter implements DataDbAdapter { - /** - * @var ModelManager - */ + /** @var ModelManager */ protected $manager; - protected $detailRepository; - protected $priceRepository; - protected $groupRepository; - - /** - * @var array - */ + /** @var array */ protected $logMessages; - /** - * @var string - */ + /** @var string */ protected $logState; - /** - * @var array - */ + /** @var array */ protected $unprocessedData; - /** - * @var ArticlePriceValidator - */ + /** @var ArticlePriceValidator */ protected $validator; - /** - * @var ArticlePriceDataManager - */ + /** @var ArticlePriceDataManager */ protected $dataManager; + public function __construct() + { + $this->dataManager = new ArticlePriceDataManager(); + $this->validator = new ArticlePriceValidator(); + $this->manager = Shopware()->Models(); + } + /** * @param $start * @param $limit @@ -64,12 +54,10 @@ class ArticlesPricesDbAdapter implements DataDbAdapter */ public function readRecordIds($start, $limit, $filter) { - $manager = $this->getManager(); - - $builder = $manager->createQueryBuilder(); + $builder = $this->manager->createQueryBuilder(); $builder->select('price.id') - ->from('Shopware\Models\Article\Article', 'article') + ->from(Article::class, 'article') ->leftJoin('article.details', 'detail') ->leftJoin('detail.prices', 'price') ->andWhere('price.price > 0') @@ -89,7 +77,7 @@ public function readRecordIds($start, $limit, $filter) $records = $builder->getQuery()->getResult(); - $result = array(); + $result = []; if ($records) { foreach ($records as $value) { $result[] = $value['id']; @@ -119,7 +107,7 @@ public function read($ids, $columns) throw new \Exception($message); } - $columns = array_merge($columns, array('customerGroup.taxInput as taxInput', 'articleTax.tax as tax')); + $columns = array_merge($columns, ['customerGroup.taxInput as taxInput', 'articleTax.tax as tax']); $builder = $this->getBuilder($columns, $ids); @@ -148,7 +136,7 @@ public function read($ids, $columns) */ public function getDefaultColumns() { - return array( + return [ 'detail.number as orderNumber', 'price.id', 'price.articleId', @@ -162,10 +150,8 @@ public function getDefaultColumns() 'article.name as name', 'detail.additionalText as additionalText', 'detail.purchasePrice as purchasePrice', - 'supplier.name as supplierName', -// 'articleTax.id as taxId', -// 'articleTax.tax as tax', - ); + 'supplier.name as supplierName' + ]; } /** @@ -197,30 +183,31 @@ public function write($records) $records = Shopware()->Events()->filter( 'Shopware_Components_SwagImportExport_DbAdapters_ArticlesPricesDbAdapter_Write', $records, - array('subject' => $this) + ['subject' => $this] ); - $manager = $this->getManager(); - $validator = $this->getValidator(); - $dataManager = $this->getDataManager(); + $customerGroupRepository = $this->manager->getRepository(CustomerGroup::class); + $detailRepository = $this->manager->getRepository(Detail::class); + $flushCounter = 0; foreach ($records['default'] as $record) { try { - $record = $validator->filterEmptyString($record); - $validator->checkRequiredFields($record); - $record = $dataManager->setDefaultFields($record); - $validator->validate($record, ArticlePriceValidator::$mapper); + $flushCounter++; + $record = $this->validator->filterEmptyString($record); + $this->validator->checkRequiredFields($record); + $record = $this->dataManager->setDefaultFields($record); + $this->validator->validate($record, ArticlePriceValidator::$mapper); /** @var CustomerGroup $customerGroup */ - $customerGroup = $this->getGroupRepository()->findOneBy(array("key" => $record['priceGroup'])); + $customerGroup = $customerGroupRepository->findOneBy(["key" => $record['priceGroup']]); if (!$customerGroup) { $message = SnippetsHelper::getNamespace() ->get('adapters/articlesPrices/price_group_not_found', 'Price group %s was not found'); throw new AdapterException(sprintf($message, $record['priceGroup'])); } - /** @var ArticleDetail $articleDetail */ - $articleDetail = $this->getDetailRepository()->findOneBy(array("number" => $record['orderNumber'])); + /** @var Detail $articleDetail */ + $articleDetail = $detailRepository->findOneBy(["number" => $record['orderNumber']]); if (!$articleDetail) { $message = SnippetsHelper::getNamespace() ->get('adapters/article_number_not_found', 'Article with order number %s does not exists'); @@ -255,43 +242,19 @@ public function write($records) $record['pseudoPrice'] = floatval(str_replace(",", ".", $record['pseudoPrice'])); } + if (isset($record['purchasePrice'])) { + $record['purchasePrice'] = floatval(str_replace(",", ".", $record['purchasePrice'])); + } + if (isset($record['percent'])) { $record['percent'] = floatval(str_replace(",", ".", $record['percent'])); } - - $dql = 'DELETE FROM Shopware\Models\Article\Price price - WHERE price.customerGroup = :customerGroup - AND price.articleDetailsId = :detailId - AND price.from = :fromValue'; - - $query = $manager->createQuery($dql); - - $query->setParameters( - array( - 'customerGroup' => $record['priceGroup'], - 'detailId' => $articleDetail->getId(), - 'fromValue' => $record['from'], - ) - ); - $query->execute(); - + // removes price with same from value from database + $this->updateArticleFromPrice($record, $articleDetail->getId()); + // checks if price belongs to graduation price if ($record['from'] != 1) { - $dql = 'UPDATE Shopware\Models\Article\Price price SET price.to = :toValue - WHERE price.customerGroup = :customerGroup - AND price.articleDetailsId = :detailId - AND price.articleId = :articleId AND price.to - LIKE \'beliebig\''; - $query = $manager->createQuery($dql); - - $query->setParameters( - array( - 'toValue' => $record['from'] - 1, - 'customerGroup' => $record['priceGroup'], - 'detailId' => $articleDetail->getId(), - 'articleId' => $articleDetail->getArticle()->getId(), - ) - ); - $query->execute(); + // updates graduation to value with from value - 1 + $this->updateArticleToPrice($record, $articleDetail->getId(), $articleDetail->getArticleId()); } // remove tax @@ -306,21 +269,32 @@ public function write($records) $price->setDetail($articleDetail); $price->setCustomerGroup($customerGroup); $price->setFrom($record['from']); - $price->setTo('beliebig'); + $price->setTo($record['to']); $price->setPrice($record['price']); + if (isset($record['pseudoPrice'])) { $price->setPseudoPrice($record['pseudoPrice']); } + + if (isset($record['purchasePrice'])) { + $articleDetail->setPurchasePrice($record['purchasePrice']); + } + $price->setPercent($record['percent']); - $this->getManager()->persist($price); + $this->manager->persist($price); - $this->getManager()->flush(); + // perform entitymanager flush every 20th record to improve performance + if (($flushCounter % 20) === 0) { + $this->manager->flush(); + } } catch (AdapterException $e) { $message = $e->getMessage(); $this->saveMessage($message); } } + // perform final db flush at the end + $this->manager->flush(); } /** @@ -328,9 +302,9 @@ public function write($records) */ public function getSections() { - return array( - array('id' => 'default', 'name' => 'default ') - ); + return [ + ['id' => 'default', 'name' => 'default '] + ]; } /** @@ -348,46 +322,6 @@ public function getColumns($section) return false; } - /** - * Returns article detail repository - * - * @return ArticleRepository - */ - public function getDetailRepository() - { - if ($this->detailRepository === null) { - $this->detailRepository = $this->getManager()->getRepository('Shopware\Models\Article\Detail'); - } - - return $this->detailRepository; - } - - /** - * Returns article detail repository - * - * @return CustomerRepository - */ - public function getGroupRepository() - { - if ($this->groupRepository === null) { - $this->groupRepository = $this->getManager()->getRepository('Shopware\Models\Customer\Group'); - } - - return $this->groupRepository; - } - - /** - * @return ModelManager - */ - public function getManager() - { - if ($this->manager === null) { - $this->manager = Shopware()->Models(); - } - - return $this->manager; - } - /** * @param $message * @throws \Exception @@ -443,9 +377,10 @@ public function setLogState($logState) */ public function getBuilder($columns, $ids) { - $builder = $this->getManager()->createQueryBuilder(); + $builder = $this->manager->createQueryBuilder(); + $builder->select($columns) - ->from('Shopware\Models\Article\Article', 'article') + ->from(Article::class, 'article') ->leftJoin('article.details', 'detail') ->leftJoin('article.tax', 'articleTax') ->leftJoin('article.supplier', 'supplier') @@ -457,27 +392,43 @@ public function getBuilder($columns, $ids) return $builder; } - /** - * @return ArticlePriceValidator - */ - public function getValidator() + private function updateArticleFromPrice($record, $articleDetailId) { - if ($this->validator === null) { - $this->validator = new ArticlePriceValidator(); - } - - return $this->validator; + $dql = 'DELETE FROM Shopware\Models\Article\Price price + WHERE price.customerGroup = :customerGroup + AND price.articleDetailsId = :detailId + AND price.from = :fromValue'; + + $query = $this->manager->createQuery($dql); + + $query->setParameters( + [ + 'customerGroup' => $record['priceGroup'], + 'detailId' => $articleDetailId, + 'fromValue' => $record['from'], + ] + ); + $query->execute(); } - /** - * @return ArticlePriceDataManager - */ - public function getDataManager() + private function updateArticleToPrice($record, $articleDetailId, $articleId) { - if ($this->dataManager === null) { - $this->dataManager = new ArticlePriceDataManager(); - } - - return $this->dataManager; + $dql = "UPDATE Shopware\Models\Article\Price price SET price.to = :toValue + WHERE price.customerGroup = :customerGroup + AND price.articleDetailsId = :detailId + AND price.articleId = :articleId + AND price.to LIKE 'beliebig'"; + + $query = $this->manager->createQuery($dql); + + $query->setParameters( + [ + 'toValue' => $record['from'] - 1, + 'customerGroup' => $record['priceGroup'], + 'detailId' => $articleDetailId, + 'articleId' => $articleId, + ] + ); + $query->execute(); } } diff --git a/Components/SwagImportExport/DbAdapters/DataDbAdapter.php b/Components/SwagImportExport/DbAdapters/DataDbAdapter.php index ad646e03..3616b336 100644 --- a/Components/SwagImportExport/DbAdapters/DataDbAdapter.php +++ b/Components/SwagImportExport/DbAdapters/DataDbAdapter.php @@ -21,22 +21,81 @@ interface DataDbAdapter const CUSTOMER_ADAPTER = 'customers'; const NEWSLETTER_RECIPIENTS_ADAPTER = 'newsletter'; const TRANSLATION_ADAPTER = 'translations'; + const ADDRESS_ADAPTER = 'addresses'; + /** + * Reads all records with the given ids and selects the passed columns. + * + * @param array $ids + * @param array $columns + * @return array + */ public function read($ids, $columns); + /** + * Returns all ids for the given export with the given parameters. + * + * @param int $start + * @param int $limit + * @param mixed $filter + * @return array + */ public function readRecordIds($start, $limit, $filter); + /** + * Returns the default column. + * @see DataDbAdapter::getColumns() + * + * @return array + */ public function getDefaultColumns(); + /** + * Returns all iteration nodes, i.e. for articles it configuratiors, similar, ... + * + * @return array + */ public function getSections(); - public function getColumns($columns); + /** + * Returns all column names. + * @example: + * [ + * 'address.id as id', + * 'address.firstname as firstname' + * ] + * + * @param string $section + * @return array + */ + public function getColumns($section); + /** + * Creates, updates and validates the imported records. + * + * @param array $records + */ public function write($records); + /** + * Returns unprocessed data. This will be used every time if an import wants to create data which relies on created data. + * For instance article images, similar or accessory articles. + * + * @return array + */ public function getUnprocessedData(); + /** + * Returns all log messages as an array. + * + * @return array + */ public function getLogMessages(); + /** + * Returns true if log messages are available. + * + * @return boolean + */ public function getLogState(); } diff --git a/Components/SwagImportExport/DbAdapters/NewsletterDbAdapter.php b/Components/SwagImportExport/DbAdapters/NewsletterDbAdapter.php index ebe8ef79..fd99cb22 100644 --- a/Components/SwagImportExport/DbAdapters/NewsletterDbAdapter.php +++ b/Components/SwagImportExport/DbAdapters/NewsletterDbAdapter.php @@ -13,6 +13,8 @@ use Shopware\Components\Model\ModelManager; use Shopware\Components\Model\QueryBuilder; use Shopware\Components\SwagImportExport\DataType\NewsletterDataType; +use Shopware\Models\Customer\Customer; +use Shopware\Models\Customer\Repository; use Shopware\Models\Newsletter\Address; use Shopware\Models\Newsletter\Group; use Shopware\Models\Newsletter\ContactData; @@ -150,7 +152,7 @@ public function read($ids, $columns) { $builder = $this->getBuilder($columns, $ids); - $result['default'] = $builder->getQuery()->getResult(); + $result['default'] = $builder->getQuery()->getArrayResult(); return $result; } @@ -166,8 +168,8 @@ public function readRecordIds($start, $limit, $filter) $builder = $this->manager->createQueryBuilder(); $builder->select('na.id') - ->from(Address::class, 'na') - ->orderBy('na.id', 'ASC'); + ->from(Address::class, 'na') + ->orderBy('na.id', 'ASC'); if (!empty($filter)) { $builder->addFilter($filter); @@ -181,7 +183,7 @@ public function readRecordIds($start, $limit, $filter) $builder->setMaxResults($limit); } - $records = $builder->getQuery()->getResult(); + $records = $builder->getQuery()->getArrayResult(); $result = []; if ($records) { @@ -213,6 +215,8 @@ public function write($records) ); $defaultValues = $this->getDefaultValues(); + /** @var Repository $customerRepository */ + $customerRepository = $this->manager->getRepository(Customer::class); /** @var EntityRepository $addressRepository */ $addressRepository = $this->manager->getRepository(Address::class); /** @var EntityRepository $groupRepository */ @@ -227,15 +231,27 @@ public function write($records) $newsletterData = $this->validator->filterEmptyString($newsletterData); $this->validator->checkRequiredFields($newsletterData); - $recipient = $addressRepository->findOneBy(['email' => $newsletterData['email']]); + // no groupname set and is customer - we check if this recipient is already registered + if (empty($newsletterData['groupName']) && !empty($newsletterData['userID'])) { + $customer = $customerRepository->find($newsletterData['userID']); - if ($recipient instanceof Address && empty($newsletterData['groupName'])) { + if (!$customer instanceof Customer) { + continue; + } + $recipient = $addressRepository->findOneBy(['email' => $newsletterData['email'], 'groupId' => 0, 'isCustomer' => true]); + + if (!$recipient instanceof Address) { + $recipient = new Address(); + $recipient->setEmail($newsletterData['email']); + $recipient->setIsCustomer(true); + $this->manager->persist($recipient); + $this->manager->flush($recipient); + } continue; } - if (!$recipient instanceof Address) { + if (empty($newsletterData['groupName'])) { $newsletterData = $this->dataManager->setDefaultFieldsForCreate($newsletterData, $defaultValues); - $recipient = new Address(); } $this->validator->validate($newsletterData, NewsletterDataType::$mapper); @@ -250,10 +266,14 @@ public function write($records) $this->manager->persist($group); $this->manager->flush($group); } - $newsletterData['groupId'] = $group->getId(); } + $recipient = $addressRepository->findOneBy(['email' => $newsletterData['email'], 'groupId' => $newsletterData['groupId']]); + + if (!$recipient instanceof Address) { + $recipient = new Address(); + } // save newsletter address $newsletterAddress = $this->prepareNewsletterAddress($newsletterData); $recipient->fromArray($newsletterAddress); @@ -269,6 +289,7 @@ public function write($records) } $contactData->fromArray($newsletterData); } + if (($count % 20) === 0) { $this->manager->flush(); } @@ -361,7 +382,7 @@ public function getSections() ['id' => 'default', 'name' => 'default '] ]; } - + /** * @param string $section * @return mixed @@ -369,7 +390,7 @@ public function getSections() public function getColumns($section) { $method = 'get' . ucfirst($section) . 'Columns'; - + if (method_exists($this, $method)) { return $this->{$method}(); } @@ -387,13 +408,13 @@ public function getBuilder($columns, $ids) $builder = $this->manager->createQueryBuilder(); $builder->select($columns) - ->from(Address::class, 'na') - ->leftJoin('na.newsletterGroup', 'ng') - ->leftJoin(ContactData::class, 'cd', Join::WITH, 'na.email = cd.email') - ->leftJoin('na.customer', 'c') - ->leftJoin('c.billing', 'cb') - ->where('na.id IN (:ids)') - ->setParameter('ids', $ids); + ->from(Address::class, 'na') + ->leftJoin('na.newsletterGroup', 'ng') + ->leftJoin(ContactData::class, 'cd', Join::WITH, 'na.email = cd.email') + ->leftJoin('na.customer', 'c', JOIN::WITH, 'na.isCustomer = 1') + ->leftJoin('c.billing', 'cb') + ->where('na.id IN (:ids)') + ->setParameter('ids', $ids); return $builder; } diff --git a/Components/SwagImportExport/Factories/DataFactory.php b/Components/SwagImportExport/Factories/DataFactory.php index f34c321e..448b88d6 100644 --- a/Components/SwagImportExport/Factories/DataFactory.php +++ b/Components/SwagImportExport/Factories/DataFactory.php @@ -9,14 +9,32 @@ namespace Shopware\Components\SwagImportExport\Factories; use Doctrine\ORM\EntityRepository; +use Shopware\Components\Model\ModelManager; use Shopware\Components\SwagImportExport\DataIO; +use Shopware\Components\SwagImportExport\DataManagers\Articles\ArticleDataManager; +use Shopware\Components\SwagImportExport\DataManagers\CategoriesDataManager; +use Shopware\Components\SwagImportExport\DataManagers\CustomerDataManager; +use Shopware\Components\SwagImportExport\DataManagers\NewsletterDataManager; +use Shopware\Components\SwagImportExport\DbAdapters\AddressDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesImagesDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesInStockDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesPricesDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesTranslationsDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\CategoriesDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\CustomerDbAdapter; use Shopware\Components\SwagImportExport\DbAdapters\DataDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\MainOrdersDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\NewsletterDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\OrdersDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\TranslationsDbAdapter; use Shopware\Components\SwagImportExport\DbalHelper; use Shopware\Components\SwagImportExport\Session\Session; use Shopware\Components\SwagImportExport\Logger\Logger; use Shopware\Components\SwagImportExport\Utils\DataColumnOptions; use Shopware\Components\SwagImportExport\Utils\DataLimit; use Shopware\Components\SwagImportExport\Utils\DataFilter; +use Shopware\Components\SwagImportExport\Validators\AddressValidator; use Shopware\CustomModels\ImportExport\Session as SessionEntity; class DataFactory extends \Enlight_Class implements \Enlight_Hook @@ -32,26 +50,23 @@ class DataFactory extends \Enlight_Class implements \Enlight_Hook */ public function createDataIO(DataDbAdapter $dbAdapter, $dataSession, Logger $logger) { - $uploadPathProvider = Shopware()->Container()->get('swag_import_export.upload_path_provider'); + $uploadPathProvider = Shopware()->Container()->get('swag_import_export.upload_path_provider'); return new DataIO($dbAdapter, $dataSession, $logger, $uploadPathProvider); } /** * Returns the necessary adapter - * + * * @param string $adapterType * @return DataDbAdapter dbAdapter * @throws \Exception */ public function createDbAdapter($adapterType) { - $event = Shopware()->Events()->notifyUntil( - 'Shopware_Components_SwagImportExport_Factories_CreateDbAdapter', - ['subject' => $this, 'adapterType' => $adapterType] - ); - + $event = $this->fireCreateFactoryEvent($adapterType); if ($event && $event instanceof \Enlight_Event_EventArgs - && $event->getReturn() instanceof DataDbAdapter) { + && $event->getReturn() instanceof DataDbAdapter + ) { return $event->getReturn(); } @@ -78,10 +93,24 @@ public function createDbAdapter($adapterType) return $this->createNewsletterDbAdapter(); case DataDbAdapter::TRANSLATION_ADAPTER: return $this->createTranslationsDbAdapter(); - default: throw new \Exception('Db adapter type is not valid'); + case DataDbAdapter::ADDRESS_ADAPTER: + return $this->createAddressDbAdapter(); + default: + throw new \Exception('Db adapter type is not valid'); } } + /** + * @param string $adapterType + * @return \Enlight_Event_EventArgs|null + */ + protected function fireCreateFactoryEvent($adapterType) + { + return Shopware()->Events()->notifyUntil( + 'Shopware_Components_SwagImportExport_Factories_CreateDbAdapter', + ['subject' => $this, 'adapterType' => $adapterType]); + } + /** * Return necessary data manager * @@ -121,7 +150,7 @@ public function loadSession($data) /** * Returns columnOptions adapter - * + * * @param $options * @return \Shopware\Components\SwagImportExport\Utils\DataColumnOptions */ @@ -129,10 +158,10 @@ public function createColOpts($options) { return new DataColumnOptions($options); } - + /** * Returns limit adapter - * + * * @param array $limit * @return \Shopware\Components\SwagImportExport\Utils\DataLimit */ @@ -140,10 +169,10 @@ public function createLimit(array $limit) { return new DataLimit($limit); } - + /** * Returns filter adapter - * + * * @param $filter * @return \Shopware\Components\SwagImportExport\Utils\DataFilter */ @@ -151,7 +180,7 @@ public function createFilter($filter) { return new DataFilter($filter); } - + /** * Helper Method to get access to the session repository. * @@ -164,173 +193,179 @@ public function getSessionRepository() } return $this->sessionRepository; } - + protected function createSession(SessionEntity $sessionEntity) { return new Session($sessionEntity); } /** - * This method can be hookable - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\CategoriesDbAdapter + * @return CategoriesDataManager */ - protected function createCategoriesDbAdapter() + protected function getCategoryDataManager() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\CategoriesDbAdapter'); + ->getProxy('Shopware\Components\SwagImportExport\DataManagers\CategoriesDataManager'); return new $proxyAdapter; } /** - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\ArticlesDbAdapter + * @return ArticleDataManager */ - protected function createArticlesDbAdapter() + protected function getArticleDataManager() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\ArticlesDbAdapter'); - return new $proxyAdapter; + ->getProxy('Shopware\Components\SwagImportExport\DataManagers\Articles\ArticleDataManager'); + $db = Shopware()->Db(); + $dbalHelper = DbalHelper::create(); + return new $proxyAdapter($db, $dbalHelper); } /** - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\ArticlesInStockDbAdapter + * @return CustomerDataManager */ - protected function createArticlesInStockDbAdapter() + protected function getCustomerDataManager() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\ArticlesInStockDbAdapter'); + ->getProxy('Shopware\Components\SwagImportExport\DataManagers\CustomerDataManager'); return new $proxyAdapter; } /** - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\ArticlesTranslationsDbAdapter + * @return NewsletterDataManager */ - protected function createArticlesTranslationsDbAdapter() + protected function getNewsletterDataManager() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\ArticlesTranslationsDbAdapter'); + ->getProxy('Shopware\Components\SwagImportExport\DataManagers\NewsletterDataManager'); return new $proxyAdapter; } /** * This method can be hookable - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\ArticlesPricesDbAdapter + * + * @return CategoriesDbAdapter */ - protected function createArticlesPricesDbAdapter() + protected function createCategoriesDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\ArticlesPricesDbAdapter'); + ->getProxy(CategoriesDbAdapter::class); return new $proxyAdapter; } /** - * This method can be hookable - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\ArticlesImagesDbAdapter + * + * @return ArticlesDbAdapter */ - protected function createArticlesImagesDbAdapter() + protected function createArticlesDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\ArticlesImagesDbAdapter'); + ->getProxy(ArticlesDbAdapter::class); return new $proxyAdapter; } /** - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\CustomerDbAdapter + * @return ArticlesInStockDbAdapter */ - protected function createCustomerDbAdapter() + protected function createArticlesInStockDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\CustomerDbAdapter'); + ->getProxy(ArticlesInStockDbAdapter::class); return new $proxyAdapter; } /** - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\OrdersDbAdapter + * + * @return ArticlesTranslationsDbAdapter */ - protected function createOrdersDbAdapter() + protected function createArticlesTranslationsDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\OrdersDbAdapter'); + ->getProxy(ArticlesTranslationsDbAdapter::class); return new $proxyAdapter; } /** - * @return \Shopware\Components\SwagImportExport\DbAdapters\MainOrdersDbAdapter + * This method can be hookable + * + * @return ArticlesPricesDbAdapter */ - protected function createMainOrdersDbAdapter() + protected function createArticlesPricesDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\MainOrdersDbAdapter'); + ->getProxy(ArticlesPricesDbAdapter::class); return new $proxyAdapter; } /** - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\NewsletterDbAdapter + * This method can be hookable + * + * @return ArticlesImagesDbAdapter */ - protected function createNewsletterDbAdapter() + protected function createArticlesImagesDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\NewsletterDbAdapter'); + ->getProxy(ArticlesImagesDbAdapter::class); return new $proxyAdapter; } + /** - * - * @return \Shopware\Components\SwagImportExport\DbAdapters\TranslationsDbAdapter + * @return CustomerDbAdapter */ - protected function createTranslationsDbAdapter() + protected function createCustomerDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DbAdapters\TranslationsDbAdapter'); + ->getProxy(CustomerDbAdapter::class); return new $proxyAdapter; } /** - * @return \Shopware\Components\SwagImportExport\DataManagers\CategoriesDataManager + * @return OrdersDbAdapter */ - protected function getCategoryDataManager() + protected function createOrdersDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DataManagers\CategoriesDataManager'); + ->getProxy(OrdersDbAdapter::class); return new $proxyAdapter; } /** - * @return \Shopware\Components\SwagImportExport\DataManagers\Articles\ArticleDataManager + * @return MainOrdersDbAdapter */ - protected function getArticleDataManager() + protected function createMainOrdersDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DataManagers\Articles\ArticleDataManager'); - $db = Shopware()->Db(); - $dbalHelper = DbalHelper::create(); - return new $proxyAdapter($db, $dbalHelper); + ->getProxy(MainOrdersDbAdapter::class); + return new $proxyAdapter; } /** - * @return \Shopware\Components\SwagImportExport\DataManagers\CustomerDataManager + * @return NewsletterDbAdapter */ - protected function getCustomerDataManager() + protected function createNewsletterDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DataManagers\CustomerDataManager'); + ->getProxy(NewsletterDbAdapter::class); return new $proxyAdapter; } /** - * @return \Shopware\Components\SwagImportExport\DataManagers\NewsletterDataManager + * @return TranslationsDbAdapter */ - protected function getNewsletterDataManager() + protected function createTranslationsDbAdapter() { $proxyAdapter = Shopware()->Hooks() - ->getProxy('Shopware\Components\SwagImportExport\DataManagers\NewsletterDataManager'); + ->getProxy(TranslationsDbAdapter::class); + return new $proxyAdapter; + } + + /** + * @return AddressDbAdapter + */ + private function createAddressDbAdapter() + { + $proxyAdapter = Shopware()->Hooks() + ->getProxy(AddressDbAdapter::class); return new $proxyAdapter; } } diff --git a/Components/SwagImportExport/Utils/CommandHelper.php b/Components/SwagImportExport/Utils/CommandHelper.php index 8dc7f622..cfb8d371 100644 --- a/Components/SwagImportExport/Utils/CommandHelper.php +++ b/Components/SwagImportExport/Utils/CommandHelper.php @@ -18,47 +18,43 @@ use Shopware\Components\SwagImportExport\Profile\Profile; use Shopware\Components\SwagImportExport\Transformers\DataTransformerChain; use Shopware\Components\SwagImportExport\UploadPathProvider; +use Shopware\CustomModels\ImportExport\Profile as ProfileEntity; +use Shopware\CustomModels\ImportExport\Repository; class CommandHelper { - // required - /** - * @var \Shopware\CustomModels\ImportExport\Profile - */ + /** @var ProfileEntity */ protected $profileEntity; + + /** @var string */ protected $filePath; + + /** @var string */ protected $format; - // optional + /** @var string */ protected $exportVariants; + + /** @var int */ protected $limit; + + /** @var int */ protected $offset; + + /** @var string */ protected $username; + + /** @var string */ protected $category; - //private + /** @var int */ protected $sessionId; - /** - * Tries to find profile by given name - * - * @param string $filename - * @param \Shopware\CustomModels\ImportExport\Repository $repository - * @return bool|Profile - */ - public static function findProfileByName($filename, $repository) - { - $parts = explode('.', $filename); - foreach ($parts as $part) { - $part = strtolower($part); - $profileEntity = $repository->findOneBy(array('name' => $part)); - if ($profileEntity !== null) { - return $profileEntity; - } - } + /** @var \Shopware_Plugins_Backend_SwagImportExport_Bootstrap */ + protected $plugin; - return false; - } + /** @var Logger */ + protected $logger; /** * Construct @@ -68,33 +64,36 @@ public static function findProfileByName($filename, $repository) */ public function __construct(array $data) { - // required - if (isset($data['profileEntity'])) { - $this->profileEntity = $data['profileEntity']; - } else { + $this->plugin = Shopware()->Plugins()->Backend()->SwagImportExport(); + $this->logger = Shopware()->Container()->get('swag_import_export.logger'); + + if (!isset($data['profileEntity'])) { throw new \Exception("No profile given!"); } - if (isset($data['filePath']) && is_dir(dirname($data['filePath']))) { - $this->filePath = $data['filePath']; - } else { - throw new \Exception("Invalid file path " . $data['filePath']); - } - if (isset($data['format'])) { - $this->format = $data['format']; - } else { + if (!isset($data['format'])) { throw new \Exception("No format given!"); } + if (!isset($data['filePath']) || !is_dir(dirname($data['filePath']))) { + throw new \Exception("Invalid file path " . $data['filePath']); + } + + $this->profileEntity = $data['profileEntity']; + $this->format = $data['format']; + $this->filePath = $data['filePath']; // optional if (isset($data['exportVariants'])) { $this->exportVariants = $data['exportVariants']; } + if (isset($data['limit'])) { $this->limit = $data['limit']; } + if (isset($data['offset'])) { $this->offset = $data['offset']; } + if (isset($data['username'])) { $this->username = $data['username']; } @@ -104,6 +103,30 @@ public function __construct(array $data) } } + /** + * Tries to find profile by given name + * + * @param string $filename + * @param Repository $repository + * @return bool|ProfileEntity + */ + public static function findProfileByName($filename, Repository $repository) + { + $parts = explode('.', $filename); + + foreach ($parts as $part) { + $part = strtolower($part); + /** @var ProfileEntity $profileEntity */ + $profileEntity = $repository->findOneBy(['name' => $part]); + + if ($profileEntity !== null) { + return $profileEntity; + } + } + + return false; + } + /** * Prepares export * @@ -112,17 +135,17 @@ public function __construct(array $data) public function prepareExport() { $this->sessionId = null; - $postData = array( + $postData = [ 'sessionId' => $this->sessionId, 'profileId' => (int) $this->profileEntity->getId(), 'type' => 'export', 'format' => $this->format, - 'filter' => array(), - 'limit' => array( + 'filter' => [], + 'limit' => [ 'limit' => $this->limit, 'offset' => $this->offset, - ), - ); + ] + ]; if ($this->exportVariants) { $postData['filter']['variants'] = $this->exportVariants; @@ -133,15 +156,15 @@ public function prepareExport() } /** @var Profile $profile */ - $profile = $this->Plugin()->getProfileFactory()->loadProfile($postData); + $profile = $this->plugin->getProfileFactory()->loadProfile($postData); /** @var DataFactory $dataFactory */ - $dataFactory = $this->Plugin()->getDataFactory(); + $dataFactory = $this->plugin->getDataFactory(); $dbAdapter = $dataFactory->createDbAdapter($profile->getType()); $dataSession = $dataFactory->loadSession($postData); - $dataIO = $dataFactory->createDataIO($dbAdapter, $dataSession, $this->getLogger()); + $dataIO = $dataFactory->createDataIO($dbAdapter, $dataSession, $this->logger); $colOpts = $dataFactory->createColOpts($postData['columnOptions']); $limit = $dataFactory->createLimit($postData['limit']); @@ -157,7 +180,10 @@ public function prepareExport() $position = $dataIO->getSessionPosition(); $position = $position == null ? 0 : $position; - return array('position' => $position, 'count' => count($ids)); + return [ + 'position' => $position, + 'count' => count($ids) + ]; } /** @@ -167,20 +193,18 @@ public function prepareExport() */ public function exportAction() { - $logger = $this->getLogger(); - - $postData = array( + $postData = [ 'profileId' => (int) $this->profileEntity->getId(), 'type' => 'export', 'format' => $this->format, 'sessionId' => $this->sessionId, 'fileName' => basename($this->filePath), - 'filter' => array(), - 'limit' => array( + 'filter' => [], + 'limit' => [ 'limit' => $this->limit, 'offset' => $this->offset, - ), - ); + ] + ]; if ($this->exportVariants) { $postData['filter']['variants'] = $this->exportVariants; @@ -190,16 +214,16 @@ public function exportAction() } /** @var Profile $profile */ - $profile = $this->Plugin()->getProfileFactory()->loadProfile($postData); + $profile = $this->plugin->getProfileFactory()->loadProfile($postData); /** @var DataFactory $dataFactory */ - $dataFactory = $this->Plugin()->getDataFactory(); + $dataFactory = $this->plugin->getDataFactory(); $dbAdapter = $dataFactory->createDbAdapter($profile->getType()); $dataSession = $dataFactory->loadSession($postData); //create dataIO - $dataIO = $dataFactory->createDataIO($dbAdapter, $dataSession, $logger); + $dataIO = $dataFactory->createDataIO($dbAdapter, $dataSession, $this->logger); $colOpts = $dataFactory->createColOpts($postData['columnOptions']); $limit = $dataFactory->createLimit($postData['limit']); @@ -213,58 +237,59 @@ public function exportAction() // we create the file writer that will write (partially) the result file /** @var FileIOFactory $fileFactory */ - $fileFactory = $this->Plugin()->getFileIOFactory(); + $fileFactory = $this->plugin->getFileIOFactory(); /** @var FileWriter $fileWriter */ $fileWriter = $fileFactory->createFileWriter($postData['format']); /** @var DataTransformerChain $dataTransformerChain */ - $dataTransformerChain = $this->Plugin()->getDataTransformerFactory() - ->createDataTransformerChain($profile, array('isTree' => $fileWriter->hasTreeStructure())); + $dataTransformerChain = $this->plugin->getDataTransformerFactory() + ->createDataTransformerChain($profile, ['isTree' => $fileWriter->hasTreeStructure()]); $dataWorkflow = new DataWorkflow($dataIO, $profile, $dataTransformerChain, $fileWriter); - $post = $dataWorkflow->export($postData, $this->filePath); + $resultData = $dataWorkflow->export($postData, $this->filePath); $message = sprintf( '%s %s %s', - $post['position'], + $resultData['position'], SnippetsHelper::getNamespace('backend/swag_import_export/default_profiles')->get('type/' . $profile->getType()), SnippetsHelper::getNamespace('backend/swag_import_export/log')->get('export/success') ); - $logger->write($message, 'false', $dataSession->getEntity()); + $this->logger->write($message, 'false', $dataSession->getEntity()); $logData = new LogDataStruct( date("Y-m-d H:i:s"), - $post['fileName'], + $resultData['fileName'], $profile->getName(), $message, 'true' ); - $logger->writeToFile($logData); + $this->logger->writeToFile($logData); - $this->sessionId = $post['sessionId']; + $this->sessionId = $resultData['sessionId']; - return $post; + return $resultData; } /** * Prepares import * * @return array + * @throws \Exception */ public function prepareImport() { $this->sessionId = null; - $postData = array( + $postData = [ 'sessionId' => $this->sessionId, 'profileId' => (int) $this->profileEntity->getId(), 'type' => 'import', 'format' => $this->format, 'file' => $this->filePath, - ); + ]; //get file format $inputFileName = $postData['file']; @@ -274,7 +299,7 @@ public function prepareImport() // we create the file reader that will read the result file /** @var FileReader $fileReader */ - $fileReader = $this->Plugin()->getFileIOFactory()->createFileReader($postData['format']); + $fileReader = $this->plugin->getFileIOFactory()->createFileReader($postData['format']); if ($this->format === 'xml') { $tree = json_decode($this->profileEntity->getTree(), true); @@ -282,56 +307,59 @@ public function prepareImport() } /** @var DataFactory $dataFactory */ - $dataFactory = $this->Plugin()->getDataFactory(); + $dataFactory = $this->plugin->getDataFactory(); $dbAdapter = $dataFactory->createDbAdapter($this->profileEntity->getType()); $dataSession = $dataFactory->loadSession($postData); //create dataIO - $dataIO = $dataFactory->createDataIO($dbAdapter, $dataSession, $this->getLogger()); + $dataIO = $dataFactory->createDataIO($dbAdapter, $dataSession, $this->logger); $position = $dataIO->getSessionPosition(); $position = $position == null ? 0 : $position; $totalCount = $fileReader->getTotalCount($inputFileName); - return array('success' => true, 'position' => $position, 'count' => $totalCount); + return [ + 'success' => true, + 'position' => $position, + 'count' => $totalCount + ]; } /** * Executes import action * * @return array + * @throws \Exception */ public function importAction() { /** @var UploadPathProvider $uploadPathProvider */ $uploadPathProvider = Shopware()->Container()->get('swag_import_export.upload_path_provider'); - $postData = array( + $postData = [ 'type' => 'import', 'profileId' => (int) $this->profileEntity->getId(), 'importFile' => $this->filePath, 'sessionId' => $this->sessionId, 'format' => $this->format, 'columnOptions' => null, - 'limit' => array(), + 'limit' => [], 'filter' => null, 'max_record_count' => null, - ); + ]; $inputFile = $postData['importFile']; - $logger = $this->getLogger(); - // we create the file reader that will read the result file /** @var FileIOFactory $fileFactory */ - $fileFactory = $this->Plugin()->getFileIOFactory(); + $fileFactory = $this->plugin->getFileIOFactory(); $fileReader = $fileFactory->createFileReader($postData['format']); //load profile /** @var Profile $profile */ - $profile = $this->Plugin()->getProfileFactory()->loadProfile($postData); + $profile = $this->plugin->getProfileFactory()->loadProfile($postData); //get profile type $postData['adapter'] = $profile->getType(); @@ -340,13 +368,13 @@ public function importAction() $postData['batchSize'] = $profile->getType() === 'articlesImages' ? 1 : 50; /** @var DataFactory $dataFactory */ - $dataFactory = $this->Plugin()->getDataFactory(); + $dataFactory = $this->plugin->getDataFactory(); $dbAdapter = $dataFactory->createDbAdapter($profile->getType()); $dataSession = $dataFactory->loadSession($postData); //create dataIO - $dataIO = $dataFactory->createDataIO($dbAdapter, $dataSession, $logger); + $dataIO = $dataFactory->createDataIO($dbAdapter, $dataSession, $this->logger); $colOpts = $dataFactory->createColOpts($postData['columnOptions']); $limit = $dataFactory->createLimit($postData['limit']); @@ -359,24 +387,24 @@ public function importAction() $dataIO->setUsername($this->username); /** @var DataTransformerChain $dataTransformerChain */ - $dataTransformerChain = $this->Plugin()->getDataTransformerFactory() - ->createDataTransformerChain($profile, array('isTree' => $fileReader->hasTreeStructure())); + $dataTransformerChain = $this->plugin->getDataTransformerFactory() + ->createDataTransformerChain($profile, ['isTree' => $fileReader->hasTreeStructure()]); $sessionState = $dataIO->getSessionState(); $dataWorkflow = new DataWorkflow($dataIO, $profile, $dataTransformerChain, $fileReader); try { - $post = $dataWorkflow->import($postData, $inputFile); + $resultData = $dataWorkflow->import($postData, $inputFile); - if (isset($post['unprocessedData']) && $post['unprocessedData']) { - $data = array( - 'data' => $post['unprocessedData'], - 'session' => array( + if (isset($resultData['unprocessedData']) && $resultData['unprocessedData']) { + $data = [ + 'data' => $resultData['unprocessedData'], + 'session' => [ 'prevState' => $sessionState, 'currentState' => $dataIO->getSessionState() - ) - ); + ] + ]; $pathInfo = pathinfo($inputFile); @@ -385,29 +413,29 @@ public function importAction() $pathInfo['filename'] . '-' . $key . '-tmp.csv' ); - $post['unprocessed'][] = array( + $post['unprocessed'][] = [ 'profileName' => $key, 'fileName' => $outputFile - ); + ]; $this->afterImport($data, $key, $outputFile); } } - $this->sessionId = $post['sessionId']; + $this->sessionId = $resultData['sessionId']; if ( $dataSession->getTotalCount() > 0 - && ($dataSession->getTotalCount() == $post['position']) - && $logger->getMessage() === null + && ($dataSession->getTotalCount() == $resultData['position']) + && $this->logger->getMessage() === null ) { $message = sprintf( '%s %s %s', - $post['position'], - SnippetsHelper::getNamespace('backend/swag_import_export/default_profiles')->get($post['adapter']), + $resultData['position'], + SnippetsHelper::getNamespace('backend/swag_import_export/default_profiles')->get($resultData['adapter']), SnippetsHelper::getNamespace('backend/swag_import_export/log')->get('import/success') ); - $logger->write($message, 'false', $dataSession->getEntity()); + $this->logger->write($message, 'false', $dataSession->getEntity()); $logDataStruct = new LogDataStruct( date("Y-m-d H:i:s"), @@ -417,12 +445,12 @@ public function importAction() 'false' ); - $logger->writeToFile($logDataStruct); + $this->logger->writeToFile($logDataStruct); } - return array('success' => true, 'data' => $post); + return ['success' => true, 'data' => $resultData]; } catch (\Exception $e) { - $logger->write($e->getMessage(), 'true', $dataSession->getEntity()); + $this->logger->write($e->getMessage(), 'true', $dataSession->getEntity()); $logDataStruct = new LogDataStruct( date("Y-m-d H:i:s"), @@ -432,7 +460,7 @@ public function importAction() 'false' ); - $logger->writeToFile($logDataStruct); + $this->logger->writeToFile($logDataStruct); throw $e; } @@ -448,35 +476,19 @@ public function importAction() protected function afterImport($data, $profileName, $outputFile) { /** @var FileIOFactory $fileFactory */ - $fileFactory = $this->Plugin()->getFileIOFactory(); + $fileFactory = $this->plugin->getFileIOFactory(); //loads hidden profile for article /** @var Profile $profile */ - $profile = $this->Plugin()->getProfileFactory()->loadHiddenProfile($profileName); + $profile = $this->plugin->getProfileFactory()->loadHiddenProfile($profileName); $fileWriter = $fileFactory->createFileWriter('csv'); /** @var DataTransformerChain $dataTransformerChain */ - $dataTransformerChain = $this->Plugin()->getDataTransformerFactory() - ->createDataTransformerChain($profile, array('isTree' => $fileWriter->hasTreeStructure())); + $dataTransformerChain = $this->plugin->getDataTransformerFactory() + ->createDataTransformerChain($profile, ['isTree' => $fileWriter->hasTreeStructure()]); $dataWorkflow = new DataWorkflow(null, $profile, $dataTransformerChain, $fileWriter); $dataWorkflow->saveUnprocessedData($data, $profileName, $outputFile); } - - /** - * @return \Shopware_Plugins_Backend_SwagImportExport_Bootstrap - */ - protected function Plugin() - { - return Shopware()->Plugins()->Backend()->SwagImportExport(); - } - - /** - * @return Logger - */ - private function getLogger() - { - return Shopware()->Container()->get('swag_import_export.logger'); - } } diff --git a/Components/SwagImportExport/Utils/TreeHelper.php b/Components/SwagImportExport/Utils/TreeHelper.php index b7c9d2d0..ffe1c9d7 100644 --- a/Components/SwagImportExport/Utils/TreeHelper.php +++ b/Components/SwagImportExport/Utils/TreeHelper.php @@ -130,6 +130,8 @@ public static function appendNode(array $child, array &$node) 'type' => $child['type'], 'index' => $child['index'], 'name' => $child['text'], + 'defaultValue' => $child['defaultValue'], + 'shopwareField' => $child['swColumn'] ); } diff --git a/Components/SwagImportExport/Validators/AddressValidator.php b/Components/SwagImportExport/Validators/AddressValidator.php new file mode 100644 index 00000000..e2cfb258 --- /dev/null +++ b/Components/SwagImportExport/Validators/AddressValidator.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Shopware\Components\SwagImportExport\Validators; + +use Shopware\Components\SwagImportExport\Exception\AdapterException; +use Shopware\Components\SwagImportExport\Utils\SnippetsHelper; +use Shopware\Models\Customer\Address; + +class AddressValidator extends Validator +{ + /** + * @var array + */ + private $requiredFields = [ + 'firstname' => [ + 'snippet' => 'adapters/address/firstname_required', + 'default' => 'Field firstname is required. Record %s' + ], + 'lastname' => [ + 'snippet' => 'adapters/address/lastname_required', + 'default' => 'Field lastname is required. Record %s' + ], + 'zipcode' => [ + 'snippet' => 'adapters/address/zipcode_required', + 'default' => 'Field zipcode is required. Record %s' + ], + 'city' => [ + 'snippet' => 'adapters/address/city_required', + 'default' => 'Field city is required. Record %s' + ], + 'countryID' => [ + 'snippet' => 'adapters/address/country_id_required', + 'default' => 'Field countryID is required. Record %s' + ] + ]; + + /** + * @param array $addressRecord + * @param bool $updateAddress + */ + public function checkRequiredFields($addressRecord, $updateAddress = false) + { + $this->validateEmptyAddressRecord($addressRecord); + $this->validateCustomerCanBeIdentified($addressRecord); + + if ($updateAddress) { + return; + } + + $this->validateAddressFields($addressRecord); + } + + /** + * @param array $addressRecord + * @throws AdapterException + */ + private function validateEmptyAddressRecord($addressRecord) + { + if (0 === count($addressRecord)) { + throw new AdapterException( + SnippetsHelper::getNamespace()->get( + 'adapters/address/no_records', + 'Could not find address records.' + ) + ); + } + } + + /** + * @param array $addressRecord + * @throws AdapterException + */ + private function validateAddressFields($addressRecord) + { + foreach ($this->requiredFields as $field => $snippetData) { + if (strlen($addressRecord[$field]) > 0) { + continue; + } + + $message = SnippetsHelper::getNamespace()->get($snippetData['snippet'], $snippetData['default']); + $recordDataForMessage = $this->recordToString($addressRecord); + throw new AdapterException(sprintf($message, $recordDataForMessage)); + } + } + + /** + * @param array $addressRecord + * @throws AdapterException + */ + private function validateCustomerCanBeIdentified($addressRecord) + { + if ( + !($addressRecord['customernumber'] && $addressRecord['email']) + && !$addressRecord['userID'] + ) { + $message = SnippetsHelper::getNamespace()->get('adapters/address/cant_identify_customer'); + $recordDataForMessage = $this->recordToString($addressRecord); + throw new AdapterException(sprintf($message, $recordDataForMessage)); + } + } + + /** + * @param array $addressRecord + * @return string + */ + private function recordToString($addressRecord) + { + $messageTemplate = '%s: %s, '; + $message = ''; + foreach ($addressRecord as $fieldName => $value) { + if (!$value) { + $value = ' - '; + } + $message .= sprintf($messageTemplate, $fieldName, $value); + } + + return $this->removeLastComma($message); + } + + /** + * @param string $message + * @return string + */ + private function removeLastComma($message) + { + return substr($message, 0, -2); + } +} diff --git a/Components/SwagImportExport/Validators/ArticlePriceValidator.php b/Components/SwagImportExport/Validators/ArticlePriceValidator.php index 5a45123e..bbd648d4 100644 --- a/Components/SwagImportExport/Validators/ArticlePriceValidator.php +++ b/Components/SwagImportExport/Validators/ArticlePriceValidator.php @@ -13,32 +13,34 @@ class ArticlePriceValidator extends Validator { - public static $mapper = array( - 'string' => array( //TODO: maybe we don't need to check fields which contains string? + public static $mapper = [ + 'string' => [ //TODO: maybe we don't need to check fields which contains string? 'orderNumber', 'priceGroup', 'name', 'additionalText', 'supplierName', - ), - 'float' => array( + ], + 'float' => [ 'price', 'purchasePrice', 'pseudoPrice', - ), - 'int' => array('from'), - ); + ], + 'int' => [ + 'from' + ] + ]; - private $requiredFields = array( - 'orderNumber', - ); + private $requiredFields = [ + 'orderNumber' + ]; - private $snippetData = array( - 'orderNumber' => array( + private $snippetData = [ + 'orderNumber' => [ 'adapters/ordernumber_required', 'Order number is required.' - ), - ); + ] + ]; /** * Checks whether required fields are filled-in diff --git a/Controllers/Backend/SwagImportExportProfile.php b/Controllers/Backend/SwagImportExportProfile.php index 0f84039d..1ad79b91 100644 --- a/Controllers/Backend/SwagImportExportProfile.php +++ b/Controllers/Backend/SwagImportExportProfile.php @@ -88,11 +88,13 @@ public function getProfilesAction() $count = $manager->getQueryCount($query); $data = $query->getArrayResult(); + /** @var Enlight_Components_Snippet_Namespace $namespace */ + $namespace = $this->get('snippets')->getNamespace('backend/swag_import_export/default_profiles'); foreach ($data as &$profile) { if (true === $profile['default']) { - $translatedProfileName = $this->get('snippets')->getNamespace('backend/swag_import_export/default_profiles')->get($profile['name']); - $profile['translation'] = $translatedProfileName; + $profile['translation'] = $namespace->get($profile['name']); + $profile['description'] = $namespace->get($profile['description']); } } diff --git a/Models/ImportExport/Logger.php b/Models/ImportExport/Logger.php index 207b90e5..7b4ca4c2 100644 --- a/Models/ImportExport/Logger.php +++ b/Models/ImportExport/Logger.php @@ -34,7 +34,7 @@ class Logger extends ModelEntity /** * @var Session $session * - * @ORM\ManyToOne(targetEntity="Shopware\CustomModels\ImportExport\Session") + * @ORM\ManyToOne(targetEntity="Shopware\CustomModels\ImportExport\Session", inversedBy="logs") * @ORM\JoinColumn(name="session_id", referencedColumnName="id", onDelete="SET NULL") */ protected $session; diff --git a/Models/ImportExport/Profile.php b/Models/ImportExport/Profile.php index cc08230d..6771c9bf 100644 --- a/Models/ImportExport/Profile.php +++ b/Models/ImportExport/Profile.php @@ -75,6 +75,13 @@ class Profile extends ModelEntity */ protected $name; + /** + * @var string $description + * + * @ORM\Column(name="description", type="text", nullable=true) + */ + protected $description; + /** * @var string $format * @@ -151,6 +158,14 @@ public function getName() return $this->name; } + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + /** * @param int $id */ @@ -191,6 +206,14 @@ public function setName($name) $this->name = $name; } + /** + * @param string $description + */ + public function setDescription($description) + { + $this->description = $description; + } + /** * @return int */ diff --git a/Models/ImportExport/Repository.php b/Models/ImportExport/Repository.php index 9ee7349a..f6b7bbaf 100644 --- a/Models/ImportExport/Repository.php +++ b/Models/ImportExport/Repository.php @@ -40,6 +40,7 @@ public function getProfilesListQuery(array $filterBy = [], array $orderBy = [], 'p.id as id', 'p.type as type', 'p.name as name', + 'p.description as description', 'p.tree as tree', 'p.default as default', 'p.baseProfile as baseProfile' diff --git a/Models/ImportExport/Session.php b/Models/ImportExport/Session.php index 1679cb76..ee806e74 100644 --- a/Models/ImportExport/Session.php +++ b/Models/ImportExport/Session.php @@ -35,8 +35,8 @@ class Session extends ModelEntity /** * @var Profile $profile * - * @ORM\ManyToOne(targetEntity="Shopware\CustomModels\ImportExport\Profile", cascade={"persist", "refresh"}) - * @ORM\JoinColumn(onDelete="CASCADE") + * @ORM\ManyToOne(targetEntity="Shopware\CustomModels\ImportExport\Profile", inversedBy="sessions", cascade={"persist", "refresh"}) + * @ORM\JoinColumn(name="profile_id", onDelete="CASCADE") */ protected $profile; diff --git a/Setup/SwagImportExport/DefaultProfiles/AddressProfile.php b/Setup/SwagImportExport/DefaultProfiles/AddressProfile.php new file mode 100644 index 00000000..117a591a --- /dev/null +++ b/Setup/SwagImportExport/DefaultProfiles/AddressProfile.php @@ -0,0 +1,218 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Shopware\Setup\SwagImportExport\DefaultProfiles; + +use Shopware\Components\SwagImportExport\DbAdapters\DataDbAdapter; + +class AddressProfile implements ProfileMetaData, \JsonSerializable +{ + /** + * @inheritdoc + */ + public function getAdapter() + { + return DataDbAdapter::ADDRESS_ADAPTER; + } + + /** + * @inheritdoc + */ + public function getName() + { + return 'default_addresses'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_addresses_description'; + } + + /** + * @inheritdoc + */ + public function jsonSerialize() + { + return [ + 'id' => 'root', + 'name' => 'Root', + 'type' => 'node', + 'children' => [ + [ + 'id' => '58458e1c359ea', + 'name' => 'addresses', + 'index' => 0, + 'type' => '', + 'children' => [ + [ + 'id' => '58458e1c21722', + 'name' => 'address', + 'type' => 'iteration', + 'adapter' => 'address', + 'parentKey' => '', + 'shopwareField' => '', + 'children' => $this->getAddressFields() + ] + ] + ] + ] + ]; + } + + /** + * @return array + */ + private function getAddressFields() + { + return [ + [ + 'id' => '58458e1c01c46', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'id', + 'shopwareField' => 'id' + ], + [ + 'id' => '58458e1c01a47', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'userID', + 'shopwareField' => 'userID' + ], + [ + 'id' => '5846753b011f1', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'email', + 'shopwareField' => 'email' + ], + [ + 'id' => '5846753b01794', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'customernumber', + 'shopwareField' => 'customernumber' + ], + [ + 'id' => '58458e1c00f88', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'company', + 'shopwareField' => 'company' + ], + [ + 'id' => '58458e1c019f8', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'department', + 'shopwareField' => 'department' + ], + [ + 'id' => '58458e1c0195d', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'salutation', + 'shopwareField' => 'salutation' + ], + [ + 'id' => '58458e1c01475', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'title', + 'shopwareField' => 'title' + ], + [ + 'id' => '58458e1c01bb1', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'firstname', + 'shopwareField' => 'firstname' + ], + [ + 'id' => '58458e1c01246', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'lastname', + 'shopwareField' => 'lastname' + ], + [ + 'id' => '58458e1c01347', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'street', + 'shopwareField' => 'street' + ], + [ + 'id' => '58458e1c02067', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'zipcode', + 'shopwareField' => 'zipcode' + ], + [ + 'id' => '58458e1c01774', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'firstname', + 'shopwareField' => 'firstname' + ], + [ + 'id' => '58458e1c0193a', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'city', + 'shopwareField' => 'city' + ], + [ + 'id' => '58458e1c0101c', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'countryID', + 'shopwareField' => 'countryID' + ], + [ + 'id' => '58458e1c013f4', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'stateID', + 'shopwareField' => 'stateID' + ], + [ + 'id' => '58458e1c011fc', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'vatID', + 'shopwareField' => 'vatId' + ], + [ + 'id' => '58458e1c01c2e', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'phone', + 'shopwareField' => 'phone' + ], + [ + 'id' => '58458e1c014cf', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'additionalAddressLine1', + 'shopwareField' => 'additionalAddressLine1' + ], + [ + 'id' => '58458e1c02265', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'additionalAddressLine2', + 'shopwareField' => 'additionalAddressLine2' + ] + ]; + } +} diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleAccessoryProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleAccessoryProfile.php index 57916494..a4997819 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleAccessoryProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleAccessoryProfile.php @@ -25,7 +25,15 @@ public function getAdapter() */ public function getName() { - return "default_article_accessories"; + return 'default_article_accessories'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_accessories_description'; } /** @@ -53,7 +61,7 @@ public function jsonSerialize() 'parentKey' => '', 'shopwareField' => '', 'children' => $this->getArticleAccessoryFields(), - 'attributes' => NULL + 'attributes' => null ] ], 'shopwareField' => '' @@ -100,4 +108,4 @@ private function getArticleAccessoryFields() ] ]; } -} \ No newline at end of file +} diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleCategoriesProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleCategoriesProfile.php index d2ba4742..b900fd60 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleCategoriesProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleCategoriesProfile.php @@ -25,7 +25,15 @@ public function getAdapter() */ public function getName() { - return "default_article_categories"; + return 'default_article_categories'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_categories_description'; } /** @@ -53,7 +61,7 @@ public function jsonSerialize() 'parentKey' => '', 'shopwareField' => '', 'children' => $this->getArticleCategoriesFields(), - 'attributes' => NULL + 'attributes' => null ] ], 'shopwareField' => '' @@ -102,4 +110,4 @@ private function getArticleCategoriesFields() ] ]; } -} \ No newline at end of file +} diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleCompleteProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleCompleteProfile.php index c0fca539..5483952f 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleCompleteProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleCompleteProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_articles_complete'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_articles_complete_description'; + } + /** * @inheritdoc */ @@ -448,6 +456,22 @@ private function getPriceFields() 'name' => 'baseprice', 'shopwareField' => 'basePrice', ], + 4 => + [ + 'id' => '586f64abcf438', + 'type' => 'leaf', + 'index' => 4, + 'name' => 'from', + 'shopwareField' => 'from' + ], + 5 => + [ + 'id' => '586f64b4a75c0', + 'type' => 'leaf', + 'index' => 5, + 'name' => 'to', + 'shopwareField' => 'to' + ] ], 'attributes' => null, ] diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleImageUrlProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleImageUrlProfile.php index 9e266149..bb34e73a 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleImageUrlProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleImageUrlProfile.php @@ -32,6 +32,14 @@ public function getName() return 'default_article_images_url'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_images_url_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleImagesProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleImagesProfile.php index 792bdee4..98e65fdb 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleImagesProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleImagesProfile.php @@ -25,7 +25,15 @@ public function getAdapter() */ public function getName() { - return "default_article_images"; + return 'default_article_images'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_images_description'; } /** diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleInStockProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleInStockProfile.php index afb0dc88..bb2ad931 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleInStockProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleInStockProfile.php @@ -25,7 +25,15 @@ public function getAdapter() */ public function getName() { - return "default_article_in_stock"; + return 'default_article_in_stock'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_in_stock_description'; } /** diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticlePriceProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticlePriceProfile.php index d70bea81..e81c3577 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticlePriceProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticlePriceProfile.php @@ -25,7 +25,15 @@ public function getAdapter() */ public function getName() { - return "default_article_prices"; + return 'default_article_prices'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_prices_description'; } /** @@ -107,37 +115,44 @@ private function getArticlePriceFields() 'shopwareField' => 'from' ], 4 => [ - 'id' => '540ffb5fd04ba', + 'id' => '586f65957f616', 'type' => 'leaf', 'index' => 4, - 'name' => 'pseudoprice', - 'shopwareField' => 'pseudoPrice' + 'name' => 'to', + 'shopwareField' => 'to' ], 5 => [ - 'id' => '540ffb61558eb', + 'id' => '540ffb5fd04ba', 'type' => 'leaf', 'index' => 5, - 'name' => 'baseprice', - 'shopwareField' => 'basePrice' + 'name' => 'pseudoprice', + 'shopwareField' => 'pseudoPrice' ], 6 => [ - 'id' => '540ffda5904e5', + 'id' => '540ffb61558eb', 'type' => 'leaf', 'index' => 6, + 'name' => 'purchaseprice', + 'shopwareField' => 'purchasePrice' + ], + 7 => [ + 'id' => '540ffda5904e5', + 'type' => 'leaf', + 'index' => 7, 'name' => '_name', 'shopwareField' => 'name' ], - 7 => [ + 8 => [ 'id' => '540ffc1d66042', 'type' => 'leaf', - 'index' => 7, + 'index' => 8, 'name' => '_additionaltext', 'shopwareField' => 'additionalText' ], - 8 => [ + 9 => [ 'id' => '540ffcf5089af', 'type' => 'leaf', - 'index' => 8, + 'index' => 9, 'name' => '_supplier', 'shopwareField' => 'supplierName' ] diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleProfile.php index 0c1a0cc8..7f1c749a 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_articles'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_articles_description'; + } + /** * @inheritdoc */ @@ -168,6 +176,22 @@ private function getArticleFields() 'name' => 'baseprice', 'shopwareField' => 'basePrice', ], + '4' => + [ + 'id' => '586f57076422f', + 'type' => 'leaf', + 'index' => 4, + 'name' => 'from', + 'shopwareField' => 'from' + ], + '5' => + [ + 'id' => '586f5711216ba', + 'type' => 'leaf', + 'index' => 5, + 'name' => 'to', + 'shopwareField' => 'to' + ] ], 'attributes' => NULL, ] diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticlePropertiesProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticlePropertiesProfile.php index 7f3eed26..d3732516 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticlePropertiesProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticlePropertiesProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_article_properties'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_properties_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleSimilarsProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleSimilarsProfile.php index ec014675..1bc0b76a 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleSimilarsProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleSimilarsProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_similar_articles'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_similar_articles_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleTranslationProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleTranslationProfile.php index 77a38fad..d5fe76e9 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleTranslationProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleTranslationProfile.php @@ -32,6 +32,14 @@ public function getName() return 'default_article_translations'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_translations_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/ArticleTranslationUpdateProfile.php b/Setup/SwagImportExport/DefaultProfiles/ArticleTranslationUpdateProfile.php index fcfb8b8b..47e9efca 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ArticleTranslationUpdateProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/ArticleTranslationUpdateProfile.php @@ -32,6 +32,14 @@ public function getName() return 'default_article_translations_update'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_translations_update_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/CategoryProfile.php b/Setup/SwagImportExport/DefaultProfiles/CategoryProfile.php index 57af053e..feaadc5e 100644 --- a/Setup/SwagImportExport/DefaultProfiles/CategoryProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/CategoryProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_categories'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_categories_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/CustomerProfile.php b/Setup/SwagImportExport/DefaultProfiles/CustomerProfile.php index fd49a5e5..1b3d2803 100644 --- a/Setup/SwagImportExport/DefaultProfiles/CustomerProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/CustomerProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_customers'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_customers_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/MinimalArticleProfile.php b/Setup/SwagImportExport/DefaultProfiles/MinimalArticleProfile.php index 26721239..1eb65005 100644 --- a/Setup/SwagImportExport/DefaultProfiles/MinimalArticleProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/MinimalArticleProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_articles_minimal'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_articles_minimal_description'; + } + /** * @inheritdoc */ @@ -144,6 +152,20 @@ private function getArticleFields() 'index' => 3, 'name' => 'baseprice', 'shopwareField' => 'basePrice' + ], + 4 => [ + 'id' => '586f6b291bb01', + 'type' => 'leaf', + 'index' => 4, + 'name' => 'from', + 'shopwareField' => 'from' + ], + 5 => [ + 'id' => '586f6b33eed94', + 'type' => 'leaf', + 'index' => 5, + 'name' => 'to', + 'shopwareField' => 'to' ] ], 'attributes' => NULL diff --git a/Setup/SwagImportExport/DefaultProfiles/MinimalArticleVariantsProfile.php b/Setup/SwagImportExport/DefaultProfiles/MinimalArticleVariantsProfile.php index ecce69b0..e19dfa34 100644 --- a/Setup/SwagImportExport/DefaultProfiles/MinimalArticleVariantsProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/MinimalArticleVariantsProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_article_variants_minimal'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_article_variants_minimal_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/MinimalCategoryProfile.php b/Setup/SwagImportExport/DefaultProfiles/MinimalCategoryProfile.php index 2cf7b3a8..e6478f35 100644 --- a/Setup/SwagImportExport/DefaultProfiles/MinimalCategoryProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/MinimalCategoryProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_categories_minimal'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_categories_minimal_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/MinimalOrdersProfile.php b/Setup/SwagImportExport/DefaultProfiles/MinimalOrdersProfile.php index d484364f..d16e53a5 100644 --- a/Setup/SwagImportExport/DefaultProfiles/MinimalOrdersProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/MinimalOrdersProfile.php @@ -25,7 +25,15 @@ public function getAdapter() */ public function getName() { - return "default_orders_minimal"; + return 'default_orders_minimal'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_orders_minimal_description'; } /** diff --git a/Setup/SwagImportExport/DefaultProfiles/NewsletterRecipientProfile.php b/Setup/SwagImportExport/DefaultProfiles/NewsletterRecipientProfile.php index 44c0464a..644fb2d2 100644 --- a/Setup/SwagImportExport/DefaultProfiles/NewsletterRecipientProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/NewsletterRecipientProfile.php @@ -25,7 +25,15 @@ public function getAdapter() */ public function getName() { - return "default_newsletter_recipient"; + return 'default_newsletter_recipient'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_newsletter_recipient_description'; } /** diff --git a/Setup/SwagImportExport/DefaultProfiles/OrderMainDataProfile.php b/Setup/SwagImportExport/DefaultProfiles/OrderMainDataProfile.php index 8b13efb0..a9d4018f 100644 --- a/Setup/SwagImportExport/DefaultProfiles/OrderMainDataProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/OrderMainDataProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_order_main_data'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_order_main_data_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/DefaultProfiles/OrderProfile.php b/Setup/SwagImportExport/DefaultProfiles/OrderProfile.php new file mode 100644 index 00000000..3ac612ce --- /dev/null +++ b/Setup/SwagImportExport/DefaultProfiles/OrderProfile.php @@ -0,0 +1,463 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Shopware\Setup\SwagImportExport\DefaultProfiles; + +use Shopware\Components\SwagImportExport\DbAdapters\DataDbAdapter; + +/** + * Class OrderProfile + * @package Shopware\Setup\SwagImportExport\DefaultProfiles + */ +class OrderProfile implements \JsonSerializable, ProfileMetaData +{ + /** + * @inheritdoc + */ + public function getAdapter() + { + return DataDbAdapter::ORDER_ADAPTER; + } + + /** + * @inheritdoc + */ + public function getName() + { + return 'default_orders'; + } + + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_orders_description'; + } + + /** + * @inheritdoc + */ + public function jsonSerialize() + { + return [ + 'id' => 'root', + 'name' => 'Root', + 'type' => 'node', + 'children' =>[ + 0 => [ + 'id' => '537359399c80a', + 'name' => 'Header', + 'index' => 0, + 'type' => 'node', + 'children' => [ + 0 => [ + 'id' => '537385ed7c799', + 'name' => 'HeaderChild', + 'index' => 0, + 'type' => 'node', + 'shopwareField' => '' + ] + ] + ], + 1 => [ + 'id' => '537359399c8b7', + 'name' => 'orders', + 'index' => 1, + 'type' => 'node', + 'children' => [ + 0 => [ + 'id' => '537359399c90d', + 'name' => 'order', + 'index' => 0, + 'type' => 'iteration', + 'adapter' => 'default', + 'attributes' => NULL, + 'children' => $this->getOrderFields(), + 'shopwareField' => '', + 'parentKey' => '' + ] + ], + 'shopwareField' => '' + ] + ] + ]; + } + + /** + * @return array + */ + private function getOrderFields() + { + return [ + 0 => + [ + 'id' => '53eca77b49d6d', + 'type' => 'leaf', + 'index' => 0, + 'name' => 'orderId', + 'shopwareField' => 'orderId', + ], + 1 => + [ + 'id' => '5373865547d06', + 'name' => 'number', + 'index' => 1, + 'type' => 'leaf', + 'shopwareField' => 'number', + ], + 2 => + [ + 'id' => '53ecb1fa09cfd', + 'type' => 'leaf', + 'index' => 2, + 'name' => 'customerId', + 'shopwareField' => 'customerId', + ], + 3 => + [ + 'id' => '53ecb3a3e43fb', + 'type' => 'leaf', + 'index' => 3, + 'name' => 'orderStatusID', + 'shopwareField' => 'status', + ], + 4 => + [ + 'id' => '53ecb496e80e0', + 'type' => 'leaf', + 'index' => 4, + 'name' => 'cleared', + 'shopwareField' => 'cleared', + ], + 5 => + [ + 'id' => '53ecb4e584159', + 'type' => 'leaf', + 'index' => 5, + 'name' => 'paymentID', + 'shopwareField' => 'paymentId', + ], + 6 => + [ + 'id' => '53ecb4f9a203b', + 'type' => 'leaf', + 'index' => 6, + 'name' => 'dispatchId', + 'shopwareField' => 'dispatchId', + ], + 7 => + [ + 'id' => '53ecb510a3379', + 'type' => 'leaf', + 'index' => 7, + 'name' => 'partnerId', + 'shopwareField' => 'partnerId', + ], + 8 => + [ + 'id' => '53ecb51a93f21', + 'type' => 'leaf', + 'index' => 8, + 'name' => 'shopId', + 'shopwareField' => 'shopId', + ], + 9 => + [ + 'id' => '53ecb6a059334', + 'type' => 'leaf', + 'index' => 9, + 'name' => 'invoiceAmount', + 'shopwareField' => 'invoiceAmount', + ], + 10 => + [ + 'id' => '53ecb6a74e399', + 'type' => 'leaf', + 'index' => 10, + 'name' => 'invoiceAmountNet', + 'shopwareField' => 'invoiceAmountNet', + ], + 11 => + [ + 'id' => '53ecb6b4587ba', + 'type' => 'leaf', + 'index' => 11, + 'name' => 'invoiceShipping', + 'shopwareField' => 'invoiceShipping', + ], + 12 => + [ + 'id' => '53ecb6be27e2e', + 'type' => 'leaf', + 'index' => 12, + 'name' => 'invoiceShippingNet', + 'shopwareField' => 'invoiceShippingNet', + ], + 13 => + [ + 'id' => '53ecb6db22a2e', + 'type' => 'leaf', + 'index' => 13, + 'name' => 'orderTime', + 'shopwareField' => 'orderTime', + ], + 14 => + [ + 'id' => '53ecb6ebaf4c5', + 'type' => 'leaf', + 'index' => 14, + 'name' => 'transactionId', + 'shopwareField' => 'transactionId', + ], + 15 => + [ + 'id' => '53ecb7014e7ad', + 'type' => 'leaf', + 'index' => 15, + 'name' => 'comment', + 'shopwareField' => 'comment', + ], + 16 => + [ + 'id' => '53ecb7f0df5db', + 'type' => 'leaf', + 'index' => 16, + 'name' => 'customerComment', + 'shopwareField' => 'customerComment', + ], + 17 => + [ + 'id' => '53ecb7f265873', + 'type' => 'leaf', + 'index' => 17, + 'name' => 'internalComment', + 'shopwareField' => 'internalComment', + ], + 18 => + [ + 'id' => '53ecb7f3baed3', + 'type' => 'leaf', + 'index' => 18, + 'name' => 'net', + 'shopwareField' => 'net', + ], + 19 => + [ + 'id' => '53ecb7f518b2a', + 'type' => 'leaf', + 'index' => 19, + 'name' => 'taxFree', + 'shopwareField' => 'taxFree', + ], + 20 => + [ + 'id' => '53ecb7f778bb0', + 'type' => 'leaf', + 'index' => 20, + 'name' => 'temporaryId', + 'shopwareField' => 'temporaryId', + ], + 21 => + [ + 'id' => '53ecb7f995899', + 'type' => 'leaf', + 'index' => 21, + 'name' => 'referer', + 'shopwareField' => 'referer', + ], + 22 => + [ + 'id' => '53ecb8ba28544', + 'type' => 'leaf', + 'index' => 22, + 'name' => 'clearedDate', + 'shopwareField' => 'clearedDate', + ], + 23 => + [ + 'id' => '53ecb8bd55dda', + 'type' => 'leaf', + 'index' => 23, + 'name' => 'trackingCode', + 'shopwareField' => 'trackingCode', + ], + 24 => + [ + 'id' => '53ecb8c076318', + 'type' => 'leaf', + 'index' => 24, + 'name' => 'languageIso', + 'shopwareField' => 'languageIso', + ], + 25 => + [ + 'id' => '53ecb8c42923d', + 'type' => 'leaf', + 'index' => 25, + 'name' => 'currency', + 'shopwareField' => 'currency', + ], + 26 => + [ + 'id' => '53ecb8c74168b', + 'type' => 'leaf', + 'index' => 26, + 'name' => 'currencyFactor', + 'shopwareField' => 'currencyFactor', + ], + 27 => + [ + 'id' => '53ecb9203cb33', + 'type' => 'leaf', + 'index' => 27, + 'name' => 'remoteAddress', + 'shopwareField' => 'remoteAddress', + ], + 28 => + [ + 'id' => '53fddf437e561', + 'type' => 'node', + 'index' => 28, + 'name' => 'details', + 'shopwareField' => '', + 'children' => [ + 0 => + [ + 'id' => '53ecb9c7d602d', + 'type' => 'leaf', + 'index' => 0, + 'name' => 'orderDetailId', + 'shopwareField' => 'orderDetailId', + ], + 1 => + [ + 'id' => '53ecb9ee6f821', + 'type' => 'leaf', + 'index' => 1, + 'name' => 'articleId', + 'shopwareField' => 'articleId', + ], + 2 => + [ + 'id' => '53ecbaa627334', + 'type' => 'leaf', + 'index' => 2, + 'name' => 'taxId', + 'shopwareField' => 'taxId', + ], + 3 => + [ + 'id' => '53ecba416356a', + 'type' => 'leaf', + 'index' => 3, + 'name' => 'taxRate', + 'shopwareField' => 'taxRate', + ], + 4 => + [ + 'id' => '53ecbaa813093', + 'type' => 'leaf', + 'index' => 4, + 'name' => 'statusId', + 'shopwareField' => 'statusId', + ], + 5 => + [ + 'id' => '53ecbb05eccf1', + 'type' => 'leaf', + 'index' => 5, + 'name' => 'number', + 'shopwareField' => 'number', + ], + 6 => + [ + 'id' => '53ecbb0411d43', + 'type' => 'leaf', + 'index' => 6, + 'name' => 'articleNumber', + 'shopwareField' => 'articleNumber', + ], + 7 => + [ + 'id' => '53ecba19dc9ef', + 'type' => 'leaf', + 'index' => 7, + 'name' => 'price', + 'shopwareField' => 'price', + ], + 8 => + [ + 'id' => '53ecba29e1a37', + 'type' => 'leaf', + 'index' => 8, + 'name' => 'quantity', + 'shopwareField' => 'quantity', + ], + 9 => + [ + 'id' => '53ecba34bf110', + 'type' => 'leaf', + 'index' => 9, + 'name' => 'articleName', + 'shopwareField' => 'articleName', + ], + 10 => + [ + 'id' => '53ecbb07dda54', + 'type' => 'leaf', + 'index' => 10, + 'name' => 'shipped', + 'shopwareField' => 'shipped', + ], + 11 => + [ + 'id' => '53ecbb09bb007', + 'type' => 'leaf', + 'index' => 11, + 'name' => 'shippedGroup', + 'shopwareField' => 'shippedGroup', + ], + 12 => + [ + 'id' => '53ecbbc15479a', + 'type' => 'leaf', + 'index' => 12, + 'name' => 'releaseDate', + 'shopwareField' => 'releasedate', + ], + 13 => + [ + 'id' => '53ecbbc40bcd3', + 'type' => 'leaf', + 'index' => 13, + 'name' => 'mode', + 'shopwareField' => 'mode', + ], + 14 => + [ + 'id' => '53ecbbc57169d', + 'type' => 'leaf', + 'index' => 14, + 'name' => 'esdArticle', + 'shopwareField' => 'esd', + ], + 15 => + [ + 'id' => '53ecbbc6b6f2c', + 'type' => 'leaf', + 'index' => 15, + 'name' => 'config', + 'shopwareField' => 'config', + ] + ] + ] + ]; + } + +} \ No newline at end of file diff --git a/Setup/SwagImportExport/DefaultProfiles/ProfileHelper.php b/Setup/SwagImportExport/DefaultProfiles/ProfileHelper.php new file mode 100644 index 00000000..bd630169 --- /dev/null +++ b/Setup/SwagImportExport/DefaultProfiles/ProfileHelper.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Shopware\Setup\SwagImportExport\DefaultProfiles; + +/** + * Class ProfileHelper + * @package Shopware\Components\SwagImportExport\Profile + */ +class ProfileHelper +{ + /** + * @return ProfileMetaData[] + */ + public static function getProfileInstances() + { + return [ + new MinimalCategoryProfile(), + new CategoryProfile(), + new ArticleCompleteProfile(), + new ArticleProfile(), + new NewsletterRecipientProfile(), + new MinimalArticleProfile(), + new ArticlePriceProfile(), + new ArticleImageUrlProfile(), + new MinimalArticleVariantsProfile(), + new ArticleTranslationProfile(), + new ArticleTranslationUpdateProfile(), + new ArticleCategoriesProfile(), + new ArticleSimilarsProfile(), + new ArticleAccessoryProfile(), + new ArticleInStockProfile(), + new MinimalOrdersProfile(), + new OrderMainDataProfile(), + new ArticlePropertiesProfile(), + new CustomerProfile(), + new ArticleImagesProfile(), + new TranslationProfile(), + new AddressProfile(), + new OrderProfile() + ]; + } +} diff --git a/Setup/SwagImportExport/DefaultProfiles/ProfileMetaData.php b/Setup/SwagImportExport/DefaultProfiles/ProfileMetaData.php index 438dea71..120d826c 100644 --- a/Setup/SwagImportExport/DefaultProfiles/ProfileMetaData.php +++ b/Setup/SwagImportExport/DefaultProfiles/ProfileMetaData.php @@ -22,4 +22,12 @@ public function getAdapter(); * @return string */ public function getName(); + + /** + * Returns a snippet key which is used to deliver a profile explaining + * descriptional text to the backend user. + * + * @return string + */ + public function getDescription(); } diff --git a/Setup/SwagImportExport/DefaultProfiles/TranslationProfile.php b/Setup/SwagImportExport/DefaultProfiles/TranslationProfile.php index ed7949b0..402a4e75 100644 --- a/Setup/SwagImportExport/DefaultProfiles/TranslationProfile.php +++ b/Setup/SwagImportExport/DefaultProfiles/TranslationProfile.php @@ -28,6 +28,14 @@ public function getName() return 'default_system_translations'; } + /** + * @inheritdoc + */ + public function getDescription() + { + return 'default_system_translations_description'; + } + /** * @inheritdoc */ diff --git a/Setup/SwagImportExport/Install/DefaultProfileInstaller.php b/Setup/SwagImportExport/Install/DefaultProfileInstaller.php index 912fd225..57da47c0 100644 --- a/Setup/SwagImportExport/Install/DefaultProfileInstaller.php +++ b/Setup/SwagImportExport/Install/DefaultProfileInstaller.php @@ -9,28 +9,8 @@ namespace Shopware\Setup\SwagImportExport\Install; use Doctrine\DBAL\Connection; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleCompleteProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleTranslationProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\CategoryProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\MinimalArticleProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\MinimalArticleVariantsProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\MinimalCategoryProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\NewsletterRecipientProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleCategoriesProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticlePriceProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleImageUrlProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleSimilarsProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleInStockProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleTranslationUpdateProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\MinimalOrdersProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\OrderMainDataProfile; +use Shopware\Setup\SwagImportExport\DefaultProfiles\ProfileHelper; use Shopware\Setup\SwagImportExport\DefaultProfiles\ProfileMetaData; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleAccessoryProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticlePropertiesProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\CustomerProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\ArticleImagesProfile; -use Shopware\Setup\SwagImportExport\DefaultProfiles\TranslationProfile; use Shopware\Setup\SwagImportExport\SetupContext; /** @@ -66,18 +46,23 @@ public function __construct(SetupContext $setupContext, Connection $connection) */ public function install() { - foreach ($this->getProfiles() as $profile) { - $serializedTree = json_encode($profile); + $sql = ' + INSERT IGNORE INTO s_import_export_profile + (`type`, `name`, `description`, `tree`, `hidden`, `is_default`) + VALUES + (:type, :name, :description, :tree, :hidden, :is_default) + '; + + /** @var ProfileMetaData[] $profiles */ + $profiles = ProfileHelper::getProfileInstances(); - $sql = ' - INSERT IGNORE INTO s_import_export_profile - (`type`, `name`, `tree`, `hidden`, `is_default`) - VALUES - (:type, :name, :tree, :hidden, :is_default)'; + foreach ($profiles as $profile) { + $serializedTree = json_encode($profile); $params = [ 'type' => $profile->getAdapter(), 'name' => $profile->getName(), + 'description' => $profile->getDescription(), 'tree' => $serializedTree, 'hidden' => 0, 'is_default' => 1 @@ -94,34 +79,4 @@ public function isCompatible() { return $this->setupContext->assertMinimumPluginVersion(self::MIN_PLUGIN_VERSION); } - - /** - * @return ProfileMetaData[] - */ - protected function getProfiles() - { - return [ - new MinimalCategoryProfile(), - new CategoryProfile(), - new ArticleCompleteProfile(), - new ArticleProfile(), - new NewsletterRecipientProfile(), - new MinimalArticleProfile(), - new ArticlePriceProfile(), - new ArticleImageUrlProfile(), - new MinimalArticleVariantsProfile(), - new ArticleTranslationProfile(), - new ArticleTranslationUpdateProfile(), - new ArticleCategoriesProfile(), - new ArticleSimilarsProfile(), - new ArticleAccessoryProfile(), - new ArticleInStockProfile(), - new MinimalOrdersProfile(), - new OrderMainDataProfile(), - new ArticlePropertiesProfile(), - new CustomerProfile(), - new ArticleImagesProfile(), - new TranslationProfile() - ]; - } } diff --git a/Setup/SwagImportExport/Update/DefaultProfileUpdater.php b/Setup/SwagImportExport/Update/DefaultProfileUpdater.php new file mode 100644 index 00000000..50c74cb1 --- /dev/null +++ b/Setup/SwagImportExport/Update/DefaultProfileUpdater.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Shopware\Setup\SwagImportExport\Update; + +use Doctrine\DBAL\Connection; +use Shopware\Setup\SwagImportExport\DefaultProfiles\ProfileHelper; +use Shopware\Setup\SwagImportExport\DefaultProfiles\ProfileMetaData; +use Shopware\Setup\SwagImportExport\SetupContext; + +class DefaultProfileUpdater implements UpdaterInterface +{ + const MIN_PLUGIN_VERSION = '2.0.0'; + + /** + * @var Connection + */ + private $connection; + + /** + * @var \Shopware_Components_Snippet_Manager + */ + private $snippetManager; + + /** + * @var SetupContext + */ + private $setupContext; + + /** + * @param SetupContext $setupContext + * @param Connection $connection + * @param \Shopware_Components_Snippet_Manager $snippetManager + */ + public function __construct( + SetupContext $setupContext, + Connection $connection, + \Shopware_Components_Snippet_Manager $snippetManager + ) { + $this->connection = $connection; + $this->snippetManager = $snippetManager; + $this->setupContext = $setupContext; + } + + /** + * Updates the default profiles. + * We won´t update unique profile names and types. + * Only changes to the profile tree should + * be made and make sense. + */ + public function update() + { + $sql = ' + UPDATE s_import_export_profile + SET `tree` = :tree, `description` = :description + WHERE `name` = :name + '; + + /** @var ProfileMetaData[] $profiles */ + $profiles = ProfileHelper::getProfileInstances(); + + foreach ($profiles as $profile) { + $serializedTree = json_encode($profile); + + $params = [ + 'tree' => $serializedTree, + 'name' => $profile->getName(), + 'description' => $profile->getDescription() + ]; + + $this->connection->executeQuery($sql, $params); + } + } + + /** + * @inheritdoc + */ + public function isCompatible() + { + return $this->setupContext->assertMinimumPluginVersion(self::MIN_PLUGIN_VERSION); + } +} diff --git a/Setup/SwagImportExport/Update/Update03DefaultProfileSupport.php b/Setup/SwagImportExport/Update/Update03DefaultProfileSupport.php index 1fe8aec8..12d166ff 100644 --- a/Setup/SwagImportExport/Update/Update03DefaultProfileSupport.php +++ b/Setup/SwagImportExport/Update/Update03DefaultProfileSupport.php @@ -56,9 +56,6 @@ public function update() { try { $this->connection->executeQuery('ALTER TABLE s_import_export_profile ADD UNIQUE (`name`);'); - - $defaultProfileInstaller = new DefaultProfileInstaller($this->setupContext, $this->connection); - $defaultProfileInstaller->install(); } catch (DBALException $exception) { if (!$this->isDuplicateNameError($exception)) { throw $exception; diff --git a/Setup/SwagImportExport/Update/Update04CreateColumns.php b/Setup/SwagImportExport/Update/Update04CreateColumns.php new file mode 100644 index 00000000..a74950ca --- /dev/null +++ b/Setup/SwagImportExport/Update/Update04CreateColumns.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Shopware\Setup\SwagImportExport\Update; + +use Doctrine\DBAL\Connection; +use Shopware\Setup\SwagImportExport\SetupContext; + +class Update04CreateColumns implements UpdaterInterface +{ + const MAX_PLUGIN_VERSION = '2.0.2'; + + /** @var SetupContext */ + private $setupContext; + + /** @var Connection */ + private $connection; + + /** + * @param SetupContext $setupContext + * @param Connection $connection + */ + public function __construct(SetupContext $setupContext, Connection $connection) + { + $this->setupContext = $setupContext; + $this->connection = $connection; + } + + /** + * @inheritdoc + */ + public function update() + { + try { + $this->connection->exec('ALTER TABLE s_import_export_profile ADD COLUMN is_default int(1)'); + } catch (\Exception $e) { + } + + try { + $this->connection->exec('ALTER TABLE s_import_export_profile ADD COLUMN description text'); + } catch (\Exception $e) { + } + + try { + $this->connection->executeQuery('ALTER TABLE s_import_export_profile ADD COLUMN base_profile int'); + } catch (\Exception $e) { + } + } + + /** + * @inheritdoc + */ + public function isCompatible() + { + return version_compare($this->setupContext->getPreviousPluginVersion(), self::MAX_PLUGIN_VERSION, '<'); + } +} diff --git a/Snippets/backend/swag_import_export/controller.ini b/Snippets/backend/swag_import_export/controller.ini index b98719e6..d1a931c1 100644 --- a/Snippets/backend/swag_import_export/controller.ini +++ b/Snippets/backend/swag_import_export/controller.ini @@ -38,6 +38,9 @@ swag_import_export/profile/profile_import_no_data_error = "The uploaded file has swag_import_export/profile/profile_import_no_valid_data_error = "The uploaded profile data does not contain all required fields." swag_import_export/profile/profile_import_error = "The profile could not be imported. Please check the dataset." swag_import_export/profile/profile_import_duplicate_error = "Profile import error. A profile with the same name already exists." +swag_import_export/profile/new_column = "New column" +swag_import_export/profile/iterator/no_extension_title = "No extension available" +swag_import_export/profile/iterator/no_extension_message = "There is no extension for this profile available." [de_DE] swag_import_export/profile/add_attribute/failure_title = "Attribut konnte nicht erzeugt werden" @@ -78,4 +81,7 @@ swag_import_export/profile/profile_import_no_json_error = "Die hochgeladene Date swag_import_export/profile/profile_import_no_data_error = "Die hochgeladene Datei enthält keine Daten." swag_import_export/profile/profile_import_no_valid_data_error = "Die hochgeladenen Profildaten enthalten nicht alle benötigten Felder." swag_import_export/profile/profile_import_error = "Das Profil konnte nicht importiert werden. Bitte überprüfen Sie Ihren Datensatz." -swag_import_export/profile/profile_import_duplicate_error = "Profilimport fehlgeschlagen. Ein Profil mit demnselben Namen existiert bereits." \ No newline at end of file +swag_import_export/profile/profile_import_duplicate_error = "Profilimport fehlgeschlagen. Ein Profil mit demnselben Namen existiert bereits." +swag_import_export/profile/new_column = "Neue Spalte" +swag_import_export/profile/iterator/no_extension_title = "Keine Erweiterung verfügbar" +swag_import_export/profile/iterator/no_extension_message = "Für dieses Profil ist keine Erweiterung verfügbar." \ No newline at end of file diff --git a/Snippets/backend/swag_import_export/default_profiles.ini b/Snippets/backend/swag_import_export/default_profiles.ini index e675b2d2..0712f78f 100644 --- a/Snippets/backend/swag_import_export/default_profiles.ini +++ b/Snippets/backend/swag_import_export/default_profiles.ini @@ -1,25 +1,50 @@ [en_GB] default_categories = "Categories" +default_categories_description = "This profile allows to create or to update categories. It does not delete categories." default_articles = "Articles" +default_articles_description = "This profile contains all relevant fields for article import. It also includes useful detail fields. It is not possible to create graduation prices." default_article_prices = "Article prices" +default_article_prices_description = "This profile allows to update article prices." default_categories_minimal = "Categories minimal" +default_categories_minimal_description = "This profile contains all required fields for creating new categories." default_articles_complete = "Articles complete" +default_articles_complete_description = "This profile contains all dataset extensions to create articles (translations, categories, accessories etc.). It is not possible to create graduation prices." default_newsletter_recipient = "Newsletter recipients" +default_newsletter_recipient_description = "This profile allows to create or update newsletter recipients. Removal is not possible." default_article_images_url = "Article images via URL" +default_article_images_url_description = "This profile allows to add images to existing articles by URL." default_article_variants_minimal = "Article variants minimal" +default_article_variants_minimal_description = "This profile contains the minimium amount of fields for creating new variant articles." default_articles_minimal = "Articles minimal" +default_articles_minimal_description = "This profile contains the minimum amount of fields to create new articles. It is not possible to create graduation prices." default_article_translations = "Article translations" +default_article_translations_description = "This is the default profile for article translations. It contains all translatable article fields and can be extended with translatable attributes." default_article_translations_update = "Add translations to article" +default_article_translations_update_description = "This profile allows to add basic translations to existing articles." default_article_categories = "Article categories" +default_article_categories_description = "This profile allows to add further categories to existing articles." default_similar_articles = "Article similars" +default_similar_articles_description = "This profile can be used to add a similar article to an exisiting article." default_article_accessories = "Article accessories" +default_article_accessories_description = "With this profile articles can be created and connected as article accessories." default_article_in_stock = "Article in stock" +default_article_in_stock_description = "This profile allows to change the stock amount of existing articles." default_orders_minimal = "Orders minimal" +default_orders_minimal_description = "This profile allows to update the status of an existing order." default_order_main_data = "Orders Main Data" +default_order_main_data_description = "This profile allows to export order data. This profile is just for export." +default_orders = "Orders" +default_orders_description = "This profile allows to update the status of an existing order and contains all extra fields." default_article_properties = "Add article properties" +default_article_properties_description = "This profile allows to update properties of existing articles." default_customers = "Customers" +default_customers_description = "This profile can be used to create or update customer data. It is not possible to delete customers with this profile." default_article_images = "Article images profile" +default_article_images_description = "This profile allows to add images to existing articles. It allows to add image information." default_system_translations = "System translations" +default_addresses = "Customer addresses" +default_addresses_description = "This profile allows to create or update customer addresses." +default_system_translations_description = "This profile allows to update selected system translations." update/duplicate_names = "You have profiles with duplicate names. Every profile must have an unique name." type/categories = "Categories" type/articles = "Articles" @@ -34,26 +59,51 @@ type/translations = "Translations" [de_DE] default_categories = "Kategorien" +default_categories_description = "Dieses Profil ermöglicht das Erstellen oder Aktualisieren von Kategorien. Es wird keine Löschung durchgeführt." default_articles = "Artikel" +default_articles_description = "Dieses Profil dient zur Anlage neuer Artikel. Es enthält neben allen Pflichtfeldern einige sinnvolle Felder für Details. Es ist nicht möglich Staffelpreise anzulegen." default_articles_complete = "Artikel komplett" -default_article_prices = Artikelpreise +default_articles_complete_description = "Dieses Profil befasst sämtliche Datensatzerweiterungen zur Anlage von Artikeln (Übersetzungen, Kategorien, Zubehörartikel etc.). Es ist nicht möglich Staffelpreise anzulegen." +default_article_prices = "Artikelpreise" +default_article_prices_description = "Dieses Profil ermöglicht es Artikelpreise anzupassen." default_categories_minimal = "Kategorien minimal" +default_categories_minimal_description = "Dieses Profil enthält alle Pflichtfelder zur Anlage neuer Kategorien." default_newsletter_recipient = "Newsletter-Empfänger" +default_newsletter_recipient_description = "Dieses Profil dient zur Neuanlage oder Aktualisierung von Newsletter-Empfängern. Eine Löschung von Datensätzen ist nicht möglich." default_articles_minimal = "Artikel minimal" +default_articles_minimal_description = "Dieses Profil enthält die minimal benötigten Felder zur Anlage neuer Artikel. Es ist nicht möglich Staffelpreise anzulegen." default_article_images_url = "Artikelbilder über URL" +default_article_images_url_description = "Dieses Profil ermöglicht das hinzufügen von Bildern zu bestehenden Artikeln über eine URL." default_article_variants_minimal = "Artikelvarianten minimal" +default_article_variants_minimal_description = "Dieses Profil enthält die minimale Anzahl Felder zur Neuanlage eines Variantenartikels." default_article_translations = "Artikelübersetzungen" +default_article_translations_description = "Dies ist das Standard Profil für Artikel Übersetzungen. Es enthält alle im Standard übersetzbaren Artikelfelder. Zusätzlich können noch übersetzbare Attributsfelder hinzugefügt werden, wenn diese in den Grundeinstellungen definiert sind." default_article_translations_update = "Übersetzungen zu Artikel hinzufügen" +default_article_translations_update_description = "Dieses Profil dient dazu bei einem bestehenden Artikel grundlegende Übersetzungen hinzuzufügen." default_article_categories = "Artikel Kategorien" +default_article_categories_description = "Mit diesem Profil ist es möglich bestehenden Artikeln weitere Kategorien zuzuweisen." default_similar_articles = "Ähnliche Artikel" -default_article_accessories = "Artikel Zubehör" +default_similar_articles_description = "Dieses Profil kann verwendet werden, wenn einem bestehenden Artikel, ein bestehender ähnlicher Artikel zugewiesen werden soll." +default_article_accessories = "Zubehörartikel" +default_article_accessories_description = "Mit Hilfe dieses Profils lassen sich beim Import Artikel erstellen und als Zubehörartikel miteinander verknüpfen." default_article_in_stock = "Artikel Lagerbestand" +default_article_in_stock_description = "Mit diesem Profil ist es möglich den Lagerbestand eines bestehenden Artikels anzupassen." default_orders_minimal = "Bestellungen minimal" +default_orders_minimal_description = "Dieses Profil ermöglicht den Statusupdate von bestehenden Bestellungen." default_order_main_data = "Bestellungen Main Data" +default_order_main_data_description = "Dieses Profil dient dem Export von Bestelldaten. Es ist ein reines Export-Profil." +default_orders = "Bestellungen" +default_orders_description = "Dieses Profil ermöglicht ein Statusupdate von Bestellungen durchzuführen und befasst zusätzlich extra Felder zur Info." default_article_properties = "Artikel Eigenschaften hinzufügen" +default_article_properties_description = "Dieses Profil dient dazu Eigenschaften bei einem bestehenden Artikel zu aktualisieren." default_customers = "Kunden" +default_customers_description = "Dieses Profil dient der Anlage oder der Aktualisierung von Kundendaten. Es ist nicht möglich über dieses Profil zu löschen." default_article_images = "Artikelbilder" +default_article_images_description = "Mit diesem Profil ist es möglich Bilder zu bestehenden Artikeln hinzuzufügen. Außerdem können Bildinformationen gesetzt werden." default_system_translations = "System-Übersetzungen" +default_addresses = "Kundenadressen" +default_addresses_description = "Dieses Profil dient zur Erstellung und Aktualisierung von Kundenadressen." +default_system_translations_description = "Dieses Profil dient zur Übersetzung von bestimmten Systemeigenschaften." update/duplicate_names = "Sie haben Profile mit doppelten Namen. Jedes Profil muss einen eindeutigen Namen haben." type/categories = "Kategorien" type/articles = "Artikel" diff --git a/Snippets/backend/swag_import_export/view/main.ini b/Snippets/backend/swag_import_export/view/main.ini index e7daffef..a368c417 100644 --- a/Snippets/backend/swag_import_export/view/main.ini +++ b/Snippets/backend/swag_import_export/view/main.ini @@ -4,6 +4,7 @@ date_to = "Date to" order_number_From = "Ordernumber from" order_state = "Order state" payment_state = "Payment state" +swag_import_export/profile/no_data = "No profiles found" swag_import_export/action/delete = "Delete file" swag_import_export/action/download = "Download file" swag_import_export/action/resume = "Resume operation" @@ -14,6 +15,8 @@ swag_import_export/column/records = "Records" swag_import_export/column/status = "Status" swag_import_export/column/totalCount = "Total count" swag_import_export/column/type = "Type" +swag_import_export/export/error = "Export error" +swag_import_export/export/error_occured = "An error occured" swag_import_export/export/error_msg = "Please select export configuration" swag_import_export/export/error_title = "Swag import export" swag_import_export/export/export_button = "Start export" @@ -32,6 +35,7 @@ swag_import_export/export/variants = "Export variants" swag_import_export/export/window_title = "Export window" swag_import_export/export/category = "Category" swag_import_export/import/close = "Close" +swag_import_export/import/error = "Import error" swag_import_export/import/error_msg_file = "No file was selected" swag_import_export/import/error_msg_profle = "Please select a profile" swag_import_export/import/error_title = "Swag import export" @@ -40,6 +44,9 @@ swag_import_export/import/finished = "Importing finished successfully. " swag_import_export/import/process = "Importing... " swag_import_export/import/start = "Start importing" swag_import_export/import/window_title = "Import window" +swag_import_export/import/unprocessed = "Start importing dataset extensions." +swag_import_export/import/extension_import_error = "Extension import error" +swag_import_export/manager/hide_default_profiles = "Hide default profiles" swag_import_export/manager/export/title = "Export" swag_import_export/manager/import/import_button = "Start import" swag_import_export/manager/import/import_description = "With file import, you are able to extract information from CSV and XML documents and save it in your database using profiles. These profiles contain information about which data is imported along with its structure. The default profiles can be individually extended and modified with custom profiles in the profiles menu." @@ -85,6 +92,7 @@ date_to = "Datum bis" order_number_From = "Bestellnummer von" order_state = "Bestellstatus" payment_state = "Zahlungsstatus" +swag_import_export/profile/no_data = "Keine Profile gefunden" swag_import_export/action/delete = "Datei löschen" swag_import_export/action/download = "Datei herunterladen" swag_import_export/action/resume = "Fortsetzen" @@ -95,6 +103,8 @@ swag_import_export/column/records = "Datensätze" swag_import_export/column/status = "Status" swag_import_export/column/totalCount = "Anzahl" swag_import_export/column/type = "Typ" +swag_import_export/export/error_occured = "Fehler aufgetreten" +swag_import_export/export/error = "Fehler beim Export" swag_import_export/export/error_msg = "Exportkonfiguration wählen" swag_import_export/export/error_title = "ImportExport" swag_import_export/export/export_button = "Export starten" @@ -113,6 +123,7 @@ swag_import_export/export/variants = "Varianten exportieren" swag_import_export/export/window_title = "Exportieren" swag_import_export/export/category = "Kategorie" swag_import_export/import/close = "Schließen" +swag_import_export/import/error = "Fehler beim Import" swag_import_export/import/error_msg_file = "Keine Datei gewählt" swag_import_export/import/error_msg_profle = "Bitte wählen Sie ein Profil" swag_import_export/import/error_title = "ImportExport" @@ -121,6 +132,9 @@ swag_import_export/import/finished = "Import erfolgreich abgeschlossen. " swag_import_export/import/process = "Importiere... " swag_import_export/import/start = "Import starten" swag_import_export/import/window_title = "Importieren" +swag_import_export/import/unprocessed = "Starte Import von Datensatzerweiterungen." +swag_import_export/import/extension_import_error = "Fehler bei Import von Datensatzerweiterung" +swag_import_export/manager/hide_default_profiles = "Standardprofile ausblenden" swag_import_export/manager/export/title = "Export" swag_import_export/manager/import/import_button = "Import starten" swag_import_export/manager/import/import_description = "Beim Dateiimport werden Informationen aus CSV- und XML-Dokumenten mit Hilfe von Profilen in die Datenbank importiert. Die Profile beschreiben dabei, welche Daten importiert und wo diese angeordnet werden. Im Profile-Menü können die Standardprofile individuell durch eigene Profile erweitert und modifiziert werden." diff --git a/Snippets/backend/swag_import_export/view/profile.ini b/Snippets/backend/swag_import_export/view/profile.ini index 82abd795..3bfda407 100644 --- a/Snippets/backend/swag_import_export/view/profile.ini +++ b/Snippets/backend/swag_import_export/view/profile.ini @@ -6,21 +6,23 @@ swag_import_export/profile/profile/toolbar/duplicate_profile = "Duplicate Select swag_import_export/profile/profile/toolbar/empty_text = "Select Profile..." swag_import_export/profile/profile/toolbar/rename_profile = "Rename Selected Profile" swag_import_export/profile/profile/toolbar/show_conversions = "Show Conversions" -swag_import_export/profile/profile/add_column = "Add column" +swag_import_export/profile/profile/add_column = "Add field" swag_import_export/profile/profile/add_entry = "Add entry" swag_import_export/profile/profile/add_attribute = "Add attribute" swag_import_export/profile/profile/remove_item = "Remove selected item" -adapter = "Adapter" +swag_import_export/profile/new_column = "New field" +adapter = "Extension" delete = "delete" -newAttribute = "New attribute" -newIterationNode = "New iteration node" +newAttribute = "New attribute (XML)" +newIterationNode = "Extend dataset" newNode = "New node" -nodeName = "Node name" +nodeName = "Fieldname" parentKey = "Parent key" save = "Save" close = "Close" -selectColumn = "Select column" -shopwareColumn = "Shopware column" +selectColumn = "Select field" +selectExtension = "Select extension" +shopwareColumn = "Database mapping" rename_profile = "Rename profile" profile_name = "Profile name" defaultValue = "Default value" @@ -33,21 +35,23 @@ swag_import_export/profile/profile/toolbar/duplicate_profile = "Profil duplizier swag_import_export/profile/profile/toolbar/empty_text = "Profil wählen..." swag_import_export/profile/profile/toolbar/rename_profile = "Profil umbenennen" swag_import_export/profile/profile/toolbar/show_conversions = "Konvertierungen bearbeiten" -swag_import_export/profile/profile/add_column = "Spalte hinzufügen" +swag_import_export/profile/profile/add_column = "Feld hinzufügen" swag_import_export/profile/profile/add_entry = "Eintrag hinzufügen" swag_import_export/profile/profile/add_attribute = "Eigenschaft hinzufügen" swag_import_export/profile/profile/remove_item = "Ausgewählten Punkt entfernen" -adapter = "Adapter" +swag_import_export/profile/new_column = "Neues Feld" +adapter = "Erweiterung" delete = "löschen" -newAttribute = "Neues Attribut" -newIterationNode = "Neuer Iterator" +newAttribute = "Neues Attribut (XML)" +newIterationNode = "Datensatz erweitern" newNode = "Neuer Knoten" -nodeName = "Knoten-Name" +nodeName = "Feldname" parentKey = "Eltern-Schlüssel" save = "Speichern" close = "Schließen" -selectColumn = "Spalte wählen" -shopwareColumn = "Shopware-Spalte" +selectColumn = "Feld wählen" +selectExtension = "Erweiterung wählen" +shopwareColumn = "Datenbank-Mapping" rename_profile = "Profil umbenennen" profile_name = "Porifil-Name" defaultValue = "Standardwert" \ No newline at end of file diff --git a/Snippets/backend/swag_import_export/view/profile/column.ini b/Snippets/backend/swag_import_export/view/profile/column.ini new file mode 100644 index 00000000..4cda8156 --- /dev/null +++ b/Snippets/backend/swag_import_export/view/profile/column.ini @@ -0,0 +1,17 @@ +[en_GB] +swag_import_export/profile/column/title = "Add field" +swag_import_export/profile/column/node_name = "Name" +swag_import_export/profile/column/shopware_column = "Database mapping" +swag_import_export/profile/column/select_column = "Select field" +swag_import_export/profile/column/close = "Close" +swag_import_export/profile/column/save = "Save" +swag_import_export/profile/column/default_value = "Default value" + +[de_DE] +swag_import_export/profile/column/title = "Feld hinzufügen" +swag_import_export/profile/column/node_name = "Name" +swag_import_export/profile/column/shopware_column = "Datenbank-Mapping" +swag_import_export/profile/column/select_column = "Feld auswählen" +swag_import_export/profile/column/close = "Schließen" +swag_import_export/profile/column/save = "Speichern" +swag_import_export/profile/column/default_value = "Standardwert" \ No newline at end of file diff --git a/Snippets/backend/swag_import_export/view/profile/iterator.ini b/Snippets/backend/swag_import_export/view/profile/iterator.ini new file mode 100644 index 00000000..5147dfd7 --- /dev/null +++ b/Snippets/backend/swag_import_export/view/profile/iterator.ini @@ -0,0 +1,27 @@ +[en_GB] +swag_import_export/profile/iterator/title = "Extend dataset" +swag_import_export/profile/iterator/close = "Close" +swag_import_export/profile/iterator/save = "Save" +swag_import_export/profile/iterator/node_name = "Name" +swag_import_export/profile/iterator/adapter = "Extend by" +swag_import_export/profile/iterator/select_adapter = "Select extension" +swag_import_export/profile/iterator/parent_key = "Parent key" +swag_import_export/profile/iterator/select_parent_key = "Select parent key" +swag_import_export/profile/iterator/grid_title = "Select fields" +swag_import_export/profile/iterator/grid_column_column = "Database mapping" +swag_import_export/profile/iterator/grid_column_name = "Fieldname" +swag_import_export/profile/iterator/grid_column_selected = "Selected" + +[de_DE] +swag_import_export/profile/iterator/title = "Datensatz erweitern" +swag_import_export/profile/iterator/close = "Schließen" +swag_import_export/profile/iterator/save = "Speichern" +swag_import_export/profile/iterator/node_name = "Name" +swag_import_export/profile/iterator/adapter = "Erweitern durch" +swag_import_export/profile/iterator/select_adapter = "Erweiterung auswählen" +swag_import_export/profile/iterator/parent_key = "Elternschlüssel" +swag_import_export/profile/iterator/select_parent_key = "Elternschlüssel wählen" +swag_import_export/profile/iterator/grid_title = "Felder auswählen" +swag_import_export/profile/iterator/grid_column_column = "Datenbank-Mapping" +swag_import_export/profile/iterator/grid_column_name = "Feldname" +swag_import_export/profile/iterator/grid_column_selected = "Übernehmen" \ No newline at end of file diff --git a/Snippets/backend/swag_import_export/view/profile/window.ini b/Snippets/backend/swag_import_export/view/profile/window.ini index 98518c99..f011ae95 100644 --- a/Snippets/backend/swag_import_export/view/profile/window.ini +++ b/Snippets/backend/swag_import_export/view/profile/window.ini @@ -5,8 +5,8 @@ swag_import_export/profile/window/add_new = "Add new" swag_import_export/profile/window/export_conversion = "Export conversion" swag_import_export/profile/window/import_conversion = "Import conversion" swag_import_export/profile/window/save = "Save" -swag_import_export/profile/window/select_column = "Select column" -swag_import_export/profile/window/shopware_field = "Shopware field" +swag_import_export/profile/window/select_column = "Select field" +swag_import_export/profile/window/shopware_field = "Field" swag_import_export/profile/window/conversion = "Conversions" swag_import_export/profile/window/title = "Profile settings" swag_import_export/profile/window/field_name = "Profile name" @@ -23,8 +23,8 @@ swag_import_export/profile/window/add_new = "Hinzufügen" swag_import_export/profile/window/export_conversion = "Export-Umwandlung" swag_import_export/profile/window/import_conversion = "Import-Umwandlung" swag_import_export/profile/window/save = "Speichern" -swag_import_export/profile/window/select_column = "Spalte wählen" -swag_import_export/profile/window/shopware_field = "Shopware-Feld" +swag_import_export/profile/window/select_column = "Feld wählen" +swag_import_export/profile/window/shopware_field = "Feld" swag_import_export/profile/window/conversion = "Konvertierungen" swag_import_export/profile/window/title = "Profileinstellungen" swag_import_export/profile/window/field_name = "Profilname" diff --git a/Snippets/backend/swag_importexport/main.ini b/Snippets/backend/swag_importexport/main.ini index 83a589e4..d771f700 100644 --- a/Snippets/backend/swag_importexport/main.ini +++ b/Snippets/backend/swag_importexport/main.ini @@ -38,7 +38,6 @@ adapters/articles/config_set_not_found = "A configurator set has to be defined o adapters/articles/property_group_name_not_found = "There is no property group name specified for article %s" adapters/articles/property_id_not_found = "Property value by id %s not found for article %s" adapters/articles/property_option_required = "A property option needs to be given for each property value for article %s" -adapters/articles/property_id_or_name_required = "Article %s requires name or id for property value" adapters/articles/image_not_found = "Image with name %s could not be found" adapters/articles/category_duplicated = "Category with name '%s' is duplicated" adapters/articles/category_not_leaf = "Category with id '%s' is not a leaf" @@ -109,6 +108,15 @@ adpaters/categories/id_required = "Category id is required. If you don't import transformers/used_colon = "A colon is used in the group name (':'). Please delete it and try again." adapters/articlesInStock/no_records = "No article stock records were found." validators/wrong_type = "%s field has to be %s!" +adapters/address/firstname_required = "Field firstname is required. Record: %s" +adapters/address/lastname_required = "Field lastname is required. Record: %s" +adapters/address/zipcode_required = "Field zipcode is required. Record: %s" +adapters/address/city_required = "Field city is required. Record: %s" +adapters/address/country_id_required = "Field countryID is required. Record: %s" +adapters/address/cant_identify_customer = "Couldn't associate customer. Email and customernumber or userID is required. Record: %s" +adapters/address/no_records = "Could not find address records." +adapters/address/customer_not_found = "Could not find customer. Email: %s, Customernumber: %s, userID: %s" +adapters/address/state_not_found = "State not found with stateID %s" [de_DE] adapters/ordernumber_required = "Bestellnummer erforderlich." @@ -150,7 +158,6 @@ adapters/articles/config_set_not_found = "Für den Artikel %s muss ein Konfigura adapters/articles/property_group_name_not_found = "Es ist kein Eigenschaftsgruppenname für den Artikel %s festgelegt." adapters/articles/property_id_not_found = "Der Eigenschaftswert mit der ID %s für den Artikel %s wurde nicht gefunden." adapters/articles/property_option_required = "Für jeden Eigenschaftswert des Artikels %s muss einen Eigenschaftsoption angegeben werden." -adapters/articles/property_id_or_name_required = "Artikel %s benötigt einen Namen oder eine ID für den Eigenschaftswert." adapters/articles/image_not_found = "Bild mit dem Namen %s konnte nicht gefunden werden." adapters/articles/category_duplicated = "Die Kategorie mit dem Namen %s ist doppelt." adapters/articles/category_not_leaf = "Die Kategorie mit der ID %s ist kein Blatt." @@ -222,3 +229,12 @@ transformers/used_colon = "Konfigurator-Gruppenname darf kein Doppelpunkt enthal adapters/articlesInStock/no_records = "Es wurden keine Artikellagerbestände gefunden." validators/wrong_type = "%s Feld muss %s sein!" adapters/translations/language_not_found = "Language id ist zwingend erforderlich." +adapters/address/firstname_required = "Firstname ist ein Pflichtfeld. Datensatz: %s" +adapters/address/lastname_required = "Lastname ist ein Pflichtfeld. Datensatz: %s" +adapters/address/zipcode_required = "Zipcode ist ein Pflichtfeld. Datensatz: %s" +adapters/address/city_required = "City ist ein Pflichtfeld. Datensatz: %s" +adapters/address/country_id_required = "CountryID ist ein Pflichtfeld. Datensatz: %s" +adapters/address/cant_identify_customer = "Kunde konnte nicht zugeordnet werden. Email und customernumber oder userID ist nötig. Datensatz: %s" +adapters/address/no_records = "Es konnten keine Address-Datensätze gefunden werden." +adapters/address/customer_not_found = "Konnte Kunden nicht finden. Email: %s, Customernumber: %s, userID: %s" +adapters/address/state_not_found = "Bundesland wurde nicht gefunden mit stateID: %s" diff --git a/Tests/Functional/Components/SwagImportExport/DbAdapters/AddressDbAdapterTest.php b/Tests/Functional/Components/SwagImportExport/DbAdapters/AddressDbAdapterTest.php new file mode 100644 index 00000000..0072898a --- /dev/null +++ b/Tests/Functional/Components/SwagImportExport/DbAdapters/AddressDbAdapterTest.php @@ -0,0 +1,460 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagImportExport\Tests\Functional\Components\SwagImportExport\DbAdapters; + +use Doctrine\DBAL\Connection; +use Shopware\Components\SwagImportExport\DbAdapters\AddressDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\DataDbAdapter; +use Shopware\Components\SwagImportExport\Exception\AdapterException; +use Shopware\Components\SwagImportExport\Validators\AddressValidator; +use SwagImportExport\Tests\Helper\DatabaseTestCaseTrait; + +class AddressDbAdapterTest extends \PHPUnit_Framework_TestCase +{ + use DatabaseTestCaseTrait; + + const NO_START = 0; + const NO_LIMIT = 0; + const NO_FILTER = ''; + const COUNTRY_ID_USA = 28; + const CUSTOMER_ID = 1; + const EXISTING_ADDRESS = 3; + const NOT_EXISTING_USERID = 999999; + const STATE_ID_ALABAMA = 20; + + private function createAddressDbAdapter() + { + return new AddressDbAdapter(); + } + + public function test_it_can_be_created() + { + $addressDbAdapter = $this->createAddressDbAdapter(); + + $this->assertInstanceOf(AddressDbAdapter::class, $addressDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $addressDbAdapter); + } + + public function test_readRecordIds_should_return_ids() + { + $allAddressIdsInDatabase = [1, 2, 3, 4]; + $addressDbAdapter = $this->createAddressDbAdapter(); + + $addressIds = $addressDbAdapter->readRecordIds(self::NO_START, self::NO_LIMIT, self::NO_FILTER); + + $this->assertEquals($allAddressIdsInDatabase, $addressIds); + } + + public function test_readRecordIds_with_start_should_return_two_ids() + { + $fetchedAmountOfIds = 2; + $firstResult = 2; + $addressDbAdapter = $this->createAddressDbAdapter(); + + $addressIds = $addressDbAdapter->readRecordIds($firstResult, self::NO_LIMIT, self::NO_FILTER); + + $this->assertCount($fetchedAmountOfIds, $addressIds); + } + + public function test_readRecordIds_with_limit_should_return_two_ids() + { + $fetchedAmountOfIds = 2; + $limit = 2; + $addressDbAdapter = $this->createAddressDbAdapter(); + + $addressIds = $addressDbAdapter->readRecordIds(self::NO_START, $limit, self::NO_FILTER); + + $this->assertCount($fetchedAmountOfIds, $addressIds); + } + + public function test_read_should_return_addresses_by_ids_and_select_given_columns() + { + $addressIdsToFetch = [1, 2]; + $selectedColumns = ['address.company', 'address.firstname', 'address.lastname', 'customer.email']; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addresses = $addressDbAdapter->read($addressIdsToFetch, $selectedColumns); + + $addresses = $addresses['address']; + $this->assertEquals('Max', $addresses[0]['firstname']); + $this->assertEquals('Mustermann', $addresses[0]['lastname']); + $this->assertEquals('Muster GmbH', $addresses[0]['company']); + $this->assertEquals('test@example.com', $addresses[0]['email']); + $this->assertCount(2, $addresses); + } + + public function test_read_should_return_attributes() + { + $connection = Shopware()->Container()->get('dbal_connection'); + $connection->executeQuery(file_get_contents(__DIR__ . '/_fixtures/address_attribute_demo.sql')); + + $addressIdsToFetch = [1]; + $selectedColumns = ['attribute.text1', 'attribute.text2']; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addresses = $addressDbAdapter->read($addressIdsToFetch, $selectedColumns); + + $addresses = $addresses['address']; + $this->assertEquals('Attr value', $addresses[0]['text1']); + } + + public function test_write_should_create_new_address_with_all_required_fields() + { + $addresses = [ + 'address' => [ + [ + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'userID' => self::CUSTOMER_ID + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addressDbAdapter->write($addresses); + + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $createdAddresses = $connection->executeQuery('SELECT * FROM s_user_addresses WHERE firstname="My firstname"')->fetchAll(); + + $this->assertAddress($createdAddresses); + } + + public function test_write_should_identify_customer_by_email_and_customernumber() + { + $addresses = [ + 'address' => [ + [ + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'email' => 'test@example.com', + 'customernumber' => '20001' + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addressDbAdapter->write($addresses); + + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $createdAddresses = $connection->executeQuery('SELECT * FROM s_user_addresses WHERE firstname="My firstname"')->fetchAll(); + + $this->assertAddress($createdAddresses); + } + + public function test_write_should_identify_customer_by_email_and_customernumber_if_an_invalid_id_was_given() + { + $addresses = [ + 'address' => [ + [ + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'userID' => 999999, + 'email' => 'test@example.com', + 'customernumber' => '20001' + ] + ] + ]; + + $addressesDbAdapter = $this->createAddressDbAdapter(); + $addressesDbAdapter->write($addresses); + + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $createdAddresses = $connection->executeQuery('SELECT * FROM s_user_addresses WHERE firstname="My firstname"')->fetchAll(); + + $this->assertAddress($createdAddresses); + } + + public function test_write_should_update_existing_address() + { + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $demoSQL = file_get_contents(__DIR__ . '/_fixtures/address_demo.sql'); + $connection->executeQuery($demoSQL)->execute(); + + $updatedAddressId = $connection->lastInsertId(); + + $addresses = [ + 'address' => [ + [ + 'id' => $updatedAddressId, + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'userID' => self::CUSTOMER_ID + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addressDbAdapter->write($addresses); + + $createdAddresses = $connection->executeQuery( + 'SELECT * FROM s_user_addresses WHERE id=?', + [$updatedAddressId] + )->fetchAll(); + + $this->assertAddress($createdAddresses); + } + + public function test_write_should_import_vatId() + { + $addresses = [ + 'address' => [ + [ + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'userID' => self::CUSTOMER_ID, + 'vatId' => 'My VatId' + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addressDbAdapter->write($addresses); + + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $createdAddresses = $connection->executeQuery('SELECT * FROM s_user_addresses WHERE firstname="My firstname"')->fetchAll(); + + $this->assertAddress($createdAddresses); + $this->assertEquals('My VatId', $createdAddresses[0]['ustid']); + } + + public function test_write_should_import_additionalAddressLines() + { + $addresses = [ + 'address' => [ + [ + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'userID' => self::CUSTOMER_ID, + 'additionalAddressLine1' => 'My additional address', + 'additionalAddressLine2' => 'My additional address2' + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addressDbAdapter->write($addresses); + + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $createdAddresses = $connection->executeQuery('SELECT * FROM s_user_addresses WHERE firstname="My firstname"')->fetchAll(); + + $this->assertAddress($createdAddresses); + $this->assertEquals('My additional address', $createdAddresses[0]['additional_address_line1']); + $this->assertEquals('My additional address2', $createdAddresses[0]['additional_address_line2']); + } + + public function test_write_should_import_attributes() + { + $addresses = [ + 'address' => [ + [ + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'userID' => self::CUSTOMER_ID, + 'attributeText1' => 'text1', + 'attributeText2' => 'text2' + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addressDbAdapter->write($addresses); + + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $addressId = $connection->executeQuery('SELECT id FROM s_user_addresses WHERE firstname="My firstname"')->fetchColumn(); + $createdAttribute = $connection->executeQuery("SELECT * FROM s_user_addresses_attributes WHERE address_id={$addressId}")->fetchAll(); + + $this->assertEquals('text1', $createdAttribute[0]['text1']); + $this->assertEquals('text2', $createdAttribute[0]['text2']); + } + + public function test_write_should_create_address_with_given_id() + { + $addresses = [ + 'address' => [ + [ + 'id' => 99999, + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'userID' => self::CUSTOMER_ID, + 'attributeText1' => 'text1', + 'attributeText2' => 'text2' + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addressDbAdapter->write($addresses); + + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $addressId = $connection->executeQuery('SELECT id FROM s_user_addresses WHERE firstname="My firstname"')->fetchColumn(); + + $this->assertEquals(99999, $addressId); + } + + public function test_getColumns_should_get_all_required_columns() + { + $addressDbAdapter = $this->createAddressDbAdapter(); + $columns = $addressDbAdapter->getColumns(); + + $this->assertTrue(in_array('address.id as id', $columns, true)); + $this->assertTrue(in_array('address.company as company', $columns, true)); + $this->assertTrue(in_array('address.firstname as firstname', $columns, true)); + $this->assertTrue(in_array('address.lastname as lastname', $columns, true)); + $this->assertTrue(in_array('address.street as street', $columns, true)); + $this->assertTrue(in_array('address.city as city', $columns, true)); + $this->assertTrue(in_array('address.zipcode as zipcode', $columns, true)); + $this->assertTrue(in_array('address.zipcode as zipcode', $columns, true)); + + $this->assertTrue(in_array('country.id as countryID', $columns, true)); + $this->assertTrue(in_array('state.id as stateID', $columns, true)); + + $this->assertTrue(in_array('customer.email as email', $columns, true)); + $this->assertTrue(in_array('customer.number as customernumber', $columns, true)); + $this->assertTrue(in_array('customer.id as userID', $columns, true)); + } + + public function test_getColumns_should_get_attribute_columns() + { + $addressDbAdapter = $this->createAddressDbAdapter(); + $columns = $addressDbAdapter->getColumns(); + + $this->assertTrue(in_array('attribute.text1 as attributeText1', $columns, true)); + $this->assertTrue(in_array('attribute.text2 as attributeText2', $columns, true)); + } + + public function test_write_should_throw_exception_if_no_addresses_were_given() + { + $addressDbAdapter = $this->createAddressDbAdapter(); + + $this->expectException(\Exception::class); + $addressDbAdapter->write([]); + } + + public function test_write_should_throw_exception_if_customer_does_not_eixst() + { + $addresses = [ + 'address' => [ + [ + 'userID' => self::NOT_EXISTING_USERID, + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Konnte Kunden nicht finden. Email: , Customernumber: , userID: 999999'); + $addressDbAdapter->write($addresses); + } + + public function test_write_should_update_state() + { + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $connection->executeQuery(file_get_contents(__DIR__ . '/_fixtures/address_with_state_demo.sql')); + $addressId = $connection->lastInsertId(); + + $addresses = [ + 'address' => [ + [ + 'id' => $addressId, + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'stateID' => self::STATE_ID_ALABAMA, + 'userID' => self::CUSTOMER_ID + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + $addressDbAdapter->write($addresses); + + /** @var Connection $connection */ + $connection = Shopware()->Container()->get('dbal_connection'); + $updateAddress = $connection->executeQuery("SELECT * FROM s_user_addresses WHERE id={$addressId}")->fetchAll(); + + $this->assertEquals(self::STATE_ID_ALABAMA, $updateAddress[0]['state_id']); + } + + public function test_write_should_throw_exception_if_stateID_was_not_found() + { + $addresses = [ + 'address' => [ + [ + 'firstname' => 'My firstname', + 'lastname' => 'My lastname', + 'zipcode' => '12345', + 'city' => 'My city', + 'countryID' => self::COUNTRY_ID_USA, + 'stateID' => 99999, + 'userID' => self::CUSTOMER_ID + ] + ] + ]; + + $addressDbAdapter = $this->createAddressDbAdapter(); + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Bundesland wurde nicht gefunden mit stateID: 99999'); + $addressDbAdapter->write($addresses); + } + + /** + * @param array $createdAddresses + */ + private function assertAddress($createdAddresses) + { + $this->assertEquals('My firstname', $createdAddresses[0]['firstname']); + $this->assertEquals('My lastname', $createdAddresses[0]['lastname']); + $this->assertEquals('12345', $createdAddresses[0]['zipcode']); + $this->assertEquals('My city', $createdAddresses[0]['city']); + $this->assertEquals(self::COUNTRY_ID_USA, $createdAddresses[0]['country_id']); + $this->assertEquals(self::CUSTOMER_ID, $createdAddresses[0]['user_id']); + } +} diff --git a/Tests/Functional/Components/SwagImportExport/DbAdapters/Articles/PropertyWriterTest.php b/Tests/Functional/Components/SwagImportExport/DbAdapters/Articles/PropertyWriterTest.php index 9ae15146..7ebef050 100644 --- a/Tests/Functional/Components/SwagImportExport/DbAdapters/Articles/PropertyWriterTest.php +++ b/Tests/Functional/Components/SwagImportExport/DbAdapters/Articles/PropertyWriterTest.php @@ -82,23 +82,6 @@ public function test_write_should_not_create_new_group_with_existing_article_and $this->assertEmpty($importedFilter, "Filter groups will only be created if a new product will be created."); } - public function test_write_should_throw_an_exception_with_empty_property_value_name() - { - $propertyWriter = $this->createPropertyWriterAdapter(); - $importData = [ - 'articleId' => self::ARTICLE_ID_WITH_PROPERTIES, - 'propertyGroupName' => self::EXISTING_FILTER_GROUP_NAME, - 'propertyGroupId' => self::NOT_EXISTING_FILTER_GROUP_ID - ]; - - $this->expectException(\Exception::class); - $propertyWriter->writeUpdateCreatePropertyGroupsFilterAndValues( - self::ARTICLE_ID_WITH_PROPERTIES, - self::ARTICLE_ORDERNUMBER, - $importData - ); - } - public function test_write_should_update_group_relations() { $propertyWriter = $this->createPropertyWriterAdapter(); @@ -156,26 +139,6 @@ public function test_write_should_create_value() $this->assertEquals(self::NOT_EXISTING_VALUE_NAME, $createdPropertyValue, 'Could not create property value.'); } - public function test_write_should_throw_exception_with_empty_property_value_name() - { - $propertyWriter = $this->createPropertyWriterAdapter(); - $importData = [ - [ - 'articleId' => self::ARTICLE_ID_WITHOUT_PROPERTIES, - 'propertyGroupName' => self::EXISTING_FILTER_GROUP_NAME, - 'propertyValueName' => '', - 'propertyOptionName' => self::NOT_EXISTING_OPTION_NAME - ] - ]; - - $this->expectException(\Exception::class); - $propertyWriter->writeUpdateCreatePropertyGroupsFilterAndValues( - self::ARTICLE_ID_WITHOUT_PROPERTIES, - self::ARTICLE_ORDERNUMBER_WITHOUT_PROPERTIES, - $importData - ); - } - public function test_write_should_create_option() { $propertyWriter = $this->createPropertyWriterAdapter(); diff --git a/Tests/Functional/Components/SwagImportExport/DbAdapters/NewsletterDbAdapterTest.php b/Tests/Functional/Components/SwagImportExport/DbAdapters/NewsletterDbAdapterTest.php index 450dfe41..b5c6c824 100644 --- a/Tests/Functional/Components/SwagImportExport/DbAdapters/NewsletterDbAdapterTest.php +++ b/Tests/Functional/Components/SwagImportExport/DbAdapters/NewsletterDbAdapterTest.php @@ -33,6 +33,27 @@ public function test_write_throws_exception_if_records_are_empty() $newsletterDbAdapter->write([]); } + public function test_should_add_customer_as_newsletter_recipient() + { + $newsletterDbAdapter = $this->createNewsletterAdapter(); + $customerData = [ + 'default' => [ + [ + 'email' => 'test@example.com', + 'userID' => 1 + ] + ] + ]; + + $newsletterDbAdapter->write($customerData); + + /** @var Connection $dbalConnection */ + $dbalConnection = Shopware()->Container()->get('dbal_connection'); + $createdRecipient = $dbalConnection->executeQuery('SELECT * FROM s_campaigns_mailaddresses WHERE email="test@example.com"')->fetchAll(); + + $this->assertEquals($customerData['default'][0]['email'], $createdRecipient[0]['email']); + } + public function test_write_should_create_newsletter_recipient() { $newsletterDbAdapter = $this->createNewsletterAdapter(); diff --git a/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_attribute_demo.sql b/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_attribute_demo.sql new file mode 100644 index 00000000..30af5e00 --- /dev/null +++ b/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_attribute_demo.sql @@ -0,0 +1 @@ +INSERT INTO s_user_addresses_attributes (address_id, text1) VALUES (1, 'Attr value'); \ No newline at end of file diff --git a/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_demo.sql b/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_demo.sql new file mode 100644 index 00000000..33491162 --- /dev/null +++ b/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_demo.sql @@ -0,0 +1 @@ +INSERT INTO s_user_addresses (user_id, company, department, salutation, title, firstname, lastname, street, zipcode, city, country_id, state_id, ustid, phone, additional_address_line1, additional_address_line2) VALUES (1, null, null, 'mr', null, 'Firstname before update', 'Lastname before update', 'Street before update', '54321 before update', 'City before update', 2, null, null, null, null, null); \ No newline at end of file diff --git a/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_with_state_demo.sql b/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_with_state_demo.sql new file mode 100644 index 00000000..55f7809f --- /dev/null +++ b/Tests/Functional/Components/SwagImportExport/DbAdapters/_fixtures/address_with_state_demo.sql @@ -0,0 +1 @@ +INSERT INTO s_user_addresses (user_id, company, department, salutation, title, firstname, lastname, street, zipcode, city, country_id, state_id, ustid, phone, additional_address_line1, additional_address_line2) VALUES (1, null, null, 'mr', null, 'Firstname before update', 'Lastname before update', 'Street before update', '54321 before update', 'City before update', 28, 21, null, null, null, null); \ No newline at end of file diff --git a/Tests/Functional/Components/SwagImportExport/Factories/DataFactoryTest.php b/Tests/Functional/Components/SwagImportExport/Factories/DataFactoryTest.php new file mode 100644 index 00000000..19949d6a --- /dev/null +++ b/Tests/Functional/Components/SwagImportExport/Factories/DataFactoryTest.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Shopware\Components\SwagImportExport\Functional\Components\SwagImportExport\Factories; + +use Shopware\Components\SwagImportExport\DbAdapters\AddressDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesImagesDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesInStockDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\ArticlesPricesDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\CategoriesDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\CustomerDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\DataDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\MainOrdersDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\NewsletterDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\OrdersDbAdapter; +use Shopware\Components\SwagImportExport\DbAdapters\TranslationsDbAdapter; +use Shopware\Components\SwagImportExport\Factories\DataFactory; + +class DataFactoryTest extends \PHPUnit_Framework_TestCase +{ + private function createDataFactory() + { + return new TestableDataFactory(); + } + + public function test_createDbAdapter_should_create_AddressDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $addressDbAdapter = $dataFactory->createDbAdapter('addresses'); + + $this->assertInstanceOf(AddressDbAdapter::class, $addressDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $addressDbAdapter); + } + + public function test_createDbAdapter_should_create_CategoriesDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $categoriesDbAdapter = $dataFactory->createDbAdapter('categories'); + + $this->assertInstanceOf(CategoriesDbAdapter::class, $categoriesDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $categoriesDbAdapter); + } + + public function test_createDbAdapter_should_create_ArticlesDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $articlesDbAdapter = $dataFactory->createDbAdapter('articles'); + + $this->assertInstanceOf(ArticlesDbAdapter::class, $articlesDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $articlesDbAdapter); + } + + public function test_createDbAdapter_should_create_ArticlesInstockDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $articlesInstockDbAdapter = $dataFactory->createDbAdapter('articlesInStock'); + + $this->assertInstanceOf(ArticlesInStockDbAdapter::class, $articlesInstockDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $articlesInstockDbAdapter); + } + + public function test_createDbAdapter_should_create_ArticlesPricesDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $articlesPricesDbAdapter = $dataFactory->createDbAdapter('articlesPrices'); + + $this->assertInstanceOf(ArticlesPricesDbAdapter::class, $articlesPricesDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $articlesPricesDbAdapter); + } + + public function test_createDbAdapter_should_create_OrdersDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $ordersDbAdapter = $dataFactory->createDbAdapter('orders'); + + $this->assertInstanceOf(OrdersDbAdapter::class, $ordersDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $ordersDbAdapter); + } + + public function test_createDbAdapter_should_create_MainOrderDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $mainOrdersDbAdapter = $dataFactory->createDbAdapter('mainOrders'); + + $this->assertInstanceOf(MainOrdersDbAdapter::class, $mainOrdersDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $mainOrdersDbAdapter); + } + + public function test_createDbAdapter_should_create_CustomerDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $customerDbAdapter = $dataFactory->createDbAdapter('customers'); + + $this->assertInstanceOf(CustomerDbAdapter::class, $customerDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $customerDbAdapter); + } + + public function test_createDbAdapter_should_create_NewsletterDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $newsletterDbAdapter = $dataFactory->createDbAdapter('newsletter'); + + $this->assertInstanceOf(NewsletterDbAdapter::class, $newsletterDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $newsletterDbAdapter); + } + + public function test_createDbAdapter_should_create_TranslationsDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $translationsDbAdapter = $dataFactory->createDbAdapter('translations'); + + $this->assertInstanceOf(TranslationsDbAdapter::class, $translationsDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $translationsDbAdapter); + } + + public function test_createDbAdapter_should_create_ArticlesImagesDbAdapter() + { + $dataFactory = $this->createDataFactory(); + + $articlesImagesDbAdapter = $dataFactory->createDbAdapter('articlesImages'); + + $this->assertInstanceOf(ArticlesImagesDbAdapter::class, $articlesImagesDbAdapter); + $this->assertInstanceOf(DataDbAdapter::class, $articlesImagesDbAdapter); + } +} + +class TestableDataFactory extends DataFactory +{ + public function __construct() + { + } +} diff --git a/Tests/Functional/Components/SwagImportExport/Validators/AddressValidatorTest.php b/Tests/Functional/Components/SwagImportExport/Validators/AddressValidatorTest.php new file mode 100644 index 00000000..26200fb2 --- /dev/null +++ b/Tests/Functional/Components/SwagImportExport/Validators/AddressValidatorTest.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagImportExport\Tests\Functional\Components\SwagImportExport\Validators; + +use Shopware\Components\SwagImportExport\Exception\AdapterException; +use Shopware\Components\SwagImportExport\Validators\AddressValidator; +use Shopware\Components\SwagImportExport\Validators\Validator; +use Shopware\Models\Customer\Address; + +class AddressValidatorTest extends \PHPUnit_Framework_TestCase +{ + const DONT_UPDATE_ADDRESS = false; + + public function test_it_can_be_created() + { + $addressValidator = new AddressValidator(); + + $this->assertInstanceOf(AddressValidator::class, $addressValidator); + $this->assertInstanceOf(Validator::class, $addressValidator); + } + + public function test_checkRquieredFields_should_throw_exception_if_address_is_empty() + { + $emptyAddressRecord = []; + + $addressValidator = new AddressValidator(); + + $this->expectException(AdapterException::class); + $this->expectExceptionMessage('Es konnten keine Address-Datensätze gefunden werden.'); + $addressValidator->checkRequiredFields($emptyAddressRecord, self::DONT_UPDATE_ADDRESS); + } + + public function test_checkRequiredFields_should_throw_exception_if_required_field_is_empty() + { + $emptyAddressRecord = [ + 'userID' => 999, + 'firstname' => '', + 'lastname' => 'lastname' + ]; + + $addressValidator = new AddressValidator(); + + $this->expectException(AdapterException::class); + $this->expectExceptionMessage('Firstname ist ein Pflichtfeld. Datensatz: userID: 999, firstname: - , lastname: lastname'); + $addressValidator->checkRequiredFields($emptyAddressRecord, self::DONT_UPDATE_ADDRESS); + } + + public function test_checkRequiredFields_should_throw_exception_if_customer_could_not_be_identified() + { + $addressWithoutCustomerId = [ + 'firstname' => 'some value', + 'lastname' => 'some value', + 'zipcode' => 'some value', + 'city' => 'some value', + 'countryID' => '1' + ]; + + $addressValidator = new AddressValidator(); + + $this->expectException(AdapterException::class); + $this->expectExceptionMessage('Kunde konnte nicht zugeordnet werden. Email und customernumber oder userID ist nötig. Datensatz: firstname: some value,'); + $addressValidator->checkRequiredFields($addressWithoutCustomerId, self::DONT_UPDATE_ADDRESS); + } + + public function test_checkRequiredFields_should_throw_exception_if_address_has_no_email_but_customernumber_is_given() + { + $addressWithoutEmail = [ + 'firstname' => 'some value', + 'lastname' => 'some value', + 'zipcode' => 'some value', + 'city' => 'some value', + 'countryID' => 'some value', + 'customernumber' => '1' + ]; + + $addressValidator = new AddressValidator(); + + $this->expectException(AdapterException::class); + $this->expectExceptionMessage('Kunde konnte nicht zugeordnet werden. Email und customernumber oder userID ist nötig. Datensatz: firstname: some value'); + $addressValidator->checkRequiredFields($addressWithoutEmail, self::DONT_UPDATE_ADDRESS); + } + + public function test_checkRequiredFields_should_throw_exception_if_address_has_customernumber_but_email_is_given() + { + $addressWithoutCustomernumber = [ + 'firstname' => 'some value', + 'lastname' => 'some value', + 'zipcode' => 'some value', + 'city' => 'some value', + 'countryID' => 'some value', + 'email' => 'test@example.org' + ]; + + $addressValidator = new AddressValidator(); + + $this->expectException(AdapterException::class); + $this->expectExceptionMessage('Kunde konnte nicht zugeordnet werden. Email und customernumber oder userID ist nötig. Datensatz: firstname: some value'); + $addressValidator->checkRequiredFields($addressWithoutCustomernumber, self::DONT_UPDATE_ADDRESS); + } +} diff --git a/Tests/Functional/Controllers/Backend/SwagImportExport/AddressExportTest.php b/Tests/Functional/Controllers/Backend/SwagImportExport/AddressExportTest.php new file mode 100644 index 00000000..f37421c7 --- /dev/null +++ b/Tests/Functional/Controllers/Backend/SwagImportExport/AddressExportTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagImportExport\Tests\Functional\Controllers\Backend\SwagImportExport; + +use Shopware\Components\Model\ModelManager; +use Shopware\CustomModels\ImportExport\Profile; +use SwagImportExport\Tests\Helper\DatabaseTestCaseTrait; +use SwagImportExport\Tests\Helper\ExportControllerTrait; + +class AddressExportTest extends \Enlight_Components_Test_Controller_TestCase +{ + use DatabaseTestCaseTrait; + use ExportControllerTrait; + + public function setUp() + { + parent::setUp(); + + Shopware()->Plugins()->Backend()->Auth()->setNoAuth(); + Shopware()->Plugins()->Backend()->Auth()->setNoAcl(); + } + + public function test_address_export_with_xml() + { + $params = $this->getExportRequestParams(); + + /** @var ModelManager $modelManager */ + $modelManager = Shopware()->Container()->get('models'); + $repo = $modelManager->getRepository(Profile::class); + $profile = $repo->findOneBy(['name' => 'default_addresses']); + + $params['profileId'] = $profile->getId(); + $params['format'] = 'xml'; + + $this->Request()->setParams($params); + $this->dispatch('backend/SwagImportExportExport/export'); + + $assigned = $this->View()->getAssign('data'); + + $fileName = $assigned['fileName']; + $file = $this->uploadPathProvider->getRealPath($fileName); + + $this->assertFileExists($file); + $this->backendControllerTestHelper->addFile($file); + + $company = $this->queryXpath($file, "//address[company='Muster GmbH']/company"); + $this->assertEquals('Muster GmbH', $company->item(0)->nodeValue); + + $company = $this->queryXpath($file, "//address[company='Muster GmbH']/firstname"); + $this->assertEquals('Max', $company->item(0)->nodeValue); + } + + public function test_address_export_with_csv() + { + $params = $this->getExportRequestParams(); + + /** @var ModelManager $modelManager */ + $modelManager = Shopware()->Container()->get('models'); + $repo = $modelManager->getRepository(Profile::class); + $profile = $repo->findOneBy(['name' => 'default_addresses']); + + $params['profileId'] = $profile->getId(); + $params['format'] = 'csv'; + $this->Request()->setParams($params); + + $this->dispatch('backend/SwagImportExportExport/export'); + $assigned = $this->View()->getAssign('data'); + + $fileName = $assigned['fileName']; + $file = $this->uploadPathProvider->getRealPath($fileName); + + $this->assertFileExists($file); + $this->backendControllerTestHelper->addFile($file); + + $exportedAddresses = $this->csvToArrayIndexedByFieldValue($file, 'id'); + + $this->assertEquals($exportedAddresses[1]['company'], 'Muster GmbH'); + $this->assertEquals($exportedAddresses[1]['firstname'], 'Max'); + $this->assertEquals($exportedAddresses[1]['lastname'], 'Mustermann'); + } +} diff --git a/Tests/Helper/DataProvider/ProfileDataProvider.php b/Tests/Helper/DataProvider/ProfileDataProvider.php index 5f0ce51c..7bad370a 100644 --- a/Tests/Helper/DataProvider/ProfileDataProvider.php +++ b/Tests/Helper/DataProvider/ProfileDataProvider.php @@ -42,7 +42,7 @@ class ProfileDataProvider const MAIN_ORDERS_PROFILE_TYPE = 'mainOrders'; const MAIN_ORDERS_PROFILE_NAME = 'main_order_profile'; - const IMPORT_MAIN_ORDER_PROFILE_NAME = 'order_profile'; + const IMPORT_MAIN_ORDER_PROFILE_NAME = 'import_main_order_profile'; const TRANSLATIONS_PROFILE_TYPE = 'translations'; const TRANSLATIONS_PROFILE_NAME = 'translation_profile'; diff --git a/Tests/Integration/DefaultProfiles/Import/AddressProfileTest.php b/Tests/Integration/DefaultProfiles/Import/AddressProfileTest.php new file mode 100644 index 00000000..9b18d763 --- /dev/null +++ b/Tests/Integration/DefaultProfiles/Import/AddressProfileTest.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagImportExport\Tests\Integration\DefaultProfiles\Import; + +use SwagImportExport\Tests\Helper\CommandTestCaseTrait; +use SwagImportExport\Tests\Helper\DatabaseTestCaseTrait; +use SwagImportExport\Tests\Integration\DefaultProfiles\DefaultProfileImportTestCaseTrait; + +class AddressProfileTest extends \PHPUnit_Framework_TestCase +{ + use DatabaseTestCaseTrait; + use CommandTestCaseTrait; + use DefaultProfileImportTestCaseTrait; + + public function test_should_import_new_addresses() + { + $file = __DIR__ . '/_fixtures/addresses_profile_create.csv'; + $this->runCommand("sw:importexport:import -p default_addresses {$file}"); + + $createdAddress = $this->executeQuery('SELECT * FROM s_user_addresses WHERE company="A Company Ltd."'); + + $this->assertEquals('Department X', $createdAddress[0]['department']); + $this->assertEquals('MyUstId', $createdAddress[0]['ustid']); + $this->assertEquals('My City', $createdAddress[0]['city']); + $this->assertEquals('Firstname', $createdAddress[0]['firstname']); + $this->assertEquals('Lastname', $createdAddress[0]['lastname']); + $this->assertEquals('ms', $createdAddress[0]['salutation']); + $this->assertEquals('My phonenumber', $createdAddress[0]['phone']); + $this->assertEquals('My additional address', $createdAddress[0]['additional_address_line1']); + } + + public function test_should_update_existing_addresses_by_id() + { + $file = __DIR__ . '/_fixtures/addresses_profile_update.csv'; + $this->runCommand("sw:importexport:import -p default_addresses {$file}"); + + $updatedAddress = $this->executeQuery('SELECT * FROM s_user_addresses WHERE company="Updated company"'); + + $this->assertEquals(2, $updatedAddress[0]['id']); + $this->assertEquals('Updated department', $updatedAddress[0]['department']); + $this->assertEquals('Updated firstname', $updatedAddress[0]['firstname']); + $this->assertEquals('Updated lastname', $updatedAddress[0]['lastname']); + $this->assertEquals('Updated city', $updatedAddress[0]['city']); + $this->assertEquals('Updated vatid', $updatedAddress[0]['ustid']); + $this->assertEquals('Updated salutation', $updatedAddress[0]['salutation']); + $this->assertEquals('Updated telephone', $updatedAddress[0]['phone']); + $this->assertEquals('Updated additional address', $updatedAddress[0]['additional_address_line1']); + } +} diff --git a/Tests/Integration/DefaultProfiles/Import/ArticlePriceProfileTest.php b/Tests/Integration/DefaultProfiles/Import/ArticlePriceProfileTest.php index 3e1631bd..b05ae14f 100644 --- a/Tests/Integration/DefaultProfiles/Import/ArticlePriceProfileTest.php +++ b/Tests/Integration/DefaultProfiles/Import/ArticlePriceProfileTest.php @@ -22,6 +22,7 @@ public function test_import_should_update_article_price() { $filePath = __DIR__ . "/_fixtures/article_price_profile.csv"; $createdArticleOrderNumber = "SW10003"; + $expectedPurchasePrice = 7.95; $expectedArticlePrice = 8.3613445378151; $this->runCommand("sw:import:import -p default_article_prices {$filePath}"); @@ -29,6 +30,7 @@ public function test_import_should_update_article_price() $updatedArticle = $this->executeQuery("SELECT * FROM s_articles_details WHERE ordernumber='{$createdArticleOrderNumber}'"); $updatedArticlePrice = $this->executeQuery("SELECT * FROM s_articles_prices WHERE articleID='{$updatedArticle[0]["articleID"]}'"); + $this->assertEquals($expectedPurchasePrice, $updatedArticle[0]['purchaseprice']); $this->assertEquals($expectedArticlePrice, $updatedArticlePrice[0]["price"]); } diff --git a/Tests/Integration/DefaultProfiles/Import/OrderProfileTest.php b/Tests/Integration/DefaultProfiles/Import/OrderProfileTest.php new file mode 100644 index 00000000..532fd259 --- /dev/null +++ b/Tests/Integration/DefaultProfiles/Import/OrderProfileTest.php @@ -0,0 +1,33 @@ + +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +namespace SwagImportExport\Tests\Integration\DefaultProfiles\Import; + +use SwagImportExport\Tests\Helper\CommandTestCaseTrait; +use SwagImportExport\Tests\Helper\DatabaseTestCaseTrait; +use SwagImportExport\Tests\Integration\DefaultProfiles\DefaultProfileImportTestCaseTrait; + +class OrderProfileTest extends \PHPUnit_Framework_TestCase +{ + use DatabaseTestCaseTrait; + use CommandTestCaseTrait; + use DefaultProfileImportTestCaseTrait; + + public function test_write_should_update_order_status() + { + $filePath = __DIR__ . "/_fixtures/order_profile.csv"; + $expectedOrderId = 15; + $expectedOrderStatus = 1; + + $this->runCommand("sw:import:import -p default_orders {$filePath}"); + + $updatedOrder = $this->executeQuery("SELECT * FROM s_order WHERE id='{$expectedOrderId}'"); + + $this->assertEquals($expectedOrderStatus, $updatedOrder[0]["status"]); + } +} \ No newline at end of file diff --git a/Tests/Integration/DefaultProfiles/Import/_fixtures/addresses_profile_create.csv b/Tests/Integration/DefaultProfiles/Import/_fixtures/addresses_profile_create.csv new file mode 100644 index 00000000..15c6f713 --- /dev/null +++ b/Tests/Integration/DefaultProfiles/Import/_fixtures/addresses_profile_create.csv @@ -0,0 +1,3 @@ +userID;email;customernumber;company;department;salutation;title;firstname;lastname;street;zipcode;city;countryID;stateID;vatID;phone;additionalAddressLine1;additionalAddressLine2 +1;test@example.com;20001;;;mr;Doctor;Max;Mustermann;Different Street;12345;Some City;28;20;An UstId;;; +2;mustermann@b2b.de;20003;A Company Ltd.;Department X;ms;;Firstname;Lastname;My Street;54321;My City;2;;MyUstId;My phonenumber;My additional address; diff --git a/Tests/Integration/DefaultProfiles/Import/_fixtures/addresses_profile_update.csv b/Tests/Integration/DefaultProfiles/Import/_fixtures/addresses_profile_update.csv new file mode 100644 index 00000000..5dd12af4 --- /dev/null +++ b/Tests/Integration/DefaultProfiles/Import/_fixtures/addresses_profile_update.csv @@ -0,0 +1,2 @@ +id;userID;company;department;salutation;title;firstname;lastname;street;zipcode;city;countryID;stateID;vatID;phone;additionalAddressLine1;additionalAddressLine2 +2;2;Updated company;Updated department;Updated salutation;;Updated firstname;Updated lastname;Updated street;Updated zipcode;Updated city;2;3;Updated vatid;Updated telephone;Updated additional address; \ No newline at end of file diff --git a/Tests/Integration/DefaultProfiles/Import/_fixtures/article_price_profile.csv b/Tests/Integration/DefaultProfiles/Import/_fixtures/article_price_profile.csv index cbb6de96..7d9e4a60 100644 --- a/Tests/Integration/DefaultProfiles/Import/_fixtures/article_price_profile.csv +++ b/Tests/Integration/DefaultProfiles/Import/_fixtures/article_price_profile.csv @@ -1,2 +1,2 @@ -ordernumber;price;pricegroup;from;pseudoprice;baseprice;_name;_additionaltext;_supplier +ordernumber;price;pricegroup;from;pseudoprice;purchaseprice;_name;_additionaltext;_supplier SW10003;9,95;EK;1;15,95;7,95;Münsterländer Aperitif 16%;;Feinbrennerei Sasse diff --git a/Tests/Integration/DefaultProfiles/Import/_fixtures/order_profile.csv b/Tests/Integration/DefaultProfiles/Import/_fixtures/order_profile.csv new file mode 100644 index 00000000..60537e85 --- /dev/null +++ b/Tests/Integration/DefaultProfiles/Import/_fixtures/order_profile.csv @@ -0,0 +1,4 @@ +orderId;number;customerId;orderStatusID;cleared;paymentID;dispatchId;partnerId;shopId;invoiceAmount;invoiceAmountNet;invoiceShipping;invoiceShippingNet;orderTime;transactionId;comment;customerComment;internalComment;net;taxFree;temporaryId;referer;clearedDate;trackingCode;languageIso;currency;currencyFactor;remoteAddress;orderDetailId;articleId;taxId;taxRate;statusId;number;articleNumber;price;quantity;articleName;shipped;shippedGroup;releaseDate;mode;esdArticle;config +15;20001;2;1;17;4;9;;1;998.56;839.13;0;0;2012-08-30 10:15:54;;;;;1;0;;;;;1;EUR;1;217.86.205.141;42;197;1;19;0;20001;SW10196;836.134;1;ESD Download Artikel;0;0;0000-00-00;0;1; +15;20001;2;1;17;4;9;;1;998.56;839.13;0;0;2012-08-30 10:15:54;;;;;1;0;;;;;1;EUR;1;217.86.205.141;43;0;0;19;0;20001;SHIPPINGDISCOUNT;-2;1;Warenkorbrabatt;0;0;0000-00-00;4;0; +15;20001;2;1;17;4;9;;1;998.56;839.13;0;0;2012-08-30 10:15:54;;;;;1;0;;;;;1;EUR;1;217.86.205.141;44;0;0;19;0;20001;sw-payment-absolute;5;1;Zuschlag für Zahlungsart;0;0;0000-00-00;4;0; diff --git a/Tests/Unit/Setup/DefaultProfiles/AddressProfileTest.php b/Tests/Unit/Setup/DefaultProfiles/AddressProfileTest.php new file mode 100644 index 00000000..814ab2c9 --- /dev/null +++ b/Tests/Unit/Setup/DefaultProfiles/AddressProfileTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagImportExport\Unit\Setup\DefaultProfiles; + +use Shopware\Setup\SwagImportExport\DefaultProfiles\AddressProfile; +use Shopware\Setup\SwagImportExport\DefaultProfiles\ProfileMetaData; +use SwagImportExport\Tests\Unit\Setup\DefaultProfiles\DefaultProfileTestCaseTrait; + +class AddressProfileTest extends \PHPUnit_Framework_TestCase +{ + use DefaultProfileTestCaseTrait; + + public function test_it_can_be_created() + { + $addressProfile = new AddressProfile(); + $this->assertInstanceOf(AddressProfile::class, $addressProfile); + $this->assertInstanceOf(ProfileMetaData::class, $addressProfile); + $this->assertInstanceOf(\JsonSerializable::class, $addressProfile); + } + + public function test_it_should_return_valid_profile_tree() + { + $addressProfile = new AddressProfile(); + + $profileTree = $addressProfile->jsonSerialize(); + $this->walkRecursive($profileTree, function ($node) { + $this->assertArrayHasKey('id', $node, "Current array: " . print_r($node, true)); + $this->assertArrayHasKey('type', $node, "Current array: " . print_r($node, true)); + $this->assertArrayHasKey('name', $node, "Current array: " . print_r($node, true)); + }); + + + $profileJson = json_encode($addressProfile); + $this->assertJson($profileJson); + } +} diff --git a/Tests/Unit/Setup/DefaultProfiles/ArticleCategoriesProfileTest.php b/Tests/Unit/Setup/DefaultProfiles/ArticleCategoriesProfileTest.php index 68c555bd..b023dded 100644 --- a/Tests/Unit/Setup/DefaultProfiles/ArticleCategoriesProfileTest.php +++ b/Tests/Unit/Setup/DefaultProfiles/ArticleCategoriesProfileTest.php @@ -40,7 +40,7 @@ public function test_it_should_return_valid_profile_tree() $this->assertArrayHasKey('type', $node, "Current array: " . print_r($node, true)); }); - $profileJson = json_encode($categoryProfile->jsonSerialize()); + $profileJson = json_encode($categoryProfile); $this->assertJson($profileJson); } -} \ No newline at end of file +} diff --git a/Tests/Unit/Setup/DefaultProfiles/ArticleTranslationUpdateProfileTest.php b/Tests/Unit/Setup/DefaultProfiles/ArticleTranslationUpdateProfileTest.php index bfb21f53..ae0bccc3 100644 --- a/Tests/Unit/Setup/DefaultProfiles/ArticleTranslationUpdateProfileTest.php +++ b/Tests/Unit/Setup/DefaultProfiles/ArticleTranslationUpdateProfileTest.php @@ -40,7 +40,6 @@ public function test_it_should_return_valid_profile_tree() $this->assertArrayHasKey('id', $node, 'Current array: ' . print_r($node, true)); $this->assertArrayHasKey('name', $node, 'Current array: ' . print_r($node, true)); $this->assertArrayHasKey('type', $node, 'Current array: ' . print_r($node, true)); - }); } } diff --git a/Tests/Unit/Setup/DefaultProfiles/CategoryProfileTest.php b/Tests/Unit/Setup/DefaultProfiles/CategoryProfileTest.php index e8685bd5..63fc1cd3 100644 --- a/Tests/Unit/Setup/DefaultProfiles/CategoryProfileTest.php +++ b/Tests/Unit/Setup/DefaultProfiles/CategoryProfileTest.php @@ -43,7 +43,7 @@ public function test_it_should_return_valid_profile_tree() $this->assertArrayHasKey('type', $node, "Current array: " . print_r($node, true)); }); - $profileJson = json_encode($categoryProfile->jsonSerialize()); + $profileJson = json_encode($categoryProfile); $this->assertJson($profileJson); } } diff --git a/Tests/Unit/Setup/DefaultProfiles/CustomerProfileTest.php b/Tests/Unit/Setup/DefaultProfiles/CustomerProfileTest.php index 5074062f..d2896b05 100644 --- a/Tests/Unit/Setup/DefaultProfiles/CustomerProfileTest.php +++ b/Tests/Unit/Setup/DefaultProfiles/CustomerProfileTest.php @@ -43,7 +43,7 @@ public function test_it_should_return_valid_profile_tree() $this->assertArrayHasKey('type', $node, "Current array: " . print_r($node, true)); }); - $profileJson = json_encode($categoryProfile->jsonSerialize()); + $profileJson = json_encode($categoryProfile); $this->assertJson($profileJson); } -} \ No newline at end of file +} diff --git a/Tests/Unit/Setup/DefaultProfiles/MinimalArticleProfileTest.php b/Tests/Unit/Setup/DefaultProfiles/MinimalArticleProfileTest.php index f468969b..efd37ed3 100644 --- a/Tests/Unit/Setup/DefaultProfiles/MinimalArticleProfileTest.php +++ b/Tests/Unit/Setup/DefaultProfiles/MinimalArticleProfileTest.php @@ -37,13 +37,13 @@ public function test_it_should_return_valid_profile_tree() $minimalArticleProfile = $this->getMinimalArticleProfile(); $profileTree = $minimalArticleProfile->jsonSerialize(); - $this->walkRecursive($profileTree, function($node) { + $this->walkRecursive($profileTree, function ($node) { $this->assertArrayHasKey('id', $node, "Current array: " . print_r($node, true)); $this->assertArrayHasKey('type', $node, "Current array: " . print_r($node, true)); $this->assertArrayHasKey('name', $node, "Current array: " . print_r($node, true)); }); - $profileJson = json_encode($minimalArticleProfile->jsonSerialize()); + $profileJson = json_encode($minimalArticleProfile); $this->assertJson($profileJson); } -} \ No newline at end of file +} diff --git a/Tests/Unit/Setup/DefaultProfiles/MinimalCategoryProfileTest.php b/Tests/Unit/Setup/DefaultProfiles/MinimalCategoryProfileTest.php index 895dafbb..198ec98b 100644 --- a/Tests/Unit/Setup/DefaultProfiles/MinimalCategoryProfileTest.php +++ b/Tests/Unit/Setup/DefaultProfiles/MinimalCategoryProfileTest.php @@ -40,7 +40,7 @@ public function test_it_should_return_valid_profile_tree() $this->assertArrayHasKey('name', $node, "Current array: " . print_r($node, true)); }); - $profileJson = json_encode($minimalCategoryProfile->jsonSerialize()); + $profileJson = json_encode($minimalCategoryProfile); $this->assertJson($profileJson); } } diff --git a/Views/backend/swag_import_export/app.js b/Views/backend/swag_import_export/app.js index 75d2f812..f52b96b7 100644 --- a/Views/backend/swag_import_export/app.js +++ b/Views/backend/swag_import_export/app.js @@ -57,6 +57,8 @@ Ext.define('Shopware.apps.SwagImportExport', { views: [ 'Window', 'profile.window.Mappings', + 'profile.window.Iterator', + 'profile.window.Column', 'profile.Profile', 'profile.Grid', 'profile.Window', diff --git a/Views/backend/swag_import_export/controller/export.js b/Views/backend/swag_import_export/controller/export.js index be34b4d1..198a3a59 100644 --- a/Views/backend/swag_import_export/controller/export.js +++ b/Views/backend/swag_import_export/controller/export.js @@ -35,8 +35,7 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Export', { form = btn.up('form'), values = form.getValues(); - if (Ext.isEmpty(values.profile) || Ext.isEmpty(values.format)) - { + if (Ext.isEmpty(values.profile) || values.profile < 1 || Ext.isEmpty(values.format)) { Shopware.Notification.createGrowlMessage( '{s name=swag_import_export/export/error_title}Swag import export{/s}', '{s name=swag_import_export/export/error_msg}Please select export configuration{/s}' @@ -139,7 +138,7 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Export', { }, failure: function(response) { Shopware.Msg.createStickyGrowlMessage({ - title: 'An error occured', + title: '{s name=swag_import_export/export/error_occured}An error occured{/s}', text: response.responseText }); } @@ -171,7 +170,7 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Export', { if(result.success === false){ Shopware.Msg.createStickyGrowlMessage({ - title: 'Export Error', + title: '{s name=swag_import_export/export/error}Export error{/s}', text: result.msg }); @@ -199,7 +198,7 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Export', { }, failure: function(response) { Shopware.Msg.createStickyGrowlMessage({ - title: 'An error occured', + title: '{s name=swag_import_export/export/error_occured}An error occured{/s}', text: response.responseText }); diff --git a/Views/backend/swag_import_export/controller/import.js b/Views/backend/swag_import_export/controller/import.js index 3cc35b54..5516bbb8 100644 --- a/Views/backend/swag_import_export/controller/import.js +++ b/Views/backend/swag_import_export/controller/import.js @@ -72,7 +72,7 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Import', { values = form.getValues(), localFile; - if (Ext.isEmpty(values.profile)) { + if (Ext.isEmpty(values.profile) || values.profile < 1) { Shopware.Notification.createGrowlMessage( '{s name=swag_import_export/import/error_title}Swag import export{/s}', '{s name=swag_import_export/import/error_msg_profle}Please select a profile{/s}' @@ -223,13 +223,18 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Import', { /** * This function sends a request to export data * - * @param object Enlight.app.SubWindow win + * @param { Enlight.app.SubWindow } win + * @param { boolean } extension */ - runRequest: function(win) { + runRequest: function(win, extension) { var me = this, config = me.batchConfig, params = config.params; + if (!Ext.isDefined(extension)) { + extension = false; + } + // if cancel button was pressed if (me.cancelOperation) { win.closeButton.enable(); @@ -245,11 +250,16 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Import', { var result = Ext.decode(response.responseText); if(result.success == false){ - Shopware.Msg.createStickyGrowlMessage({ - title: 'Import Error', + var msg = '{s name=swag_import_export/import/error}Import error{/s}'; + + if (extension) { + msg = '{s name=swag_import_export/import/extension_import_error}Extension import error{/s}' + } + + return Shopware.Msg.createStickyGrowlMessage({ + title: msg, text: result.msg }); - return; } me.batchConfig.params = result.data; @@ -260,10 +270,10 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Import', { } if (result.data.load === true) { - Shopware.Notification.createGrowlMessage( - 'Import', - me.snippets.finished + me.snippets.unprocess - ); + Shopware.Notification.createStickyGrowlMessage({ + title: '{s name=swag_import_export/import/window_title}Import{/s}', + text: me.snippets.finished + me.snippets.unprocess + }); win.importProgress.updateProgress( me.batchConfig.position / me.batchConfig.totalCount, @@ -276,7 +286,7 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Import', { //sets artificial delay of 2 secs setTimeout(function () { win.setLoading(false); - me.runRequest(win); + me.runRequest(win, true); }, 2000); } else { @@ -295,10 +305,9 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Import', { }, failure: function(response) { Shopware.Msg.createStickyGrowlMessage({ - title: 'An error occured', + title: '{s name=swag_import_export/import/failure-title}An error occured{/s}', text: response.responseText }); - me.onProcessFinish(win); } }); diff --git a/Views/backend/swag_import_export/controller/profile.js b/Views/backend/swag_import_export/controller/profile.js index 38fbc7f3..99970c87 100644 --- a/Views/backend/swag_import_export/controller/profile.js +++ b/Views/backend/swag_import_export/controller/profile.js @@ -39,16 +39,20 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { }, 'swag-import-export-profile-window{ isVisible(true) }': { baseprofileselected: me.onBaseProfileSelected, - saveProfile: me.onSaveProfile, - saveNode: me.saveNode + saveProfile: me.onSaveProfile }, 'swag-import-export-profile-profile{ isVisible(true) }': { showMappings: me.showMappings, addNewIteration: me.addNewIteration, addNewNode: me.addNewNode, deleteNode: me.deleteNode, - addNewAttribute: me.addNewAttribute, - changeColumn: me.changeColumn + addNewAttribute: me.addNewAttribute + }, + 'swag-import-export-iterator-window{ isVisible(true) }': { + addIterator: me.addIterator + }, + 'swag-import-export-column-window{ isVisible(true) }': { + addNode: me.addNode }, 'swag-import-export-mapping-window{ isVisible(true) }': { addConversion: me.addConversion, @@ -67,7 +71,6 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { onSearchProfile: function(field, newValue) { var searchString = Ext.String.trim(newValue), - checkboxFilter = field.previousSibling('#defaultprofilefilter'), store = field.up('grid').getStore(); //scroll the store to first page @@ -87,7 +90,6 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { onFilterDefaultProfiles: function(checkbox, value) { var searchfilter = checkbox.nextSibling('#searchfield'), - searchString = Ext.String.trim(searchfilter.getValue()), store = checkbox.up('grid').getStore(); //scroll the store to first page @@ -154,11 +156,91 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { onSaveProfile: function(window) { var me = this, - store = window.profileStore, + profileConfigurator = window.profileConfigurator, + treePanel = profileConfigurator.treePanel, + treeStore = profileConfigurator.treeStore, + node = treeStore.getById(profileConfigurator.selectedNodeId), + form = profileConfigurator.formPanel; + + // call save profile without saving node tree when creating new profile. + if (Ext.isEmpty(window.getProfileId())) { + me.saveProfile(window, function(success, record, message) { + window.setLoading(false); + me.getGrid().getStore().load(); + if (success) { + Shopware.Notification.createGrowlMessage( + '{s name=swag_import_export/profile/save/title}Swag import export{/s}', + message + ); + window.down('#profilebaseform').loadRecord(record); + window.setProfileId(record.get('id')); + } else { + Ext.MessageBox.show({ + title: '{s name=swag_import_export/profile/save/failure_title}Save Failed{/s}', + msg: message, + icon: Ext.Msg.ERROR, + buttons: Ext.Msg.OK + }); + } + }, me); + } else { + // save profile and node tree when editing existing profile + me.saveProfile(window, function(success, record, message) { + if (success) { + window.down('#profilebaseform').loadRecord(record); + window.setProfileId(record.get('id')); + // check if node is selected for editing + if (!node) { + window.setLoading(false); + me.getGrid().getStore().load(); + Shopware.Notification.createGrowlMessage( + '{s name=swag_import_export/profile/save/title}Swag import export{/s}', + message + ); + } else { + // synchronize node tree and give feedback to user + me.saveNode(treePanel, node, form, function(success, message) { + window.setLoading(false); + me.getGrid().getStore().load(); + if (success) { + Shopware.Notification.createGrowlMessage( + '{s name=swag_import_export/profile/save/title}Swag import export{/s}', + message + ); + treePanel.getSelectionModel().deselectAll(true); + treePanel.expand(); + treePanel.getSelectionModel().select(node); + } else { + Ext.MessageBox.show({ + title: '{s name=swag_import_export/profile/save/failure_title}Save Failed{/s}', + msg: message, + icon: Ext.Msg.ERROR, + buttons: Ext.Msg.OK + }); + } + }, me); + } + } else { + Ext.MessageBox.show({ + title: '{s name=swag_import_export/profile/save/failure_title}Save Failed{/s}', + msg: message, + icon: Ext.Msg.ERROR, + buttons: Ext.Msg.OK + }); + } + }, me); + } + }, + + saveProfile: function(window, callback, scope) { + var store = window.profileStore, form = window.down('#profilebaseform'), record = form.getRecord(); if (form.getForm().isValid()) { + if (!form.getForm().isDirty()) { + return Ext.callback(callback, scope, [true, record, '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}']); + } form.getForm().updateRecord(record); record.join(store); @@ -166,23 +248,12 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { record.save({ callback: function(record, operation, success) { - var result = operation.request.scope.reader.jsonData; - window.setLoading(false); - if (result.success) { - window.down('#profilebaseform').loadRecord(record); - window.setProfileId(record.get('id')); - me.getGrid().getStore().load(); - Shopware.Notification.createGrowlMessage( - '{s name=swag_import_export/profile/save/title}Swag import export{/s}', - '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}' - ); - } else { - Shopware.Notification.createGrowlMessage( - '{s name=swag_import_export/profile/save/title}Swag import export{/s}', - result.message - ); - me.getGrid().store.reload(); + var result = Ext.JSON.decode(operation.response.responseText), + msg = '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}'; + if (!result.success) { + msg = result.message; } + return Ext.callback(callback, scope, [result.success, record, msg]); } }); } else { @@ -303,149 +374,123 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { }, /** - * Helper function which add and remove default value field - * depending on selected shopware column + * Profile configuration handling + */ + + /** + * Shows the window with the conversions for the current profile * - * @param [Ext.data.Store] store - Column store - * @param [integer] value - id of selected shopware column - * @param [integer] nodeValue - default value saved in profile + * @param { Ext.tree.Panel } treeStore */ - changeColumn: function(store, value, nodeValue) { + showMappings: function(profileId) { var me = this; - //Add default field when store load is done - store.on('load', function () { - me.createDefaultValueField(store, value, nodeValue); - }, me, { single: true }); - - }, - - createDefaultValueField: function(store, value, nodeValue) { - var me = this, - profileForm = me.getProfileForm(), - formPanel = profileForm.formPanel, - fieldType, - settings, - record; - - formPanel.down('#defaultValue').destroy(); - - //Create default value field - fieldType = 'hidden'; - settings = { - itemId: 'defaultValue', - fieldLabel: '{s namespace=backend/swag_import_export/view/profile name=defaultValue}Default value{/s}', - width: 400, - labelWidth: 150, - name: 'defaultValue', - allowBlank: true - }; - - //Set new field type if selected column have default flag - record = store.getById(value); - if (record) { - if (record.get('default')) { - fieldType = record.get('type'); - } - } - //Merge component settings depending on field type - settings = Ext.apply({ }, settings, me.getDefaultValueType(fieldType)); - - //Add default field to grid - formPanel.insert(1, settings); - - formPanel.child('#defaultValue').setValue(nodeValue); + Ext.create('Shopware.apps.SwagImportExport.view.profile.window.Mappings', { profileId: profileId }).show(); }, /** - * Helper method which returns xtype for current field + * Adds new node to the tree as a child of the selected node * - * @param column - * @returns Object|boolean + * @param { Ext.tree.Panel } treePanel + * @param { int } profileId */ - getDefaultValueType: function(column) { - if (!column) { - return false; - } + addNewIteration: function(treePanel, profileId) { + var me = this, + sectionStore = Ext.create('Shopware.apps.SwagImportExport.store.Section', { + listeners: { + beforeload: { + single: true, + fn: function(store) { + store.getProxy().setExtraParam('profileId', profileId); + } + } + } + }); - switch (column) { - case 'id': - return { xtype: 'numberfield', minValue: 1 }; - break; - case 'integer': - case 'decimal': - case 'float': - var precision = 0; - if (column.precision) { - precision = column.precision - } else if (column.type == 'float') { - precision = 3; - } else if (column.type == 'decimal') { - precision = 3; + sectionStore.load({ + callback: function(records) { + if (records.length === 0) { + return Shopware.Notification.createGrowlMessage( + '{s name=swag_import_export/profile/iterator/no_extension_title}No extension available{/s}', + '{s name=swag_import_export/profile/iterator/no_extension_message}There is no extension for this profile available.{/s}' + ); } - return { xtype: 'numberfield', decimalPrecision: precision }; - break; - case 'string': - case 'text': - return 'textfield'; - break; - case 'boolean': - return { - xtype: 'checkbox', - inputValue: 1, - uncheckedValue: 0 - }; - break; - case 'date': - case 'dateTime': - return { - xtype: 'datefield', - format: 'Y-m-d', - submitFormat: 'Y-m-d' - }; - break; - default: - return { - hidden: true - }; - break; - } + Ext.create('Shopware.apps.SwagImportExport.view.profile.window.Iterator', { + treePanel: treePanel, + profileId: profileId, + sectionStore: sectionStore, + autoShow: true + }); + } + }); }, /** - * Profile configuration handling + * @param { Shopware.apps.SwagImportExport.view.profile.window.Iterator } win */ + addIterator: function(win) { + var me = this, + form = win.formPanel, + treePanel = win.treePanel, + treeStore = treePanel.getStore(), + store = win.columnGrid.getStore(), + formValues = form.getForm().getValues(), + iteratorNode, + columns, + mainNode = treeStore.getRootNode().findChildBy(function(node) { + return node.get('type') === 'iteration' && node.get('inIteration'); + }, me, true); + + iteratorNode = treeStore.model.create({ + text: formValues.nodeName, + adapter: formValues.adapter, + expanded: true, + type: 'iteration', + iconCls: 'sprite-blue-folders-stack', + inIteration: true, + parentKey: formValues.parentKey || '' + }); - /** - * Shows the window with the conversions for the current profile - * - * @param { Ext.tree.Panel } treeStore - */ - showMappings: function(profileId) { - var me = this; + columns = store.getRange(); - Ext.create('Shopware.apps.SwagImportExport.view.profile.window.Mappings', { profileId: profileId }).show(); + mainNode.appendChild(iteratorNode); + + me.doSync(treeStore, function() { + for (var i = 0, count = columns.length; i < count; i++) { + var column = columns[i], + columnNode; + if (!column.get('select')) { + continue; + } + columnNode = treeStore.model.create({ + text: column.get('nodeName'), + adapter: formValues.adapter, + inIteration: true, + type: 'leaf', + iconCls: 'sprite-blue-document-text', + swColumn: column.get('swColumn') + }); + iteratorNode.appendChild(columnNode); + } + me.doSync(treeStore, function() { + Shopware.Notification.createGrowlMessage( + '{s name=swag_import_export/profile/save/title}Swag import export{/s}', + '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}' + ); + treePanel.expand(); + treePanel.getSelectionModel().select(iteratorNode); + win.close(); + }); + }, me); }, /** - * Adds new node to the tree as a child of the selected node * - * @param { Ext.tree.Panel } treePanel * @param { Ext.data.TreeStore } treeStore - * @param { int } selectedNodeId + * @param callback + * @param scope */ - addNewIteration: function(treePanel, treeStore, selectedNodeId) { - var me = this; - - var node = treeStore.getById(selectedNodeId); - if (node.get('type') !== 'iteration') { - node.set('type', ''); - node.set('iconCls', ''); - } - - var data = { text: "New Iteration Node", adapter:'none', expanded: true, type: 'iteration', iconCls: 'sprite-blue-folders-stack', inIteration: true }; - - var newNode = node.appendChild(data); + doSync: function(treeStore, callback, scope) { treeStore.sync({ failure: function(batch, options) { var error = batch.exceptions[0].getError(), @@ -459,8 +504,7 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { }); }, success: function() { - treePanel.expand(); - treePanel.getSelectionModel().select(treeStore.getById(newNode.data.id)); + Ext.callback(callback, scope); } }); }, @@ -469,26 +513,48 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { * Adds new node to the tree as a child of the selected node * * @param { Ext.tree.Panel } treePanel - * @param { Ext.data.TreeStore } treeStore - * @param { int } selectedNodeId + * @param { int } profileId + * @param { string } adapter */ - addNewNode: function(treePanel, treeStore, selectedNodeId) { - var me = this; + addNewNode: function(treePanel, profileId, adapter) { + Ext.create('Shopware.apps.SwagImportExport.view.profile.window.Column', { + treePanel: treePanel, + profileId: profileId, + adapter: adapter, + autoShow: true + }); + }, - var node = treeStore.getById(selectedNodeId); - if (node.get('type') !== 'iteration') { - node.set('type', ''); - node.set('iconCls', ''); + /** + * @param { Shopware.apps.SwagImportExport.view.profile.window.Column } win + */ + addNode: function(win) { + var me = this, + treePanel = win.treePanel, + form = win.formPanel, + formValues = form.getForm().getValues(), + store = treePanel.getStore(), + parentNode = treePanel.getSelectionModel().getSelection()[0], + newNode; + + if (parentNode.get('type') === 'leaf') { + parentNode = parentNode.parentNode; } - var data = { }; - if (node.get('inIteration') === true) { - data = { text: "New Node", expanded: true, type: 'leaf', iconCls: 'sprite-blue-document-text', inIteration: true, adapter: node.get('adapter') }; - } else { - data = { text: "New Node", expanded: true }; - } - var newNode = node.appendChild(data); - treeStore.sync({ + newNode = store.model.create({ + text: formValues.nodeName, + expanded: true, + type: 'leaf', + iconCls: 'sprite-blue-document-text', + inIteration: true, + swColumn: formValues.swColumn, + defaultValue: formValues.defaultValue || '', + adapter: win.getAdapter() + }); + + parentNode.appendChild(newNode); + + store.sync({ failure: function(batch, options) { var error = batch.exceptions[0].getError(), msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error; @@ -501,8 +567,13 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { }); }, success: function() { + Shopware.Notification.createGrowlMessage( + '{s name=swag_import_export/profile/save/title}Swag import export{/s}', + '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}' + ); + win.close(); treePanel.expand(); - treePanel.getSelectionModel().select(treeStore.getById(newNode.data.id)); + treePanel.getSelectionModel().select(newNode); } }); }, @@ -510,93 +581,96 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { /** * Saves the changes of the currently selected node * - * @param { Ext.data.TreeStore } treeStore - * @param { int } selectedNodeId - * @param { string } nodeName - * @param { string } swColumn + * @param { Ext.tree.Panel } treePanel + * @param { Ext.data.NodeInterface } node + * @param { Ext.form.Panel } form + * @param callback + * @param scope */ - saveNode: function(treePanel, treeStore, selectedNodeId, nodeName, swColumn, defaultValue, adapter, parentKey) { - var me = this; + saveNode: function(treePanel, node, form, callback, scope) { + var treeStore = treePanel.getStore(), + values; - var node = treeStore.getById(selectedNodeId); - - if(!node) { - return; - } - - node.set('text', nodeName); - node.set('swColumn', swColumn); - node.set('defaultValue', defaultValue); + values = form.getForm().getValues(); + node.set('text', values.nodeName || ''); + node.set('swColumn', values.swColumn || ''); + node.set('defaultValue', values.defaultValue || ''); // change only when in iteration (because otherwise adapter will be empty) if (node.get('type') === 'iteration') { - node.set('adapter', adapter); - node.set('parentKey', parentKey); + node.set('adapter', values.adapter || ''); + node.set('parentKey', values.parentKey || ''); } - treeStore.sync({ - success: function() { - treePanel.getSelectionModel().deselectAll(true); - treePanel.expand(); - treePanel.getSelectionModel().select(treeStore.getById(node.get('id'))); - }, - failure: function(batch, options) { - var error = batch.exceptions[0].getError(), - msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error; + if (Ext.Object.getKeys(node.getChanges()).length > 0) { + treeStore.sync({ + success: function() { + return Ext.callback(callback, scope, [true, '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}']); + }, + failure: function(batch, options) { + var error = batch.exceptions[0].getError(), + msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error; - Ext.MessageBox.show({ - title: '{s name=swag_import_export/profile/save/failure_title}Save Failed{/s}', - msg: msg, - icon: Ext.Msg.ERROR, - buttons: Ext.Msg.OK - }); - } - }); + return Ext.callback(callback, scope, [false, msg]); + } + }); + } else { + return Ext.callback(callback, scope, [true, '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}']); + } }, /** * Deletes the selected node */ - deleteNode: function(treeStore, selectedNodeId, selModel) { - var me = this; + deleteNode: function(treePanel) { Ext.Msg.show({ title: '{s name=swag_import_export/profile/delete/title}Delete Node?{/s}', msg: '{s name=swag_import_export/profile/delete/msg}Are you sure you want to permanently delete the node?{/s}', buttons: Ext.Msg.YESNO, - fn: function(response) { - if (response === 'yes') { - var node = treeStore.getById(selectedNodeId), - parentNode = node.parentNode, - selectNode = node.previousSibling; - - if (!selectNode) { - selectNode = node.nextSibling; - } - if (!selectNode) { - selectNode = node.parentNode; - } + fn: function(btn) { + if (btn === 'yes') { + var selModel = treePanel.getSelectionModel(), + store = treePanel.getStore(), + selection = selModel.getSelection(); + + for (var i = 0, count = selection.length; i < count; i++) { + var node = selection[i], + parentNode = node.parentNode, + selectNode = node.previousSibling; + + if (!selectNode) { + selectNode = node.nextSibling; + } + if (!selectNode) { + selectNode = node.parentNode; + } - parentNode.removeChild(node); + parentNode.removeChild(node); - if (parentNode.get('type') !== 'iteration' && parentNode.get('inIteration') === true) { - var bChildNodes = false; + if (parentNode.get('type') !== 'iteration' && parentNode.get('inIteration') === true) { + var bChildNodes = false; - // check if there is at least one leaf, iteration or node - for (var i = 0; i < parentNode.childNodes.length; i++) { - if (parentNode.childNodes[i].get('type') !== 'attribute') { - bChildNodes = true; - break; + // check if there is at least one leaf, iteration or node + for (var j = 0; j < parentNode.childNodes.length; j++) { + if (parentNode.childNodes[j].get('type') !== 'attribute') { + bChildNodes = true; + break; + } } - } - if (!bChildNodes) { - parentNode.set('type', 'leaf'); - parentNode.set('iconCls', 'sprite-icon_taskbar_top_inhalte_active'); + if (!bChildNodes) { + parentNode.set('type', 'leaf'); + parentNode.set('iconCls', 'sprite-blue-document-text'); + } } } - treeStore.sync({ + store.sync({ success: function() { + Shopware.Notification.createGrowlMessage( + '{s name=swag_import_export/profile/save/title}Swag import export{/s}', + '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}' + ); selModel.deselectAll(); if (selectNode) { selModel.select(selectNode); @@ -627,14 +701,15 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { * @param { int } selectedNodeId */ addNewAttribute: function(treePanel, treeStore, selectedNodeId) { - var me = this; - var node = treeStore.getById(selectedNodeId); + var node = treeStore.getById(selectedNodeId), + data, + newNode; + node.set('leaf', false); node.set('expanded', true); - var children = node.childNodes; - var data = { text: "New Attribute", leaf: true, type: 'attribute', iconCls: 'sprite-sticky-notes-pin', inIteration: true, adapter: node.get('adapter') }; - var newNode = node.appendChild(data); + data = { text: "New Attribute", leaf: true, type: 'attribute', iconCls: 'sprite-sticky-notes-pin', inIteration: true, adapter: node.get('adapter') }; + newNode = node.appendChild(data); treeStore.sync({ failure: function(batch, options) { @@ -649,6 +724,10 @@ Ext.define('Shopware.apps.SwagImportExport.controller.Profile', { }); }, success: function() { + Shopware.Notification.createGrowlMessage( + '{s name=swag_import_export/profile/save/title}Swag import export{/s}', + '{s name=swag_import_export/profile/save/success}Successfully updated.{/s}' + ); treePanel.expand(); treePanel.getSelectionModel().select(treeStore.getById(newNode.getId())); } diff --git a/Views/backend/swag_import_export/model/profile_list.js b/Views/backend/swag_import_export/model/profile_list.js index ecc3837d..66cc2577 100644 --- a/Views/backend/swag_import_export/model/profile_list.js +++ b/Views/backend/swag_import_export/model/profile_list.js @@ -15,6 +15,7 @@ Ext.define('Shopware.apps.SwagImportExport.model.ProfileList', { { name: 'type', type: 'string' }, { name: 'baseProfile', type: 'int', useNull: true }, { name: 'name', type: 'string' }, + { name: 'description', persist: false }, { name: 'translation', persist: false }, { name: 'default', type: 'boolean', persist: false }, { name: 'tree', type: 'string' } diff --git a/Views/backend/swag_import_export/store/session_list.js b/Views/backend/swag_import_export/store/session_list.js index 818db4fb..ea7c58e0 100644 --- a/Views/backend/swag_import_export/store/session_list.js +++ b/Views/backend/swag_import_export/store/session_list.js @@ -3,7 +3,11 @@ Ext.define('Shopware.apps.SwagImportExport.store.SessionList', { extend : 'Ext.data.Store', autoLoad: false, - + + remoteSort: true, + + remoteFilter: true, + /** * Define the used model for this store * @string diff --git a/Views/backend/swag_import_export/view/manager/export.js b/Views/backend/swag_import_export/view/manager/export.js index 5e4cc69b..a9e87350 100644 --- a/Views/backend/swag_import_export/view/manager/export.js +++ b/Views/backend/swag_import_export/view/manager/export.js @@ -245,8 +245,19 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Export', { allowBlank: false, fieldLabel: '{s name=swag_import_export/export/select_profile}Select profile{/s}', store: Ext.create('Shopware.apps.SwagImportExport.store.ProfileList', { - remoteSort: false, - remoteFilter: false + sorters: [ + { property: 'name', direction: 'ASC' } + ], + listeners: { + load: function(store, records) { + if (records.length === 0) { + store.add({ + id: -1, + name: '{s name=swag_import_export/profile/no_data}No profiles found{/s}' + }); + } + } + } }), labelStyle: 'font-weight: 700; text-align: left;', width: me.configWidth, @@ -255,15 +266,18 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Export', { margin: '5 0 0 0', valueField: 'id', displayField: 'name', - queryMode: 'local', + queryMode: 'remote', forceSelection: true, name: 'profile', emptyText: '{s name=swag_import_export/manager/import/choose}Please choose{/s}', + matchFieldWidth: false, + minChars: 3, listConfig: { + width: 450, getInnerTpl: function (value) { return Ext.XTemplate( '{literal}' + - '{ translation } ({ name })' + + '{ name } ({ translation })' + '{ name }' + '{/literal}'); } @@ -278,7 +292,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Export', { { getFormattedName: function(values) { if (values.translation) { - return Ext.String.format('[0] ([1])', values.translation, values.name); + return Ext.String.format('[0] ([1])', values.name, values.translation); } return values.name; } @@ -286,9 +300,27 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Export', { ), listeners: { scope: me, - beforequery: function(record){ - record.query = new RegExp(record.query, 'i'); - record.forceAll = true; + change: { + buffer: 500, + fn: function(combo, newValue) { + var store = combo.getStore(), + searchString; + + if (Ext.isEmpty(newValue)) { + combo.lastQuery = ''; + store.filters.removeAtKey('search'); + store.load(); + } else if (Ext.isString(newValue)) { + searchString = Ext.String.trim(newValue); + + //scroll the store to first page + store.currentPage = 1; + //Loads the store with a special filter + store.filter([ + { id: 'search', property: 'name', value: '%' + searchString + '%', expression: 'LIKE' } + ]); + } + } }, select: function(cb, selection) { if (Ext.isEmpty(selection)) { @@ -316,7 +348,43 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Export', { } }); - return me.profileCombo; + me.profileFilterCheckbox = Ext.create('Ext.form.field.Checkbox', { + margin: '7 0 0 10', + boxLabel: '{s name=swag_import_export/manager/hide_default_profiles}Hide default profiles{/s}', + listeners: { + change: function(cb, newValue) { + var store = me.profileCombo.getStore(); + me.resetAdditionalFields(); + me.hideFields(); + + store.currentPage = 1; + + if (newValue) { + store.filters.add( + { id: 'default', property: 'default', value: false } + ); + } else { + store.filters.removeAtKey('default'); + } + + if (me.profileCombo.isDirty()) { + return me.profileCombo.clearValue(); + } + store.load(); + } + } + }); + + me.profileFieldContainer = Ext.create('Ext.form.FieldContainer', { + layout: 'hbox', + width: 800, + items: [ + me.profileCombo, + me.profileFilterCheckbox + ] + }); + + return me.profileFieldContainer; }, /* * Format drop down @@ -340,7 +408,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Export', { return Ext.create('Ext.form.field.ComboBox', { allowBlank: false, fieldLabel: '{s name=swag_import_export/export/select_format}Select export format{/s}', - margin: '20 0 0 0', + margin: '20 0 0 2', store: formats, labelStyle: 'font-weight: 700; text-align: left;', width: me.configWidth, @@ -525,7 +593,16 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Export', { if (activeFieldset) { Ext.each(activeFieldset.query('field'), function(field) { - field.reset(); + // combotree custom field needs special work to reset + if (field.getXType() === 'combotree') { + if (field.treePanel) { + field.treePanel.getSelectionModel().deselectAll(); + field.treePanel.collapseAll(); + } + field.setFieldValue(null, ''); + } else { + field.reset(); + } }); } } diff --git a/Views/backend/swag_import_export/view/manager/import.js b/Views/backend/swag_import_export/view/manager/import.js index 5803dbbb..d88989af 100644 --- a/Views/backend/swag_import_export/view/manager/import.js +++ b/Views/backend/swag_import_export/view/manager/import.js @@ -185,7 +185,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Import', { me.addBtn = Ext.create('Ext.form.field.File', { emptyText: '{s name=swag_import_export/manager/import/choose}Please choose{/s}', - margin: '5 0 0 0', + margin: '5 0 0 2', buttonText: '{s name=swag_import_export/manager/import/choose_button}Choose{/s}', buttonConfig: { cls: Ext.baseCSSPrefix + 'form-mediamanager-btn small secondary', @@ -215,22 +215,36 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Import', { var me = this; me.profileCombo = Ext.create('Ext.form.field.ComboBox', { - margin: '5 0 0 0', + allowBlank: false, fieldLabel: '{s name=swag_import_export/manager/import/select_profile}Select profile{/s}', store: Ext.create('Shopware.apps.SwagImportExport.store.ProfileList', { - remoteSort: false, - remoteFilter: false + sorters: [ + { property: 'name', direction: 'ASC' } + ], + listeners: { + load: function(store, records) { + if (records.length === 0) { + store.add({ + id: -1, + name: '{s name=swag_import_export/profile/no_data}No profiles found{/s}' + }); + } + } + } }), labelStyle: 'font-weight: 700; text-align: left;', width: me.configWidth, labelWidth: me.configLabelWidth, helpText: '{s name=swag_import_export/export/profile_help}The default profiles can be individually extended and modified with custom profiles in the profiles menu.{/s}', + margin: '5 0 0 0', valueField: 'id', displayField: 'name', name: 'profile', - queryMode: 'local', + queryMode: 'remote', forceSelection: true, emptyText: '{s name=swag_import_export/manager/import/choose}Please choose{/s}', + matchFieldWidth: false, + minChars: 3, displayTpl: new Ext.XTemplate( '' + '{literal}' + @@ -241,30 +255,81 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Import', { { getFormattedName: function(values) { if (values.translation) { - return Ext.String.format('[0] ([1])', values.translation, values.name); + return Ext.String.format('[0] ([1])', values.name, values.translation); } return values.name; } } ), listConfig: { + width: 450, getInnerTpl: function (value) { return Ext.XTemplate( '{literal}' + - '{ translation } ({ name })' + + '{ name } ({ translation })' + '{ name }' + '{/literal}'); } }, listeners : { - beforequery: function(record){ - record.query = new RegExp(record.query, 'i'); - record.forceAll = true; + change: { + buffer: 500, + fn: function(combo, newValue) { + var store = combo.getStore(), + searchString; + + if (Ext.isEmpty(newValue)) { + combo.lastQuery = ''; + store.filters.removeAtKey('search'); + store.load(); + } else if (Ext.isString(newValue)) { + searchString = Ext.String.trim(newValue); + + //scroll the store to first page + store.currentPage = 1; + //Loads the store with a special filter + store.filter([ + { id: 'search', property: 'name', value: '%' + searchString + '%', expression: 'LIKE' } + ]); + } + } } } }); - - return me.profileCombo; + + me.profileFilterCheckbox = Ext.create('Ext.form.field.Checkbox', { + margin: '7 0 0 10', + boxLabel: '{s name=swag_import_export/manager/hide_default_profiles}Hide default profiles{/s}', + listeners: { + change: function(cb, newValue) { + var store = me.profileCombo.getStore(); + + if (newValue) { + store.filter([ + { id: 'default', property: 'default', value: false } + ]); + } else { + store.filters.removeAtKey('default'); + store.currentPage = 1; + if (me.profileCombo.isDirty()) { + return me.profileCombo.clearValue(); + } + store.load(); + } + } + } + }); + + me.profileFieldContainer = Ext.create('Ext.form.FieldContainer', { + layout: 'hbox', + width: 800, + items: [ + me.profileCombo, + me.profileFilterCheckbox + ] + }); + + return me.profileFieldContainer; }, /** diff --git a/Views/backend/swag_import_export/view/manager/manager.js b/Views/backend/swag_import_export/view/manager/manager.js index 1c9b2c51..0de5b2c0 100644 --- a/Views/backend/swag_import_export/view/manager/manager.js +++ b/Views/backend/swag_import_export/view/manager/manager.js @@ -51,7 +51,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Manager', { var combo = container.profileCombo, store = combo.getStore(); - store.clearFilter(); + store.filters.removeAtKey('search'); store.load({ callback: function() { if (combo.isDirty() && !store.getById(combo.getValue())) { @@ -73,7 +73,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Manager', { var combo = container.profileCombo, store = combo.getStore(); - store.clearFilter(); + store.filters.removeAtKey('search'); store.load({ callback: function() { if (combo.isDirty() && !store.getById(combo.getValue())) { diff --git a/Views/backend/swag_import_export/view/manager/session.js b/Views/backend/swag_import_export/view/manager/session.js index 6a6411cc..c2e142de 100644 --- a/Views/backend/swag_import_export/view/manager/session.js +++ b/Views/backend/swag_import_export/view/manager/session.js @@ -25,7 +25,11 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.Session', { }, buildStore: function() { - return Ext.create('Shopware.apps.SwagImportExport.store.SessionList'); + return Ext.create('Shopware.apps.SwagImportExport.store.SessionList', { + sorters: [ + { property: 'createdAt', direction: 'DESC' } + ] + }); }, buildSelectionModel: function() { diff --git a/Views/backend/swag_import_export/view/manager/window/log.js b/Views/backend/swag_import_export/view/manager/window/log.js index 69010742..78b5be81 100644 --- a/Views/backend/swag_import_export/view/manager/window/log.js +++ b/Views/backend/swag_import_export/view/manager/window/log.js @@ -105,6 +105,9 @@ Ext.define('Shopware.apps.SwagImportExport.view.manager.window.Log', { flex: 1, logStore: Ext.create('Shopware.apps.SwagImportExport.store.Log', { autoLoad: true, + sorters: [ + { property: 'logDate', direction: 'DESC' } + ], filters: [ { property: 'session', value: me.getSessionId(), expression: '=' } ] diff --git a/Views/backend/swag_import_export/view/profile/grid.js b/Views/backend/swag_import_export/view/profile/grid.js index 30183c05..b85707a7 100644 --- a/Views/backend/swag_import_export/view/profile/grid.js +++ b/Views/backend/swag_import_export/view/profile/grid.js @@ -198,7 +198,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Grid', { if (Ext.isEmpty(record.get('translation'))) { return value; } - return Ext.String.format('[0] ([1])', record.get('translation'), value); + return Ext.String.format('[0] ([1])', value, record.get('translation')); }, renderDefault: function(value, meta, record) { diff --git a/Views/backend/swag_import_export/view/profile/profile.js b/Views/backend/swag_import_export/view/profile/profile.js index 0f6ebd27..4386dfb3 100644 --- a/Views/backend/swag_import_export/view/profile/profile.js +++ b/Views/backend/swag_import_export/view/profile/profile.js @@ -22,6 +22,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { me.initializeStores(); me.selectedNodeId = 0; + me.lastSelectedNode = null; me.items = me.buildItems(); me.dockedItems = me.buildDockedItems(); @@ -83,15 +84,15 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { itemId: 'createIteration', disabled: true, handler: function () { - me.fireEvent('addNewIteration', me.treePanel, me.treeStore, me.selectedNodeId); + me.fireEvent('addNewIteration', me.treePanel, me.getProfileId()); } }, { - text: '{s name=newNode}New node{/s}', + text: '{s name=swag_import_export/profile/new_column}New column{/s}', iconCls: 'sprite-plus-circle-frame', itemId: 'createChild', disabled: true, handler: function () { - me.fireEvent('addNewNode', me.treePanel, me.treeStore, me.selectedNodeId); + me.fireEvent('addNewNode', me.treePanel, me.getProfileId(), me.lastSelectedNode.get('adapter')); } }, { text: '{s name=newAttribute}New attribute{/s}', @@ -107,7 +108,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { itemId: 'deleteSelected', disabled: true, handler: function () { - me.fireEvent('deleteNode', me.treeStore, me.selectedNodeId, me.treePanel.getSelectionModel()); + me.fireEvent('deleteNode', me.treePanel); } }, '->', { itemId: 'conversionsMenu', @@ -134,6 +135,10 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { flex: 1, border: false, store: me.treeStore, + selModel: { + selType: 'rowmodel', + mode: 'MULTI' + }, viewConfig: { plugins: { ptype: 'customtreeviewdragdrop', @@ -142,13 +147,6 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { }, listeners: { drop: function (node, data, overModel, dropPosition, eOpts) { - if (dropPosition === 'append') { - if (overModel.get('type') !== 'iteration') { - overModel.set('type', ''); - overModel.set('iconCls', ''); - } - } - me.treeStore.sync({ success: function () { // fix selection @@ -166,7 +164,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { margin: '0 5 0 0', listeners: { scope: me, - select: me.onTreeItemSelection, + selectionchange: me.onTreeItemSelection, itemcontextmenu: me.onTreeItemContextMenu } }); @@ -192,6 +190,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { itemId: 'nodeName', fieldLabel: '{s name=nodeName}Node name{/s}', hidden: true, + disabled: true, width: 400, labelWidth: 150, name: 'nodeName', @@ -200,17 +199,19 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { itemId: 'defaultValue', fieldLabel: '{s name=defaultValue}Default value{/s}', hidden: true, + disabled: true, width: 400, labelWidth: 150, name: 'defaultValue', allowBlank: true }, { itemId: 'swColumn', - fieldLabel: '{s name=shopwareColumn}Shopware column{/s}', + fieldLabel: '{s name=shopwareColumn}Database mapping{/s}', hidden: true, + disabled: true, xtype: 'combobox', editable: false, - emptyText: 'Select Column', + emptyText: '{s name=selectColumn}Select field{/s}', queryMode: 'local', store: me.columnStore, valueField: 'id', @@ -218,21 +219,15 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { width: 400, labelWidth: 150, name: 'swColumn', - allowBlank: false, - listeners: { - change: function (field, newValue) { - var defaultValue = me.treeStore.getById(me.selectedNodeId).get('defaultValue'); - - me.fireEvent('changeColumn', me.columnStore, newValue, defaultValue); - } - } + allowBlank: false }, { itemId: 'adapter', - fieldLabel: '{s name=adapter}Adapter{/s}', + fieldLabel: '{s name=adapter}Extension{/s}', hidden: true, + disabled: true, xtype: 'combobox', editable: false, - emptyText: '{s name=selectColumn}Select column{/s}', + emptyText: '{s name=selectExtension}Select extension{/s}', queryMode: 'local', store: me.sectionStore, valueField: 'id', @@ -243,7 +238,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { allowBlank: false, listeners: { change: function (field, newValue, oldValue, eOpts) { - me.formPanel.child('#parentKey').getStore().load({ + field.nextSibling('#parentKey').getStore().load({ params: { profileId: me.getProfileId(), adapter: newValue @@ -255,6 +250,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { itemId: 'parentKey', fieldLabel: '{s name=parentKey}Parent key{/s}', hidden: true, + disabled: true, xtype: 'combobox', editable: false, emptyText: '{s name=selectColumn}Select column{/s}', @@ -271,42 +267,50 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { return me.formPanel; }, - onTreeItemSelection: function (view, record) { - var me = this; + onTreeItemSelection: function (selModel, selection) { + var me = this, + toolbar = me.toolbar, + rootSelected = false, + record; - me.selectedNodeId = record.getId(); - me.composeFormFields(); - - if (!me.readOnly) { - var toolbar = me.toolbar; - - if (record.get('type') === 'attribute') { - toolbar.items.get('createIteration').setDisabled(true); - toolbar.items.get('createAttribute').setDisabled(true); - toolbar.items.get('createChild').setDisabled(true); - toolbar.items.get('deleteSelected').setDisabled(false); - } else if (record.get('type') === 'leaf') { - toolbar.items.get('createIteration').setDisabled(false); - toolbar.items.get('createAttribute').setDisabled(false); - toolbar.items.get('createChild').setDisabled(false); - toolbar.items.get('deleteSelected').setDisabled(false); - } else if (record.get('type') === 'iteration') { - toolbar.items.get('createIteration').setDisabled(false); - toolbar.items.get('createAttribute').setDisabled(false); - toolbar.items.get('createChild').setDisabled(false); - toolbar.items.get('deleteSelected').setDisabled(false); - } else { - if (record.get('inIteration') === true) { + // check if root not is selected + for (var i = 0, count = selection.length; i < count; i++) { + var selectedRecord = selection[i]; + + if (selectedRecord.get('id') === 'root') { + rootSelected = true; + break; + } + } + + me.formPanel.setDisabled(selection.length > 1); + + toolbar.items.get('createIteration').setDisabled(true); + toolbar.items.get('createAttribute').setDisabled(true); + toolbar.items.get('createChild').setDisabled(true); + toolbar.items.get('deleteSelected').setDisabled(rootSelected); + + if (selection.length === 1) { + record = selection[0]; + me.selectedNodeId = record.get('id'); + me.lastSelectedNode = record; + me.composeFormFields(record); + if (!me.readOnly) { + if (record.get('type') === 'leaf') { + toolbar.items.get('createIteration').setDisabled(false); toolbar.items.get('createAttribute').setDisabled(false); + if (record.get('inIteration') === true && record.parentNode.get('type') === 'iteration') { + toolbar.items.get('createChild').setDisabled(false); + } + } else if (record.get('type') === 'iteration') { + toolbar.items.get('createIteration').setDisabled(false); + toolbar.items.get('createAttribute').setDisabled(false); + toolbar.items.get('createChild').setDisabled(false); } else { - toolbar.items.get('createAttribute').setDisabled(true); - } - toolbar.items.get('createIteration').setDisabled(false); - toolbar.items.get('createChild').setDisabled(false); - if (record.getId() === 'root') { - toolbar.items.get('deleteSelected').setDisabled(true); - } else { - toolbar.items.get('deleteSelected').setDisabled(false); + if (record.get('inIteration') === true) { + toolbar.items.get('createAttribute').setDisabled(false); + } + toolbar.items.get('createIteration').setDisabled(false); } } } @@ -316,6 +320,12 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { var me = this, type = record.get('type'), menuItems; + + e.stopEvent(); + if (view.getSelectionModel().getSelection().length > 1) { + return; + } + view.getSelectionModel().select(record); e.stopEvent(); @@ -327,13 +337,13 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { text: '{s name=newIterationNode}New iteration Node{/s}', iconCls: 'sprite-plus-circle-frame', handler: function () { - me.fireEvent('addNewIteration', me.treePanel, me.treeStore, record.get('id')); + me.fireEvent('addNewIteration', me.treePanel, me.getProfileId()); } }, { - text: '{s name=newNode}New entry{/s}', + text: '{s name=swag_import_export/profile/new_column}New field{/s}', iconCls: 'sprite-plus-circle-frame', handler: function () { - me.fireEvent('addNewNode', me.treePanel, me.treeStore, record.get('id')); + me.fireEvent('addNewNode', me.treePanel, me.getProfileId(), me.lastSelectedNode.get('adapter')); } }, { text: '{s name=newAttribute}New attribute{/s}', @@ -345,10 +355,14 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { text: '{s name=swag_import_export/profile/profile/remove_item}Remove selected item{/s}', iconCls: 'sprite-minus-circle-frame', handler: function () { - me.fireEvent('deleteNode', me.treeStore, me.selectedNodeId, me.treePanel.getSelectionModel()); + me.fireEvent('deleteNode', me.treePanel); } }]; + if (type !== 'iteration' && type !== 'leaf') { + delete menuItems[1]; + } + if (type === 'attribute') { menuItems = menuItems[3]; } @@ -378,17 +392,33 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { form = me.formPanel; form.child('#nodeName').hide(); + form.child('#nodeName').disable(); form.child('#swColumn').hide(); + form.child('#swColumn').disable(); }, - composeFormFields: function() { + composeFormFields: function(node) { var me = this, form = me.formPanel, - node = me.treeStore.getById(me.selectedNodeId); + parentNode, + isFirst; + + form.child('#swColumn').hide(); + form.child('#swColumn').disable(); + + form.child('#adapter').hide(); + form.child('#adapter').disable(); + + form.child('#parentKey').hide(); + form.child('#parentKey').disable(); + + form.child('#defaultValue').hide(); + form.child('#defaultValue').disable(); form.child('#nodeName').show(); + form.child('#nodeName').enable(); form.child('#nodeName').setValue(node.get('text')); - form.child('#swColumn').setValue(node.get('swColumn')); + form.child('#nodeName').resetOriginalValue(); if (node.get('type') === 'attribute') { form.child('#swColumn').getStore().load({ @@ -398,26 +428,32 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { } }); form.child('#swColumn').show(); - form.child('#adapter').hide(); - form.child('#parentKey').hide(); + form.child('#swColumn').enable(); + form.child('#swColumn').setValue(node.get('swColumn')); + form.child('#swColumn').resetOriginalValue(); } else if (node.get('type') === 'leaf') { - form.child('#swColumn').getStore().load({ + form.child('#swColumn').show(); + form.child('#swColumn').enable(); + form.child('#swColumn').setValue(node.get('swColumn')); + form.child('#swColumn').resetOriginalValue(); + me.columnStore.load({ params: { profileId: me.getProfileId(), adapter: node.get('adapter') + }, + callback: function() { + me.createDefaultValueField(me.columnStore, node.get('swColumn'), node.get('defaultValue')); } - }); - form.child('#swColumn').show(); - form.child('#adapter').hide(); - form.child('#parentKey').hide(); + }, me); } else if (node.get('type') === 'iteration') { - form.child('#swColumn').hide(); form.child('#adapter').show(); + form.child('#adapter').enable(); form.child('#adapter').setValue(node.get('adapter')); + form.child('#adapter').resetOriginalValue(); // check if it's the first iteration node - var parentNode = node.parentNode; - var isFirst = true; + parentNode = node.parentNode; + isFirst = true; while (parentNode.get('id') !== 'root') { if (parentNode.get('type') === 'iteration') { isFirst = false; @@ -432,17 +468,109 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Profile', { adapter: node.get('adapter') } }); - form.child('#parentKey').setValue(node.get('parentKey')); form.child('#parentKey').show(); + form.child('#parentKey').enable(); + form.child('#parentKey').setValue(node.get('parentKey')); + form.child('#parentKey').resetOriginalValue(); } else { - form.child('#parentKey').hide(); - form.child('#parentKey').setValue(''); + form.child('#parentKey').clearValue(); } - } else { - form.child('#swColumn').hide(); - form.child('#adapter').hide(); - form.child('#parentKey').hide(); - form.child('#defaultValue').hide(); + } + }, + + /** + * @param { Shopware.apps.SwagImportExport.store.Column } store + * @param { string } value + * @param { string } nodeValue + */ + createDefaultValueField: function(store, value, nodeValue) { + var me = this, + formPanel = me.formPanel, + fieldType, + settings, + record; + + formPanel.down('#defaultValue').destroy(); + + //Create default value field + fieldType = 'hidden'; + settings = { + itemId: 'defaultValue', + fieldLabel: '{s namespace=backend/swag_import_export/view/profile name=defaultValue}Default value{/s}', + width: 400, + labelWidth: 150, + name: 'defaultValue', + allowBlank: true + }; + + //Set new field type if selected column have default flag + record = store.getById(value); + if (record) { + if (record.get('default')) { + fieldType = record.get('type'); + } + } + //Merge component settings depending on field type + settings = Ext.apply({ }, settings, me.getDefaultValueType(fieldType)); + + //Add default field to grid + formPanel.insert(1, settings); + + formPanel.child('#defaultValue').setValue(nodeValue); + }, + + /** + * Helper method which returns xtype for current field + * + * @param column + * @returns Object|boolean + */ + getDefaultValueType: function(column) { + if (!column) { + return false; + } + + switch (column) { + case 'id': + return { xtype: 'numberfield', minValue: 1 }; + break; + case 'integer': + case 'decimal': + case 'float': + var precision = 0; + if (column.precision) { + precision = column.precision + } else if (column.type == 'float') { + precision = 3; + } else if (column.type == 'decimal') { + precision = 3; + } + return { xtype: 'numberfield', decimalPrecision: precision }; + break; + case 'string': + case 'text': + return 'textfield'; + break; + case 'boolean': + return { + xtype: 'checkbox', + inputValue: 1, + uncheckedValue: 0 + }; + break; + case 'date': + case 'dateTime': + return { + xtype: 'datefield', + format: 'Y-m-d', + submitFormat: 'Y-m-d' + }; + break; + default: + return { + hidden: true + }; + break; } }, diff --git a/Views/backend/swag_import_export/view/profile/tree/drag_and_drop.js b/Views/backend/swag_import_export/view/profile/tree/drag_and_drop.js index bb77c5e4..bd888cfe 100644 --- a/Views/backend/swag_import_export/view/profile/tree/drag_and_drop.js +++ b/Views/backend/swag_import_export/view/profile/tree/drag_and_drop.js @@ -9,10 +9,10 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.tree.DragAndDrop', { me.callParent(arguments); /** - * @TODO: override onNodeOver, because isValidDropPoint is in private class + * Custom drag&drop validation function for profile editor tree */ me.dropZone.isValidDropPoint = function(node, position, dragZone, e, data) { - if (!node || !data.item) { + if (!node || !data.item || data.records.length > 1) { return false; } @@ -28,6 +28,10 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.tree.DragAndDrop', { return false; } + if (position === 'append') { + return false; + } + // If the targetNode is within the folder we are dragging for (i = 0; i < ln; i++) { record = draggedRecords[i]; @@ -37,10 +41,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.tree.DragAndDrop', { } // Respect the allowDrop field on Tree nodes - if (position === 'append' && targetNode.get('allowDrop') === false) { - return false; - } - else if (position !== 'append' && targetNode.parentNode.get('allowDrop') === false) { + if (targetNode.get('allowDrop') === false || targetNode.parentNode.get('allowDrop') === false) { return false; } @@ -53,17 +54,19 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.tree.DragAndDrop', { for (i = 0; i < ln; i++) { record = draggedRecords[i]; // check if the node is in the same iteration - if (record.get('adapter') !== targetNode.get('adapter')) { + if (record.parentNode !== targetNode.parentNode + && record.get('adapter') !== targetNode.get('adapter') + ) { return false; } // special case check: node cannot be inserted in the same level as the iteration node - if (position === 'before' && record.get('adapter') !== targetNode.parentNode.get('adapter')) { + if (record.parentNode !== targetNode.parentNode + && position === 'before' && record.get('adapter') !== targetNode.parentNode.get('adapter') + ) { return false; } } - // @TODO: fire some event to notify that there is a valid drop possible for the node you're dragging - // Yes: this.fireViewEvent(blah....) fires an event through the owning View. return true; }; } diff --git a/Views/backend/swag_import_export/view/profile/window.js b/Views/backend/swag_import_export/view/profile/window.js index c23d0606..acdeb462 100644 --- a/Views/backend/swag_import_export/view/profile/window.js +++ b/Views/backend/swag_import_export/view/profile/window.js @@ -6,7 +6,7 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Window', { alias: 'widget.swag-import-export-profile-window', height: '80%', - width: '80%', + width: '60%', layout: 'fit', @@ -57,7 +57,10 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Window', { me.profileStore = Ext.create('Shopware.apps.SwagImportExport.store.ProfileList', { pageSize: 200, - autoLoad: true + autoLoad: true, + sorters: [ + { property: 'name', direction: 'ASC' } + ] }); me.items = me.buildItems(); @@ -86,84 +89,101 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Window', { }, items: [{ xtype: 'form', + layout: { + type: 'hbox' + }, + trackResetOnLoad: true, itemId: 'profilebaseform', padding: 15, - defaults: { - anchor: '50%' - }, border: false, items: [{ - xtype: 'hidden', - name: 'id' - }, { - xtype: 'textfield', - itemId: 'namefield', - readOnly: me.readOnly, - fieldLabel: '{s name=swag_import_export/profile/window/field_name}Profile name{/s}', - name: 'name', - allowBlank: false - }, { - xtype: 'hidden', - name: 'type' - }, { - xtype: 'combo', - name: 'baseProfile', - itemId: 'baseProfile', - fieldLabel: '{s name=swag_import_export/profile/window/field_based_on}Based on{/s}', - allowBlank: false, - editable: false, - triggerAction: 'all', - store: me.profileStore, - listConfig: { - getInnerTpl: function () { - return Ext.XTemplate( - '{literal}' + - '{ translation } ({ name })' + - '{ name }' + - '{/literal}' - ); - }, - width: 305 + xtype: 'container', + flex: 1, + layout: 'anchor', + defaults: { + anchor: '100%' }, - valueField: 'id', - displayTpl: new Ext.XTemplate( - '' + - '{literal}' + - '{[typeof values === "string" ? values : this.getFormattedName(values)]}' + - '' + me.delimiter + '' + - '{/literal}' + - '', - { - getFormattedName: function(values) { - if (values.translation) { - return Ext.String.format('[0] ([1])', values.translation, values.name); - } - return values.name; - } - } - ), - helpText: '{s name=swag_import_export/profile/window/profile_helptext}The selected default profile can be individually extended and modified via the configuration tree and be saved as a custom profile.{/s}', - listeners: { - boxready: function(combo) { - combo.relayEvents(combo.getStore(), ['load'], 'store'); + items: [{ + xtype: 'hidden', + name: 'id' + }, { + xtype: 'textfield', + itemId: 'namefield', + readOnly: me.readOnly, + fieldLabel: '{s name=swag_import_export/profile/window/field_name}Profile name{/s}', + name: 'name', + allowBlank: false + }, { + xtype: 'hidden', + name: 'type' + }, { + xtype: 'combo', + name: 'baseProfile', + itemId: 'baseProfile', + fieldLabel: '{s name=swag_import_export/profile/window/field_based_on}Based on{/s}', + allowBlank: false, + editable: false, + triggerAction: 'all', + store: me.profileStore, + listConfig: { + getInnerTpl: function () { + return Ext.XTemplate( + '{literal}' + + '{ name } ({ translation })' + + '{ name }' + + '{/literal}' + ); + }, + width: 305 }, - storeload: function() { - if (!Ext.isEmpty(me.profileId)) { - if (Ext.isEmpty(this.getValue())) { - this.disable(); - return; + valueField: 'id', + displayTpl: new Ext.XTemplate( + '' + + '{literal}' + + '{[typeof values === "string" ? values : this.getFormattedName(values)]}' + + '' + me.delimiter + '' + + '{/literal}' + + '', + { + getFormattedName: function(values) { + if (values.translation) { + return Ext.String.format('[0] ([1])', values.translation, values.name); + } + return values.name; } - this.validate(); } - }, - select: function(combo, selectedRecords) { - var selection = selectedRecords[0], - typefield = combo.previousSibling('hidden[name=type]'); + ), + helpText: '{s name=swag_import_export/profile/window/profile_helptext}The selected default profile can be individually extended and modified via the configuration tree and be saved as a custom profile.{/s}', + listeners: { + boxready: function(combo) { + combo.relayEvents(combo.getStore(), ['load'], 'store'); + }, + storeload: function() { + if (!Ext.isEmpty(me.profileId)) { + if (Ext.isEmpty(this.getValue())) { + this.disable(); + return; + } + this.validate(); + } + }, + select: function(combo, selectedRecords) { + var selection = selectedRecords[0], + typefield = combo.previousSibling('hidden[name=type]'); - typefield.setValue(selection.get('type')) - me.fireEvent('baseprofileselected', me, selection); + typefield.setValue(selection.get('type')) + me.fireEvent('baseprofileselected', me, selection); + } } - } + }] + }, { + xtype: 'container', + margin: '0 10px 0 70px', + flex: 1, + items: [{ + xtype: 'displayfield', + name: 'description' + }] }] }, me.profileConfigurator] }]; @@ -195,22 +215,8 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.Window', { cls: 'primary', itemId: 'savebutton', disabled: me.readOnly, - handler: function () { + handler: function() { me.fireEvent('saveProfile', me); - - if (me.profileId !== null) { - me.fireEvent( - 'saveNode', - me.profileConfigurator.treePanel, - me.profileConfigurator.treeStore, - me.profileConfigurator.selectedNodeId, - me.profileConfigurator.formPanel.child('#nodeName').getValue(), - me.profileConfigurator.formPanel.child('#swColumn').getValue(), - me.profileConfigurator.formPanel.child('#defaultValue').getValue(), - me.profileConfigurator.formPanel.child('#adapter').getValue(), - me.profileConfigurator.formPanel.child('#parentKey').getValue() - ); - } } }] }); diff --git a/Views/backend/swag_import_export/view/profile/window/column.js b/Views/backend/swag_import_export/view/profile/window/column.js new file mode 100644 index 00000000..2525b74a --- /dev/null +++ b/Views/backend/swag_import_export/view/profile/window/column.js @@ -0,0 +1,196 @@ +//{namespace name=backend/swag_import_export/view/profile/column} +//{block name="backend/swag_import_export/view/profile/window/column"} +Ext.define('Shopware.apps.SwagImportExport.view.profile.window.Column', { + /** + * Define that the order main window is an extension of the enlight application window + * @string + */ + extend: 'Enlight.app.Window', + padding: 5, + + /** + * List of short aliases for class names. Most useful for defining xtypes for widgets. + * @string + */ + alias: 'widget.swag-import-export-column-window', + + width: 500, + height: 200, + + layout: 'fit', + title: '{s name=swag_import_export/profile/column/title}Add column{/s}', + + config: { + treePanel: null, + profileId: null, + adapter: null + }, + + initComponent: function() { + var me = this; + + me.items = me.buildItems(); + me.dockedItems = me.buildDockedItems(); + + me.callParent(arguments); + }, + + buildItems: function() { + var me = this; + + me.formPanel = Ext.create('Ext.form.Panel', { + defaults: { + anchor: '100%' + }, + fieldDefaults: { + labelWidth: 150 + }, + border: false, + bodyPadding: 10, + items: [{ + xtype: 'textfield', + fieldLabel: '{s name=swag_import_export/profile/column/node_name}Name{/s}', + name: 'nodeName', + allowBlank: false + }, { + xtype: 'combobox', + fieldLabel: '{s name=swag_import_export/profile/column/shopware_column}Database mapping{/s}', + editable: false, + emptyText: '{s name=swag_import_export/profile/column/select_column}Select column{/s}', + queryMode: 'local', + store: Ext.create('Shopware.apps.SwagImportExport.store.Column', { + autoLoad: true, + proxy: { + type: 'ajax', + api: { + read: '{url controller="SwagImportExportProfile" action="getColumns"}' + }, + extraParams: { + adapter: me.getAdapter(), + profileId: me.getProfileId() + }, + actionMethods: 'POST', + reader: { + type: 'json', + root: 'data' + }, + writer: { + type: 'json', + root: 'data' + } + } + }), + valueField: 'id', + displayField: 'name', + name: 'swColumn', + allowBlank: false, + listeners: { + scope: me, + select: function(combo, records) { + var selection = records[0]; + + if (me.formPanel.items.getCount() === 3) { + me.formPanel.items.getAt(2).destroy(); + } + if (selection.get('default') === 'true') { + me.createDefaultValueField(selection.get('type')); + } + } + } + }] + }); + + return me.formPanel; + }, + + buildDockedItems: function() { + var me = this; + + me.bottomBar = Ext.create('Ext.toolbar.Toolbar', { + xtype: 'toolbar', + dock: 'bottom', + ui: 'shopware-ui', + cls: 'shopware-toolbar', + style: { + backgroundColor: '#F0F2F4', + borderRight: '1px solid #A4B5C0', + borderLeft: '1px solid #A4B5C0', + borderTop: '1px solid #A4B5C0', + borderBottom: '1px solid #A4B5C0' + }, + items: ['->', { + text: '{s name=swag_import_export/profile/column/close}Close{/s}', + cls: 'secondary', + handler: function() { + me.close(); + } + }, { + text: '{s name=swag_import_export/profile/column/save}Save{/s}', + cls: 'primary', + handler: function () { + if (me.formPanel.getForm().isValid()) { + me.fireEvent('addNode', me); + } + } + }] + }); + + return me.bottomBar; + }, + + createDefaultValueField: function(type) { + var me = this, + fieldConfig; + + switch (type) { + case 'id': + fieldConfig = { xtype: 'numberfield', minValue: 1 }; + break; + case 'integer': + case 'decimal': + case 'float': + var precision = 0; + if (type.precision) { + precision = type.precision + } else if (type.type == 'float') { + precision = 3; + } else if (type.type == 'decimal') { + precision = 3; + } + fieldConfig = { xtype: 'numberfield', decimalPrecision: precision }; + break; + case 'string': + case 'text': + fieldConfig = { xtype: 'textfield' }; + break; + case 'boolean': + fieldConfig = { + xtype: 'checkbox', + inputValue: 1, + uncheckedValue: 0 + }; + break; + case 'date': + case 'dateTime': + fieldConfig = { + xtype: 'datefield', + format: 'Y-m-d', + submitFormat: 'Y-m-d' + }; + break; + default: + fieldConfig = { + hidden: true + }; + break; + } + + fieldConfig = Ext.apply(fieldConfig, { + fieldLabel: '{s name=swag_import_export/profile/column/default_value}Default value{/s}', + name: 'defaultValue' + }); + + me.formPanel.add(fieldConfig); + } +}); +//{/block} \ No newline at end of file diff --git a/Views/backend/swag_import_export/view/profile/window/iterator.js b/Views/backend/swag_import_export/view/profile/window/iterator.js new file mode 100644 index 00000000..9f58f800 --- /dev/null +++ b/Views/backend/swag_import_export/view/profile/window/iterator.js @@ -0,0 +1,239 @@ +//{namespace name=backend/swag_import_export/view/profile/iterator} +//{block name="backend/swag_import_export/view/profile/window/iterator"} +Ext.define('Shopware.apps.SwagImportExport.view.profile.window.Iterator', { + /** + * Define that the order main window is an extension of the enlight application window + * @string + */ + extend: 'Enlight.app.Window', + padding: 5, + + /** + * List of short aliases for class names. Most useful for defining xtypes for widgets. + * @string + */ + alias: 'widget.swag-import-export-iterator-window', + + width: 615, + height: 430, + + layout: { + type: 'vbox', + align: 'stretch' + }, + + config: { + sectionStore: null, + treePanel: null, + profileId: null + }, + + title: '{s name=swag_import_export/profile/iterator/title}Extend dataset{/s}', + + initComponent: function() { + var me = this, + treePanel; + + me.items = me.buildItems(); + me.dockedItems = me.buildDockedItems(); + + me.callParent(arguments); + }, + + buildItems: function() { + var me = this; + + me.formPanel = me.buildFormPanel(); + me.columnGrid = me.buildColumnGrid(); + + return [ + me.formPanel, + me.columnGrid + ]; + }, + + buildDockedItems: function() { + var me = this; + + me.bottomBar = Ext.create('Ext.toolbar.Toolbar', { + xtype: 'toolbar', + dock: 'bottom', + ui: 'shopware-ui', + cls: 'shopware-toolbar', + style: { + backgroundColor: '#F0F2F4', + borderRight: '1px solid #A4B5C0', + borderLeft: '1px solid #A4B5C0', + borderTop: '1px solid #A4B5C0', + borderBottom: '1px solid #A4B5C0' + }, + items: ['->', { + text: '{s name=swag_import_export/profile/iterator/close}Close{/s}', + cls: 'secondary', + handler: function() { + me.close(); + } + }, { + text: '{s name=swag_import_export/profile/iterator/save}Save{/s}', + cls: 'primary', + handler: function () { + if (me.formPanel.getForm().isValid()) { + me.fireEvent('addIterator', me); + } + } + }] + }); + + return me.bottomBar; + }, + + buildFormPanel: function() { + var me = this; + + return Ext.create('Ext.form.Panel', { + defaults: { + anchor: '100%' + }, + fieldDefaults: { + labelWidth: 150 + }, + flex: 1, + border: false, + bodyPadding: 10, + items: [{ + xtype: 'textfield', + fieldLabel: '{s name=swag_import_export/profile/iterator/node_name}Node name{/s}', + name: 'nodeName', + allowBlank: false + }, { + xtype: 'combo', + fieldLabel: '{s name=swag_import_export/profile/iterator/adapter}Extension{/s}', + emptyText: '{s name=swag_import_export/profile/iterator/select_adapter}Select extension{/s}', + queryMode: 'local', + store: me.sectionStore, + valueField: 'id', + displayField: 'name', + name: 'adapter', + allowBlank: false, + editable: false, + listeners: { + change: function(field, newValue) { + var keyField = field.nextSibling('combo[name=parentKey]'), + loadParams = { + params: { + profileId: me.getProfileId(), + adapter: newValue + } + }; + keyField.clearValue(); + me.columnGrid.getStore().load(loadParams); + loadParams.callback = function(records) { + keyField.setDisabled(records.length === 0); + keyField.setVisible(records.length > 0); + }; + keyField.getStore().load(loadParams); + } + } + }, { + xtype: 'combobox', + fieldLabel: '{s name=swag_import_export/profile/iterator/parent_key}Parent key{/s}', + emptyText: '{s name=swag_import_export/profile/iterator/select_parent_key}Select parent key{/s}', + store: Ext.create('Shopware.apps.SwagImportExport.store.ParentKey'), + queryMode: 'local', + editable: false, + valueField: 'id', + displayField: 'name', + allowBlank: false, + name: 'parentKey' + }] + }); + }, + + buildColumnGrid: function() { + var me = this; + + return Ext.create('Ext.grid.Panel', { + flex: 2, + border: false, + title: '{s name=swag_import_export/profile/iterator/grid_title}Set columns{/s}', + selType: 'rowmodel', + plugins: [ + Ext.create('Ext.grid.plugin.RowEditing', { + clicksToEdit: 1 + }) + ], + viewConfig: { + plugins: { + ptype: 'gridviewdragdrop' + } + }, + store: Ext.create('Ext.data.Store', { + fields: [ + { name: 'swColumn', mapping: 'name' }, + { name: 'nodeName', mapping: 'name' }, + { name: 'select', type: 'boolean', defaultValue: true } + ], + proxy: { + type: 'ajax', + api: { + read: '{url controller="SwagImportExportProfile" action="getColumns"}' + }, + actionMethods: 'POST', + reader: { + type: 'json', + root: 'data' + }, + writer: { + type: 'json', + root: 'data' + } + }, + listeners: { + scope: me, + load: function() { + me.columnGrid.getSelectionModel().selectAll(); + } + } + }), + columns: [ + { + header: '{s name=swag_import_export/profile/iterator/grid_column_column}Database mapping{/s}', + dataIndex: 'swColumn', + flex: 1 + }, + { + header: '{s name=swag_import_export/profile/iterator/grid_column_name}Name{/s}', + dataIndex: 'nodeName', + flex: 1, + editor: { + xtype: 'textfield', + allowBlank: false + } + }, + { + header: '{s name=swag_import_export/profile/iterator/grid_column_selected}Selected{/s}', + dataIndex: 'select', + width: 80, + renderer: function(value) { + var cls = 'sprite-tick'; + + if (value == false) { + cls = 'sprite-cross'; + } + + return Ext.String.format( + '
 
', + cls + ); + }, + editor: { + xtype: 'checkbox', + inputValue: true, + uncheckedValue: false + } + } + ] + }); + } +}); +//{/block} diff --git a/Views/backend/swag_import_export/view/profile/window/mappings.js b/Views/backend/swag_import_export/view/profile/window/mappings.js index 20533bd3..7b2db35d 100644 --- a/Views/backend/swag_import_export/view/profile/window/mappings.js +++ b/Views/backend/swag_import_export/view/profile/window/mappings.js @@ -128,14 +128,14 @@ Ext.define('Shopware.apps.SwagImportExport.view.profile.window.Mappings', { tbar: me.createGridToolbar(), selModel: me.getGridSelModel(), columns: [{ - text: '{s name=swag_import_export/profile/window/shopware_field}Shopware field{/s}', + text: '{s name=swag_import_export/profile/window/shopware_field}Field{/s}', flex: 1, sortable: true, dataIndex: 'variable', editor: { xtype: 'combobox', editable: false, - emptyText: '{s name=swag_import_export/profile/window/select_column}Select column{/s}', + emptyText: '{s name=swag_import_export/profile/window/select_column}Select field{/s}', queryMode: 'local', store: Ext.create('Shopware.apps.SwagImportExport.store.Column').load({ params: { profileId: me.profileId, adapter: 'default' } }), valueField: 'id', diff --git a/Views/backend/swag_import_export/view/window.js b/Views/backend/swag_import_export/view/window.js index c0f614bd..8cf9e6ba 100644 --- a/Views/backend/swag_import_export/view/window.js +++ b/Views/backend/swag_import_export/view/window.js @@ -40,7 +40,11 @@ Ext.define('Shopware.apps.SwagImportExport.view.Window', { /*{if {acl_is_allowed privilege=profile}}*/ aclItems.push(Ext.create('Shopware.apps.SwagImportExport.view.profile.Grid', { // using new instance here because grid uses filtering - store: Ext.create('Shopware.apps.SwagImportExport.store.ProfileList'), + store: Ext.create('Shopware.apps.SwagImportExport.store.ProfileList', { + sorters: [ + { property: 'name', direction: 'ASC' } + ] + }), listeners: { activate: function(grid) { grid.getStore().load(); diff --git a/plugin.json b/plugin.json index 5460ee53..e1f2a4cf 100644 --- a/plugin.json +++ b/plugin.json @@ -8,7 +8,7 @@ "link": "http://store.shopware.com", "author": "Shopware AG", - "currentVersion": "2.0.1", + "currentVersion": "2.0.2", "changelog": { "de": {