Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CatalogImportExport categoryProcessor does not support escaped delimiter #6948

Closed
koenner01 opened this issue Oct 10, 2016 · 12 comments
Closed
Assignees
Labels
bug report Component: ImportExport Fixed in 2.3.x The issue has been fixed in 2.3 release line Issue: Clear Description Gate 2 Passed. Manual verification of the issue description passed Issue: Confirmed Gate 3 Passed. Manual verification of the issue completed. Issue is confirmed Issue: Format is valid Gate 1 Passed. Automatic verification of issue format passed Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development Reproduced on 2.1.x The issue has been reproduced on latest 2.1 release Reproduced on 2.2.x The issue has been reproduced on latest 2.2 release Reproduced on 2.3.x The issue has been reproduced on latest 2.3 release

Comments

@koenner01
Copy link
Contributor

When trying to import a category with an escaped '/' through the import functionality of MG2, the import will create an unwanted extra category because there is no support for escaped delimiters.

Preconditions

  1. MG2 CE 2.1.1
  2. PHP7.0

Steps to reproduce

  1. Create a .csv file with a test product
  2. Add value 'Default Category/Test/Subchild 1/2' for the _categories column
  3. Import the csv through the Import products functionality in the backend.

Expected result

  1. Magento should create 2 categories 'Test' and 'Subchild 1/2'

Actual result

  1. Magento creates 3 categories 'Test', 'Subchild 1' and '2'

A possible solution would be:
In \Magento\CatalogImportExport\Model\Import\Product\Category there is a function upsertCategory.

    protected function upsertCategory($categoryPath)
    {
        if (!isset($this->categories[$categoryPath])) {
            $pathParts = explode(self::DELIMITER_CATEGORY, $categoryPath);
            $parentId = \Magento\Catalog\Model\Category::TREE_ROOT_ID;
            $path = '';

            foreach ($pathParts as $pathPart) {
                $path .= $pathPart;
                if (!isset($this->categories[$path])) {
                    $this->categories[$path] = $this->createCategory($pathPart, $parentId);
                }
                $parentId = $this->categories[$path];
                $path .= self::DELIMITER_CATEGORY;
            }
        }

        return $this->categories[$categoryPath];
    }

The explode on the delimiter does not take into account any escaped delimiters. To create support for categories with the delimiter character in their name, the line should be changed to something like

$pathParts = preg_split('~(?<!\\\)' . preg_quote(self::DELIMITER_CATEGORY, '~') . '~', $categoryPath);

After that the escaped delimiter part should be replaced with the delimiter character.

@nikoelgatito
Copy link
Contributor

I encountered the same issue and I was able to modify the method to make it work. Right when I was about to create a new bug report, I found this one.

Escape string: \

Please find my tested and working solution below:

methodMagento\CatalogImportExport\Model\Import\Product\CategoryProcessor::upsertCategory()

protected function upsertCategory($plainCategoryPath) //1. PARAMETER RENAMED AS IT MAY CONTAIN THE ESCAPE STRING
{
    //2. THIS LINE IS ALSO REQUIRED AS THE PATH NEEDS TO BE FREE FROM ESCAPE STRING WHEN isset() IS USED TO VERIFY IF THE CATEGORY PATH IS ALREADY SET
    $categoryPath = str_replace('\\'.self::DELIMITER_CATEGORY, self::DELIMITER_CATEGORY, $plainCategoryPath);

    if (!isset($this->categories[$categoryPath])) {
        //3. REPLACE EXPLODE FOR preg_split() AND MAKE SURE TO REMOVE THE ESCAPE CHARACTER
        //$pathParts = explode(self::DELIMITER_CATEGORY, $categoryPath);
        $pathParts = str_replace('\\'.self::DELIMITER_CATEGORY, self::DELIMITER_CATEGORY, preg_split('~\\\\.(*SKIP)(*FAIL)|'.self::DELIMITER_CATEGORY.'~s', $plainCategoryPath));
        $parentId = \Magento\Catalog\Model\Category::TREE_ROOT_ID;
        $path = '';

        foreach ($pathParts as $pathPart) {
            $path .= $pathPart;
            if (!isset($this->categories[$path])) {
                $this->categories[$path] = $this->createCategory($pathPart, $parentId);
            }
            $parentId = $this->categories[$path];
            $path .= self::DELIMITER_CATEGORY;
        }
    }

    return $this->categories[$categoryPath];
}

