Browse Source

admin view for taxo genres and langues, translation for taxo genres and langues, synonyms for genres

Bachir Soussi Chiadmi 6 years ago
parent
commit
07a138cfe6
81 changed files with 6111 additions and 64 deletions
  1. 339 0
      sites/all/modules/contrib/taxonomy/synonyms/LICENSE.txt
  2. 63 0
      sites/all/modules/contrib/taxonomy/synonyms/README.txt
  3. 22 0
      sites/all/modules/contrib/taxonomy/synonyms/config/schema/synonym.schema.yml
  4. 15 0
      sites/all/modules/contrib/taxonomy/synonyms/config/schema/synonyms.behavior.schema.yml
  5. 14 0
      sites/all/modules/contrib/taxonomy/synonyms/config/schema/synonyms.provider.schema.yml
  6. 56 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Annotation/SynonymsProvider.php
  7. 66 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Controller/EntityAutocomplete.php
  8. 149 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Controller/SynonymConfigController.php
  9. 148 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Element/SynonymsEntityAutocomplete.php
  10. 161 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Element/SynonymsEntitySelect.php
  11. 235 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Entity/Synonym.php
  12. 45 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Form/SynonymDeleteForm.php
  13. 292 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Form/SynonymForm.php
  14. 40 0
      sites/all/modules/contrib/taxonomy/synonyms/src/ParamConverter/EntityTypeParamConverter.php
  15. 40 0
      sites/all/modules/contrib/taxonomy/synonyms/src/ParamConverter/SynonymsBehaviorServiceParamConverter.php
  16. 113 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Derivative/EntityReferenceField.php
  17. 133 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Derivative/Field.php
  18. 78 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Derivative/ViewsSynonymsEntityArgumentValidator.php
  19. 157 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Field/FieldWidget/EntityReferenceSynonymsAutocomplete.php
  20. 56 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Field/FieldWidget/EntityReferenceSynonymsSelect.php
  21. 58 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Synonyms/Provider/AbstractProvider.php
  22. 128 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Synonyms/Provider/BaseField.php
  23. 191 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Synonyms/Provider/EntityReferenceField.php
  24. 216 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Synonyms/Provider/Field.php
  25. 33 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/SynonymsFieldItemList.php
  26. 144 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/views/argument_validator/SynonymsEntity.php
  27. 243 0
      sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/views/filter/SynonymsEntity.php
  28. 72 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymInterface.php
  29. 21 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymProviderPluginCollection.php
  30. 58 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsFindProviderInterface.php
  31. 45 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsFindTrait.php
  32. 35 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsFormatWordingProviderInterface.php
  33. 51 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsFormatWordingTrait.php
  34. 45 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsGetProviderInterface.php
  35. 50 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsGetTrait.php
  36. 27 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsProviderInterface.php
  37. 31 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderPluginManager.php
  38. 250 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/Behavior/AutocompleteService.php
  39. 157 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/Behavior/SelectService.php
  40. 65 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/Behavior/SynonymsBehaviorConfigurableInterface.php
  41. 29 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/Behavior/SynonymsBehaviorInterface.php
  42. 143 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/BehaviorService.php
  43. 79 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/EntityGet.php
  44. 44 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/FieldTypeToSynonyms.php
  45. 84 0
      sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/SynonymsFind.php
  46. 30 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms.api.php
  47. 14 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms.info.yml
  48. 5 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms.links.action.yml
  49. 5 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms.links.menu.yml
  50. 47 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms.module
  51. 7 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms.permissions.yml
  52. 63 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms.routing.yml
  53. 46 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms.services.yml
  54. 194 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms_search/src/SynonymsService/Behavior/SearchService.php
  55. 14 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms_search/synonyms_search.info.yml
  56. 69 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms_search/synonyms_search.module
  57. 6 0
      sites/all/modules/contrib/taxonomy/synonyms/synonyms_search/synonyms_search.services.yml
  58. 20 0
      sites/default/config/sync/core.base_field_override.node.autre_son.menu_link.yml
  59. 20 0
      sites/default/config/sync/core.base_field_override.node.fil.menu_link.yml
  60. 1 1
      sites/default/config/sync/core.base_field_override.taxonomy_term.genres.name.yml
  61. 1 1
      sites/default/config/sync/core.base_field_override.taxonomy_term.langues.name.yml
  62. 19 0
      sites/default/config/sync/core.base_field_override.user.user.path.yml
  63. 10 9
      sites/default/config/sync/core.entity_form_display.node.enregistrement.default.yml
  64. 38 0
      sites/default/config/sync/core.entity_form_display.taxonomy_term.genres.default.yml
  65. 29 0
      sites/default/config/sync/core.entity_form_display.taxonomy_term.langues.default.yml
  66. 31 0
      sites/default/config/sync/core.entity_view_display.taxonomy_term.genres.default.yml
  67. 1 0
      sites/default/config/sync/core.extension.yml
  68. 0 6
      sites/default/config/sync/field.field.node.static.field_visuel.yml
  69. 19 0
      sites/default/config/sync/field.field.taxonomy_term.genres.field_synonyms.yml
  70. 21 0
      sites/default/config/sync/field.storage.taxonomy_term.field_synonyms.yml
  71. 3 3
      sites/default/config/sync/language.content_settings.taxonomy_term.genres.yml
  72. 3 3
      sites/default/config/sync/language.content_settings.taxonomy_term.langues.yml
  73. 1 0
      sites/default/config/sync/language/en/system.action.pathauto_update_alias_node.yml
  74. 1 0
      sites/default/config/sync/language/en/system.action.pathauto_update_alias_user.yml
  75. 13 0
      sites/default/config/sync/synonyms.synonym.field.synonyms.behavior.autocomplete_taxonomy_term_genres_field_synonyms.yml
  76. 2 0
      sites/default/config/sync/user.role.admin.yml
  77. 1 0
      sites/default/config/sync/user.role.anonymous.yml
  78. 1 0
      sites/default/config/sync/user.role.authenticated.yml
  79. 3 0
      sites/default/config/sync/user.role.root.yml
  80. 1 1
      sites/default/config/sync/views.view.content.yml
  81. 851 40
      sites/default/config/sync/views.view.entree_s_.yml

+ 339 - 0
sites/all/modules/contrib/taxonomy/synonyms/LICENSE.txt

@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

+ 63 - 0
sites/all/modules/contrib/taxonomy/synonyms/README.txt

@@ -0,0 +1,63 @@
+
+-- SUMMARY --
+
+The Synonyms module enriches content Entities with the notion of synonyms.
+Currently the module provides the following functionality:
+* support of synonyms through Fields both base and attached ones. Any field,
+  for which synonyms provider exists, can be enabled as source of synonyms.
+* synonyms-friendly autocomplete and select widgets for entity reference field
+  type.
+* integration with Views: Synonyms module provides a few filters and contextual
+  filters that allow filtering not only by entity name but also by one of its
+  synonyms.
+* 2 form elements are provided for developers: synonyms-friendly entity
+  autocomplete and select.
+
+-- REQUIREMENTS --
+
+The Synonyms module requires only Drupal core.
+
+-- SUPPORTED SYNONYMS PROVIDERS --
+
+Module ships with ability to provide synonyms from the following field types:
+* "Text" field type
+* "Entity Reference" field type
+* "Number" field type
+* "Float" field type
+* "Decimal" field type
+* "Email" field type
+* "Telephone" field type
+
+Worth mentioning here: this list is easily extended further by implementing new
+synonyms providers in your code. Refer to Synonyms documentation for more
+details on how to accomplish it.
+
+-- GRANULATION WITHIN SYNONYMS BEHAVIOR --
+
+In order to achieve greater flexibility, this module introduced additional
+granularity into what "synonyms" mean. This granularity is expressed via
+"synonyms behavior" idea whatsoever. Therefore each synonyms behavior may have
+its own synonyms provider than you can enable and configure through admin UI of
+the Synonyms module. For example, field "Typos" can be part of autocomplete
+behavior, while field "Other spellings" can be part of select behavior.
+Currently the following synonym behaviors are recognized (other modules actually
+can extend this list):
+* Autocomplete - whether synonyms from this provider should participate in
+  autocomplete suggestions. This module ships with synonyms friendly
+  autocomplete widget and the autocomplete suggestions will be filled in with
+  the synonyms from enabled providers for "autocomplete" behavior
+* Select - whether synonyms from this provider should be included in the
+  synonyms friendly select widget.
+
+That way on the Synonyms configuration page you will get to add/remove certain
+synonym providers for certain synonym behaviors. Also, each behavior and
+provider may have its own settings that you get to configure too.
+
+-- INSTALLATION --
+
+* Install as usual
+
+-- CONFIGURATION --
+
+* You can configure synonyms of all eligible entity types by going to Admin ->
+  Structure -> Synonyms (/admin/structure/synonyms)

+ 22 - 0
sites/all/modules/contrib/taxonomy/synonyms/config/schema/synonym.schema.yml

@@ -0,0 +1,22 @@
+synonyms.synonym.*:
+  type: config_entity
+  label: 'Synonym configuration'
+  mapping:
+    id:
+      type: string
+      label: 'ID'
+    provider_plugin:
+      type: string
+      label: 'Controlled provider plugin'
+    base_provider_plugin:
+      type: string
+      label: 'Base ID of the controlled provider plugin'
+    provider_configuration:
+      type: synonyms.provider.[%parent.base_provider_plugin]
+      label: 'Configuration of provider plugin'
+    behavior:
+      type: string
+      label: 'Controlled behavior service'
+    behavior_configuration:
+      type: synonyms.[%parent.behavior]
+      label: 'Configuration of behavior service'

+ 15 - 0
sites/all/modules/contrib/taxonomy/synonyms/config/schema/synonyms.behavior.schema.yml

@@ -0,0 +1,15 @@
+synonyms.synonyms.behavior.select:
+  type: mapping
+  label: 'Settings of select synonyms behavior'
+  mapping:
+    wording:
+      type: string
+      label: 'Wording for select entry'
+
+synonyms.synonyms.behavior.autocomplete:
+  type: mapping
+  label: 'Settings of autocomplete synonyms behavior'
+  mapping:
+    wording:
+      type: string
+      label: 'Wording for autocomplete suggestion'

+ 14 - 0
sites/all/modules/contrib/taxonomy/synonyms/config/schema/synonyms.provider.schema.yml

@@ -0,0 +1,14 @@
+synonyms.provider.field:
+  type: mapping
+  label: 'Settings of field synonyms provider'
+  mapping:
+
+synonyms.provider.base_field:
+  type: mapping
+  label: 'Settings of base field synonyms provider'
+  mapping:
+
+synonyms.provider.entityreference_field:
+  type: mapping
+  label: 'Settings of entity reference field synonyms provider'
+  mapping:

+ 56 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Annotation/SynonymsProvider.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\synonyms\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Annotation for synonyms provider plugin instance.
+ *
+ * @Annotation
+ */
+class SynonymsProvider extends Plugin {
+
+  /**
+   * Machine readable name of this plugin,
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * Human readable name of this plugin.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * Synonyms behavior service ID into which this plugin provides synonyms.
+   *
+   * Synonyms behaviors are the services with the tag 'synonyms_behavior'.
+   *
+   * @var string
+   */
+  public $synonyms_behavior_service;
+
+  /**
+   * Entity type which is controlled by ths plugin.
+   *
+   * Entity type into which this plugin provides synonyms.
+   *
+   * @var string
+   */
+  public $controlled_entity_type;
+
+  /**
+   * Bundle which is controlled by this plugin.
+   *
+   * Bundle into which this plugin provides synonyms. If the entity type does
+   * not support bundles, just put here the entity type.
+   *
+   * @var string
+   */
+  public $controlled_bundle;
+
+}

+ 66 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Controller/EntityAutocomplete.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace Drupal\synonyms\Controller;
+
+use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\Tags;
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\synonyms\SynonymsService\Behavior\AutocompleteService;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Synonyms friendly entity autocomplete controller.
+ */
+class EntityAutocomplete extends ControllerBase {
+
+  /**
+   * @var AutocompleteService
+   */
+  protected $autocompleteService;
+
+  /**
+   * EntityAutocomplete constructor.
+   */
+  public function __construct(AutocompleteService $autocomplete_service) {
+    $this->autocompleteService = $autocomplete_service;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('synonyms.behavior.autocomplete')
+    );
+  }
+
+  /**
+   * Routing callback: provide suggestions for autocomplete form element.
+   */
+  public function autocomplete(Request $request, EntityTypeInterface $target_type, $token) {
+    $matches = [];
+
+    if ($input = $request->get('q')) {
+      $input = Tags::explode($input);
+      $input = array_pop($input);
+      foreach ($this->autocompleteService->autocompleteLookup($input, $token) as $k => $suggestion) {
+        $key = $suggestion['entity_label'] . ' (' . $suggestion['entity_id'] . ')';
+        $key = preg_replace('/\s\s+/', ' ', str_replace("\n", '', trim(Html::decodeEntities(strip_tags($key)))));
+
+        // Names containing commas or quotes must be wrapped in quotes.
+        $key = Tags::encode($key);
+
+        $matches[] = [
+          'value' => $key,
+          'label' => $suggestion['wording'],
+        ];
+      }
+    }
+
+    return new JsonResponse($matches);
+  }
+
+}

+ 149 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Controller/SynonymConfigController.php

@@ -0,0 +1,149 @@
+<?php
+
+namespace Drupal\synonyms\Controller;
+
+use Drupal\Component\Utility\Html;
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Entity\ContentEntityTypeInterface;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Url;
+use Drupal\synonyms\SynonymsService\Behavior\SynonymsBehaviorInterface;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Controller for admin UI of the module.
+ */
+class SynonymConfigController extends ControllerBase {
+
+  /**
+   * @var EntityTypeBundleInfoInterface
+   */
+  protected $entityTypeBundleInfo;
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * SynonymConfigController constructor.
+   */
+  public function __construct(EntityTypeBundleInfoInterface $entity_type_bundle_info, BehaviorService $behavior_service) {
+    $this->entityTypeBundleInfo = $entity_type_bundle_info;
+    $this->behaviorService = $behavior_service;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity_type.bundle.info'),
+      $container->get('synonyms.behaviors')
+    );
+  }
+
+  /**
+   * Routing callback: show overview table of synonyms configuration.
+   */
+  public function overview() {
+    $render = [
+      '#type' => 'table',
+      '#header' => [
+        $this->t('Entity type'),
+        $this->t('Bundle'),
+        $this->t('Manage'),
+      ],
+    ];
+
+    foreach ($this->entityTypeManager()->getDefinitions() as $entity_type) {
+      if ($entity_type instanceof ContentEntityTypeInterface) {
+        foreach ($this->entityTypeBundleInfo->getBundleInfo($entity_type->id()) as $bundle => $bundle_info) {
+          $links = [];
+          foreach ($this->behaviorService->getBehaviorServices() as $service_id => $service) {
+            $count = count($this->behaviorService->getSynonymConfigEntities($service_id, $entity_type->id(), $bundle));
+
+            if ($count > 0) {
+              $title = $this->t('@behavior (@count)', [
+                '@behavior' => $service['service']->getTitle(),
+                '@count' => $count,
+              ]);
+            }
+            else {
+              $title = $service['service']->getTitle();
+            }
+
+            $links[$service_id] = [
+              'title' => $title,
+              'url' => Url::fromRoute('entity.synonym.overview.entity_type.bundle.behavior', [
+                'synonyms_entity_type' => $entity_type->id(),
+                'bundle' => $bundle,
+                'synonyms_behavior_service' => $service_id,
+              ]),
+            ];
+          }
+
+          $render[] = [
+            ['#markup' => Html::escape($entity_type->getLabel())],
+            ['#markup' => $bundle == $entity_type->id() ? '' : Html::escape($bundle_info['label'])],
+            ['#type' => 'operations', '#links' => $links],
+          ];
+        }
+      }
+    }
+
+    return $render;
+  }
+
+  /**
+   * Routing callback to overview a particular entity type and behavior service.
+   */
+  public function overviewEntityTypeBundle(EntityTypeInterface $synonyms_entity_type, $bundle, SynonymsBehaviorInterface $synonyms_behavior_service) {
+    $table = [
+      '#type' => 'table',
+      '#header' => [
+        $this->t('Provider'),
+        $this->t('Operations'),
+      ],
+    ];
+
+    foreach ($this->entityTypeManager()->getStorage('synonym')->loadMultiple() as $synonym_config) {
+      $provider_instance = $synonym_config->getProviderPluginInstance();
+      $provider_definition = $provider_instance->getPluginDefinition();
+      if ($provider_definition['controlled_entity_type'] == $synonyms_entity_type->id() && $provider_definition['controlled_bundle'] == $bundle && $this->behaviorService->getBehaviorService($provider_definition['synonyms_behavior_service'])['service'] == $synonyms_behavior_service) {
+        $table[] = [
+          ['#markup' => Html::escape($synonym_config->label())],
+          [
+            '#type' => 'operations',
+            '#links' => $this->entityTypeManager()->getListBuilder($synonym_config->getEntityTypeId())->getOperations($synonym_config),
+          ],
+        ];
+      }
+    }
+
+    return $table;
+  }
+
+  /**
+   * Title callback for 'entity.synonym.overview.entity_type.bundle.behavior'.
+   */
+  public function overviewEntityTypeBundleTitle(EntityTypeInterface $synonyms_entity_type, $bundle, SynonymsBehaviorInterface $synonyms_behavior_service) {
+    if ($synonyms_entity_type->id() == $bundle) {
+      return $this->t('Manage @behavior of @entity_type', [
+        '@behavior' => $synonyms_behavior_service->getTitle(),
+        '@entity_type' => $synonyms_entity_type->getLabel(),
+      ]);
+    }
+
+    $bundle_info = $this->entityTypeBundleInfo->getBundleInfo($synonyms_entity_type->id());
+
+    return $this->t('Manage @behavior of @entity_type @bundle', [
+      '@behavior' => $synonyms_behavior_service->getTitle(),
+      '@entity_type' => $synonyms_entity_type->getLabel(),
+      '@bundle' => $bundle_info[$bundle]['label'],
+    ]);
+  }
+
+}

+ 148 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Element/SynonymsEntityAutocomplete.php

