I find myself needing this a lot... particularly on canonical csvs and the like. I know another way to handle this would be a custom source plugin, or a hook, but I like to make as many things process plugins as possible. Since Callback only allows functions with a single argument, adding this as a reusable Process Plugin and thought I would place it here to contribute to the community.

This plugin is very useful and I'm willing to see it in migrate plus.

CommentFileSizeAuthor
#38 migrate_plus-string_replace_process-2830512-38.patch5.15 KBAda Hernandez
#38 interdiff-33-38.txt590 bytesAda Hernandez
#31 migrate_plus-string_replace_process-2830512-31.patch3.05 KBAda Hernandez
#31 interdiff-28-31.txt1.67 KBAda Hernandez
#28 migrate_plus-string_replace_process-2830512-28.patch2.68 KBAda Hernandez
#28 interdiff-25-28.txt4.23 KBAda Hernandez
#25 migrate_plus-string_replace_process-2830512-25.patch5.33 KBquiron
#24 migrate_plus-string_replace_process-2830512-24.patch5.33 KBquiron
#20 migrate_plus-string_replace_process-2830512-20.patch4.95 KBrodrigoaguilera
#18 migrate_plus-string_replace_process-2830512-18.patch5.01 KBldavidsp
#18 interdiff_6-18.txt2.5 KBldavidsp
#17 migrate_plus-string_replace_process-2830512-17.patch10.47 KBldavidsp
#17 interdiff_6-17.txt2.5 KBldavidsp
#15 interdiff_2-15.txt10.47 KBldavidsp
#15 migrate_plus-string_replace_process-2830512-15.patch2.5 KBldavidsp
#14 interdiff_2-14.txt10.47 KBldavidsp
#14 migrate_plus-string_replace_process-2830512-14.patch2.5 KBldavidsp
#12 interdiff_2-12.txt10.46 KBldavidsp
#12 string_replace_process-2830512-12.patch2.49 KBldavidsp
#6 interdiff_2-6.txt2.86 KBCharlotte17
#6 migrate_plus-string_replace_process_plugin-2830512-6.patch5.03 KBCharlotte17
#5 interdiff_2-5.txt1.59 KBCharlotte17
#5 migrate_plus-string_replace_process_plugin-2830512-5.patch5.59 KBCharlotte17
#2 migrate_plus-string_replace_process_plugin-2830512-2.patch5.72 KBgeneralredneck
#34 interdiff-31-33.txt1.42 KBAda Hernandez
#34 migrate_plus-string_replace_process-2830512-33.patch3.04 KBAda Hernandez
#40 interdiff-39-40.txt1.98 KBedysmp
#40 migrate_plus-string_replace_process-2830512-40.patch6.76 KBedysmp
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

generalredneck created an issue. See original summary.

generalredneck’s picture

Status: Active » Needs review
FileSize
5.72 KB

I really don't know how to create a test when I'm injecting another service into the plugin, so sorry I wasn't able to get tests for this. However, I did document it really well and it's got some bells and whistles

joachim’s picture

Looks useful!

Just a few nitpicks:

  1. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,178 @@
    + *     search_source: search_field
    

    I thought I saw recently in some documentation that there's a convention of a '@' prefix on a value in a migration YML to mean a source field. That would mean this extra property isn't needed.

  2. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,178 @@
    + * You can provide a source field for replaceing as well. using the
    

    Typos on this line - replacing, and missing capital letter.

  3. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,178 @@
    + * the search and replace configurations will override what ever is provided in
    

    Typo.

heddn’s picture

Status: Needs review » Needs work
  1. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,178 @@
    + *     search: foo
    ...
    + *     search_source: search_field
    ...
    + *     search: "<author>"
    ...
    + *     search_source: @version_api_search_source
    ...
    + *     search: foo
    

    search_source isn't needed. You can build up dynamic values as pseudo fields and pass them around. As an example, d6/d7_file both do this.

  2. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,178 @@
    + *     replace: bar
    ...
    + *     replace: bar
    ...
    + *     replace_source: author_name
    

    Same feedback here. A replace_source isn't necessary.

Charlotte17’s picture

Status: Needs work » Needs review
FileSize
5.59 KB
1.59 KB

Here deleted comment #3-4

Charlotte17’s picture

Update patch#5

heddn’s picture

Version: 8.x-3.x-dev » 8.x-4.x-dev
Status: Needs review » Needs work
Issue tags: +Needs tests