It might be possible to obtain a cleaner version but it is working perfectly as intended.

Use Example:

Default Category/First Category/Second\/2nd Category/Subcategory

Final Result:

|_ > Default Category
    |_ > First Category
        |_ > Second/2nd Category
            |_ > Subcategory

@VincentMarmiesse
Copy link
Contributor

Hello,

Any news on this issue?
Is it planned to merge @nikoelgatito's solution on the future 2.2?

Thanks

@AlexWorking
Copy link

Hello, @koenner01. There has been created an internal ticket-MAGETWO-70462 based on Your issue. You'll be informed after it is resolved. Thanks for applying.

@veloraven veloraven added the Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development label Jul 5, 2017
@magento-engcom-team magento-engcom-team added 2.1.x Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development bug report Issue: Format is valid Gate 1 Passed. Automatic verification of issue format passed Component: ImportExport labels Sep 11, 2017
@magento-engcom-team magento-engcom-team added the Issue: Clear Description Gate 2 Passed. Manual verification of the issue description passed label Oct 4, 2017
@magento-engcom-team
Copy link
Contributor

@koenner01, thank you for your report.
We've created internal ticket(s) MAGETWO-70462 to track progress on the issue.

@magento-engcom-team magento-engcom-team added 2.2.x Issue: Confirmed Gate 3 Passed. Manual verification of the issue completed. Issue is confirmed Reproduced on 2.1.x The issue has been reproduced on latest 2.1 release Reproduced on 2.2.x The issue has been reproduced on latest 2.2 release Reproduced on 2.3.x The issue has been reproduced on latest 2.3 release labels Oct 11, 2017
@serhii-balko serhii-balko self-assigned this Oct 26, 2017
serhii-balko added a commit to serhii-balko/magento2 that referenced this issue Oct 27, 2017
okorshenko pushed a commit that referenced this issue Nov 4, 2017
…support escaped delimiter #11801

 - Merge Pull Request #11801 from serhii-balko/magento2:github-6948
 - Merged commits:
   1. efbf57e
okorshenko pushed a commit that referenced this issue Nov 4, 2017
@magento-team
Copy link
Contributor

Internal ticket to track issue progress: MAGETWO-83131

@okorshenko
Copy link
Contributor

The issue has been fixed and delivered to 2.3-develop branch

@okorshenko okorshenko added the Fixed in 2.3.x The issue has been fixed in 2.3 release line label Nov 4, 2017
@travis5491811
Copy link

@okobchenko anyway to get this working in 2.2.x? I have 2.2.7

@hostep
Copy link
Contributor

hostep commented Feb 25, 2019

@travis5491811 : you can try to patch #11801 into your installation using this guide (at the moment of writing, this link doesn't appear to work due to some Magento/Zendesk server being down, but hopefully it will work again in the near future)

When going for this patch approach, you'll run into a conflict on 2.2.7 with the file dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars.php, but otherwise it's possible to patch all the other files. You can either try to change the patch to fix that one file, or just remove that file from the patch if you don't care about the integration tests of Magento.

But if you don't have much experience with patches, the easiest will be to only patch the files

  • app/code/Magento/CatalogImportExport/Model/Export/Product.php
  • app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php
    otherwise, you'll have to split up the patch into two parts, one for the CatalogImportExport module, and another part for the tests.
    It depends on if you care about the tests and your experience with https://github.com/cweagans/composer-patches/

@travis5491811
Copy link

travis5491811 commented Feb 25, 2019