@@ -0,0 +1,148 @@
+<?php
+
+namespace Drupal\synonyms\Element;
+
+use Drupal\Component\Utility\Crypt;
+use Drupal\Component\Utility\Tags;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element\Textfield;
+use Drupal\Core\Site\Settings;
+
+/**
+ * Form element for synonyms-friendly entity autocomplete.
+ *
+ * @FormElement("synonyms_entity_autocomplete")
+ */
+class SynonymsEntityAutocomplete extends Textfield {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getInfo() {
+    $info = parent::getInfo();
+
+    // Target entity type for suggestions.
+    $info['#target_type'] = NULL;
+
+    // String or array of allowed target bundles. If omitted, all bundles will
+    // be included in autocomplete suggestions.
+    $info['#target_bundles'] = NULL;
+
+    // Default maximum amount of provided suggestions.
+    $info['#suggestion_size'] = 10;
+
+    // Whether to suggest same entity at most once (in the case, when more than
+    // 1 synonym triggers inclusion of that entity).
+    $info['#suggest_only_unique'] = FALSE;
+
+    // Operator to match keyword. Allowed values are:
+    // - CONTAINS
+    // - STARTS_WITH
+    $info['#match'] = 'CONTAINS';
+
+    array_unshift($info['#process'], [get_class($this), 'elementSynonymsEntityAutocomplete']);
+    $info['#element_validate'][] = [get_class($this), 'validateEntityAutocomplete'];
+    return $info;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
+    $entities = NULL;
+    if ($input === FALSE) {
+      if (isset($element['#default_value'])) {
+        $entities = [];
+        foreach ($element['#default_value'] as $entity) {
+          $entities[] = $entity;
+        }
+      }
+    }
+    // Potentially the #value is set directly, so it contains the 'target_id'
+    // array structure instead of a string.
+    elseif ($input !== FALSE && is_array($input)) {
+      $entity_ids = array_map(function(array $item) {
+        return $item['target_id'];
+      }, $input);
+      $entities = \Drupal::entityTypeManager()->getStorage($element['#target_type'])->loadMultiple($entity_ids);
+    }
+
+    if (is_array($entities)) {
+      $value = [];
+      foreach ($entities as $entity) {
+        $value[] = $entity->label() . ' (' . $entity->id() . ')';
+      }
+      return Tags::implode($value);
+    }
+  }
+
+  /**
+   * Form element process callback for 'synonyms_entity_autocomplete' type.
+   */
+  public static function elementSynonymsEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) {
+    $data = [
+      'target_type' => $element['#target_type'],
+      'target_bundles' => $element['#target_bundles'],
+      'suggestion_size' => $element['#suggestion_size'],
+      'suggest_only_unique' => $element['#suggest_only_unique'],
+      'match' => $element['#match'],
+    ];
+    $token = Crypt::hmacBase64(serialize($data), Settings::getHashSalt());
+    $key_value_storage = \Drupal::keyValue('synonyms_entity_autocomplete');
+
+    $key_value_storage->setIfNotExists($token, $data);
+
+    $element['#autocomplete_route_name'] = 'synonyms.entity_autocomplete';
+    $element['#autocomplete_route_parameters'] = [
+      'target_type' => $element['#target_type'],
+      'token' => $token,
+    ];
+
+    return $element;
+  }
+
+  /**
+   * Form element validation handler for synonyms_entity_autocomplete elements.
+   */
+  public static function validateEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) {
+    $tokens = Tags::explode($form_state->getValue($element['#parents']));
+    $value = [];
+
+    $autocomplete_service = \Drupal::getContainer()->get('synonyms.behavior.autocomplete');
+    foreach ($tokens as $token) {
+      $entity_id = self::extractEntityIdFromAutocompleteInput($token);
+      if (!$entity_id) {
+        $lookup = $autocomplete_service->autocompleteLookup($token, $element['#autocomplete_route_parameters']['token']);
+        $lookup = array_shift($lookup);
+        if ($lookup) {
+          $entity_id = $lookup['entity_id'];
+        }
+      }
+
+      if ($entity_id) {
+        $value[] = ['target_id' => $entity_id];
+      }
+    }
+    $form_state->setValueForElement($element, $value);
+  }
+
+  /**
+   * Extracts the entity ID from the autocompletion result.
+   *
+   * @param string $input
+   *   The input coming from the autocompletion result.
+   *
+   * @return mixed|null
+   */
+  public static function extractEntityIdFromAutocompleteInput($input) {
+    $match = NULL;
+
+    // Take "label (entity id)', match the ID from parenthesis when it's a
+    // number.
+    if (preg_match("/.+\s\((\d+)\)/", $input, $matches)) {
+      $match = $matches[1];
+    }
+    return $match;
+  }
+
+}

+ 161 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Element/SynonymsEntitySelect.php

@@ -0,0 +1,161 @@
+<?php
+
+namespace Drupal\synonyms\Element;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element\Select;
+
+/**
+ * Form element for synonyms-friendly entity select.
+ *
+ * @FormElement("synonyms_entity_select")
+ */
+class SynonymsEntitySelect extends Select {
+
+  /**
+   * Delimiter to use when separating entity ID and its synonym.
+   *
+   * @var string
+   */
+  const DELIMITER = ':';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getInfo() {
+    $info = parent::getInfo();
+
+    // Target entity type.
+    $info['#target_type'] = NULL;
+
+    // Which SelectionInterface plugin to use for retrieving referenceable
+    // entities.
+    $info['#handler'] = 'default';
+
+    // Array of settings for the selection handler.
+    $info['#handler_settings'] = [];
+
+    // Put actual value under this key in the associative array.
+    $info['#key_column'] = 'target_id';
+
+    array_unshift($info['#process'], [get_class($this), 'elementSynonymsEntitySelect']);
+    $info['#element_validate'][] = [get_class($this), 'validateEntitySelect'];
+    return $info;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
+    $return = parent::valueCallback($element, $input, $form_state);
+
+    if (is_null($return) && isset($element['#default_value'])) {
+      $return = $element['#default_value'];
+    }
+
+    // Force default value (entity ID(-s)) to be strings. Otherwise we are
+    // hitting the situation when all synonyms are highlighted as selected.
+    // This code snippet explains the problem:
+    // $a = [25];
+    // $k = '25:25';
+    // in_array($k, $a); // Yields TRUE, because PHP seems to compare int to int
+    //                      and not string-wise.
+    if (is_array($return)) {
+      $return = array_map(function($item) {
+        return (string) $item;
+      }, $return);
+    }
+    elseif (!is_null($return)) {
+      $return = (string) $return;
+    }
+
+    return $return;
+  }
+
+  /**
+   * Form element process callback for 'synonyms_entity_select' type.
+   */
+  public static function elementSynonymsEntitySelect(array &$element, FormStateInterface $form_state, array &$complete_form) {
+    $options = [];
+
+    $selection = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance([
+      'target_type' => $element['#target_type'],
+      'handler' => $element['#handler'],
+      'handler_settings' => $element['#handler_settings'],
+      'entity' => NULL,
+    ]);
+
+    $bundle_info = \Drupal::getContainer()->get('entity_type.bundle.info')->getBundleInfo($element['#target_type']);
+
+    $referenceable_entities = $selection->getReferenceableEntities();
+    $entities = [];
+
+    foreach ($referenceable_entities as $bundle_entity_ids) {
+      $entities = array_merge($entities, array_keys($bundle_entity_ids));
+    }
+
+    if (!empty($entities)) {
+      $entities = \Drupal::entityTypeManager()->getStorage($element['#target_type'])->loadMultiple($entities);
+    }
+
+    foreach ($referenceable_entities as $bundle => $entity_ids) {
+      $key = (string) $bundle_info[$bundle]['label'];
+      $options[$key] = [];
+
+      $synonyms = \Drupal::getContainer()->get('synonyms.behavior.select')->getSynonymsMultiple(array_intersect_key($entities, $entity_ids));
+
+      foreach ($entity_ids as $entity_id => $label) {
+        $options[$key][$entity_id] = $label;
+
+        foreach ($synonyms[$entity_id] as $synonym) {
+          $options[$key][$entity_id . self::DELIMITER . $synonym['synonym']] = $synonym['wording'];
+        }
+      }
+
+      asort($options[$key]);
+    }
+
+    if (count($options) == 1) {
+      // Strip away the bundle optgroup if it's the only bundle.
+      $options = reset($options);
+    }
+
+    $element['#options'] = $options;
+
+    return $element;
+  }
+
+  /**
+   * Form element validation handler for synonyms_entity_select elements.
+   */
+  public static function validateEntitySelect(array &$element, FormStateInterface $form_state, array &$complete_form) {
+    $value = $form_state->getValue($element['#parents']);
+    if (!isset($element['#multiple']) || !$element['#multiple']) {
+      $value = [$value];
+    }
+
+    $unique = [];
+    foreach ($value as $v) {
+      if ($v !== '') {
+        if (!is_numeric($v)) {
+          $v = explode(self::DELIMITER, $v, 2)[0];
+        }
+        $unique[$v] = $v;
+      }
+    }
+
+    $items = [];
+    foreach ($unique as $v) {
+      $items[] = [
+        $element['#key_column'] => $v,
+      ];
+    }
+
+    if (!isset($element['#multiple']) || !$element['#multiple']) {
+      $items = reset($items);
+    }
+
+    $form_state->setValueForElement($element, $items);
+  }
+
+}

+ 235 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Entity/Synonym.php

