Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
7f22e76
[+FEAT] Ability to import customer wishlists.
paales Dec 23, 2013
14210ac
fixed unit test fixtures for environment
bastianccm Mar 3, 2015
96a3274
Added failing test
barbazul Apr 6, 2015
77d5aed
Fixed error accessing invalid array key
barbazul Apr 6, 2015
26ebb02
Fixed validation error so the root category gets validated before the…
barbazul Apr 6, 2015
eefbb7d
Fixed Zend coding standard for modified lines
barbazul Apr 6, 2015
89a707e
Update version in readme
rbrown Apr 16, 2015
b5beca5
Merge pull request #224 from rbrown/patch-1
paales Apr 17, 2015
ab32a84
Fix invalidating valid rows - issue #220
mbijnsdorp Apr 22, 2015
eb1ff2a
Merge customer-wishlist branch, ability to import customer wishlists
paales Apr 29, 2015
7cadf85
Fixing Store View Attachment for Images, otherwise Images will all be…
jadhub May 22, 2015
2f99552
[BUG] Fix failing unit tests after last change
May 27, 2015
da1be62
[BUG] Fix missing store id during import
May 27, 2015
d6517d2
[ENH] Better handling for store in media import
May 28, 2015
798b312
[BUG] Product import does not handle per-store-images well
May 29, 2015
45c9aad
[BUG] Create tmp target folders for media targets with paths
Jun 11, 2015
481bcb8
Merge pull request #239 from YouweGit/fix-customer-import-wrong-inval…
paales Jun 16, 2015
5b62b72
[ENH] Try to fix failing phpunit tests
Jun 25, 2015
7b2e643
added more default stores to circumvent dificult test situations base…
bastianccm Jun 25, 2015
0865bfa
removed load() on collections to resolve a bug where the load added a…
bastianccm Jul 1, 2015
a304f54
Added customer observer.
paales Jul 5, 2015
0b1ed2b
Fix issue when customer couldn't be found
paales Jul 5, 2015
5381e32
Fix issue when value isn't set
paales Jul 5, 2015
bca5e32
Implemented methods to access the import data using an observer.
paales Jul 5, 2015
bd8013a
Fix issue where customer import was very slow because it tried to imp…
paales Jul 6, 2015
e4e9923
[BUG] Handle 404 on image fetch by http
Jul 13, 2015
961d72a
[BUG] Curl must not send headers
Jul 14, 2015
acc67c2
Feat: Allow importing of categories by ID (make sure the name is set)
paales Sep 16, 2015
da7f276
Implemented getEntityByCategory for accessing imported ids.
paales Sep 16, 2015
99ade45
FEAT: EE: Directly reindex the category indexers after importing.
paales Sep 21, 2015
1233d6f
FEAT: EE: Directly reindex the product indexers after importing.
paales Sep 21, 2015
f29edeb
Fix: Actually load models with getModel instead of using the new keyword
paales Sep 30, 2015
27da9a7
#258 fix positioning of super attributes in configurable products.
Oct 14, 2015
8df2a57
Filtered stock data before save
ericrisler Oct 15, 2015
27c3ad3
Merge pull request #261 from erisler-myntpartners/master
paales Oct 15, 2015
2ab2f53
Revert "Fix: Actually load models with getModel instead of using the …
paales Oct 15, 2015
7f97d4e
Merge pull request #260 from pquerner/master
avstudnitz Oct 27, 2015
74176eb
Feat: added support for Enterprise OnTab module
paales Oct 29, 2015
fa3212a
FIX: Do not require all fields to be set.
paales Oct 30, 2015
8280983
Solve issue where the importer uses a lof of memory while processing …
paales Nov 9, 2015
04f2aa0
Solve issue with insert query onTab products
paales Nov 23, 2015
b7faf9f
Merge pull request #266 from avstudnitz/feature/ontab
paales Dec 3, 2015
c2855dc
Merge branch 'master' into develop
paales Dec 8, 2015
fe6f57e
Fixes #268 introduced in 5a9ca8d
Dec 9, 2015
eb94f07
[FIX] avoid syntax error, unexpected '['
Dec 10, 2015
b18fc69
Merge pull request #272 from mhauri/master
avstudnitz Dec 14, 2015
34962d9
Merge pull request #217 from barbazul/issue216
avstudnitz Jan 28, 2016
cfc19c3
Merge branch 'AOEpeople-master' into test-aoe
avstudnitz Jan 28, 2016
fc4e5ed
Fix merging error
avstudnitz Jan 28, 2016
c0a8c11
Merge branch 'test-aoe' into develop
avstudnitz Jan 28, 2016
57ad533
Fix getAffectedEntityIds() for category (missing root)
Mar 26, 2015
2d9a12f
Pull request #227
avstudnitz Jan 28, 2016
93c042f
Pull request #228
avstudnitz Jan 28, 2016
8abed7a
Pull request #262
avstudnitz Jan 28, 2016
e81ca33
New version 0.7.0
avstudnitz Feb 14, 2016
f741c0a
[fix] add support for PHP 5.3
Feb 29, 2016
377e982
Merge pull request #293 from mhauri/develop
avstudnitz Feb 29, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Wrapper for Magento ImportExport functionality which imports data from arrays