@hostep thanks for the heads up about the article and what to do. I'm trying to proceed without test files. I edited the composer.json that was in the root directory of project as specified in the guide.

    "extra": {
    "composer-exit-on-patch-failure": true,
    "patches": {
        "magento/module-import-export": {
            "MAGETWO-6948: escape forward slash in category on import": "patches/composer/github-issue-6948.diff"
        }
      }
    }

This is my first time trying to patch. I followed the article and when I run composer -v install, i get the following error it can't find the files.

When editing my patch file I used vim to avoid automatically removing trailing whitespace or adding new lines. vim github-issue-6948.diff -c ":%s/\/app\/code\/Magento\/CatalogImportExport//g"

ls shows the file i created is at /var/www/html/magento2/patches/composer/github-issue-6948.diff however, it looks like it's failing to find the fake a and b directories from the patch install guide. Any idea what I'm suppose to do here?

composer -v install
Gathering patches for root package.
Removing package magento/module-import-export so that it can be re-installed and re-patched.
  - Removing magento/module-import-export (100.2.7)
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
Dependency resolution completed in 0.014 seconds
Analyzed 652 packages to resolve dependencies
Analyzed 4284 rules to resolve dependencies
Gathering patches for root package.
Gathering patches for dependencies. This might take a minute.
Found 1 patches for magento/module-import-export.
  - Installing magento/module-import-export (100.2.7)
    Loading from cache
    Extracting archive

  - Applying patches for magento/module-import-export
    patches/composer/github-issue-6948.diff (MAGETWO-6948: escape forward slash in category on import)
patch '-p1' --no-backup-if-mismatch -d '/var/www/html/magento2/vendor/magento/module-import-export' < '/var/www/html/magento2/patches/composer/github-issue-6948.diff'
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/Model/Export/Product.php b/Model/Export/Product.php
|index 6f9dda090914..97a0e6aaebf4 100644
|--- a/Model/Export/Product.php
|+++ b/Model/Export/Product.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

3 out of 3 hunks ignored

can't find file to patch at input line 52
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/Model/Import/Product/CategoryProcessor.php b/Model/Import/Product/CategoryProcessor.php
|index 81c83c38bb54..788623d822e3 100644
|--- a/Model/Import/Product/CategoryProcessor.php
|+++ b/Model/Import/Product/CategoryProcessor.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

4 out of 4 hunks ignored

patch '-p0' --no-backup-if-mismatch -d '/var/www/html/magento2/vendor/magento/module-import-export' < '/var/www/html/magento2/patches/composer/github-issue-6948.diff'
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/Model/Export/Product.php b/Model/Export/Product.php
|index 6f9dda090914..97a0e6aaebf4 100644
|--- a/Model/Export/Product.php
|+++ b/Model/Export/Product.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

3 out of 3 hunks ignored

can't find file to patch at input line 52
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/Model/Import/Product/CategoryProcessor.php b/Model/Import/Product/CategoryProcessor.php
|index 81c83c38bb54..788623d822e3 100644
|--- a/Model/Import/Product/CategoryProcessor.php
|+++ b/Model/Import/Product/CategoryProcessor.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

4 out of 4 hunks ignored

patch '-p2' --no-backup-if-mismatch -d '/var/www/html/magento2/vendor/magento/module-import-export' < '/var/www/html/magento2/patches/composer/github-issue-6948.diff'
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/Model/Export/Product.php b/Model/Export/Product.php
|index 6f9dda090914..97a0e6aaebf4 100644
|--- a/Model/Export/Product.php
|+++ b/Model/Export/Product.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

3 out of 3 hunks ignored

can't find file to patch at input line 52
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/Model/Import/Product/CategoryProcessor.php b/Model/Import/Product/CategoryProcessor.php
|index 81c83c38bb54..788623d822e3 100644
|--- a/Model/Import/Product/CategoryProcessor.php
|+++ b/Model/Import/Product/CategoryProcessor.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

4 out of 4 hunks ignored