I'm really liking this. Very close. Some small nits and we need a unit test to check the case sensitive vs non-case sensitive nature of the transform. See http://cgit.drupalcode.org/migrate_plus/tree/tests/src/Unit/process/Skip... for an example of how to write a unit test.

  1. +++ b/core/modules/file/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,167 @@
    +  ¶
    ...
    +  ¶
    ...
    +  ¶
    ...
    +  ¶
    ...
    +  ¶
    ...
    +  ¶
    ...
    +  ¶
    ...
    +  ¶
    

    Nit, extra whitespace.

  2. +++ b/core/modules/file/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,167 @@
    +      throw new MigrateException('search must be configured.');
    

    Let's surround 'search' with single or double quotes to call it out more as a parameter.

  3. +++ b/core/modules/file/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,167 @@
    +      throw new MigrateException('replace must be configured.');
    

    Let's surround 'replace' with single or double quotes to call it out more as a parameter.

  4. +++ b/core/modules/file/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,167 @@
    +    $result = $function($this->configuration['search'], $this->configuration['replace'], $value);
    

    Nit: we could just return the result of this. No need to assign it to a variable before returning.

edurenye’s picture

Issue summary: View changes

This is a duplicate of #2754523: Regular expression replace process plugin, I should close this issue but as seems to be more progress here so maybe we might close the other one, not sure, up to you, just telling so we can join efforts.

mikeryan’s picture

Yes, this one should have been closed as a duplicate up front, we need to align/merge the two patches. I'll try to find time to examine the latest patches in both issues.

edurenye’s picture

The class path is wrong: "core/modules/file/src/Plugin/migrate/process/StrReplace.php"
This class must be in: "src/Plugin/migrate/process/StrReplace.php"

osopolar’s picture

The documentation of str_replace says:

If you don't need fancy replacing rules (like regular expressions), you should always use this function [str_replace] instead of preg_replace().

str_replace would be faster, and in some larger migrations performance could matter, so both plugins may have their right to exist.

ldavidsp’s picture

Status: Needs work » Needs review
FileSize
2.49 KB
10.46 KB

Status: Needs review » Needs work

The last submitted patch, 12: string_replace_process-2830512-12.patch, failed testing. View results

ldavidsp’s picture

ldavidsp’s picture

Status: Needs work » Needs review
FileSize
2.5 KB
10.47 KB

Status: Needs review » Needs work
ldavidsp’s picture

Status: Needs work » Needs review
FileSize
2.5 KB
10.47 KB
ldavidsp’s picture

heddn’s picture

Status: Needs review » Needs work

Feedback from #7 is addressed. But still needs tests so back to NW.

rodrigoaguilera’s picture

Same patch as #18 but with the paths relative to migrate plus module instead of core.

joshi.rohit100’s picture

missing diff and tests

rodrigoaguilera’s picture

A interdiff for the path of the the files that are affected by the patch will look confusing.
The path was:
diff --git a/core/modules/migrate/src/Plugin/migrate/process/StrReplace.php b/core/modules/migrate/src/Plugin/migrate/process/StrReplace.php

That is the only change I made.

tmountjr’s picture

Props for #20 - I had to do that manually as the plugin was considered missing because of namespacing problems.

quiron’s picture

Hi all,

I test it and I had not namespacing problems. I had a missing 'case_insensitive' key error.

So I commit a patch solving this, and also adding the possibility to use regex for the 'search' string.

What else is need to release it? IMHO this will be useful for a lot of people!

thanks.

quiron’s picture

Sorry, small fixup in the diff metadata and code style.

heddn’s picture

Issue tags: +Novice

Adding tests to this is a fairly trivial phpunit task. Tagging for that. See #2923891: Transliterate file names as a recent example on how to add this type of test.

heddn’s picture

  1. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,184 @@
    +  protected $migration;
    ...
    +  protected $processPluginManager;
    

    These variables do not seem used.

  2. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,184 @@
    + * This example would replace any instance of 'foo' with 'bar' in the values
    + * migrated in via the source field 'text'
    ...
    + * You can provide a source field for replacing as well. Using the
    + * 'replace_source' configuration.
    

    I do not see how these examples are possible. The code seems to throw an exception if search or replace is missing.

  3. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,184 @@
    + * You can use both search_source and replace_source at the same time. However,
    + * the Search and Replace configurations will override what ever is provided in
    

    Can we get an example of when or how this would look?

  4. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,184 @@
    + *   version_api_search_source:
    + *     plugin: concat
    + *     source:
    + *       - api
    + *       - constants/dash
    

    This does not provide an example of this plugin and is mildly confusing why it exists. Let's remove it.

  5. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,184 @@
    + *     search: my_regex
    

    Can this show an example regex? I'd be curious if we need to include the slashes, etc. A more full example with an actual regex would make that more clear.