Facts
-----
- version: 0.6.3
- version: 0.7.0
- extension key: AvS_FastSimpleImport
- extension on Magento Connect: n/a
- Magento Connect 1.0 extension key: n/a
Expand All @@ -22,14 +22,14 @@ Description
This module allows to import from arrays and thus using any import source, while the Magento module only imports from files.
ImportExport exists since Magento 1.5 CE / 1.10 EE, image import since 1.6 CE / 1.11 EE. Thus, this module needs at least
one of those versions.
ImportExport has a special import format. See [specifications](http://www.integer-net.de/download/ImportExport_EN.pdf) about the expected format.
ImportExport has a special import format. See [specifications](https://www.integer-net.com/importing-products-with-the-import-export-interface/) about the expected format.

Main Features:

- Fast Import using the built in Magento module ImportExport
- Partial Indexing of only the imported products available
- Unit tests for many test cases included
- Importing of additional entities: Categories, Category-Product relations, attribute options (coming soon)
- Importing of additional entities: Categories, Category-Product relations
- Improved error messages stating which values are expected instead of a given value

Please see our [**documentation**](http://avstudnitz.github.io/AvS_FastSimpleImport/) for a full list of features.
Expand All @@ -46,9 +46,10 @@ Compatibility
Installation Instructions
-------------------------
1. Install the extension via GitHub, composer or a similar method.
2. Clear the cache, logout from the admin panel and then login again.
3. Read the [documentation](http://avstudnitz.github.io/AvS_FastSimpleImport/)
4. Configure the extension under System -> Configuration -> Services -> FastSimpleImport.
2. If you are using the Enterprise Edition then add ```<Enterprise_ImportExport/>``` to the ```<depends>``` node directly after ```<Mage_ImportExport/>```
3. Clear the cache, logout from the admin panel and then login again.
4. Read the [documentation](http://avstudnitz.github.io/AvS_FastSimpleImport/)
5. Configure the extension at `System -> Configuration -> Services -> FastSimpleImport`.

Uninstallation
--------------
Expand Down
4 changes: 2 additions & 2 deletions src/app/code/community/AvS/FastSimpleImport/Model/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected function _construct()
$this->setAllowRenameFiles(Mage::getStoreConfigFlag('fastsimpleimport/product/allow_rename_files'));
$this->setImageAttributes(array_filter(explode(',', Mage::getStoreConfig('fastsimpleimport/product/additional_image_attributes'))));
$this->setDisablePreprocessImageData(Mage::getStoreConfigFlag('fastsimpleimport/product/disable_preprocess_images'));
$this->setUnsetEmptyFields(! Mage::getStoreConfigFlag('fastsimpleimport/general/clear_field_on_empty_string'));
$this->setUnsetEmptyFields(Mage::getStoreConfigFlag('fastsimpleimport/general/clear_field_on_empty_string'));
$this->setSymbolEmptyFields(Mage::getStoreConfig('fastsimpleimport/general/symbol_for_clear_field'));
$this->setSymbolIgnoreFields(Mage::getStoreConfig('fastsimpleimport/general/symbol_for_ignore_field'));
}
Expand Down Expand Up @@ -91,7 +91,7 @@ public function processProductImport($data, $behavior = NULL)
$entityAdapter->setUnsetEmptyFields($this->getUnsetEmptyFields());
$entityAdapter->setSymbolEmptyFields($this->getSymbolEmptyFields());
$entityAdapter->setSymbolIgnoreFields($this->getSymbolIgnoreFields());
$entityAdapter->setIgnoreDuplicates($this->getIgnoreDuplicates());
$entityAdapter->setIgnoreDuplicates($this->getIgnoreDuplicates());
$this->setEntityAdapter($entityAdapter);

$validationResult = $this->validateSource($data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,9 @@ public function __construct()
{
parent::__construct();

$this->_initWebsites()
$this
->_initOnTabAttributes()
->_initWebsites()
->_initStores()
->_initCategories()
->_initAttributes()
Expand Down Expand Up @@ -342,6 +344,7 @@ protected function _importData()
$this->_deleteCategories();
} else {
$this->_saveCategories();
$this->_saveOnTab();
}
Mage::dispatchEvent('catalog_category_import_finish_before', array('adapter'=>$this));
return true;
Expand Down Expand Up @@ -378,8 +381,16 @@ protected function _initCategories()
'level' => $category->getLevel(),
'position' => $category->getPosition()
);

//allow importing by ids.
if (!isset($this->_categoriesWithRoots[$structure[1]])) {
$this->_categoriesWithRoots[$structure[1]] = array();
}
$this->_categoriesWithRoots[$structure[1]][$category->getId()] =
$this->_categoriesWithRoots[$rootCategoryName][$index];
}
}

return $this;
}

Expand Down Expand Up @@ -416,7 +427,7 @@ protected function _initWebsites()
/**
* Initialize customer attributes.
*
* @return Mage_ImportExport_Model_Import_Entity_Customer
* @return $this
*/
protected function _initAttributes()
{
Expand Down Expand Up @@ -656,6 +667,7 @@ protected function _getUploader()
$this->_fileUploader = new Mage_ImportExport_Model_Import_Uploader();

$this->_fileUploader->init();
$this->_fileUploader->removeValidateCallback('catalog_product_image');
$this->_fileUploader->setFilesDispersion(false);

$tmpDir = Mage::getConfig()->getOptions()->getMediaDir() . '/import';
Expand Down Expand Up @@ -795,22 +807,22 @@ public function getWebsiteCodes()
*/
protected function _getParentCategory($rowData)
{
$categoryParts = $this->_explodeEscaped('/',$rowData[self::COL_CATEGORY]);
$categoryParts = $this->_explodeEscaped('/', $rowData[self::COL_CATEGORY]);
array_pop($categoryParts);
$parent = $this->_implodeEscaped('/',$categoryParts);
$parent = $this->_implodeEscaped('/', $categoryParts);

if ($parent)
{
if (isset($this->_categoriesWithRoots[$rowData[self::COL_ROOT]][$parent]))
{
if ($parent) {
if (isset($this->_categoriesWithRoots[$rowData[self::COL_ROOT]][$parent])) {
return $this->_categoriesWithRoots[$rowData[self::COL_ROOT]][$parent];
} elseif (isset($this->_newCategory[$rowData[self::COL_ROOT]][$parent])) {
return $this->_newCategory[$rowData[self::COL_ROOT]][$parent];
} else {
return false;
}
} else {
} elseif (isset($this->_categoriesWithRoots[$rowData[self::COL_ROOT]])) {
return reset($this->_categoriesWithRoots[$rowData[self::COL_ROOT]]);
} else {
return false;
}
}

Expand Down Expand Up @@ -877,9 +889,14 @@ public function validateRow(array $rowData, $rowNum)
$root = $rowData[self::COL_ROOT];
$category = $rowData[self::COL_CATEGORY];

//check if the root exists
if (! isset($this->_categoriesWithRoots[$root])) {
$this->addRowError(self::ERROR_INVALID_ROOT, $rowNum);
return false;
}

//check if parent category exists
if ($this->_getParentCategory($rowData) === false)
{
if ($this->_getParentCategory($rowData) === false) {

$this->addRowError(self::ERROR_PARENT_NOT_FOUND, $rowNum);
return false;
Expand All @@ -899,14 +916,6 @@ public function validateRow(array $rowData, $rowNum)
}
}

//check if the root exists
if (! isset($this->_categoriesWithRoots[$root]))
{
$this->addRowError(self::ERROR_INVALID_ROOT, $rowNum);
return false;
}


// check simple attributes
foreach ($this->_attributes as $attrCode => $attrParams) {
if (isset($rowData[$attrCode]) && strlen($rowData[$attrCode])) {
Expand Down Expand Up @@ -947,10 +956,10 @@ public function getAffectedEntityIds()
if (!$this->isRowAllowedToImport($rowData, $rowNum)) {
continue;
}
if (!isset($this->_newCategory[$rowData[self::COL_CATEGORY]]['entity_id'])) {
if (!isset($this->_newCategory[$rowData[self::COL_ROOT]][$rowData[self::COL_CATEGORY]]['entity_id'])) {
continue;
}
$categoryIds[] = $this->_newCategory[$rowData[self::COL_CATEGORY]]['entity_id'];
$categoryIds[] = $this->_newCategory[$rowData[self::COL_ROOT]][$rowData[self::COL_CATEGORY]]['entity_id'];
}
}
return $categoryIds;
Expand Down Expand Up @@ -1107,26 +1116,36 @@ protected function _indexDeleteEvents()
*/
protected function _reindexUpdatedCategories()
{
$entityIds = $this->_getProcessedCategoryIds();

$categoryFlatHelper = Mage::helper('catalog/category_flat');
if ($categoryFlatHelper->isAvailable() && $categoryFlatHelper->isAccessible()) {
Mage::dispatchEvent('fastsimpleimport_reindex_category_before_flat', array('entity_id' => &$entityIds));
Mage::getResourceSingleton('catalog/category_flat')->reindexAll();
}

if (Mage::getResourceModel('ecomdev_urlrewrite/indexer')) {
Mage::dispatchEvent('fastsimpleimport_reindex_category_before_ecomdev_urlrewrite', array('entity_id' => &$entityIds));
Mage::getResourceSingleton('ecomdev_urlrewrite/indexer')->updateCategoryRewrites($entityIds);
if (Mage::helper('core')->isModuleEnabled('Enterprise_Index')) {
Mage::dispatchEvent('fastsimpleimport_reindex_category_enterprise_before');
Mage::getSingleton('enterprise_index/observer')->refreshIndex(Mage::getModel('cron/schedule'));
} else {
Mage::dispatchEvent('fastsimpleimport_reindex_category_before_urlrewrite', array('entity_id' => &$entityIds));
/* @var $urlModel Mage_Catalog_Model_Url */
$urlModel = Mage::getSingleton('catalog/url');
$urlModel->clearStoreInvalidRewrites();
foreach ($entityIds as $productId) {
$urlModel->refreshCategoryRewrite($productId);
$entityIds = $this->_getProcessedCategoryIds();

$categoryFlatHelper = Mage::helper('catalog/category_flat');
if ($categoryFlatHelper->isAvailable() && $categoryFlatHelper->isAccessible()) {

Mage::dispatchEvent('fastsimpleimport_reindex_category_before_flat', array('entity_id' => &$entityIds));
Mage::getResourceSingleton('catalog/category_flat')->reindexAll();
}

if (Mage::helper('core')->isModuleEnabled('EcomDev_UrlRewrite')) {

Mage::dispatchEvent('fastsimpleimport_reindex_category_before_ecomdev_urlrewrite', array('entity_id' => &$entityIds));
Mage::getResourceSingleton('ecomdev_urlrewrite/indexer')->updateCategoryRewrites($entityIds);
} else {

Mage::dispatchEvent('fastsimpleimport_reindex_category_before_urlrewrite', array('entity_id' => &$entityIds));
/* @var $urlModel Mage_Catalog_Model_Url */
$urlModel = Mage::getSingleton('catalog/url');
$urlModel->clearStoreInvalidRewrites();
foreach ($entityIds as $productId) {
$urlModel->refreshCategoryRewrite($productId);
}
}
}

Mage::dispatchEvent('fastsimpleimport_reindex_category_after', array('entity_id' => &$entityIds));

return $this;
Expand Down Expand Up @@ -1243,4 +1262,160 @@ protected function _saveValidatedBunches()
}
return $this;
}


/**
* @param $sku
* @return array|false
*/
public function getEntityByCategory($root, $category)
{
if (isset($this->_categoriesWithRoots[$root][$category])) {
return $this->_categoriesWithRoots[$root][$category];
}

if (isset($this->_newCategory[$root][$category])) {
return $this->_newCategory[$root][$category];
}

return false;
}


/**
* @return $this
*/
protected function _initOnTabAttributes()
{
if (Mage::helper('core')->isModuleEnabled('OnTap_Merchandiser')) {
$this->_particularAttributes = array_merge($this->_particularAttributes, array(
'_ontap_heroproducts',
'_ontap_attribute',
'_ontap_attribute_value',
'_ontap_attribute_logic',
'_ontap_ruled_only',
'_ontap_automatic_sort'
));
}
return $this;
}

/**
* Stock item saving.
* Overwritten in order to fix bug with stock data import
* See http://www.magentocommerce.com/bug-tracking/issue/?issue=13539
* See https://github.com/avstudnitz/AvS_FastSimpleImport/issues/3
*
* @return Mage_ImportExport_Model_Import_Entity_Product
*/
protected function _saveOnTab()
{
if (! Mage::helper('core')->isModuleEnabled('OnTap_Merchandiser')) {
return $this;
}

$entityTable = Mage::getSingleton('core/resource')->getTableName('merchandiser_category_values');
$categoryId = null;
$attributeIdsByCode = array();

while ($bunch = $this->_dataSourceModel->getNextBunch()) {
$onTapData = array();

// Format bunch to stock data rows
foreach ($bunch as $rowNum => $rowData) {
$this->_filterRowData($rowData);
if (!$this->isRowAllowedToImport($rowData, $rowNum)) {
continue;
}

if (self::SCOPE_DEFAULT == $this->getRowScope($rowData)) {
$category = $this->getEntityByCategory($rowData[self::COL_ROOT], $rowData[self::COL_CATEGORY]);
$categoryId = (int) $category['entity_id'];

$onTapData[$categoryId] = array(
'category_id' => $categoryId,
'heroproducts' => '',
'attribute_codes' => '',
'smart_attributes' => '',
'ruled_only' => '',
'automatic_sort' => ''
);
}

//we have a non-SCOPE_DEFAULT row, we check if it has a stock_id, if not, skip it.
if (self::SCOPE_DEFAULT == $this->getRowScope($rowData)) {
if (isset($rowData['_ontap_ruled_only'])) {
$onTapData[$categoryId]['ruled_only'] = (int) $rowData['_ontap_ruled_only'];
}
if (isset($rowData['_ontap_automatic_sort'])) {
$onTapData[$categoryId]['automatic_sort'] = $rowData['_ontap_automatic_sort'];
}
}

//get the _ontab_* smart attribute values and map them to the new keys that are present in the database.
$smartAttributes = array_intersect_key($rowData, array(
'_ontap_attribute' => '',
'_ontap_attribute_value' => '',
'_ontap_attribute_logic' => '',
));

//only add if we've found data
//todo check if we've got all values, there should be three, else it will throw an error here.
if ($smartAttributes) {
if (! isset($onTapData[$categoryId]['attribute_codes'])) {
$onTapData[$categoryId]['attribute_codes'] = array();
$onTapData[$categoryId]['smart_attributes'] = array();
}

$smartAttributes = array_combine(array('attribute', 'value', 'link'), $smartAttributes);

if (! isset($attributeIdsByCode[$smartAttributes['attribute']])) {
$attributeIdsByCode[$smartAttributes['attribute']] =
Mage::getSingleton('catalog/product')
->getResource()
->getAttribute($smartAttributes['attribute'])
->getId();
}

$attributeCode = $smartAttributes['attribute'];
$smartAttributes['attribute'] = $attributeIdsByCode[$smartAttributes['attribute']];

$onTapData[$categoryId]['attribute_codes'][] = $attributeCode;
$onTapData[$categoryId]['smart_attributes'][] = $smartAttributes;
}

if (isset($rowData['_ontap_heroproducts'])) {
if (! isset($onTapData[$categoryId]['heroproducts'])) {
$onTapData[$categoryId]['heroproducts'] = array();
}
$onTapData[$categoryId]['heroproducts'][] = $rowData['_ontap_heroproducts'];
}
}

if ($onTapData) {
//flatten data
foreach ($onTapData as $catId => &$onTapRow) {
if (! empty($onTapRow['attribute_codes'])) {
$onTapRow['attribute_codes'] = implode(',', array_unique($onTapRow['attribute_codes']));
}
if (! empty($onTapRow['heroproducts'])) {
$onTapRow['heroproducts'] = implode(',', $onTapRow['heroproducts']);
}
if (! empty($onTapRow['smart_attributes'])) {
$onTapRow['smart_attributes'] = serialize($onTapRow['smart_attributes']);
}

if (count($onTapRow) <= 1) {
unset($onTapData[$catId]);
}
}

//Insert Data
if ($onTapData) {
$this->_connection->insertOnDuplicate($entityTable, $onTapData);
}
}
}
return $this;
}
}
Loading