patch '-p4' --no-backup-if-mismatch -d '/var/www/html/magento2/vendor/magento/module-import-export' < '/var/www/html/magento2/patches/composer/github-issue-6948.diff'
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/Model/Export/Product.php b/Model/Export/Product.php
|index 6f9dda090914..97a0e6aaebf4 100644
|--- a/Model/Export/Product.php
|+++ b/Model/Export/Product.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

3 out of 3 hunks ignored

can't find file to patch at input line 52
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/Model/Import/Product/CategoryProcessor.php b/Model/Import/Product/CategoryProcessor.php
|index 81c83c38bb54..788623d822e3 100644
|--- a/Model/Import/Product/CategoryProcessor.php
|+++ b/Model/Import/Product/CategoryProcessor.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

4 out of 4 hunks ignored

   Could not apply patch! Skipping. The error was: Cannot apply patch patches/composer/github-issue-6948.diff

                                                                                                                          
  [Exception]                                                                                                             
  Cannot apply patch MAGETWO-6948: escape forward slash in category on import (patches/composer/github-issue-6948.diff)!  
                                                                                                                          

Exception trace:
 () at /var/www/html/magento2/vendor/cweagans/composer-patches/src/Patches.php:320
 cweagans\Composer\Patches->postInstall() at n/a:n/a
 call_user_func() at /usr/share/php/Composer/EventDispatcher/EventDispatcher.php:171
 Composer\EventDispatcher\EventDispatcher->doDispatch() at /usr/share/php/Composer/EventDispatcher/EventDispatcher.php:114
 Composer\EventDispatcher\EventDispatcher->dispatchPackageEvent() at /usr/share/php/Composer/Installer.php:590
 Composer\Installer->doInstall() at /usr/share/php/Composer/Installer.php:228
 Composer\Installer->run() at /usr/share/php/Composer/Command/InstallCommand.php:134
 Composer\Command\InstallCommand->execute() at /usr/share/php/Symfony/Component/Console/Command/Command.php:256
 Symfony\Component\Console\Command\Command->run() at /usr/share/php/Symfony/Component/Console/Application.php:841
 Symfony\Component\Console\Application->doRunCommand() at /usr/share/php/Symfony/Component/Console/Application.php:189
 Symfony\Component\Console\Application->doRun() at /usr/share/php/Composer/Console/Application.php:166
 Composer\Console\Application->doRun() at /usr/share/php/Symfony/Component/Console/Application.php:120
 Symfony\Component\Console\Application->run() at /usr/share/php/Composer/Console/Application.php:99
 Composer\Console\Application->run() at /usr/bin/composer:44

Assuming I should specify the path relative to project root (vim github-issue-6948.diff -c ":%s/\/app\/code\/Magento\/CatalogImportExport/\/vendor\/magento\/module-import-export/g") results in the following.....

composer -v install
Gathering patches for root package.
Removing package magento/module-import-export so that it can be re-installed and re-patched.
  - Removing magento/module-import-export (100.2.7)
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
Dependency resolution completed in 0.014 seconds
Analyzed 652 packages to resolve dependencies
Analyzed 4284 rules to resolve dependencies
Gathering patches for root package.
Gathering patches for dependencies. This might take a minute.
Found 1 patches for magento/module-import-export.
  - Installing magento/module-import-export (100.2.7)
    Loading from cache
    Extracting archive

  - Applying patches for magento/module-import-export
    patches/composer/github-issue-6948.diff (MAGETWO-6948: escape forward slash in category on import)
patch '-p1' --no-backup-if-mismatch -d '/var/www/html/magento2/vendor/magento/module-import-export' < '/var/www/html/magento2/patches/composer/github-issue-6948.diff'
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/vendor/magento/module-import-export/Model/Export/Product.php b/vendor/magento/module-import-export/Model/Export/Product.php
|index 6f9dda090914..97a0e6aaebf4 100644
|--- a/vendor/magento/module-import-export/Model/Export/Product.php
|+++ b/vendor/magento/module-import-export/Model/Export/Product.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

3 out of 3 hunks ignored
can't find file to patch at input line 52
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------

|diff --git a/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php b/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
|index 81c83c38bb54..788623d822e3 100644
|--- a/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
|+++ b/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