Ada Hernandez’s picture

#27

  1. variables removed
  2. removed because don't match the code with examples
  3. ^
  4. removed
  5. example added
Ada Hernandez’s picture

Status: Needs work » Needs review
heddn’s picture

Status: Needs review » Needs work
  1. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,102 @@
    + * migrated in via the source field 'text'
    ...
    + * Case insensitive searches can be achieved using the following:
    

    Can we provide sample values for the string were this would match?

    Example: This example would replace any instance of 'Foo' or 'foo' or 'FOO' with 'bar' in the values migrated in via the source field 'text'

  2. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,102 @@
    + *   field_text:
    + *     plugin: str_replace
    + *     source: text
    + *     replace: bar
    

    I think this would fail with an exception since it is missing search.

  3. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,102 @@
    + *     regex: true
    + *     source: text
    + *     search: /\d/
    + *     replace: bar
    

    Can I assume this replace a string of '123' with the value 'bar'? Let's include that in the example.

Ada Hernandez’s picture

@heddn thanks, examples added, and #2 is removed, and there's an example -> " To do a simple hardcoded string replace" and Case insensitive searches and regular expressions

Ada Hernandez’s picture

Status: Needs work » Needs review
heddn’s picture

Status: Needs review » Needs work

Looking good. Now just need a unit test or two.

Ada Hernandez’s picture

Status: Needs work » Needs review
FileSize
3.04 KB
1.42 KB

renaming bar...

Ada Hernandez’s picture

Status: Needs review » Needs work

need tests

ao2’s picture

This is pretty useful, thanks.

By looking at the code, the only remark I have is that when both regex: true and case_insensitive: true are set, then case_insensitive: true seems to be silently ignored.

Maybe something with PCRE pattern modifiers can be done to cover this case, or at least the user should be warned about the ignored option.

osopolar’s picture

As #24 also added also a simple regex support (preg_replace) to this patch, documented in #34:

* If the value of text is "vero eos et 123 accusam et justo 123 duo"
* in source, foo is "/\d/" in search and bar is "the" in replace,
* field_text will be "vero eos et the accusam et justo the duo".

wouldn't it be nice to be able to actually process the matches before replacing them. For example if the legacy site used the node embed input filter to replace the placholder [[nid:23]] with the rendered node content which may be migrate to Entity Embed and may should look like: <drupal-entity data-entity-type="node" data-entity-id="1234" ... />.

For that purposes I had opened a separate issue: #2754523: Regular expression replace process plugin, but maybe it should be merged into this one. It should work for Entity Embed, or Media Embed but also for all other use cases where someone needs to manipulate the matches before replacing them. The patch allows to expose the matches to the full stack of process plugins.

Ada Hernandez’s picture

Status: Needs work » Needs review
FileSize
5.15 KB
590 bytes

adding tests and fixing pattern

heddn’s picture

Status: Needs review » Needs work

This is looking really close and quite nice! Just a couple more areas where I think we can add coverage. See https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writ... for testing exceptions.

  1. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,104 @@
    +    if (!isset($this->configuration['search'])) {
    ...
    +    if (!isset($this->configuration['replace'])) {
    

    Let's add a test case for these edge cases too.

  2. +++ b/src/Plugin/migrate/process/StrReplace.php
    @@ -0,0 +1,104 @@
    +    $this->multiple = is_array($value);
    

    And this as well.

edysmp’s picture

Status: Needs work » Needs review
FileSize
6.76 KB
1.98 KB

Testing exceptions and multi-value.

heddn’s picture

Status: Needs review » Reviewed & tested by the community

Wonderful work here.

  • heddn committed 3c2c48e on 8.x-4.x
    Issue #2830512 by davidparedes21, Adita, Charlotte17, quiron, edysmp,...
heddn’s picture

Status: Reviewed & tested by the community » Fixed
generalredneck’s picture

👏

Thanks for making my start a reality...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.