@@ -0,0 +1,235 @@
+<?php
+
+namespace Drupal\synonyms\Entity;
+
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\synonyms\SynonymInterface;
+use Drupal\synonyms\SynonymProviderPluginCollection;
+use Drupal\synonyms\SynonymsProviderInterface;
+
+/**
+ * Synonym configuration entity.
+ *
+ * @ConfigEntityType(
+ *   id = "synonym",
+ *   label = @Translation("Synonym configuration"),
+ *   handlers = {
+ *     "list_builder" = "Drupal\Core\Config\Entity\ConfigEntityListBuilder",
+ *     "form" = {
+ *       "add" = "Drupal\synonyms\Form\SynonymForm",
+ *       "edit" = "Drupal\synonyms\Form\SynonymForm",
+ *       "delete" = "Drupal\synonyms\Form\SynonymDeleteForm"
+ *     }
+ *   },
+ *   config_prefix = "synonym",
+ *   admin_permission = "administer synonyms",
+ *   entity_keys = {
+ *     "id" = "id"
+ *   },
+ *   links = {
+ *     "edit-form" = "/admin/structure/synonyms/{synonym}",
+ *     "delete-form" = "/admin/structure/synonyms/{synonym}/delete"
+ *   }
+ * )
+ */
+class Synonym extends ConfigEntityBase implements SynonymInterface {
+
+  /**
+   * Plugin ID that corresponds to this config entry.
+   *
+   * @var string
+   */
+  protected $provider_plugin;
+
+  /**
+   * Base plugin ID that corresponds to this config entry.
+   *
+   * @var string
+   */
+  protected $base_provider_plugin;
+
+  /**
+   * Plugin configuration.
+   *
+   * @var array
+   */
+  protected $provider_configuration = [];
+
+  /**
+   * Controlled behavior service.
+   *
+   * @var string
+   */
+  protected $behavior;
+
+  /**
+   * Behavior configuration.
+   *
+   * @var array
+   */
+  protected $behavior_configuration = [];
+
+  /**
+   * The plugin collection that stores synonym provider plugins.
+   *
+   * @var \Drupal\synonyms\SynonymProviderPluginCollection
+   */
+  protected $pluginCollection;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function label() {
+    return $this->getProviderPluginInstance()->getPluginDefinition()['label'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getProviderPluginInstance() {
+    return $this->getPluginCollection()->get($this->getProviderPlugin());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getProviderPlugin() {
+    return $this->provider_plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setProviderPlugin($plugin) {
+    $this->provider_plugin = $plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getProviderConfiguration() {
+    if ($this->getProviderPluginInstance() instanceof ConfigurablePluginInterface) {
+      return $this->getPluginCollection()->get($this->getProviderPlugin())->getConfiguration();
+    }
+    return $this->provider_configuration;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setProviderConfiguration(array $provider_configuration) {
+    if ($this->getProviderPluginInstance() instanceof ConfigurablePluginInterface) {
+      $this->getProviderPluginInstance()->setConfiguration($provider_configuration);
+    }
+    $this->provider_configuration = $provider_configuration;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getBehaviorConfiguration() {
+    return $this->behavior_configuration;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setBehaviorConfiguration(array $behavior_configuration) {
+    $this->behavior_configuration = $behavior_configuration;
+  }
+
+  /**
+   * Gets the plugin collections used by this entity.
+   *
+   * @return SynonymProviderPluginCollection[]
+   *   An array of plugin collections, keyed by the property name they use to
+   *   store their configuration.
+   */
+  public function getPluginCollections() {
+    return ['provider_configuration' => $this->getPluginCollection()];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function postLoad(EntityStorageInterface $storage, array &$entities) {
+    parent::postLoad($storage, $entities);
+    foreach ($entities as $entity) {
+      $entity->addCacheTags([self::cacheTagConstruct($entity->get('behavior'), $entity->getProviderPluginInstance()->getPluginDefinition()['controlled_entity_type'], $entity->getProviderPluginInstance()->getPluginDefinition()['controlled_bundle'])]);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageInterface $storage) {
+    parent::preSave($storage);
+
+    // Update the "static" properties. We keep them only to be able to leverage
+    // Schema API through them.
+    $this->base_provider_plugin = $this->getProviderPluginInstance()->getBaseId();
+    $this->behavior = $this->getProviderPluginInstance()->getBehaviorService();
+
+    // Make sure we have appropriate cache tags in this entity. If it was just
+    // created and runs its first save it might not have it set up yet.
+    $this->addCacheTags([self::cacheTagConstruct($this->behavior, $this->getProviderPluginInstance()->getPluginDefinition()['controlled_entity_type'], $this->getProviderPluginInstance()->getPluginDefinition()['controlled_bundle'])]);
+  }
+
+  /**
+   * Construct a cache tag.
+   *
+   * Construct a cache tag that represents synonyms config for a given behavior,
+   * entity type, and bundle.
+   *
+   * @param string $behavior
+   *   Synonyms behavior whose cache tag is requested
+   * @param string $entity_type
+   *   Entity type whose cache tag is requested
+   * @param string $bundle
+   *   Bundle whose cache tag is requested
+   *
+   * @return string
+   *   Cache tag
+   */
+  public static function cacheTagConstruct($behavior, $entity_type, $bundle) {
+    return 'synonyms:' . $behavior . '.' . $entity_type . '.' . $bundle;
+  }
+
+  /**
+   * Encapsulates the creation of entity's LazyPluginCollection.
+   *
+   * @return SynonymProviderPluginCollection
+   *   The entity's plugin collection.
+   */
+  protected function getPluginCollection() {
+    if (!$this->pluginCollection && $this->getProviderPlugin()) {
+      $this->pluginCollection = new SynonymProviderPluginCollection(\Drupal::service('plugin.manager.synonyms_provider'), $this->getProviderPlugin(), $this->provider_configuration);
+    }
+    return $this->pluginCollection;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function invalidateTagsOnSave($update) {
+    parent::invalidateTagsOnSave($update);
+    Cache::invalidateTags($this->cacheTags);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static function invalidateTagsOnDelete(EntityTypeInterface $entity_type, array $entities) {
+    $cacheability_metadata = new CacheableMetadata();
+    foreach ($entities as $entity) {
+      $cacheability_metadata->addCacheableDependency($entity);
+    }
+    Cache::invalidateTags($cacheability_metadata->getCacheTags());
+  }
+
+}

+ 45 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Form/SynonymDeleteForm.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace Drupal\synonyms\Form;
+
+use Drupal\Core\Entity\EntityConfirmFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+
+/**
+ * Delete form for synonym config entity.
+ */
+class SynonymDeleteForm extends EntityConfirmFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQuestion() {
+    return $this->t('Are you sure you want to delete synonym configuration %name?', ['%name' => $this->entity->label()]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCancelUrl() {
+    return new Url('entity.synonym.overview');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfirmText() {
+    return $this->t('Delete');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $this->entity->delete();
+    drupal_set_message($this->t('Synonym configuration %label has been deleted.', ['%label' => $this->entity->label()]));
+
+    $form_state->setRedirectUrl($this->getCancelUrl());
+  }
+
+}

+ 292 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Form/SynonymForm.php

@@ -0,0 +1,292 @@
+<?php
+
+namespace Drupal\synonyms\Form;
+
+use Drupal\Core\Entity\EntityForm;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Form\SubformState;
+use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\synonyms\SynonymInterface;
+use Drupal\synonyms\SynonymsProviderPluginManager;
+use Drupal\synonyms\SynonymsService\Behavior\SynonymsBehaviorConfigurableInterface;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Entity form for 'synonym' config entity type.
+ */
+class SynonymForm extends EntityForm {
+
+  /**
+   * @var SynonymInterface
+   */
+  protected $entity;
+
+  /**
+   * @var \Drupal\Core\Entity\Query\QueryFactory
+   */
+  protected $entityQuery;
+
+  /**
+   * Entity type manager.
+   *
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Entity type bundle info.
+   *
+   * @var EntityTypeBundleInfoInterface
+   */
+  protected $entityTypeBundleInfo;
+
+  /**
+   * @var SynonymsProviderPluginManager
+   */
+  protected $synonymsProviderPluginManager;
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorServices;
+
+  /**
+   * Entity type that is being edited/added.
+   *
+   * @var EntityTypeInterface
+   */
+  protected $controlledEntityType;
+
+  /**
+   * Bundle that is being edited/added.
+   *
+   * @var string
+   */
+  protected $controlledBundle;
+
+  /**
+   * Service ID that is being edited/added.
+   *
+   * @var string
+   */
+  protected $behaviorServiceId;
+
+  /**
+   * @var ContainerInterface
+   */
+  protected $container;
+
+  public function __construct(QueryFactory $entity_query, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, SynonymsProviderPluginManager $synonyms_provider_plugin_manager, BehaviorService $behavior_services, ContainerInterface $container) {
+    $this->entityQuery = $entity_query;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->entityTypeBundleInfo = $entity_type_bundle_info;
+    $this->synonymsProviderPluginManager = $synonyms_provider_plugin_manager;
+    $this->behaviorServices = $behavior_services;
+    $this->container = $container;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity.query'),
+      $container->get('entity_type.manager'),
+      $container->get('entity_type.bundle.info'),
+      $container->get('plugin.manager.synonyms_provider'),
+      $container->get('synonyms.behaviors'),
+      $container
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function init(FormStateInterface $form_state) {
+    parent::init($form_state);
+
+    if ($this->entity->isNew()) {
+      $this->controlledEntityType = $this->getRequest()->get('synonyms_entity_type')->id();
+      $this->controlledBundle = $this->getRequest()->get('bundle');
+      $this->behaviorServiceId = $this->getRouteMatch()->getRawParameter('synonyms_behavior_service');
+    }
+    else {
+      $plugin_definition = $this->entity->getProviderPluginInstance()->getPluginDefinition();
+      $this->controlledEntityType = $plugin_definition['controlled_entity_type'];
+      $this->controlledBundle = $plugin_definition['controlled_bundle'];
+      $this->behaviorServiceId = $plugin_definition['synonyms_behavior_service'];
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function form(array $form, FormStateInterface $form_state) {
+    $form = parent::form($form, $form_state);
+
+    $class = get_class($this);
+
+    $provider_plugin = $this->entity->getProviderPlugin();
+    if ($form_state->getValue('provider_plugin')) {
+      $provider_plugin = $form_state->getValue('provider_plugin');
+    }
+
+    $form['id'] = [
+      '#type' => 'value',
+      '#value' => str_replace(':', '.', $provider_plugin),
+    ];
+
+    $options = [];
+    foreach ($this->synonymsProviderPluginManager->getDefinitions() as $plugin_id => $plugin) {
+      if ($plugin['controlled_entity_type'] ==  $this->controlledEntityType && $plugin['controlled_bundle'] == $this->controlledBundle && $plugin['synonyms_behavior_service'] == $this->behaviorServiceId) {
+        $options[$plugin_id] = $plugin['label'];
+      }
+    }
+
+    $form['provider_plugin'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Synonyms provider'),
+      '#description' => $this->t('Select what synonyms provider it should represent.'),
+      '#required' => TRUE,
+      '#options' => $options,
+      '#default_value' => $this->entity->getProviderPlugin(),
+      '#ajax' => [
+        'wrapper' => 'synonyms-entity-configuration-ajax-wrapper',
+        'event' => 'change',
+        'callback' => [$class, 'ajaxForm'],
+      ],
+    ];
+
+    $form['ajax_wrapper'] = [
+      '#prefix' => '<div id="synonyms-entity-configuration-ajax-wrapper">',
+      '#suffix' => '</div>',
+    ];
+
+    $form['ajax_wrapper']['provider_configuration'] = [
+      '#tree' => TRUE,
+      '#title' => $this->t('Provider settings'),
+      '#open' => TRUE,
+    ];
+
+    $form['ajax_wrapper']['behavior_configuration'] = [
+      '#tree' => TRUE,
+      '#title' => $this->t('Behavior settings'),
+      '#open' => TRUE,
+    ];
+
+    if ($provider_plugin) {
+      $provider_plugin_instance = $this->entity->getProviderPluginInstance();
+
+      if ($provider_plugin_instance instanceof PluginFormInterface) {
+        $form['ajax_wrapper']['provider_configuration']['#type'] = 'details';
+        $form['ajax_wrapper']['provider_configuration'] += $provider_plugin_instance->buildConfigurationForm($form['ajax_wrapper']['provider_configuration'], $form_state);
+      }
+
+      $behavior_service_instance = $provider_plugin_instance->getBehaviorServiceInstance();
+      if ($behavior_service_instance instanceof SynonymsBehaviorConfigurableInterface) {
+        $form['ajax_wrapper']['behavior_configuration']['#type'] = 'details';
+        $form['ajax_wrapper']['behavior_configuration'] += $behavior_service_instance->buildConfigurationForm($form['ajax_wrapper']['behavior_configuration'], $form_state, $this->entity->getBehaviorConfiguration(), $this->entity);
+      }
+
+    }
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    parent::validateForm($form, $form_state);
+
+    if ($this->entity->getProviderPluginInstance() instanceof PluginFormInterface) {
+      $this->entity->getProviderPluginInstance()->validateConfigurationForm($form['ajax_wrapper']['provider_configuration'], $this->getSubFormState('provider_configuration', $form, $form_state));
+    }
+
+    if ($this->entity->getProviderPluginInstance()->getBehaviorServiceInstance() instanceof SynonymsBehaviorConfigurableInterface) {
+      $this->entity->getProviderPluginInstance()->getBehaviorServiceInstance()->validateConfigurationForm($form['ajax_wrapper']['behavior_configuration'], $this->getSubFormState('behavior_configuration', $form, $form_state), $this->entity);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    parent::submitForm($form, $form_state);
+
+    if ($this->entity->getProviderPluginInstance() instanceof PluginFormInterface) {
+      $this->entity->getProviderPluginInstance()->submitConfigurationForm($form['ajax_wrapper']['provider_configuration'], $this->getSubFormState('provider_configuration', $form, $form_state));
+    }
+
+    if ($this->entity->getProviderPluginInstance()->getBehaviorServiceInstance() instanceof SynonymsBehaviorConfigurableInterface) {
+      $this->entity->setBehaviorConfiguration($this->entity->getProviderPluginInstance()->getBehaviorServiceInstance()->submitConfigurationForm($form['ajax_wrapper']['behavior_configuration'], $this->getSubFormState('behavior_configuration', $form, $form_state), $this->entity));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save(array $form, FormStateInterface $form_state) {
+    $status = $this->entity->save();
+
+    if ($status) {
+      drupal_set_message($this->t('Saved the %label synonym configuration.', [
+        '%label' => $this->entity->label(),
+      ]));
+    }
+    else {
+      drupal_set_message($this->t('The %label synonym configuration was not saved.', [
+        '%label' => $this->entity->label(),
+      ]), 'error');
+    }
+
+    $form_state->setRedirect('entity.synonym.overview');
+  }
+
+  /**
+   * Check whether entity with such ID already exists.
+   *
+   * @param string $id
+   *   Entity ID to check
+   *
+   * @return bool
+   *   Whether entity with such ID already exists.
+   */
+  public function exist($id) {
+    $entity = $this->entityQuery->get('synonym')
+      ->condition('id', $id)
+      ->execute();
+    return (bool) $entity;
+  }
+
+  /**
+   * Ajax callback.
+   */
+  public static function ajaxForm(array &$form, FormStateInterface $form_state, Request $request) {
+    return $form['ajax_wrapper'];
+  }
+
+  /**
+   * Supportive method to create sub-form-states.
+   *
+   * @param string $element_name
+   *   Name of the nested form element for which to create a sub form state
+   * @param array $form
+   *   Full form array
+   * @param FormStateInterface $form_state
+   *   Full form state out of which to create sub form state
+   *
+   * @return SubformState
+   *   Sub form state object generated based on the input arguments
+   */
+  protected function getSubFormState($element_name, array $form, FormStateInterface $form_state) {
+    return SubformState::createForSubform($form['ajax_wrapper'][$element_name], $form, $form_state);
+  }
+
+}

+ 40 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/ParamConverter/EntityTypeParamConverter.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace Drupal\synonyms\ParamConverter;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\ParamConverter\ParamConverterInterface;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Param converter service for entity types.
+ */
+class EntityTypeParamConverter implements ParamConverterInterface {
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * EntityTypeParamConverter constructor.
+   */
+  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function convert($value, $definition, $name, array $defaults) {
+    return $this->entityTypeManager->getDefinition($value);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function applies($definition, $name, Route $route) {
+    return (!empty($definition['type']) && $definition['type'] == 'synonyms_entity_type');
+  }
+
+}

+ 40 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/ParamConverter/SynonymsBehaviorServiceParamConverter.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace Drupal\synonyms\ParamConverter;
+
+use Drupal\Core\ParamConverter\ParamConverterInterface;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Param converter for synonyms behavior service.
+ */
+class SynonymsBehaviorServiceParamConverter implements ParamConverterInterface {
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * SynonymsBehaviorServiceParamConverter constructor.
+   */
+  public function __construct(BehaviorService $behavior_service) {
+    $this->behaviorService = $behavior_service;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function convert($value, $definition, $name, array $defaults) {
+    return $this->behaviorService->getBehaviorService($value)['service'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function applies($definition, $name, Route $route) {
+    return (!empty($definition['type']) && $definition['type'] == 'synonyms_behavior_service');
+  }
+
+}

+ 113 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Derivative/EntityReferenceField.php

@@ -0,0 +1,113 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Derivative;
+
+use Drupal\Component\Plugin\Derivative\DeriverBase;
+use Drupal\Core\Entity\ContentEntityType;
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Derivative for entity_reference synonyms provider plugin.
+ */
+class EntityReferenceField extends DeriverBase implements ContainerDeriverInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * Entity type manager.
+   *
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * Entity type bundle info.
+   *
+   * @var EntityTypeBundleInfoInterface
+   */
+  protected $entityTypeBundleInfo;
+
+  /**
+   * @var EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  function __construct(EntityTypeManagerInterface $entity_type_manager, BehaviorService $behavior_service, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityFieldManagerInterface $entity_field_manager) {
+    $this->entityTypeManager = $entity_type_manager;
+    $this->behaviorService = $behavior_service;
+    $this->entityTypeBundleInfo = $entity_type_bundle_info;
+    $this->entityFieldManager = $entity_field_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static(
+      $container->get('entity_type.manager'),
+      $container->get('synonyms.behaviors'),
+      $container->get('entity_type.bundle.info'),
+      $container->get('entity_field.manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    $implemented_interfaces = new \ReflectionClass($base_plugin_definition['class']);
+    $implemented_interfaces = $implemented_interfaces->getInterfaceNames();
+
+    foreach ($this->behaviorService->getBehaviorServices() as $service_id => $behavior) {
+      $required_interfaces = $behavior['required_interfaces'];
+
+      $diff = array_diff($required_interfaces, $implemented_interfaces);
+      if (empty($diff)) {
+        // This plugin has implemented all required interfaces for this
+        // behavior.
+        foreach ($this->entityTypeManager->getDefinitions() as $entity_type) {
+          if ($entity_type instanceof ContentEntityType) {
+            foreach ($this->entityTypeBundleInfo->getBundleInfo($entity_type->id()) as $bundle => $bundle_info) {
+              $fields = $this->entityFieldManager->getFieldDefinitions($entity_type->id(), $bundle);
+
+              foreach ($fields as $field) {
+                if ($field->getType() == 'entity_reference') {
+                  $derivative_name = implode('_', [
+                    $service_id,
+                    $entity_type->id(),
+                    $bundle,
+                    $field->getName(),
+                  ]);
+
+                  $this->derivatives[$derivative_name] = $base_plugin_definition;
+                  $this->derivatives[$derivative_name]['label'] = $this->t('@behavior on @field', [
+                    '@behavior' => $behavior['service']->getTitle(),
+                    '@field' => $field->getLabel(),
+                  ]);
+                  $this->derivatives[$derivative_name]['synonyms_behavior_service'] = $service_id;
+                  $this->derivatives[$derivative_name]['controlled_entity_type'] = $entity_type->id();
+                  $this->derivatives[$derivative_name]['controlled_bundle'] = $bundle;
+                  $this->derivatives[$derivative_name]['field'] = $field->getName();
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return $this->derivatives;
+  }
+
+}

+ 133 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Derivative/Field.php

@@ -0,0 +1,133 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Derivative;
+
+use Drupal\Component\Plugin\Derivative\DeriverBase;
+use Drupal\Core\Entity\ContentEntityType;
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+use Drupal\synonyms\SynonymsService\FieldTypeToSynonyms;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Derivative for synonyms provider plugins.
+ */
+class Field extends DeriverBase implements ContainerDeriverInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * Entity type manager.
+   *
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * Entity type bundle info.
+   *
+   * @var EntityTypeBundleInfoInterface
+   */
+  protected $entityTypeBundleInfo;
+
+  /**
+   * @var EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * @var FieldTypeToSynonyms
+   */
+  protected $fieldTypeToSynonyms;
+
+  function __construct(EntityTypeManagerInterface $entity_type_manager, BehaviorService $behavior_service, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityFieldManagerInterface $entity_field_manager, FieldTypeToSynonyms $field_type_to_synonyms) {
+    $this->entityTypeManager = $entity_type_manager;
+    $this->behaviorService = $behavior_service;
+    $this->entityTypeBundleInfo = $entity_type_bundle_info;
+    $this->entityFieldManager = $entity_field_manager;
+    $this->fieldTypeToSynonyms = $field_type_to_synonyms;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static(
+      $container->get('entity_type.manager'),
+      $container->get('synonyms.behaviors'),
+      $container->get('entity_type.bundle.info'),
+      $container->get('entity_field.manager'),
+      $container->get('synonyms.provider.field_type_to_synonyms')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    $implemented_interfaces = new \ReflectionClass($base_plugin_definition['class']);
+    $implemented_interfaces = $implemented_interfaces->getInterfaceNames();
+
+    $field_type_to_property_map = $this->fieldTypeToSynonyms->getSimpleFieldTypeToPropertyMap();
+    foreach ($this->behaviorService->getBehaviorServices() as $service_id => $behavior) {
+      $required_interfaces = $behavior['required_interfaces'];
+
+      $diff = array_diff($required_interfaces, $implemented_interfaces);
+      if (empty($diff)) {
+        // This plugin has implemented all required interfaces for this
+        // behavior.
+        foreach ($this->entityTypeManager->getDefinitions() as $entity_type) {
+          if ($entity_type instanceof ContentEntityType) {
+            foreach ($this->entityTypeBundleInfo->getBundleInfo($entity_type->id()) as $bundle => $bundle_info) {
+              $base_fields = $this->entityFieldManager->getBaseFieldDefinitions($entity_type->id());
+              $fields = $this->entityFieldManager->getFieldDefinitions($entity_type->id(), $bundle);
+
+              switch ($base_plugin_definition['id']) {
+                case 'base_field':
+                  $fields = $base_fields;
+                  break;
+
+                case 'field':
+                  $fields = array_diff_key($fields, $base_fields);
+                  break;
+              }
+
+              foreach ($fields as $field) {
+                if ($field->getName() != 'synonyms' && isset($field_type_to_property_map[$field->getType()])) {
+                  $derivative_name = implode('_', [
+                    $service_id,
+                    $entity_type->id(),
+                    $bundle,
+                    $field->getName(),
+                  ]);
+
+                  $this->derivatives[$derivative_name] = $base_plugin_definition;
+                  $this->derivatives[$derivative_name]['label'] = $this->t('@behavior on @field', [
+                    '@behavior' => $behavior['service']->getTitle(),
+                    '@field' => $field->getLabel(),
+                  ]);
+                  $this->derivatives[$derivative_name]['synonyms_behavior_service'] = $service_id;
+                  $this->derivatives[$derivative_name]['controlled_entity_type'] = $entity_type->id();
+                  $this->derivatives[$derivative_name]['controlled_bundle'] = $bundle;
+                  $this->derivatives[$derivative_name]['field'] = $field->getName();
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return $this->derivatives;
+  }
+
+}

+ 78 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Derivative/ViewsSynonymsEntityArgumentValidator.php

@@ -0,0 +1,78 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Derivative;
+
+use Drupal\Component\Plugin\Derivative\DeriverBase;
+use Drupal\Core\Entity\ContentEntityTypeInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslationInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides synonyms argument validator plugin definitions for all entity types.
+ */
+class ViewsSynonymsEntityArgumentValidator extends DeriverBase implements ContainerDeriverInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * The base plugin ID this derivative is for.
+   *
+   * @var string
+   */
+  protected $basePluginId;
+
+  /**
+   * The entity type manager.
+   *
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs an ViewsSynonymsEntityArgumentValidator object.
+   */
+  public function __construct($base_plugin_id, EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) {
+    $this->basePluginId = $base_plugin_id;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->stringTranslation = $string_translation;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static(
+      $base_plugin_id,
+      $container->get('entity_type.manager'),
+      $container->get('string_translation')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    $entity_types = $this->entityTypeManager->getDefinitions();
+    $this->derivatives = [];
+    foreach ($entity_types as $entity_type_id => $entity_type) {
+      if ($entity_type instanceof ContentEntityTypeInterface) {
+        $this->derivatives[$entity_type_id] = [
+          'id' => 'synonyms_entity:' . $entity_type_id,
+          'provider' => 'synonyms',
+          'title' => $this->t('Synonyms of @entity_type', [
+            '@entity_type' => $entity_type->getLowercaseLabel(),
+          ]),
+          'help' => $this->t('Validate @label', ['@label' => $entity_type->getLabel()]),
+          'entity_type' => $entity_type_id,
+          'class' => $base_plugin_definition['class'],
+        ];
+      }
+    }
+
+    return $this->derivatives;
+  }
+
+}

+ 157 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Field/FieldWidget/EntityReferenceSynonymsAutocomplete.php

@@ -0,0 +1,157 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Plugin implementation of the 'synonyms friendly autocomplete' widget.
+ *
+ * @FieldWidget(
+ *   id = "synonyms_autocomplete",
+ *   label = @Translation("Synonyms-friendly autocomplete"),
+ *   description = @Translation("An autocomplete with entities and their synonyms."),
+ *   field_types = {
+ *     "entity_reference"
+ *   },
+ *   multiple_values = TRUE
+ * )
+ */
+class EntityReferenceSynonymsAutocomplete extends WidgetBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, BehaviorService $behavior_service) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
+
+    $this->behaviorService = $behavior_service;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['third_party_settings'],
+      $container->get('synonyms.behaviors')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return [
+      'suggestion_size' => 10,
+      'suggest_only_unique' => FALSE,
+      'match' => 'CONTAINS',
+    ] + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $elements = parent::settingsForm($form, $form_state);
+
+    $elements['suggestion_size'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Suggestions Size'),
+      '#description' => $this->t('Please, enter how many suggested entities to show in the autocomplete textfield.'),
+      '#required' => TRUE,
+      '#default_value' => $this->getSetting('suggestion_size'),
+    ];
+
+    $elements['suggest_only_unique'] = [
+      '#type' => 'checkbox',
+      '#title' => t('Suggest only one entry per entity'),
+      '#description' => t('If you want to include only name or a single synonym, suggesting a particular entity, while disregarding all ongoing ones, please, tick this checkbox on.'),
+      '#default_value' => $this->getSetting('suggest_only_unique'),
+    ];
+
+    $elements['match'] = [
+      '#type' => 'radios',
+      '#title' => $this->t('Match operator'),
+      '#description' => $this->t('Choose how to match the keyword against existing data.'),
+      '#options' => $this->getMatchOperatorOptions(),
+      '#default_value' => $this->getSetting('match'),
+      '#required' => TRUE,
+    ];
+
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = parent::settingsSummary();
+
+    $summary[] = $this->t('Suggestion size: @size', [
+      '@size' => $this->getSetting('suggestion_size'),
+    ]);
+
+    $summary[] = $this->t('Only unique: @unique', [
+      '@unique' => $this->getSetting('suggest_only_unique') ? $this->t('Yes') : $this->t('No'),
+    ]);
+
+    $summary[] = $this->t('Match: @match', [
+      '@match' => $this->getMatchOperatorOptions()[$this->getSetting('match')],
+    ]);
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    $default_value = [];
+    foreach ($items as $item) {
+      if ($item->entity) {
+        $default_value[] = $item->entity;
+      }
+    }
+    $element += [
+      '#type' => 'synonyms_entity_autocomplete',
+      '#target_type' => $this->getFieldSetting('target_type'),
+      '#target_bundles' => $this->getFieldSetting('handler_settings')['target_bundles'],
+      '#suggestion_size' => $this->getSetting('suggestion_size'),
+      '#suggest_only_unique' => $this->getSetting('suggest_only_unique'),
+      '#match' => $this->getSetting('match'),
+      '#default_value' => $default_value,
+    ];
+
+    return $element;
+  }
+
+  /**
+   * Returns the options for the match operator.
+   *
+   * @return array
+   *   List of options.
+   */
+  protected function getMatchOperatorOptions() {
+    return [
+      'STARTS_WITH' => t('Starts with'),
+      'CONTAINS' => t('Contains'),
+    ];
+  }
+
+}

+ 56 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Field/FieldWidget/EntityReferenceSynonymsSelect.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Plugin implementation of the 'synonyms friendly select' widget.
+ *
+ * @FieldWidget(
+ *   id = "synonyms_select",
+ *   label = @Translation("Synonyms-friendly select"),
+ *   description = @Translation("A dropdown with entities and their synonyms."),
+ *   field_types = {
+ *     "entity_reference"
+ *   },
+ *   multiple_values = TRUE
+ * )
+ */
+class EntityReferenceSynonymsSelect extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    $default_value = [];
+    foreach ($items as $item) {
+      if ($item->{$this->getKeyColumn()}) {
+        $default_value[] = $item->{$this->getKeyColumn()};
+      }
+    }
+
+    $element += [
+      '#type' => 'synonyms_entity_select',
+      '#key_column' => $this->getKeyColumn(),
+      '#target_type' => $this->getFieldSetting('target_type'),
+      '#handler' => $this->fieldDefinition->getSetting('handler'),
+      '#handler_settings' => $this->fieldDefinition->getSetting('handler_settings') ?: [],
+      '#multiple' => $this->fieldDefinition->getFieldStorageDefinition()->isMultiple(),
+      '#default_value' => $this->fieldDefinition->getFieldStorageDefinition()->isMultiple() ? $default_value : reset($default_value),
+    ];
+    return $element;
+  }
+
+  /**
+   * Get name of the column that is managed by this widget in the field
+   * .
+   * @return string
+   */
+  protected function getKeyColumn() {
+    return $this->fieldDefinition->getFieldStorageDefinition()->getPropertyNames()[0];
+  }
+
+}

+ 58 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Synonyms/Provider/AbstractProvider.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Synonyms\Provider;
+
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsProviderInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Good starting point for a synonyms provider plugin.
+ */
+abstract class AbstractProvider extends PluginBase implements SynonymsProviderInterface, ContainerFactoryPluginInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * @var ContainerInterface
+   */
+  protected $container;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, ContainerInterface $container) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->container = $container;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getBehaviorService() {
+    return $this->getPluginDefinition()['synonyms_behavior_service'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getBehaviorServiceInstance() {
+    return $this->container->get($this->getPluginDefinition()['synonyms_behavior_service']);
+  }
+
+}

+ 128 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Synonyms/Provider/BaseField.php

@@ -0,0 +1,128 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Synonyms\Provider;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\ConditionInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindTrait;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFormatWordingProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFormatWordingTrait;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetTrait;
+use Drupal\synonyms\SynonymsService\FieldTypeToSynonyms;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provide synonyms from base fields.
+ *
+ * @SynonymsProvider(
+ *   id = "base_field",
+ *   deriver = "Drupal\synonyms\Plugin\Derivative\Field"
+ * )
+ */
+class BaseField extends AbstractProvider implements SynonymsGetProviderInterface, SynonymsFindProviderInterface, SynonymsFormatWordingProviderInterface {
+
+  use SynonymsGetTrait, SynonymsFindTrait, SynonymsFormatWordingTrait;
+
+  /**
+   * @var EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * @var FieldTypeToSynonyms
+   */
+  protected $fieldTypeToSynonyms;
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var Connection
+   */
+  protected $database;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityFieldManagerInterface $entity_field_manager, FieldTypeToSynonyms $field_type_to_synonyms, EntityTypeManagerInterface $entity_type_manager, Connection $database, ContainerInterface $container) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $container);
+
+    $this->entityFieldManager = $entity_field_manager;
+    $this->fieldTypeToSynonyms = $field_type_to_synonyms;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->database = $database;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_field.manager'),
+      $container->get('synonyms.provider.field_type_to_synonyms'),
+      $container->get('entity_type.manager'),
+      $container->get('database'),
+      $container
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSynonyms(ContentEntityInterface $entity, array $behavior_configuration = []) {
+    $map = $this->fieldTypeToSynonyms->getSimpleFieldTypeToPropertyMap();
+    $field_type = $entity->getFieldDefinition($this->getPluginDefinition()['field'])->getType();
+
+    $synonyms = [];
+
+    if (isset($map[$field_type])) {
+      foreach ($entity->get($this->getPluginDefinition()['field']) as $item) {
+        $synonyms[] = $item->{$map[$field_type]};
+      }
+    }
+
+    return $synonyms;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function synonymsFind(ConditionInterface $condition) {
+    $entity_type_definition = $this->entityTypeManager->getDefinition($this->getPluginDefinition()['controlled_entity_type']);
+    $entity_keys = $entity_type_definition->getKeys();
+
+    $query = $this->database->select($entity_type_definition->getDataTable(), 'base');
+    $query->addField('base', $entity_keys['id'], 'entity_id');
+    $query->addField('base', $this->getPluginDefinition()['field'], 'synonym');
+
+    if ($this->getPluginDefinition()['controlled_entity_type'] != $this->getPluginDefinition()['controlled_bundle'] && isset($entity_keys['bundle']) && $entity_keys['bundle']) {
+      $query->condition($entity_keys['bundle'], $this->getPluginDefinition()['controlled_bundle']);
+    }
+
+    $this->synonymsFindProcessCondition($condition, $this->getPluginDefinition()['field'], $entity_keys['id']);
+    $query->condition($condition);
+
+    return $query->execute();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    $field = $this->entityFieldManager->getFieldDefinitions($this->getPluginDefinition()['controlled_entity_type'], $this->getPluginDefinition()['controlled_bundle'])[$this->getPluginDefinition()['field']];
+    return [
+      $field->getConfigDependencyKey() => [$field->getConfigDependencyName()],
+    ];
+  }
+
+}

+ 191 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Synonyms/Provider/EntityReferenceField.php

@@ -0,0 +1,191 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Synonyms\Provider;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\ConditionInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\Query\QueryBase;
+use Drupal\Core\Entity\Query\Sql\Condition;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindTrait;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFormatWordingProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFormatWordingTrait;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetTrait;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provide synonyms from entity reference field type.
+ *
+ * @SynonymsProvider(
+ *   id = "entityreference_field",
+ *   deriver = "Drupal\synonyms\Plugin\Derivative\EntityReferenceField"
+ * )
+ */
+class EntityReferenceField extends AbstractProvider implements SynonymsGetProviderInterface, SynonymsFindProviderInterface, SynonymsFormatWordingProviderInterface {
+
+  use SynonymsGetTrait, SynonymsFindTrait, SynonymsFormatWordingTrait;
+
+  /**
+   * @var EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var Connection
+   */
+  protected $database;
+
+  /**
+   * @var QueryFactory
+   */
+  protected $entityQueryFactory;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityFieldManagerInterface $entity_field_manager, EntityTypeManagerInterface $entity_type_manager, Connection $database, QueryFactory $entity_query_factory, ContainerInterface $container) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $container);
+
+    $this->entityFieldManager = $entity_field_manager;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->database = $database;
+    $this->entityQueryFactory = $entity_query_factory;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_field.manager'),
+      $container->get('entity_type.manager'),
+      $container->get('database'),
+      $container->get('entity.query'),
+      $container
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSynonyms(ContentEntityInterface $entity, array $behavior_configuration = []) {
+    $synonyms = [];
+
+    foreach ($entity->get($this->getPluginDefinition()['field']) as $item) {
+      $synonyms[] = $item->entity->label();
+    }
+
+    return $synonyms;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function synonymsFind(ConditionInterface $condition) {
+    $entity_type_definition = $this->entityTypeManager->getDefinition($this->getPluginDefinition()['controlled_entity_type']);
+    $field = $this->entityFieldManager->getFieldDefinitions($this->getPluginDefinition()['controlled_entity_type'], $this->getPluginDefinition()['controlled_bundle']);
+    $field = $field[$this->getPluginDefinition()['field']];
+
+    $query = new FieldQuery($entity_type_definition, 'AND', $this->database, QueryBase::getNamespaces($this->entityQueryFactory->get($entity_type_definition->id(), 'AND')));
+
+    if ($entity_type_definition->hasKey('bundle')) {
+      $query->condition($entity_type_definition->getKey('bundle'), $this->getPluginDefinition()['controlled_bundle']);
+    }
+
+    $target_entity_type_definition = $this->entityTypeManager->getDefinition($field->getSetting('target_type'));
+    $label_column = $target_entity_type_definition->getKey('label');
+
+    // Some hacks.
+    if (!$label_column && $target_entity_type_definition->id() == 'user') {
+      $label_column = 'name';
+    }
+
+    if (!$label_column) {
+      // No label column is defined on target entity type, there's nothing we
+      // can do.
+      return [];
+    }
+
+    $synonym_column = $field->getName() . '.entity.' . $label_column;
+    $this->synonymsFindProcessCondition($condition, $synonym_column, $entity_type_definition->getKey('id'));
+
+    $conditions_array = $condition->conditions();
+    $entity_condition = new Condition($conditions_array['#conjunction'], $query);
+
+    // We will insert a dummy condition for a synonym column just to have the
+    // actual table.column data on the synonym column.
+    $hash = md5($synonym_column);
+    $query->condition($synonym_column, $hash);
+
+    unset($conditions_array['#conjunction']);
+    foreach ($conditions_array as $v) {
+      $entity_condition->condition($v['field'], $v['value'], $v['operator']);
+    }
+
+    $query->condition($entity_condition);
+
+    // We need run the entity query in order to force it into building a normal
+    // SQL query.
+    $query->execute();
+
+    // Now let's get "demapped" normal SQL query that will tell us explicitly
+    // where all entity properties/fields are stored among the SQL tables. Such
+    // data is what we need and we do not want to demap it manually.
+    $sql_query = $query->getSqlQuery();
+
+    // Swap the entity_id column into the alias "entity_id" as we are supposed
+    // to do in this method implementation.
+    $select_fields = &$sql_query->getFields();
+    $select_fields = ['entity_id' => $select_fields[$entity_type_definition->getKey('id')]];
+    $select_fields['entity_id']['alias'] = 'entity_id';
+
+    // We need some dummy extra condition to force them into re-compilation.
+    $sql_query->where('1 = 1');
+    $conditions_array = &$sql_query->conditions();
+    foreach ($conditions_array as $k => $condition_array) {
+      if (isset($condition_array['value']) && $condition_array['value'] == $hash) {
+        list($table_alias, $column) = explode('.', $condition_array['field']);
+        unset($conditions_array[$k]);
+
+        // Also unsetting the table aliased by this condition.
+        $tables = &$sql_query->getTables();
+        $real_table = $tables[$table_alias]['table'];
+        foreach ($tables as $k2 => $v2) {
+          if ($k2 != $table_alias && $real_table == $v2['table']) {
+            unset($tables[$table_alias]);
+            $table_alias = $k2;
+          }
+        }
+
+        $sql_query->addField($table_alias, $column, 'synonym');
+        break;
+      }
+    }
+    $result = $sql_query->execute();
+    return $result;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    $field = $this->entityFieldManager->getFieldDefinitions($this->getPluginDefinition()['controlled_entity_type'], $this->getPluginDefinition()['controlled_bundle'])[$this->getPluginDefinition()['field']];
+    return [
+      $field->getConfigDependencyKey() => [$field->getConfigDependencyName()],
+    ];
+  }
+
+}

+ 216 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/Synonyms/Provider/Field.php

@@ -0,0 +1,216 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\Synonyms\Provider;
+
+use Drupal\Component\Plugin\DependentPluginInterface;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\ConditionInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\Query\QueryBase;
+use Drupal\Core\Entity\Query\Sql\Condition;
+use Drupal\Core\Entity\Query\Sql\Query;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindTrait;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFormatWordingProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFormatWordingTrait;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetTrait;
+use Drupal\synonyms\SynonymsService\FieldTypeToSynonyms;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provide synonyms from attached simple fields.
+ *
+ * @SynonymsProvider(
+ *   id = "field",
+ *   deriver = "Drupal\synonyms\Plugin\Derivative\Field"
+ * )
+ */
+class Field extends AbstractProvider implements SynonymsGetProviderInterface, SynonymsFindProviderInterface, SynonymsFormatWordingProviderInterface, DependentPluginInterface {
+
+  use SynonymsGetTrait, SynonymsFindTrait, SynonymsFormatWordingTrait;
+
+  /**
+   * @var EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * @var FieldTypeToSynonyms
+   */
+  protected $fieldTypeToSynonyms;
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var Connection
+   */
+  protected $database;
+
+  /**
+   * @var QueryFactory
+   */
+  protected $entityQueryFactory;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityFieldManagerInterface $entity_field_manager, FieldTypeToSynonyms $field_type_to_synonyms, EntityTypeManagerInterface $entity_type_manager, Connection $database, QueryFactory $entity_query_factory, ContainerInterface $container) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $container);
+
+    $this->entityFieldManager = $entity_field_manager;
+    $this->fieldTypeToSynonyms = $field_type_to_synonyms;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->database = $database;
+    $this->entityQueryFactory = $entity_query_factory;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_field.manager'),
+      $container->get('synonyms.provider.field_type_to_synonyms'),
+      $container->get('entity_type.manager'),
+      $container->get('database'),
+      $container->get('entity.query'),
+      $container
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSynonyms(ContentEntityInterface $entity, array $behavior_configuration = []) {
+    $map = $this->fieldTypeToSynonyms->getSimpleFieldTypeToPropertyMap();
+    $field_type = $entity->getFieldDefinition($this->getPluginDefinition()['field'])->getType();
+
+    $synonyms = [];
+
+    if (isset($map[$field_type])) {
+      foreach ($entity->get($this->getPluginDefinition()['field']) as $item) {
+        $synonyms[] = $item->{$map[$field_type]};
+      }
+    }
+
+    return $synonyms;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function synonymsFind(ConditionInterface $condition) {
+    $entity_type_definition = $this->entityTypeManager->getDefinition($this->getPluginDefinition()['controlled_entity_type']);
+    $field = $this->entityFieldManager->getFieldDefinitions($this->getPluginDefinition()['controlled_entity_type'], $this->getPluginDefinition()['controlled_bundle']);
+    $field = $field[$this->getPluginDefinition()['field']];
+    $field_property = $this->fieldTypeToSynonyms->getSimpleFieldTypeToPropertyMap();
+    if (isset($field_property[$field->getType()])) {
+      $field_property = $field_property[$field->getType()];
+    }
+    else {
+      return [];
+    }
+
+    $query = new FieldQuery($entity_type_definition, 'AND', $this->database, QueryBase::getNamespaces($this->entityQueryFactory->get($entity_type_definition->id(), 'AND')));
+
+
+    if ($entity_type_definition->hasKey('bundle')) {
+      $query->condition($entity_type_definition->getKey('bundle'), $this->getPluginDefinition()['controlled_bundle']);
+    }
+
+    $synonym_column = $field->getName() . '.' . $field_property;
+    $this->synonymsFindProcessCondition($condition, $synonym_column, $entity_type_definition->getKey('id'));
+
+    $conditions_array = $condition->conditions();
+    $entity_condition = new Condition($conditions_array['#conjunction'], $query);
+
+    // We will insert a dummy condition for a synonym column just to have the
+    // actual table.column data on the synonym column.
+    $hash = md5($synonym_column);
+    $query->condition($synonym_column, $hash);
+
+    unset($conditions_array['#conjunction']);
+    foreach ($conditions_array as $v) {
+      $entity_condition->condition($v['field'], $v['value'], $v['operator']);
+    }
+
+    $query->condition($entity_condition);
+
+    // We need run the entity query in order to force it into building a normal
+    // SQL query.
+    $query->execute();
+
+    // Now let's get "demapped" normal SQL query that will tell us explicitly
+    // where all entity properties/fields are stored among the SQL tables. Such
+    // data is what we need and we do not want to demap it manually.
+    $sql_query = $query->getSqlQuery();
+
+    // Swap the entity_id column into the alias "entity_id" as we are supposed
+    // to do in this method implementation.
+    $select_fields = &$sql_query->getFields();
+    $select_fields = ['entity_id' => $select_fields[$entity_type_definition->getKey('id')]];
+    $select_fields['entity_id']['alias'] = 'entity_id';
+
+    // We need some dummy extra condition to force them into re-compilation.
+    $sql_query->where('1 = 1');
+    $conditions_array = &$sql_query->conditions();
+    foreach ($conditions_array as $k => $condition_array) {
+      if (isset($condition_array['value']) && $condition_array['value'] == $hash) {
+        list($table_alias, $column) = explode('.', $condition_array['field']);
+        unset($conditions_array[$k]);
+
+        // Also unsetting the table aliased by this condition.
+        $tables = &$sql_query->getTables();
+        $real_table = $tables[$table_alias]['table'];
+        foreach ($tables as $k2 => $v2) {
+          if ($k2 != $table_alias && $real_table == $v2['table']) {
+            unset($tables[$table_alias]);
+            $table_alias = $k2;
+          }
+        }
+
+        $sql_query->addField($table_alias, $column, 'synonym');
+        break;
+      }
+    }
+    $result = $sql_query->execute();
+    return $result;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    $field = $this->entityFieldManager->getFieldDefinitions($this->getPluginDefinition()['controlled_entity_type'], $this->getPluginDefinition()['controlled_bundle'])[$this->getPluginDefinition()['field']];
+    return [
+      $field->getConfigDependencyKey() => [$field->getConfigDependencyName()],
+    ];
+  }
+
+}
+
+/**
+ * Hacked implementation of Entity query.
+ */
+class FieldQuery extends Query {
+
+  /**
+   * We need to be able to extract SQL query object.
+   *
+   * @return \Drupal\Core\Database\Query\SelectInterface
+   */
+  public function getSqlQuery() {
+    return $this->sqlQuery;
+  }
+
+}

+ 33 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/SynonymsFieldItemList.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace Drupal\synonyms\Plugin;
+
+use Drupal\Core\Field\FieldItemList;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetProviderInterface;
+
+/**
+ * Field item list of "synonyms" computed base field.
+ */
+class SynonymsFieldItemList extends FieldItemList {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue($include_computed = FALSE) {
+    $synonyms = [];
+
+    $entity = $this->getEntity();
+
+    $behavior_service = \Drupal::getContainer()->get('synonyms.behaviors');
+
+    $services = $behavior_service->getBehaviorServicesWithInterface(SynonymsGetProviderInterface::class);
+    foreach ($services as $service_id => $service) {
+      foreach ($behavior_service->getSynonymConfigEntities($service_id, $entity->getEntityTypeId(), $entity->bundle()) as $synonym_config) {
+        $synonyms = array_merge($synonyms, $synonym_config->getProviderPluginInstance()->getSynonyms($entity, $synonym_config->getBehaviorConfiguration()));
+      }
+    }
+
+    return array_unique($synonyms);
+  }
+
+}

+ 144 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/views/argument_validator/SynonymsEntity.php

@@ -0,0 +1,144 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\views\argument_validator;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindProviderInterface;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+use Drupal\views\Plugin\views\argument_validator\Entity;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Synonyms-friendly entity validator.
+ *
+ * @ViewsArgumentValidator(
+ *   id = "synonyms_entity",
+ *   deriver = "Drupal\synonyms\Plugin\Derivative\ViewsSynonymsEntityArgumentValidator"
+ * )
+ */
+class SynonymsEntity extends Entity {
+
+  protected $multipleCapable = FALSE;
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var QueryFactory
+   */
+  protected $entityQuery;
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, EntityTypeManagerInterface $entity_type_manager, QueryFactory $entity_query, BehaviorService $behavior_service) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_manager);
+
+    $this->entityTypeManager = $entity_type_manager;
+    $this->entityQuery = $entity_query;
+    $this->behaviorService = $behavior_service;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_definition,
+      $plugin_definition,
+      $container->get('entity.manager'),
+      $container->get('entity_type.manager'),
+      $container->get('entity.query'),
+      $container->get('synonyms.behaviors')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+    parent::buildOptionsForm($form, $form_state);
+
+    $form['transform'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Transform dashes in URL to spaces.'),
+      '#default_value' => $this->options['transform'],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateArgument($argument) {
+    if ($this->options['transform']) {
+      $argument = str_replace('-', ' ', $argument);
+    }
+
+    $entity_type = $this->entityTypeManager->getDefinition($this->definition['entity_type']);
+
+    if ($entity_type->hasKey('label') || $entity_type->id() == 'user') {
+      $query = $this->entityQuery->get($entity_type->id());
+
+      // User entity type does not declare its label, while it does have one.
+      $label_column = $entity_type->id() == 'user' ? 'name' : $entity_type->getKey('label');
+      $query->condition($label_column, $argument, '=');
+
+      if ($entity_type->hasKey('bundle') && !empty($this->options['bundles'])) {
+        $query->condition($entity_type->getKey('bundle'), $this->options['bundles'], 'IN');
+      }
+
+      $result = $query->execute();
+      if (!empty($result)) {
+        $entities = $this->entityTypeManager->getStorage($entity_type->id())->loadMultiple($result);
+        foreach ($entities as $entity) {
+          if ($this->validateEntity($entity)) {
+            $this->argument->argument = $entity->id();
+            return TRUE;
+          }
+        }
+      }
+    }
+
+    // We've fallen through with search by entity name, now it's time to search
+    // by synonyms.
+    $condition = new Condition('AND');
+    $condition->condition(SynonymsFindProviderInterface::COLUMN_SYNONYM_PLACEHOLDER, $argument, '=');
+
+    foreach ($this->behaviorService->getBehaviorServicesWithInterface(SynonymsFindProviderInterface::class) as $service_id => $service) {
+      foreach ($this->behaviorService->getSynonymConfigEntities($service_id, $entity_type->id(), empty($this->options['bundles']) ? NULL : $this->options['bundles']) as $synonym_config) {
+        foreach ($synonym_config->getProviderPluginInstance()->synonymsFind(clone $condition) as $synonym) {
+          $entity = $this->entityTypeManager->getStorage($entity_type->id())->load($synonym->entity_id);
+          if ($this->validateEntity($entity)) {
+            $this->argument->argument = $entity->id();
+            return TRUE;
+          }
+        }
+      }
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+    $options['transform'] = ['default' => FALSE];
+
+    return $options;
+  }
+
+}

+ 243 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/Plugin/views/filter/SynonymsEntity.php

@@ -0,0 +1,243 @@
+<?php
+
+namespace Drupal\synonyms\Plugin\views\filter;
+
+use Drupal\Core\Entity\Entity;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\views\Plugin\views\display\DisplayPluginBase;
+use Drupal\views\Plugin\views\filter\FilterPluginBase;
+use Drupal\views\ViewExecutable;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Filter entity by its name or one of its synonyms.
+ *
+ * @ViewsFilter("synonyms_entity")
+ */
+class SynonymsEntity extends FilterPluginBase {
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var EntityTypeBundleInfoInterface
+   */
+  protected $entityTypeBundleInfo;
+
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->entityTypeManager = $entity_type_manager;
+    $this->entityTypeBundleInfo = $entity_type_bundle_info;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_type.manager'),
+      $container->get('entity_type.bundle.info')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defineOptions() {
+    $options = parent::defineOptions();
+
+    $options['widget'] = [
+      'default' => 'autocomplete',
+    ];
+
+    $options['target_bundles'] = [
+      'default' => NULL,
+    ];
+
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
+    parent::init($view, $display, $options);
+
+    switch ($this->options['widget']) {
+      case 'autocomplete':
+        $this->operator = 'IN';
+        break;
+
+      case 'select':
+        $this->operator = !$this->isExposed() || $this->options['expose']['multiple'] ? 'IN' : '=';
+        break;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
+    parent::buildExtraOptionsForm($form, $form_state);
+
+    $form['widget'] = [
+      '#type' => 'radios',
+      '#title' => $this->t('Widget'),
+      '#options' => [
+        'autocomplete' => $this->t('Autocomplete'),
+        'select' => $this->t('Select'),
+      ],
+      '#default_value' => $this->options['widget'],
+      '#required' => TRUE,
+      '#description' => $this->t('Choose what widget to use in order to specify entity.'),
+    ];
+
+    if ($this->entityTypeManager->getDefinition($this->definition['entity_type'])->hasKey('bundle')) {
+      $options = array_map(function($item) {
+        return $item['label'];
+      }, $this->entityTypeBundleInfo->getBundleInfo($this->definition['entity_type']));
+
+      $form['target_bundles'] = [
+        '#type' => 'checkboxes',
+        '#title' => $this->t('Bundles'),
+        '#description' => $this->t('Limit the possible values down to specific subset of bundles. Leave empty to have no filter by bundles.'),
+        '#default_value' => $this->options['target_bundles'],
+        '#options' => $options,
+      ];
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitExtraOptionsForm($form, FormStateInterface $form_state) {
+    parent::submitExtraOptionsForm($form, $form_state);
+
+    if (isset($form['target_bundles'])) {
+      $target_bundles = array_values(array_filter($form_state->getValue($form['target_bundles']['#parents'])));
+      if (empty($target_bundles)) {
+        $target_bundles = NULL;
+      }
+      $form_state->setValueForElement($form['target_bundles'], $target_bundles);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasExtraOptions() {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateExposed(&$form, FormStateInterface $form_state) {
+    parent::validateExposed($form, $form_state);
+
+    $identifier = $this->options['expose']['identifier'];
+
+    $target_ids = $form_state->getValue($identifier);
+    switch ($this->operator) {
+      case 'IN':
+        $target_ids = array_map(function($item) {
+          return $item['target_id'];
+        }, $target_ids);
+        break;
+
+      case '=':
+        $target_ids = $target_ids['target_id'];
+        break;
+    }
+
+    $form_state->setValue($identifier, $target_ids);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function adminSummary() {
+    if ($this->isExposed()) {
+      return $this->t('Exposed');
+    }
+
+    $labels = [];
+
+    if (!empty($this->value)) {
+      foreach ($this->getEntityStorage()->loadMultiple($this->value) as $entity) {
+        $labels[] = $entity->label();
+      }
+    }
+
+    return $this->operator . ' ' . implode(', ', $labels);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function valueForm(&$form, FormStateInterface $form_state) {
+    if (!empty($this->value)) {
+      $default_value = $this->getEntityStorage()->loadMultiple($this->value);
+    }
+    else {
+      $default_value = [];
+    }
+
+    switch ($this->options['widget']) {
+      case 'autocomplete':
+        $form['value'] = [
+          '#type' => 'synonyms_entity_autocomplete',
+          '#title' => $this->t('Entity'),
+          '#target_type' => $this->definition['entity_type'],
+          '#target_bundles' => $this->options['target_bundles'],
+          '#default_value' => $default_value,
+        ];
+        break;
+
+      case 'select':
+        $form['value'] = [
+          '#type' => 'synonyms_entity_select',
+          '#title' => $this->t('Entity'),
+          '#target_type' => $this->definition['entity_type'],
+          '#handler_settings' => [
+            'target_bundles' => $this->options['target_bundles'],
+          ],
+          '#default_value' => array_keys($default_value),
+          '#multiple' => TRUE,
+          '#empty_option' => '',
+        ];
+        break;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function valueSubmit($form, FormStateInterface $form_state) {
+    parent::valueSubmit($form, $form_state);
+
+    $target_ids = array_map(function($item) {
+      return $item['target_id'];
+    }, $form_state->getValue($form['value']['#parents']));
+
+    $form_state->setValueForElement($form['value'], $target_ids);
+  }
+
+  /**
+   * Get entity storage of the entity type this filter is set up to use.
+   *
+   * @return \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected function getEntityStorage() {
+    return $this->entityTypeManager->getStorage($this->definition['entity_type']);
+  }
+
+}

+ 72 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymInterface.php

@@ -0,0 +1,72 @@
+<?php
+
+namespace Drupal\synonyms;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsProviderInterface;
+
+/**
+ * Interface of synonyms configuration entity.
+ */
+interface SynonymInterface extends ConfigEntityInterface, EntityWithPluginCollectionInterface {
+
+  /**
+   * Get ID of the synonyms provider plugin that is set up in this entity.
+   *
+   * @return string
+   *   Plugin ID of synonyms provider that corresponds to this configuration
+   *   entity
+   */
+  public function getProviderPlugin();
+
+  /**
+   * Get instance of the synonyms provider plugin that is set up in this entity.
+   *
+   * @return SynonymsProviderInterface
+   *   Initiated synonyms provider instance that corresponds to this
+   *   configuration entity
+   */
+  public function getProviderPluginInstance();
+
+  /**
+   * Set the synonyms provider plugin to use in this entity.
+   *
+   * @param string $plugin
+   *   Synonyms provider plugin ID to set in this configuration entity
+   */
+  public function setProviderPlugin($plugin);
+
+  /**
+   * Get synonyms provider plugin configuration from this entity.
+   *
+   * @return array
+   *   Array of synonyms provider plugin configuration
+   */
+  public function getProviderConfiguration();
+
+  /**
+   * Set synonyms provider plugin configuration for this entity.
+   *
+   * @param array $provider_configuration
+   *   Array of synonyms provider plugin configuration to set
+   */
+  public function setProviderConfiguration(array $provider_configuration);
+
+  /**
+   * Get synonyms behavior configuration from this entity.
+   *
+   * @return array
+   *   Array of synonyms behavior configuration
+   */
+  public function getBehaviorConfiguration();
+
+  /**
+   * Set synonyms behavior configuration for this entity.
+   *
+   * @param array $behavior_configuration
+   *   Array of synonyms behavior configuration to set
+   */
+  public function setBehaviorConfiguration(array $behavior_configuration);
+
+}

+ 21 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymProviderPluginCollection.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace Drupal\synonyms;
+
+use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
+
+/**
+ * Provides a collection of synonym provider plugins.
+ */
+class SynonymProviderPluginCollection extends DefaultSingleLazyPluginCollection {
+
+  /**
+   * {@inheritdoc}
+   *
+   * @return \Drupal\synonyms\SynonymsProviderInterface\SynonymsProviderInterface
+   */
+  public function &get($instance_id) {
+    return parent::get($instance_id);
+  }
+
+}

+ 58 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsFindProviderInterface.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsProviderInterface;
+
+use Drupal\Core\Database\Query\ConditionInterface;
+
+/**
+ * Interface to look up entities by synonyms they have.
+ */
+interface SynonymsFindProviderInterface extends SynonymsProviderInterface {
+
+  /**
+   * Constant which denotes placeholder of a synonym column.
+   *
+   * @var string
+   */
+  const COLUMN_SYNONYM_PLACEHOLDER = '***SYNONYM_COLUMN***';
+
+  /**
+   * Constant which denotes placeholder of an entity ID column.
+   *
+   * @var string
+   */
+  const COLUMN_ENTITY_ID_PLACEHOLDER = '***ENTITY_ID***';
+
+  /**
+   * Look up entities by their synonyms within a behavior implementation.
+   *
+   * You are provided with a SQL condition that you should apply to the storage
+   * of synonyms within the provided behavior implementation. And then return
+   * result: what entities are matched by the provided condition through what
+   * synonyms.
+   *
+   * @param \Drupal\Core\Database\Query\ConditionInterface $condition
+   *   Condition that defines what to search for. Apart from normal SQL
+   *   conditions as known in Drupal, it may contain the following placeholders:
+   *   - SynonymsFindProviderInterface::COLUMN_SYNONYM_PLACEHOLDER: to denote
+   *     synonyms column which you should replace with the actual column name
+   *     where the synonyms data for your provider is stored in plain text.
+   *   - SynonymsFindProviderInterface::COLUMN_ENTITY_ID_PLACEHOLDER: to denote
+   *     column that holds entity ID. You are supposed to replace this
+   *     placeholder with actual column name that holds entity ID in your case.
+   *   For ease of work with these placeholders, you may use the
+   *   SynonymsFindTrait and then just invoke the
+   *   $this->synonymsFindProcessCondition() method, so you won't have to worry
+   *   much about it
+   *
+   * @return \Traversable
+   *   Traversable result set of found synonyms and entity IDs to which those
+   *   belong. Each element in the result set should be an object and should
+   *   have the following structure:
+   *   - synonym: (string) Synonym that was found and which satisfies the
+   *     provided condition
+   *   - entity_id: (int) ID of the entity to which the found synonym belongs
+   */
+  public function synonymsFind(ConditionInterface $condition);
+
+}

+ 45 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsFindTrait.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsProviderInterface;
+
+use Drupal\Core\Database\Query\ConditionInterface;
+
+/**
+ * Supportive trait to find synonyms.
+ */
+trait SynonymsFindTrait {
+
+  /**
+   * Supportive method to process $condition argument in synonymsFind().
+   *
+   * This method will swap SynonymsFindProviderInterface::COLUMN_* to real
+   * column names in $condition for you, so you do not have to worry about
+   * internal processing of $condition object.
+   *
+   * @param \Drupal\Core\Database\Query\ConditionInterface $condition
+   *   Condition to be processed
+   * @param string $synonym_column
+   *   Actual name of the column where synonyms are kept in text
+   * @param string $entity_id_column
+   *   Actual name of the column where entity_ids are kept
+   */
+  public function synonymsFindProcessCondition(ConditionInterface $condition, $synonym_column, $entity_id_column) {
+    $condition_array = &$condition->conditions();
+    foreach ($condition_array as &$v) {
+      if (is_array($v) && isset($v['field'])) {
+        if ($v['field'] instanceof ConditionInterface) {
+          // Recursively process this condition too.
+          $this->synonymsFindProcessCondition($v['field'], $synonym_column, $entity_id_column);
+        }
+        else {
+          $replace = [
+            SynonymsFindProviderInterface::COLUMN_SYNONYM_PLACEHOLDER => $synonym_column,
+            SynonymsFindProviderInterface::COLUMN_ENTITY_ID_PLACEHOLDER => $entity_id_column,
+          ];
+          $v['field'] = str_replace(array_keys($replace), array_values($replace), $v['field']);
+        }
+      }
+    }
+  }
+
+}

+ 35 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsFormatWordingProviderInterface.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsProviderInterface;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\synonyms\SynonymInterface;
+
+/**
+ * Interface to format a synonym into some kind of wording.
+ */
+interface SynonymsFormatWordingProviderInterface {
+
+  /**
+   * Format a synonym into wording as requested by configuration.
+   *
+   * @param string $synonym
+   *   Synonym that should be formatted
+   * @param ContentEntityInterface $entity
+   *   Entity to which this synonym belongs
+   * @param SynonymInterface $synonym_config
+   *   Synonym config entity in the context of which it all happens
+   *
+   * @return string
+   *   Formatted wording
+   */
+  public function synonymFormatWording($synonym, ContentEntityInterface $entity, SynonymInterface $synonym_config);
+
+  /**
+   * @return array
+   *   Array of supported tokens in wording. Keys are the tokens whereas
+   *   corresponding values are explanations about what each token means
+   */
+  public function formatWordingAvailableTokens();
+
+}

+ 51 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsFormatWordingTrait.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsProviderInterface;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\synonyms\SynonymInterface;
+
+/**
+ * Trait to format wording of a synonym.
+ */
+trait SynonymsFormatWordingTrait {
+
+  /**
+   * Format a synonym into wording as requested by configuration.
+   *
+   * @param string $synonym
+   *   Synonym that should be formatted
+   * @param ContentEntityInterface $entity
+   *   Entity to which this synonym belongs
+   * @param SynonymInterface $synonym_config
+   *   Synonym config entity in the context of which it all happens
+   *
+   * @return string
+   *   Formatted wording
+   */
+  public function synonymFormatWording($synonym, ContentEntityInterface $entity, SynonymInterface $synonym_config) {
+    // TODO: maybe we should use tokens replacement here? But then it would mean
+    // an extra dependency on the tokens module. Is it worth it? For now let's
+    // use stupid str_replace() and incorporate tokens only if user base really
+    // asks for it.
+    $map = [
+      '@synonym' => $synonym,
+      '@entity_label' => $entity->label(),
+    ];
+    return str_replace(array_keys($map), array_values($map), $synonym_config->getBehaviorConfiguration()['wording']);
+  }
+
+  /**
+   * @return array
+   *   Array of supported tokens in wording. Keys are the tokens whereas
+   *   corresponding values are explanations about what each token means
+   */
+  public function formatWordingAvailableTokens() {
+    return [
+      '@synonym' => $this->t('actual synonym value'),
+      '@entity_label' => $this->t('actual label of the entity this synonym belongs to'),
+    ];
+  }
+
+}
+

+ 45 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsGetProviderInterface.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsProviderInterface;
+
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\synonyms\SynonymsBehavior\SynonymsBehaviorInterface;
+
+/**
+ * Interface to extract (get) synonyms from an entity.
+ */
+interface SynonymsGetProviderInterface extends SynonymsProviderInterface {
+
+  /**
+   * Fetch synonyms from an entity.
+   *
+   * @param ContentEntityInterface $entity
+   *   Entity whose synonyms should be fetched
+   * @param array $behavior_configuration
+   *   Configuration of the synonyms behavior that this provider should obey to
+   *
+   * @return string[]
+   *   Array of extracted synonyms
+   */
+  public function getSynonyms(ContentEntityInterface $entity, array $behavior_configuration = []);
+
+  /**
+   * Fetch synonyms from multiple entities at once.
+   *
+   * @param ContentEntityInterface[] $entities
+   *   Array of entities whose synonyms should be fetched. The array will be
+   *   keyed by entity ID and all provided entities will be of the same entity
+   *   type and bundle
+   * @param array $behavior_configuration
+   *   Configuration of the synonyms behavior that this provider should obey to
+   *
+   * @return array
+   *   Array of extracted synonyms. It must be keyed by entity ID and each sub
+   *   array should represent a list of synonyms that were extracted from the
+   *   corresponding entity
+   */
+  public function getSynonymsMultiple(array $entities, array $behavior_configuration = []);
+
+}

+ 50 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsGetTrait.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsProviderInterface;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+
+/**
+ * Trait to extract synonyms from an entity.
+ */
+trait SynonymsGetTrait {
+
+  /**
+   * Fetch synonyms from multiple entities at once.
+   *
+   * @param ContentEntityInterface[] $entities
+   *   Array of entities whose synonyms should be fetched. They array will be
+   *   keyed by entity ID and all provided entities will be of the same entity
+   *   type and bundle
+   * @param array $behavior_configuration
+   *   Configuration of the synonyms behavior that this provider should obey to
+   *
+   * @return array
+   *   Array of extracted synonyms. It must be keyed by entity ID and each sub
+   *   array should represent a list of synonyms that were extracted from the
+   *   corresponding entity
+   */
+  public function getSynonymsMultiple(array $entities, array $behavior_configuration = []) {
+    $synonyms = [];
+
+    foreach ($entities as $entity_id => $entity) {
+      $synonyms[$entity_id] = $this->getSynonyms($entity, $behavior_configuration);
+    }
+
+    return $synonyms;
+  }
+
+  /**
+   * Fetch synonyms from an entity.
+   *
+   * @param ContentEntityInterface $entity
+   *   Entity whose synonyms should be fetched
+   * @param array $behavior_configuration
+   *   Configuration of the synonyms behavior that this provider should obey to
+   *
+   * @return string[]
+   *   Array of extracted synonyms
+   */
+  abstract public function getSynonyms(ContentEntityInterface $entity, array $behavior_configuration = []);
+
+}

+ 27 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderInterface/SynonymsProviderInterface.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsProviderInterface;
+
+use Drupal\synonyms\SynonymsService\Behavior\SynonymsBehaviorInterface;
+
+/**
+ * Most generic synonyms provider interface. All providers must implement it.
+ */
+interface SynonymsProviderInterface {
+
+  /**
+   * Fetch behavior service which corresponds to this provider.
+   *
+   * @return string
+   *   Name of synonyms behavior service which corresponds to this provider
+   */
+  public function getBehaviorService();
+
+  /**
+   * Fetch behavior service instance which corresponds to this provider.
+   *
+   * @return SynonymsBehaviorInterface
+   */
+  public function getBehaviorServiceInstance();
+
+}

+ 31 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsProviderPluginManager.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace Drupal\synonyms;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Plugin\DefaultPluginManager;
+use Drupal\synonyms\Annotation\SynonymsProvider;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsProviderInterface;
+
+/**
+ * Plugin manager for Synonyms provider plugin type.
+ */
+class SynonymsProviderPluginManager extends DefaultPluginManager {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
+    parent::__construct(
+      'Plugin/Synonyms/Provider',
+      $namespaces,
+      $module_handler,
+      SynonymsProviderInterface::class,
+      SynonymsProvider::class
+    );
+    $this->alterInfo('synonyms_provider_info');
+    $this->setCacheBackend($cache_backend, 'synonyms_provider_info_plugins');
+  }
+
+}

+ 250 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/Behavior/AutocompleteService.php

@@ -0,0 +1,250 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsService\Behavior;
+
+use Drupal\Component\Utility\Html;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
+use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\synonyms\SynonymInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFormatWordingProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetProviderInterface;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+
+/**
+ * Synonyms behavior service for autocomplete.
+ */
+class AutocompleteService implements SynonymsBehaviorConfigurableInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * @var KeyValueStoreInterface
+   */
+  protected $keyValue;
+
+  /**
+   * The entity reference selection handler plugin manager.
+   *
+   * @var SelectionPluginManagerInterface
+   */
+  protected $selectionManager;
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * @var Connection
+   */
+  protected $database;
+
+  /**
+   * @var RendererInterface
+   */
+  protected $renderer;
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  public function __construct(KeyValueFactoryInterface $key_value, SelectionPluginManagerInterface $selection_plugin_manager, BehaviorService $behavior_service, Connection $database, EntityTypeManagerInterface $entity_type_manager, RendererInterface $renderer) {
+    $this->keyValue = $key_value->get('synonyms_entity_autocomplete');
+    $this->selectionManager = $selection_plugin_manager;
+    $this->behaviorService = $behavior_service;
+    $this->database = $database;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->renderer = $renderer;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state, array $configuration, SynonymInterface $synonym_config) {
+    $replacements = [
+      '#theme' => 'item_list',
+      '#list_type' => 'ul',
+      '#items' => [],
+    ];
+    foreach ($synonym_config->getProviderPluginInstance()->formatWordingAvailableTokens() as $token => $token_info) {
+      $replacements['#items'][] = Html::escape($token) . ': ' . $token_info;
+    }
+
+    $replacements = $this->renderer->renderRoot($replacements);
+
+    $form['wording'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Wording for autocomplete suggestion'),
+      '#default_value' => $configuration['wording'],
+      '#description' => $this->t('Specify the wording with which the autocomplete suggestion should be presented. Available replacement tokens are: @replacements', [
+        '@replacements' => $replacements,
+      ]),
+      '#required' => TRUE,
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateConfigurationForm(array &$form, FormStateInterface $form_state, SynonymInterface $synonym_config) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state, SynonymInterface $synonym_config) {
+    return [
+      'wording' => $form_state->getValue('wording'),
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTitle() {
+    return $this->t('Autocomplete');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRequiredInterfaces() {
+    return [
+      SynonymsGetProviderInterface::class,
+      SynonymsFindProviderInterface::class,
+      SynonymsFormatWordingProviderInterface::class,
+    ];
+  }
+
+  /**
+   * Execute synonym-friendly lookup of entities by a given keyword.
+   *
+   * @param string $keyword
+   *   Keyword to search for
+   * @param string $key_value_key
+   *   Key under which additional settings about the lookup are stored in
+   *   key-value storage
+   *
+   * @return array
+   *   Array of looked up suggestions. Each array will have the following
+   *   structure:
+   *   - entity_id: (int) ID of the entity which this entry represents
+   *   - entity_label: (string) Label of the entity which this entry represents
+   *   - wording: (string) Wording with which this entry should be shown to the
+   *     end user on the UI
+   */
+  public function autocompleteLookup($keyword, $key_value_key) {
+    $suggestions = [];
+
+    if ($this->keyValue->has($key_value_key)) {
+      $settings = $this->keyValue->get($key_value_key);
+
+      $suggested_entity_ids = [];
+
+      $target_bundles = $settings['target_bundles'];
+      $handler_settings = [];
+      if (!empty($target_bundles)) {
+        $handler_settings['target_bundles'] = $target_bundles;
+      }
+      elseif (!$this->entityTypeManager->getDefinition($settings['target_type'])->hasKey('bundle')) {
+        $target_bundles = [$settings['target_type']];
+      }
+
+      $options = [
+        'target_type' => $settings['target_type'],
+        'handler' => 'default',
+        'handler_settings' => $handler_settings,
+      ];
+      $handler = $this->selectionManager->getInstance($options);
+
+      foreach ($handler->getReferenceableEntities($keyword, $settings['match'], $settings['suggestion_size']) as $suggested_entities) {
+        foreach ($suggested_entities as $entity_id => $entity_label) {
+          $suggestions[] = [
+            'entity_id' => $entity_id,
+            'entity_label' => $entity_label,
+            'wording' => $entity_label,
+          ];
+          if ($settings['suggest_only_unique']) {
+            $suggested_entity_ids[] = $entity_id;
+          }
+        }
+      }
+
+      if (count($suggestions) < $settings['suggestion_size']) {
+        foreach ($this->behaviorService->getSynonymConfigEntities('synonyms.behavior.autocomplete', $settings['target_type'], $target_bundles) as $behavior_service) {
+          $plugin_instance = $behavior_service->getProviderPluginInstance();
+
+          $condition = new Condition('AND');
+          switch ($settings['match']) {
+            case 'CONTAINS':
+              $condition->condition(SynonymsFindProviderInterface::COLUMN_SYNONYM_PLACEHOLDER, '%' . $this->database->escapeLike($keyword) . '%', 'LIKE');
+              break;
+
+            case 'STARTS_WITH':
+              $condition->condition(SynonymsFindProviderInterface::COLUMN_SYNONYM_PLACEHOLDER, $this->database->escapeLike($keyword) . '%', 'LIKE');
+              break;
+          }
+
+          if (!empty($suggested_entity_ids)) {
+            $condition->condition(SynonymsFindProviderInterface::COLUMN_ENTITY_ID_PLACEHOLDER, $suggested_entity_ids, 'NOT IN');
+          }
+
+
+          foreach ($plugin_instance->synonymsFind($condition) as $row) {
+            if (!in_array($row->entity_id, $suggested_entity_ids)) {
+              $suggestions[] = [
+                'entity_id' => $row->entity_id,
+                'entity_label' => NULL,
+                'synonym' => $row->synonym,
+                'synonym_config_entity' => $behavior_service,
+                'wording' => NULL,
+              ];
+            }
+
+            if ($settings['suggest_only_unique']) {
+              $suggested_entity_ids[] = $row->entity_id;
+            }
+
+            if (count($suggestions) == $settings['suggestion_size']) {
+              break(2);
+            }
+          }
+        }
+      }
+
+      $ids = [];
+      foreach ($suggestions as $suggestion) {
+        if (!$suggestion['entity_label']) {
+          $ids[] = $suggestion['entity_id'];
+        }
+      }
+      $ids = array_unique($ids);
+
+      if (!empty($ids)) {
+        $entities = $this->entityTypeManager->getStorage($settings['target_type'])
+          ->loadMultiple($ids);
+
+        foreach ($suggestions as $k => $suggestion) {
+          if (!$suggestion['entity_label']) {
+            $suggestions[$k]['entity_label'] = $entities[$suggestion['entity_id']]->label();
+            $suggestions[$k]['wording'] = $suggestion['synonym_config_entity']->getProviderPluginInstance()->synonymFormatWording($suggestion['synonym'], $entities[$suggestion['entity_id']], $suggestion['synonym_config_entity']);
+          }
+        }
+      }
+    }
+
+    return $suggestions;
+  }
+
+}

+ 157 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/Behavior/SelectService.php

@@ -0,0 +1,157 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsService\Behavior;
+
+use Drupal\Component\Utility\Html;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\synonyms\SynonymInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFormatWordingProviderInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetProviderInterface;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+
+/**
+ * Synonyms behavior service for select widget.
+ */
+class SelectService implements SynonymsBehaviorConfigurableInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * @var RendererInterface
+   */
+  protected $renderer;
+
+  /**
+   * SelectService constructor.
+   */
+  public function __construct(BehaviorService $behavior_service, RendererInterface $renderer) {
+    $this->behaviorService = $behavior_service;
+    $this->renderer = $renderer;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state, array $configuration, SynonymInterface $synonym_config) {
+    $replacements = [
+      '#theme' => 'item_list',
+      '#list_type' => 'ul',
+      '#items' => [],
+    ];
+    foreach ($synonym_config->getProviderPluginInstance()->formatWordingAvailableTokens() as $token => $token_info) {
+      $replacements['#items'][] = Html::escape($token) . ': ' . $token_info;
+    }
+
+    $replacements = $this->renderer->renderRoot($replacements);
+
+    $form['wording'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Wording for select entry'),
+      '#default_value' => $configuration['wording'],
+      '#description' => $this->t('Specify the wording with which the select entry should be presented. Available replacement tokens are: @replacements', [
+        '@replacements' => $replacements,
+      ]),
+      '#required' => TRUE,
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateConfigurationForm(array &$form, FormStateInterface $form_state, SynonymInterface $synonym_config) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state, SynonymInterface $synonym_config) {
+    return [
+      'wording' => $form_state->getValue('wording'),
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTitle() {
+    return $this->t('Select');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRequiredInterfaces() {
+    return [
+      SynonymsGetProviderInterface::class,
+      SynonymsFormatWordingProviderInterface::class,
+    ];
+  }
+
+  /**
+   * Extract a list of synonyms from an entity.
+   *
+   * @param ContentEntityInterface $entity
+   *   Entity from which to extract the synonyms
+   *
+   * @return array
+   *   Array of synonyms. Each sub array will have the following structure:
+   *   - synonym: (string) Synonym itself
+   *   - wording: (string) Formatted wording with which this synonym should be
+   *     presented to the end user
+   */
+  public function getSynonyms(ContentEntityInterface $entity) {
+    $synonyms = $this->getSynonymsMultiple([$entity->id() => $entity]);
+    return $synonyms[$entity->id()];
+  }
+
+  /**
+   * Extract a list of synonyms from multiple entities.
+   *
+   * @param ContentEntityInterface[] $entities
+   *   Array of entities from which to extract the synonyms. It should be keyed
+   *   by entity ID and may only contain entities of the same type and bundle
+   *
+   * @return array
+   *   Array of synonyms. The returned array will be keyed by entity ID and the
+   *   inner array will have the following structure:
+   *   - synonym: (string) Synonym itself
+   *   - wording: (string) Formatted wording with which this synonym should be
+   *     presented to the end user
+   */
+  public function getSynonymsMultiple(array $entities) {
+    if (empty($entities)) {
+      return [];
+    }
+
+    $synonym_configs = $this->behaviorService->getSynonymConfigEntities('synonyms.behavior.select', reset($entities)->getEntityTypeId(), reset($entities)->bundle());
+
+    $synonyms = [];
+    foreach ($entities as $entity) {
+      $synonyms[$entity->id()] = [];
+    }
+
+    foreach ($synonym_configs as $synonym_config) {
+      foreach ($synonym_config->getProviderPluginInstance()->getSynonymsMultiple($entities, $synonym_config->getBehaviorConfiguration()) as $entity_id => $entity_synonyms) {
+        foreach ($entity_synonyms as $entity_synonym) {
+          $synonyms[$entity_id][] = [
+            'synonym' => $entity_synonym,
+            'wording' => $synonym_config->getProviderPluginInstance()->synonymFormatWording($entity_synonym, $entities[$entity_id], $synonym_config),
+          ];
+        }
+      }
+    }
+
+    return $synonyms;
+  }
+
+}

+ 65 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/Behavior/SynonymsBehaviorConfigurableInterface.php

@@ -0,0 +1,65 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsService\Behavior;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\synonyms\SynonymInterface;
+
+/**
+ * Interface of a configurable synonyms behavior.
+ */
+interface SynonymsBehaviorConfigurableInterface extends SynonymsBehaviorInterface {
+
+  /**
+   * Build configuration form.
+   *
+   * @param array $form
+   *   Form into which your configuration form will be embedded. You are
+   *   supposed to extend this array with additional configuration form elements
+   *   that your behavior needs
+   * @param FormStateInterface $form_state
+   *   Form state object that corresponds to this form
+   * @param array $configuration
+   *   Array of existing configuration for your behavior. Normally you would use
+   *   it as a source of default values for your configuration form elements
+   * @param SynonymInterface $synonym_config
+   *   Synonym config entity in the context of which the form is being built
+   *
+   * @return array
+   *   Extended $form that includes the form elements required for configuration
+   *   of your behavior
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state, array $configuration, SynonymInterface $synonym_config);
+
+  /**
+   * Validate submitted values into your configuration form.
+   *
+   * @param array $form
+   *   Your configuration form as it was built in
+   *   static::buildConfigurationForm()
+   * @param FormStateInterface $form_state
+   *   Form state that corresponds to this form. You should rise form validation
+   *   errors on this form state, should you discover any in user input
+   * @param SynonymInterface $synonym_config
+   *   Synonym config entity in the context of which the form is being built
+   */
+  public function validateConfigurationForm(array &$form, FormStateInterface $form_state, SynonymInterface $synonym_config);
+
+  /**
+   * Process submitted values and generate new configuration.
+   *
+   * @param array $form
+   *   Your configuration form as it was built in
+   *   static::buildConfigurationForm()
+   * @param FormStateInterface $form_state
+   *   Form state that corresponds to this form
+   * @param SynonymInterface $synonym_config
+   *   Synonym config entity in the context of which the form is being built
+   *
+   * @return array
+   *   Array of new behavior configuration that corresponds to the submitted
+   *   values in the form
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state, SynonymInterface $synonym_config);
+
+}

+ 29 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/Behavior/SynonymsBehaviorInterface.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsService\Behavior;
+
+/**
+ * Interface of a synonyms behavior. All behaviors must implement it.
+ */
+interface SynonymsBehaviorInterface {
+
+  /**
+   * Get human readable title of this behavior.
+   *
+   * @return string
+   */
+  public function getTitle();
+
+  /**
+   * Get a list of interfaces required from synonyms provider plugins.
+   *
+   * Get a list of PHP interfaces a synonyms provider plugin must implement in
+   * order to support this behavior.
+   *
+   * @return array
+   *   Array of PHP interfaces a synonyms provider plugin must implement in
+   *   order to support this behavior
+   */
+  public function getRequiredInterfaces();
+
+}

+ 143 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/BehaviorService.php

@@ -0,0 +1,143 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsService;
+
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\synonyms\Entity\Synonym;
+use Drupal\synonyms\SynonymsService\Behavior\SynonymsBehaviorInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Collect all known synonyms behavior services.
+ *
+ * Collect all known synonyms behavior services during dependency injection
+ * container compilation.
+ */
+class BehaviorService implements ContainerInjectionInterface {
+
+  /**
+   * @var array
+   */
+  protected $behaviorServices;
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
+    $this->behaviorServices = [];
+
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * Add a new discovered behavior service.
+   *
+   * @param SynonymsBehaviorInterface $behavior_service
+   *   Behavior service object that was discovered and should be added into the
+   *   list of known ones
+   * @param string $id
+   *   Service ID that corresponds to this behavior service
+   */
+  public function addBehaviorService(SynonymsBehaviorInterface $behavior_service, $id) {
+    if (!isset($this->behaviorServices[$id])) {
+      $this->behaviorServices[$id] = [
+        'service' => $behavior_service,
+        'required_interfaces' => [],
+      ];
+    }
+    $this->behaviorServices[$id]['required_interfaces'] = $behavior_service->getRequiredInterfaces();
+  }
+
+  /**
+   * Array of known synonyms behavior service.
+   *
+   * @return array
+   */
+  public function getBehaviorServices() {
+    return $this->behaviorServices;
+  }
+
+  /**
+   * Get a synonyms behavior service.
+   *
+   * @param string $behavior_service_id
+   *   ID of the service to retrieve
+   *
+   * @return array
+   *   Array of information about the behavior service. The array will have the
+   *   following structure:
+   *   - service: (SynonymsBehaviorInterface) Initiated behavior service
+   *   - required_interfaces: (array) Array of PHP interfaces it requires
+   */
+  public function getBehaviorService($behavior_service_id) {
+    return isset($this->behaviorServices[$behavior_service_id]) ? $this->behaviorServices[$behavior_service_id] : NULL;
+  }
+
+  /**
+   * Get a list of behavior services that require a given interface.
+   *
+   * @param string $interface
+   *   Full name of the interface
+   *
+   * @return array
+   *   The return structure of this method is identical of the return structure
+   *   of static::getBehaviorServices()
+   */
+  public function getBehaviorServicesWithInterface($interface) {
+    $return = [];
+
+    foreach ($this->getBehaviorServices() as $service_id => $service) {
+      if (in_array($interface, $service['required_interfaces'])) {
+        $return[$service_id] = $service;
+      }
+    }
+
+    return $return;
+  }
+
+  /**
+   * Get a list of enabled synonym providers for a requested synonyms behavior.
+   *
+   * @param string $synonyms_behavior
+   *   ID of the synonyms behavior services whose enabled providers should be
+   *   returned
+   * @param string $entity_type
+   *   Entity type for which to conduct the search
+   * @param string|array $bundle
+   *   Single bundle or an array of them for which to conduct the search. If
+   *   null is given, then no restrictions are applied on bundle level
+   *
+   * @return Synonym[]
+   */
+  public function getSynonymConfigEntities($synonyms_behavior, $entity_type, $bundle) {
+    $entities = [];
+
+    if (is_scalar($bundle) && !is_null($bundle)) {
+      $bundle = [$bundle];
+    }
+
+    foreach ($this->entityTypeManager->getStorage('synonym')->loadMultiple() as $entity) {
+      $provider_instance = $entity->getProviderPluginInstance();
+      $provider_definition = $provider_instance->getPluginDefinition();
+      if ($provider_definition['synonyms_behavior_service'] == $synonyms_behavior && $provider_definition['controlled_entity_type'] == $entity_type && (!is_array($bundle) || in_array($provider_definition['controlled_bundle'], $bundle))) {
+        $entities[] = $entity;
+      }
+    }
+
+    return $entities;
+  }
+
+}

+ 79 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/EntityGet.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsService;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindProviderInterface;
+
+/**
+ * Service to look up an entity by its name or synonym.
+ */
+class EntityGet {
+
+  /**
+   * @var SynonymsFind
+   */
+  protected $synonymsFindService;
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var QueryFactory
+   */
+  protected $queryFactory;
+
+  public function __construct(SynonymsFind $synonyms_find_service, EntityTypeManagerInterface $entity_type_manager, QueryFactory $query_factory) {
+    $this->synonymsFindService = $synonyms_find_service;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->queryFactory = $query_factory;
+  }
+
+  /**
+   * Try finding an entity by its name or synonym.
+   *
+   * @param EntityTypeInterface $entity_type
+   *   What entity type is being searched
+   * @param string $name
+   *   The look up keyword (the supposed name or synonym)
+   * @param string $bundle
+   *   Optionally limit the search within a specific bundle name of the provided
+   *   entity type
+   *
+   * @return int
+   *   ID of the looked up entity. If such entity was not found, then 0 is
+   *   returned
+   */
+  public function entityGetBySynonym(EntityTypeInterface $entity_type, $name, $bundle = NULL) {
+    if ($entity_type->id() == 'user' || $entity_type->hasKey('label')) {
+      $label_column = $entity_type->id() == 'user' ? 'name' : $entity_type->getKey('label');
+      $query = $this->queryFactory->get($entity_type->id());
+      $query->condition($label_column, $name);
+      if ($entity_type->hasKey('bundle') && $bundle) {
+        $query->condition($entity_type->getKey('bundle'), $bundle);
+      }
+
+      $result = $query->execute();
+      $result = reset($result);
+      if ($result) {
+        return $result;
+      }
+    }
+
+    $condition = new Condition('AND');
+    $condition->condition(SynonymsFindProviderInterface::COLUMN_SYNONYM_PLACEHOLDER, $name);
+
+    $synonyms_found = $this->synonymsFindService->synonymsFind($condition, $entity_type, $bundle, '*');
+    if (isset($synonyms_found[0]->entity_id)) {
+      return $synonyms_found[0]->entity_id;
+    }
+
+    return 0;
+  }
+
+}

+ 44 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/FieldTypeToSynonyms.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsService;
+
+use Drupal\Core\Extension\ModuleHandlerInterface;
+
+/**
+ * Service to map known field types to how synonyms are encoded in them.
+ */
+class FieldTypeToSynonyms {
+
+  /**
+   * @var ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * FieldTypeToSynonyms constructor.
+   */
+  public function __construct(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * Map field types to the properties within them where synonyms are stored.
+   *
+   * @return array
+   *   Map where keys are simple field types and values are the properties where
+   *   the corresponding field type keeps the synonyms
+   */
+  public function getSimpleFieldTypeToPropertyMap() {
+    $map = [
+      'integer' => 'value',
+      'float' => 'value',
+      'decimal' => 'value',
+      'string' => 'value',
+      'email' => 'value',
+      'telephone' => 'value',
+    ];
+    $this->moduleHandler->alter('synonyms_field_type_to_synonym', $map);
+    return $map;
+  }
+
+}

+ 84 - 0
sites/all/modules/contrib/taxonomy/synonyms/src/SynonymsService/SynonymsFind.php

@@ -0,0 +1,84 @@
+<?php
+
+namespace Drupal\synonyms\SynonymsService;
+
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsFindProviderInterface;
+
+/**
+ * Service that allows to look up entities by their synonyms.
+ */
+class SynonymsFind {
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * @var EntityTypeBundleInfoInterface
+   */
+  protected $entityTypeBundleInfo;
+
+  /**
+   * SynonymsFind constructor.
+   */
+  public function __construct(BehaviorService $behavior_service, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
+    $this->behaviorService = $behavior_service;
+    $this->entityTypeBundleInfo = $entity_type_bundle_info;
+  }
+
+  /**
+   * Lookup entity IDs by the $condition.
+   *
+   * @param Condition $condition
+   *   Condition which defines what to search for
+   * @param EntityTypeInterface $entity_type
+   *   Entity type within which to search
+   * @param string|array $bundle
+   *   Either single bundle string or array of such within which to search. NULL
+   *   stands for no filtering by bundle, i.e. searching among all bundles
+   * @param string|array $service_id
+   *   Either a single behavior service ID or an array of them within which to
+   *   execute the lookup. You may also use the wildcard * to search among all
+   *   supported behaviors
+   *
+   * @return array
+   *   Array of looked up synonyms/entities. Each element in this array will be
+   *   an object with the following structure:
+   *   - synonym: (string) synonym that was looked up
+   *   - entity_id: (int) ID of the entity which this synonym belongs to
+   */
+  public function synonymsFind(Condition $condition, EntityTypeInterface $entity_type, $bundle = NULL, $service_id = 'synonyms.behavior.autocomplete') {
+    if (!$entity_type->getKey('bundle')) {
+      $bundle = $entity_type->id();
+    }
+
+    $lookup = [];
+
+    if ($service_id == '*') {
+      $service_id = array_keys($this->behaviorService->getBehaviorServicesWithInterface(SynonymsFindProviderInterface::class));
+    }
+
+    if (!is_array($service_id)) {
+      $service_id = [$service_id];
+    }
+
+    if (is_null($bundle)) {
+      $bundle = array_keys($this->entityTypeBundleInfo->getBundleInfo($entity_type->id()));
+    }
+
+    foreach ($service_id as $service_id_value) {
+      foreach ($this->behaviorService->getSynonymConfigEntities($service_id_value, $entity_type->id(), $bundle) as $synonym_config) {
+        foreach ($synonym_config->getProviderPluginInstance()->synonymsFind(clone $condition) as $synonym) {
+          $lookup[] = $synonym;
+        }
+      }
+    }
+
+    return $lookup;
+  }
+
+}

+ 30 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms.api.php

@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Documentation for Synonyms module.
+ */
+
+/**
+ * Hook to alter known simple field types that contain potential synonyms data.
+ *
+ * The simple field types (those defined by $map) are used for synonyms
+ * providing through Drupal\synonyms\Plugin\Synonyms\Provider\Field or
+ * Drupal\synonyms\Plugin\Synonyms\Provider\BaseField plugins depending whether
+ * it is an attached field or base one correspondingly. Both synonyms providers
+ * plugin simply take a specific column/value from the field and return it as a
+ * synonym.
+ *
+ * @param array $map
+ *   Array of known simple field types eligible for synonyms providing through
+ *   the 2 plugins. Keys are field types whereas corresponding values are field
+ *   columns that contain synonyms. You are encouraged to alter $map in order to
+ *   add/remove known field types per your business needs
+ */
+function hook_synonyms_field_type_to_synonym_alter(&$map) {
+  // Let's assume our module provides some additional field type and we want
+  // that field type to be eligible for synonyms providing through the 2 simple
+  // plugins. And let's suppose the synonyms are actually stored in 'value'
+  // column within our custom field type.
+  $map['the_field_type_my_module_provides'] = 'value';
+}

+ 14 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms.info.yml

@@ -0,0 +1,14 @@
+name: Synonyms
+description: Provides synonyms feature for content entities.
+package: Synonyms
+type: module
+# core: 8.x
+configure: entity.synonym.overview
+dependencies:
+  - system (>=8.2)
+
+# Information added by Drupal.org packaging script on 2018-03-11
+version: '8.x-1.0-alpha1+4-dev'
+core: '8.x'
+project: 'synonyms'
+datestamp: 1520765586

+ 5 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms.links.action.yml

@@ -0,0 +1,5 @@
+entity.synonym.entity_type.bundle.behavior.add_form:
+  route_name: 'entity.synonym.entity_type.bundle.behavior.add_form'
+  title: 'Add synonym configuration'
+  appears_on:
+    - entity.synonym.overview.entity_type.bundle.behavior

+ 5 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms.links.menu.yml

@@ -0,0 +1,5 @@
+synonyms.configure:
+  title: 'Synonyms'
+  route_name: entity.synonym.overview
+  description: 'Manage entity synonyms.'
+  parent: system.admin_structure

+ 47 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms.module

@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Provide synonyms feature for content entities.
+ */
+
+/**
+ * Implements hook_entity_base_field_info().
+ */
+function synonyms_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
+  if ($entity_type instanceof \Drupal\Core\Entity\ContentEntityTypeInterface) {
+    $fields = [];
+
+    $fields['synonyms'] = \Drupal\Core\Field\BaseFieldDefinition::create('string')
+      ->setLabel(t('Entity synonyms'))
+      ->setDescription(t('A list of known entity synonyms.'))
+      ->setComputed(TRUE)
+      ->setClass('\Drupal\synonyms\Plugin\SynonymsFieldItemList');
+
+    return $fields;
+  }
+}
+
+/**
+ * Implements hook_views_data().
+ */
+function synonyms_views_data() {
+  $data = [];
+
+  foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type) {
+    if ($entity_type instanceof \Drupal\Core\Entity\ContentEntityTypeInterface && $entity_type->getBaseTable() && $entity_type->getKey('id')) {
+      $data[$entity_type->getBaseTable()]['synonyms'] = [
+        'title' => t('Synonyms of @entity_type', [
+          '@entity_type' => $entity_type->getLowercaseLabel(),
+        ]),
+        'filter' => [
+          'id' => 'synonyms_entity',
+          'real field' => $entity_type->getKey('id'),
+          'entity_type' => $entity_type->id(),
+        ],
+      ];
+    }
+  }
+
+  return $data;
+}

+ 7 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms.permissions.yml

@@ -0,0 +1,7 @@
+administer synonyms:
+  title: 'Administer synonyms'
+  description: 'Administer synonyms of entities.'
+
+access synonyms entity autocomplete:
+  title: 'Access synonyms entity autocomplete'
+  description: 'Access synonyms-friendly entity autocomplete'

+ 63 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms.routing.yml

@@ -0,0 +1,63 @@
+entity.synonym.overview:
+  path: '/admin/structure/synonyms'
+  defaults:
+    _controller: 'Drupal\synonyms\Controller\SynonymConfigController::overview'
+    _title: 'Synonyms'
+  requirements:
+    _permission: 'administer synonyms'
+
+entity.synonym.overview.entity_type.bundle.behavior:
+  path: '/admin/structure/synonyms/{synonyms_entity_type}/{bundle}/{synonyms_behavior_service}'
+  options:
+    parameters:
+      synonyms_entity_type:
+        type: synonyms_entity_type
+      synonyms_behavior_service:
+        type: synonyms_behavior_service
+  defaults:
+    _controller: 'Drupal\synonyms\Controller\SynonymConfigController::overviewEntityTypeBundle'
+    _title: 'Synonyms'
+    _title_callback: 'Drupal\synonyms\Controller\SynonymConfigController::overviewEntityTypeBundleTitle'
+  requirements:
+    _permission: 'administer synonyms'
+
+entity.synonym.entity_type.bundle.behavior.add_form:
+  path: '/admin/structure/synonyms/{synonyms_entity_type}/{bundle}/{synonyms_behavior_service}/add'
+  options:
+    parameters:
+      synonyms_entity_type:
+        type: synonyms_entity_type
+      synonyms_behavior_service:
+        type: synonyms_behavior_service
+  defaults:
+    _entity_form: 'synonym.add'
+    _title: 'Add synonym configuration'
+  requirements:
+    _permission: 'administer synonyms'
+
+entity.synonym.edit_form:
+  path: '/admin/structure/synonyms/{synonym}'
+  defaults:
+    _entity_form: 'synonym.edit'
+    _title: 'Edit synonym configuration'
+  requirements:
+    _permission: 'administer synonyms'
+
+entity.synonym.delete_form:
+  path: '/admin/structure/synonyms/{synonym}/delete'
+  defaults:
+    _entity_form: 'synonym.delete'
+    _title: 'Delete synonym configuration'
+  requirements:
+    _permission: 'administer synonyms'
+
+synonyms.entity_autocomplete:
+  path: '/synonyms/entity/autocomplete/{target_type}/{token}'
+  options:
+    parameters:
+      target_type:
+        type: synonyms_entity_type
+  defaults:
+    _controller: 'Drupal\synonyms\Controller\EntityAutocomplete::autocomplete'
+  requirements:
+    _permission: 'access synonyms entity autocomplete'

+ 46 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms.services.yml

@@ -0,0 +1,46 @@
+services:
+  plugin.manager.synonyms_provider:
+    class: Drupal\synonyms\SynonymsProviderPluginManager
+    parent: default_plugin_manager
+
+  synonyms.behaviors:
+    class: Drupal\synonyms\SynonymsService\BehaviorService
+    tags:
+      - { name: service_collector, tag: synonyms_behavior, call: addBehaviorService }
+    arguments: [ '@entity_type.manager' ]
+
+  synonyms.provider.field_type_to_synonyms:
+    class: Drupal\synonyms\SynonymsService\FieldTypeToSynonyms
+    arguments: [ '@module_handler' ]
+
+  synonyms.synonyms_find:
+    class: Drupal\synonyms\SynonymsService\SynonymsFind
+    arguments: [ '@synonyms.behaviors', '@entity_type.bundle.info' ]
+
+  synonyms.synonyms_entity_get:
+    class: Drupal\synonyms\SynonymsService\EntityGet
+    arguments: [ '@synonyms.synonyms_find', '@entity_type.manager', '@entity.query' ]
+
+  synonyms.behavior.autocomplete:
+    class: Drupal\synonyms\SynonymsService\Behavior\AutocompleteService
+    arguments: [ '@keyvalue', '@plugin.manager.entity_reference_selection', '@synonyms.behaviors', '@database', '@entity_type.manager', '@renderer' ]
+    tags:
+      - { name: synonyms_behavior }
+
+  synonyms.behavior.select:
+    class: Drupal\synonyms\SynonymsService\Behavior\SelectService
+    arguments: [ '@synonyms.behaviors', '@renderer' ]
+    tags:
+      - { name: synonyms_behavior }
+
+  synonyms.param_converter.entity_type:
+    class: Drupal\synonyms\ParamConverter\EntityTypeParamConverter
+    tags:
+      - { name: paramconverter }
+    arguments: [ '@entity_type.manager' ]
+
+  synonyms.param_converter.synonyms_behavior:
+    class: Drupal\synonyms\ParamConverter\SynonymsBehaviorServiceParamConverter
+    tags:
+      - { name: paramconverter }
+    arguments: [ '@synonyms.behaviors' ]

+ 194 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms_search/src/SynonymsService/Behavior/SearchService.php

@@ -0,0 +1,194 @@
+<?php
+
+namespace Drupal\synonyms_search\SynonymsService\Behavior;
+
+use Drupal\Component\Datetime\TimeInterface;
+use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\ContentEntityTypeInterface;
+use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\synonyms\Entity\Synonym;
+use Drupal\synonyms\SynonymsProviderInterface\SynonymsGetProviderInterface;
+use Drupal\synonyms\SynonymsService\Behavior\SynonymsBehaviorInterface;
+use Drupal\synonyms\SynonymsService\BehaviorService;
+
+/**
+ * Expose synonyms of referenced entities to core Search index.
+ */
+class SearchService implements SynonymsBehaviorInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * Behavior name this class represents.
+   *
+   * @var string
+   */
+  const behavior = 'synonyms.behavior.search';
+
+  /**
+   * @var EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * @var EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * @var BehaviorService
+   */
+  protected $behaviorService;
+
+  /**
+   * @var QueryFactory
+   */
+  protected $queryFactory;
+
+  /**
+   * @var Connection
+   */
+  protected $database;
+
+  /**
+   * @var TimeInterface
+   */
+  protected $time;
+
+  /**
+   * SearchService constructor.
+   */
+  public function __construct(EntityFieldManagerInterface $entity_field_manager, EntityTypeManagerInterface $entity_type_manager, BehaviorService $behavior_service, QueryFactory $query_factory, Connection $database, TimeInterface $time) {
+    $this->entityFieldManager = $entity_field_manager;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->behaviorService = $behavior_service;
+    $this->queryFactory = $query_factory;
+    $this->database = $database;
+    $this->time = $time;
+  }
+
+  /**
+   * Implementation of hook_entity_view().
+   */
+  public function entityView(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
+    if ($entity instanceof ContentEntityInterface && $view_mode == 'search_index') {
+      $synonyms = [];
+      $cacheable_metadata = new CacheableMetadata();
+
+      $entity_references = array_filter($this->entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()), function($item) {
+        if ($item->getType() == 'entity_reference') {
+          $target_entity_type = $this->entityTypeManager->getDefinition($item->getSetting('target_type'));
+          return $target_entity_type instanceof ContentEntityTypeInterface;
+        }
+        return FALSE;
+      });
+      foreach ($entity_references as $entity_reference) {
+        foreach ($entity->get($entity_reference->getName())->referencedEntities() as $target_entity) {
+          $synonyms = array_merge($synonyms, $this->getEntitySynonyms($target_entity));
+          $cacheable_metadata->addCacheableDependency($target_entity);
+
+          // Depend on the synonyms configs for this entity type + bundle.
+          $cacheable_metadata->addCacheTags([Synonym::cacheTagConstruct(self::behavior, $target_entity->getEntityTypeId(), $target_entity->bundle())]);
+        }
+      }
+
+      $build['synonyms_search'] = [
+        '#markup' => implode(', ', $synonyms),
+      ];
+      $cacheable_metadata->applyTo($build['synonyms_search']);
+    }
+  }
+
+  /**
+   * Mark all search index dependent on a given entity for reindexing.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+   *   Entity whose dependent search index should be marked for reindexing
+   */
+  public function entityMarkForReindex(ContentEntityInterface $entity) {
+    $this->entityMarkForReindexMultiple([$entity->id()], $entity->getEntityTypeId());
+  }
+
+  /**
+   * Mark all search index dependent on given entities for reindexing.
+   *
+   * @param array $entity_ids
+   *   Entity IDs whose dependent search index should be marked for reindexing
+   * @param string $entity_type
+   *   Entity type of the give entity IDs
+   */
+  public function entityMarkForReindexMultiple($entity_ids, $entity_type) {
+    if (empty($entity_ids)) {
+      return;
+    }
+
+    $map = $this->entityFieldManager->getFieldMapByFieldType('entity_reference');
+    foreach ($map as $host_entity_type => $fields) {
+      foreach ($fields as $field_name => $field_info) {
+        $field = FieldStorageConfig::loadByName($host_entity_type, $field_name);
+        if ($field && $field->getSetting('target_type') == $entity_type) {
+          $query = $this->queryFactory->get($host_entity_type, 'AND');
+          $query->condition($field_name, $entity_ids, 'IN');
+          $result = $query->execute();
+
+          // For the sake of performance we do a direct query on the
+          // {search_dataset} table instead of using search_mark_for_reindex()
+          // function.
+          // TODO: is there any smarter way to generate search type rather then
+          // adding suffix of '_search'?
+          if (!empty($result)) {
+            $this->database->update('search_dataset')
+              ->fields(['reindex' => $this->time->getRequestTime()])
+              ->condition('reindex', 0)
+              ->condition('type', $host_entity_type . '_search')
+              ->condition('sid', array_values($result), 'IN')
+              ->execute();
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTitle() {
+    return $this->t('Search');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRequiredInterfaces() {
+    return [
+      SynonymsGetProviderInterface::class,
+    ];
+  }
+
+  /**
+   * Retrieve a list of synonyms from a given entity.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+   *
+   * @return string[]
+   *   A list of synonyms of a given entity
+   */
+  protected function getEntitySynonyms(ContentEntityInterface $entity) {
+    $synonyms = [];
+
+    foreach ($this->behaviorService->getSynonymConfigEntities('synonyms.behavior.search', $entity->getEntityTypeId(), $entity->bundle()) as $synonym_config) {
+      $synonyms = array_merge($synonyms, $synonym_config->getProviderPluginInstance()->getSynonyms($entity));
+    }
+
+    return $synonyms;
+  }
+
+}

+ 14 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms_search/synonyms_search.info.yml

@@ -0,0 +1,14 @@
+name: Synonyms Search
+description: Integrates Synonyms with core Search module.
+package: Synonyms
+type: module
+# core: 8.x
+dependencies:
+  - synonyms
+  - search
+
+# Information added by Drupal.org packaging script on 2018-03-11
+version: '8.x-1.0-alpha1+4-dev'
+core: '8.x'
+project: 'synonyms'
+datestamp: 1520765586

+ 69 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms_search/synonyms_search.module

@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Integrates Synonyms with core Search module.
+ */
+
+/**
+ * Implements hook_entity_view().
+ */
+function synonyms_search_entity_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
+  \Drupal::service('synonyms.behavior.search')->entityView($build, $entity, $display, $view_mode);
+}
+
+/**
+ * Implements hook_entity_update().
+ */
+function synonyms_search_entity_update(Drupal\Core\Entity\EntityInterface $entity) {
+  if ($entity instanceof \Drupal\Core\Entity\ContentEntityInterface) {
+    \Drupal::service('synonyms.behavior.search')->entityMarkForReindex($entity);
+  }
+}
+
+/**
+ * Implements hook_entity_delete().
+ */
+function synonyms_search_entity_delete(Drupal\Core\Entity\EntityInterface $entity) {
+  if ($entity instanceof \Drupal\Core\Entity\ContentEntityInterface) {
+    \Drupal::service('synonyms.behavior.search')->entityMarkForReindex($entity);
+  }
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_insert().
+ */
+function synonyms_search_synonym_insert(Drupal\Core\Entity\EntityInterface $entity) {
+  synonyms_search_synonym_reindex($entity);
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_update().
+ */
+function synonyms_search_synonym_update(Drupal\Core\Entity\EntityInterface $entity) {
+  synonyms_search_synonym_reindex($entity);
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_delete().
+ */
+function synonyms_search_synonym_delete(Drupal\Core\Entity\EntityInterface $entity) {
+  synonyms_search_synonym_reindex($entity);
+}
+
+/**
+ * Mark all search index dependent on a given synonym config for reindexing.
+ *
+ * @param \Drupal\synonyms\SynonymInterface $synonym
+ *   Synonym config whose dependent search index should be marked for reindexing
+ */
+function synonyms_search_synonym_reindex(\Drupal\synonyms\SynonymInterface $synonym) {
+  if ($synonym->get('behavior') == 'synonyms.behavior.search') {
+    $entity_type = \Drupal::entityTypeManager()->getDefinition($synonym->getProviderPluginInstance()->getPluginDefinition()['controlled_entity_type']);
+    $bundle = $synonym->getProviderPluginInstance()->getPluginDefinition()['controlled_bundle'];
+    $query = \Drupal::entityQuery($entity_type->id());
+    $query->condition($entity_type->getKey('bundle'), $bundle);
+    $result = $query->execute();
+    \Drupal::service('synonyms.behavior.search')->entityMarkForReindexMultiple(array_values($result), $entity_type->id());
+  }
+}

+ 6 - 0
sites/all/modules/contrib/taxonomy/synonyms/synonyms_search/synonyms_search.services.yml

@@ -0,0 +1,6 @@
+services:
+  synonyms.behavior.search:
+    class: Drupal\synonyms_search\SynonymsService\Behavior\SearchService
+    arguments: [ '@entity_field.manager', '@entity_type.manager', '@synonyms.behaviors', '@entity.query', '@database', '@datetime.time' ]
+    tags:
+      - { name: synonyms_behavior }

+ 20 - 0
sites/default/config/sync/core.base_field_override.node.autre_son.menu_link.yml

@@ -0,0 +1,20 @@
+uuid: 4864fda4-27e7-4375-932f-d5493d37236e
+langcode: fr
+status: true
+dependencies:
+  config:
+    - node.type.autre_son
+id: node.autre_son.menu_link
+field_name: menu_link
+entity_type: node
+bundle: autre_son
+label: 'Lien du menu'
+description: 'Computed menu link for the node (only available during node saving).'
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: default
+  handler_settings: {  }
+field_type: entity_reference

+ 20 - 0
sites/default/config/sync/core.base_field_override.node.fil.menu_link.yml

@@ -0,0 +1,20 @@
+uuid: a2747f17-57c4-4f4c-8dfe-9f4fea51a414
+langcode: fr
+status: true
+dependencies:
+  config:
+    - node.type.fil
+id: node.fil.menu_link
+field_name: menu_link
+entity_type: node
+bundle: fil
+label: 'Lien du menu'
+description: 'Computed menu link for the node (only available during node saving).'
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: default
+  handler_settings: {  }
+field_type: entity_reference

+ 1 - 1
sites/default/config/sync/core.base_field_override.taxonomy_term.genres.name.yml

@@ -11,7 +11,7 @@ bundle: genres
 label: Name
 description: ''
 required: true
-translatable: false
+translatable: true
 default_value: {  }
 default_value_callback: ''
 settings: {  }

+ 1 - 1
sites/default/config/sync/core.base_field_override.taxonomy_term.langues.name.yml

@@ -11,7 +11,7 @@ bundle: langues
 label: Name
 description: ''
 required: true
-translatable: false
+translatable: true
 default_value: {  }
 default_value_callback: ''
 settings: {  }

+ 19 - 0
sites/default/config/sync/core.base_field_override.user.user.path.yml

@@ -0,0 +1,19 @@
+uuid: 7a74202f-9c18-4376-b97e-cde0e86c42fe
+langcode: fr
+status: true
+dependencies:
+  module:
+    - path
+    - user
+id: user.user.path
+field_name: path
+entity_type: user
+bundle: user
+label: 'Alias d''URL'
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings: {  }
+field_type: path

+ 10 - 9
sites/default/config/sync/core.entity_form_display.node.enregistrement.default.yml

@@ -19,6 +19,7 @@ dependencies:
   module:
     - field_group
     - file
+    - synonyms
     - text
     - workflow
 third_party_settings:
@@ -102,8 +103,8 @@ third_party_settings:
     group_taxonomy:
       children:
         - field_entrees
-        - field_genres
         - field_langues
+        - field_genres
       parent_name: group_onglets
       weight: 27
       format_type: tab
@@ -144,25 +145,25 @@ content:
       size: 60
       placeholder: ''
     third_party_settings: {  }
-    type: entity_reference_autocomplete
+    type: entity_reference_autocomplete_tags
     region: content
   field_genres:
-    weight: 12
+    weight: 13
     settings:
-      match_operator: CONTAINS
-      size: 60
-      placeholder: ''
+      suggestion_size: 10
+      suggest_only_unique: false
+      match: CONTAINS
     third_party_settings: {  }
-    type: entity_reference_autocomplete
+    type: synonyms_autocomplete
     region: content
   field_langues:
-    weight: 13
+    weight: 12
     settings:
       match_operator: CONTAINS
       size: 60
       placeholder: ''
     third_party_settings: {  }
-    type: entity_reference_autocomplete
+    type: entity_reference_autocomplete_tags
     region: content
   field_nbr_locuteurs:
     weight: 16

+ 38 - 0
sites/default/config/sync/core.entity_form_display.taxonomy_term.genres.default.yml

@@ -0,0 +1,38 @@
+uuid: dfdb11b9-c837-4adc-bd18-ad95a30d05f3
+langcode: fr
+status: true
+dependencies:
+  config:
+    - field.field.taxonomy_term.genres.field_synonyms
+    - taxonomy.vocabulary.genres
+id: taxonomy_term.genres.default
+targetEntityType: taxonomy_term
+bundle: genres
+mode: default
+content:
+  field_synonyms:
+    weight: 2
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+    type: string_textfield
+    region: content
+  langcode:
+    type: language_select
+    weight: 1
+    region: content
+    settings:
+      include_locked: true
+    third_party_settings: {  }
+  name:
+    type: string_textfield
+    weight: 0
+    region: content
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+hidden:
+  description: true
+  path: true

+ 29 - 0
sites/default/config/sync/core.entity_form_display.taxonomy_term.langues.default.yml

@@ -0,0 +1,29 @@
+uuid: ad860d07-87dc-4803-abc7-41e1724a77e4
+langcode: fr
+status: true
+dependencies:
+  config:
+    - taxonomy.vocabulary.langues
+id: taxonomy_term.langues.default
+targetEntityType: taxonomy_term
+bundle: langues
+mode: default
+content:
+  langcode:
+    type: language_select
+    weight: 1
+    region: content
+    settings:
+      include_locked: true
+    third_party_settings: {  }
+  name:
+    type: string_textfield
+    weight: 0
+    region: content
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+hidden:
+  description: true
+  path: true

+ 31 - 0
sites/default/config/sync/core.entity_view_display.taxonomy_term.genres.default.yml

@@ -0,0 +1,31 @@
+uuid: 0845979e-b977-46c8-9f90-47c6543a355e
+langcode: fr
+status: true
+dependencies:
+  config:
+    - field.field.taxonomy_term.genres.field_synonyms
+    - taxonomy.vocabulary.genres
+  module:
+    - text
+id: taxonomy_term.genres.default
+targetEntityType: taxonomy_term
+bundle: genres
+mode: default
+content:
+  description:
+    label: hidden
+    type: text_default
+    weight: 0
+    region: content
+    settings: {  }
+    third_party_settings: {  }
+  field_synonyms:
+    weight: 1
+    label: above
+    settings:
+      link_to_entity: false
+    third_party_settings: {  }
+    type: string
+    region: content
+hidden:
+  langcode: true

+ 1 - 0
sites/default/config/sync/core.extension.yml

@@ -71,6 +71,7 @@ module:
   responsive_image: 0
   search_api: 0
   search_api_db: 0
+  synonyms: 0
   system: 0
   taxonomy: 0
   text: 0

+ 0 - 6
sites/default/config/sync/field.field.node.static.field_visuel.yml

@@ -7,12 +7,6 @@ dependencies:
     - node.type.static
   module:
     - image
-third_party_settings:
-  content_translation:
-    translation_sync:
-      alt: alt
-      title: title
-      file: '0'
 id: node.static.field_visuel
 field_name: field_visuel
 entity_type: node

+ 19 - 0
sites/default/config/sync/field.field.taxonomy_term.genres.field_synonyms.yml

@@ -0,0 +1,19 @@
+uuid: 633eb359-7553-4848-b50c-1a2a9a249a24
+langcode: fr
+status: true
+dependencies:
+  config:
+    - field.storage.taxonomy_term.field_synonyms
+    - taxonomy.vocabulary.genres
+id: taxonomy_term.genres.field_synonyms
+field_name: field_synonyms
+entity_type: taxonomy_term
+bundle: genres
+label: Synonyms
+description: ''
+required: false
+translatable: true
+default_value: {  }
+default_value_callback: ''
+settings: {  }
+field_type: string

+ 21 - 0
sites/default/config/sync/field.storage.taxonomy_term.field_synonyms.yml

@@ -0,0 +1,21 @@
+uuid: 5a2f08b1-bc6a-44f8-83a0-5a222f49901b
+langcode: fr
+status: true
+dependencies:
+  module:
+    - taxonomy
+id: taxonomy_term.field_synonyms
+field_name: field_synonyms
+entity_type: taxonomy_term
+type: string
+settings:
+  max_length: 255
+  is_ascii: false
+  case_sensitive: false
+module: core
+locked: false
+cardinality: -1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false

+ 3 - 3
sites/default/config/sync/language.content_settings.taxonomy_term.genres.yml

@@ -8,11 +8,11 @@ dependencies:
     - content_translation
 third_party_settings:
   content_translation:
-    enabled: false
+    enabled: true
     bundle_settings:
-      untranslatable_fields_hide: '0'
+      untranslatable_fields_hide: '1'
 id: taxonomy_term.genres
 target_entity_type_id: taxonomy_term
 target_bundle: genres
 default_langcode: site_default
-language_alterable: false
+language_alterable: true

+ 3 - 3
sites/default/config/sync/language.content_settings.taxonomy_term.langues.yml

@@ -8,11 +8,11 @@ dependencies:
     - content_translation
 third_party_settings:
   content_translation:
-    enabled: false
+    enabled: true
     bundle_settings:
-      untranslatable_fields_hide: '0'
+      untranslatable_fields_hide: '1'
 id: taxonomy_term.langues
 target_entity_type_id: taxonomy_term
 target_bundle: langues
 default_langcode: site_default
-language_alterable: false
+language_alterable: true

+ 1 - 0
sites/default/config/sync/language/en/system.action.pathauto_update_alias_node.yml

@@ -0,0 +1 @@
+label: 'Update URL alias'

+ 1 - 0
sites/default/config/sync/language/en/system.action.pathauto_update_alias_user.yml

@@ -0,0 +1 @@
+label: 'Update URL alias'

+ 13 - 0
sites/default/config/sync/synonyms.synonym.field.synonyms.behavior.autocomplete_taxonomy_term_genres_field_synonyms.yml

@@ -0,0 +1,13 @@
+uuid: f3bc2d60-f84d-401c-b265-f2dc9bce7d2a
+langcode: fr
+status: true
+dependencies:
+  config:
+    - field.field.taxonomy_term.genres.field_synonyms
+id: field.synonyms.behavior.autocomplete_taxonomy_term_genres_field_synonyms
+provider_plugin: 'field:synonyms.behavior.autocomplete_taxonomy_term_genres_field_synonyms'
+base_provider_plugin: field
+provider_configuration: {  }
+behavior: synonyms.behavior.autocomplete
+behavior_configuration:
+  wording: '@entity_label (@synonym)'

+ 2 - 0
sites/default/config/sync/user.role.admin.yml

@@ -77,6 +77,8 @@ permissions:
   - 'translate enregistrement node'
   - 'translate entrees taxonomy_term'
   - 'translate evenement node'
+  - 'translate genres taxonomy_term'
+  - 'translate langues taxonomy_term'
   - 'translate page node'
   - 'translate static node'
   - 'update content translations'

+ 1 - 0
sites/default/config/sync/user.role.anonymous.yml

@@ -12,6 +12,7 @@ permissions:
   - 'access content'
   - 'access devel information'
   - 'access kint'
+  - 'access synonyms entity autocomplete'
   - 'create corpus_documents workflow_transition'
   - 'create generique workflow_transition'
   - 'view published fil entities'

+ 1 - 0
sites/default/config/sync/user.role.authenticated.yml

@@ -12,6 +12,7 @@ permissions:
   - 'access content'
   - 'access devel information'
   - 'access kint'
+  - 'access synonyms entity autocomplete'
   - 'add composition entities'
   - 'add fil entities'
   - 'create corpus_documents workflow_transition'

+ 3 - 0
sites/default/config/sync/user.role.root.yml

@@ -80,6 +80,7 @@ permissions:
   - 'administer site configuration'
   - 'administer software updates'
   - 'administer studio'
+  - 'administer synonyms'
   - 'administer taxonomy'
   - 'administer taxonomy_term display'
   - 'administer taxonomy_term fields'
@@ -245,7 +246,9 @@ permissions:
   - 'translate entrees taxonomy_term'
   - 'translate evenement node'
   - 'translate fil node'
+  - 'translate genres taxonomy_term'
   - 'translate interface'
+  - 'translate langues taxonomy_term'
   - 'translate page node'
   - 'translate static node'
   - 'update content translations'

+ 1 - 1
sites/default/config/sync/views.view.content.yml

@@ -979,7 +979,7 @@ display:
       path: admin/content/production
       menu:
         type: tab
-        title: Production
+        title: Content
         description: ''
         expanded: false
         parent: 'menu_link_content:8b5fed48-c008-4041-9bda-06f997582175'

+ 851 - 40
sites/default/config/sync/views.view.entree_s_.yml

@@ -5,8 +5,11 @@ dependencies:
   config:
     - field.storage.taxonomy_term.field_color
     - field.storage.taxonomy_term.field_notice
+    - field.storage.taxonomy_term.field_synonyms
     - field.storage.taxonomy_term.field_workflow
     - taxonomy.vocabulary.entrees
+    - taxonomy.vocabulary.genres
+    - taxonomy.vocabulary.langues
     - user.role.admin
     - user.role.collectionneur
     - user.role.root
@@ -18,7 +21,7 @@ dependencies:
     - user
     - workflow
 id: entree_s_
-label: Entrée(s)
+label: 'Admin Taxo'
 module: views
 description: ''
 tag: ''
@@ -90,21 +93,10 @@ display:
           summary: ''
           description: ''
           columns:
-            field_color: field_color
             name: name
-            field_workflow: name
-            edit_taxonomy_term: name
-            operations: name
-            description__value: description__value
-            field_notice: field_notice
+            field_synonyms: field_synonyms
+            operations: operations
           info:
-            field_color:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
             name:
               sortable: false
               default_sort_order: asc
@@ -112,16 +104,7 @@ display:
               separator: '<br/>'
               empty_column: false
               responsive: ''
-            field_workflow:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            edit_taxonomy_term:
-              sortable: false
-              default_sort_order: asc
+            field_synonyms:
               align: ''
               separator: ''
               empty_column: false
@@ -131,18 +114,6 @@ display:
               separator: ''
               empty_column: false
               responsive: ''
-            description__value:
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
-            field_notice:
-              sortable: false
-              default_sort_order: asc
-              align: ''
-              separator: ''
-              empty_column: false
-              responsive: ''
           default: '-1'
           empty_table: false
       row:
@@ -507,12 +478,42 @@ display:
           id: vid
           table: taxonomy_term_field_data
           field: vid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
           value:
-            entrees: entrees
+            genres: genres
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
           entity_type: taxonomy_term
           entity_field: vid
           plugin_id: bundle
-          group: 1
         field_workflow_value:
           id: field_workflow_value
           table: taxonomy_term__field_workflow
@@ -642,7 +643,7 @@ display:
           entity_field: langcode
           plugin_id: language
       sorts: {  }
-      title: Entrée(s)
+      title: Langues
       header:
         result:
           id: result
@@ -678,7 +679,7 @@ display:
   page_1:
     display_plugin: page
     id: page_1
-    display_title: Page
+    display_title: Entrees
     position: 1
     display_options:
       display_extenders: {  }
@@ -693,6 +694,183 @@ display:
         context: '0'
         menu_name: admin
       rendering_language: '***LANGUAGE_entity_translation***'
+      display_description: ''
+      filters:
+        vid:
+          id: vid
+          table: taxonomy_term_field_data
+          field: vid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value:
+            entrees: entrees
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: vid
+          plugin_id: bundle
+        field_workflow_value:
+          id: field_workflow_value
+          table: taxonomy_term__field_workflow
+          field: field_workflow_value
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: or
+          value: {  }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: field_workflow_value_op
+            label: Workflow
+            description: ''
+            use_operator: false
+            operator: field_workflow_value_op
+            identifier: field_workflow_value
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              collectionneur: '0'
+              admin: '0'
+              root: '0'
+              invite: '0'
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          reduce_duplicates: false
+          plugin_id: workflow_state
+        name:
+          id: name
+          table: taxonomy_term_field_data
+          field: name
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: '='
+          value: ''
+          group: 1
+          exposed: true
+          expose:
+            operator_id: name_op
+            label: Name
+            description: ''
+            use_operator: false
+            operator: name_op
+            identifier: name
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              collectionneur: '0'
+              admin: '0'
+              root: '0'
+              invite: '0'
+            placeholder: ''
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: name
+          plugin_id: string
+        langcode:
+          id: langcode
+          table: taxonomy_term_field_data
+          field: langcode
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value:
+            '***LANGUAGE_language_interface***': '***LANGUAGE_language_interface***'
+            und: und
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: langcode
+          plugin_id: language
+      defaults:
+        filters: false
+        filter_groups: false
+      filter_groups:
+        operator: AND
+        groups:
+          1: AND
     cache_metadata:
       max-age: -1
       contexts:
@@ -705,3 +883,636 @@ display:
         - 'config:field.storage.taxonomy_term.field_color'
         - 'config:field.storage.taxonomy_term.field_notice'
         - 'config:field.storage.taxonomy_term.field_workflow'
+  page_2:
+    display_plugin: page
+    id: page_2
+    display_title: Genres
+    position: 1
+    display_options:
+      display_extenders: {  }
+      path: admin/content/genres
+      menu:
+        type: tab
+        title: Genres
+        description: ''
+        expanded: false
+        parent: 'menu_link_content:8b5fed48-c008-4041-9bda-06f997582175'
+        weight: 200
+        context: '0'
+        menu_name: admin
+      rendering_language: '***LANGUAGE_entity_translation***'
+      display_description: ''
+      fields:
+        name:
+          id: name
+          table: taxonomy_term_field_data
+          field: name
+          entity_type: taxonomy_term
+          entity_field: name
+          alter:
+            alter_text: false
+            make_link: false
+            absolute: false
+            trim: false
+            word_boundary: false
+            ellipsis: false
+            strip_tags: false
+            html: false
+          hide_empty: false
+          empty_zero: false
+          type: string
+          settings:
+            link_to_entity: true
+          plugin_id: term_name
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: Name
+          exclude: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_alter_empty: true
+          click_sort_column: value
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          convert_spaces: false
+        field_synonyms:
+          id: field_synonyms
+          table: taxonomy_term__field_synonyms
+          field: field_synonyms
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: Synonyms
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: false
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          plugin_id: field
+        operations:
+          id: operations
+          table: taxonomy_term_data
+          field: operations
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: 'Liens d''actions'
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          destination: true
+          entity_type: taxonomy_term
+          plugin_id: entity_operations
+      defaults:
+        fields: false
+        filters: false
+        filter_groups: false
+      filters:
+        vid:
+          id: vid
+          table: taxonomy_term_field_data
+          field: vid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value:
+            genres: genres
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: vid
+          plugin_id: bundle
+        name:
+          id: name
+          table: taxonomy_term_field_data
+          field: name
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: '='
+          value: ''
+          group: 1
+          exposed: true
+          expose:
+            operator_id: name_op
+            label: Name
+            description: ''
+            use_operator: false
+            operator: name_op
+            identifier: name
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              collectionneur: '0'
+              admin: '0'
+              root: '0'
+              invite: '0'
+              user: '0'
+            placeholder: ''
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: name
+          plugin_id: string
+        langcode:
+          id: langcode
+          table: taxonomy_term_field_data
+          field: langcode
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value:
+            '***LANGUAGE_language_interface***': '***LANGUAGE_language_interface***'
+            und: und
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: langcode
+          plugin_id: language
+        field_synonyms_value:
+          id: field_synonyms_value
+          table: taxonomy_term__field_synonyms
+          field: field_synonyms_value
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: contains
+          value: ''
+          group: 1
+          exposed: true
+          expose:
+            operator_id: field_synonyms_value_op
+            label: 'Synonyms (field_synonyms)'
+            description: ''
+            use_operator: false
+            operator: field_synonyms_value_op
+            identifier: field_synonyms_value
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              collectionneur: '0'
+              admin: '0'
+              root: '0'
+              invite: '0'
+              user: '0'
+            placeholder: ''
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          plugin_id: string
+      filter_groups:
+        operator: AND
+        groups:
+          1: AND
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - user.roles
+      tags:
+        - 'config:field.storage.taxonomy_term.field_synonyms'
+  page_3:
+    display_plugin: page
+    id: page_3
+    display_title: Langues
+    position: 1
+    display_options:
+      display_extenders: {  }
+      path: admin/content/langues
+      menu:
+        type: tab
+        title: Langues
+        description: ''
+        expanded: false
+        parent: 'menu_link_content:8b5fed48-c008-4041-9bda-06f997582175'
+        weight: 201
+        context: '0'
+        menu_name: admin
+      rendering_language: '***LANGUAGE_entity_translation***'
+      display_description: ''
+      fields:
+        name:
+          id: name
+          table: taxonomy_term_field_data
+          field: name
+          entity_type: taxonomy_term
+          entity_field: name
+          alter:
+            alter_text: false
+            make_link: false
+            absolute: false
+            trim: false
+            word_boundary: false
+            ellipsis: false
+            strip_tags: false
+            html: false
+          hide_empty: false
+          empty_zero: false
+          type: string
+          settings:
+            link_to_entity: true
+          plugin_id: term_name
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: Name
+          exclude: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_alter_empty: true
+          click_sort_column: value
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+          convert_spaces: false
+        operations:
+          id: operations
+          table: taxonomy_term_data
+          field: operations
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: 'Liens d''actions'
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          destination: true
+          entity_type: taxonomy_term
+          plugin_id: entity_operations
+      defaults:
+        fields: false
+        filters: false
+        filter_groups: false
+      filters:
+        vid:
+          id: vid
+          table: taxonomy_term_field_data
+          field: vid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value:
+            langues: langues
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: vid
+          plugin_id: bundle
+        name:
+          id: name
+          table: taxonomy_term_field_data
+          field: name
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: '='
+          value: ''
+          group: 1
+          exposed: true
+          expose:
+            operator_id: name_op
+            label: Name
+            description: ''
+            use_operator: false
+            operator: name_op
+            identifier: name
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              collectionneur: '0'
+              admin: '0'
+              root: '0'
+              invite: '0'
+              user: '0'
+            placeholder: ''
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: name
+          plugin_id: string
+        langcode:
+          id: langcode
+          table: taxonomy_term_field_data
+          field: langcode
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value:
+            '***LANGUAGE_language_interface***': '***LANGUAGE_language_interface***'
+            und: und
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: taxonomy_term
+          entity_field: langcode
+          plugin_id: language
+      filter_groups:
+        operator: AND
+        groups:
+          1: AND
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - user.roles
+      tags: {  }