4 out of 4 hunks ignored

patch '-p0' --no-backup-if-mismatch -d '/var/www/html/magento2/vendor/magento/module-import-export' < '/var/www/html/magento2/patches/composer/github-issue-6948.diff'
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/vendor/magento/module-import-export/Model/Export/Product.php b/vendor/magento/module-import-export/Model/Export/Product.php
|index 6f9dda090914..97a0e6aaebf4 100644
|--- a/vendor/magento/module-import-export/Model/Export/Product.php
|+++ b/vendor/magento/module-import-export/Model/Export/Product.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.
3 out of 3 hunks ignored
can't find file to patch at input line 52
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php b/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
|index 81c83c38bb54..788623d822e3 100644
|--- a/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
|+++ b/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.
4 out of 4 hunks ignored

patch '-p2' --no-backup-if-mismatch -d '/var/www/html/magento2/vendor/magento/module-import-export' < '/var/www/html/magento2/patches/composer/github-issue-6948.diff'
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/vendor/magento/module-import-export/Model/Export/Product.php b/vendor/magento/module-import-export/Model/Export/Product.php
|index 6f9dda090914..97a0e6aaebf4 100644
|--- a/vendor/magento/module-import-export/Model/Export/Product.php
|+++ b/vendor/magento/module-import-export/Model/Export/Product.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

3 out of 3 hunks ignored

can't find file to patch at input line 52
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php b/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
|index 81c83c38bb54..788623d822e3 100644
|--- a/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
|+++ b/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

4 out of 4 hunks ignored

patch '-p4' --no-backup-if-mismatch -d '/var/www/html/magento2/vendor/magento/module-import-export' < '/var/www/html/magento2/patches/composer/github-issue-6948.diff'
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/vendor/magento/module-import-export/Model/Export/Product.php b/vendor/magento/module-import-export/Model/Export/Product.php
|index 6f9dda090914..97a0e6aaebf4 100644
|--- a/vendor/magento/module-import-export/Model/Export/Product.php
|+++ b/vendor/magento/module-import-export/Model/Export/Product.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

3 out of 3 hunks ignored

can't find file to patch at input line 52
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php b/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
|index 81c83c38bb54..788623d822e3 100644
|--- a/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
|+++ b/vendor/magento/module-import-export/Model/Import/Product/CategoryProcessor.php
--------------------------
File to patch: 
Skip this patch? [y] 
Skipping patch.

4 out of 4 hunks ignored

   Could not apply patch! Skipping. The error was: Cannot apply patch patches/composer/github-issue-6948.diff

                                                                                                                          
  [Exception]                                                                                                             
  Cannot apply patch MAGETWO-6948: escape forward slash in category on import (patches/composer/github-issue-6948.diff)!  
                                                                                                                          

Exception trace:
 () at /var/www/html/magento2/vendor/cweagans/composer-patches/src/Patches.php:320
 cweagans\Composer\Patches->postInstall() at n/a:n/a
 call_user_func() at /usr/share/php/Composer/EventDispatcher/EventDispatcher.php:171
 Composer\EventDispatcher\EventDispatcher->doDispatch() at /usr/share/php/Composer/EventDispatcher/EventDispatcher.php:114
 Composer\EventDispatcher\EventDispatcher->dispatchPackageEvent() at /usr/share/php/Composer/Installer.php:590
 Composer\Installer->doInstall() at /usr/share/php/Composer/Installer.php:228
 Composer\Installer->run() at /usr/share/php/Composer/Command/InstallCommand.php:134
 Composer\Command\InstallCommand->execute() at /usr/share/php/Symfony/Component/Console/Command/Command.php:256
 Symfony\Component\Console\Command\Command->run() at /usr/share/php/Symfony/Component/Console/Application.php:841
 Symfony\Component\Console\Application->doRunCommand() at /usr/share/php/Symfony/Component/Console/Application.php:189
 Symfony\Component\Console\Application->doRun() at /usr/share/php/Composer/Console/Application.php:166
 Composer\Console\Application->doRun() at /usr/share/php/Symfony/Component/Console/Application.php:120
 Symfony\Component\Console\Application->run() at /usr/share/php/Composer/Console/Application.php:99
 Composer\Console\Application->run() at /usr/bin/composer:44

install [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--no-plugins] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no-progress] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--ignore-platform-reqs] [--] [<packages>]...

That last command made me realize there is no Product.php in Model/Export/ and no Product/ directory in /Model/Import directory in v2.2.7, so i'm not sure this patch can actually be applied to v2.2.7

@hostep
Copy link
Contributor

hostep commented Feb 26, 2019

Hi @travis5491811

Sorry, I'm a bit busy at the moment, maybe I'll find some time later today to help you figure this out, but no promises.

Regarding your last comment, about missing files, that can't be, because they are there in 2.2.7:

As for the paths in the diff file, they should be relative towards the module, so towards vendor/magento/module-import-export, so they should start with a/Model/... and b/Model/...

Hope you can already try to proceed with this info now :)

@travis5491811
Copy link

@hostep you're correct. I'm not sure why I wasn't seeing the files yesterday. They are there. Maybe i'm just loosing my mind because composer is saying they are not there. if the paths should start with a/Model/... `b/Model/', my first attempt was correct from my last post (it had two versions of attempts), but still didn't work.

Thanks for trying to help! The patch guide was helpful and got me close. I changed the path's back to original a/Model/... b/Model/... and still no luck. Maybe it's the a and b that composer is looking for that's messing things up. I don't know.

For now i'm going to write a script that changes all the / inside a category in the import file before the import and then manually change them back in magento categories after import. It's a solution to keep work moving forward but sucks because I still don't understand how to apply patches and at some point I won't have a choice and progress will stop until i figure out how to apply a patch.

For anybody else that see's this, here are my exact steps and files summarized and modified after following this.

  1. Create patches/composer in root of project folder.

  2. From inside that folder run this command to get the file from the appropriate commit:

wget -O github-issue-6948.diff https://github.com/magento/magento2/commit/efbf57eafce7cbe6cd2bb43c928f9b7ebbb3ca8b.diff`
  1. Remove all the test since i'm not concerned with them for this patch. Removing everything from line 107 to end gives you:
diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
index 6f9dda090914..97a0e6aaebf4 100644
--- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
@@ -5,6 +5,7 @@
  */
 namespace Magento\CatalogImportExport\Model\Export;
 
+use Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor;
 use Magento\ImportExport\Model\Import;
 use \Magento\Store\Model\Store;
 use \Magento\CatalogImportExport\Model\Import\Product as ImportProduct;
@@ -438,11 +439,12 @@ protected function initCategories()
             if ($pathSize > 1) {
                 $path = [];
                 for ($i = 1; $i < $pathSize; $i++) {
-                    $path[] = $collection->getItemById($structure[$i])->getName();
+                    $name = $collection->getItemById($structure[$i])->getName();
+                    $path[] = $this->quoteCategoryDelimiter($name);
                 }
                 $this->_rootCategories[$category->getId()] = array_shift($path);
                 if ($pathSize > 2) {
-                    $this->_categories[$category->getId()] = implode('/', $path);
+                    $this->_categories[$category->getId()] = implode(CategoryProcessor::DELIMITER_CATEGORY, $path);
                 }
             }
         }
@@ -1470,4 +1472,19 @@ protected function getProductEntityLinkField()
         }
         return $this->productEntityLinkField;
     }
+
+    /**
+     * Quoting category delimiter character in string.
+     *
+     * @param string $string
+     * @return string
+     */
+    private function quoteCategoryDelimiter($string)
+    {
+        return str_replace(
+            CategoryProcessor::DELIMITER_CATEGORY,
+            '\\' . CategoryProcessor::DELIMITER_CATEGORY,
+            $string
+        );
+    }
 }
diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php
index 81c83c38bb54..788623d822e3 100644
--- a/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php
@@ -84,7 +84,8 @@ protected function initCategories()
                 if ($pathSize > 1) {
                     $path = [];
                     for ($i = 1; $i < $pathSize; $i++) {
-                        $path[] = $collection->getItemById((int)$structure[$i])->getName();
+                        $name = $collection->getItemById((int)$structure[$i])->getName();
+                        $path[] = $this->quoteDelimiter($name);
                     }
                     /** @var string $index */
                     $index = $this->standardizeString(
@@ -114,7 +115,7 @@ protected function createCategory($name, $parentId)
         }
         $category->setPath($parentCategory->getPath());
         $category->setParentId($parentId);
-        $category->setName($name);
+        $category->setName($this->unquoteDelimiter($name));
         $category->setIsActive(true);
         $category->setIncludeInMenu(true);
         $category->setAttributeSetId($category->getDefaultAttributeSetId());
@@ -137,7 +138,7 @@ protected function upsertCategory($categoryPath)
         $index = $this->standardizeString($categoryPath);
 
         if (!isset($this->categories[$index])) {
-            $pathParts = explode(self::DELIMITER_CATEGORY, $categoryPath);
+            $pathParts = preg_split('~(?<!\\\)' . preg_quote(self::DELIMITER_CATEGORY, '~') . '~', $categoryPath);
             $parentId = \Magento\Catalog\Model\Category::TREE_ROOT_ID;
             $path = '';
 
@@ -243,4 +244,26 @@ private function standardizeString($string)
     {
         return mb_strtolower($string);
     }
+
+    /**
+     * Quoting delimiter character in string.
+     *
+     * @param string $string
+     * @return string
+     */
+    private function quoteDelimiter($string)
+    {
+        return str_replace(self::DELIMITER_CATEGORY, '\\' . self::DELIMITER_CATEGORY, $string);
+    }
+
+    /**
+     * Remove quoting delimiter in string.
+     *
+     * @param string $string
+     * @return string
+     */
+    private function unquoteDelimiter($string)
+    {
+        return str_replace('\\' . self::DELIMITER_CATEGORY, self::DELIMITER_CATEGORY, $string);
+    }
 }
  1. Change app/code/<VENDOR>/<PACKAGE> so all paths are relative to vendor:
vim github-issue-6948.diff -c ":%s/\/app\/code\/Magento\/CatalogImportExport//g"

That should give you the following file:

diff --git a/Model/Export/Product.php b/Model/Export/Product.php
index 6f9dda090914..97a0e6aaebf4 100644
--- a/Model/Export/Product.php
+++ b/Model/Export/Product.php
@@ -5,6 +5,7 @@
  */
 namespace Magento\CatalogImportExport\Model\Export;
 
+use Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor;
 use Magento\ImportExport\Model\Import;
 use \Magento\Store\Model\Store;
 use \Magento\CatalogImportExport\Model\Import\Product as ImportProduct;
@@ -438,11 +439,12 @@ protected function initCategories()
             if ($pathSize > 1) {
                 $path = [];
                 for ($i = 1; $i < $pathSize; $i++) {
-                    $path[] = $collection->getItemById($structure[$i])->getName();
+                    $name = $collection->getItemById($structure[$i])->getName();
+                    $path[] = $this->quoteCategoryDelimiter($name);
                 }
                 $this->_rootCategories[$category->getId()] = array_shift($path);
                 if ($pathSize > 2) {
-                    $this->_categories[$category->getId()] = implode('/', $path);
+                    $this->_categories[$category->getId()] = implode(CategoryProcessor::DELIMITER_CATEGORY, $path);
                 }
             }
         }
@@ -1470,4 +1472,19 @@ protected function getProductEntityLinkField()
         }
         return $this->productEntityLinkField;
     }
+
+    /**
+     * Quoting category delimiter character in string.
+     *
+     * @param string $string
+     * @return string
+     */
+    private function quoteCategoryDelimiter($string)
+    {
+        return str_replace(
+            CategoryProcessor::DELIMITER_CATEGORY,
+            '\\' . CategoryProcessor::DELIMITER_CATEGORY,
+            $string
+        );
+    }
 }
diff --git a/Model/Import/Product/CategoryProcessor.php b/Model/Import/Product/CategoryProcessor.php
index 81c83c38bb54..788623d822e3 100644
--- a/Model/Import/Product/CategoryProcessor.php
+++ b/Model/Import/Product/CategoryProcessor.php
@@ -84,7 +84,8 @@ protected function initCategories()
                 if ($pathSize > 1) {
                     $path = [];
                     for ($i = 1; $i < $pathSize; $i++) {
-                        $path[] = $collection->getItemById((int)$structure[$i])->getName();
+                        $name = $collection->getItemById((int)$structure[$i])->getName();
+                        $path[] = $this->quoteDelimiter($name);
                     }
                     /** @var string $index */
                     $index = $this->standardizeString(
@@ -114,7 +115,7 @@ protected function createCategory($name, $parentId)
         }
         $category->setPath($parentCategory->getPath());
         $category->setParentId($parentId);
-        $category->setName($name);
+        $category->setName($this->unquoteDelimiter($name));
         $category->setIsActive(true);
         $category->setIncludeInMenu(true);
         $category->setAttributeSetId($category->getDefaultAttributeSetId());
@@ -137,7 +138,7 @@ protected function upsertCategory($categoryPath)
         $index = $this->standardizeString($categoryPath);
 
         if (!isset($this->categories[$index])) {
-            $pathParts = explode(self::DELIMITER_CATEGORY, $categoryPath);
+            $pathParts = preg_split('~(?<!\\\)' . preg_quote(self::DELIMITER_CATEGORY, '~') . '~', $categoryPath);
             $parentId = \Magento\Catalog\Model\Category::TREE_ROOT_ID;
             $path = '';
 
@@ -243,4 +244,26 @@ private function standardizeString($string)
     {
         return mb_strtolower($string);
     }
+
+    /**
+     * Quoting delimiter character in string.
+     *
+     * @param string $string
+     * @return string
+     */
+    private function quoteDelimiter($string)
+    {
+        return str_replace(self::DELIMITER_CATEGORY, '\\' . self::DELIMITER_CATEGORY, $string);
+    }
+
+    /**
+     * Remove quoting delimiter in string.
+     *
+     * @param string $string
+     * @return string
+     */
+    private function unquoteDelimiter($string)
+    {
+        return str_replace('\\' . self::DELIMITER_CATEGORY, self::DELIMITER_CATEGORY, $string);
+    }
 }
  1. Add appropriate plugin to composer.json with:
composer require cweagans/composer-patches
  1. Then edit composer.json in the root of project (there are composer.json files in different places and the guide did not specify which one so I assumed to modify the one in the project root. My extras section started looking like this:
    "extra": {
    "composer-exit-on-patch-failure": true,
    "patches": {
        "magento/module-import-export": {
            "MAGETWO-6948: escape forward slash in category on import": "patches/composer/github-issue-6948.diff"
        }
      }
    }
  1. Apply the patch with composer -v install from root of project.

  2. Lastly you would update the composer.lock file with composer update --lock but I didn't go that far since my troubles were revealed at the last command.

@omerts
Copy link

omerts commented Jun 13, 2021

I still have this issue in magento 2.4.2

magento-engcom-team pushed a commit that referenced this issue Jul 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report Component: ImportExport Fixed in 2.3.x The issue has been fixed in 2.3 release line Issue: Clear Description Gate 2 Passed. Manual verification of the issue description passed Issue: Confirmed Gate 3 Passed. Manual verification of the issue completed. Issue is confirmed Issue: Format is valid Gate 1 Passed. Automatic verification of issue format passed Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development Reproduced on 2.1.x The issue has been reproduced on latest 2.1 release Reproduced on 2.2.x The issue has been reproduced on latest 2.2 release Reproduced on 2.3.x The issue has been reproduced on latest 2.3 release
Projects
None yet
Development

No branches or pull requests