diff --git a/composer.json b/composer.json index 7d7236e26efaad1d2df403ddd6601235ace6e1e3..32a24f1136ae29b281cd7ab7c922c60e9e7f707a 100644 --- a/composer.json +++ b/composer.json @@ -121,7 +121,6 @@ "drupal/entity_embed": "1.1", "drupal/entity_reference_revisions": "1.9", "drupal/externalauth": "1.3", - "drupal/features": "3.8", "drupal/field_group": "3.1", "drupal/field_permissions": "1.1", "drupal/file_browser": "1.3", diff --git a/composer.lock b/composer.lock index d541fe7873fd7aba1a4dad5da7ff221616c7d121..3d7e506764ad348b05e8708de44c031a1e5aaebd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "843798e535532282f5f95604c8d1c8db", + "content-hash": "e3ee1d5a5d5f54ba54a8f18646828dd0", "packages": [ { "name": "alchemy/zippy", @@ -4935,92 +4935,6 @@ "source": "https://git.drupalcode.org/project/externalauth" } }, - { - "name": "drupal/features", - "version": "3.8.0", - "source": { - "type": "git", - "url": "https://git.drupalcode.org/project/features.git", - "reference": "8.x-3.8" - }, - "dist": { - "type": "zip", - "url": "https://ftp.drupal.org/files/projects/features-8.x-3.8.zip", - "reference": "8.x-3.8", - "shasum": "15cebd00e38d63c0d946682e76327a03499c27be" - }, - "require": { - "drupal/config_update": "^1.4", - "drupal/core": "^8" - }, - "type": "drupal-module", - "extra": { - "drupal": { - "version": "8.x-3.8", - "datestamp": "1536512284", - "security-coverage": { - "status": "covered", - "message": "Covered by Drupal's security advisory policy" - } - }, - "drush": { - "services": { - "drush.services.yml": "^9" - } - } - }, - "notification-url": "https://packages.drupal.org/8/downloads", - "license": [ - "GPL-2.0+" - ], - "authors": [ - { - "name": "dawehner", - "homepage": "https://www.drupal.org/user/99340" - }, - { - "name": "donquixote", - "homepage": "https://www.drupal.org/user/459338" - }, - { - "name": "e2thex", - "homepage": "https://www.drupal.org/user/189123" - }, - { - "name": "febbraro", - "homepage": "https://www.drupal.org/user/43670" - }, - { - "name": "flocondetoile", - "homepage": "https://www.drupal.org/user/2006064" - }, - { - "name": "jmiccolis", - "homepage": "https://www.drupal.org/user/31731" - }, - { - "name": "joseph.olstad", - "homepage": "https://www.drupal.org/user/1321830" - }, - { - "name": "mpotter", - "homepage": "https://www.drupal.org/user/616192" - }, - { - "name": "nedjo", - "homepage": "https://www.drupal.org/user/4481" - }, - { - "name": "tim.plunkett", - "homepage": "https://www.drupal.org/user/241634" - } - ], - "description": "Enables administrators to package configuration into modules", - "homepage": "https://www.drupal.org/project/features", - "support": { - "source": "https://git.drupalcode.org/project/features" - } - }, { "name": "drupal/field_group", "version": "3.1.0", diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php index daedd43494d640dc2902b544ef82e98c2dfa70e6..acc10dc5c0306ff975cae803b186ce7e21587435 100644 --- a/vendor/composer/InstalledVersions.php +++ b/vendor/composer/InstalledVersions.php @@ -30,7 +30,7 @@ class InstalledVersions 'aliases' => array ( ), - 'reference' => '11ac4bc4a7dc85d65a11da78cbdc0ddccfae171d', + 'reference' => 'fb181bce9c126206eb904564a795200a8dbc2b7e', 'name' => 'osu-asc-webservices/d8-upstream', ), 'versions' => @@ -1104,15 +1104,6 @@ class InstalledVersions ), 'reference' => '8.x-1.3', ), - 'drupal/features' => - array ( - 'pretty_version' => '3.8.0', - 'version' => '3.8.0.0', - 'aliases' => - array ( - ), - 'reference' => '8.x-3.8', - ), 'drupal/field' => array ( 'replaced' => @@ -2431,7 +2422,7 @@ class InstalledVersions 'aliases' => array ( ), - 'reference' => '11ac4bc4a7dc85d65a11da78cbdc0ddccfae171d', + 'reference' => 'fb181bce9c126206eb904564a795200a8dbc2b7e', ), 'pantheon-systems/quicksilver-pushback' => array ( diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index a98ae9222003e67923856e1cc92c45fcb432698b..6da2ec35e7c8ff6795c46e7d21d1080238ea1b81 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -5047,86 +5047,6 @@ }, "install-path": "../../web/modules/externalauth" }, - { - "name": "drupal/features", - "version": "3.8.0", - "version_normalized": "3.8.0.0", - "source": { - "type": "git", - "url": "https://git.drupalcode.org/project/features.git", - "reference": "8.x-3.8" - }, - "dist": { - "type": "zip", - "url": "https://ftp.drupal.org/files/projects/features-8.x-3.8.zip", - "reference": "8.x-3.8", - "shasum": "15cebd00e38d63c0d946682e76327a03499c27be" - }, - "require": { - "drupal/config_update": "^1.4", - "drupal/core": "*" - }, - "type": "drupal-module", - "extra": { - "branch-alias": { - "dev-3.x": "3.x-dev" - }, - "drupal": { - "version": "8.x-3.8", - "datestamp": "1536512284", - "security-coverage": { - "status": "covered", - "message": "Covered by Drupal's security advisory policy" - } - }, - "drush": { - "services": { - "drush.services.yml": "^9" - } - } - }, - "installation-source": "dist", - "notification-url": "https://packages.drupal.org/8/downloads", - "license": [ - "GPL-2.0+" - ], - "authors": [ - { - "name": "dawehner", - "homepage": "https://www.drupal.org/user/99340" - }, - { - "name": "e2thex", - "homepage": "https://www.drupal.org/user/189123" - }, - { - "name": "febbraro", - "homepage": "https://www.drupal.org/user/43670" - }, - { - "name": "jmiccolis", - "homepage": "https://www.drupal.org/user/31731" - }, - { - "name": "mpotter", - "homepage": "https://www.drupal.org/user/616192" - }, - { - "name": "nedjo", - "homepage": "https://www.drupal.org/user/4481" - }, - { - "name": "tim.plunkett", - "homepage": "https://www.drupal.org/user/241634" - } - ], - "description": "Enables administrators to package configuration into modules", - "homepage": "https://www.drupal.org/project/features", - "support": { - "source": "http://cgit.drupalcode.org/features" - }, - "install-path": "../../web/modules/features" - }, { "name": "drupal/field_group", "version": "3.1.0", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index db814007492bb7097979415e4bfc935d998ec567..f1b38e6e80359e59098f56cdbfa8c9cf9475a5db 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -6,7 +6,7 @@ 'aliases' => array ( ), - 'reference' => '11ac4bc4a7dc85d65a11da78cbdc0ddccfae171d', + 'reference' => 'fb181bce9c126206eb904564a795200a8dbc2b7e', 'name' => 'osu-asc-webservices/d8-upstream', ), 'versions' => @@ -1080,15 +1080,6 @@ ), 'reference' => '8.x-1.3', ), - 'drupal/features' => - array ( - 'pretty_version' => '3.8.0', - 'version' => '3.8.0.0', - 'aliases' => - array ( - ), - 'reference' => '8.x-3.8', - ), 'drupal/field' => array ( 'replaced' => @@ -2407,7 +2398,7 @@ 'aliases' => array ( ), - 'reference' => '11ac4bc4a7dc85d65a11da78cbdc0ddccfae171d', + 'reference' => 'fb181bce9c126206eb904564a795200a8dbc2b7e', ), 'pantheon-systems/quicksilver-pushback' => array ( diff --git a/web/modules/features/LICENSE.txt b/web/modules/features/LICENSE.txt deleted file mode 100644 index d159169d1050894d3ea3b98e1c965c4058208fe1..0000000000000000000000000000000000000000 --- a/web/modules/features/LICENSE.txt +++ /dev/null @@ -1,339 +0,0 @@ - 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. diff --git a/web/modules/features/composer.json b/web/modules/features/composer.json deleted file mode 100644 index de7ea040a6df8a17e66567a5dd32ed2c07ab27a9..0000000000000000000000000000000000000000 --- a/web/modules/features/composer.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "description": "Enables administrators to package configuration into modules", - "license": "GPL-2.0+", - "minimum-stability": "dev", - "name": "drupal/features", - "require": { - "drupal/config_update": "^1.4" - }, - "type": "drupal-module", - "extra": { - "drush": { - "services": { - "drush.services.yml": "^9" - } - } - } -} diff --git a/web/modules/features/config/install/features.bundle.default.yml b/web/modules/features/config/install/features.bundle.default.yml deleted file mode 100644 index ea4bb8819b1bfb9c2739d448422ed5a0a2495c6a..0000000000000000000000000000000000000000 --- a/web/modules/features/config/install/features.bundle.default.yml +++ /dev/null @@ -1,98 +0,0 @@ -langcode: en -status: true -dependencies: { } -name: Default -machine_name: default -description: '' -assignments: - alter: - core: true - uuid: true - user_permissions: true - enabled: true - weight: 0 - base: - types: - config: - comment_type: comment_type - node_type: node_type - content: - user: user - enabled: true - weight: -2 - core: - types: - config: - date_format: date_format - field_storage_config: field_storage_config - entity_form_mode: entity_form_mode - image_style: image_style - menu: menu - responsive_image_style: responsive_image_style - user_role: user_role - entity_view_mode: entity_view_mode - enabled: true - weight: 5 - dependency: - enabled: true - weight: 15 - exclude: - types: - config: - features_bundle: features_bundle - curated: true - module: - installed: true - profile: true - namespace: true - namespace_any: false - enabled: true - weight: -5 - existing: - enabled: true - weight: 12 - forward_dependency: - enabled: true - weight: 4 - namespace: - enabled: true - weight: 0 - optional: - types: - config: {} - enabled: true - weight: 0 - packages: - enabled: true - weight: -20 - profile: - curated: true - standard: - files: true - dependencies: true - types: - config: - block: block - language_content_settings: language_content_settings - configurable_language: configurable_language - migration: migration - shortcut_set: shortcut_set - tour: tour - enabled: true - weight: 10 - site: - types: - config: - action: action - contact_form: contact_form - block_content_type: block_content_type - rdf_mapping: rdf_mapping - search_page: search_page - taxonomy_vocabulary: taxonomy_vocabulary - editor: editor - filter_format: filter_format - enabled: true - weight: 7 -profile_name: '' -is_profile: false - diff --git a/web/modules/features/config/install/features.settings.yml b/web/modules/features/config/install/features.settings.yml deleted file mode 100644 index ed8b37a57cb1672f0673de3872e5886bf06f738e..0000000000000000000000000000000000000000 --- a/web/modules/features/config/install/features.settings.yml +++ /dev/null @@ -1,3 +0,0 @@ -export: - folder: 'custom' -langcode: en diff --git a/web/modules/features/config/schema/features.schema.yml b/web/modules/features/config/schema/features.schema.yml deleted file mode 100644 index 3d53f1d9f81880855aee96700635ce1ccafc0341..0000000000000000000000000000000000000000 --- a/web/modules/features/config/schema/features.schema.yml +++ /dev/null @@ -1,188 +0,0 @@ -features.settings: - type: config_entity - label: 'Features settings' - mapping: - export: - type: mapping - label: "Export settings" - mapping: - folder: - type: string - label: "Folder" - langcode: - type: string - label: "Language Code" - -features.bundle.*: - type: config_entity - label: 'Features bundle' - mapping: - machine_name: - type: string - label: "Machine name" - name: - type: string - label: "Name" - description: - type: string - label: "Description" - assignments: - type: sequence - label: "Assignment" - sequence: - type: features.assignment.[%key] - profile_name: - type: string - label: "Profile name" - is_profile: - type: boolean - label: "Is install profile" - -features.assignment.settings: - type: mapping - label: "Assignment settings" - mapping: - enabled: - type: boolean - label: "Enabled" - weight: - type: integer - label: "Weight" - -features.assignment.*: - type: features.assignment.settings - -features.assignment.base: - type: features.assignment.settings - label: "Base type" - mapping: - types: - type: mapping - label: "Types" - mapping: - config: - type: sequence - label: "Configuration Types" - sequence: - type: string - content: - type: sequence - label: "Content entity types" - sequence: - type: string - -features.assignment.core: - type: features.assignment.settings - label: "Core type" - mapping: - types: - type: mapping - label: "Types" - mapping: - config: - type: sequence - label: "Configuration Types" - sequence: - type: string - -features.assignment.exclude: - type: features.assignment.settings - label: "Exclude" - mapping: - types: - type: mapping - label: "Types" - mapping: - config: - type: sequence - label: "Configuration Types" - sequence: - type: string - curated: - type: boolean - label: "Exclude designated site-specific configuration" - module: - type: mapping - label: "Module" - mapping: - installed: - type: boolean - label: "Exclude installed module-provided entity configuration" - profile: - type: boolean - label: "Don't exclude install profile's configuration" - namespace: - type: boolean - label: "Don't exclude non-installed configuration by namespace" - namespace_any: - type: boolean - label: "Don't exclude ANY configuration by namespace" - -features.assignment.optional: - type: features.assignment.settings - label: "Optional" - mapping: - types: - type: mapping - label: "Types" - mapping: - config: - type: sequence - label: "Configuration Types" - sequence: - type: string - -features.assignment.profile: - type: features.assignment.settings - label: "Profile" - mapping: - curated: - type: boolean - label: "Add commonly-needed configuration" - standard: - type: mapping - label: "Standard" - mapping: - files: - type: boolean - label: "Add configuration and files from Standard profile" - dependencies: - type: boolean - label: "Add module and theme dependencies from Standard profile" - types: - type: mapping - label: "Types" - mapping: - config: - type: sequence - label: "Configuration Types" - sequence: - type: string - -features.assignment.site: - type: features.assignment.settings - label: "Site" - mapping: - types: - type: mapping - label: "Types" - mapping: - config: - type: sequence - label: "Configuration Types" - sequence: - type: string - -features.assignment.alter: - type: features.assignment.settings - label: "Alter" - mapping: - core: - type: boolean - label: "Core" - uuid: - type: boolean - label: "UUID" - user_permissions: - type: boolean - label: "User permissions" diff --git a/web/modules/features/drush.services.yml b/web/modules/features/drush.services.yml deleted file mode 100644 index 16b0f29c854acd5ec1557fc1d9bd47bc9224c04c..0000000000000000000000000000000000000000 --- a/web/modules/features/drush.services.yml +++ /dev/null @@ -1,11 +0,0 @@ -services: - features.commands: - class: \Drupal\features\Commands\FeaturesCommands - arguments: - - '@features_assigner' - - '@features.manager' - - '@features_generator' - - '@config_update.config_diff' - - '@config.storage' - tags: - - { name: drush.command } diff --git a/web/modules/features/drush/features.drush8.inc b/web/modules/features/drush/features.drush8.inc deleted file mode 100644 index 35a76abe83d06ef5fd1977039756ab5f918b112e..0000000000000000000000000000000000000000 --- a/web/modules/features/drush/features.drush8.inc +++ /dev/null @@ -1,912 +0,0 @@ -<?php - -/** - * @file - * Features module drush integration. - */ - -use Drupal\features\ConfigurationItem; -use Drupal\features\FeaturesBundleInterface; -use Drupal\features\FeaturesManagerInterface; -use Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite; -use Drupal\Component\Diff\DiffFormatter; - -/** - * Implements hook_drush_command(). - */ -function features_drush_command() { - $items = []; - - $items['features-status'] = [ - 'description' => 'Display current Features settings.', - 'aliases' => ['fs'], - ]; - - $items['features-list-packages'] = [ - 'description' => 'Display a list of all existing features and packages available to be generated. If a package name is provided as an argument, then all of the configuration objects assigned to that package will be listed.', - 'examples' => [ - "drush features-list-packages" => 'Display a list of all existing featurea and packages available to be generated.', - "drush features-list-packages 'example_article'" => "Display a list of all configuration objects assigned to the 'example_article' package.", - ], - 'arguments' => [ - 'package' => 'The package to list. Optional; if specified, lists all configuration objects assigned to that package. If no package is specified, lists all of the features.', - ], - 'outputformat' => [ - 'default' => 'table', - 'pipe-format' => 'list', - 'field-labels' => [ - 'name' => 'Name', - 'machine_name' => 'Machine name', - 'status' => 'Status', - 'version' => 'Version', - 'state' => 'State', - 'object' => 'Configuration object', - ], - 'output-data-type' => 'format-table', - ], - 'aliases' => ['fl'], - ]; - - $items['features-import-all'] = [ - 'description' => 'Import module config from all installed features.', - 'examples' => [ - "drush features-import-all" => 'Import module config from all installed features.', - ], - 'aliases' => ['fra', 'fia', 'fim-all'], - ]; - - $items['features-export'] = [ - 'description' => "Export the configuration on your site into a custom module.", - 'arguments' => [ - 'package' => 'A space delimited list of features to export.', - ], - 'options' => [ - 'add-profile' => 'Package features into an install profile.', - ], - 'examples' => [ - "drush features-export" => 'Export all available packages.', - "drush features-export example_article example_page" => "Export the example_article and example_page packages.", - "drush features-export --add-profile" => "Export all available packages and add them to an install profile.", - ], - // Add previous "fu" alias for compatibility. - 'aliases' => ['fex', 'fu', 'fua', 'fu-all'], - ]; - - $items['features-add'] = [ - 'description' => "Add a config item to a feature package.", - 'arguments' => [ - 'feature' => 'Feature package to export and add config to.', - 'components' => 'Patterns of config to add, see features-components for the format of patterns.', - ], - 'aliases' => ['fa', 'fe'], - ]; - - $items['features-components'] = [ - 'description' => 'List features components.', - 'arguments' => [ - 'patterns' => 'The features components type to list. Omit this argument to list all components.', - ], - 'options' => [ - 'exported' => [ - 'description' => 'Show only components that have been exported.', - ], - 'not-exported' => [ - 'description' => 'Show only components that have not been exported.', - ], - ], - 'aliases' => ['fc'], - ]; - - $items['features-diff'] = [ - 'description' => "Show the difference between the active config and the default config stored in a feature package.", - 'arguments' => [ - 'feature' => 'The feature in question.', - ], - 'options' => [ - 'ctypes' => 'Comma separated list of component types to limit the output to. Defaults to all types.', - 'lines' => 'Generate diffs with <n> lines of context instead of the usual two.', - ], - 'aliases' => ['fd'], - ]; - - $items['features-import'] = [ - 'description' => "Import a module config into your site.", - 'arguments' => [ - 'feature' => 'A space delimited list of features or feature:component pairs to import.', - ], - 'options' => [ - 'force' => "Force import even if config is not overridden.", - ], - 'examples' => [ - 'drush features-import foo:node.type.page foo:taxonomy.vocabulary.tags bar' => 'Import node and taxonomy config of feature "foo". Import all config of feature "bar".', - ], - 'aliases' => ['fim', 'fr'], - ]; - - foreach ($items as $name => &$item) { - $item['options']['bundle'] = [ - 'description' => 'Use a specific bundle namespace.', - ]; - } - - return $items; -} - -/** - * Applies global options for Features drush commands. - * - * The option --name="bundle_name" sets the bundle namespace. - * - * @return \Drupal\features\FeaturesAssignerInterface -*/ -function _drush_features_options() { - /** @var \Drupal\features\FeaturesAssignerInterface $assigner */ - $assigner = \Drupal::service('features_assigner'); - $bundle_name = drush_get_option('bundle'); - if (!empty($bundle_name)) { - $bundle = $assigner->applyBundle($bundle_name); - if ($bundle->getMachineName() != $bundle_name) { - drush_log(dt('Bundle @name not found. Using default.', ['@name' => $bundle_name]), 'warning'); - } - } - else { - $assigner->assignConfigPackages(); - } - return $assigner; -} - -/** - * Provides Drush command callback for features-status. - */ -function drush_features_status() { - $args = func_get_args(); - $assigner = _drush_features_options(); - - - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - $current_bundle = $assigner->getBundle(); - $export_settings = $manager->getExportSettings(); - $methods = $assigner->getEnabledAssigners(); - if ($current_bundle->isDefault()) { - drush_print(dt('Current bundle: none')); - } - else { - drush_print(dt('Current bundle: @name (@machine_name)', - [ - '@name' => $current_bundle->getName(), - '@machine_name' => $current_bundle->getMachineName(), - ])); - } - drush_print(dt('Export folder: @folder', ['@folder' => $export_settings['folder']])); - $dt_args = ['@methods' => implode(', ', array_keys($methods))]; - drush_print(dt('The following assignment methods are enabled:')); - drush_print(dt(' @methods', $dt_args)); - - if (!empty($args)) { - $config = $manager->getConfigCollection(); - if (count($args) > 1) { - print_r(array_keys($config)); - } - else { - print_r($config[$args[0]]); - } - } -} - -/** - * Drush command callback for features-list-packages. - * - * @param string $package_name - * (optional) The package name. - * - * @return array|bool - */ -function drush_features_list_packages($package_name = '') { - $assigner = _drush_features_options(); - $current_bundle = $assigner->getBundle(); - $namespace = $current_bundle->isDefault() ? FeaturesBundleInterface::DEFAULT_BUNDLE : $current_bundle->getMachineName(); - - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - $packages = $manager->getPackages(); - - $packages = $manager->filterPackages($packages, $namespace); - $result = []; - - // If no package was specified, list all packages. - if (empty($package_name)) { - drush_hide_output_fields(['object']); - foreach ($packages as $package) { - $overrides = $manager->detectOverrides($package); - $state = $package->getState(); - if (!empty($overrides) && ($package->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT)) { - $state = FeaturesManagerInterface::STATE_OVERRIDDEN; - } - - $result[$package->getMachineName()] = [ - 'name' => $package->getName(), - 'machine_name' => $package->getMachineName(), - 'status' => $manager->statusLabel($package->getStatus()), - 'version' => $package->getVersion(), - 'state' => ($state != FeaturesManagerInterface::STATE_DEFAULT) - ? $manager->stateLabel($state) - : '', - ]; - } - return $result; - } - // If a valid package was listed, list its configuration. - else { - foreach ($packages as $package) { - if ($package->getMachineName() == $package_name) { - drush_hide_output_fields([ - 'machine_name', - 'name', - 'status', - 'version', - 'state', - ]); - foreach ($package->getConfig() as $item_name) { - $result[$item_name] = [ - 'object' => $item_name, - ]; - } - return $result; - } - } - - } - - // If no matching package found, return an error. - drush_log(dt('Package "@package" not found.', ['@package' => $package_name]), 'warning'); - return FALSE; -} - -/** - * Drush command callback for features-import-all. - * - */ -function drush_features_import_all() { - $assigner = _drush_features_options(); - $current_bundle = $assigner->getBundle(); - $namespace = $current_bundle->isDefault() ? FeaturesBundleInterface::DEFAULT_BUNDLE : $current_bundle->getMachineName(); - - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - $packages = $manager->getPackages(); - $packages = $manager->filterPackages($packages, $namespace); - $overridden = []; - - foreach ($packages as $package) { - $overrides = $manager->detectOverrides($package); - $missing = $manager->detectMissing($package); - if ((!empty($missing) || !empty($overrides)) && ($package->getStatus() == FeaturesManagerInterface::STATUS_INSTALLED)) { - $overridden[] = $package->getMachineName(); - } - } - - if (!empty($overridden)) { - call_user_func_array('drush_features_import', $overridden); - } - else { - drush_log(dt('Current state already matches active config, aborting.'), 'ok'); - } -} - -/** - * Provides Drush command callback for features-export. - */ -function drush_features_export($packages = NULL) { - $packages = func_get_args(); - $assigner = _drush_features_options(); - - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - /** @var \Drupal\features\FeaturesGeneratorInterface $generator */ - $generator = \Drupal::service('features_generator'); - - $current_bundle = $assigner->getBundle(); - - if (drush_get_option('add-profile')) { - if ($current_bundle->isDefault) { - return drush_set_error('', dt("Must specify a profile name with --name")); - } - $current_bundle->setIsProfile(TRUE); - } - - $all_packages = $manager->getPackages(); - foreach ($packages as $name) { - if (!isset($all_packages[$name])) { - return drush_set_error('', dt("The package @name does not exist.", ['@name' => $name])); - } - } - - if (empty($packages)) { - $packages = $all_packages; - $dt_args = ['@modules' => implode(', ', array_keys($packages))]; - drush_print(dt('The following extensions will be exported: @modules', $dt_args)); - if (!drush_confirm(dt('Do you really want to continue?'))) { - return drush_user_abort('Aborting.'); - } - } - - // If any packages exist, confirm before overwriting. - if ($existing_packages = $manager->listPackageDirectories($packages, $current_bundle)) { - foreach ($existing_packages as $name => $directory) { - drush_print(dt("The extension @name already exists at @directory.", ['@name' => $name, '@directory' => $directory])); - } - // Apparently, format_plural is not always available. - if (count($existing_packages) == 1) { - $message = dt('Would you like to overwrite it?'); - } - else { - $message = dt('Would you like to overwrite them?'); - } - if (!drush_confirm($message)) { - return drush_user_abort(); - } - } - - // Use the write generation method. - $method_id = FeaturesGenerationWrite::METHOD_ID; - $result = $generator->generatePackages($method_id, $current_bundle, $packages); - - foreach ($result as $message) { - $type = $message['success'] ? 'success' : 'error'; - drush_log($message['message'], $message['variables'], $type); - } -} - -/** - * Adds a component to a features module. - * - * @param - * The selected components. - */ -function drush_features_add() { - if ($args = func_get_args()) { - $assigner = _drush_features_options(); - - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - /** @var \Drupal\features\FeaturesGeneratorInterface $generator */ - $generator = \Drupal::service('features_generator'); - - $current_bundle = $assigner->getBundle(); - - $module = array_shift($args); - if (empty($args)) { - return drush_set_error('', 'No components supplied.'); - } - $components = _drush_features_component_list(); - $options = [ - 'exported' => FALSE, - ]; - - $filtered_components = _drush_features_component_filter($components, $args, $options); - $items = $filtered_components['components']; - - if (empty($items)) { - return drush_set_error('', 'No components to add.'); - } - - $packages = [$module]; - // If any packages exist, confirm before overwriting. - if ($existing_packages = $manager->listPackageDirectories($packages)) { - foreach ($existing_packages as $name => $directory) { - drush_print(dt("The extension @name already exists at @directory.", ['@name' => $name, '@directory' => $directory])); - } - // Apparently, format_plural is not always available. - if (count($existing_packages) == 1) { - $message = dt('Would you like to overwrite it?'); - } - else { - $message = dt('Would you like to overwrite them?'); - } - if (!drush_confirm($message)) { - return drush_user_abort(); - } - } - else { - $package = $manager->initPackage($module, NULL, '', 'module', $current_bundle); - list($full_name, $path) = $manager->getExportInfo($package, $current_bundle); - drush_print(dt('Will create a new extension @name in @directory', ['@name' => $full_name, '@directory' => $path])); - if (!drush_confirm(dt('Do you really want to continue?'))) { - drush_die('Aborting.'); - } - } - - $config = _drush_features_build_config($items); - - $manager->assignConfigPackage($module, $config); - - // Use the write generation method. - $method_id = FeaturesGenerationWrite::METHOD_ID; - $result = $generator->generatePackages($method_id, $current_bundle, $packages); - - foreach ($result as $message) { - $type = $message['success'] ? 'success' : 'error'; - drush_log($message['message'], $message['variables'], $type); - } - } - else { - return drush_set_error('', 'No feature name given.'); - } -} - -/** - * Lists components, with pattern matching. - */ -function drush_features_components() { - $args = func_get_args(); - _drush_features_options(); - - $components = _drush_features_component_list(); - ksort($components); - // If no args supplied, prompt with a list. - if (empty($args)) { - $types = array_keys($components); - array_unshift($types, 'all'); - $choice = drush_choice($types, 'Enter a number to choose which component type to list.'); - if ($choice === FALSE) { - return; - } - - $args = ($choice == 0) ? ['*'] : [$types[$choice]]; - } - $options = [ - 'provided by' => TRUE, - ]; - if (drush_get_option(['exported', 'e'], NULL)) { - $options['not exported'] = FALSE; - } - elseif (drush_get_option(['not-exported', 'o'], NULL)) { - $options['exported'] = FALSE; - } - - $filtered_components = _drush_features_component_filter($components, $args, $options); - if ($filtered_components) { - _drush_features_component_print($filtered_components); - } -} - -/** - * Lists the differences in the package config vs the active store. - * - * @param string $package - * The machine name of a package. - */ -function drush_features_diff() { - if (!$args = func_get_args()) { - drush_print_table(drush_features_list_packages()); - return; - } - - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - /** @var \Drupal\features\FeaturesAssignerInterface $assigner */ - $assigner = \Drupal::service('features_assigner'); - $assigner->assignConfigPackages(); - - $module = $args[0]; - $filter_ctypes = drush_get_option("ctypes"); - if ($filter_ctypes) { - $filter_ctypes = explode(',', $filter_ctypes); - } - - $feature = $manager->loadPackage($module, TRUE); - if (empty($feature)) { - drush_log(dt('No such feature is available: @module', ['@module' => $module]), 'error'); - return; - } - - $lines = drush_get_option('lines'); - $lines = isset($lines) ? $lines : 2; - - $formatter = new DiffFormatter(); - $formatter->leading_context_lines = $lines; - $formatter->trailing_context_lines = $lines; - $formatter->show_header = FALSE; - - if (drush_get_context('DRUSH_NOCOLOR')) { - $red = $green = "%s"; - } - else { - $red = "\033[31;40m\033[1m%s\033[0m"; - $green = "\033[0;32;40m\033[1m%s\033[0m"; - } - - $overrides = $manager->detectOverrides($feature); - $missing = $manager->reorderMissing($manager->detectMissing($feature)); - $overrides = array_merge($overrides, $missing); - - if (empty($overrides)) { - drush_print(dt('Active config matches stored config for @module.', ['@module' => $module])); - } - else { - /** @var \Drupal\config_update\ConfigDiffInterface $config_diff */ - $config_diff = \Drupal::service('config_update.config_diff'); - /** @var \Drupal\Core\Config\StorageInterface $active_storage */ - $active_storage = \Drupal::service('config.storage'); - - // Print key for colors. - drush_print(dt('Legend: ')); - drush_print(sprintf($red, dt('Code: drush features-import will replace the active config with the displayed code.'))); - drush_print(sprintf($green, dt('Active: drush features-export will update the exported feature with the displayed active config'))); - - foreach ($overrides as $name) { - $message = ''; - if (in_array($name, $missing)) { - $message = sprintf($red, t('(missing from active)')); - $extension = []; - } - else { - $active = $manager->getActiveStorage()->read($name); - $extension = $manager->getExtensionStorages()->read($name); - if (empty($extension)) { - $extension = []; - $message = sprintf($green, t('(not exported)')); - } - $diff = $config_diff->diff($extension, $active); - $rows = explode("\n", $formatter->format($diff)); - } - drush_print(); - drush_print(dt("Config @name @message", ['@name' => $name, '@message' => $message])); - if (!empty($extension)) { - foreach ($rows as $row) { - if (strpos($row, '>') === 0) { - drush_print(sprintf($green, $row)); - } - elseif (strpos($row, '<') === 0) { - drush_print(sprintf($red, $row)); - } - else { - drush_print($row); - } - } - } - } - } -} - -/** - * Imports module config into the active store. - * - * Same as the old "revert" functionality. - */ -function drush_features_import() { - if ($args = func_get_args()) { - _drush_features_options(); - - // Determine if revert should be forced. - $force = drush_get_option('force'); - // Determine if -y was supplied. If so, we can filter out needless output - // from this command. - $skip_confirmation = drush_get_context('DRUSH_AFFIRMATIVE'); - - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - - // Parse list of arguments. - $modules = []; - foreach ($args as $arg) { - $arg = explode(':', $arg); - $module = array_shift($arg); - $component = array_shift($arg); - - if (isset($module)) { - if (empty($component)) { - // If we received just a feature name, this means that we need all of - // its components. - $modules[$module] = TRUE; - } - elseif ($modules[$module] !== TRUE) { - if (!isset($modules[$module])) { - $modules[$module] = []; - } - $modules[$module][] = $component; - } - } - } - - // Process modules. - foreach ($modules as $module => $components_needed) { - - $dt_args['@module'] = $module; - /** @var \Drupal\features\Package $feature */ - $feature = $manager->loadPackage($module, TRUE); - if (empty($feature)) { - drush_log(dt('No such feature is available: @module', $dt_args), 'error'); - return; - } - - if ($feature->getStatus() != FeaturesManagerInterface::STATUS_INSTALLED) { - drush_log(dt('No such feature is installed: @module', $dt_args), 'error'); - return; - } - - // Forcefully revert all components of a feature. - if ($force) { - $components = $feature->getConfigOrig(); - } - // Only revert components that are detected to be Overridden. - else { - $components = $manager->detectOverrides($feature); - $missing = $manager->reorderMissing($manager->detectMissing($feature)); - // Be sure to import missing components first. - $components = array_merge($missing, $components); - } - - if (!empty($components_needed) && is_array($components_needed)) { - $components = array_intersect($components, $components_needed); - } - - if (empty($components)) { - drush_log(dt('Current state already matches active config, aborting.'), 'ok'); - } - else { - // Determine which config the user wants to import/revert. - $config_to_create = []; - foreach ($components as $component) { - $dt_args['@component'] = $component; - $confirmation_message = 'Do you really want to import @module : @component?'; - if ($skip_confirmation || drush_confirm(dt($confirmation_message, $dt_args))) { - $config_to_create[$component] = ''; - } - } - - // Perform the import/revert. - $config_imported = $manager->createConfiguration($config_to_create); - - // List the results. - foreach ($components as $component) { - $dt_args['@component'] = $component; - if (isset($config_imported['new'][$component])) { - drush_log(dt('Imported @module : @component.', $dt_args), 'ok'); - } - elseif (isset($config_imported['updated'][$component])) { - drush_log(dt('Reverted @module : @component.', $dt_args), 'ok'); - } - elseif (!isset($config_to_create[$component])) { - drush_log(dt('Skipping @module : @component.', $dt_args), 'ok'); - } - else { - drush_log(dt('Error importing @module : @component.', $dt_args), 'error'); - } - } - } - } - } - else { - drush_print_table(drush_features_list_packages()); - return; - } -} - -/** - * Returns an array of full config names given a array[$type][$component]. - * - * @param array $items - * The items to return data for. - */ -function _drush_features_build_config(array $items) { - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - $result = []; - foreach ($items as $config_type => $item) { - foreach ($item as $item_name => $title) { - $result[] = $manager->getFullName($config_type, $item_name); - } - } - return $result; -} - -/** - * Returns a listing of all known components, indexed by source. - */ -function _drush_features_component_list() { - $result = []; - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - $config = $manager->getConfigCollection(); - foreach ($config as $item_name => $item) { - $result[$item->getType()][$item->getShortName()] = $item->getLabel(); - } - return $result; -} - -/** - * Filters components by patterns. - */ -function _drush_features_component_filter($all_components, $patterns = [], $options = []) { - $options += [ - 'exported' => TRUE, - 'not exported' => TRUE, - 'provided by' => FALSE, - ]; - $pool = []; - // Maps exported components to feature modules. - $components_map = _drush_features_get_component_map(); - // First filter on exported state. - foreach ($all_components as $source => $components) { - foreach ($components as $name => $title) { - $exported = count($components_map[$source][$name]) > 0; - if ($exported) { - if ($options['exported']) { - $pool[$source][$name] = $title; - } - } - else { - if ($options['not exported']) { - $pool[$source][$name] = $title; - } - } - } - } - - $state_string = ''; - - if (!$options['exported']) { - $state_string = 'unexported'; - } - elseif (!$options['not exported']) { - $state_string = 'exported'; - } - - $selected = []; - foreach ($patterns as $pattern) { - // Rewrite * to %. Let users use both as wildcard. - $pattern = strtr($pattern, ['*' => '%']); - $sources = []; - list($source_pattern, $component_pattern) = explode(':', $pattern, 2); - // If source is empty, use a pattern. - if ($source_pattern == '') { - $source_pattern = '%'; - } - if ($component_pattern == '') { - $component_pattern = '%'; - } - - $preg_source_pattern = strtr(preg_quote($source_pattern, '/'), ['%' => '.*']); - $preg_component_pattern = strtr(preg_quote($component_pattern, '/'), ['%' => '.*']); - // If it isn't a pattern, but a simple string, we don't anchor the - // pattern. This allows for abbreviating. Otherwise, we do, as this seems - // more natural for patterns. - if (strpos($source_pattern, '%') !== FALSE) { - $preg_source_pattern = '^' . $preg_source_pattern . '$'; - } - if (strpos($component_pattern, '%') !== FALSE) { - $preg_component_pattern = '^' . $preg_component_pattern . '$'; - } - $matches = []; - - // Find the sources. - $all_sources = array_keys($pool); - $matches = preg_grep('/' . $preg_source_pattern . '/', $all_sources); - if (count($matches) > 0) { - // If we have multiple matches and the source string wasn't a - // pattern, check if one of the matches is equal to the pattern, and - // use that, or error out. - if (count($matches) > 1 and $preg_source_pattern[0] != '^') { - if (in_array($source_pattern, $matches)) { - $matches = [$source_pattern]; - } - else { - return drush_set_error('', dt('Ambiguous source "@source", matches @matches', [ - '@source' => $source_pattern, - '@matches' => implode(', ', $matches), - ])); - } - } - // Loose the indexes preg_grep preserved. - $sources = array_values($matches); - } - else { - return drush_set_error('', dt('No @state sources match "@source"', ['@state' => $state_string, '@source' => $source_pattern])); - } - - // Now find the components. - foreach ($sources as $source) { - // Find the components. - $all_components = array_keys($pool[$source]); - // See if there's any matches. - $matches = preg_grep('/' . $preg_component_pattern . '/', $all_components); - if (count($matches) > 0) { - // If we have multiple matches and the components string wasn't a - // pattern, check if one of the matches is equal to the pattern, and - // use that, or error out. - if (count($matches) > 1 and $preg_component_pattern[0] != '^') { - if (in_array($component_pattern, $matches)) { - $matches = [$component_pattern]; - } - else { - return drush_set_error('', dt('Ambiguous component "@component", matches @matches', [ - '@component' => $component_pattern, - '@matches' => implode(', ', $matches), - ])); - } - } - if (!is_array($selected[$source])) { - $selected[$source] = []; - } - $selected[$source] += array_intersect_key($pool[$source], array_flip($matches)); - } - else { - // No matches. If the source was a pattern, just carry on, else - // error out. Allows for patterns like :*field* - if ($preg_source_pattern[0] != '^') { - return drush_set_error('', dt('No @state @source components match "@component"', [ - '@state' => $state_string, - '@component' => $component_pattern, - '@source' => $source, - ])); - } - } - } - } - - // Lastly, provide feature module information on the selected components, if - // requested. - $provided_by = []; - if ($options['provided by'] && $options['exported']) { - foreach ($selected as $source => $components) { - foreach ($components as $name => $title) { - $exported = count($components_map[$source][$name]) > 0; - if ($exported) { - $provided_by[$source . ':' . $name] = implode(', ', $components_map[$source][$name]); - } - } - } - } - - return [ - 'components' => $selected, - 'sources' => $provided_by, - ]; -} - -/** - * Provides a component to feature map (port of features_get_component_map). - */ -function _drush_features_get_component_map() { - $result = []; - /** @var \Drupal\features\FeaturesManagerInterface $manager */ - $manager = \Drupal::service('features.manager'); - // Recalc full config list without running assignments. - $config = $manager->getConfigCollection(); - $packages = $manager->getPackages(); - - foreach ($config as $item_name => $item) { - $type = $item->getType(); - $short_name = $item->getShortName(); - $name = $item->getName(); - if (!isset($result[$type][$short_name])) { - $result[$type][$short_name] = []; - } - if (!empty($item->getPackage())) { - $package = $packages[$item->getPackage()]; - $result[$type][$short_name][] = $package->getMachineName(); - } - } - - return $result; -} - -/** - * Prints a list of filtered components. - */ -function _drush_features_component_print($filtered_components) { - $rows = [[dt('Available sources')]]; - foreach ($filtered_components['components'] as $source => $components) { - foreach ($components as $name => $value) { - $row = [$source . ':' . $name]; - if (isset($filtered_components['sources'][$source . ':' . $name])) { - $row[] = dt('Provided by') . ': ' . $filtered_components['sources'][$source . ':' . $name]; - } - $rows[] = $row; - } - } - - drush_print_table($rows, TRUE); -} diff --git a/web/modules/features/features.info.yml b/web/modules/features/features.info.yml deleted file mode 100644 index 65cef8a96ca2a5d8231519bbe1f16df1b6c575d9..0000000000000000000000000000000000000000 --- a/web/modules/features/features.info.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: 'Features' -type: module -description: 'Enables administrators to package configuration into modules.' -package: Development -# core: 8.x -dependencies: - - drupal:config - - config_update:config_update - -# Information added by Drupal.org packaging script on 2018-09-09 -version: '8.x-3.8' -core: '8.x' -project: 'features' -datestamp: 1536512288 diff --git a/web/modules/features/features.install b/web/modules/features/features.install deleted file mode 100644 index 5bb46f01f314ff48308f8048bfac8482f3ca8c68..0000000000000000000000000000000000000000 --- a/web/modules/features/features.install +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/** - * @file - * Contains install and update functions for Features. - */ - -/** - * Rebuild the container to add a parameter to the features.manager service. - */ -function features_update_8300() { - // Empty update to cause a cache rebuild so that the container is rebuilt. -} - -/** - * Update existing feature bundles with new alter plugin configuration. - */ -function features_update_8301() { - foreach (\Drupal::service('entity_type.manager')->getStorage('features_bundle')->loadMultiple() as $bundle) { - $bundle = \Drupal::configFactory()->getEditable('features.bundle.' . $bundle->id()); - $assignments = $bundle->get('assignments'); - $assignments['alter'] = [ - 'core' => TRUE, - 'uuid' => TRUE, - 'user_permissions' => TRUE, - 'enabled' => TRUE, - 'weight' => 0, - ]; - $bundle->set('assignments', $assignments)->save(); - } -} diff --git a/web/modules/features/features.module b/web/modules/features/features.module deleted file mode 100644 index 3bf4bf7348140c450ca6243d8c2ad6919d5dbdce..0000000000000000000000000000000000000000 --- a/web/modules/features/features.module +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/** - * @file - * Main hooks for Features module. - */ - -use Drupal\Core\Routing\RouteMatchInterface; - -/** - * Implements hook_help(). - */ -function features_help($route_name, RouteMatchInterface $route_match) { - switch ($route_name) { - case 'help.page.features': - $output = ''; - $output .= '<h3>' . t('About') . '</h3>'; - $output .= '<p>' . t('The Features module provides a user interface for exporting bundles of configuration into modules. For more information, see the online documentation for <a href=":url">Features module</a>', [ - ':url' => 'http://drupal.org/node/2404427', - ]) . '</p>'; - return $output; - } -} - -/** - * Implements hook_file_download(). - */ -function features_file_download($uri) { - $scheme = file_uri_scheme($uri); - $target = file_uri_target($uri); - - if ($scheme == 'temporary' && $target) { - $request = \Drupal::request(); - $route = $request->attributes->get('_route'); - // Check if we were called by Features download route. - // No additional access checking needed here: route requires - // "export configuration" permission, token is validated by the controller. - // @see \Drupal\features\Controller\FeaturesController::downloadExport() - if ($route == 'features.export_download') { - return [ - 'Content-disposition' => 'attachment; filename="' . $target . '"', - ]; - } - } -} - -/** - * Implements hook_modules_installed(). - */ -function features_modules_installed($modules) { - if (!in_array('features', $modules)) { - /** @var \Drupal\features\FeaturesAssignerInterface $assigner */ - $assigner = \Drupal::service('features_assigner'); - $assigner->purgeConfiguration(); - } -} diff --git a/web/modules/features/features.routing.yml b/web/modules/features/features.routing.yml deleted file mode 100644 index 3b6c25b334487103a691a1900f9d70361a92ab32..0000000000000000000000000000000000000000 --- a/web/modules/features/features.routing.yml +++ /dev/null @@ -1,6 +0,0 @@ -features.export_download: - path: '/admin/config/development/features/download/{uri}' - defaults: - _controller: 'Drupal\features\Controller\FeaturesController::downloadExport' - requirements: - _permission: 'export configuration' diff --git a/web/modules/features/features.services.yml b/web/modules/features/features.services.yml deleted file mode 100644 index 6122f5353fc3f24940b33536eb6c36ddd0ae060f..0000000000000000000000000000000000000000 --- a/web/modules/features/features.services.yml +++ /dev/null @@ -1,38 +0,0 @@ -services: - plugin.manager.features_assignment_method: - class: Drupal\features\FeaturesAssignmentMethodManager - arguments: ['@container.namespaces', '@cache.discovery', '@module_handler'] - plugin.manager.features_generation_method: - class: Drupal\features\FeaturesGenerationMethodManager - arguments: ['@container.namespaces', '@cache.discovery', '@module_handler'] - features_assigner: - class: Drupal\features\FeaturesAssigner - arguments: ['@features.manager', '@plugin.manager.features_assignment_method', '@entity.manager', '@config.factory', '@config.storage'] - calls: - - [initFeaturesManager] - features_generator: - class: Drupal\features\FeaturesGenerator - arguments: ['@features.manager', '@plugin.manager.features_generation_method', '@features_assigner'] - calls: - - [initFeaturesManager] - features.manager: - class: Drupal\features\FeaturesManager - arguments: ['@app.root', '@entity.manager', '@config.factory', '@config.storage', '@config.manager', '@module_handler', '@features.config_update'] - - features.config_update: - class: Drupal\config_update\ConfigReverter - arguments: ['@entity.manager', '@config.storage', '@features.extension_storage', '@features.extension_optional_storage', '@config.factory', '@event_dispatcher'] - - features.extension_storage: - class: Drupal\features\FeaturesInstallStorage - arguments: ['@config.storage'] - - features.extension_optional_storage: - class: Drupal\features\FeaturesInstallStorage - arguments: ['@config.storage', 'config/optional'] - - features.config.installer: - class: Drupal\features\FeaturesConfigInstaller - decorates: config.installer - decoration_priority: 9 - arguments: ['@features.config.installer.inner', '@features.manager', '@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher'] diff --git a/web/modules/features/modules/features_ui/css/features_ui.admin.css b/web/modules/features/modules/features_ui/css/features_ui.admin.css deleted file mode 100644 index 1f8a7817893f8f97aa3549c615537cdd729427f1..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/css/features_ui.admin.css +++ /dev/null @@ -1,283 +0,0 @@ -span.features-item-list span { - background: #eee; - border-radius: 5px; - margin-right: 5px; - padding: 2px 5px; - white-space: nowrap; - line-height: 1.7em; -} - -.features-listing span.features-override, -.features-listing a.features-override { - background: #FFCE6F; - border-radius: 5px; - margin-right: 5px; - padding: 2px 5px; - white-space: nowrap; -} - -.features-listing span.features-detected, -.features-listing a.features-detected { - color:#68a; - background:#def; - border-radius: 5px; - margin-right: 5px; - padding: 2px 5px; - white-space: nowrap; -} - -.features-listing span.features-conflict, -.features-listing a.features-conflict { - color: #fff; - background-color: #c30 !important; - border-radius: 5px; - margin-right: 5px; - padding: 2px 5px; - white-space: nowrap; -} - -.features-listing span.features-moved, -.features-listing a.features-moved { - color: #fff; - background-color: #215900 !important; - border-radius: 5px; - margin-right: 5px; - padding: 2px 5px; - white-space: nowrap; -} - -.features-listing span.features-missing, -.features-listing a.features-missing { - color: #fff; - background-color: #0E5EA9 !important; - border-radius: 5px; - margin-right: 5px; - padding: 2px 5px; - white-space: nowrap; -} - -table.features-listing .column-nowrap { - white-space: nowrap; -} - -tr.features-export-header-row td { - border-top: 30px solid white; - background: #eee; - padding-top: 10px; -} - -#features-assignment-methods tr.draggable > td:nth-child(1) { - white-space: nowrap; -} - -/** Styles for Features Export/Listing page **/ -.features-listing td { - vertical-align: top; -} - -.features-listing td.feature-name { - font-size: 14px; - white-space: nowrap; -} - -.features-listing td details { - border: 0; - margin: 0; - height: 20px; -} - -.features-listing details[open] { - height: auto; - overflow: visible; - white-space: normal; -} - -.features-listing td summary { - padding: 0; - text-transform: none; - font-weight: normal; -} - -.features-listing td .features-item-label { - font-weight: bold; -} - -.features-header > div, -.features-header > input { - display: inline-block; -} - -/** Styles for Features Edit page **/ - -.fieldset-legend { - font-size: 14px; -} - -#features-export-info { - width: 49%; - float: left; - position: relative; -} -#features-export-wrapper { - width: 49%; - float: right; - clear: both; - position: relative; -} - -.form-type-checkbox.form-item-conflicts { - clear: left; -} - -div.features-export-list { - font-weight: normal; - font-size: 12px; - border: 1px solid #CCC; - border-top-width: 0; - overflow: hidden; - padding: 0 10px 0 30px; -} - -span.features-component-list span { - white-space:nowrap; - margin-right:5px; - padding:2px 5px; - background:#eee; - border-radius:5px; -} - -div.features-export-empty { - display: none; -} - -span.features-component-list span.features-conflict { - background-color: #c30 !important; - color: #fff; -} - -span.features-component-list .features-detected { - color:#68a; - background:#def; -} - -span.features-component-list .features-dependency { - color:#999; - background:#f8f8f8; -} - -#features-legend .fieldset-wrapper span { - font-style: normal; - color: black; - display: inline-block; - background: transparent; - border: 1px solid #DDD; - border-radius: 5px; - white-space: nowrap; - padding: 0 8px; - margin: 0 10px 0 0; -} -#features-export-wrapper .config-name { - color: #777; -} -#features-export-wrapper .component-detected .form-type-checkbox, -#features-legend .fieldset-wrapper .component-detected { - font-style: italic; - color:#68a; - background:#def; - border-width: 0; -} -#features-export-wrapper .component-added .form-type-checkbox, -#features-legend .fieldset-wrapper .component-added { - font-weight: bold; - background: #EEE; - border-width: 0; -} -#features-export-wrapper .component-conflict.form-type-checkbox, -#features-legend .fieldset-wrapper .component-conflict { - color: #c30 !important; - font-weight: bold !important; -} - -#features-export-wrapper .component-conflict.form-type-checkbox label, -#features-export-wrapper .component-added .form-type-checkbox label { - font-weight: bold !important; -} - -#features-filter input[size="60"].form-text { - width: 200px; -} -#features-filter .fieldset-content, -#features-filter .fieldset-wrapper, -#features-filter fieldset { - border: 0; - padding: 0; - margin: 0; -} -#features-filter fieldset legend { - display: none; -} -#features-filter label, -#features-filter input { - display: inline; - width: auto; -} -#features-filter .form-item { - float: left; - margin: 5px 0; - padding: 0; -} -#features-filter .form-item.form-type-checkbox { - margin: 5px 0; -} -#features-filter span { - float: left; - white-space: normal; - margin: 5px 5px; - padding: 0 5px; - background: transparent; - background: #EEE; - border-radius: 5px; - cursor: pointer; -} -#features-filter span:hover { - background:#def; -} - -#features-export-wrapper div.features-export-parent { - clear: both; - margin: 0 0 10px; -} - -details.features-export-component { - background: #F3F8FB; - margin: 0; - padding: 0 5px; -} -details.features-export-component summary { - white-space: nowrap; - text-transform: none; - font-weight: normal; - font-size: 14px; -} -details.features-export-component summary .component-count { - font-size: 11px; -} -details.features-export-component .details-wrapper { - padding-left: 25px; - padding-top: 0; -} - -/** Styles for Bundle assignment config form **/ -#edit-bundles-wrapper .form-item-bundle-bundle-select { - display: inline-block; -} - -#edit-bundles-wrapper #edit-bundle-remove { - display: inline-block; - font-size: 10px; -} - -/** Styles for plugin config forms **/ -.features-assignment-settings-form .fieldset-wrapper { - padding-left: 16px; -} diff --git a/web/modules/features/modules/features_ui/features_ui.admin.inc b/web/modules/features/modules/features_ui/features_ui.admin.inc deleted file mode 100644 index 0b7186252e680d6a63a895d434909dfb6564f3e3..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/features_ui.admin.inc +++ /dev/null @@ -1,175 +0,0 @@ -<?php - -/** - * @file - * Administration functions for features.module. - */ - -use Drupal\Core\Render\Element; -Use \Drupal\Component\Render\FormattableMarkup; -use Drupal\Component\Utility\Html; - -/** - * Returns HTML for the features listing form. - * - * @param array $variables - * An associative array containing: - * - form: A render element representing the form. - * - * @ingroup themeable - */ -function theme_features_listing(array $variables) { - $form = $variables['form']; - $renderer = \Drupal::service('renderer'); - - // Individual table headers. - $rows = []; - // Iterate through all the features, which are children of this element. - foreach (Element::children($form) as $key) { - // Stick the key into $module for easier access. - $element = $form[$key]; - // Create the row for the table. - $row = []; - // Add the checkbox into the first cell. - unset($element['enable']['#title']); - - $row[] = ['class' => ['checkbox'], 'data' => $renderer->render($element['enable'])]; - - // Add the module label and expand/collapse functionalty. - $id = Html::getUniqueId('feature-' . $key); - $col2 = new FormattableMarkup('<label id="@id" for="@for" class="module-name table-filter-text-source">@name</label>', - [ - '@id' => $id, - '@for' => $element['enable']['#id'], - '@name' => $renderer->render($element['name']), - ] - ); - $row[] = ['class' => ['module'], 'data' => $col2]; - - $row[] = ['class' => ['machine_name'], 'data' => $renderer->render($element['machine_name'])]; - - $description = t('@details', ['@details' => $renderer->render($element['details'])]); - $details = [ - '#type' => 'details', - '#title' => new FormattableMarkup('<span class="text">@desc</span>', [ '@desc' => $renderer->render($element['description'])]), - '#attributes' => ['id' => $element['enable']['#id'] . '-description'], - '#description' => $description, - ]; - $row[] = [ - 'class' => ['description', 'expand'], - 'data' => $renderer->render($details), - ]; - $row[] = [ - 'class' => ['feature-version'], - 'data' => $renderer->render($element['version']), - ]; - $row[] = [ - 'class' => ['feature-state'], - 'data' => $renderer->render($element['state']), - ]; - - $rows[] = ['data' => $row]; - } - - $table = [ - '#type' => 'tableselect', - '#header' => $form['#header'], - '#options' => $rows, - '#empty' => t('No Features packages available.'), - ]; - return $renderer->render($table); -} - -/** - * Prepares variables for package assignment configuration form. - * - * @param array $variables - * An associative array containing: - * - form: A render element representing the form. - */ -function template_preprocess_features_assignment_configure_form(&$variables) { - $form =& $variables['form']; - - $header = [ - t('Assignment method'), - t('Description'), - t('Enabled'), - t('Weight'), - ]; - - // If there is at least one operation enabled, show the operation column. - if ($form['#show_operations']) { - $header[] = t('Operations'); - } - - $table = [ - '#type' => 'table', - '#weight' => 5, - '#header' => $header, - '#attributes' => ['id' => 'features-assignment-methods'], - '#tabledrag' => [ - [ - 'action' => 'order', - 'relationship' => 'sibling', - 'group' => 'assignment-method-weight', - ], - ], - ]; - - foreach ($form['title'] as $id => $element) { - // Do not take form control structures. - if (is_array($element) && Element::child($id)) { - $table[$id]['#attributes']['class'][] = 'draggable'; - $table[$id]['#weight'] = $element['#weight']; - - $table[$id]['title'] = [ - '#prefix' => '<strong>', - $form['title'][$id], - '#suffix' => '</strong>', - ]; - $table[$id]['description'] = $form['description'][$id]; - $table[$id]['enabled'] = $form['enabled'][$id]; - $table[$id]['weight'] = $form['weight'][$id]; - if ($form['#show_operations']) { - $table[$id]['operation'] = $form['operation'][$id]; - } - // Unset to prevent rendering along with children. - unset($form['title'][$id]); - unset($form['description'][$id]); - unset($form['enabled'][$id]); - unset($form['weight'][$id]); - unset($form['operation'][$id]); - } - } - - // For some reason, the #weight is not being handled by drupal_render. - // So we remove the actions and then put them back into the form after the - // table. - $actions = $form['actions']; - unset($form['actions']); - $form['table'] = $table; - $form['actions'] = $actions; -} - -/** - * Themes individual items in an item list. - */ -function theme_features_items(array $variables) { - $items = $variables['items']; - - $list = []; - foreach ($items as $item) { - $class = !empty($item['class']) ? $item['class'] : ''; - $list[] = '<span class="features-item ' . $class . '" title="' . $item['name'] . '">' . $item['label'] . '</span>'; - } - - return '<span class="features-item-list">' . implode(' ', $list) . '</span>'; -} - -/** - * Themes the assignment form. - */ -function theme_assignment_form(array $variables) { - $renderer = \Drupal::service('renderer'); - return $renderer->render($variables['form']); -} diff --git a/web/modules/features/modules/features_ui/features_ui.info.yml b/web/modules/features/modules/features_ui/features_ui.info.yml deleted file mode 100644 index d78b3f7722622573240acda9f88a4cf7c2261b52..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/features_ui.info.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Features UI -type: module -description: 'Provides the user interface for Features.' -package: Development -# core: 8.x -configure: features.assignment -dependencies: - - features:features - -# Information added by Drupal.org packaging script on 2018-09-09 -version: '8.x-3.8' -core: '8.x' -project: 'features' -datestamp: 1536512288 diff --git a/web/modules/features/modules/features_ui/features_ui.libraries.yml b/web/modules/features/modules/features_ui/features_ui.libraries.yml deleted file mode 100644 index 07a4d490aa54707a03833bf5ca336a35ce0816ac..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/features_ui.libraries.yml +++ /dev/null @@ -1,11 +0,0 @@ -drupal.features_ui.admin: - version: VERSION - css: - theme: - css/features_ui.admin.css: {} - js: - js/features_ui.admin.js: {} - dependencies: - - core/jquery - - core/drupal - - core/drupalSettings diff --git a/web/modules/features/modules/features_ui/features_ui.links.action.yml b/web/modules/features/modules/features_ui/features_ui.links.action.yml deleted file mode 100644 index 93a37b453cce42b8b3492dfd8527f43c5d1d8452..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/features_ui.links.action.yml +++ /dev/null @@ -1,5 +0,0 @@ -features_ui.feature_add: - route_name: features.edit - title: 'Create new feature' - appears_on: - - features.export diff --git a/web/modules/features/modules/features_ui/features_ui.links.menu.yml b/web/modules/features/modules/features_ui/features_ui.links.menu.yml deleted file mode 100644 index 379a3e4cf28039a8339bc6429c7f1ccb0b1b7ee5..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/features_ui.links.menu.yml +++ /dev/null @@ -1,5 +0,0 @@ -features.export: - title: 'Features' - description: 'Package your configuration into feature modules.' - route_name: features.export - parent: system.admin_config_development diff --git a/web/modules/features/modules/features_ui/features_ui.links.task.yml b/web/modules/features/modules/features_ui/features_ui.links.task.yml deleted file mode 100644 index fb8d6360d9dcec80fc14a620311814beff053194..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/features_ui.links.task.yml +++ /dev/null @@ -1,14 +0,0 @@ -features.export: - route_name: features.export - title: 'Features' - base_route: features.export - -features.assignment: - route_name: features.assignment - title: 'Configure Bundles' - base_route: features.export - -features.diff: - route_name: features.diff - title: 'Differences' - base_route: features.export diff --git a/web/modules/features/modules/features_ui/features_ui.module b/web/modules/features/modules/features_ui/features_ui.module deleted file mode 100644 index 1860427bd40ff4d4fec4eb13948f6fb30e7e29a2..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/features_ui.module +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/** - * @file - * Allows site administrators to modify configuration. - */ - -use Drupal\Core\Routing\RouteMatchInterface; - -/** - * Implements hook_help(). - */ -function features_ui_help($route_name, RouteMatchInterface $route_match) { - switch ($route_name) { - case 'features.assignment': - $output = ''; - $output .= '<p>' . t('Bundles are used to collect together groups of features. A bundle provides a shared <a href=":namespace">namespace</a> for all features included in it, which prevents conflicts and helps distinguish your features from those produced for other purposes. Common uses of bundles include:', [':namespace' => 'http://en.wikipedia.org/wiki/Namespace']); - $output .= '<ul>'; - $output .= '<li>' . t('Custom features for use on a particular site.') . '</li>'; - $output .= '<li>' . t('The features of a given <a href=":distributions">distribution</a>.', [':distributions' => 'https://www.drupal.org/documentation/build/distributions']) . '</li>'; - $output .= '</ul></p>'; - $output .= '<p>' . t('Use the form below to manage bundles. Each bundle comes with a set of assignment methods. By configuring and ordering the assignment methods, you can set the defaults for what does and doesn\'t get packaged into features for your bundle. Use the <em>Bundle</em> select to choose which bundle to edit, or chose <em>--New--</em> to create a new bundle. The <em>Default</em> bundle does not include a namespace and cannot be deleted.') . '</p>'; - return $output; - - case 'features.export': - $output = ''; - $output .= '<p>' . t('Export packages of configuration into modules.') . '</p>'; - return $output; - } -} - -/** - * Implements hook_theme(). - */ -function features_ui_theme() { - return [ - 'features_listing' => [ - 'render element' => 'form', - 'file' => 'features_ui.admin.inc', - 'function' => 'theme_features_listing', - ], - 'features_assignment_configure_form' => [ - 'render element' => 'form', - 'file' => 'features_ui.admin.inc', - 'function' => 'theme_assignment_form', - ], - 'features_items' => [ - 'variables' => [ - 'items' => [], - ], - 'file' => 'features_ui.admin.inc', - 'function' => 'theme_features_items', - ], - ]; -} diff --git a/web/modules/features/modules/features_ui/features_ui.routing.yml b/web/modules/features/modules/features_ui/features_ui.routing.yml deleted file mode 100644 index 9343aee071cdc7d6bc11a91f6258167ba6eca3f6..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/features_ui.routing.yml +++ /dev/null @@ -1,104 +0,0 @@ -features.export: - path: '/admin/config/development/features' - defaults: - _form: '\Drupal\features_ui\Form\FeaturesExportForm' - _title: 'Features' - requirements: - _permission: 'export configuration' - -features.assignment: - path: '/admin/config/development/features/bundle/{bundle_name}' - defaults: - _form: '\Drupal\features_ui\Form\AssignmentConfigureForm' - _title: 'Bundle assignment' - bundle_name: NULL - requirements: - _permission: 'administer site configuration' - -features.assignment_alter: - path: '/admin/config/development/features/bundle/_alter/{bundle_name}' - defaults: - _form: '\Drupal\features_ui\Form\AssignmentAlterForm' - _title: 'Configure package configuration altering' - bundle_name: NULL - requirements: - _permission: 'administer site configuration' - -features.assignment_base: - path: '/admin/config/development/features/bundle/_base/{bundle_name}' - defaults: - _form: '\Drupal\features_ui\Form\AssignmentBaseForm' - _title: 'Configure base package assignment' - bundle_name: NULL - requirements: - _permission: 'administer site configuration' - -features.assignment_core: - path: '/admin/config/development/features/bundle/_core/{bundle_name}' - defaults: - _form: '\Drupal\features_ui\Form\AssignmentCoreForm' - _title: 'Configure core package assignment' - bundle_name: NULL - requirements: - _permission: 'administer site configuration' - -features.assignment_exclude: - path: '/admin/config/development/features/bundle/_exclude/{bundle_name}' - defaults: - _form: '\Drupal\features_ui\Form\AssignmentExcludeForm' - _title: 'Configure package exclusion' - bundle_name: NULL - requirements: - _permission: 'administer site configuration' - -features.assignment_optional: - path: '/admin/config/development/features/bundle/_optional/{bundle_name}' - defaults: - _form: '\Drupal\features_ui\Form\AssignmentOptionalForm' - _title: 'Configure optional package assignment' - bundle_name: NULL - requirements: - _permission: 'administer site configuration' - -features.assignment_profile: - path: '/admin/config/development/features/bundle/_profile/{bundle_name}' - defaults: - _form: '\Drupal\features_ui\Form\AssignmentProfileForm' - _title: 'Configure profile package assignment' - bundle_name: NULL - requirements: - _permission: 'administer site configuration' - -features.assignment_site: - path: '/admin/config/development/features/bundle/_site/{bundle_name}' - defaults: - _form: '\Drupal\features_ui\Form\AssignmentSiteForm' - _title: 'Configure site package assignment' - bundle_name: NULL - requirements: - _permission: 'administer site configuration' - -features.edit: - path: '/admin/config/development/features/edit/{featurename}' - defaults: - _form: '\Drupal\features_ui\Form\FeaturesEditForm' - _title: 'Edit' - featurename: '' - requirements: - _permission: 'administer site configuration' - -features.diff: - path: '/admin/config/development/features/diff/{featurename}' - defaults: - _form: '\Drupal\features_ui\Form\FeaturesDiffForm' - _title: 'Differences' - featurename: '' - requirements: - _permission: 'administer site configuration' - -features.detect: - path: '/features/api/detect/{name}' - defaults: - _controller: '\Drupal\features_ui\Controller\FeaturesUIController::detect' - requirements: - _permission: 'administer site configuration' diff --git a/web/modules/features/modules/features_ui/js/features_ui.admin.js b/web/modules/features/modules/features_ui/js/features_ui.admin.js deleted file mode 100644 index d4019681b1a40acf708906e39e182454c5f78c57..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/js/features_ui.admin.js +++ /dev/null @@ -1,401 +0,0 @@ -/** - * jQuery.fn.sortElements - * -------------- - * @param Function comparator: - * Exactly the same behaviour as [1,2,3].sort(comparator) - * - * @param Function getSortable - * A function that should return the element that is - * to be sorted. The comparator will run on the - * current collection, but you may want the actual - * resulting sort to occur on a parent or another - * associated element. - * - * E.g. $('td').sortElements(comparator, function(){ - * return this.parentNode; - * }) - * - * The <td>'s parent (<tr>) will be sorted instead - * of the <td> itself. - * - * Credit: http://james.padolsey.com/javascript/sorting-elements-with-jquery/ - * - */ -jQuery.fn.sortElements = (function () { - - "use strict"; - - var sort = [].sort; - - return function (comparator, getSortable) { - - getSortable = getSortable || function () {return this;}; - - var placements = this.map(function () { - - var sortElement = getSortable.call(this); - var parentNode = sortElement.parentNode; - - // Since the element itself will change position, we have - // to have some way of storing its original position in - // the DOM. The easiest way is to have a 'flag' node: - var nextSibling = parentNode.insertBefore( - document.createTextNode(''), - sortElement.nextSibling - ); - - return function () { - - if (parentNode === this) { - throw new Error( - "You can't sort elements if any one is a descendant of another." - ); - } - - // Insert before flag: - parentNode.insertBefore(this, nextSibling); - // Remove flag: - parentNode.removeChild(nextSibling); - - }; - - }); - - return sort.call(this, comparator).each(function (i) { - placements[i].call(getSortable.call(this)); - }); - - }; - -})(); - -(function ($) { - - "use strict"; - - Drupal.behaviors.features = { - attach: function (context) { - - // mark any conflicts with a class - if ((typeof drupalSettings.features !== 'undefined') && (typeof drupalSettings.features.conflicts !== 'undefined')) { - // for (var configType in drupalSettings.features.conflicts) { - if (drupalSettings.features.conflicts) { - var configConflicts = drupalSettings.features.conflicts; - $('#features-export-wrapper input[type=checkbox]', context).each(function () { - if (!$(this).hasClass('features-checkall')) { - var key = $(this).attr('name'); - var matches = key.match(/^([^\[]+)(\[.+\])?\[(.+)\]\[(.+)\]$/); - var component = matches[1]; - var item = matches[4]; - if ((component in configConflicts) && (item in configConflicts[component])) { - $(this).parent().addClass('component-conflict'); - } - } - }); - } - //} - } - - function _checkAll(value) { - if (value) { - $('#features-export-wrapper .component-select input[type=checkbox]:visible', context).each(function () { - var move_id = $(this).attr('id'); - $(this).click(); - $('#'+ move_id).prop('checked', true); - }); - } - else { - $('#features-export-wrapper .component-added input[type=checkbox]:visible', context).each(function () { - var move_id = $(this).attr('id'); - $(this).click(); - $('#'+ move_id).prop('checked', false); - }); - } - } - - function updateComponentCountInfo(item, section) { - var parent; - - switch (section) { - case 'select': - parent = $(item).closest('.features-export-list').siblings('.features-export-component'); - $('.component-count', parent).text(function (index, text) { - return +text + 1; - } - ); - break; - case 'added': - case 'detected': - parent = $(item).closest('.features-export-component'); - $('.component-count', parent).text(function (index, text) { - return text - 1; - }); - } - } - - function moveCheckbox(item, section, value) { - updateComponentCountInfo(item, section); - var curParent = item; - if ($(item).hasClass('form-type-checkbox')) { - item = $(item).children('input[type=checkbox]'); - } - else { - curParent = $(item).parents('.form-type-checkbox'); - } - var newParent = $(curParent).parents('.features-export-parent').find('.component-'+section+' .form-checkboxes'); - $(curParent).detach(); - $(curParent).appendTo(newParent); - var list = ['select', 'added', 'detected', 'included']; - for (var i in list) { - if (list[i]) { - $(curParent).removeClass('component-' + list[i]); - $(item).removeClass('component-' + list[i]); - } - } - $(curParent).addClass('component-'+section); - $(item).addClass('component-'+section); - if (value) { - $(item).attr('checked', 'checked'); - } - else { - $(item).removeAttr('checked'); - } - $(newParent).parents('.component-list').removeClass('features-export-empty'); - - // re-sort new list of checkboxes based on labels - $(newParent).find('label').sortElements( - function (a, b) { - return $(a).text() > $(b).text() ? 1 : -1; - }, - function () { - return this.parentNode; - } - ); - } - - // provide timer for auto-refresh trigger - var timeoutID = 0; - var inTimeout = 0; - function _triggerTimeout() { - timeoutID = 0; - _updateDetected(); - } - function _resetTimeout() { - inTimeout++; - // if timeout is already active, reset it - if (timeoutID !== 0) { - window.clearTimeout(timeoutID); - if (inTimeout > 0) { inTimeout--; } - } - timeoutID = window.setTimeout(_triggerTimeout, 500); - } - - function _updateDetected() { - if (!drupalSettings.features.autodetect) { return; } - // query the server for a list of components/items in the feature and update - // the auto-detected items - var items = []; // will contain a list of selected items exported to feature - var components = {}; // contains object of component names that have checked items - $('#features-export-wrapper input[type=checkbox]:checked', context).each(function () { - if (!$(this).hasClass('features-checkall')) { - var key = $(this).attr('name'); - var matches = key.match(/^([^\[]+)(\[.+\])?\[(.+)\]\[(.+)\]$/); - components[matches[1]] = matches[1]; - if (!$(this).hasClass('component-detected')) { - items.push(key); - } - } - }); - var featureName = $('#edit-machine-name').val(); - if (featureName === '') { - featureName = '*'; - } - - var url = Drupal.url('features/api/detect/' + featureName); - var excluded = drupalSettings.features.excluded; - var required = drupalSettings.features.required; - var postData = {'items': items, 'excluded': excluded, 'required': required}; - jQuery.post(url, postData, function (data) { - if (inTimeout > 0) { inTimeout--; } - // if we have triggered another timeout then don't update with old results - if (inTimeout === 0) { - // data is an object keyed by component listing the exports of the feature - for (var component in data) { - if (data[component]) { - var itemList = data[component]; - $('#features-export-wrapper .component-' + component + ' input[type=checkbox]', context).each(function () { - var key = $(this).attr('value'); - // first remove any auto-detected items that are no longer in component - if ($(this).hasClass('component-detected')) { - if (!(key in itemList)) { - moveCheckbox(this, 'select', false); - } - } - // next, add any new auto-detected items - else if ($(this).hasClass('component-select')) { - if (key in itemList) { - moveCheckbox(this, 'detected', itemList[key]); - $(this).prop('checked', true); - $(this).parent().show(); // make sure it's not hidden from filter - } - } - }); - } - } - // loop over all selected components and check for any that have been completely removed - for (var selectedComponent in components) { - if ((data == null) || !(selectedComponent in data)) { - $('#features-export-wrapper .component-' + selectedComponent + ' input[type=checkbox].component-detected', context).each(moveCheckbox(this, 'select', false)); - } - } - } - }, "json"); - } - - // Handle component selection UI - $('#features-export-wrapper input[type=checkbox]', context).click(function () { - _resetTimeout(); - if ($(this).hasClass('component-select')) { - moveCheckbox(this, 'added', true); - } - else if ($(this).hasClass('component-included')) { - moveCheckbox(this, 'added', false); - } - else if ($(this).hasClass('component-added')) { - if ($(this).is(':checked')) { - moveCheckbox(this, 'included', true); - } - else { - moveCheckbox(this, 'select', false); - } - } - }); - - // Handle select/unselect all - $('#features-filter .features-checkall.form-checkbox', context).click(function () { - if ($(this).prop('checked')) { - _checkAll(true); - $(this).next().html(Drupal.t('Deselect all')); - } - else { - _checkAll(false); - $(this).next().html(Drupal.t('Select all')); - } - _resetTimeout(); - }); - - // Handle filtering - - // provide timer for auto-refresh trigger - var filterTimeoutID = 0; - function _triggerFilterTimeout() { - filterTimeoutID = 0; - _updateFilter(); - } - function _resetFilterTimeout() { - // if timeout is already active, reset it - if (filterTimeoutID !== 0) { - window.clearTimeout(filterTimeoutID); - filterTimeoutID = null; - } - filterTimeoutID = window.setTimeout(_triggerFilterTimeout, 200); - } - function _updateFilter() { - var filter = $('#features-filter input').val(); - var regex = new RegExp(filter, 'i'); - // collapse fieldsets - var newState = {}; - var currentState = {}; - $('#features-export-wrapper details.features-export-component', context).each(function () { - // expand parent fieldset - var section = $(this).attr('id'); - var details = $(this); - - currentState[section] = details.prop('open'); - if (!(section in newState)) { - newState[section] = false; - } - - details.find('.form-checkboxes label').each(function () { - if (filter === '') { - // collapse the section, but make checkbox visible - if (currentState[section]) { - details.prop('open', false); - currentState[section] = false; - } - $(this).parent().show(); - } - else if ($(this).text().match(regex)) { - $(this).parent().show(); - newState[section] = true; - } - else { - $(this).parent().hide(); - } - }); - }); - for (var section in newState) { - if (currentState[section] !== newState[section]) { - if (newState[section]) { - $('#'+section).prop('open', true); - } - else { - $('#'+section).prop('open', false); - } - } - } - } - $('#features-filter input', context).bind("input", function () { - _resetFilterTimeout(); - }); - $('#features-filter .features-filter-clear', context).click(function () { - $('#features-filter input').val(''); - _updateFilter(); - }); - - // show the filter bar - $('#features-filter', context).removeClass('element-invisible'); - - // handle Package selection checkboxes in the Differences page - $('.features-diff-listing .features-diff-header input.form-checkbox', context).click(function () { - var value = $(this).prop('checked'); - $('.features-diff-listing .diff-'+$(this).prop('value')+' input.form-checkbox', context).each(function () { - $(this).prop('checked', value); - if (value) { - $(this).parents('tr').addClass('selected'); - } - else { - $(this).parents('tr').removeClass('selected'); - } - }); - }); - - // handle special theming of headers in tableselect - $('td.features-export-header-row', context).each(function () { - var row = $(this).parent('tr'); - row.addClass('features-export-header-row'); - var checkbox = row.find('td input:checkbox'); - if (checkbox.length) { - checkbox.hide(); - } - }); - - // handle clicking anywhere in row on Differences page - $('.features-diff-listing tr td:nth-child(2)', context).click(function () { - var checkbox = $(this).parent().find('td input:checkbox'); - checkbox.prop('checked', !checkbox.prop('checked')).triggerHandler('click'); - if (checkbox.prop('checked')) { - $(this).parents('tr').addClass('selected'); - } - else { - $(this).parents('tr').removeClass('selected'); - } - }); - $('.features-diff-listing thead th:nth-child(2)', context).click(function () { - var checkbox = $(this).parent().find('th input:checkbox'); - checkbox.click(); - }); - } - }; - -})(jQuery); diff --git a/web/modules/features/modules/features_ui/src/Controller/FeaturesUIController.php b/web/modules/features/modules/features_ui/src/Controller/FeaturesUIController.php deleted file mode 100644 index 786a51cd05de6b5f25adbab112823841e068e853..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Controller/FeaturesUIController.php +++ /dev/null @@ -1,193 +0,0 @@ -<?php - -namespace Drupal\features_ui\Controller; - -use Drupal\Core\DependencyInjection\ContainerInjectionInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\JsonResponse; -use Drupal\features\FeaturesManagerInterface; -use Drupal\features\FeaturesAssignerInterface; - -/** - * Returns ajax responses for the Features UI. - */ -class FeaturesUIController implements ContainerInjectionInterface { - - /** - * The features manager. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * The package assigner. - * - * @var array - */ - protected $assigner; - - /** - * Constructs a new FeaturesUIController object. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - */ - public function __construct(FeaturesManagerInterface $features_manager, FeaturesAssignerInterface $assigner) { - $this->featuresManager = $features_manager; - $this->assigner = $assigner; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('features.manager'), - $container->get('features_assigner') - ); - } - - /** - * Returns a list of auto-detected config items for a feature. - * - * @param string $name - * Short machine name of feature to process. - * - * @return array - * List of auto-detected config items, keyed by type and short name. - */ - public function detect($name) { - $detected = []; - $this->assigner->assignConfigPackages(); - $config_collection = $this->featuresManager->getConfigCollection(); - - $items = $_POST['items']; - if (!empty($items)) { - $excluded = (!empty($_POST['excluded'])) ? $_POST['excluded'] : []; - $selected = []; - foreach ($items as $key) { - preg_match('/^([^\[]+)(\[.+\])?\[(.+)\]\[(.+)\]$/', $key, $matches); - if (!empty($matches[1]) && !empty($matches[4])) { - $component = $matches[1]; - $item = $this->domDecode($matches[4]); - if (!isset($excluded[$component][$item])) { - $selected[] = $this->featuresManager->getFullName($component, $item); - } - } - } - $detected = !empty($selected) ? $this->getConfigDependents($selected, $name) : []; - $detected = array_merge($detected, $selected); - } - - $result = []; - foreach ($detected as $config_name) { - $item = $config_collection[$config_name]; - $result[$item->getType()][$item->getShortName()] = $item->getName(); - } - return new JsonResponse($result); - } - - /** - * Returns the configuration dependent on given items. - * - * @param array $item_names - * An array of item names. - * @param string $package_name - * Short machine name of feature to process. - * - * @return array - * An array of config items. - */ - protected function getConfigDependents(array $item_names, $package_name) { - $result = []; - $config_collection = $this->featuresManager->getConfigCollection(); - $packages = $this->featuresManager->getPackages(); - $settings = $this->featuresManager->getSettings(); - $allow_conflicts = $settings->get('conflicts'); - - if (empty($item_names)) { - $item_names = array_keys($config_collection); - } - - // Add any existing auto-detected items already in the package config - $this->package = $packages[$package_name]; - $package_config = isset($this->package) ? $this->package->getConfig() : []; - $package_config = !empty($package_config) ? array_unique(array_merge($package_config, $item_names)) : $item_names; - foreach ($package_config as $config_name) { - if (!$config_collection[$config_name]->getPackageExcluded()) { - $result[] = $config_name; - } - } - - // Now add dependents of the items selected - foreach ($item_names as $item_name) { - if ($config_collection[$item_name]->getPackage()) { - foreach ($config_collection[$item_name]->getDependents() as $dependent_item_name) { - if (isset($config_collection[$dependent_item_name])) { - $allow = TRUE; - if (!$allow_conflicts && $config_collection[$dependent_item_name]->getPackage()) { - if ($packages[$config_collection[$dependent_item_name]->getPackage()]) { - $allow = ($packages[$config_collection[$dependent_item_name]->getPackage()]->getStatus() == FeaturesManagerInterface::STATUS_NO_EXPORT) - || ($config_collection[$item_name]->getPackage() == $config_collection[$dependent_item_name]->getPackage()); - } - } - if ($allow) { - $result[] = $dependent_item_name; - } - } - } - } - } - return $result; - } - - /** - * Encodes a given key. - * - * @param string $key - * The key to encode. - * - * @return string - * The encoded key. - */ - protected function domEncode($key) { - $replacements = $this->domEncodeMap(); - return strtr($key, $replacements); - } - - /** - * Decodes a given key. - * - * @param string $key - * The key to decode. - * - * @return string - * The decoded key. - */ - protected function domDecode($key) { - $replacements = array_flip($this->domEncodeMap()); - return strtr($key, $replacements); - } - - /** - * Returns encoding map for decode and encode options. - * - * @return array - * An encoding map. - */ - protected function domEncodeMap() { - return [ - ':' => '__' . ord(':') . '__', - '/' => '__' . ord('/') . '__', - ',' => '__' . ord(',') . '__', - '.' => '__' . ord('.') . '__', - '<' => '__' . ord('<') . '__', - '>' => '__' . ord('>') . '__', - '%' => '__' . ord('%') . '__', - ')' => '__' . ord(')') . '__', - '(' => '__' . ord('(') . '__', - ]; - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentAlterForm.php b/web/modules/features/modules/features_ui/src/Form/AssignmentAlterForm.php deleted file mode 100644 index 462ee0ba5fb62d71d61625346e675e87644f3d4f..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentAlterForm.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Configures the selected configuration assignment method for this site. - */ -class AssignmentAlterForm extends AssignmentFormBase { - - const METHOD_ID = 'alter'; - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_assignment_alter_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) { - $this->currentBundle = $this->assigner->loadBundle($bundle_name); - - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - $core_setting = $settings['core']; - $uuid_setting = $settings['uuid']; - $user_permissions_setting = $settings['user_permissions']; - - $form['core'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Strip out <em>_core</em> property.'), - '#default_value' => $core_setting, - '#description' => $this->t('Select this option to remove the <em>_core</em> configuration property on export. This property is added by Drupal core when configuration is installed.'), - ]; - - $form['uuid'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Strip out <em>uuid</em> property.'), - '#default_value' => $uuid_setting, - '#description' => $this->t('Select this option to remove the <em>uuid</em> configuration property on export. This property is added by Drupal core when configuration is installed.'), - ]; - - $form['user_permissions'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Strip out user permissions.'), - '#default_value' => $user_permissions_setting, - '#description' => $this->t('Select this option to remove permissions from user roles on export.'), - ]; - - $this->setActions($form, self::METHOD_ID); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Merge in selections. - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - $settings = array_merge($settings, [ - 'core' => $form_state->getValue('core'), - 'uuid' => $form_state->getValue('uuid'), - 'user_permissions' => $form_state->getValue('user_permissions'), - ]); - - $this->currentBundle->setAssignmentSettings(self::METHOD_ID, $settings)->save(); - - $this->setRedirect($form_state); - drupal_set_message($this->t('Package assignment configuration saved.')); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentBaseForm.php b/web/modules/features/modules/features_ui/src/Form/AssignmentBaseForm.php deleted file mode 100644 index 44f8022176f321231e0834815a08a66bac6fac7c..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentBaseForm.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Configures the selected configuration assignment method for this site. - */ -class AssignmentBaseForm extends AssignmentFormBase { - - const METHOD_ID = 'base'; - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_assignment_base_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) { - $this->currentBundle = $this->assigner->loadBundle($bundle_name); - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - - // Pass the last argument to limit the select to config entity types that - // provide bundles for other entity types. - $this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('base'), TRUE); - // Pass the last argument to limit the select to content entity types do - // not have config entity provided bundles, thus avoiding duplication with - // the config type select options. - $this->setContentTypeSelect($form, $settings['types']['content'], $this->t('base'), TRUE); - - $this->setActions($form, self::METHOD_ID); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - $form_state->setValue('types', array_map('array_filter', $form_state->getValue('types'))); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Merge in types selections. - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - $settings['types'] = $form_state->getValue('types'); - $this->currentBundle->setAssignmentSettings(self::METHOD_ID, $settings)->save(); - $this->setRedirect($form_state); - - drupal_set_message($this->t('Package assignment configuration saved.')); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentConfigureForm.php b/web/modules/features/modules/features_ui/src/Form/AssignmentConfigureForm.php deleted file mode 100644 index 44630827522560299cd53cafe80dd57bbd1c4ca1..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentConfigureForm.php +++ /dev/null @@ -1,445 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Component\Utility\Html; -use Drupal\Component\Utility\Unicode; -use Drupal\features\FeaturesManagerInterface; -use Drupal\features\FeaturesAssignerInterface; -use Drupal\features\FeaturesBundleInterface; -use Drupal\Core\Form\FormBase; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Url; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Configures the configuration assignment methods for this site. - */ -class AssignmentConfigureForm extends FormBase { - - /** - * Bundle select value that should trigger a new bundle to be created. - */ - const NEW_BUNDLE_SELECT_VALUE = 'new'; - - /** - * The features manager. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * The package assigner. - * - * @var \Drupal\features\FeaturesAssignerInterface - */ - protected $assigner; - - /** - * Constructs a AssignmentConfigureForm object. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - * @param \Drupal\features\FeaturesAssignerInterface $assigner - * The configuration assignment methods manager. - */ - public function __construct(FeaturesManagerInterface $features_manager, FeaturesAssignerInterface $assigner) { - $this->featuresManager = $features_manager; - $this->assigner = $assigner; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('features.manager'), - $container->get('features_assigner') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_assignment_configure_form'; - } - - /** - * Load the values from the bundle into the user input. - * Used during Ajax callback since updating #default_values is ignored. - * @param $bundle_name - * @param \Drupal\Core\Form\FormStateInterface $form_state - */ - protected function loadBundleValues($bundle_name, FormStateInterface &$form_state, $current_bundle, $enabled_methods, $methods_weight) { - $input = $form_state->getUserInput(); - if ($bundle_name == self::NEW_BUNDLE_SELECT_VALUE) { - $input['bundle']['name'] = ''; - $input['bundle']['machine_name'] = ''; - $input['bundle']['description'] = ''; - $input['bundle']['is_profile'] = NULL; - $input['bundle']['profile_name'] = ''; - } - else { - $input['bundle']['name'] = $current_bundle->getName(); - $input['bundle']['machine_name'] = $current_bundle->getMachineName(); - $input['bundle']['description'] = $current_bundle->getDescription(); - $input['bundle']['is_profile'] = $current_bundle->isProfile() ? 1 : null; - $input['bundle']['profile_name'] = $current_bundle->isProfile() ? $current_bundle->getProfileName() : ''; - } - - foreach ($methods_weight as $method_id => $weight) { - $enabled = isset($enabled_methods[$method_id]); - $input['weight'][$method_id] = $weight; - $input['enabled'][$method_id] = $enabled ? 1 : null; - } - - $form_state->setUserInput($input); - } - - /** - * Detects if an element triggered the form submission via Ajax. - * TODO: SHOULDN'T NEED THIS! BUT DRUPAL IS CALLING buildForm AFTER THE - * BUNDLE AJAX IS SELECTED AND DOESN'T HAVE getTriggeringElement() SET YET. - */ - protected function elementTriggeredScriptedSubmission(FormStateInterface &$form_state) { - $input = $form_state->getUserInput(); - if (!empty($input['_triggering_element_name'])) { - return $input['_triggering_element_name']; - } - return ''; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) { - $load_values = FALSE; - $trigger = $form_state->getTriggeringElement(); - // TODO: See if there is a Drupal Core issue for this. - // Sometimes the first ajax call on the page causes buildForm to be called - // twice! First time form_state->getTriggeringElement is NOT SET, but - // the form_state['input'] shows the _triggering_element_name. Then the - // SECOND time it is called the getTriggeringElement is fine. - $real_trigger = $this->elementTriggeredScriptedSubmission($form_state); - if (!isset($trigger) && ($real_trigger == 'bundle[bundle_select]')) { - $input = $form_state->getUserInput(); - $bundle_name = $input['bundle']['bundle_select']; - if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE) { - $this->assigner->setCurrent($this->assigner->getBundle($bundle_name)); - } - $load_values = TRUE; - } - elseif ($trigger['#name'] == 'bundle[bundle_select]') { - $bundle_name = $form_state->getValue(['bundle', 'bundle_select']); - if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE) { - $this->assigner->setCurrent($this->assigner->getBundle($bundle_name)); - } - $load_values = TRUE; - } - elseif ($trigger['#name'] == 'removebundle') { - $current_bundle = $this->assigner->loadBundle($bundle_name); - $bundle_name = $current_bundle->getMachineName(); - $this->assigner->removeBundle($bundle_name); - return $this->redirect('features.assignment', ['']); - } - if (!isset($current_bundle)) { - switch ($bundle_name) { - // If no bundle is selected, use the current one. - case NULL: - $current_bundle = $this->assigner->loadBundle(); - $bundle_name = $current_bundle->getMachineName(); - break; - case self::NEW_BUNDLE_SELECT_VALUE: - $current_bundle = $this->assigner->loadBundle(FeaturesBundleInterface::DEFAULT_BUNDLE); - break; - default: - $current_bundle = $this->assigner->loadBundle($bundle_name); - break; - } - } - - $enabled_methods = $current_bundle->getEnabledAssignments(); - $methods_weight = $current_bundle->getAssignmentWeights(); - - // Add missing data to the methods lists. - $assignment_info = $this->assigner->getAssignmentMethods(); - foreach ($assignment_info as $method_id => $method) { - if (!isset($methods_weight[$method_id])) { - $methods_weight[$method_id] = isset($method['weight']) ? $method['weight'] : 0; - } - } - // Order methods list by weight. - asort($methods_weight); - - if ($load_values) { - $this->loadBundleValues($bundle_name, $form_state, $current_bundle, $enabled_methods, $methods_weight); - } - - $form = [ - '#attached' => [ - 'library' => [ - // Provides the copyFieldValue behavior invoked below. - 'system/drupal.system', - 'features_ui/drupal.features_ui.admin', - ], - ], - // '#attributes' => array('class' => 'edit-bundles-wrapper'), - '#tree' => TRUE, - '#show_operations' => FALSE, - 'weight' => ['#tree' => TRUE], - '#prefix' => '<div id="edit-bundles-wrapper">', - '#suffix' => '</div>', - ]; - - $form['bundle'] = [ - '#type' => 'fieldset', - '#title' => $this->t('Bundle'), - '#tree' => TRUE, - '#weight' => -9, - ]; - - if ($bundle_name == self::NEW_BUNDLE_SELECT_VALUE) { - $default_values = [ - 'bundle_select' => self::NEW_BUNDLE_SELECT_VALUE, - 'name' => '', - 'machine_name' => '', - 'description' => '', - 'is_profile' => FALSE, - 'profile_name' => '', - ]; - } - else { - $default_values = [ - 'bundle_select' => $current_bundle->getMachineName(), - 'name' => $current_bundle->getName(), - 'machine_name' => $current_bundle->getMachineName(), - 'description' => $current_bundle->getDescription(), - 'is_profile' => $current_bundle->isProfile(), - 'profile_name' => $current_bundle->getProfileName(), - ]; - } - $form['bundle']['bundle_select'] = [ - '#title' => $this->t('Bundle'), - '#title_display' => 'invisible', - '#type' => 'select', - '#options' => [self::NEW_BUNDLE_SELECT_VALUE => $this->t('--New--')] + $this->assigner->getBundleOptions(), - '#default_value' => $default_values['bundle_select'], - '#ajax' => [ - 'callback' => '::updateForm', - 'wrapper' => 'edit-bundles-wrapper', - ], - ]; - - // Don't show the remove button for the default bundle or when adding a new - // bundle. - if ($bundle_name != self::NEW_BUNDLE_SELECT_VALUE && !$current_bundle->isDefault()) { - $form['bundle']['remove'] = [ - '#type' => 'button', - '#name' => 'removebundle', - '#value' => $this->t('Remove bundle'), - ]; - } - - $form['bundle']['name'] = [ - '#title' => $this->t('Bundle name'), - '#type' => 'textfield', - '#description' => $this->t('A unique human-readable name of this bundle.'), - '#default_value' => $default_values['name'], - '#required' => TRUE, - '#disabled' => $bundle_name == FeaturesBundleInterface::DEFAULT_BUNDLE, - ]; - - // Don't allow changing the default bundle machine name. - if ($bundle_name == FeaturesBundleInterface::DEFAULT_BUNDLE) { - $form['bundle']['machine_name'] = [ - '#type' => 'value', - '#value' => $default_values['machine_name'], - ]; - } - else { - $form['bundle']['machine_name'] = [ - '#title' => $this->t('Machine name'), - '#type' => 'machine_name', - '#required' => TRUE, - '#default_value' => $default_values['machine_name'], - '#description' => $this->t('A unique machine-readable name of this bundle. Used to prefix exported packages. It must only contain lowercase letters, numbers, and underscores.'), - '#machine_name' => [ - 'source' => ['bundle', 'name'], - 'exists' => [$this, 'bundleExists'], - ], - ]; - } - - $form['bundle']['description'] = [ - '#title' => $this->t('Distribution description'), - '#type' => 'textfield', - '#default_value' => $default_values['description'], - '#description' => $this->t('A description of the bundle.'), - '#size' => 80, - ]; - - $form['bundle']['is_profile'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Include install profile'), - '#default_value' => $default_values['is_profile'], - '#description' => $this->t('Select this option to have your features packaged into an install profile.'), - '#attributes' => [ - 'data-add-profile' => 'status', - ], - ]; - - $show_and_require_if_profile_checked = [ - 'visible' => [ - ':input[data-add-profile="status"]' => ['checked' => TRUE], - ], - 'required' => [ - ':input[data-add-profile="status"]' => ['checked' => TRUE], - ], - ]; - - $form['bundle']['profile_name'] = [ - '#title' => $this->t('Profile name'), - '#type' => 'textfield', - '#default_value' => $default_values['profile_name'], - '#description' => $this->t('The machine name (directory name) of your profile.'), - '#size' => 30, - // Show and require only if the profile.add option is selected. - '#states' => $show_and_require_if_profile_checked, - ]; - - // Attach the copyFieldValue behavior to the profile_name field. In - // practice this only works if a user tabs through the bundle machine name - // field or manually edits it. - $form['#attached']['drupalSettings']['copyFieldValue']['edit-bundle-machine-name'] = ['edit-bundle-profile-name']; - - foreach ($methods_weight as $method_id => $weight) { - - // A packaging method might no longer be available if the defining module - // has been uninstalled after the last configuration saving. - if (!isset($assignment_info[$method_id])) { - continue; - } - - $enabled = isset($enabled_methods[$method_id]); - $method = $assignment_info[$method_id]; - - $method_name = Html::escape($method['name']); - - $form['weight'][$method_id] = [ - '#type' => 'weight', - '#title' => $this->t('Weight for @title package assignment method', ['@title' => Unicode::strtolower($method_name)]), - '#title_display' => 'invisible', - '#default_value' => $weight, - '#attributes' => ['class' => ['assignment-method-weight']], - '#delta' => 20, - ]; - - $form['title'][$method_id] = ['#markup' => $method_name]; - - $form['enabled'][$method_id] = [ - '#type' => 'checkbox', - '#title' => $this->t('Enable @title package assignment method', ['@title' => Unicode::strtolower($method_name)]), - '#title_display' => 'invisible', - '#default_value' => $enabled, - ]; - - $form['description'][$method_id] = ['#markup' => $method['description']]; - - $config_op = []; - if (isset($method['config_route_name'])) { - $config_op['configure'] = [ - 'title' => $this->t('Configure'), - 'url' => Url::fromRoute($method['config_route_name'], ['bundle_name' => $current_bundle->getMachineName()]), - ]; - // If there is at least one operation enabled, show the operation - // column. - $form['#show_operations'] = TRUE; - } - $form['operation'][$method_id] = [ - '#type' => 'operations', - '#links' => $config_op, - ]; - } - - $form['actions'] = ['#type' => 'actions', '#weight' => 9]; - $form['actions']['submit'] = [ - '#type' => 'submit', - '#button_type' => 'primary', - '#value' => $this->t('Save settings'), - ]; - - return $form; - } - - /** - * Ajax callback for handling switching the bundle selector. - */ - public function updateForm($form, FormStateInterface $form_state) { - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - if ($form_state->getValue(['bundle', 'is_profile']) && empty($form_state->getValue(['bundle', 'profile_name']))) { - $form_state->setErrorByName('bundle][profile_name', $this->t('To create a profile, please enter a profile name.')); - } - - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - - $enabled_methods = array_filter($form_state->getValue('enabled')); - ksort($enabled_methods); - $method_weights = $form_state->getValue('weight'); - ksort($method_weights); - - $machine_name = $form_state->getValue(['bundle', 'machine_name']); - - // If this is a new bundle, create it. - if ($form_state->getValue(['bundle', 'bundle_select']) == self::NEW_BUNDLE_SELECT_VALUE) { - $bundle = $this->assigner->createBundleFromDefault($machine_name); - } - // Otherwise, load the current bundle and rename if needed. - else { - $bundle = $this->assigner->loadBundle(); - $old_name = $bundle->getMachineName(); - $new_name = $form_state->getValue(['bundle', 'machine_name']); - if ($old_name != $new_name) { - $bundle = $this->assigner->renameBundle($old_name, $new_name); - } - } - - $bundle->setName($form_state->getValue(['bundle', 'name'])); - $bundle->setDescription($form_state->getValue(['bundle', 'description'])); - $bundle->setEnabledAssignments(array_keys($enabled_methods)); - $bundle->setAssignmentWeights($method_weights); - $bundle->setIsProfile($form_state->getValue(['bundle', 'is_profile'])); - $bundle->setProfileName($form_state->getValue(['bundle', 'profile_name'])); - $bundle->save(); - $this->assigner->setBundle($bundle); - $this->assigner->setCurrent($bundle); - - $form_state->setRedirect('features.assignment'); - drupal_set_message($this->t('Package assignment configuration saved.')); - } - - /** - * Callback for machine_name exists() - * @param $value - * @param $element - * @param $form_state - * @return bool - */ - public function bundleExists($value, $element, $form_state) { - $bundle = $this->assigner->getBundle($value); - return isset($bundle); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentCoreForm.php b/web/modules/features/modules/features_ui/src/Form/AssignmentCoreForm.php deleted file mode 100644 index 0e186b814080afddef58f2ca32559231e1244873..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentCoreForm.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Configures the selected configuration assignment method for this site. - */ -class AssignmentCoreForm extends AssignmentFormBase { - - const METHOD_ID = 'core'; - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_assignment_core_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) { - $this->currentBundle = $this->assigner->loadBundle($bundle_name); - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - - $this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('core')); - $this->setActions($form, self::METHOD_ID); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - $form_state->setValue('types', array_map('array_filter', $form_state->getValue('types'))); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Merge in types selections. - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - $settings['types'] = $form_state->getValue('types'); - $this->currentBundle->setAssignmentSettings(self::METHOD_ID, $settings)->save(); - $this->setRedirect($form_state); - - drupal_set_message($this->t('Package assignment configuration saved.')); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentExcludeForm.php b/web/modules/features/modules/features_ui/src/Form/AssignmentExcludeForm.php deleted file mode 100644 index 459bf7ce839a0b1ade47145cf643767d60078f31..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentExcludeForm.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Configures the selected configuration assignment method for this site. - */ -class AssignmentExcludeForm extends AssignmentFormBase { - - const METHOD_ID = 'exclude'; - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_assignment_exclude_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) { - $this->currentBundle = $this->assigner->loadBundle($bundle_name); - - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - $module_settings = $settings['module']; - $curated_settings = $settings['curated']; - - $this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('exclude'), FALSE, - $this->t("Select types of configuration that should be excluded from packaging.")); - - $form['curated'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Exclude designated site-specific configuration'), - '#default_value' => $curated_settings, - '#description' => $this->t('Select this option to exclude a curated list of site-specific configuration from packaging.'), - ]; - - $form['module'] = [ - '#type' => 'fieldset', - '#tree' => TRUE, - '#title' => $this->t('Exclude configuration provided by modules'), - ]; - - $form['module']['installed'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Exclude installed module-provided entity configuration'), - '#default_value' => $module_settings['installed'], - '#description' => $this->t('Select this option to exclude configuration provided by INSTALLED modules from reassignment.'), - '#attributes' => [ - 'data-module-installed' => 'status', - ], - ]; - - $show_if_module_installed_checked = [ - 'visible' => [ - ':input[data-module-installed="status"]' => ['checked' => TRUE], - ], - ]; - - $info = system_get_info('module', drupal_get_profile()); - $form['module']['profile'] = [ - '#type' => 'checkbox', - '#title' => $this->t("Don't exclude install profile's configuration"), - '#default_value' => $module_settings['profile'], - '#description' => $this->t("Select this option to allow configuration provided by the site's install profile (%profile) to be reassigned.", ['%profile' => $info['name']]), - '#states' => $show_if_module_installed_checked, - ]; - - $bundle_name = $this->currentBundle->getMachineName(); - $bundle_name = !empty($bundle_name) ? $bundle_name : $this->t('none'); - $form['module']['namespace'] = [ - '#type' => 'checkbox', - '#title' => $this->t("Don't exclude non-installed configuration by namespace"), - '#default_value' => $module_settings['namespace'], - '#description' => $this->t("Select this option to allow configuration provided by uninstalled modules with the bundle namespace (%namespace_*) to be reassigned.", ['%namespace' => $bundle_name]), - '#states' => $show_if_module_installed_checked, - '#attributes' => [ - 'data-namespace' => 'status', - ], - ]; - - $show_if_namespace_checked = [ - 'visible' => [ - ':input[data-namespace="status"]' => ['checked' => TRUE], - ':input[data-module-installed="status"]' => ['checked' => TRUE], - ], - ]; - - $form['module']['namespace_any'] = [ - '#type' => 'checkbox', - '#title' => $this->t("Don't exclude ANY configuration by namespace"), - '#default_value' => $module_settings['namespace_any'], - '#description' => $this->t("Select this option to allow configuration provided by ANY modules with the bundle namespace (%namespace_*) to be reassigned. - Warning: Can cause installed configuration to be reassigned to different packages.", ['%namespace' => $bundle_name]), - '#states' => $show_if_namespace_checked, - ]; - - $this->setActions($form, self::METHOD_ID); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - $form_state->setValue('types', array_map('array_filter', $form_state->getValue('types'))); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Merge in selections. - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - $settings = array_merge($settings, [ - 'types' => $form_state->getValue('types'), - 'curated' => $form_state->getValue('curated'), - 'module' => $form_state->getValue('module'), - ]); - - $this->currentBundle->setAssignmentSettings(self::METHOD_ID, $settings)->save(); - - $this->setRedirect($form_state); - drupal_set_message($this->t('Package assignment configuration saved.')); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentFormBase.php b/web/modules/features/modules/features_ui/src/Form/AssignmentFormBase.php deleted file mode 100644 index 9b7dca927976c018f4f866bd73b7df798b764ce7..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentFormBase.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\features\FeaturesManagerInterface; -use Drupal\features\FeaturesAssignerInterface; -use Drupal\Core\Entity\ContentEntityTypeInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Form\FormBase; -use Drupal\Core\Form\FormStateInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Configures the selected configuration assignment method for this site. - */ -abstract class AssignmentFormBase extends FormBase { - - /** - * The features manager. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * The package assigner. - * - * @var \Drupal\features\FeaturesAssignerInterface - */ - protected $assigner; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * The current bundle. - * - * @var \Drupal\features\FeaturesBundleInterface - */ - protected $currentBundle; - - /** - * Constructs a AssignmentBaseForm object. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - * @param \Drupal\features\FeaturesAssignerInterface $assigner - * The assigner. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity type manager. - */ - public function __construct(FeaturesManagerInterface $features_manager, FeaturesAssignerInterface $assigner, EntityTypeManagerInterface $entity_type_manager) { - $this->featuresManager = $features_manager; - $this->assigner = $assigner; - $this->entityTypeManager = $entity_type_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('features.manager'), - $container->get('features_assigner'), - $container->get('entity_type.manager') - ); - } - - /** - * Adds configuration types checkboxes. - */ - protected function setConfigTypeSelect(&$form, $defaults, $type, $bundles_only = FALSE, $description = '') { - $options = $this->featuresManager->listConfigTypes($bundles_only); - - if (!isset($form['types'])) { - $form['types'] = [ - '#type' => 'container', - '#tree' => TRUE, - ]; - } - - $form['types']['config'] = [ - '#type' => 'checkboxes', - '#title' => $this->t('Configuration types'), - '#description' => !empty($description) ? $description : $this->t('Select types of configuration that should be considered @type types.', ['@type' => $type]), - '#options' => $options, - '#default_value' => $defaults, - ]; - } - - /** - * Adds content entity types checkboxes. - */ - protected function setContentTypeSelect(&$form, $defaults, $type, $exclude_has_config_bundles = TRUE) { - $entity_types = $this->entityTypeManager->getDefinitions(); - - $has_config_bundle = []; - foreach ($entity_types as $definition) { - if ($entity_type_id = $definition->getBundleOf()) { - $has_config_bundle[] = $entity_type_id; - } - } - $options = []; - - foreach ($entity_types as $entity_type_id => $entity_type) { - if (!$entity_type instanceof ContentEntityTypeInterface) { - continue; - } - if ($exclude_has_config_bundles && in_array($entity_type_id, $has_config_bundle)) { - continue; - } - $options[$entity_type_id] = $entity_type->getLabel() ?: $entity_type_id; - } - - // Sort the entity types by label. - uasort($options, 'strnatcasecmp'); - - if (!isset($form['types'])) { - $form['types'] = [ - '#type' => 'container', - '#tree' => TRUE, - ]; - } - - $form['types']['content'] = [ - '#type' => 'checkboxes', - '#title' => $this->t('Content entity types'), - '#description' => $this->t('Select content entity types that should be considered @type types.', ['@type' => $type]), - '#options' => $options, - '#default_value' => $defaults, - ]; - } - - /** - * Adds a "Save settings" submit action. - */ - protected function setActions(&$form, $method_id = NULL) { - $assignment_info = $this->assigner->getAssignmentMethods(); - if (isset($method_id) && isset($assignment_info[$method_id])) { - $method = $assignment_info[$method_id]; - $form['help_text'] = [ - '#markup' => $method['description'], - '#prefix' => '<p class="messages messages--status">', - '#suffix' => '</p>', - '#weight' => -99, - ]; - } - - $form['actions'] = ['#type' => 'actions']; - $form['actions']['submit'] = [ - '#type' => 'submit', - '#button_type' => 'primary', - '#value' => $this->t('Save settings'), - ]; - $form['#attributes']['class'][] = 'features-assignment-settings-form'; - $form['#attached'] = [ - 'library' => [ - 'features_ui/drupal.features_ui.admin', - ]]; - } - - /** - * Redirects back to the Bundle config form. - * - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The form state. - */ - protected function setRedirect(FormStateInterface $form_state) { - $form_state->setRedirect('features.assignment', ['bundle_name' => $this->currentBundle->getMachineName()]); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentOptionalForm.php b/web/modules/features/modules/features_ui/src/Form/AssignmentOptionalForm.php deleted file mode 100644 index 756fb5489cbc8e0e83390a5679d4a52e8435093c..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentOptionalForm.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Configures the selected configuration assignment method for this site. - */ -class AssignmentOptionalForm extends AssignmentFormBase { - - const METHOD_ID = 'optional'; - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_assignment_optional_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) { - $this->currentBundle = $this->assigner->loadBundle($bundle_name); - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - - $this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('optional')); - $this->setActions($form, self::METHOD_ID); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - $form_state->setValue('types', array_map('array_filter', $form_state->getValue('types'))); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Merge in types selections. - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - $settings['types'] = $form_state->getValue('types'); - $this->currentBundle->setAssignmentSettings(self::METHOD_ID, $settings)->save(); - $this->setRedirect($form_state); - - drupal_set_message($this->t('Package assignment configuration saved.')); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentProfileForm.php b/web/modules/features/modules/features_ui/src/Form/AssignmentProfileForm.php deleted file mode 100644 index 88c86348dd181d99a76b87bae2078a5d88c845f8..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentProfileForm.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Configures the selected configuration assignment method for this profile. - */ -class AssignmentProfileForm extends AssignmentFormBase { - - const METHOD_ID = 'profile'; - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_assignment_profile_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) { - $this->currentBundle = $this->assigner->loadBundle($bundle_name); - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - - $this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('profile')); - - $form['curated'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Add commonly-needed configuration'), - '#default_value' => $settings['curated'], - '#description' => $this->t('Select this option to add a curated list of commonly-needed configuration including cron- and theme-related settings to the install profile.'), - ]; - - $standard_settings = $settings['standard']; - - $form['standard'] = [ - '#type' => 'fieldset', - '#title' => $this->t('Crib from the Standard profile'), - '#tree' => TRUE, - ]; - $form['standard']['files'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Crib code'), - '#default_value' => $standard_settings['files'], - '#description' => $this->t('Select this option to add configuration and other files to the optional install profile from the Drupal core Standard install profile. Without these additions, a generated install profile will be missing some important initial setup.'), - ]; - $form['standard']['dependencies'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Crib dependencies'), - '#default_value' => $standard_settings['dependencies'], - '#description' => $this->t('Select this option to add module and theme dependencies from the Standard install profile.'), - ]; - - $this->setActions($form, self::METHOD_ID); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - $form_state->setValue('types', array_map('array_filter', $form_state->getValue('types'))); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Merge in selections. - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - - $settings = array_merge($settings, [ - 'curated' => $form_state->getValue('curated'), - 'standard' => $form_state->getValue('standard'), - 'types' => $form_state->getValue('types'), - ]); - - $this->currentBundle->setAssignmentSettings(self::METHOD_ID, $settings)->save(); - $this->setRedirect($form_state); - - drupal_set_message($this->t('Package assignment configuration saved.')); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/AssignmentSiteForm.php b/web/modules/features/modules/features_ui/src/Form/AssignmentSiteForm.php deleted file mode 100644 index 443d1f9454336a1576edede9fd37189f49111c51..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/AssignmentSiteForm.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Configures the selected configuration assignment method for this site. - */ -class AssignmentSiteForm extends AssignmentFormBase { - - const METHOD_ID = 'site'; - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_assignment_site_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $bundle_name = NULL) { - $this->currentBundle = $this->assigner->loadBundle($bundle_name); - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - - $this->setConfigTypeSelect($form, $settings['types']['config'], $this->t('site')); - $this->setActions($form, self::METHOD_ID); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - $form_state->setValue('types', array_map('array_filter', $form_state->getValue('types'))); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Merge in types selections. - $settings = $this->currentBundle->getAssignmentSettings(self::METHOD_ID); - $settings['types'] = $form_state->getValue('types'); - $this->currentBundle->setAssignmentSettings(self::METHOD_ID, $settings)->save(); - $this->setRedirect($form_state); - - drupal_set_message($this->t('Package assignment configuration saved.')); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/FeaturesDiffForm.php b/web/modules/features/modules/features_ui/src/Form/FeaturesDiffForm.php deleted file mode 100644 index b04ca241a9d511cffc86ab400eea7464afe699b9..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/FeaturesDiffForm.php +++ /dev/null @@ -1,270 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Component\Utility\Html; -use Drupal\features\ConfigurationItem; -use Drupal\features\FeaturesAssignerInterface; -use Drupal\features\FeaturesManagerInterface; -use Drupal\Core\Form\FormBase; -use Drupal\Core\Form\FormStateInterface; -use Drupal\features\Package; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\Component\Diff\DiffFormatter; -use Drupal\config_update\ConfigRevertInterface; -use Drupal\config_update\ConfigDiffInterface; - -/** - * Defines the features differences form. - */ -class FeaturesDiffForm extends FormBase { - - /** - * The features manager. - * - * @var array - */ - protected $featuresManager; - - /** - * The package assigner. - * - * @var array - */ - protected $assigner; - - /** - * The config differ. - * - * @var \Drupal\config_update\ConfigDiffInterface - */ - protected $configDiff; - - /** - * The diff formatter. - * - * @var \Drupal\Core\Diff\DiffFormatter - */ - protected $diffFormatter; - - /** - * The config reverter. - * - * @var \Drupal\config_update\ConfigRevertInterface - */ - protected $configRevert; - - /** - * Constructs a FeaturesDiffForm object. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - */ - public function __construct(FeaturesManagerInterface $features_manager, FeaturesAssignerInterface $assigner, - ConfigDiffInterface $config_diff, DiffFormatter $diff_formatter, - ConfigRevertInterface $config_revert) { - $this->featuresManager = $features_manager; - $this->assigner = $assigner; - $this->configDiff = $config_diff; - $this->diffFormatter = $diff_formatter; - $this->configRevert = $config_revert; - $this->diffFormatter->show_header = FALSE; - $this->diffFormatter->leading_context_lines = 0; - $this->diffFormatter->trailing_context_lines = 0; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('features.manager'), - $container->get('features_assigner'), - $container->get('config_update.config_diff'), - $container->get('diff.formatter'), - $container->get('features.config_update') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_diff_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $featurename = '') { - $current_bundle = $this->assigner->applyBundle(); - $packages = $this->featuresManager->getPackages(); - $form = []; - - $machine_name = ''; - if (!empty($featurename) && empty($packages[$featurename])) { - drupal_set_message($this->t('Feature @name does not exist.', ['@name' => $featurename]), 'error'); - return []; - } - elseif (!empty($featurename)) { - $machine_name = $packages[$featurename]->getMachineName(); - $packages = [$packages[$featurename]]; - } - else { - $packages = $this->featuresManager->filterPackages($packages, $current_bundle->getMachineName()); - } - - $header = [ - 'row' => [ - 'data' => !empty($machine_name) - ? $this->t('Differences in @name', ['@name' => $machine_name]) - : ($current_bundle->isDefault() ? $this->t('All differences') : $this->t('All differences in bundle: @bundle', ['@bundle' => $current_bundle->getName()])), - ], - ]; - - $options = []; - foreach ($packages as $package) { - if ($package->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT) { - $missing = $this->featuresManager->reorderMissing($this->featuresManager->detectMissing($package)); - $overrides = $this->featuresManager->detectOverrides($package, TRUE); - if (!empty($overrides) || !empty($missing)) { - $options += [ - $package->getMachineName() => [ - 'row' => [ - 'data' => [ - '#type' => 'html_tag', - '#tag' => 'h2', - '#value' => Html::escape($package->getName()), - ], - ], - '#attributes' => [ - 'class' => 'features-diff-header', - ], - ], - ]; - $options += $this->diffOutput($package, $overrides, $missing); - } - } - } - - $form['diff'] = [ - '#type' => 'tableselect', - '#header' => $header, - '#options' => $options, - '#attributes' => ['class' => ['features-diff-listing']], - '#empty' => $this->t('No differences exist in exported features.'), - ]; - - $form['actions'] = ['#type' => 'actions', '#tree' => TRUE]; - $form['actions']['revert'] = [ - '#type' => 'submit', - '#value' => $this->t('Import changes'), - ]; - $form['actions']['help'] = [ - '#markup' => $this->t('Import the selected changes above into the active configuration.'), - ]; - - $form['#attached']['library'][] = 'system/diff'; - $form['#attached']['library'][] = 'features_ui/drupal.features_ui.admin'; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $this->assigner->assignConfigPackages(); - $config = $this->featuresManager->getConfigCollection(); - $items = array_filter($form_state->getValue('diff')); - if (empty($items)) { - drupal_set_message($this->t('No configuration was selected for import.'), 'warning'); - return; - } - foreach ($items as $config_name) { - if (isset($config[$config_name])) { - $item = $config[$config_name]; - $type = ConfigurationItem::fromConfigStringToConfigType($item->getType()); - $this->configRevert->revert($type, $item->getShortName()); - } - else { - $item = $this->featuresManager->getConfigType($config_name); - $type = ConfigurationItem::fromConfigStringToConfigType($item['type']); - $this->configRevert->import($type, $item['name_short']); - } - drupal_set_message($this->t('Imported @name', ['@name' => $config_name])); - } - } - - /** - * Returns a form element for the given overrides. - * - * @param \Drupal\features\Package $package - * A package. - * @param array $overrides - * An array of overrides. - * @param array $missing - * An array of missing config. - * - * @return array - * A form element. - */ - protected function diffOutput(Package $package, $overrides, $missing = []) { - $element = []; - $config = $this->featuresManager->getConfigCollection(); - $components = array_merge($missing, $overrides); - - $header = [ - ['data' => '', 'class' => 'diff-marker'], - ['data' => $this->t('Active site config'), 'class' => 'diff-context'], - ['data' => '', 'class' => 'diff-marker'], - ['data' => $this->t('Feature code config'), 'class' => 'diff-context'], - ]; - - foreach ($components as $name) { - $rows[] = [['data' => $name, 'colspan' => 4, 'header' => TRUE]]; - - if (!isset($config[$name])) { - $details = [ - '#markup' => $this->t('Component in feature missing from active config.'), - ]; - } - else { - $active = $this->featuresManager->getActiveStorage()->read($name); - $extension = $this->featuresManager->getExtensionStorages()->read($name); - if (empty($extension)) { - $details = [ - '#markup' => $this->t('Dependency detected in active config but not exported to the feature.'), - ]; - } - else { - $diff = $this->configDiff->diff($active, $extension); - $details = [ - '#type' => 'table', - '#header' => $header, - '#rows' => $this->diffFormatter->format($diff), - '#attributes' => ['class' => ['diff', 'features-diff']], - ]; - } - } - $element[$name] = [ - 'row' => [ - 'data' => [ - '#type' => 'details', - '#title' => Html::escape($name), - '#open' => TRUE, - '#description' => [ - 'data' => $details, - ], - ], - ], - '#attributes' => [ - 'class' => 'diff-' . $package->getMachineName(), - ], - ]; - } - - return $element; - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/FeaturesEditForm.php b/web/modules/features/modules/features_ui/src/Form/FeaturesEditForm.php deleted file mode 100644 index 62808765769db24d02ebc1a3e0d8acbf4263d25f..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/FeaturesEditForm.php +++ /dev/null @@ -1,1091 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Component\Utility\Html; -use Drupal\Component\Utility\Xss; -use Drupal\features\FeaturesAssignerInterface; -use Drupal\features\FeaturesGeneratorInterface; -use Drupal\features\FeaturesManagerInterface; -use Drupal\features\ConfigurationItem; -use Drupal\Core\Form\FormBase; -use Drupal\Core\Form\FormStateInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -Use Drupal\Component\Render\FormattableMarkup; -use Drupal\config_update\ConfigRevertInterface; - -/** - * Defines the features settings form. - */ -class FeaturesEditForm extends FormBase { - - /** - * The features manager. - * - * @var array - */ - protected $featuresManager; - - /** - * The package assigner. - * - * @var array - */ - protected $assigner; - - /** - * The package generator. - * - * @var array - */ - protected $generator; - - /** - * Current package being edited. - * - * @var \Drupal\features\Package - */ - protected $package; - - /** - * Current bundle machine name. - * - * NOTE: D8 cannot serialize objects within forms so you can't directly - * store the entire Bundle object here. - * - * @var string - */ - protected $bundle; - - /** - * Previous bundle name for ajax processing. - * - * @var string - */ - protected $oldBundle; - - /** - * Config to be specifically excluded. - * - * @var array - */ - protected $excluded; - - /** - * Config to be specifically required. - * - * @var array - */ - protected $required; - - /** - * Config referenced by other packages. - * - * @var array - */ - protected $conflicts; - - /** - * Determine if conflicts are allowed to be added. - * - * @var bool - */ - protected $allowConflicts; - - /** - * Config missing from active site. - * - * @var array - */ - protected $missing; - - /** - * The config reverter. - * - * @var \Drupal\config_update\ConfigRevertInterface - */ - protected $configRevert; - - /** - * Constructs a FeaturesEditForm object. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - */ - public function __construct(FeaturesManagerInterface $features_manager, FeaturesAssignerInterface $assigner, FeaturesGeneratorInterface $generator, ConfigRevertInterface $config_revert) { - $this->featuresManager = $features_manager; - $this->assigner = $assigner; - $this->generator = $generator; - $this->configRevert = $config_revert; - $this->excluded = []; - $this->required = []; - $this->conflicts = []; - $this->missing = []; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('features.manager'), - $container->get('features_assigner'), - $container->get('features_generator'), - $container->get('features.config_update') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_edit_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state, $featurename = '') { - $session = $this->getRequest()->getSession(); - $trigger = $form_state->getTriggeringElement(); - if ($trigger['#name'] == 'package') { - // Save current bundle name for later ajax callback. - $this->oldBundle = $this->bundle; - } - elseif ($trigger['#name'] == 'conflicts') { - if (isset($session)) { - $session->set('features_allow_conflicts', $form_state->getValue('conflicts')); - } - } - if (!$form_state->isValueEmpty('package')) { - $bundle_name = $form_state->getValue('package'); - $bundle = $this->assigner->getBundle($bundle_name); - } - else { - $bundle = $this->assigner->loadBundle(); - } - // Only store bundle name, not full object. - $this->bundle = $bundle->getMachineName(); - - $this->allowConflicts = FALSE; - if (isset($session)) { - $this->allowConflicts = $session->get('features_allow_conflicts', FALSE); - } - - // Pass the $force argument as TRUE because we want to include any excluded - // configuration items. These should show up as automatically assigned, but - // not selected, thus allowing the admin to reselect if desired. - // @see FeaturesManagerInterface::assignConfigPackage() - $this->assigner->assignConfigPackages(TRUE); - - $packages = $this->featuresManager->getPackages(); - if (empty($packages[$featurename])) { - $featurename = str_replace(['-', ' '], '_', $featurename); - $this->package = $this->featuresManager->initPackage($featurename, NULL, '', 'module', $bundle); - } - else { - $this->package = $packages[$featurename]; - } - - if (!empty($packages[$featurename]) && $this->package->getBundle() !== $this->bundle && $form_state->isValueEmpty('package')) { - // Make sure the current bundle matches what is stored in the package. - // But only do this if the Package value hasn't been manually changed. - $bundle = $this->assigner->getBundle($this->package->getBundle()); - if (empty($bundle)) { - // Create bundle if it doesn't exist yet - $bundle = $this->assigner->createBundleFromDefault($this->package->getBundle()); - } - $this->bundle = $bundle->getMachineName(); - $this->assigner->reset(); - $this->assigner->assignConfigPackages(TRUE); - $packages = $this->featuresManager->getPackages(); - $this->package = $packages[$featurename]; - } - - $form = [ - '#show_operations' => FALSE, - '#prefix' => '<div id="features-edit-wrapper">', - '#suffix' => '</div>', - ]; - - $form['info'] = [ - '#type' => 'fieldset', - '#title' => $this->t('General Information'), - '#tree' => FALSE, - '#weight' => 2, - '#prefix' => "<div id='features-export-info'>", - '#suffix' => '</div>', - ]; - - $form['info']['name'] = [ - '#title' => $this->t('Name'), - '#description' => $this->t('Example: Image gallery') . ' (' . $this->t('Do not begin name with numbers.') . ')', - '#type' => 'textfield', - '#default_value' => $this->package->getName(), - ]; - if (!$bundle->isDefault()) { - $form['info']['name']['#description'] .= '<br/>' . - $this->t('The namespace "@name_" will be prepended to the machine name', ['@name' => $bundle->getMachineName()]); - } - - $form['info']['machine_name'] = [ - '#type' => 'machine_name', - '#title' => $this->t('Machine-readable name'), - '#description' => $this->t('Example: image_gallery') . ' ' . $this->t('May only contain lowercase letters, numbers and underscores.'), - '#required' => TRUE, - '#default_value' => $bundle->getShortName($this->package->getMachineName()), - '#machine_name' => [ - 'source' => ['info', 'name'], - 'exists' => [$this, 'featureExists'], - ], - ]; - if (!$bundle->isDefault()) { - $form['info']['machine_name']['#description'] .= '<br/>' . - $this->t('NOTE: Do NOT include the namespace prefix "@name_"; it will be added automatically.', ['@name' => $bundle->getMachineName()]); - } - - $form['info']['description'] = [ - '#title' => $this->t('Description'), - '#description' => $this->t('Provide a short description of what users should expect when they install your feature.'), - '#type' => 'textarea', - '#rows' => 3, - '#default_value' => $this->package->getDescription(), - ]; - - $form['info']['package'] = [ - '#title' => $this->t('Bundle'), - '#type' => 'select', - '#options' => $this->assigner->getBundleOptions(), - '#default_value' => $bundle->getMachineName(), - '#ajax' => [ - 'callback' => '::updateBundle', - 'wrapper' => 'features-export-info', - ], - ]; - - $form['info']['version'] = [ - '#title' => $this->t('Version'), - '#description' => $this->t('Examples: 8.x-1.0, 8.x-1.0-beta1'), - '#type' => 'textfield', - '#required' => FALSE, - '#default_value' => $this->package->getVersion(), - '#size' => 30, - ]; - - list($full_name, $path) = $this->featuresManager->getExportInfo($this->package, $bundle); - $form['info']['directory'] = [ - '#title' => $this->t('Path'), - '#description' => $this->t('Path to export package using Write action, relative to root directory.'), - '#type' => 'textfield', - '#required' => FALSE, - '#default_value' => $path, - '#size' => 30, - ]; - - $require_all = $this->package->getRequiredAll(); - $form['info']['require_all'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Mark all config as required'), - '#default_value' => $this->package->getRequiredAll(), - '#description' => $this->t('Required config will be assigned to this feature regardless of other assignment plugins.'), - ]; - - $form['conflicts'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Allow conflicts'), - '#default_value' => $this->allowConflicts, - '#description' => $this->t('Allow configuration to be exported to more than one feature.'), - '#weight' => 8, - '#ajax' => [ - 'callback' => '::updateForm', - 'wrapper' => 'features-edit-wrapper', - ], - ]; - - $generation_info = []; - if (\Drupal::currentUser()->hasPermission('export configuration')) { - // Offer available generation methods. - $generation_info = $this->generator->getGenerationMethods(); - // Sort generation methods by weight. - uasort($generation_info, '\Drupal\Component\Utility\SortArray::sortByWeightElement'); - } - - $form['actions'] = ['#type' => 'actions', '#tree' => TRUE]; - foreach ($generation_info as $method_id => $method) { - $form['actions'][$method_id] = [ - '#type' => 'submit', - '#name' => $method_id, - '#value' => $this->t('@name', ['@name' => $method['name']]), - '#attributes' => [ - 'title' => Html::escape($method['description']), - ], - ]; - } - - // Build the Component Listing panel on the right. - $form['export'] = $this->buildComponentList($form_state); - - if (!empty($this->missing)) { - if ($this->allowConflicts) { - $form['actions']['#prefix'] = '<strong>' . - $this->t('WARNING: Package contains configuration missing from site.') . '<br>' . - $this->t('This configuration will be removed if you export it.') . - '</strong>'; - } - else { - foreach ($generation_info as $method_id => $method) { - unset($form['actions'][$method_id]); - } - $form['actions']['#prefix'] = '<strong>' . - $this->t('Package contains configuration missing from site.') . '<br>' . - $this->t('Import the feature to create the missing config before you can export it.') . '<br>' . - $this->t('Or, enable the Allow Conflicts option above.') . - '</strong>'; - } - $form['actions']['import_missing'] = [ - '#type' => 'submit', - '#name' => 'import_missing', - '#value' => $this->t('Import Missing'), - '#attributes' => [ - 'title' => $this->t('Import only the missing configuration items.'), - ], - ]; - } - - $form['#attached'] = [ - 'library' => [ - 'features_ui/drupal.features_ui.admin', - ], - 'drupalSettings' => [ - 'features' => [ - 'excluded' => $this->excluded, - 'required' => $this->required, - 'conflicts' => $this->conflicts, - 'autodetect' => TRUE, - ], - ], - ]; - - return $form; - } - - /** - * Provides an ajax callback for handling conflict checkbox. - */ - public function updateForm($form, FormStateInterface $form_state) { - return $form; - } - - /** - * Provides an ajax callback for handling switching the bundle selector. - */ - public function updateBundle($form, FormStateInterface $form_state) { - $old_bundle = $this->assigner->getBundle($this->oldBundle); - $bundle_name = $form_state->getValue('package'); - $bundle = $this->assigner->getBundle($bundle_name); - if (isset($bundle) && isset($old_bundle)) { - $short_name = $old_bundle->getShortName($this->package->getMachineName()); - if ($bundle->isDefault()) { - $short_name = $old_bundle->getFullName($short_name); - } - $this->package->setMachineName($bundle->getFullName($short_name)); - $form['info']['machine_name']['#value'] = $bundle->getShortName($this->package->getMachineName()); - } - return $form['info']; - } - - /** - * Callback for machine_name exists() - * @param $value - * @param $element - * @param $form_state - * @return bool - */ - public function featureExists($value, $element, $form_state) { - $bundle = $this->assigner->getBundle($this->bundle); - $value = $bundle->getFullName($value); - $packages = $this->featuresManager->getPackages(); - // A package may conflict only if it's been exported. - return (isset($packages[$value]) && ($packages[$value]->getState() !== FeaturesManagerInterface::STATUS_NO_EXPORT)) || \Drupal::moduleHandler()->moduleExists($value); - } - - /** - * Returns the render array elements for the Components selection on the Edit - * form. - */ - protected function buildComponentList(FormStateInterface $form_state) { - $element = [ - '#type' => 'fieldset', - '#title' => $this->t('Components'), - '#description' => $this->t('Expand each component section and select which items should be included in this feature export.'), - '#tree' => FALSE, - '#prefix' => "<div id='features-export-wrapper'>", - '#suffix' => '</div>', - '#weight' => 1, - ]; - - // Filter field used in javascript, so javascript will unhide it. - $element['features_filter_wrapper'] = [ - '#type' => 'fieldset', - '#title' => $this->t('Filters'), - '#tree' => FALSE, - '#prefix' => "<div id='features-filter' class='element-invisible'>", - '#suffix' => '</div>', - '#weight' => -10, - ]; - $element['features_filter_wrapper']['features_filter'] = [ - '#type' => 'textfield', - '#title' => $this->t('Search'), - '#hidden' => TRUE, - '#default_value' => '', - '#suffix' => "<span class='features-filter-clear'>" . $this->t('Clear') . "</span>", - ]; - $element['features_filter_wrapper']['checkall'] = [ - '#type' => 'checkbox', - '#default_value' => FALSE, - '#hidden' => TRUE, - '#title' => $this->t('Select all'), - '#attributes' => [ - 'class' => ['features-checkall'], - ], - ]; - - $sections = ['included', 'detected', 'added']; - $config_types = $this->featuresManager->listConfigTypes(); - - // Generate the export array for the current feature and user selections. - $export = $this->getComponentList($form_state); - - foreach ($export['components'] as $component => $component_info) { - - $component_items_count = count($component_info['_features_options']['sources']); - $label = new FormattableMarkup('@component (<span class="component-count">@count</span>)', - [ - '@component' => $config_types[$component], - '@count' => $component_items_count, - ] - ); - - $count = 0; - foreach ($sections as $section) { - $count += count($component_info['_features_options'][$section]); - } - $extra_class = ($count == 0) ? 'features-export-empty' : ''; - $component_name = str_replace('_', '-', Html::escape($component)); - - if ($count + $component_items_count > 0) { - $element[$component] = [ - '#markup' => '', - '#tree' => TRUE, - ]; - - $element[$component]['sources'] = [ - '#type' => 'details', - '#title' => $label, - '#tree' => TRUE, - '#open' => FALSE, - '#attributes' => ['class' => ['features-export-component']], - '#prefix' => "<div class='features-export-parent component-$component'>", - ]; - $element[$component]['sources']['selected'] = [ - '#type' => 'checkboxes', - '#id' => "edit-sources-$component_name", - '#options' => $this->domDecodeOptions($component_info['_features_options']['sources']), - '#default_value' => $this->domDecodeOptions($component_info['_features_selected']['sources'], FALSE), - '#attributes' => ['class' => ['component-select']], - '#prefix' => "<span class='component-select'>", - '#suffix' => '</span>', - ]; - - $element[$component]['before-list'] = [ - '#markup' => "<div class='component-list features-export-list $extra_class'>", - ]; - - foreach ($sections as $section) { - $element[$component][$section] = [ - '#type' => 'checkboxes', - '#options' => !empty($component_info['_features_options'][$section]) ? - $this->domDecodeOptions($component_info['_features_options'][$section]) : [], - '#default_value' => !empty($component_info['_features_selected'][$section]) ? - $this->domDecodeOptions($component_info['_features_selected'][$section], FALSE) : [], - '#attributes' => ['class' => ['component-' . $section]], - '#prefix' => "<span class='component-$section'>", - '#suffix' => '</span>', - ]; - } - - // Close both the before-list as well as the sources div. - $element[$component]['after-list'] = [ - '#markup' => "</div></div>", - ]; - } - } - - $element['features_missing'] = [ - '#theme' => 'item_list', - '#items' => $export['missing'], - '#title' => $this->t('Configuration missing from active site:'), - '#suffix' => '<div class="description">' . - $this->t('Import the feature to create the missing config listed above.') . - '</div>', - ]; - - $element['features_legend'] = [ - '#type' => 'fieldset', - '#title' => $this->t('Legend'), - '#tree' => FALSE, - '#prefix' => "<div id='features-legend'>", - '#suffix' => '</div>', - ]; - $element['features_legend']['legend'] = [ - '#markup' => - "<span class='component-included'>" . $this->t('Normal') . "</span> " . - "<span class='component-added'>" . $this->t('Added') . "</span> " . - "<span class='component-detected'>" . $this->t('Auto detected') . "</span> " . - "<span class='component-conflict'>" . $this->t('Conflict') . "</span> ", - ]; - - return $element; - } - - /** - * Returns the full feature export array based upon user selections in - * form_state. - * - * @param \Drupal\Core\Form\FormStateInterface $form_state - * Optional form_state information for user selections. Can be updated to - * reflect new selection status. - * - * @return \Drupal\features\Package - * New export array to be exported - * array['components'][$component_name] = $component_info - * $component_info['_features_options'][$section] is list of available options - * $component_info['_features_selected'][$section] is option state TRUE/FALSE - * $section = array('sources', included', 'detected', 'added') - * sources - options that are available to be added to the feature - * included - options that have been previously exported to the feature - * detected - options that have been auto-detected - * added - newly added options to the feature - * - * NOTE: This routine gets a bit complex to handle all of the different - * possible user checkbox selections and de-selections. - * Cases to test: - * 1a) uncheck Included item -> mark as Added but unchecked - * 1b) re-check unchecked Added item -> return it to Included check item - * 2a) check Sources item -> mark as Added and checked - * 2b) uncheck Added item -> return it to Sources as unchecked - * 3a) uncheck Included item that still exists as auto-detect -> mark as - * Detected but unchecked - * 3b) re-check Detected item -> return it to Included and checked - * 4a) check Sources item should also add any auto-detect items as Detected - * and checked - * 4b) uncheck Sources item with auto-detect and auto-detect items should - * return to Sources and unchecked - * 5a) uncheck a Detected item -> refreshing page should keep it as - * unchecked Detected - * 6) when nothing changes, refresh should not change any state - * 7) should never see an unchecked Included item - */ - protected function getComponentList(FormStateInterface $form_state) { - $config = $this->featuresManager->getConfigCollection(); - - $package_name = $this->package->getMachineName(); - // Auto-detect dependencies for included config. - $package_config = $this->package->getConfig(); - if (!empty($this->package->getConfigOrig())) { - $package_config = array_unique(array_merge($package_config, $this->package->getConfigOrig())); - } - if (!empty($package_config)) { - $this->featuresManager->assignConfigDependents($package_config, $package_name); - } - - $packages = $this->featuresManager->getPackages(); - // Re-fetch the package in case config was updated with Dependents above. - $this->package = $packages[$package_name]; - - // Make a map of all config data. - $components = []; - $this->conflicts = []; - foreach ($config as $item_name => $item) { - if (($item->getPackage() != $package_name) && - !empty($packages[$item->getPackage()]) && ($packages[$item->getPackage()]->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT)) { - $this->conflicts[$item->getType()][$item->getShortName()] = $item->getLabel(); - } - if ($this->allowConflicts - || !isset($this->conflicts[$item->getType()][$item->getShortName()]) - || ($this->package->getConfigOrig() && in_array($item_name, $this->package->getConfigOrig()))) { - $components[$item->getType()][$item->getShortName()] = $item->getLabel(); - } - } - - // Make a map of the config data already exported to the Feature. - $this->missing = []; - $exported_features_info = []; - foreach ($this->package->getConfigOrig() as $item_name) { - // Make sure the extension provided item exists in the active - // configuration storage. - if (isset($config[$item_name])) { - $item = $config[$item_name]; - // Remove any conflicts if those are not being allowed. - // if ($this->allowConflicts || !isset($this->conflicts[$item['type']][$item['name_short']])) { - $exported_features_info[$item->getType()][$item->getShortName()] = $item->getLabel(); - // } - } - else { - $this->missing[] = $item_name; - } - } - $exported_features_info['dependencies'] = $this->package->getDependencyInfo(); - - // Make a map of any config specifically excluded and/or required. - foreach (['excluded', 'required'] as $constraint) { - $this->{$constraint} = []; - $info = !empty($this->package->{'get' . $constraint}()) ? $this->package->{'get' . $constraint}() : []; - // $info may be boolean. - if (is_array($info)) { - foreach ($info as $item_name) { - if (!isset($config[$item_name])) { - continue; - } - $item = $config[$item_name]; - $this->{$constraint}[$item->getType()][$item->getShortName()] = $item->getLabel(); - } - } - } - - // Make a map of the config data to be exported within the Feature. - $new_features_info = []; - foreach ($this->package->getConfig() as $item_name) { - $item = $config[$item_name]; - $new_features_info[$item->getType()][$item->getShortName()] = $item->getLabel(); - } - $new_features_info['dependencies'] = $this->package->getDependencies(); - - // Assemble the combined component list. - $config_new = []; - $sections = ['sources', 'included', 'detected', 'added']; - - // Generate list of config to be exported. - $config_count = []; - foreach ($components as $component => $component_info) { - // User-selected components take precedence. - $config_new[$component] = []; - $config_count[$component] = 0; - // Add selected items from Sources checkboxes. - if (!$form_state->isValueEmpty([$component, 'sources', 'selected'])) { - $config_new[$component] = array_merge($config_new[$component], $this->domDecodeOptions(array_filter($form_state->getValue([ - $component, - 'sources', - 'selected', - ])))); - $config_count[$component]++; - } - // Add selected items from already Included, newly Added, auto-detected - // checkboxes. - foreach (['included', 'added', 'detected'] as $section) { - if (!$form_state->isValueEmpty([$component, $section])) { - $config_new[$component] = array_merge($config_new[$component], $this->domDecodeOptions(array_filter($form_state->getValue([$component, $section])))); - $config_count[$component]++; - } - } - // Only fallback to an existing feature's values if there are no export - // options for the component. - if ($component == 'dependencies') { - if (($config_count[$component] == 0) && !empty($exported_features_info['dependencies'])) { - $config_new[$component] = array_combine($exported_features_info['dependencies'], $exported_features_info['dependencies']); - } - } - elseif (($config_count[$component] == 0) && !empty($exported_features_info[$component])) { - $config_names = array_keys($exported_features_info[$component]); - $config_new[$component] = array_combine($config_names, $config_names); - } - } - - // Generate new populated feature. - $export['package'] = $this->package; - $export['config_new'] = $config_new; - - // Now fill the $export with categorized sections of component options - // based upon user selections and de-selections. - foreach ($components as $component => $component_info) { - $component_export = $component_info; - foreach ($sections as $section) { - $component_export['_features_options'][$section] = []; - $component_export['_features_selected'][$section] = []; - } - if (!empty($component_info)) { - $exported_components = !empty($exported_features_info[$component]) ? $exported_features_info[$component] : []; - $new_components = !empty($new_features_info[$component]) ? $new_features_info[$component] : []; - - foreach ($component_info as $key => $label) { - $config_name = $this->featuresManager->getFullName($component, $key); - // If checkbox in Sources is checked, move it to Added section. - if (!$form_state->isValueEmpty([$component, 'sources', 'selected', $key])) { - $form_state->setValue([$component, 'sources', 'selected', $key], FALSE); - $form_state->setValue([$component, 'added', $key], 1); - $component_export['_features_options']['added'][$key] = $this->configLabel($component, $key, $label); - $component_export['_features_selected']['added'][$key] = $key; - // If this was previously excluded, we don't need to set it as - // required because it was automatically assigned. - if (isset($this->excluded[$component][$key])) { - unset($this->excluded[$component][$key]); - } - else { - $this->required[$component][$key] = $key; - } - } - elseif (isset($new_components[$key]) || isset($config_new[$component][$key])) { - // Option is in the New exported array. - if (isset($exported_components[$key])) { - // Option was already previously exported so it's part of the - // Included checkboxes. - $section = 'included'; - $default_value = $key; - // If Included item was un-selected (removed from export - // $config_new) but was re-detected in the $new_components - // means it was an auto-detect that was previously part of the - // export and is now de-selected in UI. - if ($form_state->isSubmitted() && - ($form_state->hasValue([$component, 'included', $key]) || - ($form_state->isValueEmpty([$component, 'detected', $key]))) && - empty($config_new[$component][$key])) { - $section = 'detected'; - $default_value = FALSE; - } - // Unless it's unchecked in the form, then move it to Newly - // disabled item. - elseif ($form_state->isSubmitted() && - $form_state->isValueEmpty([$component, 'added', $key]) && - $form_state->isValueEmpty([$component, 'detected', $key]) && - $form_state->isValueEmpty([$component, 'included', $key])) { - $section = 'added'; - $default_value = FALSE; - } - } - else { - // Option was in New exported array, but NOT in already exported - // so it's a user-selected or an auto-detect item. - $section = 'detected'; - $default_value = NULL; - // Check for item explicitly excluded. - if (isset($this->excluded[$component][$key]) && !$form_state->isSubmitted()) { - $default_value = FALSE; - } - else { - $default_value = $key; - } - // If it's already checked in Added or Sources, leave it in Added - // as checked. - if ($form_state->isSubmitted() && - (!$form_state->isValueEmpty([$component, 'added', $key]) || - !$form_state->isValueEmpty([$component, 'sources', 'selected', $key]))) { - $section = 'added'; - $default_value = $key; - } - // If it's already been unchecked, leave it unchecked. - elseif ($form_state->isSubmitted() && - $form_state->isValueEmpty([$component, 'sources', 'selected', $key]) && - $form_state->isValueEmpty([$component, 'detected', $key]) && - !$form_state->hasValue([$component, 'added', $key])) { - $section = 'detected'; - $default_value = FALSE; - } - } - $component_export['_features_options'][$section][$key] = $this->configLabel($component, $key, $label); - $component_export['_features_selected'][$section][$key] = $default_value; - // Save which dependencies are specifically excluded from - // auto-detection. - if (($section == 'detected') && ($default_value === FALSE)) { - // If this was previously required, we don't need to set it as - // excluded because it wasn't automatically assigned. - if (!isset($this->required[$component][$key]) || ($this->package->getRequired() === TRUE)) { - $this->excluded[$component][$key] = $key; - } - unset($this->required[$component][$key]); - // Remove excluded item from export. - if ($component == 'dependencies') { - $export['package']->removeDependency($key); - } - else { - $export['package']->removeConfig($config_name); - } - } - else { - unset($this->excluded[$component][$key]); - } - // Remove the 'input' and set the 'values' so Drupal stops looking - // at 'input'. - if ($form_state->isSubmitted()) { - if (!$default_value) { - $form_state->setValue([$component, $section, $key], FALSE); - } - else { - $form_state->setValue([$component, $section, $key], 1); - } - } - } - elseif (!$form_state->isSubmitted() && isset($exported_components[$key])) { - // Component is not part of new export, but was in original export. - // Mark component as Added when creating initial form. - $component_export['_features_options']['added'][$key] = $this->configLabel($component, $key, $label); - $component_export['_features_selected']['added'][$key] = $key; - } - else { - // Option was not part of the new export. - $added = FALSE; - foreach (['included', 'added'] as $section) { - // Restore any user-selected checkboxes. - if (!$form_state->isValueEmpty([$component, $section, $key])) { - $component_export['_features_options'][$section][$key] = $this->configLabel($component, $key, $label); - $component_export['_features_selected'][$section][$key] = $key; - $added = TRUE; - } - } - if (!$added) { - // If not Included or Added, then put it back in the unchecked - // Sources checkboxes. - $component_export['_features_options']['sources'][$key] = $this->configLabel($component, $key, $label); - $component_export['_features_selected']['sources'][$key] = FALSE; - } - } - } - } - $export['components'][$component] = $component_export; - } - $export['features_exclude'] = $this->excluded; - $export['features_require'] = $this->required; - $export['conflicts'] = $this->conflicts; - $export['missing'] = $this->missing; - - return $export; - } - - /** - * Returns a formatted and sanitized label for a config item. - * - * @param string $type - * The config type. - * @param string $key - * The short machine name of the item. - * @param string $label - * The human label for the item. - */ - protected function configLabel($type, $key, $label) { - $value = Html::escape($label); - if ($key != $label) { - $value .= ' <span class="config-name">(' . Html::escape($key) . ')</span>'; - } - if (isset($this->conflicts[$type][$key])) { - // Show what package the conflict is stored in. - $config = $this->featuresManager->getConfigCollection(); - $config_name = $this->featuresManager->getFullName($type, $key); - $package_name = isset($config[$config_name]) ? $config[$config_name]->getPackage() : ''; - // Get the full machine name instead of the short name. - $packages = $this->featuresManager->getPackages(); - if (isset($packages[$package_name])) { - $package_name = $packages[$package_name]->getMachineName(); - } - $value .= ' <span class="config-name">[' . $this->t('in') . ' ' . Html::escape($package_name) . ']</span>'; - } - return Xss::filterAdmin($value); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $bundle = $this->assigner->getBundle($this->bundle); - $this->assigner->assignConfigPackages(); - - $this->package->setName($form_state->getValue('name')); - $this->package->setMachineName($form_state->getValue('machine_name')); - $this->package->setDescription($form_state->getValue('description')); - $this->package->setVersion($form_state->getValue('version')); - $this->package->setDirectory($form_state->getValue('directory')); - $this->package->setBundle($bundle->getMachineName()); - // Save it first just to create it in case it's a new package. - $this->featuresManager->setPackage($this->package); - - $config = $this->updatePackageConfig($form_state); - $this->featuresManager->assignConfigPackage($this->package->getMachineName(), $config, TRUE); - $this->package->setExcluded($this->updateExcluded()); - if ($form_state->getValue('require_all')) { - $this->package->setRequired(TRUE); - } - else { - $required = $this->updateRequired(); - $this->package->setRequired($required); - } - // Now save it with the selected config data. - $this->featuresManager->setPackage($this->package); - - $method_id = NULL; - $trigger = $form_state->getTriggeringElement(); - $op = $form_state->getValue('op'); - if (!empty($trigger) && empty($op)) { - $method_id = $trigger['#name']; - } - - // Set default redirect, but allow generators to change it later. - $form_state->setRedirect('features.edit', ['featurename' => $this->package->getMachineName()]); - if ($method_id == 'import_missing') { - $this->importMissing(); - } - elseif (!empty($method_id)) { - $packages = [$this->package->getMachineName()]; - $this->generator->generatePackages($method_id, $bundle, $packages); - $this->generator->applyExportFormSubmit($method_id, $form, $form_state); - } - - $this->assigner->setCurrent($bundle); - } - - /** - * Updates the config stored in the package from the current edit form. - * - * @return array - * Config array to be exported. - */ - protected function updatePackageConfig(FormStateInterface $form_state) { - $config = []; - $components = $this->getComponentList($form_state); - foreach ($components['config_new'] as $config_type => $items) { - foreach ($items as $name) { - $config[] = $this->featuresManager->getFullName($config_type, $name); - } - } - return $config; - } - - /** - * Imports the configuration missing from the active store - */ - protected function importMissing() { - $config = $this->featuresManager->getConfigCollection(); - $missing = $this->featuresManager->reorderMissing($this->missing); - foreach ($missing as $config_name) { - if (!isset($config[$config_name])) { - $item = $this->featuresManager->getConfigType($config_name); - $type = ConfigurationItem::fromConfigStringToConfigType($item['type']); - try { - $this->configRevert->import($type, $item['name_short']); - drupal_set_message($this->t('Imported @name', ['@name' => $config_name])); - } catch (\Exception $e) { - drupal_set_message($this->t('Error importing @name : @message', - ['@name' => $config_name, '@message' => $e->getMessage()]), 'error'); - } - } - } - } - - /** - * Updates the list of excluded config. - * - * @return array - * The list of excluded config in a simple array of full config names - * suitable for storing in the info.yml file. - */ - protected function updateExcluded() { - return $this->updateConstrained('excluded'); - } - - /** - * Updates the list of required config. - * - * @return array - * The list of required config in a simple array of full config names - * suitable for storing in the info.yml file. - */ - protected function updateRequired() { - return $this->updateConstrained('required'); - } - - /** - * Returns a list of constrained (excluded or required) configuration. - * - * @param string $constraint - * The constraint (excluded or required). - * @return array - * The list of constrained config in a simple array of full config names - * suitable for storing in the info.yml file. - */ - protected function updateConstrained($constraint) { - $constrained = []; - foreach ($this->{$constraint} as $type => $item) { - foreach ($item as $name => $value) { - $constrained[] = $this->featuresManager->getFullName($type, $name); - } - } - return $constrained; - } - - /** - * Encodes a given key. - * - * @param string $key - * The key to encode. - * - * @return string - * The encoded key. - */ - protected function domEncode($key) { - $replacements = $this->domEncodeMap(); - return strtr($key, $replacements); - } - - /** - * Decodes a given key. - * - * @param string $key - * The key to decode. - * - * @return string - * The decoded key. - */ - protected function domDecode($key) { - $replacements = array_flip($this->domEncodeMap()); - return strtr($key, $replacements); - } - - /** - * Decodes an array of option values that have been encoded by - * features_dom_encode_options(). - * - * @param array $options - * The key to encode. - * @param bool $keys_only - * Whether to decode only the keys. - * - * @return array - * An array of encoded options. - */ - protected function domDecodeOptions(array $options, $keys_only = FALSE) { - $replacements = array_flip($this->domEncodeMap()); - $encoded = []; - foreach ($options as $key => $value) { - $encoded[strtr($key, $replacements)] = $keys_only ? $value : strtr($value, $replacements); - } - return $encoded; - } - - /** - * Returns encoding map for decode and encode options. - * - * @return array - * An encoding map. - */ - protected function domEncodeMap() { - return [ - ':' => '__' . ord(':') . '__', - '/' => '__' . ord('/') . '__', - ',' => '__' . ord(',') . '__', - '.' => '__' . ord('.') . '__', - '<' => '__' . ord('<') . '__', - '>' => '__' . ord('>') . '__', - '%' => '__' . ord('%') . '__', - ')' => '__' . ord(')') . '__', - '(' => '__' . ord('(') . '__', - ]; - } - -} diff --git a/web/modules/features/modules/features_ui/src/Form/FeaturesExportForm.php b/web/modules/features/modules/features_ui/src/Form/FeaturesExportForm.php deleted file mode 100644 index bed30b10e95ef052006584821bf09e15753f4da4..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Form/FeaturesExportForm.php +++ /dev/null @@ -1,561 +0,0 @@ -<?php - -namespace Drupal\features_ui\Form; - -use Drupal\Component\Utility\Html; -use Drupal\Component\Utility\Xss; -use Drupal\features\FeaturesAssignerInterface; -use Drupal\features\FeaturesGeneratorInterface; -use Drupal\features\FeaturesManagerInterface; -use Drupal\features\FeaturesBundleInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Form\FormBase; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Render\Element; -use Drupal\features\Package; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\Core\Url; - -/** - * Defines the configuration export form. - */ -class FeaturesExportForm extends FormBase { - - /** - * The features manager. - * - * @var array - */ - protected $featuresManager; - - /** - * The package assigner. - * - * @var array - */ - protected $assigner; - - /** - * The package generator. - * - * @var array - */ - protected $generator; - - /** - * The module handler service. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * Constructs a FeaturesExportForm object. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - * @param \Drupal\features\FeaturesAssignerInterface $features_assigner - * The features assigner. - * @param \Drupal\features\FeaturesGeneratorInterface $features_generator - * The features generator. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The features generator. - */ - public function __construct(FeaturesManagerInterface $features_manager, FeaturesAssignerInterface $assigner, FeaturesGeneratorInterface $generator, ModuleHandlerInterface $module_handler) { - $this->featuresManager = $features_manager; - $this->assigner = $assigner; - $this->generator = $generator; - $this->moduleHandler = $module_handler; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('features.manager'), - $container->get('features_assigner'), - $container->get('features_generator'), - $container->get('module_handler') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'features_export_form'; - } - - /** - * Detects if an element triggered the form submission via Ajax. - * TODO: SHOULDN'T NEED THIS! BUT DRUPAL IS CALLING buildForm AFTER THE - * BUNDLE AJAX IS SELECTED AND DOESN'T HAVE getTriggeringElement() SET YET. - */ - protected function elementTriggeredScriptedSubmission(FormStateInterface &$form_state) { - $input = $form_state->getUserInput(); - if (!empty($input['_triggering_element_name'])) { - return $input['_triggering_element_name']; - } - return ''; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state) { - - $trigger = $form_state->getTriggeringElement(); - // TODO: See if there is a Drupal Core issue for this. - // Sometimes the first ajax call on the page causes buildForm to be called - // twice! First time form_state->getTriggeringElement is NOT SET, but - // the form_state['input'] shows the _triggering_element_name. Then the - // SECOND time it is called the getTriggeringElement is fine. - $real_trigger = $this->elementTriggeredScriptedSubmission($form_state); - if (!isset($trigger) && ($real_trigger == 'bundle')) { - $input = $form_state->getUserInput(); - $bundle_name = $input['bundle']; - $this->assigner->setCurrent($this->assigner->getBundle($bundle_name)); - } - elseif ($trigger['#name'] == 'bundle') { - $bundle_name = $form_state->getValue('bundle', ''); - $this->assigner->setCurrent($this->assigner->getBundle($bundle_name)); - } - else { - $this->assigner->loadBundle(); - } - $current_bundle = $this->assigner->getBundle(); - $this->assigner->assignConfigPackages(); - - $packages = $this->featuresManager->getPackages(); - $config_collection = $this->featuresManager->getConfigCollection(); - - // Add in un-packaged configuration items. - $this->addUnpackaged($packages, $config_collection); - - $packages = $this->featuresManager->filterPackages($packages, $current_bundle->getMachineName()); - - // Pass the packages and bundle data for use in the form pre_render - // callback. - $form['#packages'] = $packages; - $form['#profile_package'] = $current_bundle->getProfileName(); - $form['header'] = [ - '#type' => 'container', - '#attributes' => ['class' => 'features-header'], - ]; - - $bundle_options = $this->assigner->getBundleOptions(); - - // If there are no custom bundles, provide message. - if (count($bundle_options) < 2) { - drupal_set_message($this->t('You have not yet created any bundles. Before generating features, you may wish to <a href=":create">create a bundle</a> to group your features within.', [':create' => Url::fromRoute('features.assignment')->toString()])); - } - - $form['#prefix'] = '<div id="edit-features-wrapper">'; - $form['#suffix'] = '</div>'; - $form['header']['bundle'] = [ - '#title' => $this->t('Bundle'), - '#type' => 'select', - '#options' => $bundle_options, - '#default_value' => $current_bundle->getMachineName(), - '#prefix' => '<div id="edit-package-set-wrapper">', - '#suffix' => '</div>', - '#ajax' => [ - 'callback' => '::updatePreview', - 'wrapper' => 'edit-features-preview-wrapper', - ], - '#attributes' => [ - 'data-new-package-set' => 'status', - ], - ]; - - $form['preview'] = $this->buildListing($packages, $current_bundle); - - $form['#attached'] = [ - 'library' => [ - 'features_ui/drupal.features_ui.admin', - ], - ]; - - if (\Drupal::currentUser()->hasPermission('export configuration')) { - // Offer available generation methods. - $generation_info = $this->generator->getGenerationMethods(); - // Sort generation methods by weight. - uasort($generation_info, '\Drupal\Component\Utility\SortArray::sortByWeightElement'); - - $form['description'] = [ - '#markup' => '<p>' . $this->t('Use an export method button below to generate the selected features.') . '</p>', - ]; - - $form['actions'] = ['#type' => 'actions', '#tree' => TRUE]; - foreach ($generation_info as $method_id => $method) { - $form['actions'][$method_id] = [ - '#type' => 'submit', - '#name' => $method_id, - '#value' => $this->t('@name', ['@name' => $method['name']]), - '#attributes' => [ - 'title' => Html::escape($method['description']), - ], - ]; - } - } - - $form['#pre_render'][] = [get_class($this), 'preRenderRemoveInvalidCheckboxes']; - - return $form; - } - - /** - * Handles switching the configuration type selector. - */ - public function updatePreview($form, FormStateInterface $form_state) { - // We should really be able to add this pre_render callback to the - // 'preview' element. However, since doing so leads to an error (no rows - // are displayed), we need to instead explicitly invoke it here for the - // processing to apply to the Ajax-rendered form element. - $form = $this->preRenderRemoveInvalidCheckboxes($form); - return $form['preview']; - } - - /** - * Builds the portion of the form showing a listing of features. - * - * @param \Drupal\features\Package[] $packages - * The packages. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * The current bundle - * - * @return array - * A render array of a form element. - */ - protected function buildListing(array $packages, FeaturesBundleInterface $bundle) { - - $header = [ - 'name' => ['data' => $this->t('Feature')], - 'machine_name' => ['data' => $this->t('')], - 'details' => ['data' => $this->t('Description'), 'class' => [RESPONSIVE_PRIORITY_LOW]], - 'version' => ['data' => $this->t('Version'), 'class' => [RESPONSIVE_PRIORITY_LOW]], - 'status' => ['data' => $this->t('Status'), 'class' => [RESPONSIVE_PRIORITY_LOW]], - 'state' => ['data' => $this->t('State'), 'class' => [RESPONSIVE_PRIORITY_LOW]], - ]; - - $options = []; - $first = TRUE; - foreach ($packages as $package) { - if ($first && $package->getStatus() == FeaturesManagerInterface::STATUS_NO_EXPORT) { - // Don't offer new non-profile packages that are empty. - if ($package->getStatus() === FeaturesManagerInterface::STATUS_NO_EXPORT && - !$bundle->isProfilePackage($package->getMachineName()) && - empty($package->getConfig())) { - continue; - } - $first = FALSE; - $options[] = [ - 'name' => [ - 'data' => $this->t('The following packages are not exported.'), - 'class' => 'features-export-header-row', - 'colspan' => 6, - ], - ]; - } - $options[$package->getMachineName()] = $this->buildPackageDetail($package, $bundle); - } - - $element = [ - '#type' => 'tableselect', - '#header' => $header, - '#options' => $options, - '#attributes' => ['class' => ['features-listing']], - '#prefix' => '<div id="edit-features-preview-wrapper">', - '#suffix' => '</div>', - ]; - - return $element; - } - - /** - * Builds the details of a package. - * - * @param \Drupal\features\Package $package - * The package. - * @param \Drupal\features\FeaturesBundleInterface - * The current bundle. - * - * @return array - * A render array of a form element. - */ - protected function buildPackageDetail(Package $package, FeaturesBundleInterface $bundle) { - $config_collection = $this->featuresManager->getConfigCollection(); - - $url = Url::fromRoute('features.edit', ['featurename' => $package->getMachineName()]); - - $element['name'] = [ - 'data' => \Drupal::l($package->getName(), $url), - 'class' => ['feature-name'], - ]; - $machine_name = $package->getMachineName(); - // Except for the 'unpackaged' pseudo-package, display the full name, since - // that's what will be generated. - if ($machine_name !== 'unpackaged') { - $machine_name = $bundle->getFullName($machine_name); - } - $element['machine_name'] = $machine_name; - $element['status'] = [ - 'data' => $this->featuresManager->statusLabel($package->getStatus()), - 'class' => ['column-nowrap'], - ]; - // Use 'data' instead of plain string value so a blank version doesn't - // remove column from table. - $element['version'] = [ - 'data' => Html::escape($package->getVersion()), - 'class' => ['column-nowrap'], - ]; - $overrides = $this->featuresManager->detectOverrides($package); - $new_config = $this->featuresManager->detectNew($package); - $conflicts = []; - $missing = []; - $moved = []; - - if ($package->getStatus() == FeaturesManagerInterface::STATUS_NO_EXPORT) { - $overrides = []; - $new_config = []; - } - // Bundle package configuration by type. - $package_config = []; - foreach ($package->getConfig() as $item_name) { - if (isset($config_collection[$item_name])) { - $item = $config_collection[$item_name]; - $package_config[$item->getType()][] = [ - 'name' => Html::escape($item_name), - 'label' => Html::escape($item->getLabel()), - 'class' => in_array($item_name, $overrides) ? 'features-override' : - (in_array($item_name, $new_config) ? 'features-detected' : ''), - ]; - } - } - // Conflict config from other modules. - foreach ($package->getConfigOrig() as $item_name) { - if (!isset($config_collection[$item_name])) { - $missing[] = $item_name; - $package_config['missing'][] = [ - 'name' => Html::escape($item_name), - 'label' => Html::escape($item_name), - 'class' => 'features-missing', - ]; - } - elseif (!in_array($item_name, $package->getConfig())) { - $item = $config_collection[$item_name]; - if (empty($item->getProvider())) { - $conflicts[] = $item_name; - $package_name = !empty($item->getPackage()) ? $item->getPackage() : $this->t('PACKAGE NOT ASSIGNED'); - $package_config[$item->getType()][] = [ - 'name' => Html::escape($package_name), - 'label' => Html::escape($item->getLabel()), - 'class' => 'features-conflict', - ]; - } - else { - $moved[] = $item_name; - $package_name = !empty($item->getPackage()) ? $item->getPackage() : $this->t('PACKAGE NOT ASSIGNED'); - $package_config[$item->getType()][] = [ - 'name' => $this->t('Moved to @package', ['@package' => $package_name]), - 'label' => Html::escape($item->getLabel()), - 'class' => 'features-moved', - ]; - } - } - } - // Add dependencies. - $package_config['dependencies'] = []; - foreach ($package->getDependencies() as $dependency) { - $package_config['dependencies'][] = [ - 'name' => $dependency, - 'label' => $this->moduleHandler->moduleExists($dependency) ? $this->moduleHandler->getName($dependency) : $dependency, - 'class' => '', - ]; - } - - $class = ''; - $state_links = []; - if (!empty($conflicts)) { - $state_links[] = [ - '#type' => 'link', - '#title' => $this->t('Conflicts'), - '#url' => Url::fromRoute('features.edit', ['featurename' => $package->getMachineName()]), - '#attributes' => ['class' => ['features-conflict']], - ]; - } - if (!empty($overrides)) { - $state_links[] = [ - '#type' => 'link', - '#title' => $this->featuresManager->stateLabel(FeaturesManagerInterface::STATE_OVERRIDDEN), - '#url' => Url::fromRoute('features.diff', ['featurename' => $package->getMachineName()]), - '#attributes' => ['class' => ['features-override']], - ]; - } - if (!empty($new_config)) { - $state_links[] = [ - '#type' => 'link', - '#title' => $this->t('New detected'), - '#url' => Url::fromRoute('features.diff', ['featurename' => $package->getMachineName()]), - '#attributes' => ['class' => ['features-detected']], - ]; - } - if (!empty($missing) && ($package->getStatus() == FeaturesManagerInterface::STATUS_INSTALLED)) { - $state_links[] = [ - '#type' => 'link', - '#title' => $this->t('Missing'), - '#url' => Url::fromRoute('features.edit', ['featurename' => $package->getMachineName()]), - '#attributes' => ['class' => ['features-missing']], - ]; - } - if (!empty($moved)) { - $state_links[] = [ - '#type' => 'link', - '#title' => $this->t('Moved'), - '#url' => Url::fromRoute('features.edit', ['featurename' => $package->getMachineName()]), - '#attributes' => ['class' => ['features-moved']], - ]; - } - if (!empty($state_links)) { - $element['state'] = [ - 'data' => $state_links, - 'class' => ['column-nowrap'], - ]; - } - else { - $element['state'] = ''; - } - - $config_types = $this->featuresManager->listConfigTypes(); - // Add dependencies. - $config_types['dependencies'] = $this->t('Dependencies'); - $config_types['missing'] = $this->t('Missing'); - uasort($config_types, 'strnatcasecmp'); - - $rows = array(); - // Use sorted array for order. - foreach ($config_types as $type => $label) { - // For each component type, offer alternating rows. - $row = array(); - if (isset($package_config[$type])) { - $row[] = array( - 'data' => array( - '#type' => 'html_tag', - '#tag' => 'span', - '#value' => Html::escape($label), - '#attributes' => array( - 'title' => Html::escape($type), - 'class' => 'features-item-label', - ), - ), - ); - $row[] = array( - 'data' => array( - '#theme' => 'features_items', - '#items' => $package_config[$type], - '#value' => Html::escape($label), - '#title' => Html::escape($type), - ), - 'class' => 'item', - ); - $rows[] = $row; - } - } - $element['table'] = array( - '#type' => 'table', - '#rows' => $rows, - ); - - $details = array(); - $details['description'] = array( - '#markup' => Xss::filterAdmin($package->getDescription()), - ); - $details['table'] = array( - '#type' => 'details', - '#title' => $this->t('Included configuration'), - '#description' => array('data' => $element['table']), - ); - $element['details'] = array( - 'class' => array('description', 'expand'), - 'data' => $details, - ); - - return $element; - } - - /** - * Adds a pseudo-package to display unpackaged configuration. - * - * @param array $packages - * An array of package names. - * @param \Drupal\features\ConfigurationItem[] $config_collection - * A collection of configuration. - */ - protected function addUnpackaged(array &$packages, array $config_collection) { - $packages['unpackaged'] = new Package('unpackaged', [ - 'name' => $this->t('Unpackaged'), - 'description' => $this->t('Configuration that has not been added to any package.'), - 'config' => [], - 'status' => FeaturesManagerInterface::STATUS_NO_EXPORT, - 'version' => '', - ]); - foreach ($config_collection as $item_name => $item) { - if (!$item->getPackage() && !$item->isExcluded() && !$item->isProviderExcluded()) { - $packages['unpackaged']->appendConfig($item_name); - } - } - } - - /** - * Denies access to the checkboxes for uninstalled or empty packages and the - * "unpackaged" pseudo-package. - * - * @param array $form - * The form build array to alter. - * - * @return array - * The form build array. - */ - public static function preRenderRemoveInvalidCheckboxes(array $form) { - /** @var \Drupal\features\Package $package */ - foreach ($form['#packages'] as $package) { - // Remove checkboxes for packages that: - // - have no configuration assigned and are not the profile, or - // - are the "unpackaged" pseudo-package. - if ((empty($package->getConfig()) && !($package->getMachineName() == $form['#profile_package'])) || - $package->getMachineName() == 'unpackaged') { - $form['preview'][$package->getMachineName()]['#access'] = FALSE; - } - } - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $current_bundle = $this->assigner->loadBundle(); - $this->assigner->assignConfigPackages(); - - $package_names = array_filter($form_state->getValue('preview')); - - if (empty($package_names)) { - drupal_set_message($this->t('Please select one or more packages to export.'), 'warning'); - return; - } - - $method_id = NULL; - $trigger = $form_state->getTriggeringElement(); - $op = $form_state->getValue('op'); - if (!empty($trigger) && empty($op)) { - $method_id = $trigger['#name']; - } - - if (!empty($method_id)) { - $this->generator->generatePackages($method_id, $current_bundle, $package_names); - $this->generator->applyExportFormSubmit($method_id, $form, $form_state); - } - } - -} diff --git a/web/modules/features/modules/features_ui/src/Tests/FeaturesBundleUITest.php b/web/modules/features/modules/features_ui/src/Tests/FeaturesBundleUITest.php deleted file mode 100644 index 091c55e22f39e7c2f87082b8d7ef6cef2b7b6e13..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Tests/FeaturesBundleUITest.php +++ /dev/null @@ -1,188 +0,0 @@ -<?php - -namespace Drupal\features_ui\Tests; - -use Drupal\Core\Entity\EntityStorageInterface; -use Drupal\features\FeaturesBundleInterface; -use Drupal\simpletest\WebTestBase; -use Drupal\Core\StringTranslation\StringTranslationTrait; - -/** - * Tests configuring bundles. - * - * @group features_ui - */ -class FeaturesBundleUITest extends WebTestBase { - use StringTranslationTrait; - - /** - * @todo Remove the disabled strict config schema checking. - */ - protected $strictConfigSchema = FALSE; - - /** - * {@inheritdoc} - */ - public static $modules = ['block', 'features', 'features_ui']; - - /** - * The features bundle storage. - * - * @var \Drupal\Core\Entity\EntityStorageInterface $bundleStorage - */ - protected $bundleStorage; - - /** - * {@inheritdoc} - */ - public function setUp() { - parent::setUp(); - $this->bundleStorage = \Drupal::entityTypeManager()->getStorage('features_bundle'); - - $admin_user = $this->createUser(['administer site configuration', 'export configuration', 'administer modules']); - $this->drupalLogin($admin_user); - $this->drupalPlaceBlock('local_actions_block'); - } - - /** - * Get the default features bundle. - * - * @return \Drupal\features\FeaturesBundleInterface - * The features bundle. - */ - protected function defaultBundle() { - return $this->bundleStorage->load(FeaturesBundleInterface::DEFAULT_BUNDLE); - } - - /** - * Completely remove a features assignment method from the bundle. - * - * @param string $method_id - * The assignment method ID. - */ - protected function removeAssignment($method_id) { - $bundle = $this->defaultBundle(); - $assignments = $bundle->get('assignments'); - unset($assignments[$method_id]); - $bundle->set('assignments', $assignments); - $bundle->save(); - } - - /** - * Tests configuring an assignment. - */ - public function testAssignmentConfigure() { - // Check initial values. - $settings = $this->defaultBundle()->getAssignmentSettings('exclude'); - $this->assertTrue(isset($settings['types']['config']['features_bundle']), 'Excluding features_bundle'); - $this->assertFalse(isset($settings['types']['config']['system_simple']), 'Not excluding system_simple'); - $this->assertFalse(isset($settings['types']['config']['user_role']), 'Not excluding user_role'); - $this->assertTrue($settings['curated'], 'Excluding curated items'); - $this->assertTrue($settings['module']['namespace'], 'Excluding by namespace'); - - // Check initial form. - $this->drupalGet('admin/config/development/features/bundle/_exclude/default'); - $this->assertFieldChecked('edit-types-config-features-bundle', 'features_bundle is checked'); - $this->assertNoFieldChecked('edit-types-config-system-simple', 'system_simple is not checked'); - $this->assertNoFieldChecked('edit-types-config-user-role', 'user_role is not checked'); - $this->assertFieldChecked('edit-curated', 'curated is checked'); - $this->assertFieldChecked('edit-module-namespace', 'namespace is checked'); - - // Configure the form. - $this->drupalPostForm(NULL, [ - 'types[config][system_simple]' => TRUE, - 'types[config][user_role]' => FALSE, - 'curated' => TRUE, - 'module[namespace]' => FALSE, - ], $this->t('Save settings')); - - // Check form results. - $this->drupalGet('admin/config/development/features/bundle/_exclude/default'); - $this->assertFieldChecked('edit-types-config-features-bundle', 'Saved, features_bundle is checked'); - $this->assertFieldChecked('edit-types-config-system-simple', 'Saved, system_simple is checked'); - $this->assertNoFieldChecked('edit-types-config-user-role', 'Saved, user_role is not checked'); - $this->assertFieldChecked('edit-curated', 'Saved, curated is checked'); - $this->assertNoFieldChecked('edit-module-namespace', 'Saved, namespace is not checked'); - - // Check final values. - $settings = $this->defaultBundle()->getAssignmentSettings('exclude'); - $this->assertTrue(isset($settings['types']['config']['features_bundle']), 'Saved, excluding features_bundle'); - $this->assertTrue(isset($settings['types']['config']['system_simple']), 'Saved, excluding system_simple'); - $this->assertFalse(isset($settings['types']['config']['user_role']), 'Saved, not excluding user_role'); - $this->assertTrue($settings['curated'], 'Saved, excluding curated items'); - $this->assertFalse($settings['module']['namespace'], 'Saved, not excluding by namespace'); - } - - /** - * Tests configuring an assignment that didn't exist before. - */ - public function testNewAssignmentConfigure() { - $this->removeAssignment('exclude'); - - // Is it really removed? - $all_settings = $this->defaultBundle()->getAssignmentSettings(); - $this->assertFalse(isset($all_settings['exclude']), 'Exclude plugin is unknown'); - - // Can still get settings. - $settings = $this->defaultBundle()->getAssignmentSettings('exclude'); - $this->assertFalse($settings['enabled'], 'Disabled exclude plugin'); - $this->assertFalse(isset($settings['types']['config']['features_bundle']), 'Not excluding features_bundle'); - $this->assertFalse(isset($settings['types']['config']['system_simple']), 'Not excluding system_simple'); - $this->assertFalse(isset($settings['types']['config']['user_role']), 'Not excluding user_role'); - $this->assertFalse($settings['curated'], 'Not excluding curated items'); - $this->assertFalse($settings['module']['namespace'], 'Not excluding by namespace'); - - // Can we visit the config page with no settings? - $this->drupalGet('admin/config/development/features/bundle/_exclude/default'); - $this->assertNoFieldChecked('edit-types-config-features-bundle', 'features_bundle is not checked'); - $this->assertNoFieldChecked('edit-types-config-system-simple', 'system_simple is not checked'); - $this->assertNoFieldChecked('edit-types-config-user-role', 'user_role is not checked'); - $this->assertNoFieldChecked('edit-curated', 'curated is not checked'); - $this->assertNoFieldChecked('edit-module-namespace', 'namespace is not checked'); - - // Can we enable the method? - $this->drupalGet('admin/config/development/features/bundle'); - $this->assertNoFieldChecked('edit-enabled-exclude', 'Exclude disabled'); - $this->drupalPostForm(NULL, [ - 'enabled[exclude]' => TRUE, - ], $this->t('Save settings')); - $this->assertFieldChecked('edit-enabled-exclude', 'Exclude enabled'); - - // Check new settings. - $settings = $this->defaultBundle()->getAssignmentSettings('exclude'); - $this->assertTrue($settings['enabled'], 'Enabled exclude plugin'); - $this->assertFalse(isset($settings['types']['config']['features_bundle']), 'Not excluding features_bundle'); - $this->assertFalse(isset($settings['types']['config']['system_simple']), 'Not excluding system_simple'); - $this->assertFalse(isset($settings['types']['config']['user_role']), 'Not excluding user_role'); - $this->assertFalse($settings['curated'], 'Not excluding curated items'); - $this->assertFalse($settings['module']['namespace'], 'Not excluding by namespace'); - - // Can we run assignment with no settings? - $this->drupalGet('admin/config/development/features'); - - // Can we configure the method? - $this->drupalPostForm('admin/config/development/features/bundle/_exclude/default', [ - 'types[config][system_simple]' => TRUE, - 'types[config][user_role]' => FALSE, - 'curated' => TRUE, - 'module[namespace]' => FALSE, - ], $this->t('Save settings')); - - // Check form results. - $this->drupalGet('admin/config/development/features/bundle/_exclude/default'); - $this->assertNoFieldChecked('edit-types-config-features-bundle', 'Saved, features_bundle is not checked'); - $this->assertFieldChecked('edit-types-config-system-simple', 'Saved, system_simple is checked'); - $this->assertNoFieldChecked('edit-types-config-user-role', 'Saved, user_role is not checked'); - $this->assertFieldChecked('edit-curated', 'Saved, curated is checked'); - $this->assertNoFieldChecked('edit-module-namespace', 'Saved, namespace is not checked'); - - // Check final values. - $settings = $this->defaultBundle()->getAssignmentSettings('exclude'); - $this->assertFalse(isset($settings['types']['config']['features_bundle']), 'Saved, not excluding features_bundle'); - $this->assertTrue(isset($settings['types']['config']['system_simple']), 'Saved, excluding system_simple'); - $this->assertFalse(isset($settings['types']['config']['user_role']), 'Saved, not excluding user_role'); - $this->assertTrue($settings['curated'], 'Saved, excluding curated items'); - $this->assertFalse($settings['module']['namespace'], 'Saved, not excluding by namespace'); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Tests/FeaturesCreateUITest.php b/web/modules/features/modules/features_ui/src/Tests/FeaturesCreateUITest.php deleted file mode 100644 index 70c1da4d39caa3ba43cbefa0af0c6cd26bd057ee..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Tests/FeaturesCreateUITest.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -namespace Drupal\features_ui\Tests; - -use Drupal\Component\Serialization\Yaml; -use Drupal\Core\Archiver\ArchiveTar; -use Drupal\simpletest\WebTestBase; -use Drupal\Core\StringTranslation\StringTranslationTrait; - -/** - * Tests the creation of a feature. - * - * @group features_ui - */ -class FeaturesCreateUITest extends WebTestBase { - use StringTranslationTrait; - - /** - * @todo Remove the disabled strict config schema checking. - */ - protected $strictConfigSchema = FALSE; - - /** - * {@inheritdoc} - */ - public static $modules = ['block', 'features', 'features_ui']; - - /** - * Tests creating a feature via UI and download it. - */ - public function testCreateFeaturesUI() { - list($major, $minor, ) = explode('.', \Drupal::VERSION); - // In D8.3 the module category was removed from the module name field. - $name_prefix = (intval($major) == 8 && intval($minor) > 2) ? 'modules[' : 'modules[Other]['; - - $feature_name = 'test_feature2'; - $admin_user = $this->createUser(['administer site configuration', 'export configuration', 'administer modules']); - $this->drupalLogin($admin_user); - $this->drupalPlaceBlock('local_actions_block'); - $this->drupalGet('admin/config/development/features'); - $this->clickLink('Create new feature'); - $this->assertResponse(200); - - $edit = [ - 'name' => 'Test feature', - 'machine_name' => $feature_name, - 'description' => 'Test description: <strong>giraffe</strong>', - 'version' => '8.x-1.0', - 'system_simple[sources][selected][system.theme]' => TRUE, - 'system_simple[sources][selected][user.settings]' => TRUE, - ]; - $this->drupalPostForm(NULL, $edit, $this->t('Download Archive')); - - $this->assertResponse(200); - $archive = $this->getRawContent(); - $filename = tempnam($this->tempFilesDirectory, 'feature'); - file_put_contents($filename, $archive); - - $archive = new ArchiveTar($filename); - $files = $archive->listContent(); - - $this->assertEqual(4, count($files)); - $this->assertEqual($feature_name . '/' . $feature_name . '.info.yml', $files[0]['filename']); - $this->assertEqual($feature_name . '/' . $feature_name . '.features.yml', $files[1]['filename']); - $this->assertEqual($feature_name . '/config/install/system.theme.yml', $files[2]['filename']); - $this->assertEqual($feature_name . '/config/install/user.settings.yml', $files[3]['filename']); - - // Ensure that the archive contains the expected values. - $info_filename = tempnam($this->tempFilesDirectory, 'feature'); - file_put_contents($info_filename, $archive->extractInString($feature_name . '/' . $feature_name . '.info.yml')); - $features_info_filename = tempnam($this->tempFilesDirectory, 'feature'); - file_put_contents($features_info_filename, $archive->extractInString($feature_name . '/' . $feature_name . '.features.yml')); - /** @var \Drupal\Core\Extension\InfoParser $info_parser */ - $info_parser = \Drupal::service('info_parser'); - $parsed_info = $info_parser->parse($info_filename); - $this->assertEqual('Test feature', $parsed_info['name']); - $parsed_features_info = Yaml::decode(file_get_contents($features_info_filename)); - $this->assertEqual([ - 'required' => ['system.theme', 'user.settings'], - ], $parsed_features_info); - - $archive->extract(\Drupal::service('kernel')->getSitePath() . '/modules'); - $module_path = \Drupal::service('kernel')->getSitePath() . '/modules/' . $feature_name; - - // Ensure that the features listing renders the right content. - $this->drupalGet('admin/config/development/features'); - $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0]; - $this->assertLink('Test feature'); - $this->assertEqual($feature_name, (string) $tr->children()[2]); - $description_column = (string) $tr->children()[3]->asXml(); - $this->assertTrue(strpos($description_column, 'system.theme') !== FALSE); - $this->assertTrue(strpos($description_column, 'user.settings') !== FALSE); - $this->assertRaw('Test description: <strong>giraffe</strong>'); - $this->assertEqual('Uninstalled', (string) $tr->children()[5]); - $this->assertEqual('', (string) $tr->children()[6]); - - // Remove one and add new configuration. - $this->clickLink('Test feature'); - $edit = [ - 'system_simple[included][system.theme]' => FALSE, - 'user_role[sources][selected][authenticated]' => TRUE, - ]; - $this->drupalPostForm(NULL, $edit, $this->t('Write')); - $info_filename = $module_path . '/' . $feature_name . '.info.yml'; - - $parsed_info = $info_parser->parse($info_filename); - $this->assertEqual('Test feature', $parsed_info['name']); - - $features_info_filename = $module_path . '/' . $feature_name . '.features.yml'; - $parsed_features_info = Yaml::decode(file_get_contents($features_info_filename)); - $this->assertEqual([ - 'excluded' => ['system.theme'], - 'required' => true, - ], $parsed_features_info); - - $this->drupalGet('admin/modules'); - $edit = [ - $name_prefix . $feature_name . '][enable]' => TRUE, - ]; - $this->drupalPostForm(NULL, $edit, $this->t('Install')); - - // Check that the feature is listed as installed. - $this->drupalGet('admin/config/development/features'); - - $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0]; - $this->assertEqual('Installed', (string) $tr->children()[5]); - - // Check that a config change results in a feature marked as changed. - \Drupal::configFactory()->getEditable('user.settings') - ->set('anonymous', 'Anonymous giraffe') - ->save(); - - $this->drupalGet('admin/config/development/features'); - - $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0]; - $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE); - - // Uninstall module. - $this->drupalPostForm('admin/modules/uninstall', [ - 'uninstall[' . $feature_name . ']' => TRUE, - ], $this->t('Uninstall')); - $this->drupalPostForm(NULL, [], $this->t('Uninstall')); - - $this->drupalGet('admin/config/development/features'); - - $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0]; - $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE); - - $this->clickLink($this->t('Changed')); - $this->drupalGet('admin/config/development/features/diff/' . $feature_name); - $this->assertRaw('<td class="diff-context diff-deletedline">anonymous : Anonymous <span class="diffchange">giraffe</span></td>'); - $this->assertRaw('<td class="diff-context diff-addedline">anonymous : Anonymous</td>'); - - $this->drupalGet('admin/modules'); - $edit = [ - $name_prefix . $feature_name . '][enable]' => TRUE, - ]; - $this->drupalPostForm(NULL, $edit, $this->t('Install')); - $this->drupalGet('admin/config/development/features'); - $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0]; - $this->assertEqual('Installed', (string) $tr->children()[5]); - - // Ensure that the changed config got overridden. - $this->assertEqual('Anonymous', \Drupal::config('user.settings')->get('anonymous')); - - // Change the value, export and ensure that its not shown as changed. - \Drupal::configFactory()->getEditable('user.settings') - ->set('anonymous', 'Anonymous giraffe') - ->save(); - - // Ensure that exporting this change will result in an unchanged feature. - $this->drupalGet('admin/config/development/features'); - $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0]; - $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE); - - $this->clickLink('Test feature'); - $this->drupalPostForm(NULL, [], $this->t('Write')); - - $this->drupalGet('admin/config/development/features'); - $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0]; - $this->assertEqual('Installed', (string) $tr->children()[5]); - } - -} diff --git a/web/modules/features/modules/features_ui/src/Tests/FeaturesUITest.php b/web/modules/features/modules/features_ui/src/Tests/FeaturesUITest.php deleted file mode 100644 index 12f92ae5be9b5c5b31037bdce8a5ee26e2c2d39f..0000000000000000000000000000000000000000 --- a/web/modules/features/modules/features_ui/src/Tests/FeaturesUITest.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -namespace Drupal\features_ui\Tests; - -use Drupal\simpletest\WebTestBase; -use Drupal\Core\StringTranslation\StringTranslationTrait; - -/** - * Tests the creation of a feature. - * - * @group features_ui - */ -class FeaturesUITest extends WebTestBase { - use StringTranslationTrait; - - /** - * @todo Remove the disabled strict config schema checking. - */ - protected $strictConfigSchema = FALSE; - - /** - * {@inheritdoc} - */ - public static $modules = ['features', 'features_ui']; - - /** - * Tests creating a feature via UI and download it. - */ - public function testFeaturesUI() { - $admin_user = $this->drupalCreateUser(['administer site configuration', 'export configuration', 'administer modules']); - $this->drupalLogin($admin_user); - $this->drupalGet('admin/config/development/features'); - // Check the message is displaying if there are no custom bundles. - $this->assertText($this->t('You have not yet created any bundles. Before generating features, you may wish to create a bundle to group your features within.')); - // Creating custom bundle. - $this->drupalGet('admin/config/development/features/bundle'); - $this->drupalPostAjaxForm(NULL, ['bundle[bundle_select]' => 'new'], 'bundle[bundle_select]'); - $edit = [ - 'bundle[name]' => 'foo', - 'bundle[machine_name]' => 'foo', - 'bundle[description]' => $this->randomString(), - ]; - $this->drupalPostForm(NULL, $edit, $this->t('Save settings')); - $this->drupalGet('admin/config/development/features'); - // Check the message is not displaying if there are custom bundles. - $this->assertNoText($this->t('You have not yet created any bundles. Before generating features, you may wish to create a bundle to group your features within.')); - } - -} diff --git a/web/modules/features/src/Commands/FeaturesCommands.php b/web/modules/features/src/Commands/FeaturesCommands.php deleted file mode 100644 index a0dec38e30d46f31d88d9c0a65f73b5d8e2cb2fb..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Commands/FeaturesCommands.php +++ /dev/null @@ -1,1053 +0,0 @@ -<?php - -namespace Drupal\features\Commands; - -use Consolidation\OutputFormatters\StructuredData\RowsOfFields; -use Drupal\Component\Diff\DiffFormatter; -use Drupal\config_update\ConfigDiffInterface; -use Drupal\Core\Config\StorageInterface; -use Drupal\features\Exception\DomainException; -use Drupal\features\Exception\InvalidArgumentException; -use Drupal\features\FeaturesAssignerInterface; -use Drupal\features\FeaturesBundleInterface; -use Drupal\features\FeaturesGeneratorInterface; -use Drupal\features\FeaturesManagerInterface; -use Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite; -use Drush\Commands\DrushCommands; -use Drush\Exceptions\UserAbortException; -use Drush\Utils\StringUtils; - -/** - * Drush commands for Features. - */ -class FeaturesCommands extends DrushCommands { - - const OPTIONS =[ - 'bundle' => NULL, - ]; - - const OPTIONS_ADD = self::OPTIONS; - - const OPTIONS_COMPONENTS = self::OPTIONS + [ - 'exported' => NULL, - 'format' => 'table', - 'not-exported' => NULL, - ]; - - const OPTIONS_DIFF = self::OPTIONS + [ - 'ctypes' => NULL, - 'lines' => NULL, - ]; - - const OPTIONS_EXPORT = self::OPTIONS + [ - 'add-profile' => NULL, - ]; - - const OPTIONS_IMPORT = self::OPTIONS + [ - 'force' => NULL, - ]; - - const OPTIONS_IMPORT_ALL = self::OPTIONS; - - const OPTIONS_LIST = self::OPTIONS + [ - 'format' => 'table', - ]; - - const OPTIONS_STATUS = self::OPTIONS; - - /** - * The features_assigner service. - * - * @var \Drupal\features\FeaturesAssignerInterface - */ - protected $assigner; - - /** - * The features.manager service. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $manager; - - /** - * The features_generator service. - * - * @var \Drupal\features\FeaturesGeneratorInterface - */ - protected $generator; - - /** - * The config_update.config_diff service. - * - * @var \Drupal\config_update\ConfigDiffInterface - */ - protected $configDiff; - - /** - * The config.storage service. - * - * @var \Drupal\Core\Config\StorageInterface - */ - protected $configStorage; - - /** - * FeaturesCommands constructor. - * - * @param \Drupal\features\FeaturesAssignerInterface $assigner - * The features_assigner service. - * @param \Drupal\features\FeaturesManagerInterface $manager - * The features.manager service. - * @param \Drupal\features\FeaturesGeneratorInterface $generator - * The features_generator service. - * @param \Drupal\config_update\ConfigDiffInterface $configDiff - * The config_update.config_diff service. - * @param \Drupal\Core\Config\StorageInterface $configStorage - * The config.storage service. - */ - public function __construct( - FeaturesAssignerInterface $assigner, - FeaturesManagerInterface $manager, - FeaturesGeneratorInterface $generator, - ConfigDiffInterface $configDiff, - StorageInterface $configStorage - ) { - parent::__construct(); - $this->assigner = $assigner; - $this->configDiff = $configDiff; - $this->configStorage = $configStorage; - $this->generator = $generator; - $this->manager = $manager; - } - - /** - * Applies global options for Features drush commands, including the bundle. - * - * The option --name="bundle_name" sets the bundle namespace. - * - * @return \Drupal\features\FeaturesAssignerInterface - * The features.assigner with options applied. - */ - protected function featuresOptions(array $options) { - $bundleName = $this->getOption($options, 'bundle'); - if (!empty($bundleName)) { - $bundle = $this->assigner->applyBundle($bundleName); - if ($bundle->getMachineName() !== $bundleName) { - $this->logger()->warning('Bundle {name} not found. Using default.', [ - 'name' => $bundleName, - ]); - } - } - else { - $this->assigner->assignConfigPackages(); - } - return $this->assigner; - } - - /** - * Get the value of an option. - * - * @param array $options - * The options array. - * @param string $name - * The option name. - * @param mixed $default - * The default value of the option. - * - * @return mixed|null - * The option value, defaulting to NULL. - */ - protected function getOption(array $options, $name, $default = NULL) { - return isset($options[$name]) - ? $options[$name] - : $default; - } - - /** - * Display current Features settings. - * - * @param string $keys - * A possibly empty, comma-separated, list of config information to display. - * - * @command features:status - * - * @option bundle Use a specific bundle namespace. - * - * @aliases fs,features-status - */ - public function status($keys = NULL, array $options = self::OPTIONS_STATUS) { - $this->featuresOptions($options); - - $currentBundle = $this->assigner->getBundle(); - $export_settings = $this->manager->getExportSettings(); - $methods = $this->assigner->getEnabledAssigners(); - $output = $this->output(); - if ($currentBundle->isDefault()) { - $output->writeln(dt('Current bundle: none')); - } - else { - $output->writeln(dt('Current bundle: @name (@machine_name)', [ - '@name' => $currentBundle->getName(), - '@machine_name' => $currentBundle->getMachineName(), - ])); - } - $output->writeln(dt('Export folder: @folder', [ - '@folder' => $export_settings['folder'], - ])); - $output - ->writeln(dt('The following assignment methods are enabled:')); - $output->writeln(dt(' @methods', [ - '@methods' => implode(', ', array_keys($methods)), - ])); - - if (!empty($keys)) { - $config = $this->manager->getConfigCollection(); - $keys = StringUtils::csvToArray($keys); - $data = count($keys) > 1 - ? array_keys($config) - : $config[$keys[0]]; - $output->writeln(print_r($data, TRUE)); - } - } - - /** - * Display a list of all generate-able existing features and packages. - * - * If a package name is provided as an argument, then all of the configuration - * objects assigned to that package will be listed. - * - * @param string $package_name - * The package to list. Optional; if specified, lists all configuration - * objects assigned to that package. If no package is specified, lists all - * of the features. - * - * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields|bool - * The command output, or FALSE if a requested package was not found. - * - * @command features:list:packages - * - * @option bundle Use a specific bundle namespace. - * - * @usage drush features:list:packages - * Display a list of all existing features and packages available to be - * generated. - * @usage drush features:list:packages 'example_article' - * Display a list of all configuration objects assigned to the - * 'example_article' package. - * - * @field-labels - * config: Config - * name: Name - * machine_name: Machine name - * status: Status - * version: Version - * state: State - * - * @aliases fl,features-list-packages - */ - public function listPackages($package_name = NULL, $options = self::OPTIONS_LIST) { - $assigner = $this->featuresOptions($options); - $current_bundle = $assigner->getBundle(); - $namespace = $current_bundle->isDefault() ? FeaturesBundleInterface::DEFAULT_BUNDLE : $current_bundle->getMachineName(); - - $manager = $this->manager; - $packages = $manager->getPackages(); - - $packages = $manager->filterPackages($packages, $namespace); - $result = []; - - // If no package was specified, list all packages. - if (empty($package_name)) { - foreach ($packages as $package) { - $overrides = $manager->detectOverrides($package); - $state = $package->getState(); - if (!empty($overrides) && ($package->getStatus() != FeaturesManagerInterface::STATUS_NO_EXPORT)) { - $state = FeaturesManagerInterface::STATE_OVERRIDDEN; - } - - $packageState = ($state != FeaturesManagerInterface::STATE_DEFAULT) - ? $manager->stateLabel($state) - : ''; - - $result[$package->getMachineName()] = [ - 'name' => $package->getName(), - 'machine_name' => $package->getMachineName(), - 'status' => $manager->statusLabel($package->getStatus()), - 'version' => $package->getVersion(), - 'state' => $packageState, - ]; - } - return new RowsOfFields($result); - } - - // A valid package was listed. - $package = $this->manager->findPackage($package_name); - - // If no matching package found, return an error. - if (empty($package)) { - $this->logger()->warning(dt('Package "@package" not found.', [ - '@package' => $package_name, - ])); - return FALSE; - } - - // This is a valid package, list its configuration. - $config = array_map(function ($name) { - return ['config' => $name]; - }, $package->getConfig()); - - return new RowsOfFields($config); - } - - /** - * Import module config from all installed features. - * - * @command features:import:all - * - * @option bundle Use a specific bundle namespace. - * - * @usage drush features-import-all - * Import module config from all installed features. - * - * @aliases fra,fia,fim-all,features-import-all - */ - public function importAll($options = self::OPTIONS_IMPORT_ALL) { - $assigner = $this->featuresOptions($options); - $currentBundle = $assigner->getBundle(); - $namespace = $currentBundle->isDefault() ? FeaturesBundleInterface::DEFAULT_BUNDLE : $currentBundle->getMachineName(); - - $manager = $this->manager; - $packages = $manager->getPackages(); - $packages = $manager->filterPackages($packages, $namespace); - $overridden = []; - - foreach ($packages as $package) { - $overrides = $manager->detectOverrides($package); - $missing = $manager->detectMissing($package); - if ((!empty($missing) || !empty($overrides)) && ($package->getStatus() == FeaturesManagerInterface::STATUS_INSTALLED)) { - $overridden[] = $package->getMachineName(); - } - } - - if (!empty($overridden)) { - $this->import($overridden); - } - else { - $this->logger->info(dt('Current state already matches active config, aborting.')); - } - } - - /** - * Export the configuration on your site into a custom module. - * - * @param array $packages - * A list of features to export. - * - * @command features:export - * - * @option add-profile Package features into an install profile. - * @option bundle Use a specific bundle namespace. - * - * @usage drush features-export - * Export all available packages. - * @usage drush features-export example_article example_page - * Export the example_article and example_page packages. - * @usage drush features-export --add-profile - * Export all available packages and add them to an install profile. - * - * @aliases fex,fu,fua,fu-all,features-export - * - * @throws \Drupal\features\Exception\DomainException - * @throws \Drupal\features\Exception\InvalidArgumentException - * @throws \Drush\Exceptions\UserAbortException - * @throws \Exception - */ - public function export(array $packages, $options = self::OPTIONS_EXPORT) { - $assigner = $this->featuresOptions($options); - $manager = $this->manager; - $generator = $this->generator; - - $current_bundle = $assigner->getBundle(); - - if ($options['add-profile']) { - if ($current_bundle->isDefault) { - throw new InvalidArgumentException(dt("Must specify a profile name with --name")); - } - $current_bundle->setIsProfile(TRUE); - } - - $all_packages = $manager->getPackages(); - foreach ($packages as $name) { - if (!isset($all_packages[$name])) { - throw new DomainException(dt("The package @name does not exist.", [ - '@name' => $name, - ])); - } - } - - if (empty($packages)) { - $packages = $all_packages; - $dt_args = ['@modules' => implode(', ', array_keys($packages))]; - drush_print(dt('The following extensions will be exported: @modules', - $dt_args)); - if (!$this->io()->confirm('Do you really want to continue?')) { - throw new UserAbortException(); - } - } - else { - $packages = array_combine($packages, $packages); - } - - // If any packages exist, confirm before overwriting. - if ($existing_packages = $manager->listPackageDirectories($packages, - $current_bundle)) { - foreach ($existing_packages as $name => $directory) { - drush_print(dt("The extension @name already exists at @directory.", - ['@name' => $name, '@directory' => $directory])); - } - // Apparently, format_plural is not always available. - if (count($existing_packages) == 1) { - $message = dt('Would you like to overwrite it?'); - } - else { - $message = dt('Would you like to overwrite them?'); - } - if (!$this->io()->confirm($message)) { - throw new UserAbortException(); - } - } - - // Use the write generation method. - $method_id = FeaturesGenerationWrite::METHOD_ID; - $result = $generator->generatePackages($method_id, $current_bundle, array_keys($packages)); - - foreach ($result as $message) { - $method = $message['success'] ? 'success' : 'error'; - $this->logger()->$method(dt($message['message'], $message['variables'])); - } - } - - /** - * Add a config item to a feature package. - * - * @param array|null $components - * Patterns of config to add, see features:components for the format to use. - * - * @command features:add - * - * @todo @param $feature Feature package to export and add config to. - * - * @option bundle Use a specific bundle namespace. - * - * @aliases fa,fe,features-add - * - * @throws \Drush\Exceptions\UserAbortException - * @throws \Exception - */ - public function add($components = NULL, $options = self::OPTIONS_ADD) { - if ($components) { - $assigner = $this->featuresOptions($options); - $manager = $this->manager; - $generator = $this->generator; - - $current_bundle = $assigner->getBundle(); - - $module = array_shift($args); - if (empty($args)) { - throw new \Exception('No components supplied.'); - } - $components = $this->componentList(); - $options = [ - 'exported' => FALSE, - ]; - - $filtered_components = $this->componentFilter($components, $args, - $options); - $items = $filtered_components['components']; - - if (empty($items)) { - throw new \Exception('No components to add.'); - } - - $packages = [$module]; - // If any packages exist, confirm before overwriting. - if ($existing_packages = $manager->listPackageDirectories($packages)) { - foreach ($existing_packages as $name => $directory) { - drush_print(dt("The extension @name already exists at @directory.", - ['@name' => $name, '@directory' => $directory])); - } - // Apparently, format_plural is not always available. - if (count($existing_packages) == 1) { - $message = dt('Would you like to overwrite it?'); - } - else { - $message = dt('Would you like to overwrite them?'); - } - if (!$this->io()->confirm($message)) { - throw new UserAbortException(); - } - } - else { - $package = $manager->initPackage($module, NULL, '', 'module', - $current_bundle); - list($full_name, $path) = $manager->getExportInfo($package, - $current_bundle); - drush_print(dt('Will create a new extension @name in @directory', - ['@name' => $full_name, '@directory' => $path])); - if (!$this->io()->confirm(dt('Do you really want to continue?'))) { - throw new UserAbortException(); - } - } - - $config = $this->buildConfig($items); - - $manager->assignConfigPackage($module, $config); - - // Use the write generation method. - $method_id = FeaturesGenerationWrite::METHOD_ID; - $result = $generator->generatePackages($method_id, $current_bundle, - $packages); - - foreach ($result as $message) { - $method = $message['success'] ? 'success' : 'error'; - $this->logger()->$method(dt($message['message'], - $message['variables'])); - } - } - else { - throw new \Exception('No feature name given.'); - } - } - - /** - * List features components. - * - * @param array $patterns - * The components types to list. Omit this argument to list them all. - * - * @command features:components - * - * @option exported Show only components that have been exported. - * @option not-exported Show only components that have not been exported. - * @option bundle Use a specific bundle namespace. - * - * @aliases fc,features-components - * - * @field-labels - * source: Available sources - * - * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields|null - * The command output. May be empty. - */ - public function components(array $patterns, $options = self::OPTIONS_COMPONENTS) { - $args = $patterns; - $this->featuresOptions($options); - - $components = $this->componentList(); - ksort($components); - // If no args supplied, prompt with a list. - if (empty($args)) { - $types = array_keys($components); - array_unshift($types, 'all'); - $choice = $this->io() - ->choice('Enter a number to choose which component type to list.', $types); - if ($choice === FALSE) { - return NULL; - } - - $args = ($choice == 0) ? ['*'] : [$types[$choice]]; - } - $options = [ - 'provided by' => TRUE, - ]; - if ($options['exported']) { - $options['not exported'] = FALSE; - } - elseif ($options['not-exported']) { - $options['exported'] = FALSE; - } - - $filtered_components = $this->componentFilter($components, $args, $options); - if ($filtered_components) { - return $this->componentPrint($filtered_components); - } - } - - /** - * Show the difference between active|default config from a feature package. - * - * @param string $feature - * The feature in question. - * - * @command features:diff - * - * @option ctypes Comma-separated list of component types to limit the output - * to. Defaults to all types. - * @option lines Generate diffs with <n> lines of context instead of the - * usual two. - * @option bundle Use a specific bundle namespace. - * - * @aliases fd,features-diff - * - * @throws \Exception - */ - public function diff($feature, $options = self::OPTIONS_DIFF) { - $manager = $this->manager; - $assigner = $this->featuresOptions($options); - $assigner->assignConfigPackages(); - - $module = $feature; - - // @FIXME Actually do something with the "ctypes" option. - $filter_ctypes = $options['ctypes']; - if ($filter_ctypes) { - $filter_ctypes = explode(',', $filter_ctypes); - } - - $feature = $manager->loadPackage($module, TRUE); - if (empty($feature)) { - throw new DomainException(dt('No such feature is available: @module', [ - '@module' => $module, - ])); - } - - $lines = $options['lines']; - $lines = isset($lines) ? $lines : 2; - - $formatter = new DiffFormatter(); - $formatter->leading_context_lines = $lines; - $formatter->trailing_context_lines = $lines; - $formatter->show_header = FALSE; - - if (drush_get_context('DRUSH_NOCOLOR')) { - $red = $green = "%s"; - } - else { - $red = "\033[31;40m\033[1m%s\033[0m"; - $green = "\033[0;32;40m\033[1m%s\033[0m"; - } - - $overrides = $manager->detectOverrides($feature); - $missing = $manager->reorderMissing($manager->detectMissing($feature)); - $overrides = array_merge($overrides, $missing); - - $output = $this->output(); - - if (empty($overrides)) { - $output->writeln(dt('Active config matches stored config for @module.', [ - '@module' => $module, - ])); - } - else { - $config_diff = $this->configDiff; - - // Print key for colors. - $output->writeln(dt('Legend: ')); - $output->writeln(sprintf($red, - dt('Code: drush features-import will replace the active config with the displayed code.'))); - $output->writeln(sprintf($green, - dt('Active: drush features-export will update the exported feature with the displayed active config'))); - - foreach ($overrides as $name) { - $message = ''; - if (in_array($name, $missing)) { - $extension = []; - $message = sprintf($red, dt('(missing from active)')); - } - else { - $active = $manager->getActiveStorage()->read($name); - $extension = $manager->getExtensionStorages()->read($name); - if (empty($extension)) { - $extension = []; - $message = sprintf($green, dt('(not exported)')); - } - $diff = $config_diff->diff($extension, $active); - $rows = explode("\n", $formatter->format($diff)); - } - - $output->writeln(''); - $output->writeln(dt("Config @name @message", [ - '@name' => $name, - '@message' => $message, - ])); - - if (!empty($extension)) { - foreach ($rows as $row) { - if (strpos($row, '>') === 0) { - $output->writeln(sprintf($green, $row)); - } - elseif (strpos($row, '<') === 0) { - $output->writeln(sprintf($red, $row)); - } - else { - $output->writeln($row); - } - } - } - } - } - } - - /** - * Import a module config into your site. - * - * @param string $feature - * A comma-delimited list of features or feature:component pairs to import. - * - * @command features:import - * - * @option force Force import even if config is not overridden. - * @option bundle Use a specific bundle namespace. - * - * @usage drush features-import foo:node.type.page - * foo:taxonomy.vocabulary.tags bar Import node and taxonomy config of - * feature "foo". Import all config of feature "bar". - * - * @aliases fim,fr,features-import - * - * @throws \Exception - */ - public function import($feature, $options = self::OPTIONS_IMPORT) { - $this->featuresOptions($options); - - $features = StringUtils::csvToArray($feature); - if (empty($features)) { - drush_invoke_process('@self', 'features:list:packages', [], $options); - return; - } - - // Determine if revert should be forced. - $force = $this->getOption($options, 'force'); - - // Determine if -y was supplied. If so, we can filter out needless output - // from this command. - $skip_confirmation = drush_get_context('DRUSH_AFFIRMATIVE'); - $manager = $this->manager; - - // Parse list of arguments. - $modules = []; - foreach ($features as $featureString) { - list($module, $component) = explode(':', $featureString); - - // We cannot use just a component name without its module. - if (empty($module)) { - continue; - } - - // We received just a feature name, meaning we need all of its components. - if (empty($component)) { - $modules[$module] = TRUE; - continue; - } - - if (empty($modules[$module])) { - $modules[$module] = []; - } - - if ($modules[$module] !== TRUE) { - $modules[$module][] = $component; - } - } - - // Process modules. - foreach ($modules as $module => $componentsNeeded) { - // Reset the arguments on each loop pass. - $dt_args = ['@module' => $module]; - - /** @var \Drupal\features\Package $feature */ - $feature = $manager->loadPackage($module, TRUE); - if (empty($feature)) { - throw new DomainException(dt('No such feature is available: @module', $dt_args)); - } - - if ($feature->getStatus() != FeaturesManagerInterface::STATUS_INSTALLED) { - throw new DomainException(dt('No such feature is installed: @module', $dt_args)); - } - - // Forcefully revert all components of a feature. - if ($force) { - $components = $feature->getConfigOrig(); - } - // Only revert components that are detected to be Overridden. - else { - $overrides = $manager->detectOverrides($feature); - $missing = $manager->reorderMissing($manager->detectMissing($feature)); - - // Be sure to import missing components first. - $components = array_merge($missing, $overrides); - } - - if (!empty($componentsNeeded) && is_array($componentsNeeded)) { - $components = array_intersect($components, $componentsNeeded); - } - - if (empty($components)) { - $this->logger()->info(dt('Current state already matches active config, aborting.')); - continue; - } - - // Determine which config the user wants to import/revert. - $configToCreate = []; - foreach ($components as $component) { - $dt_args['@component'] = $component; - $confirmation_message = 'Do you really want to import @module : @component?'; - if ($skip_confirmation || $this->io()->confirm(dt($confirmation_message, $dt_args))) { - $configToCreate[$component] = ''; - } - } - - // Perform the import/revert. - $importedConfig = $manager->createConfiguration($configToCreate); - - // List the results. - foreach ($components as $component) { - $dt_args['@component'] = $component; - if (isset($importedConfig['new'][$component])) { - $this->logger()->info(dt('Imported @module : @component.', $dt_args)); - } - elseif (isset($importedConfig['updated'][$component])) { - $this->logger()->info(dt('Reverted @module : @component.', $dt_args)); - } - elseif (!isset($configToCreate[$component])) { - $this->logger()->info(dt('Skipping @module : @component.', $dt_args)); - } - else { - $this->logger()->error(dt('Error importing @module : @component.', $dt_args)); - } - } - } - } - - /** - * Returns an array of full config names given a array[$type][$component]. - * - * @param array $items - * The items to return data for. - * - * @return array - * An array of config items. - */ - protected function buildConfig(array $items) { - $result = []; - foreach ($items as $config_type => $item) { - foreach ($item as $item_name => $title) { - $result[] = $this->manager->getFullName($config_type, $item_name); - } - } - return $result; - } - - /** - * Returns a listing of all known components, indexed by source. - */ - protected function componentList() { - $result = []; - $config = $this->manager->getConfigCollection(); - foreach ($config as $item) { - $result[$item->getType()][$item->getShortName()] = $item->getLabel(); - } - return $result; - } - - /** - * Filters components by patterns. - */ - protected function componentFilter($all_components, $patterns = [], $options = []) { - $options += [ - 'exported' => TRUE, - 'not exported' => TRUE, - 'provided by' => FALSE, - ]; - $pool = []; - // Maps exported components to feature modules. - $components_map = $this->componentMap(); - // First filter on exported state. - foreach ($all_components as $source => $components) { - foreach ($components as $name => $title) { - $exported = count($components_map[$source][$name]) > 0; - if ($exported) { - if ($options['exported']) { - $pool[$source][$name] = $title; - } - } - else { - if ($options['not exported']) { - $pool[$source][$name] = $title; - } - } - } - } - - $state_string = ''; - - if (!$options['exported']) { - $state_string = 'unexported'; - } - elseif (!$options['not exported']) { - $state_string = 'exported'; - } - - $selected = []; - foreach ($patterns as $pattern) { - // Rewrite * to %. Let users use both as wildcard. - $pattern = strtr($pattern, ['*' => '%']); - $sources = []; - list($source_pattern, $component_pattern) = explode(':', $pattern, 2); - // If source is empty, use a pattern. - if ($source_pattern == '') { - $source_pattern = '%'; - } - if ($component_pattern == '') { - $component_pattern = '%'; - } - - $preg_source_pattern = strtr(preg_quote($source_pattern, '/'), - ['%' => '.*']); - $preg_component_pattern = strtr(preg_quote($component_pattern, '/'), - ['%' => '.*']); - // If it isn't a pattern, but a simple string, we don't anchor the - // pattern. This allows for abbreviating. Otherwise, we do, as this seems - // more natural for patterns. - if (strpos($source_pattern, '%') !== FALSE) { - $preg_source_pattern = '^' . $preg_source_pattern . '$'; - } - if (strpos($component_pattern, '%') !== FALSE) { - $preg_component_pattern = '^' . $preg_component_pattern . '$'; - } - $matches = []; - - // Find the sources. - $all_sources = array_keys($pool); - $matches = preg_grep('/' . $preg_source_pattern . '/', $all_sources); - if (count($matches) > 0) { - // If we have multiple matches and the source string wasn't a - // pattern, check if one of the matches is equal to the pattern, and - // use that, or error out. - if (count($matches) > 1 and $preg_source_pattern[0] != '^') { - if (in_array($source_pattern, $matches)) { - $matches = [$source_pattern]; - } - else { - throw new \Exception(dt('Ambiguous source "@source", matches @matches', - [ - '@source' => $source_pattern, - '@matches' => implode(', ', $matches), - ])); - } - } - // Loose the indexes preg_grep preserved. - $sources = array_values($matches); - } - else { - throw new \Exception(dt('No @state sources match "@source"', - ['@state' => $state_string, '@source' => $source_pattern])); - } - - // Now find the components. - foreach ($sources as $source) { - // Find the components. - $all_components = array_keys($pool[$source]); - // See if there's any matches. - $matches = preg_grep('/' . $preg_component_pattern . '/', - $all_components); - if (count($matches) > 0) { - // If we have multiple matches and the components string wasn't a - // pattern, check if one of the matches is equal to the pattern, and - // use that, or error out. - if (count($matches) > 1 and $preg_component_pattern[0] != '^') { - if (in_array($component_pattern, $matches)) { - $matches = [$component_pattern]; - } - else { - throw new \Exception(dt('Ambiguous component "@component", matches @matches', - [ - '@component' => $component_pattern, - '@matches' => implode(', ', $matches), - ])); - } - } - if (!is_array($selected[$source])) { - $selected[$source] = []; - } - $selected[$source] += array_intersect_key($pool[$source], - array_flip($matches)); - } - else { - // No matches. If the source was a pattern, just carry on, else - // error out. Allows for patterns like ":*field*". - if ($preg_source_pattern[0] != '^') { - throw new \Exception(dt('No @state @source components match "@component"', - [ - '@state' => $state_string, - '@component' => $component_pattern, - '@source' => $source, - ])); - } - } - } - } - - // Lastly, provide feature module information on the selected components, if - // requested. - $provided_by = []; - if ($options['provided by'] && $options['exported']) { - foreach ($selected as $source => $components) { - foreach ($components as $name => $title) { - $exported = count($components_map[$source][$name]) > 0; - if ($exported) { - $provided_by[$source . ':' . $name] = implode(', ', - $components_map[$source][$name]); - } - } - } - } - - return [ - 'components' => $selected, - 'sources' => $provided_by, - ]; - } - - /** - * Provides a component to feature map (port of features_get_component_map). - */ - protected function componentMap() { - $result = []; - $manager = $this->manager; - // Recalc full config list without running assignments. - $config = $manager->getConfigCollection(); - $packages = $manager->getPackages(); - - foreach ($config as $item) { - $type = $item->getType(); - $short_name = $item->getShortName(); - if (!isset($result[$type][$short_name])) { - $result[$type][$short_name] = []; - } - if (!empty($item->getPackage())) { - $package = $packages[$item->getPackage()]; - $result[$type][$short_name][] = $package->getMachineName(); - } - } - - return $result; - } - - /** - * Prints a list of filtered components. - */ - protected function componentPrint($filtered_components) { - $rows = []; - foreach ($filtered_components['components'] as $source => $components) { - foreach ($components as $name => $value) { - $row = ['source' => $source . ':' . $name]; - if (isset($filtered_components['sources'][$source . ':' . $name])) { - $row['source'] = dt('Provided by') . ': ' . $filtered_components['sources'][$source . ':' . $name]; - } - $rows[] = $row; - } - } - - return new RowsOfFields($rows); - } - -} diff --git a/web/modules/features/src/ConfigurationItem.php b/web/modules/features/src/ConfigurationItem.php deleted file mode 100644 index 52e39586131278a8debb773a875dcfc043482734..0000000000000000000000000000000000000000 --- a/web/modules/features/src/ConfigurationItem.php +++ /dev/null @@ -1,351 +0,0 @@ -<?php - -namespace Drupal\features; - -/** - * Contains some configuration together with metadata like the name + package. - * - * @todo Should the object be immutable? - * @todo Should this object have an interface? - */ -class ConfigurationItem { - - /** - * Prefixed configuration item name. - * - * @var string - */ - protected $name; - - /** - * Configuration item name without prefix. - * - * @var string - */ - protected $shortName; - - /** - * Human readable name of configuration item. - * - * @var string - */ - protected $label; - - /** - * Type of configuration. - * - * @var string - */ - protected $type; - - /** - * The contents of the configuration item in exported format. - * - * @var array - */ - protected $data; - - /** - * Array of names of dependent configuration items. - * - * @var string[] - */ - protected $dependents = []; - - /** - * Feature subdirectory to export item to. - * - * @var string - */ - protected $subdirectory; - - /** - * Machine name of a package the configuration is assigned to. - * - * @var string - */ - protected $package; - - /** - * Whether the configuration is marked as excluded. - * - * @var bool - */ - protected $excluded = FALSE; - - /** - * Whether the configuration provider is excluded. - * - * @var bool - */ - protected $providerExcluded = FALSE; - - /** - * The provider of the config item. - * - * @var string - */ - protected $provider; - - /** - * Array of package names that this item should be excluded from. - * - * @var string[] - */ - protected $packageExcluded = []; - - /** - * Creates a new ConfigurationItem instance. - * - * @param string $name - * The config name. - * @param array $data - * The config data. - * @param array $additional_properties - * (optional) Additional properties set on the object. - */ - public function __construct($name, array $data, array $additional_properties = []) { - $this->name = $name; - $this->data = $data; - - $properties = get_object_vars($this); - foreach ($additional_properties as $property => $value) { - if (!array_key_exists($property, $properties)) { - throw new \InvalidArgumentException('Invalid property: ' . $property); - } - $this->{$property} = $value; - } - } - - /** - * Calculates the config type usable in configuration. - * - * By default Drupal uses system.simple as config type, which cannot be used - * inside configuration itself. Therefore convert it to system_simple. - * - * @param string $type - * The config type provided by core. - * - * @return string - * The config type as string without dots. - */ - public static function fromConfigTypeToConfigString($type) { - return $type == 'system.simple' ? FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG : $type; - } - - /** - * Converts a config type string in configuration back to the config type. - * - * @param string $type - * The config type as string without dots. - * - * @return string - * The config type provided by core. - */ - public static function fromConfigStringToConfigType($type) { - return $type == FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG ? 'system.simple' : $type; - } - - /** - * @return mixed - */ - public function getName() { - return $this->name; - } - - /** - * @param mixed $name - * - * @return ConfigurationItem - */ - public function setName($name) { - $this->name = $name; - return $this; - } - - /** - * @return mixed - */ - public function getShortName() { - return $this->shortName; - } - - /** - * @param mixed $shortName - * - * @return ConfigurationItem - */ - public function setShortName($shortName) { - $this->shortName = $shortName; - return $this; - } - - /** - * @return mixed - */ - public function getLabel() { - return $this->label; - } - - /** - * @param mixed $label - * - * @return ConfigurationItem - */ - public function setLabel($label) { - $this->label = $label; - return $this; - } - - /** - * @return mixed - */ - public function getType() { - return $this->type; - } - - /** - * @param mixed $type - * - * @return ConfigurationItem - */ - public function setType($type) { - $this->type = $type; - return $this; - } - - /** - * @return mixed - */ - public function getData() { - return $this->data; - } - - /** - * @param mixed array - * - * @return ConfigurationItem - */ - public function setData(array $data) { - $this->data = $data; - return $this; - } - - /** - * @return string[] - */ - public function getDependents() { - return $this->dependents; - } - - /** - * @param array $dependents - * - * @return ConfigurationItem - */ - public function setDependents($dependents) { - $this->dependents = $dependents; - return $this; - } - - /** - * @return mixed - */ - public function getSubdirectory() { - return $this->subdirectory; - } - - /** - * @param mixed $subdirectory - * - * @return ConfigurationItem - */ - public function setSubdirectory($subdirectory) { - $this->subdirectory = $subdirectory; - return $this; - } - - /** - * @return mixed - */ - public function getPackage() { - return $this->package; - } - - /** - * @param mixed $package - * - * @return ConfigurationItem - */ - public function setPackage($package) { - $this->package = $package; - return $this; - } - - /** - * @return boolean - */ - public function isExcluded() { - return $this->excluded; - } - - /** - * @param boolean $excluded - * - * @return ConfigurationItem - */ - public function setExcluded($excluded) { - $this->excluded = $excluded; - return $this; - } - - /** - * @return boolean - */ - public function isProviderExcluded() { - return $this->providerExcluded; - } - - /** - * @param boolean $providerExcluded - * - * @return ConfigurationItem - */ - public function setProviderExcluded($providerExcluded) { - $this->providerExcluded = $providerExcluded; - return $this; - } - - /** - * @return string - */ - public function getProvider() { - return $this->provider; - } - - /** - * @param string $provider - */ - public function setProvider($provider) { - $this->provider = $provider; - return $this; - } - - /** - * @return string[] - */ - public function getPackageExcluded() { - return $this->packageExcluded; - } - - /** - * @param array $packageExcluded - * - * @return ConfigurationItem - */ - public function setPackageExcluded($packageExcluded) { - $this->packageExcluded = $packageExcluded; - return $this; - } - -} diff --git a/web/modules/features/src/Controller/FeaturesController.php b/web/modules/features/src/Controller/FeaturesController.php deleted file mode 100644 index e456577e316d9b5f7a3c21e776c4d6501bc31cb9..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Controller/FeaturesController.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -namespace Drupal\features\Controller; - -use Drupal\Core\Access\CsrfTokenGenerator; -use Drupal\Core\DependencyInjection\ContainerInjectionInterface; -use Drupal\system\FileDownloadController; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; - -/** - * Returns responses for config module routes. - */ -class FeaturesController implements ContainerInjectionInterface { - - /** - * The file download controller. - * - * @var \Drupal\system\FileDownloadController - */ - protected $fileDownloadController; - - /** - * The CSRF token generator. - * - * @var \Drupal\Core\Access\CsrfTokenGenerator - */ - protected $csrfToken; - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - new FileDownloadController(), - $container->get('csrf_token') - ); - } - - /** - * Constructs a FeaturesController object. - * - * @param \Drupal\system\FileDownloadController $file_download_controller - * The file download controller. - * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token - * The CSRF token generator. - */ - public function __construct(FileDownloadController $file_download_controller, CsrfTokenGenerator $csrf_token) { - $this->fileDownloadController = $file_download_controller; - $this->csrfToken = $csrf_token; - } - - /** - * Downloads a tarball of the site configuration. - * - * @param string $uri - * The URI to download. - * @param \Symfony\Component\HttpFoundation\Request $request - * The request. - * - * @return \Symfony\Component\HttpFoundation\BinaryFileResponse - * The downloaded file. - */ - public function downloadExport($uri, Request $request) { - if ($uri) { - // @todo Simplify once https://www.drupal.org/node/2630920 is solved. - if (!$this->csrfToken->validate($request->query->get('token'), $uri)) { - throw new AccessDeniedHttpException(); - } - - $request = new Request(['file' => $uri]); - return $this->fileDownloadController->download($request, 'temporary'); - } - } - -} diff --git a/web/modules/features/src/Entity/FeaturesBundle.php b/web/modules/features/src/Entity/FeaturesBundle.php deleted file mode 100644 index ced0be6de6113ec46657f33cb6be0d3922a9731a..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Entity/FeaturesBundle.php +++ /dev/null @@ -1,310 +0,0 @@ -<?php - -namespace Drupal\features\Entity; - -use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\features\FeaturesBundleInterface; -use Drupal\Core\Site\Settings; - -/** - * Defines a features bundle. - * @todo Better description - * - * @ConfigEntityType( - * id = "features_bundle", - * label = @Translation("Features bundle"), - * handlers = { - * }, - * admin_permission = "administer site configuration", - * config_prefix = "bundle", - * entity_keys = { - * "id" = "machine_name", - * "label" = "name" - * }, - * links = { - * }, - * config_export = { - * "name", - * "machine_name", - * "description", - * "assignments", - * "profile_name", - * "is_profile", - * } - * ) - */ -class FeaturesBundle extends ConfigEntityBase implements FeaturesBundleInterface { - - /** - * @var string - */ - protected $name; - - /** - * @var - */ - protected $machine_name; - - /** - * @var string - */ - protected $description; - - /** - * @var string[] - */ - protected $assignments = []; - - /** - * @var string - */ - protected $profile_name; - - /** - * @var bool - */ - protected $is_profile = FALSE; - - public function id() { - // @todo Convert it to $this->id in the long run. - return $this->getMachineName(); - } - - /** - * {@inheritdoc} - */ - public function isDefault() { - return $this->machine_name == static::DEFAULT_BUNDLE; - } - - /** - * {@inheritdoc} - */ - public function getMachineName() { - return $this->machine_name; - } - - /** - * {@inheritdoc} - */ - public function setMachineName($machine_name) { - $this->machine_name = $machine_name; - } - - /** - * {@inheritdoc} - */ - public function getName() { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function setName($name) { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function getFullName($short_name) { - if ($this->isDefault() || - // If it's already prefixed, don't repeat the prefix. - $this->inBundle($short_name) || - // If we are a profile, don't duplicate the bundle if same as profile. - $this->isProfilePackage($short_name)) { - return $short_name; - } - else { - return $this->machine_name . '_' . $short_name; - } - } - - /** - * {@inheritdoc} - */ - public function getShortName($machine_name) { - if (!$this->isProfilePackage($machine_name) && $this->inBundle($machine_name)) { - return substr($machine_name, strlen($this->getMachineName()) + 1, strlen($machine_name) - strlen($this->getMachineName()) - 1); - } - return $machine_name; - } - - /** - * {@inheritdoc} - */ - public function inBundle($machine_name) { - return ($this->isProfilePackage($machine_name) || strpos($machine_name, $this->machine_name . '_') === 0); - } - - /** - * {@inheritdoc} - */ - public function isProfilePackage($machine_name) { - return ($this->isProfile() && $machine_name == $this->getProfileName()); - } - - /** - * {@inheritdoc} - */ - public function getDescription() { - return $this->description; - } - - /** - * {@inheritdoc} - */ - public function setDescription($description) { - $this->description = $description; - } - - /** - * {@inheritdoc} - */ - public function isProfile() { - return $this->is_profile; - } - - /** - * {@inheritdoc} - */ - public function setIsProfile($value) { - $this->is_profile = $value; - } - - /** - * {@inheritdoc} - */ - public function getProfileName() { - $name = $this->isProfile() ? $this->profile_name : ''; - // Use Settings::get to fetch current profile name so we can easily test. - return !empty($name) ? $name : Settings::get('install_profile'); - } - - /** - * {@inheritdoc} - */ - public function setProfileName($machine_name) { - $this->profile_name = $machine_name; - } - - /** - * {@inheritdoc} - */ - public function getEnabledAssignments() { - $list = []; - foreach ($this->assignments as $method_id => $method) { - if ($method['enabled']) { - $list[$method_id] = $method_id; - } - } - return $list; - } - - /** - * {@inheritdoc} - */ - public function setEnabledAssignments(array $assignments) { - // Add any new assignments that we don't yet know about. - $new_assignments = array_diff($assignments, array_keys($this->assignments)); - foreach ($new_assignments as $method_id) { - $this->assignments[$method_id] = $this->getAssignmentSettings($method_id); - } - - foreach ($this->assignments as $method_id => &$method) { - $method['enabled'] = in_array($method_id, $assignments); - } - } - - /** - * {@inheritdoc} - */ - public function getAssignmentWeights() { - $list = []; - foreach ($this->assignments as $method_id => $method) { - $list[$method_id] = $method['weight']; - } - return $list; - } - - /** - * {@inheritdoc} - */ - public function setAssignmentWeights(array $assignments) { - foreach ($this->assignments as $method_id => &$method) { - if (isset($assignments[$method_id])) { - $method['weight'] = $assignments[$method_id]; - } - } - } - - /** - * Return array of default settings for the given plugin method - * - * @param $method_id - * @return array - */ - protected function getDefaultSettings($method_id) { - $settings = ['enabled' => FALSE, 'weight' => 0]; - - $manager = \Drupal::service('plugin.manager.features_assignment_method'); - $definition = $manager->getDefinition($method_id); - - if (isset($definition['weight'])) { - $settings['weight'] = $definition['weight']; - } - if (isset($definition['default_settings'])) { - $settings += $definition['default_settings']; - } - - return $settings; - } - - /** - * {@inheritdoc} - */ - public function getAssignmentSettings($method_id = NULL) { - if (isset($method_id)) { - if (isset($this->assignments[$method_id])) { - return $this->assignments[$method_id]; - } - else { - // Use defaults. - return $this->getDefaultSettings($method_id); - } - } - else { - $list = []; - foreach (array_keys($this->assignments) as $method_id) { - $list[$method_id] = $this->getAssignmentSettings($method_id); - } - return $list; - } - } - - /** - * {@inheritdoc} - */ - public function setAssignmentSettings($method_id, array $settings) { - if (isset($method_id)) { - $this->assignments[$method_id] = $settings; - } - else { - foreach ($settings as $method_id => $method_settings) { - if (!empty($method_settings)) { - $this->setAssignmentSettings($method_id, $method_settings); - } - } - } - return $this; - } - - /** - * {@inheritdoc} - */ - public function remove() { - $this->delete(); - } - -} diff --git a/web/modules/features/src/Exception/DomainException.php b/web/modules/features/src/Exception/DomainException.php deleted file mode 100644 index c496d3b0e9d542419738992332497bf958a11a96..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Exception/DomainException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Drupal\features\Exception; - -class DomainException extends \DomainException { - -} diff --git a/web/modules/features/src/Exception/InvalidArgumentException.php b/web/modules/features/src/Exception/InvalidArgumentException.php deleted file mode 100644 index 199d51e163e07f8594f70422660b87907b215caa..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Drupal\features\Exception; - -class InvalidArgumentException extends \InvalidArgumentException { - -} diff --git a/web/modules/features/src/FeaturesAssigner.php b/web/modules/features/src/FeaturesAssigner.php deleted file mode 100644 index f06b0d16755ffa5579737c0dfdeca126357c7a3f..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesAssigner.php +++ /dev/null @@ -1,446 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Component\Plugin\PluginManagerInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Config\ExtensionInstallStorage; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Config\StorageInterface; -use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\features\Entity\FeaturesBundle; - -/** - * Class responsible for performing package assignment. - */ -class FeaturesAssigner implements FeaturesAssignerInterface { - use StringTranslationTrait; - - /** - * The package assignment method plugin manager. - * - * @var \Drupal\Component\Plugin\PluginManagerInterface - */ - protected $assignerManager; - - /** - * The features manager. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * The configuration factory. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected $configFactory; - - /** - * The configuration storage. - * - * @var \Drupal\Core\Config\StorageInterface - */ - protected $configStorage; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * Local cache for package assignment method instances. - * - * @var array - */ - protected $methods; - - /** - * Bundles. - * - * @var array of \Drupal\features\FeaturesBundleInterface - */ - protected $bundles; - - /** - * Currently active bundle. - * - * @var \Drupal\features\FeaturesBundleInterface - */ - protected $currentBundle; - - /** - * Constructs a new FeaturesAssigner object. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - * @param \Drupal\Component\Plugin\PluginManagerInterface $assigner_manager - * The package assignment methods plugin manager. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity type manager. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The configuration factory. - * @param \Drupal\Core\Config\StorageInterface $config_storage - * The configuration factory. - */ - public function __construct(FeaturesManagerInterface $features_manager, PluginManagerInterface $assigner_manager, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, StorageInterface $config_storage) { - $this->featuresManager = $features_manager; - $this->assignerManager = $assigner_manager; - $this->entityTypeManager = $entity_type_manager; - $this->configFactory = $config_factory; - $this->configStorage = $config_storage; - $this->bundles = $this->getBundleList(); - $this->currentBundle = $this->getBundle(FeaturesBundleInterface::DEFAULT_BUNDLE); - // Ensure bundle information is fresh. - $this->createBundlesFromPackages(); - } - - /** - * Initializes the injected features manager with the assigner. - * - * This should be called right after instantiating the assigner to make it - * available to the features manager without introducing a circular - * dependency. - */ - public function initFeaturesManager() { - $this->featuresManager->setAssigner($this); - } - - /** - * {@inheritdoc} - */ - public function reset() { - $this->methods = []; - $this->featuresManager->reset(); - } - - /** - * Gets enabled assignment methods. - * - * @return array - * An array of enabled assignment methods, sorted by weight. - */ - public function getEnabledAssigners() { - $enabled = $this->currentBundle->getEnabledAssignments(); - $weights = $this->currentBundle->getAssignmentWeights(); - foreach ($enabled as $key => $value) { - $enabled[$key] = $weights[$key]; - } - asort($enabled); - return $enabled; - } - - /** - * Clean up the package list after all config has been assigned - */ - protected function cleanup() { - $packages = $this->featuresManager->getPackages(); - foreach ($packages as $index => $package) { - if ($package->getStatus() === FeaturesManagerInterface::STATUS_NO_EXPORT && empty($package->getConfig()) && empty($package->getConfigOrig())) { - unset($packages[$index]); - } - } - $this->featuresManager->setPackages($packages); - } - - /** - * {@inheritdoc} - */ - public function assignConfigPackages($force = FALSE) { - foreach ($this->getEnabledAssigners() as $method_id => $info) { - $this->applyAssignmentMethod($method_id, $force); - } - $this->cleanup(); - } - - /** - * {@inheritdoc} - */ - public function applyAssignmentMethod($method_id, $force = FALSE) { - $this->getAssignmentMethodInstance($method_id)->assignPackages($force); - } - - /** - * {@inheritdoc} - */ - public function getAssignmentMethods() { - return $this->assignerManager->getDefinitions(); - } - - /** - * Returns an instance of the specified package assignment method. - * - * @param string $method_id - * The string identifier of the package assignment method to use to package - * configuration. - * - * @return \Drupal\features\FeaturesAssignmentMethodInterface - */ - protected function getAssignmentMethodInstance($method_id) { - if (!isset($this->methods[$method_id])) { - $instance = $this->assignerManager->createInstance($method_id, []); - $instance->setFeaturesManager($this->featuresManager); - $instance->setAssigner($this); - $instance->setEntityTypeManager($this->entityTypeManager); - $instance->setConfigFactory($this->configFactory); - $this->methods[$method_id] = $instance; - } - return $this->methods[$method_id]; - } - - /** - * {@inheritdoc} - */ - public function purgeConfiguration() { - // Ensure that we are getting the defined package assignment information. - // An invocation of \Drupal\Core\Extension\ModuleHandler::install() or - // \Drupal\Core\Extension\ModuleHandler::uninstall() could invalidate the - // cached information. - $this->assignerManager->clearCachedDefinitions(); - $this->featuresManager->reset(); - } - - /** - * {@inheritdoc} - */ - public function getBundle($name = NULL) { - if (empty($name)) { - return $this->currentBundle; - } - elseif (isset($this->bundles[$name])) { - return $this->bundles[$name]; - } - return NULL; - } - - /** - * {@inheritdoc} - */ - public function setBundle(FeaturesBundleInterface $bundle, $current = TRUE) { - $this->bundles[$bundle->getMachineName()] = $bundle; - if (isset($this->currentBundle) && ($current || ($bundle->getMachineName() == $this->currentBundle->getMachineName()))) { - $this->currentBundle = $bundle; - } - } - - /** - * {@inheritdoc} - */ - public function findBundle(array $info, $features_info = NULL) { - $bundle = NULL; - if (!empty($features_info['bundle'])) { - $bundle = $this->getBundle($features_info['bundle']); - } - elseif (!empty($info['package'])) { - $bundle = $this->findBundleByName($info['package']); - } - if (!isset($bundle)) { - // Return the default bundle. - return $this->getBundle(FeaturesBundleInterface::DEFAULT_BUNDLE); - } - return $bundle; - } - - /** - * {@inheritdoc} - */ - public function setCurrent(FeaturesBundleInterface $bundle) { - $this->currentBundle = $bundle; - $session = \Drupal::request()->getSession(); - if (isset($session)) { - $session->set('features_current_bundle', $bundle->getMachineName()); - } - return $bundle; - } - - /** - * {@inheritdoc} - */ - public function getBundleList() { - if (empty($this->bundles)) { - $this->bundles = []; - foreach ($this->entityTypeManager->getStorage('features_bundle')->loadMultiple() as $machine_name => $bundle) { - $this->bundles[$machine_name] = $bundle; - } - } - return $this->bundles; - } - - /** - * {@inheritdoc} - */ - public function findBundleByName($name, $create = FALSE) { - $bundles = $this->getBundleList(); - foreach ($bundles as $machine_name => $bundle) { - if ($name == $bundle->getName()) { - return $bundle; - } - } - $machine_name = strtolower(str_replace([' ', '-'], '_', $name)); - if (isset($bundles[$machine_name])) { - return $bundles[$machine_name]; - } - return NULL; - } - - /** - * {@inheritdoc} - */ - public function createBundleFromDefault($machine_name, $name = NULL, $description = NULL, $is_profile = FALSE, $profile_name = NULL) { - // Duplicate the default bundle to get its default configuration. - $default = $this->getBundle(FeaturesBundleInterface::DEFAULT_BUNDLE); - if (!$default) { - // If we don't have the default installed, generate it from the install - // config file. - $ext_storage = new ExtensionInstallStorage($this->configStorage); - $record = $ext_storage->read('features.bundle.default'); - $bundle_storage = $this->entityTypeManager->getStorage('features_bundle'); - $default = $bundle_storage->createFromStorageRecord($record); - } - - /** @var \Drupal\features\Entity\FeaturesBundle $bundle */ - $bundle = $default->createDuplicate(); - - $bundle->setMachineName($machine_name); - $name = !empty($name) ? $name : $machine_name; - $bundle->setName($name); - if (isset($description)) { - $bundle->setDescription($description); - } - else { - $bundle->setDescription(t('Auto-generated bundle from package @name', ['@name' => $name])); - } - $bundle->setIsProfile($is_profile); - if (isset($profile_name)) { - $bundle->setProfileName($profile_name); - } - $bundle->save(); - $this->setBundle($bundle); - - return $bundle; - } - - /** - * {@inheritdoc} - */ - public function createBundlesFromPackages() { - $existing_bundles = $this->getBundleList(); - $new_bundles = []; - // Only parse from installed features. - $modules = $this->featuresManager->getFeaturesModules(NULL, TRUE); - - foreach ($modules as $module) { - $info = $this->featuresManager->getExtensionInfo($module); - // @todo This entire function could be simplified a lot using packages. - $features_info = $this->featuresManager->getFeaturesInfo($module); - // Create a new bundle if: - // - the feature specifies a bundle and - // - that bundle doesn't yet exist locally. - // Allow profiles to override previous values. - if (!empty($features_info['bundle']) && - !isset($existing_bundles[$features_info['bundle']]) && - (!in_array($features_info['bundle'], $new_bundles) || $info['type'] == 'profile')) { - if ($info['type'] == 'profile') { - $new_bundle = [ - 'name' => $info['name'], - 'description' => $info['description'], - 'is_profile' => TRUE, - 'profile_name' => $module->getName(), - ]; - } - else { - $new_bundle = [ - 'name' => isset($info['package']) ? $info['package'] : ucwords(str_replace('_', ' ', $features_info['bundle'])), - 'description' => NULL, - 'is_profile' => FALSE, - 'profile_name' => NULL, - ]; - } - $new_bundle['machine_name'] = $features_info['bundle']; - $new_bundles[$new_bundle['machine_name']] = $new_bundle; - } - } - foreach ($new_bundles as $new_bundle) { - $this->createBundleFromDefault($new_bundle['machine_name'], $new_bundle['name'], $new_bundle['description'], $new_bundle['is_profile']); - } - - } - - /** - * {@inheritdoc} - */ - public function getBundleOptions() { - $list = $this->getBundleList(); - $result = []; - foreach ($list as $machine_name => $bundle) { - $result[$machine_name] = $bundle->getName(); - } - return $result; - } - - /** - * {@inheritdoc} - */ - public function applyBundle($machine_name = NULL) { - $this->reset(); - $bundle = $this->loadBundle($machine_name); - if (isset($bundle)) { - $this->assignConfigPackages(); - return $this->currentBundle; - } - return NULL; - } - - /** - * {@inheritdoc} - */ - public function renameBundle($old_machine, $new_machine) { - $is_current = (isset($this->currentBundle) && ($old_machine == $this->currentBundle->getMachineName())); - $bundle = $this->getBundle($old_machine); - if ($bundle->getMachineName() != '') { - // Remove old bundle from the list if it's not the Default bundle. - unset($this->bundles[$old_machine]); - } - $bundle->setMachineName($new_machine); - $this->setBundle($bundle); - // Put the bundle into the list with the correct name. - $this->bundles[$bundle->getMachineName()] = $bundle; - if ($is_current) { - $this->setCurrent($bundle); - } - return $bundle; - } - - /** - * {@inheritdoc} - */ - public function loadBundle($machine_name = NULL) { - if (!isset($machine_name)) { - $session = \Drupal::request()->getSession(); - if (isset($session)) { - $machine_name = isset($session) ? $session->get('features_current_bundle', FeaturesBundleInterface::DEFAULT_BUNDLE) : FeaturesBundleInterface::DEFAULT_BUNDLE; - } - } - $bundle = $this->getBundle($machine_name); - if (!isset($bundle)) { - // If bundle no longer exists then return default. - $bundle = $this->bundles[FeaturesBundleInterface::DEFAULT_BUNDLE]; - } - return $this->setCurrent($bundle); - } - - /** - * {@inheritdoc} - */ - public function removeBundle($machine_name) { - $bundle = $this->getBundle($machine_name); - if (isset($bundle) && !$bundle->isDefault()) { - unset($this->bundles[$machine_name]); - $bundle->remove(); - } - } - -} diff --git a/web/modules/features/src/FeaturesAssignerInterface.php b/web/modules/features/src/FeaturesAssignerInterface.php deleted file mode 100644 index 946c6ec8bf9e7c97e0d801b8b03fa401f7e71738..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesAssignerInterface.php +++ /dev/null @@ -1,228 +0,0 @@ -<?php - -namespace Drupal\features; - -/** - * Common interface for features assignment services. - * - * The feature API is based on two major concepts: - * - Packages: modules into which configuration is packaged. - * - Package assignment methods: responsible for `determining - * which package to assign a given piece of configuration to. - * Assignment methods are customizable. - * - * Features defines several package assignment methods, which are simple plugin - * classes that implement a particular logic to assign pieces of configuration - * to a given package (module). - * - * Modules can define additional package assignment methods by simply providing - * the related plugins, and alter existing methods through - * hook_features_assignment_method_info_alter(). Here is an example - * snippet: - * @code - * function mymodule_features_assignment_method_info_alter(&$assignment_info) { - * // Replace the original plugin with our own implementation. - * $method_id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentBaseType::METHOD_ID; - * $assignment_info[$method_id]['class'] = 'Drupal\my_module\Plugin\FeaturesAssignment\MyFeaturesAssignmentBaseType'; - * } - * - * class MyFeaturesAssignmentBaseType extends FeaturesAssignmentBaseType { - * public function assignPackages($force = FALSE) { - * // Insert customization here. - * } - * } - * ?> - * @endcode - * - * For more information, see - * @link http://drupal.org/node/2404473 Developing for Features 3.x @endlink - */ -interface FeaturesAssignerInterface { - - /** - * The package assignment method id for the package assigner itself. - */ - const METHOD_ID = 'assigner-default'; - - /** - * Resets the assigned packages and the method instances. - */ - public function reset(); - - /** - * Apply all enabled package assignment methods. - * - * @param bool $force - * (optional) If TRUE, assign config regardless of restrictions such as it - * being already assigned to a package. - */ - public function assignConfigPackages($force = FALSE); - - /** - * Applies a given package assignment method. - * - * @param string $method_id - * The string identifier of the package assignment method to use to package - * configuration. - * @param bool $force - * (optional) If TRUE, assign config regardless of restrictions such as it - * being already assigned to a package. - */ - public function applyAssignmentMethod($method_id, $force = FALSE); - - /** - * Returns the enabled package assignment methods. - * - * @return array - * An array of package assignment method IDs. - */ - public function getAssignmentMethods(); - - /** - * Resaves the configuration to purge missing assignment methods. - */ - public function purgeConfiguration(); - - /** - * Returns a FeaturesBundle object. - * - * @param string $name - * machine name of package set. If omitted, returns the current bundle. - * - * @return \Drupal\features\FeaturesBundleInterface - * A features bundle object. - */ - public function getBundle($name = NULL); - - /** - * Stores a features bundle. - * - * Added to list if machine_name is new. - * - * @param \Drupal\features\FeaturesBundleInterface $bundle - * A features bundle. - * @param bool $current - * Determine if the current bundle is set to $bundle. - * If False, the current bundle is only updated if it already has the same - * machine name as the $bundle. - */ - public function setBundle(FeaturesBundleInterface $bundle, $current = TRUE); - - /** - * Searches for a bundle that matches the $info.yml or $features.yml export. - * - * Creates a new bundle as needed. - * - * @param array $info - * The bundle info. - * @param mixed $features_info - * The features info. - * - * @return \Drupal\features\FeaturesBundleInterface - * A bundle. - */ - public function findBundle(array $info, $features_info = NULL); - - /** - * Sets the currently active bundle. - * - * Updates value in current SESSION. - * - * @param \Drupal\features\FeaturesBundleInterface $bundle - * A features bundle object. - */ - public function setCurrent(FeaturesBundleInterface $bundle); - - /** - * Returns an array of all existing features bundles. - * - * @return \Drupal\features\FeaturesBundleInterface[] - * Keyed by machine_name with value of - * \Drupal\features\FeaturesBundleInterface. - */ - public function getBundleList(); - - /** - * Returns a named bundle. - * - * First searches by Human name, then by machine_name. - * - * @param string $name - * The bundle name to search by. - * - * @return \Drupal\features\FeaturesBundleInterface - * A features bundle object. - */ - public function findBundleByName($name); - - /** - * Creates a new bundle by duplicating the default bundle and customizing. - * - * @param string $machine_name - * Machine name. - * @param string $name - * (optional) Human readable name of the bundle. - * @param string $description - * (optional) Description of the bundle. - * @param bool $is_profile - * (optional) TRUE if a profile is used with this bundle. - * @param string $profile_name - * (optional) The machine name of the profile. - * - * @return \Drupal\features\FeaturesBundleInterface - * A features bundle object. - */ - public function createBundleFromDefault($name, $machine_name = '', $description = '', $is_profile = FALSE, $profile_name = NULL); - - /** - * Creates bundles by parsing information from installed packages. - */ - public function createBundlesFromPackages(); - - /** - * Returns an array of bundle names suitable for a select option list. - * - * @return array - * An array of bundles, keyed by machine_name, with values being human - * readable names. - */ - public function getBundleOptions(); - - /** - * Makes the named bundle the current bundle. - * - * @param string $machine_name - * The name of a features bundle. If omitted, gets the last bundle from the - * Session. - * - * @return \Drupal\features\FeaturesBundleInterface - * A features bundle object. - */ - public function applyBundle($machine_name = NULL); - - /** - * Renames a bundle. - * - * @param string $old_machine - * The old machine name of a bundle. - * @param string $new_machine - * The new machine name of a bundle. - * - * @return \Drupal\features\FeaturesBundleInterface - * A features bundle object. - */ - public function renameBundle($old_machine, $new_machine); - - /** - * Loads a named bundle. - * - * @param string $machine_name - * (optional) The name of a features bundle. - * Defaults to NULL, gets the last bundle from the session. - * - * @return \Drupal\features\FeaturesBundleInterface - * A features bundle object. - */ - public function loadBundle($machine_name = NULL); - -} diff --git a/web/modules/features/src/FeaturesAssignmentMethodBase.php b/web/modules/features/src/FeaturesAssignmentMethodBase.php deleted file mode 100644 index 2b7465756e6db9ab01e4e1c305e70b54cbd47892..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesAssignmentMethodBase.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Plugin\PluginBase; - -/** - * Base class for package assignment methods. - */ -abstract class FeaturesAssignmentMethodBase extends PluginBase implements FeaturesAssignmentMethodInterface { - /** - * The features manager. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * The features assigner. - * - * @var \Drupal\features\FeaturesAssignerInterface - */ - protected $assigner; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * The configuration factory. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected $configFactory; - - /** - * {@inheritdoc} - */ - public function setfeaturesManager(FeaturesManagerInterface $features_manager) { - $this->featuresManager = $features_manager; - } - - /** - * {@inheritdoc} - */ - public function setAssigner(FeaturesAssignerInterface $assigner) { - $this->assigner = $assigner; - } - - /** - * {@inheritdoc} - */ - public function setEntityTypeManager(EntityTypeManagerInterface $entity_type_manager) { - $this->entityTypeManager = $entity_type_manager; - } - - /** - * {@inheritdoc} - */ - public function setConfigFactory(ConfigFactoryInterface $config_factory) { - $this->configFactory = $config_factory; - } - - /** - * Assigns configuration of the types specified in a setting to a package. - * - * @param string $machine_name - * Machine name of the package. - * @param bool $force - * (optional) If TRUE, assign config regardless of restrictions such as it - * being already assigned to a package. - */ - protected function assignPackageByConfigTypes($machine_name, $force = FALSE) { - $current_bundle = $this->assigner->getBundle(); - $settings = $current_bundle->getAssignmentSettings($this->getPluginId()); - $types = $settings['types']['config']; - - $config_collection = $this->featuresManager->getConfigCollection(); - - foreach ($config_collection as $item_name => $item) { - // Don't assign configuration that's provided by an extension. - if (in_array($item->getType(), $types) && !($item->isProviderExcluded())) { - try { - $this->featuresManager->assignConfigPackage($machine_name, [$item_name]); - } - catch (\Exception $exception) { - \Drupal::logger('features')->error($exception->getMessage()); - } - } - } - } - - /** - * Assigns a given subdirectory to configuration of specified types. - * - * @param string $subdirectory - * The subdirectory that designated configuration should be exported to. - */ - protected function assignSubdirectoryByConfigTypes($subdirectory) { - $current_bundle = $this->assigner->getBundle(); - $settings = $current_bundle->getAssignmentSettings($this->getPluginId()); - $types = $settings['types']['config']; - - if (!empty($types)) { - $config_collection = $this->featuresManager->getConfigCollection(); - - foreach ($config_collection as &$item) { - if (in_array($item->getType(), $types)) { - $item->setSubdirectory($subdirectory); - } - } - // Clean up the $item pass by reference. - unset($item); - - $this->featuresManager->setConfigCollection($config_collection); - } - } - -} diff --git a/web/modules/features/src/FeaturesAssignmentMethodInterface.php b/web/modules/features/src/FeaturesAssignmentMethodInterface.php deleted file mode 100644 index abb29f19dbe05c4bdfc5c336b40fd24c0cf0802c..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesAssignmentMethodInterface.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Component\Plugin\PluginInspectionInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; - -/** - * Interface for package assignment classes. - */ -interface FeaturesAssignmentMethodInterface extends PluginInspectionInterface { - - /** - * Injects the features manager. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager to be used to retrieve the configuration list and - * the already assigned packages. - */ - public function setFeaturesManager(FeaturesManagerInterface $features_manager); - - /** - * Injects the features assigner. - * - * @param \Drupal\features\FeaturesAssignerInterface $assigner - * The features assigner to be used to retrieve the bundle configuration. - */ - public function setAssigner(FeaturesAssignerInterface $assigner); - - /** - * Injects the entity manager. - * - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity type manager to be used to retrieve entity information. - */ - public function setEntityTypeManager(EntityTypeManagerInterface $entity_type_manager); - - /** - * Injects the configuration factory. - * - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The configuration factory to be used to retrieve configuration values. - */ - public function setConfigFactory(ConfigFactoryInterface $config_factory); - - /** - * Performs package assignment. - * - * @param bool $force - * (optional) If TRUE, assign config regardless of restrictions such as it - * being already assigned to a package. - */ - public function assignPackages($force = FALSE); - -} diff --git a/web/modules/features/src/FeaturesAssignmentMethodManager.php b/web/modules/features/src/FeaturesAssignmentMethodManager.php deleted file mode 100644 index 40b4a5824c0fd0cbda5573f2638a50b0be15b8c6..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesAssignmentMethodManager.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Plugin\DefaultPluginManager; - -/** - * Manages configuration packaging methods. - */ -class FeaturesAssignmentMethodManager extends DefaultPluginManager { - - /** - * Constructs a new FeaturesAssignmentMethodManager object. - * - * @param \Traversable $namespaces - * An object that implements \Traversable which contains the root paths - * keyed by the corresponding namespace to look for plugin implementations. - * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend - * An object that implements CacheBackendInterface. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * An object that implements ModuleHandlerInterface. - */ - public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/FeaturesAssignment', $namespaces, $module_handler, - 'Drupal\features\FeaturesAssignmentMethodInterface'); - $this->alterInfo('features_assignment_info'); - $this->setCacheBackend($cache_backend, 'features_assignment_methods'); - } - -} diff --git a/web/modules/features/src/FeaturesBundleInterface.php b/web/modules/features/src/FeaturesBundleInterface.php deleted file mode 100644 index 83dfbf5a9bc034dbd43fd8e099477872fb266375..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesBundleInterface.php +++ /dev/null @@ -1,240 +0,0 @@ -<?php - -namespace Drupal\features; - -/** - * Provides an interface for the FeaturesBundle object. - */ -interface FeaturesBundleInterface { - - const DEFAULT_BUNDLE = 'default'; - - /** - * Determines whether the current bundle is the default one. - * - * @return bool - * Returns TRUE if this is the default bundle. - */ - public function isDefault(); - - /** - * Returns the machine name of a bundle. - * - * @return string - * The machine name of a bundle. - * - * @see \Drupal\features\FeaturesBundleInterface::setMachineName() - */ - public function getMachineName(); - - /** - * Sets the machine name of a bundle. - * - * @param string $machine_name - * The machine name of a bundle. - * - * @see \Drupal\features\FeaturesBundleInterface::getMachineName() - */ - public function setMachineName($machine_name); - - /** - * Gets the human readable name of a bundle. - * - * @return string - * The human readable name of a bundle. - * - * @see \Drupal\features\FeaturesBundleInterface::setName() - */ - public function getName(); - - /** - * Sets the human readable name of a bundle. - * - * @param string $name - * The human readable name of a bundle. - * - * @see \Drupal\features\FeaturesBundleInterface::getName() - */ - public function setName($name); - - /** - * Returns a full machine name prefixed with the bundle name. - * - * @param string $short_name - * The short machine_name of a bundle. - * - * @return string - * The full machine_name of a bundle. - */ - public function getFullName($short_name); - - /** - * Returns a short machine name not prefixed with the bundle name. - * - * @param string $machine_name - * The full machine_name of a bundle. - * - * @return string - * The short machine_name of a bundle. - */ - public function getShortName($machine_name); - - /** - * Determines if the $machine_name is prefixed by the bundle machine name. - * - * @param string $machine_name - * The machine name of a package. - * - * @return bool - * TRUE if the machine name is prefixed by the bundle machine name. - */ - public function inBundle($machine_name); - - /** - * Determines if the package with $machine_name is the bundle profile. - * - * @param string $machine_name - * The machine name of a package. - * - * @return bool - * TRUE if the package with $machine_name is the bundle profile. - */ - public function isProfilePackage($machine_name); - - /** - * Gets the description of a bundle. - * - * @return string - * The description of a bundle. - * - * @see \Drupal\features\FeaturesBundleInterface::setDescription() - */ - public function getDescription(); - - /** - * Sets the description of a bundle. - * - * @param string $description - * The description of a bundle. - * - * @see \Drupal\features\FeaturesBundleInterface::getDescription() - */ - public function setDescription($description); - - /** - * Gets option for using a profile with this bundle. - * - * @return bool - * TRUE if a profile is used with this profile. - */ - public function isProfile(); - - /** - * Sets option for using a profile with this bundle. - * - * @param bool $value - * TRUE if a profile is used with this bundle. - */ - public function setIsProfile($value); - - /** - * Returns the machine name of the profile. - * - * If the bundle doesn't use a profile, return the current site profile. - * - * @return string - * THe machie name of a profile. - * - * @see \Drupal\features\FeaturesBundleInterface::setProfileName() - */ - public function getProfileName(); - - /** - * Sets the name of the profile associated with this bundle. - * - * @param string $machine_name - * The machine name of a profile. - * - * @see \Drupal\features\FeaturesBundleInterface::getProfileName() - */ - public function setProfileName($machine_name); - - /** - * Gets the list of enabled assignment methods. - * - * @return array - * An array of method IDs keyed by assignment method IDs. - * - * @see \Drupal\features\FeaturesBundleInterface::setEnabledAssignments() - */ - public function getEnabledAssignments(); - - /** - * Sets the list of enabled assignment methods. - * - * @param array $assignments - * An array of values keyed by assignment method IDs. Non-empty value is - * enabled. - * - * @see \Drupal\features\FeaturesBundleInterface::getEnabledAssignments() - */ - public function setEnabledAssignments(array $assignments); - - /** - * Gets the weights of the assignment methods. - * - * @return array - * An array keyed by assignment method_id with a numeric weight. - * - * @see \Drupal\features\FeaturesBundleInterface::setAssignmentWeights() - */ - public function getAssignmentWeights(); - - /** - * Sets the weights of the assignment methods. - * - * @param array $assignments - * An array keyed by assignment method_id with a numeric weight value. - * - * @see \Drupal\features\FeaturesBundleInterface::getAssignmentWeights() - */ - public function setAssignmentWeights(array $assignments); - - /** - * Gets settings specific to an assignment method. - * - * @param string $method_id - * The ID of an assignment method. If NULL, return all assignment settings - * keyed by method_id. - * - * @return array - * An array of settings. Format specific to assignment method. - * - * @see \Drupal\features\FeaturesBundleInterface::setAssignmentSettings() - */ - public function getAssignmentSettings($method_id = NULL); - - /** - * Sets settings specific to an assignment method. - * - * @param string $method_id - * The ID of an assignment method. If NULL, all $settings are given keyed - * by method_ID. - * @param array $settings - * An array of setting values. - * - * @see \Drupal\features\FeaturesBundleInterface::getAssignmentSettings() - */ - public function setAssignmentSettings($method_id, array $settings); - - /** - * Saves the bundle to the active config. - */ - public function save(); - - /** - * Removes the bundle from the active config. - */ - public function remove(); - -} diff --git a/web/modules/features/src/FeaturesConfigDependencyManager.php b/web/modules/features/src/FeaturesConfigDependencyManager.php deleted file mode 100644 index ea01e305cd632464df1916d1e27b4199d908e5f6..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesConfigDependencyManager.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Config\Entity\ConfigDependencyManager; -use Drupal\Core\Config\Entity\ConfigEntityDependency; - -/** - * Class FeaturesConfigDependencyManager - * @package Drupal\features - */ -class FeaturesConfigDependencyManager extends ConfigDependencyManager{ - - protected $sorted_graph; - - /** - * {@inheritdoc} - */ - public function getDependentEntities($type, $name) { - $dependent_entities = []; - - $entities_to_check = []; - if ($type == 'config') { - $entities_to_check[] = $name; - } - else { - if ($type == 'module' || $type == 'theme' || $type == 'content') { - $dependent_entities = array_filter($this->data, function (ConfigEntityDependency $entity) use ($type, $name) { - return $entity->hasDependency($type, $name); - }); - } - // If checking content, module, or theme dependencies, discover which - // entities are dependent on the entities that have a direct dependency. - foreach ($dependent_entities as $entity) { - $entities_to_check[] = $entity->getConfigDependencyName(); - } - } - $dependencies = array_merge($this->createGraphConfigEntityDependencies($entities_to_check), $dependent_entities); - if (!$this->sorted_graph) { - // Sort dependencies in the reverse order of the graph. So the least - // dependent is at the top. For example, this ensures that fields are - // always after field storages. This is because field storages need to be - // created before a field. - $this->sorted_graph = $this->getGraph(); - uasort($this->sorted_graph, [$this, 'sortGraph']); - } - return array_replace(array_intersect_key($this->sorted_graph, $dependencies), $dependencies); - } - - /** - * {@inheritdoc} - */ - public function setData(array $data) { - parent::setData($data); - $this->sorted_graph = NULL; - return $this; - } - -} diff --git a/web/modules/features/src/FeaturesConfigInstaller.php b/web/modules/features/src/FeaturesConfigInstaller.php deleted file mode 100644 index da4c2a94170e885ec215bb6dc7e63e2da7a1a2fa..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesConfigInstaller.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Config\ConfigInstaller; -use Drupal\Core\Config\ConfigInstallerInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Config\StorageInterface; -use Drupal\Core\Config\TypedConfigManagerInterface; -use Drupal\Core\Config\ConfigManagerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; - -/** - * Class for customizing the test for pre existing configuration. - * - * Decorates the ConfigInstaller with findPreExistingConfiguration() modified - * to allow Feature modules to be installed. - */ -class FeaturesConfigInstaller extends ConfigInstaller { - - /** - * The configuration installer. - * - * @var \Drupal\Core\Config\ConfigInstallerInterface - */ - protected $configInstaller; - - /** - * The features manager. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * Constructs the configuration installer. - * - * @param \Drupal\Core\Config\ConfigInstallerInterface $config_installer - * The configuration installer. - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The configuration factory. - * @param \Drupal\Core\Config\StorageInterface $active_storage - * The active configuration storage. - * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config - * The typed configuration manager. - * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager - * The configuration manager. - * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher - * The event dispatcher. - */ - public function __construct(ConfigInstallerInterface $config_installer, FeaturesManagerInterface $features_manager, ConfigFactoryInterface $config_factory, StorageInterface $active_storage, TypedConfigManagerInterface $typed_config, ConfigManagerInterface $config_manager, EventDispatcherInterface $event_dispatcher) { - $this->configInstaller = $config_installer; - $this->featuresManager = $features_manager; - - list($major, $minor, ) = explode('.', \Drupal::VERSION); - if ($major == 8 && $minor > 2) { - // D8.3 added the %install_profile% argument. - $install_profile = \Drupal::installProfile(); - parent::__construct($config_factory, $active_storage, $typed_config, $config_manager, $event_dispatcher, $install_profile); - } - else { - parent::__construct($config_factory, $active_storage, $typed_config, $config_manager, $event_dispatcher); - } - } - - /** - * {@inheritdoc} - */ - protected function findPreExistingConfiguration(StorageInterface $storage) { - // Override - // Drupal\Core\Config\ConfigInstaller::findPreExistingConfiguration(). - // Allow config that already exists coming from Features. - $features_config = array_keys($this->featuresManager->listExistingConfig()); - // Map array so we can use isset instead of in_array for faster access. - $features_config = array_combine($features_config, $features_config); - $existing_configuration = []; - // Gather information about all the supported collections. - $collection_info = $this->configManager->getConfigCollectionInfo(); - - foreach ($collection_info->getCollectionNames() as $collection) { - $config_to_create = array_keys($this->getConfigToCreate($storage, $collection)); - $active_storage = $this->getActiveStorages($collection); - foreach ($config_to_create as $config_name) { - if ($active_storage->exists($config_name)) { - // Test if config is part of a Feature package. - if (!isset($features_config[$config_name])) { - $existing_configuration[$collection][] = $config_name; - } - } - } - } - return $existing_configuration; - } - - /** - * Creates configuration in a collection based on the provided list. - * - * @param string $collection - * The configuration collection. - * @param array $config_to_create - * An array of configuration data to create, keyed by name. - */ - public function createConfiguration($collection, array $config_to_create) { - return parent::createConfiguration($collection, $config_to_create); - } - -} diff --git a/web/modules/features/src/FeaturesExtensionStorages.php b/web/modules/features/src/FeaturesExtensionStorages.php deleted file mode 100644 index 67dce968e62651ae79c5d4ffa63f8fce121bedb2..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesExtensionStorages.php +++ /dev/null @@ -1,121 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Config\InstallStorage; -use Drupal\Core\Config\StorageInterface; -use Drupal\Core\Extension\Extension; - -/** - * Wraps FeaturesInstallStorage to support multiple configuration - * directories. - */ -class FeaturesExtensionStorages implements FeaturesExtensionStoragesInterface { - - /** - * The target storage. - * - * @var \Drupal\Core\Config\StorageInterface - */ - protected $configStorage; - - /** - * The extension storages. - * - * @var \Drupal\Core\Config\StorageInterface[] - */ - protected $extensionStorages; - - /** - * Configuration provided by extension storages. - * - * @var array - */ - protected $configurationLists; - - /** - * Constructs a new FeaturesExtensionStorages object. - * - * @param \Drupal\Core\Config\StorageInterface $config_storage - * The configuration storage. - */ - public function __construct(StorageInterface $config_storage) { - $this->configStorage = $config_storage; - } - - /** - * {@inheritdoc} - */ - public function getExtensionStorages() { - return $this->extensionStorages; - } - - /** - * {@inheritdoc} - */ - public function addStorage($directory = InstallStorage::CONFIG_INSTALL_DIRECTORY) { - $this->extensionStorages[$directory] = new FeaturesInstallStorage($this->configStorage, $directory); - $this->reset(); - } - - /** - * {@inheritdoc} - */ - public function read($name) { - $list = $this->listAllByDirectory(''); - if (isset($list[$name])) { - $directory = $list[$name]; - return $this->extensionStorages[$directory]->read($name); - } - return FALSE; - } - - /** - * {@inheritdoc} - */ - public function listAll($prefix = '') { - return array_keys($this->listAllByDirectory($prefix)); - } - - /** - * {@inheritdoc} - */ - public function listExtensionConfig(Extension $extension) { - $extension_config = []; - foreach ($this->extensionStorages as $directory => $extension_storage) { - $extension_config = array_merge($extension_config, array_keys($extension_storage->getComponentNames([ - $extension->getName() => $extension, - ]))); - } - return $extension_config; - } - - /** - * Resets packages and configuration assignment. - */ - protected function reset() { - $this->configurationLists = []; - } - - /** - * Returns a list of all configuration available from extensions. - * - * @param string $prefix - * (optional) The prefix to search for. If omitted, all configuration object - * names that exist are returned. - * - * @return array - * An array with configuration item names as keys and configuration - * directories as values. - */ - protected function listAllByDirectory($prefix = '') { - if (!isset($this->configurationLists[$prefix])) { - $this->configurationLists[$prefix] = []; - foreach ($this->extensionStorages as $directory => $extension_storage) { - $this->configurationLists[$prefix] += array_fill_keys($extension_storage->listAll($prefix), $directory); - } - } - return $this->configurationLists[$prefix]; - } - -} diff --git a/web/modules/features/src/FeaturesExtensionStoragesByDirectory.php b/web/modules/features/src/FeaturesExtensionStoragesByDirectory.php deleted file mode 100644 index 6c0269e9e106967e369fdcb9c119821d65398015..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesExtensionStoragesByDirectory.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Drupal\features; - -/** - * Wraps FeaturesInstallStorage to support multiple configuration - * directories. - */ -class FeaturesExtensionStoragesByDirectory extends FeaturesExtensionStorages implements FeaturesExtensionStoragesByDirectoryInterface { - - /** - * {@inheritdoc} - */ - public function listAllByDirectory($prefix = '') { - if (!isset($this->configurationLists[$prefix])) { - $this->configurationLists[$prefix] = []; - foreach ($this->extensionStorages as $directory => $extension_storage) { - $this->configurationLists[$prefix] += array_fill_keys($extension_storage->listAll($prefix), $directory); - } - } - return $this->configurationLists[$prefix]; - } - -} diff --git a/web/modules/features/src/FeaturesExtensionStoragesByDirectoryInterface.php b/web/modules/features/src/FeaturesExtensionStoragesByDirectoryInterface.php deleted file mode 100644 index e955cecce3cf26963ffd77c5a72ce6e2f7ea0c74..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesExtensionStoragesByDirectoryInterface.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -namespace Drupal\features; - -/** - * Defines an extended interface for extension storages. - */ -interface FeaturesExtensionStoragesByDirectoryInterface extends FeaturesExtensionStoragesInterface { - - /** - * Returns a list of all configuration available from extensions. - * - * This method was made public late in the 8.x-3.x cycle and so is not - * included in the interface. - * - * @param string $prefix - * (optional) The prefix to search for. If omitted, all configuration object - * names that exist are returned. - * - * @return array - * An array with configuration item names as keys and configuration - * directories as values. - */ - public function listAllByDirectory($prefix = ''); - -} diff --git a/web/modules/features/src/FeaturesExtensionStoragesInterface.php b/web/modules/features/src/FeaturesExtensionStoragesInterface.php deleted file mode 100644 index a48ebd0e5857653166486ac32cc5ef37bb136ee3..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesExtensionStoragesInterface.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Config\InstallStorage; -use Drupal\Core\Extension\Extension; - -/** - * The FeaturesExtensionStorages provides a collection of extension storages, - * one for each supported configuration directory. - * - * Typically this will include the install and optional directories defined by - * Drupal core, but may also include any extension configuration directories - * added by contributed modules. - * - * This class serves as a partial wrapper to - * Drupal\Core\Config\StorageInterface, providing a subset of methods that can - * be called to apply to all available extension storages. For example, - * FeaturesExtensionStoragesInterface::read() will read an extension-provided - * configuration item regardless of which extension storage directory it is - * provided in. - */ -interface FeaturesExtensionStoragesInterface { - - /** - * Returns all registered extension storages. - * - * @return FeaturesInstallStorage[] - * Array of install storages keyed by configuration directory. - */ - public function getExtensionStorages(); - - /** - * Adds a storage. - * - * @param string $directory - * (optional) The configuration directory. If omitted, - * InstallStorage::CONFIG_INSTALL_DIRECTORY will be used. - */ - public function addStorage($directory = InstallStorage::CONFIG_INSTALL_DIRECTORY); - - /** - * Reads configuration data from the storages. - * - * @param string $name - * The name of a configuration object to load. - * - * @return array|bool - * The configuration data stored for the configuration object name. If no - * configuration data exists for the given name, FALSE is returned. - */ - public function read($name); - - /** - * Gets configuration object names starting with a given prefix. - * - * Given the following configuration objects: - * - node.type.article - * - node.type.page - * - * Passing the prefix 'node.type.' will return an array containing the above - * names. - * - * @param string $prefix - * (optional) The prefix to search for. If omitted, all configuration object - * names that exist are returned. - * - * @return array - * An array containing matching configuration object names. - */ - public function listAll($prefix = ''); - - /** - * Lists names of configuration objects provided by a given extension. - * - * If a $name and/or $namespace is specified, only matching modules will be - * returned. Otherwise, all install are returned. - * - * @param mixed $extension - * A string name of an extension or a full Extension object. - * - * @return array - * An array of configuration object names. - */ - public function listExtensionConfig(Extension $extension); - -} diff --git a/web/modules/features/src/FeaturesGenerationMethodBase.php b/web/modules/features/src/FeaturesGenerationMethodBase.php deleted file mode 100644 index e329f686399b02c82aa7c24daab9566d8a062145..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesGenerationMethodBase.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Component\Serialization\Yaml; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\StringTranslation\StringTranslationTrait; - -/** - * Base class for package assignment methods. - */ -abstract class FeaturesGenerationMethodBase implements FeaturesGenerationMethodInterface { - use StringTranslationTrait; - - /** - * The features manager. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * The features assigner. - * - * @var \Drupal\features\FeaturesAssignerInterface - */ - protected $assigner; - - /** - * {@inheritdoc} - */ - public function setFeaturesManager(FeaturesManagerInterface $features_manager) { - $this->featuresManager = $features_manager; - } - - /** - * {@inheritdoc} - */ - public function setAssigner(FeaturesAssignerInterface $assigner) { - $this->assigner = $assigner; - } - - /** - * {@inheritdoc} - */ - public function exportFormSubmit(array &$form, FormStateInterface $form_state) { - - } - - /** - * Merges an info file into a package's info file. - * - * @param string $package_info - * The Yaml encoded package info. - * @param string $info_file_uri - * The info file's URI. - */ - protected function mergeInfoFile($package_info, $info_file_uri) { - $package_info = Yaml::decode($package_info); - /** @var \Drupal\Core\Extension\InfoParserInterface $existing_info */ - $existing_info = \Drupal::service('info_parser')->parse($info_file_uri); - return Yaml::encode($this->featuresManager->mergeInfoArray($existing_info, $package_info)); - } - - /** - * {@inheritdoc} - */ - public function prepare(array &$packages = [], FeaturesBundleInterface $bundle = NULL) { - // If no packages were specified, get all packages. - if (empty($packages)) { - $packages = $this->featuresManager->getPackages(); - } - - // If any packages exist, read in their files. - $existing_packages = $this->featuresManager->listPackageDirectories(array_keys($packages), $bundle); - - foreach ($packages as &$package) { - list($full_name, $path) = $this->featuresManager->getExportInfo($package, $bundle); - if (empty($package->getDirectory())) { - $package->setDirectory($path); - } - - // If this is the profile, its directory is already assigned. - if (!isset($bundle) || !$bundle->isProfilePackage($package->getMachineName())) { - $current_path = $package->getDirectory(); - if (strpos($current_path, $full_name) < strlen($current_path) - strlen($full_name)) { - // Only append package name if it isn't already there. - $package->setDirectory($package->getDirectory() . '/' . $full_name); - } - } - - $this->preparePackage($package, $existing_packages, $bundle); - } - // Clean up the $package pass by reference. - unset($package); - } - - /** - * Performs any required changes on a package prior to generation. - * - * @param \Drupal\features\Package $package - * The package to be prepared. - * @param array $existing_packages - * An array of existing packages with machine names as keys and paths as - * values. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * Optional bundle used for export - */ - abstract protected function preparePackage(Package $package, array $existing_packages, FeaturesBundleInterface $bundle = NULL); - -} diff --git a/web/modules/features/src/FeaturesGenerationMethodInterface.php b/web/modules/features/src/FeaturesGenerationMethodInterface.php deleted file mode 100644 index 92b939280492a9e1d18342ad6f026ca991f9fdc8..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesGenerationMethodInterface.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Interface for package assignment classes. - */ -interface FeaturesGenerationMethodInterface { - - /** - * Injects the features manager. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager to be used to retrieve the configuration - * list and the assigned packages. - */ - public function setFeaturesManager(FeaturesManagerInterface $features_manager); - - /** - * Injects the features assigner. - * - * @param \Drupal\features\FeaturesAssignerInterface $assigner - * The features assigner to be used to retrieve the bundle configuration. - */ - public function setAssigner(FeaturesAssignerInterface $assigner); - - /** - * Prepares packages for generation. - * - * @param array $packages - * Array of package data. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * The optional bundle used for the generation. Used to generate profiles. - * - * @return array - * An array of packages data. - */ - public function prepare(array &$packages = [], FeaturesBundleInterface $bundle = NULL); - - /** - * Performs package generation. - * - * @param array $packages - * Array of package data. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * The optional bundle used for the generation. Used to generate profiles. - * - * @return array - * Array of results for profile and/or packages, each result including the - * following keys: - * - 'success': boolean TRUE or FALSE for successful writing. - * - 'display': boolean TRUE if the message should be displayed to the - * user, otherwise FALSE. - * - 'message': a message about the result of the operation. - * - 'variables': an array of substitutions to be used in the message. - */ - public function generate(array $packages = [], FeaturesBundleInterface $bundle = NULL); - - /** - * Responds to the submission of - * \Drupal\features_ui\Form\FeaturesExportForm. - */ - public function exportFormSubmit(array &$form, FormStateInterface $form_state); - -} diff --git a/web/modules/features/src/FeaturesGenerationMethodManager.php b/web/modules/features/src/FeaturesGenerationMethodManager.php deleted file mode 100644 index 9ede58e60801a508f86702d42a0d09147f521ff2..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesGenerationMethodManager.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Plugin\DefaultPluginManager; - -/** - * Manages configuration packaging methods. - */ -class FeaturesGenerationMethodManager extends DefaultPluginManager { - - /** - * Constructs a new FeaturesGenerationMethodManager object. - * - * @param \Traversable $namespaces - * An object that implements \Traversable which contains the root paths - * keyed by the corresponding namespace to look for plugin implementations. - * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend - * An object that implements CacheBackendInterface. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * An object that implements ModuleHandlerInterface. - */ - public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct('Plugin/FeaturesGeneration', $namespaces, $module_handler, 'Drupal\features\FeaturesGenerationMethodInterface'); - $this->cacheBackend = $cache_backend; - $this->cacheKeyPrefix = 'features_generation_methods'; - $this->cacheKey = 'features_generation_methods'; - $this->alterInfo('features_generation_info'); - } - -} diff --git a/web/modules/features/src/FeaturesGenerator.php b/web/modules/features/src/FeaturesGenerator.php deleted file mode 100644 index ae21e60b7a04a1a3e29bde734740246ec21571ee..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesGenerator.php +++ /dev/null @@ -1,173 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Component\Plugin\PluginManagerInterface; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\StringTranslation\StringTranslationTrait; - -/** - * Class responsible for performing package generation. - */ -class FeaturesGenerator implements FeaturesGeneratorInterface { - use StringTranslationTrait; - - /** - * The package generation method plugin manager. - * - * @var \Drupal\Component\Plugin\PluginManagerInterface - */ - protected $generatorManager; - - /** - * The features manager. - * - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * The features assigner. - * - * @var \Drupal\features\FeaturesAssignerInterface - */ - protected $assigner; - - /** - * Local cache for package generation method instances. - * - * @var array - */ - protected $methods; - - /** - * Constructs a new FeaturesGenerator object. - * - * @param \Drupal\features\FeaturesManagerInterface $features_manager - * The features manager. - * @param \Drupal\Component\Plugin\PluginManagerInterface $generator_manager - * The package generation methods plugin manager. - */ - public function __construct(FeaturesManagerInterface $features_manager, PluginManagerInterface $generator_manager, FeaturesAssignerInterface $assigner) { - $this->featuresManager = $features_manager; - $this->generatorManager = $generator_manager; - $this->assigner = $assigner; - } - - /** - * Initializes the injected features manager with the generator. - * - * This should be called right after instantiating the generator to make it - * available to the features manager without introducing a circular - * dependency. - */ - public function initFeaturesManager() { - $this->featuresManager->setGenerator($this); - } - - /** - * {@inheritdoc} - */ - public function reset() { - $this->methods = []; - } - - /** - * {@inheritdoc} - */ - public function applyGenerationMethod($method_id, array $packages = [], FeaturesBundleInterface $bundle = NULL) { - $method = $this->getGenerationMethodInstance($method_id); - $method->prepare($packages, $bundle); - return $method->generate($packages, $bundle); - } - - /** - * {@inheritdoc} - */ - public function applyExportFormSubmit($method_id, &$form, FormStateInterface $form_state) { - $method = $this->getGenerationMethodInstance($method_id); - $method->exportFormSubmit($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function getGenerationMethods() { - return $this->generatorManager->getDefinitions(); - } - - /** - * Returns an instance of the specified package generation method. - * - * @param string $method_id - * The string identifier of the package generation method to use to package - * configuration. - * - * @return \Drupal\features\FeaturesGenerationMethodInterface - */ - protected function getGenerationMethodInstance($method_id) { - if (!isset($this->methods[$method_id])) { - $instance = $this->generatorManager->createInstance($method_id, []); - $instance->setFeaturesManager($this->featuresManager); - $instance->setAssigner($this->assigner); - $this->methods[$method_id] = $instance; - } - return $this->methods[$method_id]; - } - - /** - * {@inheritdoc} - */ - public function generatePackages($method_id, FeaturesBundleInterface $bundle, array $package_names = []) { - $this->featuresManager->setPackageBundleNames($bundle, $package_names); - return $this->generate($method_id, $bundle, $package_names); - } - - /** - * Generates a file representation of configuration packages and, optionally, - * an install profile. - * - * @param string $method_id - * The ID of the generation method to use. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * The bundle used for the generation. - * @param string[] $package_names - * Names of packages to be generated. If none are specified, all - * available packages will be added. - * - * @return array - * Array of results for profile and/or packages, each result including the - * following keys: - * - 'success': boolean TRUE or FALSE for successful writing. - * - 'display': boolean TRUE if the message should be displayed to the - * user, otherwise FALSE. - * - 'message': a message about the result of the operation. - * - 'variables': an array of substitutions to be used in the message. - */ - protected function generate($method_id, FeaturesBundleInterface $bundle, array $package_names = []) { - $packages = $this->featuresManager->getPackages(); - - // Filter out the packages that weren't requested. - if (!empty($package_names)) { - $packages = array_intersect_key($packages, array_fill_keys($package_names, NULL)); - } - - $this->featuresManager->assignInterPackageDependencies($bundle, $packages); - - // Prepare the files. - $this->featuresManager->prepareFiles($packages); - - $return = $this->applyGenerationMethod($method_id, $packages, $bundle); - - foreach ($return as $message) { - if ($message['display']) { - $type = $message['success'] ? 'status' : 'error'; - drupal_set_message($this->t($message['message'], $message['variables']), $type); - } - $type = $message['success'] ? 'notice' : 'error'; - \Drupal::logger('features')->{$type}($message['message'], $message['variables']); - } - return $return; - } - -} diff --git a/web/modules/features/src/FeaturesGeneratorInterface.php b/web/modules/features/src/FeaturesGeneratorInterface.php deleted file mode 100644 index 0cafa145143558b25bc3ebd1c92b73a89c3b2b06..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesGeneratorInterface.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Form\FormStateInterface; - -/** - * Common interface for features generation services. - * - * The configuration packaging API is based on two major concepts: - * - Packages: modules into which configuration is packaged. - * - Package generation methods: responsible for `determining - * which package to assign a given piece of configuration to. - * Generation methods are customizable. - * - * Features defines two package generation methods, which are simple plugin - * classes that implement a particular logic to assign pieces of configuration - * to a given package (module). - * - * Modules can define additional package generation methods by simply providing - * the related plugins, and alter existing methods through - * hook_features_generation_method_info_alter(). Here is an example - * snippet: - * @code - * function mymodule_features_generation_method_info_alter(&$generation_info) { - * // Replace the original plugin with our own implementation. - * $method_id = \Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationArchive::METHOD_ID; - * $generation_info[$method_id]['class'] = 'Drupal\my_module\Plugin\FeaturesGeneration\MyFeaturesGenerationArchive'; - * } - * - * class MyFeaturesGenerationArchive extends FeaturesGenerationArchive { - * public function generate(array $packages = array(), FeaturesBundleInterface $bundle = NULL) { - * // Insert customization here. - * } - * } - * ?> - * @endcode - * - * For more information, see - * @link http://drupal.org/node/2404473 Developing for Features 3.x @endlink - */ -interface FeaturesGeneratorInterface { - - /** - * The package generation method id for the package generator itself. - */ - const METHOD_ID = 'generator-default'; - - /** - * Resets the assigned packages and the method instances. - */ - public function reset(); - - /** - * Apply a given package generation method. - * - * @param string $method_id - * The string identifier of the package generation method to use to package - * configuration. - * @param array $packages - * Array of package data. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * The optional bundle used for the generation. Used to generate profiles. - * - * @return array - * Array of results for profile and/or packages, each result including the - * following keys: - * - 'success': boolean TRUE or FALSE for successful writing. - * - 'display': boolean TRUE if the message should be displayed to the - * user, otherwise FALSE. - * - 'message': a message about the result of the operation. - * - 'variables': an array of substitutions to be used in the message. - */ - public function applyGenerationMethod($method_id, array $packages = [], FeaturesBundleInterface $bundle = NULL); - - /** - * Responds to the submission of - * \Drupal\features_ui\Form\FeaturesExportForm. - */ - public function applyExportFormSubmit($method_id, &$form, FormStateInterface $form_state); - - /** - * Returns the enabled package generation methods. - * - * @return array - * An array of package generation method definitions keyed by method id. - */ - public function getGenerationMethods(); - - /** - * Generates file representations of configuration packages. - * - * @param string $method_id - * The ID of the generation method to use. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * The bundle used for the generation. - * @param array $package_names - * Array of names of packages to be generated. If none are specified, all - * available packages will be added. - */ - public function generatePackages($method_id, FeaturesBundleInterface $bundle, array $package_names = []); - -} diff --git a/web/modules/features/src/FeaturesInstallStorage.php b/web/modules/features/src/FeaturesInstallStorage.php deleted file mode 100644 index 666b5d6803ded4287a04628bcda123e08d9c7535..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesInstallStorage.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Site\Settings; -use Drupal\Core\Config\ExtensionInstallStorage; -use Drupal\Core\Config\StorageInterface; -use Drupal\Core\Extension\ExtensionDiscovery; - -/** - * Storage to access configuration and schema in installed extensions. - * - * Overrides the normal ExtensionInstallStorage to prevent profile from - * overriding. - * - * Also supports modules that are not installed yet. - * - * @see \Drupal\Core\Config\ExtensionInstallStorage - */ -class FeaturesInstallStorage extends ExtensionInstallStorage { - - /** - * Overrides \Drupal\Core\Config\ExtensionInstallStorage::__construct(). - * - * Sets includeProfile to FALSE. - * - * @param \Drupal\Core\Config\StorageInterface $config_storage - * The active configuration store where the list of installed modules and - * themes is stored. - * @param string $directory - * The directory to scan in each extension to scan for files. Defaults to - * 'config/install'. - * @param string $collection - * (optional) The collection to store configuration in. Defaults to the - * default collection. - */ - public function __construct(StorageInterface $config_storage, $directory = self::CONFIG_INSTALL_DIRECTORY, $collection = StorageInterface::DEFAULT_COLLECTION) { - list($major, $minor, ) = explode('.', \Drupal::VERSION); - if ($major == 8 && $minor > 2) { - // D8.3 added the %profile% argument. - $profile = \Drupal::installProfile(); - parent::__construct($config_storage, $directory, $collection, FALSE, $profile); - } - else { - parent::__construct($config_storage, $directory, $collection, FALSE); - } - } - - /** - * Returns a map of all config object names and their folders. - * - * The list is based on installed modules and themes. The active - * configuration storage is used rather than - * \Drupal\Core\Extension\ModuleHandler and - * \Drupal\Core\Extension\ThemeHandler in order to resolve circular - * dependencies between these services and - * \Drupal\Core\Config\ConfigInstaller and - * \Drupal\Core\Config\TypedConfigManager. - * - * NOTE: This code is copied from ExtensionInstallStorage::getAllFolders() with - * the following changes (Notes in CHANGED below) - * - Load all modules whether installed or not - * - * @return array - * An array mapping config object names with directories. - */ - public function getAllFolders() { - if (!isset($this->folders)) { - $this->folders = []; - $this->folders += $this->getCoreNames(); - - $install_profile = Settings::get('install_profile'); - $profile = drupal_get_profile(); - $extensions = $this->configStorage->read('core.extension'); - // @todo Remove this scan as part of https://www.drupal.org/node/2186491 - $listing = new ExtensionDiscovery(\Drupal::root()); - - // CHANGED START: Add profile directories for any bundles that use a profile. - $listing->setProfileDirectoriesFromSettings(); - $profile_directories = $listing->getProfileDirectories(); - if ($this->includeProfile) { - // Add any profiles used in bundles. - /** @var \Drupal\features\FeaturesAssignerInterface $assigner */ - $assigner = \Drupal::service('features_assigner'); - $bundles = $assigner->getBundleList(); - foreach ($bundles as $bundle_name => $bundle) { - if ($bundle->isProfile()) { - // Register the profile directory. - $profile_directory = 'profiles/' . $bundle->getProfileName(); - if (is_dir($profile_directory)) { - $profile_directories[] = $profile_directory; - } - } - } - } - $listing->setProfileDirectories($profile_directories); - // CHANGED END - - if (!empty($extensions['module'])) { - - // CHANGED START: Find ANY modules, not just installed ones. - //$modules = $extensions['module']; - $module_list_scan = $listing->scan('module'); - $modules = $module_list_scan; - // CHANGED END - - // Remove the install profile as this is handled later. - unset($modules[$install_profile]); - $profile_list = $listing->scan('profile'); - if ($profile && isset($profile_list[$profile])) { - // Prime the drupal_get_filename() static cache with the profile info - // file location so we can use drupal_get_path() on the active profile - // during the module scan. - // @todo Remove as part of https://www.drupal.org/node/2186491 - drupal_get_filename('profile', $profile, $profile_list[$profile]->getPathname()); - } - // CHANGED START: Put Features modules first in list returned. - // to allow features to override config provided by other extensions. - $featuresManager = \Drupal::service('features.manager'); - $features_list = []; - $module_list = []; - foreach (array_keys($module_list_scan) as $module) { - if ($featuresManager->isFeatureModule($module_list_scan[$module])) { - $features_list[$module] = $module_list_scan[$module]; - } - else { - $module_list[$module] = $module_list_scan[$module]; - } - } - $this->folders += $this->getComponentNames($features_list); - $this->folders += $this->getComponentNames($module_list); - // CHANGED END - } - if (!empty($extensions['theme'])) { - $theme_list_scan = $listing->scan('theme'); - foreach (array_keys($extensions['theme']) as $theme) { - if (isset($theme_list_scan[$theme])) { - $theme_list[$theme] = $theme_list_scan[$theme]; - } - } - $this->folders += $this->getComponentNames($theme_list); - } - - if ($this->includeProfile) { - // The install profile can override module default configuration. We do - // this by replacing the config file path from the module/theme with the - // install profile version if there are any duplicates. - if (isset($profile)) { - if (!isset($profile_list)) { - $profile_list = $listing->scan('profile'); - } - if (isset($profile_list[$profile])) { - $profile_folders = $this->getComponentNames([$profile_list[$profile]]); - $this->folders = $profile_folders + $this->folders; - } - } - } - } - - return $this->folders; - } - -} diff --git a/web/modules/features/src/FeaturesManager.php b/web/modules/features/src/FeaturesManager.php deleted file mode 100644 index 07c46e0427855f187db15011ff2c764c1c941a29..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesManager.php +++ /dev/null @@ -1,1399 +0,0 @@ -<?php - -namespace Drupal\features; -use Drupal; -use Drupal\Component\Serialization\Yaml; -use Drupal\Component\Utility\NestedArray; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Config\ConfigManagerInterface; -use Drupal\Core\Config\InstallStorage; -use Drupal\Core\Config\StorageInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\Core\Extension\Extension; -use Drupal\Core\Extension\ExtensionDiscovery; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\config_update\ConfigRevertInterface; - -/** - * The FeaturesManager provides helper functions for building packages. - */ -class FeaturesManager implements FeaturesManagerInterface { - use StringTranslationTrait; - - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * The target storage. - * - * @var \Drupal\Core\Config\StorageInterface - */ - protected $configStorage; - - /** - * The extension storages. - * - * @var \Drupal\features\FeaturesExtensionStoragesByDirectoryInterface - */ - protected $extensionStorages; - - /** - * The configuration manager. - * - * @var \Drupal\Core\Config\ConfigManagerInterface - */ - protected $configManager; - - /** - * The configuration factory. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected $configFactory; - - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * The config reverter. - * - * @var \Drupal\config_update\ConfigRevertInterface - */ - protected $configReverter; - - /** - * The Features settings. - * - * @var array - */ - protected $settings; - - /** - * The app root. - * - * @var string - */ - protected $root; - - /** - * The configuration present on the site. - * - * @var \Drupal\features\ConfigurationItem[] - */ - private $configCollection; - - /** - * The packages to be generated. - * - * @var \Drupal\features\Package[] - */ - protected $packages; - - /** - * Whether the packages have been assigned a bundle prefix. - * - * @var boolean - */ - protected $packagesPrefixed; - - /** - * The package assigner. - * - * @var \Drupal\features\FeaturesAssigner - */ - protected $assigner; - - /** - * Cache module.features.yml data keyed by module name. - * - * @var array - */ - protected $featureInfoCache; - - /** - * Constructs a FeaturesManager object. - * - * @param string $root - * The app root. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity type manager. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The configuration factory. - * @param \Drupal\Core\Config\StorageInterface $config_storage - * The target storage. - * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager - * The configuration manager. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler. - * @param \Drupal\config_update\ConfigRevertInterface $config_reverter - */ - public function __construct($root, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, - StorageInterface $config_storage, ConfigManagerInterface $config_manager, - ModuleHandlerInterface $module_handler, ConfigRevertInterface $config_reverter) { - $this->root = $root; - $this->entityTypeManager = $entity_type_manager; - $this->configStorage = $config_storage; - $this->configManager = $config_manager; - $this->moduleHandler = $module_handler; - $this->configFactory = $config_factory; - $this->configReverter = $config_reverter; - $this->settings = $config_factory->getEditable('features.settings'); - $this->extensionStorages = new FeaturesExtensionStoragesByDirectory($this->configStorage); - $this->extensionStorages->addStorage(InstallStorage::CONFIG_INSTALL_DIRECTORY); - $this->extensionStorages->addStorage(InstallStorage::CONFIG_OPTIONAL_DIRECTORY); - $this->packages = []; - $this->packagesPrefixed = FALSE; - $this->configCollection = []; - } - - /** - * {@inheritdoc} - */ - public function setRoot($root) { - $this->root = $root; - // Clear cache. - $this->featureInfoCache = []; - } - - /** - * {@inheritdoc} - */ - public function getActiveStorage() { - return $this->configStorage; - } - - /** - * {@inheritdoc} - */ - public function getExtensionStorages() { - return $this->extensionStorages; - } - - /** - * {@inheritdoc} - */ - public function getFullName($type, $name) { - if ($type == FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG || !$type) { - return $name; - } - - $definition = $this->entityTypeManager->getDefinition($type); - $prefix = $definition->getConfigPrefix() . '.'; - return $prefix . $name; - } - - /** - * {@inheritdoc} - */ - public function getConfigType($fullname) { - $result = [ - 'type' => '', - 'name_short' => '', - ]; - $prefix = FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG . '.'; - if (strpos($fullname, $prefix) !== FALSE) { - $result['type'] = FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG; - $result['name_short'] = substr($fullname, strlen($prefix)); - } - else { - foreach ($this->entityTypeManager->getDefinitions() as $entity_type => $definition) { - if ($definition->isSubclassOf('Drupal\Core\Config\Entity\ConfigEntityInterface')) { - $prefix = $definition->getConfigPrefix() . '.'; - if (strpos($fullname, $prefix) === 0) { - $result['type'] = $entity_type; - $result['name_short'] = substr($fullname, strlen($prefix)); - } - } - } - } - return $result; - } - - /** - * {@inheritdoc} - */ - public function reset() { - $this->packages = []; - // Don't use getConfigCollection because reset() may be called in - // cases where we don't need to load config. - foreach ($this->configCollection as $config) { - $config->setPackage(NULL); - } - } - - /** - * {@inheritdoc} - */ - public function getConfigCollection($reset = FALSE) { - $this->initConfigCollection($reset); - return $this->configCollection; - } - - /** - * {@inheritdoc} - */ - public function setConfigCollection(array $config_collection) { - $this->configCollection = $config_collection; - } - - /** - * {@inheritdoc} - */ - public function getPackages() { - return $this->packages; - } - - /** - * {@inheritdoc} - */ - public function setPackages(array $packages) { - $this->packages = $packages; - } - - /** - * {@inheritdoc} - */ - public function getPackage($machine_name) { - if (isset($this->packages[$machine_name])) { - return $this->packages[$machine_name]; - } - return NULL; - } - - /** - * {@inheritdoc} - */ - public function findPackage($machine_name) { - $result = $this->getPackage($machine_name); - if (!isset($result)) { - // Didn't find direct match, but now go through and look for matching - // full name (bundle_machinename) - foreach ($this->packages as $name => $package) { - if ($package->getFullName() == $machine_name) { - return $this->packages[$name]; - } - } - } - return $result; - } - - /** - * {@inheritdoc} - */ - public function setPackage(Package $package) { - if ($package->getMachineName()) { - $this->packages[$package->getMachineName()] = $package; - } - } - - /** - * {@inheritdoc} - */ - public function loadPackage($module_name, $any = FALSE) { - $package = $this->getPackage($module_name); - // Load directly from module if packages are not loaded or - // if we want to include ANY module regardless of its a feature. - if ((empty($this->packages) || $any) && !isset($package)) { - $module_list = $this->moduleHandler->getModuleList(); - if (!empty($module_list[$module_name])) { - $extension = $module_list[$module_name]; - $package = $this->initPackageFromExtension($extension); - $config = $this->listExtensionConfig($extension); - $package->setConfigOrig($config); - $package->setStatus(FeaturesManagerInterface::STATUS_INSTALLED); - } - } - return $package; - } - - /** - * {@inheritdoc} - */ - public function filterPackages(array $packages, $namespace = '', $only_exported = FALSE) { - $result = []; - /** @var \Drupal\features\Package $package */ - foreach ($packages as $key => $package) { - // A package matches the namespace if: - // - it's prefixed with the namespace, or - // - it's assigned to a bundle named for the namespace, or - // - the namespace is the default bundle and it has an empty bundle, and - // - we're not removing only exported packages, or - // - we are removing only exported packages and it's not exported. - if ((strpos($package->getMachineName(), $namespace . '_') === 0 || - ($package->getBundle() && $package->getBundle() === $namespace) || - ($namespace === FeaturesBundleInterface::DEFAULT_BUNDLE && empty($package->getBundle()))) && - (!$only_exported || ($package->getStatus() === FeaturesManagerInterface::STATUS_NO_EXPORT))) { - $result[$key] = $package; - } - } - return $result; - } - - /** - * {@inheritdoc} - */ - public function getAssigner() { - if (empty($this->assigner)) { - $this->setAssigner(\Drupal::service('features_assigner')); - } - return $this->assigner; - } - - /** - * {@inheritdoc} - */ - public function setAssigner(FeaturesAssignerInterface $assigner) { - $this->assigner = $assigner; - $this->reset(); - } - - /** - * {@inheritdoc} - */ - public function getGenerator() { - return $this->generator; - } - - /** - * {@inheritdoc} - */ - public function setGenerator(FeaturesGeneratorInterface $generator) { - $this->generator = $generator; - } - - /** - * {@inheritdoc} - */ - public function getExportSettings() { - return $this->settings->get('export'); - } - - /** - * {@inheritdoc} - */ - public function getSettings() { - return $this->settings; - } - - /** - * {@inheritdoc} - */ - public function getExtensionInfo(Extension $extension) { - return \Drupal::service('info_parser')->parse($this->root . '/' . $extension->getPathname()); - } - - /** - * {@inheritdoc} - */ - public function isFeatureModule(Extension $module, FeaturesBundleInterface $bundle = NULL) { - if ($features_info = $this->getFeaturesInfo($module)) { - // If no bundle was requested, it's enough that this is a feature. - if (is_null($bundle)) { - return TRUE; - } - // If the default bundle was requested, look for features where - // the bundle is not set. - elseif ($bundle->isDefault()) { - return !isset($features_info['bundle']); - } - // If we have a bundle name, look for it. - else { - return (isset($features_info['bundle']) && ($features_info['bundle'] == $bundle->getMachineName())); - } - } - return FALSE; - } - - /** - * {@inheritdoc} - */ - public function listPackageDirectories(array $machine_names = [], FeaturesBundleInterface $bundle = NULL) { - if (empty($machine_names)) { - $machine_names = array_keys($this->getPackages()); - } - - // If the bundle is a profile, then add the profile's machine name. - if (isset($bundle) && $bundle->isProfile() && !in_array($bundle->getProfileName(), $machine_names)) { - $machine_names[] = $bundle->getProfileName(); - } - - // If we are checking the default bundle, return all features. - if (isset($bundle) && $bundle->isDefault()) { - $bundle = NULL; - } - - $modules = $this->getFeaturesModules($bundle); - // Filter to include only the requested packages. - $modules = array_filter($modules, function ($module) use ($bundle, $machine_names) { - return in_array($module->getName(), $machine_names); - }); - - $directories = []; - foreach ($modules as $module) { - $directories[$module->getName()] = $module->getPath(); - } - - return $directories; - } - - /** - * {@inheritdoc} - */ - public function getAllModules() { - static $modules; - - if (!isset($modules)) { - // ModuleHandler::getModuleDirectories() returns data only for installed - // modules. system_rebuild_module_data() includes only the site's install - // profile directory, while we may need to include a custom profile. - // @see _system_rebuild_module_data(). - $listing = new ExtensionDiscovery($this->root); - - $profile_directories = $listing->setProfileDirectoriesFromSettings()->getProfileDirectories(); - $installed_profile = $this->drupalGetProfile(); - if (isset($bundle) && $bundle->isProfile()) { - $profile_directory = 'profiles/' . $bundle->getProfileName(); - if (($bundle->getProfileName() != $installed_profile) && is_dir($profile_directory)) { - $profile_directories[] = $profile_directory; - } - } - $listing->setProfileDirectories($profile_directories); - - // Find modules. - $modules = $listing->scan('module'); - - // Find installation profiles. - $profiles = $listing->scan('profile'); - - foreach ($profiles as $key => $profile) { - $modules[$key] = $profile; - } - } - - return $modules; - } - - /** - * {@inheritdoc} - */ - public function getFeaturesModules(FeaturesBundleInterface $bundle = NULL, $installed = FALSE) { - $modules = $this->getAllModules(); - - // Filter by bundle. - $features_manager = $this; - $modules = array_filter($modules, function ($module) use ($features_manager, $bundle) { - return $features_manager->isFeatureModule($module, $bundle); - }); - - // Filtered by installed status. - if ($installed) { - $features_manager = $this; - $modules = array_filter($modules, function ($extension) use ($features_manager) { - return $features_manager->extensionEnabled($extension); - }); - } - - return $modules; - } - - /** - * {@inheritdoc} - */ - public function extensionEnabled(Extension $extension) { - return $this->moduleHandler->moduleExists($extension->getName()); - } - - /** - * {@inheritdoc} - */ - public function initPackage($machine_name, $name = NULL, $description = '', $type = 'module', FeaturesBundleInterface $bundle = NULL, Extension $extension = NULL) { - if (isset($this->packages[$machine_name])) { - return $this->packages[$machine_name]; - } - // Also look for existing package within the bundle - elseif (isset($bundle) && isset($this->packages[$bundle->getFullName($machine_name)])) { - return $this->packages[$bundle->getFullName($machine_name)]; - } - return $this->packages[$machine_name] = $this->getPackageObject($machine_name, $name, $description, $type, $bundle, $extension); - } - - /** - * {@inheritdoc} - */ - public function initPackageFromExtension(Extension $extension) { - $info = $this->getExtensionInfo($extension); - $features_info = $this->getFeaturesInfo($extension); - $bundle = $this->getAssigner()->findBundle($info, $features_info); - // Use the full extension name as the short_name. Important to allow - // multiple modules with different namespaces such as oa_media, test_media. - $short_name = $extension->getName(); - return $this->initPackage($short_name, $info['name'], !empty($info['description']) ? $info['description'] : '', $info['type'], $bundle, $extension); - } - - /** - * Helper function to update dependencies array for a specific config item - * @param \Drupal\features\ConfigurationItem $config a config item - * @param array $module_list - * @return array $dependencies - */ - protected function getConfigDependency(ConfigurationItem $config, $module_list = []) { - $dependencies = []; - $type = $config->getType(); - - // For configuration in the InstallStorage::CONFIG_INSTALL_DIRECTORY - // directory, set any dependencies of the configuration item as package - // dependencies. - // As its name implies, the core-provided - // InstallStorage::CONFIG_OPTIONAL_DIRECTORY should not create - // dependencies. - if ($config->getSubdirectory() === InstallStorage::CONFIG_INSTALL_DIRECTORY) { - if ($type === FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG) { - $dependencies[] = strtok($config->getName(), '.'); - } - else { - $dependencies[] = $this->entityTypeManager->getDefinition($type)->getProvider(); - } - - if (isset($config->getData()['dependencies']['module'])) { - $dependencies = array_merge($dependencies, $config->getData()['dependencies']['module']); - } - - // Only return dependencies for installed modules and not, for example, - // 'core'. - $dependencies = array_intersect($dependencies, array_keys($module_list)); - } - - return $dependencies; - } - - /** - * {@inheritdoc} - */ - public function assignConfigPackage($package_name, array $item_names, $force = FALSE) { - $config_collection = $this->getConfigCollection(); - $module_list = $this->moduleHandler->getModuleList(); - - $packages =& $this->packages; - if (isset($packages[$package_name])) { - $package =& $packages[$package_name]; - } - else { - throw new \Exception($this->t('Failed to package @package_name. Package not found.', ['@package_name' => $package_name])); - } - - foreach ($item_names as $item_name) { - if (isset($config_collection[$item_name])) { - // Add to the package if: - // - force is set or - // - the item hasn't already been assigned elsewhere, and - // - the package hasn't been excluded. - // - and the item isn't already in the package. - - $item = &$config_collection[$item_name]; - $already_assigned = !empty($item->getPackage()); - // If this is the profile package, we can reassign extension-provided configuration. - $package_bundle = $this->getAssigner()->getBundle($package->getBundle()); - $is_profile_package = isset($package_bundle) ? $package_bundle->isProfilePackage($package_name) : FALSE; - // An item is assignable if: - // - it is not provider excluded or this is the profile package, and - // - it is not flagged as excluded. - $assignable = (!$item->isProviderExcluded() || $is_profile_package) && !$item->isExcluded(); - // An item is assignable if it was provided by the current package - $assignable = $assignable || ($item->getProvider() == $package->getMachineName()); - $excluded_from_package = in_array($package_name, $item->getPackageExcluded()); - $already_in_package = in_array($item_name, $package->getConfig()); - if (($force || (!$already_assigned && $assignable && !$excluded_from_package)) && !$already_in_package) { - // Add the item to the package's config array. - $package->appendConfig($item_name); - // Mark the item as already assigned. - $item->setPackage($package_name); - - $module_dependencies = $this->getConfigDependency($item, $module_list); - $package->setDependencies($this->mergeUniqueItems($package->getDependencies(), $module_dependencies)); - } - // Return memory - unset($item); - } - } - - $this->setConfigCollection($config_collection); - } - - /** - * {@inheritdoc} - */ - public function assignConfigByPattern(array $patterns) { - // Regular expressions for items that are likely to generate false - // positives when assigned by pattern. - $false_positives = [ - // Blocks with the page title should not be assigned to a 'page' package. - '/block\.block\..*_page_title/', - ]; - $config_collection = $this->getConfigCollection(); - // Sort by key so that specific package will claim items before general - // package. E.g., event_registration and registration_event will claim - // before event. - uksort($patterns, function($a, $b) { - // Count underscores to determine specificity of the package. - return (int) (substr_count($a, '_') <= substr_count($b, '_')); - }); - foreach ($patterns as $pattern => $machine_name) { - if (isset($this->packages[$machine_name])) { - foreach ($config_collection as $item_name => $item) { - // Test for and skip false positives. - foreach ($false_positives as $false_positive) { - if (preg_match($false_positive, $item_name)) { - continue 2; - } - } - - if (!$item->getPackage() && preg_match('/(\.|-|_|^)' . $pattern . '(\.|-|_|$)/', $item->getShortName())) { - try { - $this->assignConfigPackage($machine_name, [$item_name]); - } - catch (\Exception $exception) { - \Drupal::logger('features')->error($exception->getMessage()); - } - } - } - } - } - } - - /** - * {@inheritdoc} - */ - public function assignConfigDependents(array $item_names = NULL, $package = NULL) { - $config_collection = $this->getConfigCollection(); - if (empty($item_names)) { - $item_names = array_keys($config_collection); - } - foreach ($item_names as $item_name) { - // Make sure the extension provided item exists in the active - // configuration storage. - if (isset($config_collection[$item_name]) && $config_collection[$item_name]->getPackage()) { - foreach ($config_collection[$item_name]->getDependents() as $dependent_item_name) { - if (isset($config_collection[$dependent_item_name]) && (!empty($package) || empty($config_collection[$dependent_item_name]->getPackage()))) { - try { - $package_name = !empty($package) ? $package : $config_collection[$item_name]->getPackage(); - $this->assignConfigPackage($package_name, [$dependent_item_name]); - } - catch (\Exception $exception) { - \Drupal::logger('features')->error($exception->getMessage()); - } - } - } - } - } - } - - /** - * {@inheritdoc} - */ - public function setPackageBundleNames(FeaturesBundleInterface $bundle, array &$package_names = []) { - $this->packagesPrefixed = TRUE; - if (!$bundle->isDefault()) { - $new_package_names = []; - // Assign the selected bundle to the exports. - $packages = $this->getPackages(); - if (empty($package_names)) { - $package_names = array_keys($packages); - } - foreach ($package_names as $package_name) { - // Rename package to use bundle prefix. - $package = $packages[$package_name]; - - // The install profile doesn't need renaming. - if ($package->getType() != 'profile') { - unset($packages[$package_name]); - $package->setMachineName($bundle->getFullName($package->getMachineName())); - $packages[$package->getMachineName()] = $package; - } - - // Set the bundle machine name. - $packages[$package->getMachineName()]->setBundle($bundle->getMachineName()); - $new_package_names[] = $package->getMachineName(); - } - $this->setPackages($packages); - $package_names = $new_package_names; - } - } - - /** - * {@inheritdoc} - */ - public function assignPackageDependencies(Package $package = NULL) { - if (is_null($package)) { - $packages = $this->getPackages(); - } - else { - $packages = [$package]; - } - $module_list = $this->moduleHandler->getModuleList(); - $config_collection = $this->getConfigCollection(); - - foreach ($packages as $package) { - $module_dependencies = []; - foreach ($package->getConfig() as $item_name) { - if (isset($config_collection[$item_name])) { - $dependencies = $this->getConfigDependency($config_collection[$item_name], $module_list); - $module_dependencies = array_merge($module_dependencies, $dependencies); - } - } - $package->setDependencies($this->mergeUniqueItems($package->getDependencies(), $module_dependencies)); - } - } - - /** - * {@inheritdoc} - */ - public function assignInterPackageDependencies(FeaturesBundleInterface $bundle, array &$packages) { - if (!$this->packagesPrefixed) { - throw new \Exception($this->t('The packages have not yet been prefixed with a bundle name.')); - } - - $config_collection = $this->getConfigCollection(); - $module_list = $this->moduleHandler->getModuleList(); - - /** @var \Drupal\features\Package[] $packages */ - foreach ($packages as $package) { - foreach ($package->getConfig() as $item_name) { - if (!empty($config_collection[$item_name]->getData()['dependencies']['config'])) { - foreach ($config_collection[$item_name]->getData()['dependencies']['config'] as $dependency_name) { - if (isset($config_collection[$dependency_name]) && - // For configuration in the - // InstallStorage::CONFIG_INSTALL_DIRECTORY directory, set any - // package dependencies of the configuration item. - // As its name implies, the core-provided - // InstallStorage::CONFIG_OPTIONAL_DIRECTORY should not create - // dependencies. - ($config_collection[$dependency_name]->getSubdirectory() === InstallStorage::CONFIG_INSTALL_DIRECTORY)) { - // If the required item is assigned to one of the packages, add - // a dependency on that package. - $dependency_set = FALSE; - if ($dependency_package = $config_collection[$dependency_name]->getPackage()) { - $package_name = $bundle->getFullName($dependency_package); - // Package shouldn't be dependent on itself. - if ($package_name && array_key_exists($package_name, $packages) && $package_name != $package->getMachineName() && isset($module_list[$package_name])) { - $package->setDependencies($this->mergeUniqueItems($package->getDependencies(), [$package_name])); - $dependency_set = TRUE; - } - } - // Otherwise, if the dependency is provided by an existing - // feature, add a dependency on that feature. - if (!$dependency_set && $extension_name = $config_collection[$dependency_name]->getProvider()) { - // No extension should depend on the install profile. - $package_name = $bundle->getFullName($package->getMachineName()); - if ($extension_name != $package_name && $extension_name != $this->drupalGetProfile() && isset($module_list[$extension_name])) { - $package->setDependencies($this->mergeUniqueItems($package->getDependencies(), [$extension_name])); - } - } - } - } - } - } - } - // Unset the $package pass by reference. - unset($package); - } - - /** - * Gets the name of the currently active installation profile. - * - * @return string|null $profile - * The name of the installation profile or NULL if no installation profile is - * currently active. This is the case for example during the first steps of - * the installer or during unit tests. - */ - protected function drupalGetProfile() { - return drupal_get_profile(); - } - - /** - * Merges a set of new item into an array and sorts the result. - * - * Only unique values are retained. - * - * @param array $items - * An array of items. - * @param array $new_items - * An array of new items to be merged in. - * - * @return array - * The merged, sorted and unique items. - */ - protected function mergeUniqueItems($items, $new_items) { - $items = array_unique(array_merge($items, $new_items)); - sort($items); - return $items; - } - - /** - * Initializes and returns a package or profile array. - * - * @param string $machine_name - * Machine name of the package. - * @param string $name - * (optional) Human readable name of the package. - * @param string $description - * (optional) Description of the package. - * @param string $type - * (optional) Type of project. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * (optional) Bundle to use to add profile directories to the scan. - * @param \Drupal\Core\Extension\Extension $extension - * (optional) An Extension object. - * - * @return \Drupal\features\Package - * An array of package properties; see - * FeaturesManagerInterface::getPackages(). - */ - protected function getPackageObject($machine_name, $name = NULL, $description = '', $type = 'module', FeaturesBundleInterface $bundle = NULL, Extension $extension = NULL) { - if (!isset($bundle)) { - $bundle = $this->getAssigner()->getBundle(); - } - $package = new Package($machine_name, [ - 'name' => isset($name) ? $name : ucwords(str_replace(['_', '-'], ' ', $machine_name)), - 'description' => $description, - 'type' => $type, - 'core' => Drupal::CORE_COMPATIBILITY, - 'dependencies' => [], - 'themes' => [], - 'config' => [], - 'status' => FeaturesManagerInterface::STATUS_DEFAULT, - 'version' => '', - 'state' => FeaturesManagerInterface::STATE_DEFAULT, - 'files' => [], - 'bundle' => $bundle->isDefault() ? '' : $bundle->getMachineName(), - 'extension' => NULL, - 'info' => [], - 'configOrig' => [], - ]); - - // If no extension was passed in, look for a match. - if (!isset($extension)) { - $module_list = $this->getFeaturesModules($bundle); - $module_name = $package->getMachineName(); - if (isset($module_list[$module_name])) { - $extension = $module_list[$module_name]; - } - } - - // If there is an extension, set extension-specific properties. - if (isset($extension)) { - $info = $this->getExtensionInfo($extension); - $features_info = $this->getFeaturesInfo($extension); - $package->setExtension($extension); - $package->setInfo($info); - $package->setFeaturesInfo($features_info); - $package->setConfigOrig($this->listExtensionConfig($extension)); - $package->setStatus($this->extensionEnabled($extension) - ? FeaturesManagerInterface::STATUS_INSTALLED - : FeaturesManagerInterface::STATUS_UNINSTALLED); - $package->setVersion(isset($info['version']) ? $info['version'] : ''); - } - - return $package; - } - - /** - * Generates and adds .info.yml files to a package. - * - * @param \Drupal\features\Package $package - * The package. - */ - protected function addInfoFile(Package $package) { - $info = [ - 'name' => $package->getName(), - 'description' => $package->getDescription(), - 'type' => $package->getType(), - 'core' => $package->getCore(), - 'dependencies' => $package->getDependencies(), - 'themes' => $package->getThemes(), - 'version' => $package->getVersion(), - ]; - - $features_info = []; - - // Assign to a "package" named for the profile. - if ($package->getBundle()) { - $bundle = $this->getAssigner()->getBundle($package->getBundle()); - } - // Save the current bundle in the info file so the package - // can be reloaded later by the AssignmentPackages plugin. - if (isset($bundle) && !$bundle->isDefault()) { - $info['package'] = $bundle->getName(); - $features_info['bundle'] = $bundle->getMachineName(); - } - else { - unset($features_info['bundle']); - } - - if ($package->getConfig()) { - foreach (['excluded', 'required'] as $constraint) { - if (!empty($package->{'get' . $constraint}())) { - $features_info[$constraint] = $package->{'get' . $constraint}(); - } - else { - unset($features_info[$constraint]); - } - } - - if (empty($features_info)) { - $features_info = TRUE; - } - } - - // The name and description need to be cast as strings from the - // TranslatableMarkup objects returned by t() to avoid raising an - // InvalidDataTypeException on Yaml serialization. - foreach (['name', 'description'] as $key) { - $info[$key] = (string) $info[$key]; - } - - // Add profile-specific info data. - if ($info['type'] == 'profile') { - // Set the distribution name. - $info['distribution'] = [ - 'name' => $info['name'] - ]; - } - - $package->appendFile([ - 'filename' => $package->getMachineName() . '.info.yml', - 'subdirectory' => NULL, - // Filter to remove any empty keys, e.g., an empty themes array. - 'string' => Yaml::encode(array_filter($info)) - ], 'info'); - - $package->appendFile([ - 'filename' => $package->getMachineName() . '.features.yml', - 'subdirectory' => NULL, - 'string' => Yaml::encode($features_info) - ], 'features'); - } - - /** - * Generates and adds files to a given package or profile. - */ - protected function addPackageFiles(Package $package) { - $config_collection = $this->getConfigCollection(); - // Always add .info.yml and .features.yml files. - $this->addInfoFile($package); - // Only add files if there is at least one piece of configuration present. - if ($package->getConfig()) { - // Add configuration files. - foreach ($package->getConfig() as $name) { - $config = $config_collection[$name]; - - $package->appendFile([ - 'filename' => $config->getName() . '.yml', - 'subdirectory' => $config->getSubdirectory(), - 'string' => Yaml::encode($config->getData()) - ], $name); - } - } - } - - /** - * {@inheritdoc} - */ - public function mergeInfoArray(array $info1, array $info2, array $keys = []) { - // If keys were specified, use only those. - if (!empty($keys)) { - $info2 = array_intersect_key($info2, array_fill_keys($keys, NULL)); - } - - $info = NestedArray::mergeDeep($info1, $info2); - - // Process the dependencies and themes keys. - $keys = ['dependencies', 'themes']; - foreach ($keys as $key) { - if (isset($info[$key]) && is_array($info[$key])) { - // NestedArray::mergeDeep() may produce duplicate values. - $info[$key] = array_unique($info[$key]); - sort($info[$key]); - } - } - return $info; - } - - /** - * {@inheritdoc} - */ - public function listConfigTypes($bundles_only = FALSE) { - $definitions = []; - foreach ($this->entityTypeManager->getDefinitions() as $entity_type => $definition) { - if ($definition->isSubclassOf('Drupal\Core\Config\Entity\ConfigEntityInterface')) { - if (!$bundles_only || $definition->getBundleOf()) { - $definitions[$entity_type] = $definition; - } - } - } - $entity_types = array_map(function (EntityTypeInterface $definition) { - return $definition->getLabel(); - }, $definitions); - // Sort the entity types by label, then add the simple config to the top. - uasort($entity_types, 'strnatcasecmp'); - return $bundles_only ? $entity_types : [ - FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG => $this->t('Simple configuration'), - ] + $entity_types; - } - - /** - * {@inheritdoc} - */ - public function listExtensionConfig(Extension $extension) { - return $this->extensionStorages->listExtensionConfig($extension); - } - - /** - * {@inheritdoc} - */ - public function listExistingConfig($installed = FALSE, FeaturesBundleInterface $bundle = NULL) { - $config = []; - $existing = $this->getFeaturesModules($bundle, $installed); - foreach ($existing as $extension) { - // Keys are configuration item names and values are providing extension - // name. - $new_config = array_fill_keys($this->listExtensionConfig($extension), $extension->getName()); - $config = array_merge($config, $new_config); - } - return $config; - } - - /** - * {@inheritdoc} - */ - public function listConfigByType($config_type) { - // For a given entity type, load all entities. - if ($config_type && $config_type !== FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG) { - $entity_storage = $this->entityTypeManager->getStorage($config_type); - $names = []; - foreach ($entity_storage->loadMultiple() as $entity) { - $entity_id = $entity->id(); - $label = $entity->label() ?: $entity_id; - $names[$entity_id] = $label; - } - } - // Handle simple configuration. - else { - $definitions = []; - foreach ($this->entityTypeManager->getDefinitions() as $entity_type => $definition) { - if ($definition->isSubclassOf('Drupal\Core\Config\Entity\ConfigEntityInterface')) { - $definitions[$entity_type] = $definition; - } - } - // Gather the config entity prefixes. - $config_prefixes = array_map(function (EntityTypeInterface $definition) { - return $definition->getConfigPrefix() . '.'; - }, $definitions); - - // Find all config, and then filter our anything matching a config prefix. - $names = $this->configStorage->listAll(); - $names = array_combine($names, $names); - foreach ($names as $item_name) { - foreach ($config_prefixes as $config_prefix) { - if (strpos($item_name, $config_prefix) === 0) { - unset($names[$item_name]); - } - } - } - } - return $names; - } - - /** - * Creates a high performant version of the ConfigDependencyManager. - * - * @return \Drupal\features\FeaturesConfigDependencyManager - * A high performant version of the ConfigDependencyManager. - * - * @see \Drupal\Core\Config\Entity\ConfigDependencyManager - */ - protected function getFeaturesConfigDependencyManager() { - $dependency_manager = new FeaturesConfigDependencyManager(); - // Read all configuration using the factory. This ensures that multiple - // deletes during the same request benefit from the static cache. Using the - // factory also ensures configuration entity dependency discovery has no - // dependencies on the config entity classes. Assume data with UUID is a - // config entity. Only configuration entities can be depended on so we can - // ignore everything else. - $data = array_map(function(Drupal\Core\Config\ImmutableConfig $config) { - $data = $config->get(); - if (isset($data['uuid'])) { - return $data; - } - return FALSE; - }, $this->configFactory->loadMultiple($this->configStorage->listAll())); - $dependency_manager->setData(array_filter($data)); - return $dependency_manager; - } - - /** - * Loads configuration from storage into a property. - */ - protected function initConfigCollection($reset = FALSE) { - if ($reset || empty($this->configCollection)) { - $config_collection = []; - $config_types = $this->listConfigTypes(); - $dependency_manager = $this->getFeaturesConfigDependencyManager(); - // List configuration provided by installed features. - $existing_config = $this->listExistingConfig(NULL); - $existing_config_by_directory = $this->extensionStorages->listAllByDirectory(); - foreach (array_keys($config_types) as $config_type) { - $config = $this->listConfigByType($config_type); - foreach ($config as $item_name => $label) { - $name = $this->getFullName($config_type, $item_name); - $data = $this->configStorage->read($name); - - $config_collection[$name] = (new ConfigurationItem($name, $data, [ - 'shortName' => $item_name, - 'label' => $label, - 'type' => $config_type, - 'dependents' => array_keys($dependency_manager->getDependentEntities('config', $name)), - // Default to the install directory. - 'subdirectory' => isset($existing_config_by_directory[$name]) ? $existing_config_by_directory[$name] : InstallStorage::CONFIG_INSTALL_DIRECTORY, - 'package' => '', - 'providerExcluded' => NULL, - 'provider' => isset($existing_config[$name]) ? $existing_config[$name] : NULL, - 'packageExcluded' => [], - ])); - } - } - $this->setConfigCollection($config_collection); - } - } - - /** - * {@inheritdoc} - */ - public function prepareFiles(array $packages) { - foreach ($packages as $package) { - $this->addPackageFiles($package); - } - } - - /** - * {@inheritdoc} - */ - public function getExportInfo(Package $package, FeaturesBundleInterface $bundle = NULL) { - $full_name = isset($bundle) ? $bundle->getFullName($package->getMachineName()) : $package->getMachineName(); - - $path = ''; - - // Adjust export directory to be in profile. - if (isset($bundle) && $bundle->isProfile()) { - $path .= 'profiles/' . $bundle->getProfileName(); - } - - // If this is not the profile package, nest the directory. - if (!isset($bundle) || !$bundle->isProfilePackage($package->getMachineName())) { - $path .= empty($path) ? 'modules' : '/modules'; - $export_settings = $this->getExportSettings(); - if (!empty($export_settings['folder'])) { - $path .= '/' . $export_settings['folder']; - } - } - - // Use the same path of a package to override it. - if ($extension = $package->getExtension()) { - $extension_path = $extension->getPath(); - $path = dirname($extension_path); - } - - return [$full_name, $path]; - } - - /** - * {@inheritdoc} - */ - public function detectOverrides(Package $feature, $include_new = FALSE) { - /** @var \Drupal\config_update\ConfigDiffInterface $config_diff */ - $config_diff = \Drupal::service('config_update.config_diff'); - - $different = []; - foreach ($feature->getConfig() as $name) { - $active = $this->configStorage->read($name); - $extension = $this->extensionStorages->read($name); - $extension = !empty($extension) ? $extension : []; - if (($include_new || !empty($extension)) && !$config_diff->same($extension, $active)) { - $different[] = $name; - } - } - - if (!empty($different)) { - $feature->setState(FeaturesManagerInterface::STATE_OVERRIDDEN); - } - return $different; - } - - /** - * {@inheritdoc} - */ - public function detectNew(Package $feature) { - $result = []; - foreach ($feature->getConfig() as $name) { - $extension = $this->extensionStorages->read($name); - if (empty($extension)) { - $result[] = $name; - } - } - return $result; - } - - /** - * {@inheritdoc} - */ - public function detectMissing(Package $feature) { - $config = $this->getConfigCollection(); - $result = []; - foreach ($feature->getConfigOrig() as $name) { - if (!isset($config[$name])) { - $result[] = $name; - } - } - return $result; - } - - /** - * {@inheritdoc} - */ - public function reorderMissing(array $missing) { - $list = []; - $result = []; - foreach ($missing as $full_name) { - $this->addConfigList($full_name, $list); - } - foreach ($list as $full_name) { - if (in_array($full_name, $missing)) { - $result[] = $full_name; - } - } - return $result; - } - - protected function addConfigList($full_name, &$list) { - $index = array_search($full_name, $list); - if ($index !== FALSE) { - unset($list[$index]); - } - array_unshift($list, $full_name); - $value = $this->extensionStorages->read($full_name); - if (isset($value['dependencies']['config'])) { - foreach ($value['dependencies']['config'] as $config_name) { - $this->addConfigList($config_name, $list); - } - } - } - - /** - * {@inheritdoc} - */ - public function statusLabel($status) { - switch ($status) { - case FeaturesManagerInterface::STATUS_NO_EXPORT: - return $this->t('Not exported'); - - case FeaturesManagerInterface::STATUS_UNINSTALLED: - return $this->t('Uninstalled'); - - case FeaturesManagerInterface::STATUS_INSTALLED: - return $this->t('Installed'); - } - } - - /** - * {@inheritdoc} - */ - public function stateLabel($state) { - switch ($state) { - case FeaturesManagerInterface::STATE_DEFAULT: - return $this->t('Default'); - - case FeaturesManagerInterface::STATE_OVERRIDDEN: - return $this->t('Changed'); - } - } - - /** - * {@inheritdoc} - */ - public function getFeaturesInfo(Extension $extension) { - $module_name = $extension->getName(); - if (isset($this->featureInfoCache[$module_name])) { - return $this->featureInfoCache[$module_name]; - } - $features_info = NULL; - $filename = $this->root . '/' . $extension->getPath() . '/' . $module_name . '.features.yml'; - if (file_exists($filename)) { - $features_info = Yaml::decode(file_get_contents($filename)); - } - $this->featureInfoCache[$module_name] = $features_info; - return $features_info; - } - - /** - * {@inheritdoc} - */ - public function createConfiguration(array $config_to_create) { - $existing_config = $this->getConfigCollection(); - - // If config data is not specified, load it from the extension storage. - foreach ($config_to_create as $name => $item) { - if (empty($item)) { - $config = $this->configReverter->getFromExtension('', $name); - // For testing purposes, if it couldn't load from a module, get config - // from the cached Config Collection - if (empty($config) && isset($existing_config[$name])) { - $config = $existing_config[$name]->getData(); - } - $config_to_create[$name] = $config; - } - } - - // Determine which config is new vs existing. - $existing = array_intersect_key($config_to_create, $existing_config); - $new = array_diff_key($config_to_create, $existing); - - // The FeaturesConfigInstaller exposes the normally protected createConfiguration - // function from Core ConfigInstaller than handles the creation of new - // config or the changing of existing config. - /** @var \Drupal\features\FeaturesConfigInstaller $config_installer */ - $config_installer = \Drupal::service('features.config.installer'); - $config_installer->createConfiguration(StorageInterface::DEFAULT_COLLECTION, $config_to_create); - - // Collect results for new and updated config. - $new_config = $this->getConfigCollection(TRUE); - $result['updated'] = array_intersect_key($new_config, $existing); - $result['new'] = array_intersect_key($new_config, $new); - return $result; - } - - /** - * {@inheritdoc} - */ - public function import($modules, $any = FALSE) { - $result = []; - foreach ($modules as $module_name) { - $package = $this->loadPackage($module_name, $any); - $components = isset($package) ? $package->getConfigOrig() : []; - if (empty($components)) { - continue; - } - $result[$module_name] = $this->createConfiguration(array_fill_keys($components, [])); - } - return $result; - } - -} diff --git a/web/modules/features/src/FeaturesManagerInterface.php b/web/modules/features/src/FeaturesManagerInterface.php deleted file mode 100644 index 2f47e5248b2e742034432756de175183f328a1f7..0000000000000000000000000000000000000000 --- a/web/modules/features/src/FeaturesManagerInterface.php +++ /dev/null @@ -1,647 +0,0 @@ -<?php - -namespace Drupal\features; - -use Drupal\Core\Extension\Extension; - -/** - * Provides an interface for the FeaturesManager. - */ -interface FeaturesManagerInterface { - - /** - * Simple configuration. - * - * Core uses system.simple, but since we're using this key in configuration - * arrays we can't include a period. - * - * @see https://www.drupal.org/node/2297311 - */ - const SYSTEM_SIMPLE_CONFIG = 'system_simple'; - - /** - * Constants for package/module status. - */ - const STATUS_NO_EXPORT = 0; - const STATUS_UNINSTALLED = 1; - const STATUS_INSTALLED = 2; - const STATUS_DEFAULT = self::STATUS_NO_EXPORT; - - /** - * Constants for package/module state. - */ - const STATE_DEFAULT = 0; - const STATE_OVERRIDDEN = 1; - - /** - * Set the app.root. - * - * Should only be used by tests. - * @param string $root - */ - public function setRoot($root); - - /** - * Returns the active config store. - * - * @return \Drupal\Core\Config\StorageInterface - */ - public function getActiveStorage(); - - /** - * Returns a set of config storages. - * - * This method is used for support of multiple extension configuration - * directories, including the core-provided install and optional directories. - * - * @return \Drupal\Core\Config\StorageInterface[] - */ - public function getExtensionStorages(); - - /** - * Resets packages and configuration assignment. - */ - public function reset(); - - /** - * Gets an array of site configuration. - * - * @param bool $reset - * If TRUE, recalculate the configuration (undo all assignment methods). - * - * @return \Drupal\features\ConfigurationItem[] - * An array of items, each with the following keys: - * - 'name': prefixed configuration item name. - * - 'name_short': configuration item name without prefix. - * - 'label': human readable name of configuration item. - * - 'type': type of configuration. - * - 'data': the contents of the configuration item in exported format. - * - 'dependents': array of names of dependent configuration items. - * - 'subdirectory': feature subdirectory to export item to. - * - 'package': machine name of a package the configuration is assigned to. - * - 'extension_provided': whether the configuration is provided by an - * extension. - * - 'package_excluded': array of package names that this item should be - * excluded from. - */ - public function getConfigCollection($reset = FALSE); - - /** - * Sets an array of site configuration. - * - * @param \Drupal\features\ConfigurationItem[] $config_collection - * An array of items. - */ - public function setConfigCollection(array $config_collection); - - /** - * Gets an array of packages. - * - * @return \Drupal\features\Package[] - * An array of items, each with the following keys: - * - 'machine_name': machine name of the package such as 'example_article'. - * 'article'. - * - 'name': human readable name of the package such as 'Example Article'. - * - 'description': description of the package. - * - 'type': type of Drupal project ('module'). - * - 'core': Drupal core compatibility ('8.x'). - * - 'dependencies': array of module dependencies. - * - 'themes': array of names of themes to install. - * - 'config': array of names of configuration items. - * - 'status': status of the package. Valid values are: - * - FeaturesManagerInterface::STATUS_NO_EXPORT - * - FeaturesManagerInterface::STATUS_INSTALLED - * - FeaturesManagerInterface::STATUS_UNINSTALLED - * - 'version': version of the extension. - * - 'state': state of the extension. Valid values are: - * - FeaturesManagerInterface::STATE_DEFAULT - * - FeaturesManagerInterface::STATE_OVERRIDDEN - * - 'directory': the extension's directory. - * - 'files' array of files, each having the following keys: - * - 'filename': the name of the file. - * - 'subdirectory': any subdirectory of the file within the extension - * directory. - * - 'string': the contents of the file. - * - 'bundle': name of the features bundle this package belongs to. - * - 'extension': \Drupal\Core\Extension\Extension object. - * - 'info': the original info array from an existing package. - * - 'config_info': the original config of the module. - * - * @see \Drupal\features\FeaturesManagerInterface::setPackages() - */ - public function getPackages(); - - /** - * Sets an array of packages. - * - * @param \Drupal\features\Package[] $packages - * An array of packages. - */ - public function setPackages(array $packages); - - /** - * Gets a specific package. - * - * @param string $machine_name - * Full machine name of package. - * - * @return \Drupal\features\Package - * Package data. - * - * @see \Drupal\features\FeaturesManagerInterface::getPackages() - */ - public function getPackage($machine_name); - - /** - * Gets a specific package. - * Similar to getPackage but will also match package FullName - * - * @param string $machine_name - * Full machine name of package. - * - * @return \Drupal\features\Package - * Package data. - * - * @see \Drupal\features\FeaturesManagerInterface::getPackages() - */ - public function findPackage($machine_name); - - /** - * Updates a package definition in the package list. - * - * NOTE: This does not "export" the package; it simply updates the internal - * data. - * - * @param \Drupal\features\Package $package - * The package. - */ - public function setPackage(Package $package); - - /** - * Load a specific package. - * - * Similar to getPackage but can also load modules that are not Features. - * - * @param string $module_name - * Full machine name of module. - * @param bool $any - * If TRUE then check for any module, not just a Features module. - * - * @return \Drupal\features\Package - * Package data. - */ - public function loadPackage($module_name, $any = FALSE); - - /** - * Filters the supplied package list by the given namespace. - * - * @param \Drupal\features\Package[] $packages - * An array of packages. - * @param string $namespace - * The namespace to use. - * @param bool $only_exported - * If true, only filter out packages that are exported - * - * @return \Drupal\features\Package[] - * An array of packages. - */ - public function filterPackages(array $packages, $namespace = '', $only_exported = FALSE); - - /** - * Gets a reference to a package assigner. - * - * @return \Drupal\features\FeaturesAssignerInterface - * The package assigner. - */ - public function getAssigner(); - - /** - * Injects the package assigner. - * - * @param \Drupal\features\FeaturesAssignerInterface $assigner - * The package assigner. - */ - public function setAssigner(FeaturesAssignerInterface $assigner); - - /** - * Gets a reference to a package generator. - * - * @return \Drupal\features\FeaturesGeneratorInterface - * The package generator. - */ - public function getGenerator(); - - /** - * Injects the package generator. - * - * @param \Drupal\features\FeaturesGeneratorInterface $generator - * The package generator. - */ - public function setGenerator(FeaturesGeneratorInterface $generator); - - /** - * Returns the current export settings. - * - * @return array - * An array with the following keys: - * - 'folder' - subdirectory to export packages to. - * - 'namespace' - module namespace being exported. - */ - public function getExportSettings(); - - /** - * Returns the current general features settings. - * - * @return \Drupal\Core\Config\Config - * A config object containing settings. - */ - public function getSettings(); - - /** - * Returns the contents of an extensions info.yml file. - * - * @param \Drupal\Core\Extension\Extension $extension - * An Extension object. - * - * @return array - * An array representing data in an info.yml file. - */ - public function getExtensionInfo(Extension $extension); - - /** - * Determine if extension is enabled - * - * @param \Drupal\Core\Extension\Extension $extension - * @return bool - */ - public function extensionEnabled(Extension $extension); - - /** - * Initializes a configuration package. - * - * @param string $machine_name - * Machine name of the package. - * @param string $name - * (optional) Human readable name of the package. - * @param string $description - * (optional) Description of the package. - * @param string $type - * (optional) Type of project. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * (optional) Bundle to use to add profile directories to the scan. - * @param \Drupal\Core\Extension\Extension $extension - * (optional) An Extension object. - * @return \Drupal\features\Package - * The created package array. - */ - public function initPackage($machine_name, $name = NULL, $description = '', $type = 'module', FeaturesBundleInterface $bundle = NULL, Extension $extension = NULL); - - /** - * Initializes a configuration package using module info data. - * - * @param \Drupal\Core\Extension\Extension $extension - * An Extension object. - * - * @return \Drupal\features\Package - * The created package array. - */ - public function initPackageFromExtension(Extension $extension); - - /** - * Lists directories in which packages are present. - * - * This method scans to find package modules whether or not they are - * currently active (installed). As well as the directories that are - * usually scanned for modules and profiles, a profile directory for the - * current profile is scanned if it exists. For example, if the value - * for $bundle->getProfileName() is 'example', a - * directory profiles/example will be scanned if it exists. Therefore, when - * regenerating package modules, existing ones from a prior export will be - * recognized. - * - * @param string[] $machine_names - * Package machine names to return directories for. If omitted, return all - * directories. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * Optional bundle to use to add profile directories to the scan. - * - * @return array - * Array of package directories keyed by package machine name. - */ - public function listPackageDirectories(array $machine_names = [], FeaturesBundleInterface $bundle = NULL); - - /** - * Assigns a set of configuration items to a given package or profile. - * - * @param string $package_name - * Machine name of a package or the profile. - * @param string[] $item_names - * Configuration item names. - * @param bool $force - * (optional) If TRUE, assign config regardless of restrictions such as it - * being already assigned to a package. - * - * @throws Exception - */ - public function assignConfigPackage($package_name, array $item_names, $force = FALSE); - - /** - * Assigns configuration items with names matching given strings to given - * packages. - * - * @param array $patterns - * Array with string patterns as keys and package machine names as values. - */ - public function assignConfigByPattern(array $patterns); - - /** - * For given configuration items, assigns any dependent configuration to the - * same package. - * - * @param string[] $item_names - * Configuration item names. - * @param string $package - * Short machine name of package to assign dependent config to. If NULL, - * use the current package of the parent config items. - */ - public function assignConfigDependents(array $item_names = NULL, $package = NULL); - - /** - * Adds the optional bundle prefix to package machine names. - * - * @param \Drupal\features\FeaturesBundleInterface $bundle - * The bundle used for the generation. - * @param string[] &$package_names - * (optional) Array of package names, passed by reference. - */ - public function setPackageBundleNames(FeaturesBundleInterface $bundle, array &$package_names = []); - - /** - * Assigns dependencies from config items into the package. - * - * @param \Drupal\features\Package[] $packages - * An array of packages. NULL for all packages - */ - public function assignPackageDependencies(Package $package = NULL); - - /** - * Assigns dependencies between packages based on configuration dependencies. - * - * \Drupal\features\FeaturesBundleInterface::setPackageBundleNames() must be - * called prior to calling this method. - * - * @param \Drupal\features\FeaturesBundleInterface $bundle - * A features bundle. - * @param \Drupal\features\Package[] $packages - * An array of packages. - */ - public function assignInterPackageDependencies(FeaturesBundleInterface $bundle, array &$packages); - - /** - * Merges two info arrays and processes the resulting array. - * - * Ensures values are unique and sorted. - * - * @param array $info1 - * The first array. - * @param array $info2 - * The second array. - * @param string[] $keys - * Keys to merge. If not specified, all keys present will be merged. - * - * @return array - * An array with the merged and processed results. - * - * @fixme Should this be moved to the package object or a related helper? - */ - public function mergeInfoArray(array $info1, array $info2, array $keys = []); - - /** - * Lists the types of configuration available on the site. - * - * @param boolean $bundles_only - * Whether to list only configuration types that provide bundles. - * - * @return array - * An array with machine name keys and human readable values. - */ - public function listConfigTypes($bundles_only = FALSE); - - /** - * Lists stored configuration for a given configuration type. - * - * @param string $config_type - * The type of configuration. - */ - public function listConfigByType($config_type); - - /** - * Returns a list of all modules present on the site's file system. - * - * @return Drupal\Core\Extension\Extension[] - * An array of extension objects. - */ - public function getAllModules(); - - /** - * Returns a list of Features modules regardless of if they are installed. - * - * @param \Drupal\features\FeaturesBundleInterface $bundle - * Optional bundle to filter module list. - * If given, only modules matching the bundle namespace will be returned. - * If the bundle uses a profile, only modules in the profile will be - * returned. - * @param bool $installed - * List only installed modules. - * - * @return Drupal\Core\Extension\Extension[] - * An array of extension objects. - */ - public function getFeaturesModules(FeaturesBundleInterface $bundle = NULL, $installed = FALSE); - - /** - * Lists names of configuration objects provided by a given extension. - * - * @param \Drupal\Core\Extension\Extension $extension - * An Extension object. - * - * @return array - * An array of configuration object names. - */ - public function listExtensionConfig(Extension $extension); - - /** - * Lists names of configuration items provided by existing Features modules. - * - * @param bool $installed - * List only installed Features. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * (optional) Bundle to find existing configuration for. - * - * @return array - * An array with config names as keys and providing module names as values. - */ - public function listExistingConfig($installed = FALSE, FeaturesBundleInterface $bundle = NULL); - - /** - * Iterates through packages and prepares file names and contents. - * - * @param array $packages - * An array of packages. - */ - public function prepareFiles(array $packages); - - /** - * Returns the full name of a config item. - * - * @param string $type - * The config type, or '' to indicate $name is already prefixed. - * @param string $name - * The config name, without prefix. - * - * @return string - * The config item's full name. - */ - public function getFullName($type, $name); - - /** - * Returns the short name and type of a full config name. - * - * @param string $fullname - * The full configuration name - * @return array - * 'type' => string the config type - * 'name_short' => string the short config name, without prefix. - */ - public function getConfigType($fullname); - - /** - * Returns the full machine name and directory for exporting a package. - * - * @param \Drupal\features\Package $package - * The package. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * Optional bundle being used for export. - * - * @return array - * An array with the full name as the first item and directory as second - * item. - */ - public function getExportInfo(Package $package, FeaturesBundleInterface $bundle = NULL); - - /** - * Determines if the module is a Features package, optionally testing by - * bundle. - * - * @param \Drupal\Core\Extension\Extension $module - * An extension object. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * (optional) Bundle to filter by. - * - * @return bool - * TRUE if the given module is a Features package of the given bundle (if any). - */ - public function isFeatureModule(Extension $module, FeaturesBundleInterface $bundle); - - /** - * Determines which config is overridden in a package. - * - * @param \Drupal\features\Package $feature - * The package array. - * The 'state' property is updated if overrides are detected. - * @param bool $include_new - * If set, include newly detected config not yet exported. - * - * @result array $different - * The array of config items that are overridden. - * - * @see \Drupal\features\FeaturesManagerInterface::detectNew() - */ - public function detectOverrides(Package $feature, $include_new = FALSE); - - /** - * Determines which config has not been exported to the feature. - * - * Typically added as an auto-detected dependency. - * - * @param \Drupal\features\Package $feature - * The package array. - * - * @return array - * The array of config items that are overridden. - */ - public function detectNew(Package $feature); - - /** - * Determines which config is exported in the feature but not in the active. - * - * @param \Drupal\features\Package $feature - * The package array. - * - * @return array - * The array of config items that are missing from active store. - */ - public function detectMissing(Package $feature); - - /** - * Sort the Missing config into order by dependencies. - * @param array $missing config items - * @return array of config items in dependency order - */ - public function reorderMissing(array $missing); - - /** - * Helper function that returns a translatable label for the different status - * constants. - * - * @param int $status - * A status constant. - * - * @return string - * A translatable label. - */ - public function statusLabel($status); - - /** - * Helper function that returns a translatable label for the different state - * constants. - * - * @param int $state - * A state constant. - * - * @return string - * A translatable label. - */ - public function stateLabel($state); - - /** - * @param \Drupal\Core\Extension\Extension $extension - * - * @return array - */ - public function getFeaturesInfo(Extension $extension); - - /** - * Creates configuration in a collection based on the provided list. - * - * @param array $config_to_create - * An array of configuration data to create, keyed by name. - * @return array of config imported - * 'new': list of new config created keyed by name. - * 'updated': list of updated config keyed by name. - */ - public function createConfiguration(array $config_to_create); - - /** - * @param array $modules - * An array of module names to import (revert) - * @param bool $any - * Set to TRUE to import config from non-Features modules - * @return array of config imported - * keyed by name of module, then: - * 'new': list of new config created keyed by name. - * 'updated': list of updated config keyed by name. - */ - public function import($modules, $any = FALSE); - -} diff --git a/web/modules/features/src/Package.php b/web/modules/features/src/Package.php deleted file mode 100644 index c7f2872a2909d4c600a7a09ae690c61f24815db5..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Package.php +++ /dev/null @@ -1,562 +0,0 @@ -<?php - -namespace Drupal\features; - -/** - * Defines a value object for storing package related data. - * - * A package contains of a name, version number, containing config etc. - */ -class Package { - - /** - * @var string - */ - protected $machineName = ''; - - /** - * @var string - */ - protected $name = ''; - - /** - * @var string - */ - protected $description = ''; - - /** - * @todo This could be fetched from the extension object. - * - * @var string - */ - protected $version = ''; - - /** - * @var string - */ - protected $core = '8.x'; - - /** - * @todo This could be fetched from the extension object. - * - * @var string - */ - protected $type = 'module'; - - /** - * @var string[] - */ - protected $themes = []; - - /** - * @var string - */ - protected $bundle; - - /** - * @var string[] - */ - protected $excluded = []; - - /** - * @var string[]|bool - */ - protected $required = false; - - /** - * @var array - */ - protected $info = []; - - /** - * @var string[] - */ - protected $dependencies = []; - - /** - * @todo This could be fetched from the extension object. - * - * @var int - */ - protected $status; - - /** - * @var int - */ - protected $state; - - /** - * @todo This could be fetched from the extension object. - * - * @var string - */ - protected $directory; - - /** - * @var string[] - */ - protected $files; - - /** - * @var \Drupal\Core\Extension\Extension - */ - protected $extension; - - /** - * @var string[] - */ - protected $config = []; - - /** - * @var string[] - */ - protected $configOrig = []; - - /** - * Creates a new Package instance. - * - * @param string $machine_name - * The machine name. - * @param array $additional_properties - * (optional) Additional properties of the object. - */ - public function __construct($machine_name, array $additional_properties = []) { - $this->machineName = $machine_name; - - $properties = get_object_vars($this); - foreach ($additional_properties as $property => $value) { - if (!array_key_exists($property, $properties)) { - throw new \InvalidArgumentException('Invalid property: ' . $property); - } - $this->{$property} = $value; - } - } - - /** - * @return mixed - */ - public function getMachineName() { - return $this->machineName; - } - - /** - * Return TRUE if the machine_name already has the bundle prefix. - * - * @param string $machine_name - * @param string $bundle_name - * @return bool - */ - protected function inBundle($machine_name, $bundle_name) { - return strpos($machine_name, $bundle_name . '_') === 0; - } - - /** - * Return the full name of the package by prefixing it with bundle as needed - * - * NOTE: When possible, use the Bundle::getFullName method since it can - * better handle cases where a bundle is a profile. - * - * @return string - */ - public function getFullName() { - if (empty($this->bundle) || $this->inBundle($this->machineName, $this->bundle)) { - return $this->machineName; - } - else { - return $this->bundle . '_' . $this->machineName; - } - } - - /** - * @return string - */ - public function getName() { - return $this->name; - } - - /** - * @return string - */ - public function getDescription() { - return $this->description; - } - - /** - * @return string - */ - public function getVersion() { - return $this->version; - } - - /** - * @return int - */ - public function getStatus() { - return $this->status; - } - - /** - * @return string[] - */ - public function getConfig() { - return $this->config; - } - - /** - * Append a new filename. - * - * @param string $config - * - * @return $this - */ - public function appendConfig($config) { - $this->config[] = $config; - $this->config = array_unique($this->config); - return $this; - } - - public function removeConfig($name) { - $this->config = array_diff($this->config, [$name]); - return $this; - } - - /** - * @return string - */ - public function getBundle() { - return $this->bundle; - } - - /** - * @return string[] - */ - public function getExcluded() { - return $this->excluded; - } - - /** - * @return string[]|bool - */ - public function getRequired() { - return $this->required; - } - - /** - * @return bool - */ - public function getRequiredAll() { - // Mark all as required if the package is not yet exported. - if ($this->getStatus() === FeaturesManagerInterface::STATUS_NO_EXPORT) { - return TRUE; - } - - // Mark all as required if required is TRUE. - if (is_bool($this->required)) { - return $this->required; - } - - // Mark all as required if required contains all the exported config. - $config_orig = $this->getConfigOrig(); - $diff = array_diff($config_orig, $this->required); - return empty($diff); - } - - /** - * @return string[] - */ - public function getConfigOrig() { - return $this->configOrig; - } - - /** - * @return string - */ - public function getCore() { - return $this->core; - } - - /** - * @return string - */ - public function getType() { - return $this->type; - } - - /** - * @return \string[] - */ - public function getThemes() { - return $this->themes; - } - - /** - * @return array - */ - public function getInfo() { - return $this->info; - } - - /** - * @return mixed - */ - public function getState() { - return $this->state; - } - - /** - * @return string - */ - public function getDirectory() { - return $this->directory; - } - - /** - * @return mixed - */ - public function getFiles() { - return $this->files; - } - - /** - * @return \Drupal\Core\Extension\Extension - */ - public function getExtension() { - return $this->extension; - } - - public function getDependencies() { - return $this->dependencies; - } - - public function removeDependency($name) { - $this->dependencies = array_diff($this->dependencies, [$name]); - return $this; - } - - public function getDependencyInfo() { - return isset($this->info['dependencies']) ? $this->info['dependencies'] : []; - } - - /** - * Returns the features info. - * - * @return array - */ - public function getFeaturesInfo() { - $info = []; - if (!empty($this->bundle)) { - $info['bundle'] = $this->bundle; - } - if (!empty($this->excluded)) { - $info['excluded'] = $this->excluded; - } - if ($this->required !== FALSE) { - $info['required'] = $this->required; - } - return $info; - } - - /** - * Sets a new machine name. - * - * @param string $machine_name - * The machine name - * - * @return $this - */ - public function setMachineName($machine_name) { - $this->machineName = $machine_name; - return $this; - } - - /** - * @param string $name - * - * @return $this - */ - public function setName($name) { - $this->name = $name; - return $this; - } - - /** - * @param string $description - * - * @return $this - */ - public function setDescription($description) { - $this->description = $description; - return $this; - } - - /** - * @param string $version - * - * @return $this - */ - public function setVersion($version) { - $this->version = $version; - return $this; - } - - /** - * @param string $bundle - * - * @return $this - */ - public function setBundle($bundle) { - $this->bundle = $bundle; - return $this; - } - - /** - * @param array $info - * - * @return $this - */ - public function setInfo($info) { - $this->info = $info; - return $this; - } - - /** - * @param \string[] $features_info - * - * @return $this - */ - public function setFeaturesInfo($features_info) { - if (isset($features_info['bundle'])) { - $this->setBundle($features_info['bundle']); - } - $this->setRequired(isset($features_info['required']) ? $features_info['required'] : false); - $this->setExcluded(isset($features_info['excluded']) ? $features_info['excluded'] : []); - - return $this; - } - - /** - * @param \string[] $dependencies - * - * @return $this - */ - public function setDependencies($dependencies) { - $this->dependencies = $dependencies; - return $this; - } - - /** - * @param string $dependency - * - * return $this - */ - public function appendDependency($dependency) { - $this->dependencies[] = $dependency; - return $this; - } - - /** - * @param int $status - * - * @return $this - */ - public function setStatus($status) { - $this->status = $status; - return $this; - } - - /** - * @param \string[] $config - * - * @return $this - */ - public function setConfig($config) { - $this->config = $config; - return $this; - } - - /** - * @param bool $excluded - */ - public function setExcluded($excluded) { - $this->excluded = $excluded; - } - - /** - * @param bool $required - */ - public function setRequired($required) { - $this->required = $required; - } - - /** - * @param string $core - */ - public function setCore($core) { - $this->core = $core; - } - - /** - * @param string $type - */ - public function setType($type) { - $this->type = $type; - } - - /** - * @param \string[] $themes - */ - public function setThemes($themes) { - $this->themes = $themes; - } - - /** - * @param int $state - */ - public function setState($state) { - $this->state = $state; - } - - /** - * @param string $directory - */ - public function setDirectory($directory) { - $this->directory = $directory; - } - - /** - * @param \string[] $files - */ - public function setFiles($files) { - $this->files = $files; - } - - /** - * @param array $file_array - * - * @return $this - */ - public function appendFile(array $file_array, $key = NULL) { - if (!isset($key)) { - $this->files[] = $file_array; - } - else { - $this->files[$key] = $file_array; - } - return $this; - } - - /** - * @param \Drupal\Core\Extension\Extension $extension - */ - public function setExtension($extension) { - $this->extension = $extension; - } - - /** - * @param \string[] $configOrig - */ - public function setConfigOrig($configOrig) { - $this->configOrig = $configOrig; - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentAlter.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentAlter.php deleted file mode 100644 index 91cbf12f2d64e67c0a09b6baa59346735dfb14ef..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentAlter.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; -use Drupal\features\FeaturesManagerInterface; - -/** - * Class for excluding configuration from packages. - * - * @Plugin( - * id = "alter", - * weight = 0, - * name = @Translation("Alter"), - * description = @Translation("Alter configuration items before they are exported. Altering includes options such as removing permissions from roles."), - * config_route_name = "features.assignment_alter", - * default_settings = { - * "core" = TRUE, - * "uuid" = TRUE, - * "user_permissions" = TRUE, - * } - * ) - */ -class FeaturesAssignmentAlter extends FeaturesAssignmentMethodBase { - - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $current_bundle = $this->assigner->getBundle(); - $settings = $current_bundle->getAssignmentSettings($this->getPluginId()); - - // Alter configuration items. - if ($settings['core'] || $settings['uuid'] || $settings['user_permissions']) { - $config_collection = $this->featuresManager->getConfigCollection(); - foreach ($config_collection as &$config) { - $data = $config->getData(); - if ($settings['core']) { - unset($data['_core']); - } - // Unset UUID for configuration entities. - if ($settings['uuid'] && $config->getType() !== FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG) { - unset($data['uuid']); - } - // Unset permissions for user roles. Doing so facilitates packaging - // roles that may have permissions that relate to multiple packages. - if ($settings['user_permissions'] && $config->getType() == 'user_role') { - // Unset and not empty permissions data to prevent loss of configured - // role permissions in the event of a feature revert. - unset($data['permissions']); - } - $config->setData($data); - } - // Clean up the $config pass by reference. - unset($config); - - // Register the updated data. - $this->featuresManager->setConfigCollection($config_collection); - } - - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentBaseType.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentBaseType.php deleted file mode 100644 index a8f83cb6409259fe36cd3958d259be7ff61784fa..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentBaseType.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\Component\Utility\Unicode; -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for assigning configuration to packages based on entity types. - * - * @Plugin( - * id = "base", - * weight = -2, - * name = @Translation("Base type"), - * description = @Translation("Use designated types of configuration as the base for configuration package modules. For example, if content types are selected as a base type, a package will be generated for each content type and will include all configuration dependent on that content type."), - * config_route_name = "features.assignment_base", - * default_settings = { - * "types" = { - * "config" = {}, - * "content" = {} - * } - * } - * ) - */ -class FeaturesAssignmentBaseType extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $current_bundle = $this->assigner->getBundle(); - $settings = $current_bundle->getAssignmentSettings($this->getPluginId()); - $config_base_types = $settings['types']['config']; - - $config_types = $this->featuresManager->listConfigTypes(); - $config_collection = $this->featuresManager->getConfigCollection(); - - foreach ($config_collection as $item_name => $item) { - if (in_array($item->getType(), $config_base_types)) { - if (is_null($this->featuresManager->findPackage($item->getShortName())) && !$item->getPackage()) { - $description = $this->t('Provides @label @type and related configuration.', ['@label' => $item->getLabel(), '@type' => Unicode::strtolower($config_types[$item->getType()])]); - if (isset($item->getData()['description'])) { - $description .= ' ' . $item->getData()['description']; - } - $this->featuresManager->initPackage($item->getShortName(), $item->getLabel(), $description, 'module', $current_bundle); - // Update list with the package we just added. - try { - $this->featuresManager->assignConfigPackage($item->getShortName(), [$item_name]); - } - catch (\Exception $exception) { - \Drupal::logger('features')->error($exception->getMessage()); - } - } - } - } - - $entity_types = $this->entityTypeManager->getDefinitions(); - - $content_base_types = $settings['types']['content']; - foreach ($content_base_types as $entity_type_id) { - if (!isset($packages[$entity_type_id]) && isset($entity_types[$entity_type_id])) { - $label = $entity_types[$entity_type_id]->getLabel(); - $description = $this->t('Provide @label related configuration.', ['@label' => $label]); - $this->featuresManager->initPackage($entity_type_id, $label, $description, 'module', $current_bundle); - } - } - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentCoreType.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentCoreType.php deleted file mode 100644 index d221b31a8f88522b42a9ed3a34222371b0c14268..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentCoreType.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for assigning configuration to a core package based on entity types. - * - * @Plugin( - * id = "core", - * weight = 5, - * name = @Translation("Core type"), - * description = @Translation("Assign designated types of configuration to a core configuration package module. For example, if image styles are selected as a core type, a core package will be generated and image styles will be assigned to it."), - * config_route_name = "features.assignment_core", - * default_settings = { - * "types" = { - * "config" = {}, - * } - * } - * ) - */ -class FeaturesAssignmentCoreType extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $current_bundle = $this->assigner->getBundle(); - $machine_name = 'core'; - $name = $this->t('Core'); - $description = $this->t('Provides core components required by other features.'); - $package = $this->featuresManager->initPackage($machine_name, $name, $description, 'module', $current_bundle); - $this->assignPackageByConfigTypes($package->getMachineName(), $force); - } - - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentDependency.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentDependency.php deleted file mode 100644 index e8b596e68568f795e6dd99989a1cb2978957f2dd..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentDependency.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for assigning configuration to packages based on configuration - * dependencies. - * - * @Plugin( - * id = "dependency", - * weight = 15, - * name = @Translation("Dependency"), - * description = @Translation("Add to packages configuration dependent on items already in that package."), - * ) - */ -class FeaturesAssignmentDependency extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $this->featuresManager->assignConfigDependents(); - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentExclude.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentExclude.php deleted file mode 100644 index 75fecb92ddf1fbf7a7fabbbe0b8a7509c7005512..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentExclude.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for excluding configuration from packages. - * - * @Plugin( - * id = "exclude", - * weight = -5, - * name = @Translation("Exclude"), - * description = @Translation("Exclude configuration items from packaging by various methods including by configuration type. When configuration is excluded, it won't be automatically reassigned to other packages."), - * config_route_name = "features.assignment_exclude", - * default_settings = { - * "curated" = FALSE, - * "module" = { - * "installed" = FALSE, - * "profile" = FALSE, - * "namespace" = FALSE, - * "namespace_any" = FALSE, - * }, - * "types" = { "config" = {} } - * } - * ) - */ -class FeaturesAssignmentExclude extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $current_bundle = $this->assigner->getBundle(); - $settings = $current_bundle->getAssignmentSettings($this->getPluginId()); - - $config_collection = $this->featuresManager->getConfigCollection(); - - // Exclude by configuration type. - $exclude_types = $settings['types']['config']; - if (!empty($exclude_types)) { - foreach ($config_collection as $item_name => $item) { - // Don't exclude already-assigned items. - if (empty($item->getPackage()) && in_array($item->getType(), $exclude_types)) { - $item->setExcluded(TRUE); - } - } - } - - // Exclude configuration already provided by modules. - $exclude_module = $settings['module']; - if (!empty($exclude_module['installed'])) { - $install_list = $this->featuresManager->getExtensionStorages()->listAll(); - - // There are two settings that can limit what's included. - // First, we can skip configuration provided by the install profile. - $module_profile = !empty($exclude_module['profile']); - // Second, we can skip configuration provided by namespaced modules. - $module_namespace = !empty($exclude_module['namespace']); - if ($module_profile || $module_namespace) { - $profile_list = []; - $extension_list = []; - // Load the names of any configuration objects provided by the install - // profile. - if ($module_profile) { - $all_modules = $this->featuresManager->getAllModules(); - // FeaturesBundleInterface::getProfileName() would return the profile - // for the current bundle, if any. We want the profile that was - // installed. - $profile_name = drupal_get_profile(); - if (isset($all_modules[$profile_name])) { - $profile_list = $this->featuresManager->listExtensionConfig($all_modules[$profile_name]); - // If the configuration has been assigned to a feature that's - // present on the file system, don't make an exception for it. - foreach ($all_modules as $name => $extension) { - if ($name != $profile_name && $this->featuresManager->isFeatureModule($extension)) { - $profile_list = array_diff($profile_list, $this->featuresManager->listExtensionConfig($extension)); - } - } - } - } - // Load the names of any configuration objects provided by modules - // having the namespace of the current package set. - if ($module_namespace) { - $modules = $this->featuresManager->getFeaturesModules($current_bundle); - foreach ($modules as $extension) { - // Only make exception for uninstalled modules or - // if namespace_any is set - if (!empty($exclude_module['namespace_any']) || !$this->featuresManager->extensionEnabled($extension)) { - $extension_list = array_merge($extension_list, $this->featuresManager->listExtensionConfig($extension)); - } - } - } - // If any configuration was found, remove it from the list. - $install_list = array_diff($install_list, $profile_list, $extension_list); - } - foreach ($install_list as $item_name) { - if (isset($config_collection[$item_name])) { - // Flag extension-provided configuration, which should not be added - // to regular features but can be added to an install profile. - $config_collection[$item_name]->setProviderExcluded(TRUE); - } - } - } - - // Exclude configuration items on a curated list of site-specific - // configuration. - if ($settings['curated']) { - $item_names = [ - 'core.extension', - 'field.settings', - 'field_ui.settings', - 'filter.settings', - 'forum.settings', - 'image.settings', - 'node.settings', - 'system.authorize', - 'system.date', - 'system.file', - 'system.diff', - 'system.logging', - 'system.maintenance', - 'system.performance', - 'system.site', - 'update.settings', - ]; - foreach ($item_names as $item_name) { - unset($config_collection[$item_name]); - } - // Unset role-related actions that are automatically created by the - // User module. - // @see user_user_role_insert() - $prefixes = [ - 'system.action.user_add_role_action.', - 'system.action.user_remove_role_action.', - ]; - foreach (array_keys($config_collection) as $item_name) { - foreach ($prefixes as $prefix) { - if (strpos($item_name, $prefix) === 0) { - unset($config_collection[$item_name]); - } - } - } - } - - // Register the updated data. - $this->featuresManager->setConfigCollection($config_collection); - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentExisting.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentExisting.php deleted file mode 100644 index 6d78628d2608533c1bd2a6d518f383c7795dbc48..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentExisting.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; -use Drupal\features\FeaturesManagerInterface; - -/** - * Class for assigning existing modules to packages. - * - * @Plugin( - * id = "existing", - * weight = 12, - * name = @Translation("Existing"), - * description = @Translation("Add exported config to existing packages."), - * ) - */ -class FeaturesAssignmentExisting extends FeaturesAssignmentMethodBase { - /** - * Calls assignConfigPackage without allowing exceptions to abort us. - * - * @param string $machine_name - * Machine name of package. - * @param \Drupal\Core\Extension\Extension $extension - * An Extension object. - */ - protected function safeAssignConfig($machine_name, $extension) { - $config = $this->featuresManager->listExtensionConfig($extension); - try { - $this->featuresManager->assignConfigPackage($machine_name, $config); - } - catch (\Exception $exception) { - \Drupal::logger('features')->error($exception->getMessage()); - } - } - - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $packages = $this->featuresManager->getPackages(); - - // Assign config to installed modules first. - foreach ($packages as $name => $package) { - // @todo Introduce $package->isInstalled() and / or $package->isUninstalled(). - if ($package->getStatus() === FeaturesManagerInterface::STATUS_INSTALLED) { - $this->safeAssignConfig($package->getMachineName(), $package->getExtension()); - } - } - // Now assign to uninstalled modules. - foreach ($packages as $name => $package) { - if ($package->getStatus() === FeaturesManagerInterface::STATUS_UNINSTALLED) { - $this->safeAssignConfig($package->getMachineName(), $package->getExtension()); - } - } - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentForwardDependency.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentForwardDependency.php deleted file mode 100644 index c0c5801e57779cd8a2bfb95d512544a96c39e238..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentForwardDependency.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\Component\Graph\Graph; -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for assigning configuration to packages based on forward dependencies. - * - * @Plugin( - * id = "forward_dependency", - * weight = 20, - * name = @Translation("Forward dependency"), - * description = @Translation("Add to packages configuration on which items in the package depend."), - * ) - */ -class FeaturesAssignmentForwardDependency extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $config_collection = $this->featuresManager->getConfigCollection(); - $ordered = $this->dependencyOrder($config_collection); - - foreach ($ordered as $name) { - $item = $config_collection[$name]; - if ($item->getPackage()) { - // Already has a package, not our business. - continue; - } - - // Find packages of dependent items. - $dependent_packages = []; - foreach ($item->getDependents() as $dependent) { - if (isset($config_collection[$dependent])) { - if ($package = $config_collection[$dependent]->getPackage()) { - $dependent_packages[$package] = $package; - } - } - } - - // If zero or multiple packages, we don't know what to do. - if (count($dependent_packages) == 1) { - $package = key($dependent_packages); - $this->featuresManager->assignConfigPackage($package, [$name]); - } - } - } - - /** - * Get config items such that each item comes before anything it depends on. - * - * @param \Drupal\features\ConfigurationItem[] $config_collection - * A collection of configuration items. - * - * @return string[] - * The names of configuration items, in dependency order. - */ - protected function dependencyOrder($config_collection) { - // Populate a graph. - $graph = []; - foreach ($config_collection as $config) { - $graph[$config->getName()] = []; - foreach ($config->getDependents() as $dependent) { - $graph[$config->getName()]['edges'][$dependent] = 1; - } - } - $graph_object = new Graph($graph); - $graph = $graph_object->searchAndSort(); - - // Order by inverse weight. - $weights = array_column($graph, 'weight'); - array_multisort($weights, SORT_DESC, $graph); - return array_keys($graph); - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentNamespace.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentNamespace.php deleted file mode 100644 index bc2b6d00f360613b07f00b7df43d7c60c098ed71..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentNamespace.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for assigning configuration to packages based on namespaces. - * - * @Plugin( - * id = "namespace", - * weight = 0, - * name = @Translation("Namespace"), - * description = @Translation("Add config to packages that contain that package's machine name."), - * ) - */ -class FeaturesAssignmentNamespace extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $packages = $this->featuresManager->getPackages(); - $current_bundle = $this->assigner->getBundle(); - - // Build an array of patterns. - // Keys are short names while values are full machine names. - // We need full names because existing packages may receive machine names - // prefixed with a bundle name. - $patterns = []; - foreach ($packages as $package) { - $machine_name = $package->getMachineName(); - $pattern = $current_bundle->getShortName($machine_name); - $patterns[$pattern] = $machine_name; - } - $this->featuresManager->assignConfigByPattern($patterns); - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentOptionalType.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentOptionalType.php deleted file mode 100644 index d76835785e72f45ac9c69c4f31f07bdbbcabf005..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentOptionalType.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\Core\Config\InstallStorage; -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for assigning configuration to the - * InstallStorage::CONFIG_OPTIONAL_DIRECTORY based on entity types. - * - * @Plugin( - * id = "optional", - * weight = 0, - * name = @Translation("Optional type"), - * description = @Translation("Assign designated types of configuration to the 'config/optional' install directory. For example, if views are selected as optional, views assigned to any feature will be exported to the 'config/optional' directory and will not create a dependency on the Views module."), - * config_route_name = "features.assignment_optional", - * default_settings = { - * "types" = { - * "config" = {}, - * } - * } - * ) - */ -class FeaturesAssignmentOptionalType extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $this->assignSubdirectoryByConfigTypes(InstallStorage::CONFIG_OPTIONAL_DIRECTORY); - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentPackages.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentPackages.php deleted file mode 100644 index 759e9efc793a6ea6584ae6ed21e58874d06659f9..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentPackages.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for assigning existing modules to packages. - * - * @Plugin( - * id = "packages", - * weight = -20, - * name = @Translation("Packages"), - * description = @Translation("Detect and add existing package modules."), - * ) - */ -class FeaturesAssignmentPackages extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $bundle = $this->assigner->getBundle(); - $existing = $this->featuresManager->getFeaturesModules(); - foreach ($existing as $extension) { - $package = $this->featuresManager->initPackageFromExtension($extension); - $short_name = $package->getMachineName(); - - // Copy over package excluded settings, if any. - if ($package->getExcluded()) { - $config_collection = $this->featuresManager->getConfigCollection(); - foreach ($package->getExcluded() as $config_name) { - if (isset($config_collection[$config_name])) { - $package_excluded = $config_collection[$config_name]->getPackageExcluded(); - $package_excluded[] = $short_name; - $config_collection[$config_name]->setPackageExcluded($package_excluded); - } - } - $this->featuresManager->setConfigCollection($config_collection); - } - - // Assign required components, if any. - if ($package->getRequired() !== FALSE) { - $config = $package->getRequired(); - if (empty($config) || !is_array($config)) { - // if required is "true" or empty, add all config as required - $config = $this->featuresManager->listExtensionConfig($extension); - } - $this->featuresManager->assignConfigPackage($short_name, $config); - } - } - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentProfile.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentProfile.php deleted file mode 100644 index 81c503e073fab4fcc792d1a391c60ea88922ac26..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentProfile.php +++ /dev/null @@ -1,177 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; -use Drupal\Core\Config\InstallStorage; - -/** - * Class for adding configuration for the optional install profile. - * - * @Plugin( - * id = "profile", - * weight = 10, - * name = @Translation("Profile"), - * description = @Translation("Add configuration and other files to the optional install profile from the Drupal core Standard install profile. Without these additions, a generated install profile will be missing some important initial setup."), - * config_route_name = "features.assignment_profile", - * default_settings = { - * "curated" = FALSE, - * "standard" = { - * "files" = FALSE, - * "dependencies" = FALSE, - * }, - * "types" = { "config" = {} } - * } - * ) - */ -class FeaturesAssignmentProfile extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $current_bundle = $this->assigner->getBundle(); - - if ($current_bundle->isProfile()) { - $settings = $current_bundle->getAssignmentSettings($this->getPluginId()); - - // Ensure the profile package exists. - $profile_name = $current_bundle->getProfileName(); - - $profile_package = $this->featuresManager->getPackage($profile_name); - if (empty($profile_package)) { - $profile_package = $this->featuresManager->initPackage($profile_name, $current_bundle->getName(), $current_bundle->getDescription(), 'profile', $current_bundle); - } - - // Assign configuration by type. - $this->assignPackageByConfigTypes($profile_name, $force); - - // Include a curated list of configuration. - if ($settings['curated']) { - $config_collection = $this->featuresManager->getConfigCollection(); - $item_names = [ - 'automated_cron.settings', - 'system.cron', - 'system.theme', - ]; - $theme_settings = $this->configFactory->get('system.theme'); - foreach (['default', 'admin'] as $key) { - $item_names[] = $theme_settings->get($key) . '.settings'; - } - foreach ($item_names as $item_name) { - if (isset($config_collection[$item_name])) { - try { - $this->featuresManager->assignConfigPackage($profile_name, [$item_name]); - } - catch (\Exception $exception) { - \Drupal::logger('features')->error($exception->getMessage()); - } - } - } - } - - // Only read in from the Standard profile if this profile doesn't already - // exist. - $package_directories = $this->featuresManager->listPackageDirectories([], $current_bundle); - if (!isset($package_directories[$profile_name])) { - $standard_directory = 'core/profiles/standard'; - // Conditionally add files from the 'standard' install profile. - if ($settings['standard']['files']) { - // Add configuration from the Standard profile. - $config_collection = $this->featuresManager->getConfigCollection(); - $subdirectory = InstallStorage::CONFIG_INSTALL_DIRECTORY; - $item_names = $this->listRequiredStandardConfig(); - foreach ($item_names as $item_name) { - // If the configuration is present on the site, assign it. - if (isset($config_collection[$item_name])) { - // Only assign it if it's not already assigned to a package. - // @todo: if it's provided by a module, add a dependency. - if (!$config_collection[$item_name]->getPackage()) { - $this->featuresManager->assignConfigPackage($profile_name, [$item_name], $force); - // Reload the profile to refresh the config array after the addition. - $profile_package = $this->featuresManager->getPackage($profile_name); - } - // If it's already assigned to a package in the current bundle, - // add a dependency. - else { - $machine_name = $current_bundle->getFullName($config_collection[$item_name]->getPackage()); - if (!in_array($machine_name, $profile_package->getDependencies())) { - $profile_package->appendDependency($machine_name); - } - } - } - // Otherwise, copy it over from Standard. - else { - $filename = $item_name . '.yml'; - $profile_package->appendFile([ - 'filename' => $filename, - 'subdirectory' => $subdirectory, - 'string' => file_get_contents($standard_directory . '/' . $subdirectory . '/' . $filename) - ]); - } - } - - // Add .profile and .install files from Standard. - $files = [ - 'install', - 'profile', - ]; - // Iterate through the files. - foreach ($files as $extension) { - $filename = $standard_directory . '/standard.' . $extension; - if (file_exists($filename)) { - // Read the file contents. - $string = file_get_contents($filename); - // Substitute the profile's machine name and name for the Standard - // profile's equivalents. - $string = str_replace( - ['standard', 'Standard'], - [$profile_name, $current_bundle->getName()], - $string - ); - // Add the files to those to be output. - $profile_package->appendFile([ - 'filename' => $profile_name . '.' . $extension, - 'subdirectory' => NULL, - 'string' => $string - ], $extension); - } - } - } - // Conditionally merge in module and theme dependencies from the - // 'standard' install profile. - if ($settings['standard']['dependencies']) { - $info_file_uri = $standard_directory . '/standard.info.yml'; - if (file_exists($info_file_uri)) { - $profile_info = \Drupal::service('info_parser')->parse($info_file_uri); - $info = [ - 'dependencies' => $profile_package->getDependencies(), - 'themes' => $profile_package->getThemes(), - ]; - $info = $this->featuresManager->mergeInfoArray($info, $profile_info); - $profile_package->setDependencies($info['dependencies']); - $profile_package->setThemes($info['themes']); - } - } - $this->featuresManager->setPackage($profile_package); - } - } - } - - /** - * Returns the list of configuration items required by the Standard install - * profile. - * - * If install code is adapted from the Standard profile, these configuration - * items will be required. - * - * @return array - * An array of configuration item names. - */ - protected function listRequiredStandardConfig() { - return [ - 'contact.form.feedback', - 'user.role.administrator' - ]; - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentSiteType.php b/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentSiteType.php deleted file mode 100644 index 0269658208230bcb4dfbc49068b05d0f36eb71c7..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentSiteType.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesAssignment; - -use Drupal\features\FeaturesAssignmentMethodBase; - -/** - * Class for assigning configuration to a site package based on entity types. - * - * @Plugin( - * id = "site", - * weight = 7, - * name = @Translation("Site type"), - * description = @Translation("Assign designated types of configuration to a site configuration package module. For example, if image styles are selected as a site type, a site package will be generated and image styles will be assigned to it."), - * config_route_name = "features.assignment_site", - * default_settings = { - * "types" = { - * "config" = {}, - * } - * } - * ) - */ -class FeaturesAssignmentSiteType extends FeaturesAssignmentMethodBase { - /** - * {@inheritdoc} - */ - public function assignPackages($force = FALSE) { - $current_bundle = $this->assigner->getBundle(); - $machine_name = 'site'; - $name = $this->t('Site'); - $description = $this->t('Provides site components.'); - $package = $this->featuresManager->initPackage($machine_name, $name, $description, 'module', $current_bundle); - $this->assignPackageByConfigTypes($package->getMachineName(), $force); - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesGeneration/FeaturesGenerationArchive.php b/web/modules/features/src/Plugin/FeaturesGeneration/FeaturesGenerationArchive.php deleted file mode 100644 index a40c7a6dcf95761f926f4f6ae5fa19f7c75ee8da..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesGeneration/FeaturesGenerationArchive.php +++ /dev/null @@ -1,292 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesGeneration; - -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\features\FeaturesGenerationMethodBase; -use Drupal\Core\Archiver\ArchiveTar; -use Drupal\Core\Form\FormStateInterface; -use Drupal\features\FeaturesBundleInterface; -use Drupal\features\Package; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Class for generating a compressed archive of packages. - * - * @Plugin( - * id = \Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationArchive::METHOD_ID, - * weight = -2, - * name = @Translation("Download Archive"), - * description = @Translation("Generate packages and optional profile as a compressed archive for download."), - * ) - */ -class FeaturesGenerationArchive extends FeaturesGenerationMethodBase implements ContainerFactoryPluginInterface { - - /** - * The app root. - * - * @var string - */ - protected $root; - - /** - * The CSRF token generator. - * - * @var \Drupal\Core\Access\CsrfTokenGenerator - */ - protected $csrfToken; - - /** - * Creates a new FeaturesGenerationArchive instance. - * - * @param string $root - * The app root. - * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token - * The CSRF token generator. - */ - public function __construct($root, \Drupal\Core\Access\CsrfTokenGenerator $csrf_token) { - $this->root = $root; - $this->csrfToken = $csrf_token; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $container->get('app.root'), - $container->get('csrf_token') - ); - } - - /** - * The package generation method id. - */ - const METHOD_ID = 'archive'; - - /** - * The filename being written. - * - * @var string - */ - protected $archiveName; - - /** - * Reads and merges in existing files for a given package or profile. - */ - protected function preparePackage(Package $package, array $existing_packages, FeaturesBundleInterface $bundle = NULL) { - if (isset($existing_packages[$package->getMachineName()])) { - $existing_directory = $existing_packages[$package->getMachineName()]; - } - else { - $existing_directory = $package->getDirectory(); - } - $existing_directory = $this->root . '/' . $existing_directory; - - if (is_dir($existing_directory)) { - // Scan for all files. - $files = file_scan_directory($existing_directory, '/.*/'); - // Skip any existing .features.yml as it will be replaced. - $exclude_files = [ - $package->getMachineName() . '.features', - ]; - foreach ($files as $file) { - // Skip files in the any existing configuration directory, as these - // will be replaced. - foreach (array_keys($this->featuresManager->getExtensionStorages()->getExtensionStorages()) as $directory) { - if (strpos($file->uri, $directory) !== FALSE) { - continue 2; - } - } - // Merge in the info file. - if ($file->name == $package->getMachineName() . '.info') { - $files = $package->getFiles(); - $files['info']['string'] = $this->mergeInfoFile($package->getFiles()['info']['string'], $file->uri); - $package->setFiles($files); - } - // Read in remaining files. - elseif (!in_array($file->name, $exclude_files)) { - // Determine if the file is within a subdirectory of the - // extension's directory. - $file_directory = dirname($file->uri); - if ($file_directory !== $existing_directory) { - $subdirectory = substr($file_directory, strlen($existing_directory) + 1); - } - else { - $subdirectory = NULL; - } - $package->appendFile([ - 'filename' => $file->filename, - 'subdirectory' => $subdirectory, - 'string' => file_get_contents($file->uri) - ]); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function generate(array $packages = [], FeaturesBundleInterface $bundle = NULL) { - - // If no packages were specified, get all packages. - if (empty($packages)) { - $packages = $this->featuresManager->getPackages(); - } - - // Determine the best name for the tar archive. - // Single package export, so name by package name. - if (count($packages) == 1) { - $filename = current($packages)->getMachineName(); - } - // Profile export, so name by profile. - elseif (isset($bundle) && $bundle->isProfile()) { - $filename = $bundle->getProfileName(); - } - // Non-default bundle, so name by bundle. - elseif (isset($bundle) && !$bundle->isDefault()) { - $filename = $bundle->getMachineName(); - } - // Set a fallback name. - else { - $filename = 'generated_features'; - } - - $return = []; - - $this->archiveName = $filename . '.tar.gz'; - $archive_name = file_directory_temp() . '/' . $this->archiveName; - if (file_exists($archive_name)) { - file_unmanaged_delete($archive_name); - } - - $archiver = new ArchiveTar($archive_name); - - // Add package files. - foreach ($packages as $package) { - if (count($packages) == 1) { - // Single module export, so don't generate entire modules dir structure. - $package->setDirectory($package->getMachineName()); - } - $this->generatePackage($return, $package, $archiver); - } - - return $return; - } - - /** - * Writes a package or profile's files to an archive. - * - * @param array &$return - * The return value, passed by reference. - * @param \Drupal\features\Package $package - * The package or profile. - * @param ArchiveTar $archiver - * The archiver. - */ - protected function generatePackage(array &$return, Package $package, ArchiveTar $archiver) { - $success = TRUE; - foreach ($package->getFiles() as $file) { - try { - $this->generateFile($package->getDirectory(), $file, $archiver); - } - catch (\Exception $exception) { - $this->failure($return, $package, $exception); - $success = FALSE; - break; - } - } - if ($success) { - $this->success($return, $package); - } - } - - /** - * Registers a successful package or profile archive operation. - * - * @param array &$return - * The return value, passed by reference. - * @param \Drupal\features\Package $package - * The package or profile. - */ - protected function success(array &$return, Package $package) { - $type = $package->getType() == 'module' ? $this->t('Package') : $this->t('Profile'); - $return[] = [ - 'success' => TRUE, - // Archive writing doesn't merit a message, and if done through the UI - // would appear on the subsequent page load. - 'display' => FALSE, - 'message' => '@type @package written to archive.', - 'variables' => [ - '@type' => $type, - '@package' => $package->getName(), - ], - ]; - } - - /** - * Registers a failed package or profile archive operation. - * - * @param array &$return - * The return value, passed by reference. - * @param \Drupal\features\Package $package - * The package or profile. - * @param \Exception $exception - * The exception object. - * @param string $message - * Error message when there isn't an Exception object. - */ - protected function failure(array &$return, Package $package, \Exception $exception = NULL, $message = '') { - $type = $package->getType() == 'module' ? $this->t('Package') : $this->t('Profile'); - $return[] = [ - 'success' => FALSE, - // Archive writing doesn't merit a message, and if done through the UI - // would appear on the subsequent page load. - 'display' => FALSE, - 'message' => '@type @package not written to archive. Error: @error.', - 'variables' => [ - '@type' => $type, - '@package' => $package->getName(), - '@error' => isset($exception) ? $exception->getMessage() : $message, - ], - ]; - } - - /** - * Writes a file to the file system, creating its directory as needed. - * - * @param string $directory - * The extension's directory. - * @param array $file - * Array with the following keys: - * - 'filename': the name of the file. - * - 'subdirectory': any subdirectory of the file within the extension - * directory. - * - 'string': the contents of the file. - * @param ArchiveTar $archiver - * The archiver. - * - * @throws Exception - */ - protected function generateFile($directory, array $file, ArchiveTar $archiver) { - $filename = $directory; - if (!empty($file['subdirectory'])) { - $filename .= '/' . $file['subdirectory']; - } - $filename .= '/' . $file['filename']; - // Set the mode to 0644 rather than the default of 0600. - if ($archiver->addString($filename, $file['string'], FALSE, ['mode' => 0644]) === FALSE) { - throw new \Exception($this->t('Failed to archive file @filename.', ['@filename' => $file['filename']])); - } - } - - /** - * {@inheritdoc} - */ - public function exportFormSubmit(array &$form, FormStateInterface $form_state) { - // Redirect to the archive file download. - $form_state->setRedirect('features.export_download', ['uri' => $this->archiveName, 'token' => $this->csrfToken->get($this->archiveName)]); - } - -} diff --git a/web/modules/features/src/Plugin/FeaturesGeneration/FeaturesGenerationWrite.php b/web/modules/features/src/Plugin/FeaturesGeneration/FeaturesGenerationWrite.php deleted file mode 100644 index 5844c0e2d1c3a89f637f29194bf05fd5dfc08848..0000000000000000000000000000000000000000 --- a/web/modules/features/src/Plugin/FeaturesGeneration/FeaturesGenerationWrite.php +++ /dev/null @@ -1,237 +0,0 @@ -<?php - -namespace Drupal\features\Plugin\FeaturesGeneration; - -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\File\FileSystemInterface; -use Drupal\features\FeaturesGenerationMethodBase; -use Drupal\features\FeaturesBundleInterface; -use Drupal\features\Package; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Class for writing packages to the local file system. - * - * @Plugin( - * id = \Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite::METHOD_ID, - * weight = 2, - * name = @Translation("Write"), - * description = @Translation("Write packages and optional profile to the file system."), - * ) - */ -class FeaturesGenerationWrite extends FeaturesGenerationMethodBase implements ContainerFactoryPluginInterface { - - /** - * The package generation method id. - */ - const METHOD_ID = 'write'; - - /** - * The app root. - * - * @var string - */ - protected $root; - - /** - * The file_system service. - * @var \Drupal\Core\File\FileSystemInterface - */ - protected $fileSystem; - - /** - * Creates a new FeaturesGenerationWrite instance. - * - * @param string $root - * The app root. - */ - public function __construct($root, FileSystemInterface $fileSystem) { - $this->root = $root; - $this->fileSystem = $fileSystem; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $container->get('app.root'), - $container->get('file_system') - ); - } - - /** - * Reads and merges in existing files for a given package or profile. - * - * @param \Drupal\features\Package &$package - * The package. - * @param array $existing_packages - * An array of existing packages. - * @param \Drupal\features\FeaturesBundleInterface $bundle - * The bundle the package belongs to. - */ - protected function preparePackage(Package $package, array $existing_packages, FeaturesBundleInterface $bundle = NULL) { - // If this package is already present, prepare files. - if (isset($existing_packages[$package->getMachineName()])) { - $existing_directory = $existing_packages[$package->getMachineName()]; - $package->setDirectory($existing_directory); - } - else { - $existing_directory = $package->getDirectory(); - } - - // Merge in the info file. - $info_file_uri = $this->root . '/' . $existing_directory . '/' . $package->getMachineName() . '.info.yml'; - if (file_exists($info_file_uri)) { - $files = $package->getFiles(); - $files['info']['string'] = $this->mergeInfoFile($package->getFiles()['info']['string'], $info_file_uri); - $package->setFiles($files); - - // Remove the config directories, as they will be replaced. - foreach (array_keys($this->featuresManager->getExtensionStorages() - ->getExtensionStorages()) as $directory) { - $config_directory = $this->root . '/' . $existing_directory . '/' . $directory; - if (is_dir($config_directory)) { - file_unmanaged_delete_recursive($config_directory); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function generate(array $packages = [], FeaturesBundleInterface $bundle = NULL) { - // If no packages were specified, get all packages. - if (empty($packages)) { - $packages = $this->featuresManager->getPackages(); - } - - $return = []; - - // Add package files. - // We need to update the system.module.files state because it's cached. - // Cannot just call system_rebuild_module_data() because $listing->scan() has - // it's own internal static cache that we cannot clear at this point. - $files = \Drupal::state()->get('system.module.files'); - foreach ($packages as $package) { - $this->generatePackage($return, $package); - if (!isset($files[$package->getMachineName()]) && isset($package->getFiles()['info'])) { - $files[$package->getMachineName()] = $package->getDirectory() . '/' . $package->getFiles()['info']['filename']; - } - } - - // Rebuild system module cache - \Drupal::state()->set('system.module.files', $files); - - return $return; - } - - /** - * Writes a package or profile's files to the file system. - * - * @param array &$return - * The return value, passed by reference. - * @param \Drupal\features\Package $package - * The package or profile. - */ - protected function generatePackage(array &$return, Package $package) { - if (!$package->getFiles()) { - $this->failure($return, $package, NULL, $this->t('No configuration was selected to be exported.')); - return; - } - $success = TRUE; - foreach ($package->getFiles() as $file) { - try { - $this->generateFile($package->getDirectory(), $file); - } - catch (\Exception $exception) { - $this->failure($return, $package, $exception); - $success = FALSE; - break; - } - } - if ($success) { - $this->success($return, $package); - } - } - - /** - * Registers a successful package or profile write operation. - * - * @param array &$return - * The return value, passed by reference. - * @param \Drupal\features\Package $package - * The package or profile. - */ - protected function success(array &$return, Package $package) { - $type = $package->getType() == 'module' ? $this->t('Package') : $this->t('Profile'); - $return[] = [ - 'success' => TRUE, - 'display' => TRUE, - 'message' => '@type @package written to @directory.', - 'variables' => [ - '@type' => $type, - '@package' => $package->getName(), - '@directory' => $package->getDirectory(), - ], - ]; - } - - /** - * Registers a failed package or profile write operation. - * - * @param array &$return - * The return value, passed by reference. - * @param \Drupal\features\Package $package - * The package or profile. - * @param \Exception $exception - * The exception object. - * @param string $message - * Error message when there isn't an Exception object. - */ - protected function failure(array &$return, Package $package, \Exception $exception = NULL, $message = '') { - $type = $package->getType() == 'module' ? $this->t('Package') : $this->t('Profile'); - $return[] = [ - 'success' => FALSE, - 'display' => TRUE, - 'message' => '@type @package not written to @directory. Error: @error.', - 'variables' => [ - '@type' => $type, - '@package' => $package->getName(), - '@directory' => $package->getDirectory(), - '@error' => isset($exception) ? $exception->getMessage() : $message, - ], - ]; - } - - /** - * Writes a file to the file system, creating its directory as needed. - * - * @param string $directory - * The extension's directory. - * @param array $file - * Array with the following keys: - * - 'filename': the name of the file. - * - 'subdirectory': any subdirectory of the file within the extension - * directory. - * - 'string': the contents of the file. - * - * @throws Exception - */ - protected function generateFile($directory, array $file) { - if (!empty($file['subdirectory'])) { - $directory .= '/' . $file['subdirectory']; - } - $directory = $this->root . '/' . $directory; - if (!is_dir($directory)) { - if ($this->fileSystem->mkdir($directory, NULL, TRUE) === FALSE) { - throw new \Exception($this->t('Failed to create directory @directory.', ['@directory' => $directory])); - } - } - if (file_put_contents($directory . '/' . $file['filename'], $file['string']) === FALSE) { - throw new \Exception($this->t('Failed to write file @filename.', ['@filename' => $file['filename']])); - } - } - -} diff --git a/web/modules/features/tests/modules/test_feature/config/install/core.date_format.short.yml b/web/modules/features/tests/modules/test_feature/config/install/core.date_format.short.yml deleted file mode 100644 index f7fbe193a1db067a844ab309b29a0ce2edf2f013..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/modules/test_feature/config/install/core.date_format.short.yml +++ /dev/null @@ -1,7 +0,0 @@ -langcode: en -status: true -dependencies: { } -id: short -label: 'Default short date' -locked: false -pattern: 'm/d/Y - H:i' diff --git a/web/modules/features/tests/modules/test_feature/config/install/system.cron.yml b/web/modules/features/tests/modules/test_feature/config/install/system.cron.yml deleted file mode 100644 index e6f30d3d2d8e3a8b8012df9b053938ce86928974..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/modules/test_feature/config/install/system.cron.yml +++ /dev/null @@ -1,3 +0,0 @@ -threshold: - requirements_warning: 172800 - requirements_error: 1209600 diff --git a/web/modules/features/tests/modules/test_feature/test_feature.features.yml b/web/modules/features/tests/modules/test_feature/test_feature.features.yml deleted file mode 100644 index cbe4b9e2f069ea2f9925f34ff30535454879eaa1..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/modules/test_feature/test_feature.features.yml +++ /dev/null @@ -1,3 +0,0 @@ -bundle: test -excluded: - - system.theme diff --git a/web/modules/features/tests/modules/test_feature/test_feature.info.yml b/web/modules/features/tests/modules/test_feature/test_feature.info.yml deleted file mode 100644 index b90578e884831465e244a463bb0a6b04d24aec19..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/modules/test_feature/test_feature.info.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: feature -type: module -# core: 8.x -package: Test -# Force this to install after features. -dependencies: - - features - -# Information added by Drupal.org packaging script on 2018-09-09 -version: '8.x-3.8' -core: '8.x' -project: 'features' -datestamp: 1536512288 diff --git a/web/modules/features/tests/modules/test_mybundle_core/config/install/core.date_format.long.yml b/web/modules/features/tests/modules/test_mybundle_core/config/install/core.date_format.long.yml deleted file mode 100644 index 9e385f1c16877c554a79a0ce14215d90c405d5c3..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/modules/test_mybundle_core/config/install/core.date_format.long.yml +++ /dev/null @@ -1,7 +0,0 @@ -langcode: en -status: true -dependencies: { } -id: long -label: 'Default long date' -locked: false -pattern: 'l, F j, Y - H:i' diff --git a/web/modules/features/tests/modules/test_mybundle_core/test_mybundle_core.features.yml b/web/modules/features/tests/modules/test_mybundle_core/test_mybundle_core.features.yml deleted file mode 100644 index 3387e5fee59b597dcfe3d194090dba1e5649be9a..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/modules/test_mybundle_core/test_mybundle_core.features.yml +++ /dev/null @@ -1,5 +0,0 @@ -bundle: test_mybundle -excluded: - - system.theme -required: - - core.date_format.long diff --git a/web/modules/features/tests/modules/test_mybundle_core/test_mybundle_core.info.yml b/web/modules/features/tests/modules/test_mybundle_core/test_mybundle_core.info.yml deleted file mode 100644 index 2f0e6404ab97e692cfa72f9e154b11927f7ecb2b..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/modules/test_mybundle_core/test_mybundle_core.info.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Test Core -type: module -# core: 8.x -package: Test -# Ensure features is enabled first -dependencies: - - features - -# Information added by Drupal.org packaging script on 2018-09-09 -version: '8.x-3.8' -core: '8.x' -project: 'features' -datestamp: 1536512288 diff --git a/web/modules/features/tests/src/Kernel/Entity/FeaturesBundleIntegrationTest.php b/web/modules/features/tests/src/Kernel/Entity/FeaturesBundleIntegrationTest.php deleted file mode 100644 index aaf62bc726c18b02216c193018f8c1264897ef2e..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Kernel/Entity/FeaturesBundleIntegrationTest.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Kernel\Entity; - -use Drupal\features\Entity\FeaturesBundle; -use Drupal\features\FeaturesBundleInterface; -use Drupal\KernelTests\KernelTestBase; - -/** - * @coversDefaultClass \Drupal\features\Entity\FeaturesBundle - * @group features - */ -class FeaturesBundleIntegrationTest extends KernelTestBase { - - /** - * {@inheritdoc} - */ - public static $modules = ['features']; - - public function testCrud() { - $bundle = FeaturesBundle::create([ - 'machine_name' => 'test', - 'name' => 'Test', - ]); - $bundle->save(); - - /** @var \Drupal\features\Entity\FeaturesBundle $bundle */ - $bundle = FeaturesBundle::load('test'); - $this->assertEquals('Test', $bundle->getName()); - } - - /** - * @covers ::isDefault - */ - public function testIsDefaultWithDefaultBundle() { - $bundle = FeaturesBundle::create([ - 'machine_name' => FeaturesBundleInterface::DEFAULT_BUNDLE, - ]); - - $this->assertTrue($bundle->isDefault()); - } - - /** - * @covers ::isDefault - */ - public function testIsDefaultWithNonDefaultBundle() { - $bundle = FeaturesBundle::create([ - 'machine_name' => 'other', - ]); - - $this->assertFalse($bundle->isDefault()); - } - - /** - * @covers ::getFullName - */ - public function testGetFullName() { - } - - /** - * @covers ::getShortName - */ - public function testGetShortName() { - } - - /** - * @covers ::getProfileName - * @covers ::setProfileName - */ - public function testGetProfile() { - $bundle = FeaturesBundle::create([ - 'machine_name' => 'other', - 'profile_name' => 'example', - 'is_profile' => TRUE, - ]); - $this->assertEquals('example', $bundle->getProfileName()); - - $bundle->setProfileName('example2'); - $this->assertEquals('example2', $bundle->getProfileName()); - } - -} diff --git a/web/modules/features/tests/src/Kernel/FeaturesAssignTest.php b/web/modules/features/tests/src/Kernel/FeaturesAssignTest.php deleted file mode 100644 index 59b4ad961cd7efc8535de8173a76b082e0806c7c..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Kernel/FeaturesAssignTest.php +++ /dev/null @@ -1,855 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Kernel; - -use Drupal\KernelTests\KernelTestBase; -use Drupal\features\ConfigurationItem; -use Drupal\features\FeaturesManagerInterface; -use Drupal\Core\Config\InstallStorage; - -/** - * @group features - */ -class FeaturesAssignTest extends KernelTestBase { - - const PACKAGE_NAME = 'my_test_package'; - // Installed test feature package - const TEST_INSTALLED_PACKAGE = 'test_mybundle_core'; - // Uninstalled test feature package - const TEST_UNINSTALLED_PACKAGE = 'test_feature'; - - /** - * {@inheritdoc} - */ - public static $modules = ['features', 'node', 'system', 'user', self::TEST_INSTALLED_PACKAGE]; - - /** - * @var \Drupal\features\FeaturesManager - */ - protected $featuresManager; - - /** - * @var \Drupal\features\FeaturesAssigner - */ - protected $assigner; - - /** - * @var \Drupal\features\FeaturesBundleInterface - */ - protected $bundle; - - /** - * @todo Remove the disabled strict config schema checking. - */ - protected $strictConfigSchema = FALSE; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - - $this->installConfig('features'); - $this->installConfig('system'); - - $this->featuresManager = \Drupal::service('features.manager'); - $this->assigner = \Drupal::service('features_assigner'); - $this->bundle = $this->assigner->getBundle(); - - // Turn off all assignment plugins. - $this->bundle->setEnabledAssignments([]); - - // Start with an empty configuration collection. - $this->featuresManager->setConfigCollection([]); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentAlter - */ - public function testAssignAlter() { - $method_id = 'alter'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - // Add some configuration. - $this->addConfigurationItem('example.settings', [ - '_core' => ['something'], - 'uuid' => 'something', - ], - [ - 'type' => FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG, - ]); - $this->addConfigurationItem('node.type.article', [ - '_core' => ['something'], - 'uuid' => 'something', - 'permissions' => [ - 'first', - 'second', - ], - ], - [ - 'type' => 'node_type', - ]); - $this->addConfigurationItem('user.role.test', [ - '_core' => ['something'], - 'uuid' => 'something', - 'permissions' => [ - 'first', - 'second', - ], - ], - [ - 'type' => 'user_role', - ]); - - // Set all settings to FALSE. - $settings = [ - 'core' => FALSE, - 'uuid' => FALSE, - 'user_permissions' => FALSE, - ]; - $this->bundle->setAssignmentSettings($method_id, $settings); - - $this->assigner->applyAssignmentMethod($method_id); - - $config = $this->featuresManager->getConfigCollection(); - $this->assertNotEmpty($config['example.settings'], 'Expected config not created.'); - $this->assertNotEmpty($config['node.type.article'], 'Expected config not created.'); - $this->assertNotEmpty($config['user.role.test'], 'Expected config not created.'); - - $example_settings_data = $config['example.settings']->getData(); - $this->assertEquals($example_settings_data['_core'], ['something'], 'Expected _core value missing.'); - $this->assertEquals($example_settings_data['uuid'], 'something', 'Expected uuid value missing.'); - - $node_type_data = $config['node.type.article']->getData(); - $this->assertEquals($node_type_data['_core'], ['something'], 'Expected _core value missing.'); - $this->assertEquals($node_type_data['uuid'], 'something', 'Expected uuid value missing.'); - $this->assertEquals($node_type_data['permissions'], [ - 'first', - 'second', - ], 'Expected permissions value missing.'); - - $user_role_data = $config['user.role.test']->getData(); - $this->assertEquals($user_role_data['_core'], ['something'], 'Expected _core value missing.'); - $this->assertEquals($user_role_data['uuid'], 'something', 'Expected uuid value missing.'); - $this->assertEquals($user_role_data['permissions'], [ - 'first', - 'second', - ], 'Expected permissions value missing.'); - - // Set all settings to TRUE. - $settings = [ - 'core' => TRUE, - 'uuid' => TRUE, - 'user_permissions' => TRUE, - ]; - $this->bundle->setAssignmentSettings($method_id, $settings); - - $this->assigner->applyAssignmentMethod($method_id); - - $config = $this->featuresManager->getConfigCollection(); - $this->assertNotEmpty($config['example.settings'], 'Expected config not created.'); - $this->assertNotEmpty($config['node.type.article'], 'Expected config not created.'); - $this->assertNotEmpty($config['user.role.test'], 'Expected config not created.'); - - $example_settings_data = $config['example.settings']->getData(); - $this->assertFalse(isset($example_settings_data['_core']), 'Unexpected _core value present.'); - // uuid should be retained for simple configuration. - $this->assertEquals($example_settings_data['uuid'], 'something', 'Expected uuid value missing.'); - - $node_type_data = $config['node.type.article']->getData(); - $this->assertFalse(isset($node_type_data['_core']), 'Unexpected _core value present.'); - $this->assertFalse(isset($node_type_data['uuid']), 'Unexpected uuid value present.'); - // permissions should be stripped only for user_role configuration. - $this->assertEquals($node_type_data['permissions'], [ - 'first', - 'second', - ], 'Expected permissions value missing.'); - - $user_role_data = $config['user.role.test']->getData(); - $this->assertFalse(isset($user_role_data['_core']), 'Unexpected _core value present.'); - $this->assertFalse(isset($user_role_data['uuid']), 'Unexpected uuid value present.'); - $this->assertFalse(isset($user_role_data['permissions']), 'Unexpected permissions value present.'); - - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentBaseType - */ - public function testAssignBase() { - $method_id = 'base'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - // Test the default options for the base assignment method. - - // Test node type assignments. - // Declare the node_type entity 'article'. - $this->addConfigurationItem('node.type.article', [], [ - 'shortName' => 'article', - 'label' => 'Article', - 'type' => 'node_type', - 'dependents' => ['field.field.node.article.body'], - ]); - - // Add a piece of dependent configuration. - $this->addConfigurationItem('field.field.node.article.body', [], [ - 'shortName' => 'node.article.body', - 'label' => 'Body', - 'type' => 'field_config', - 'dependents' => [], - ]); - - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - - $expected_package_names = ['article', 'user']; - - $this->assertEquals($expected_package_names, array_keys($packages), 'Expected packages not created.'); - - // Dependents like field.field.node.article.body should not be assigned. - $expected_config_items = [ - 'node.type.article', - ]; - - $this->assertEquals($expected_config_items, $packages['article']->getConfig(), 'Expected configuration items not present in article package.'); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentCoreType - */ - public function testAssignCore() { - $method_id = 'core'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - // Test the default options for the core assignment method. - - // Add a piece of configuration of a core type. - $this->addConfigurationItem('field.storage.node.body', [], [ - 'shortName' => 'node.body', - 'label' => 'node.body', - 'type' => 'field_storage_config', - 'dependents' => ['field.field.node.article.body'], - ]); - - // Add a piece of configuration of a non-core type. - $this->addConfigurationItem('field.field.node.article.body', [], [ - 'shortName' => 'node.article.body', - 'label' => 'Body', - 'type' => 'field_config', - 'dependents' => [], - ]); - - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - - $expected_package_names = ['core']; - - $this->assertEquals($expected_package_names, array_keys($packages), 'Expected packages not created.'); - - $this->assertTrue(in_array('field.storage.node.body', $packages['core']->getConfig(), 'Expected configuration item not present in core package.')); - $this->assertFalse(in_array('field.field.node.article.body', $packages['core']->getConfig(), 'Unexpected configuration item present in core package.')); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentDependency - */ - public function testAssignDependency() { - $method_id = 'dependency'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - // Test the default options for the base assignment method. - - // Test node type assignments. - // Declare the node_type entity 'article'. - $this->addConfigurationItem('node.type.article', [], [ - 'shortName' => 'article', - 'label' => 'Article', - 'type' => 'node_type', - 'dependents' => ['field.field.node.article.body'], - ]); - - // Add a piece of dependent configuration. - $this->addConfigurationItem('field.field.node.article.body', [], [ - 'shortName' => 'node.article.body', - 'label' => 'Body', - 'type' => 'field_config', - 'dependents' => [], - ]); - - $this->featuresManager->initPackage(self::PACKAGE_NAME, 'My test package'); - $this->featuresManager->assignConfigPackage(self::PACKAGE_NAME, ['node.type.article']); - - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - - $expected_package_names = [self::PACKAGE_NAME]; - - $this->assertEquals($expected_package_names, array_keys($packages), 'Expected packages not created.'); - - $expected_config_items = [ - 'node.type.article', - 'field.field.node.article.body', - ]; - - $this->assertEquals($expected_config_items, $packages[self::PACKAGE_NAME]->getConfig(), 'Expected configuration items not present in article package.'); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentExclude - */ - public function testAssignExclude() { - $method_id = 'exclude'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - // Also enable Packages and Core plugins. - $this->enableAssignmentMethod('packages', FALSE); - $this->enableAssignmentMethod('core', FALSE); - - // Apply the bundle - $this->bundle = $this->assigner->loadBundle('test_mybundle'); - - $this->assigner->applyAssignmentMethod('packages'); - $packages = $this->featuresManager->getPackages(); - $this->assertNotEmpty($packages[self::TEST_INSTALLED_PACKAGE], 'Expected package not created.'); - - // 1. When Required is set to True, config should stay with the module - // First, test with "Required" set to True. - $packages[self::TEST_INSTALLED_PACKAGE]->setRequired(true); - $this->featuresManager->setPackages($packages); - - $this->assigner->applyAssignmentMethod('exclude'); - $this->assigner->applyAssignmentMethod('core'); - $this->assigner->applyAssignmentMethod('existing'); - $packages = $this->featuresManager->getPackages(); - - $expected_config_items = [ - 'core.date_format.long', - ]; - - $this->assertEquals($expected_config_items, $packages[self::TEST_INSTALLED_PACKAGE]->getConfig(), 'Expected configuration items not present in existing test_core package.'); - - // 2. When Required is set to False, config still stays with module - // Because the module is installed. - $this->reset(); - $this->bundle = $this->assigner->loadBundle('test_mybundle'); - - $this->assigner->applyAssignmentMethod('packages'); - $packages = $this->featuresManager->getPackages(); - $this->assertNotEmpty($packages[self::TEST_INSTALLED_PACKAGE], 'Expected test_mybundle_core package not created.'); - - // Set "Required" set to False - $packages[self::TEST_INSTALLED_PACKAGE]->setRequired(false); - $this->featuresManager->setPackages($packages); - - $this->assigner->applyAssignmentMethod('exclude'); - $this->assigner->applyAssignmentMethod('core'); - $this->assigner->applyAssignmentMethod('existing'); - $packages = $this->featuresManager->getPackages(); - $this->assertFalse(array_key_exists('core', $packages), 'Core package should not be created.'); - - $expected_config_items = [ - 'core.date_format.long', - ]; - $this->assertEquals($expected_config_items, $packages[self::TEST_INSTALLED_PACKAGE]->getConfig(), 'Expected configuration items not present in existing test_core package.'); - - // 3. When Required is set to False and module is NOT installed, - // Config stays with module if it doesn't match the current namespace - $this->reset(); - // Load a bundle different from TEST_UNINSTALLED_PACKAGE - $this->bundle = $this->assigner->loadBundle('test_mybundle'); - - $this->assigner->applyAssignmentMethod('packages'); - $packages = $this->featuresManager->getPackages(); - $this->assertNotEmpty($packages[self::TEST_UNINSTALLED_PACKAGE], 'Expected test_feature package not created.'); - $this->assertNotEmpty($packages[self::TEST_INSTALLED_PACKAGE], 'Expected test_mybundle_core package not created.'); - - // Mark package as uninstalled, set "Required" set to False - $packages[self::TEST_UNINSTALLED_PACKAGE]->setRequired(false); - $this->featuresManager->setPackages($packages); - - $this->assigner->applyAssignmentMethod('exclude'); - $this->assigner->applyAssignmentMethod('core'); - $this->assigner->applyAssignmentMethod('existing'); - $packages = $this->featuresManager->getPackages(); - $this->assertFalse(array_key_exists('core', $packages), 'Core package should not be created.'); - - $expected_config_items = [ - 'core.date_format.short', - 'system.cron', - ]; - $this->assertEquals($expected_config_items, $packages[self::TEST_UNINSTALLED_PACKAGE]->getConfig(), 'Expected configuration items not present in existing test_feature package.'); - - // 4. When Required is set to False and module is NOT installed, - // Config is reassigned within modules that match the namespace. - $this->reset(); - // Load the bundle used in TEST_UNINSTALLED_PACKAGE - $this->bundle = $this->assigner->loadBundle('test'); - if (empty($this->bundle) || $this->bundle->isDefault()) { - // Since we uninstalled the test_feature, we probably need to create - // an empty "test" bundle - $this->bundle = $this->assigner->createBundleFromDefault('test'); - } - - $this->assigner->applyAssignmentMethod('packages'); - $packages = $this->featuresManager->getPackages(); - $this->assertNotEmpty($packages[self::TEST_UNINSTALLED_PACKAGE], 'Expected test_feature package not created.'); - - // Set "Required" set to False - $packages[self::TEST_UNINSTALLED_PACKAGE]->setRequired(false); - $this->featuresManager->setPackages($packages); - - $this->assigner->applyAssignmentMethod('exclude'); - $this->assigner->applyAssignmentMethod('core'); - $this->assigner->applyAssignmentMethod('existing'); - $packages = $this->featuresManager->getPackages(); - $this->assertNotEmpty($packages['core'], 'Expected Core package not created.'); - - // Ensure "core" package is not confused with "test_core" module - // Since we are in a bundle - $this->assertEmpty($packages['core']->getExtension(), 'Autogenerated core package should not have an extension'); - - // Core config should be reassigned from TEST_UNINSTALLED_PACKAGE into Core - $expected_config_items = [ - 'system.cron', - ]; - $this->assertEquals($expected_config_items, $packages[self::TEST_UNINSTALLED_PACKAGE]->getConfig(), 'Expected configuration items not present in existing test_feature package.'); - $expected_config_items = [ - 'core.date_format.short', - ]; - $this->assertEquals($expected_config_items, $packages['core']->getConfig(), 'Expected configuration items not present in core package.'); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentExclude - */ - public function testAssignExisting() { - $method_id = 'existing'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - // Also enable Packages plugin. - $this->enableAssignmentMethod('packages', FALSE); - - // First create the existing packages. - $this->assigner->applyAssignmentMethod('packages'); - // Now move config into those existing packages. - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - $this->assertNotEmpty($packages[self::TEST_INSTALLED_PACKAGE], 'Expected package not created.'); - $this->assertNotEmpty($packages[self::TEST_UNINSTALLED_PACKAGE], 'Expected package not created.'); - - // Turn off any "required" option in package to let config get reassigned - $package = $packages[self::TEST_INSTALLED_PACKAGE]; - $package->setRequired(true); - - $expected_config_items = [ - 'core.date_format.long', - ]; - $this->assertEquals($expected_config_items, $packages[self::TEST_INSTALLED_PACKAGE]->getConfig(), 'Expected configuration items not present in existing package.'); - - $expected_config_items = [ - 'core.date_format.short', - 'system.cron', - ]; - $this->assertEquals($expected_config_items, $packages[self::TEST_UNINSTALLED_PACKAGE]->getConfig(), 'Expected configuration items not present in existing package.'); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentForwardDependency - */ - public function testAssignForwardDependency() { - $method_id = 'forward_dependency'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - // Add some configuration. - // Two parent items. - $this->addConfigurationItem('parent1', [], [ - 'type' => 'node_type', - 'dependents' => ['grandparent'], - ]); - $this->addConfigurationItem('parent2', [], [ - 'type' => 'node_type', - 'dependents' => [], - ]); - // Something that belongs to just one parent. - $this->addConfigurationItem('child1', [], [ - 'type' => 'node_type', - 'dependents' => ['parent1'], - ]); - // Something that belongs to both parents. - $this->addConfigurationItem('child2', [], [ - 'type' => 'node_type', - 'dependents' => ['parent1', 'parent2'], - ]); - // Something that indirectly belongs to parent1. - $this->addConfigurationItem('grandchild', [], [ - 'type' => 'node_type', - 'dependents' => ['child1'], - ]); - // A dependent, not a dependency. - $this->addConfigurationItem('grandparent', [], [ - 'type' => 'node_type', - 'dependents' => [], - ]); - // Something completely unrelated. - $this->addConfigurationItem('stranger', [], [ - 'type' => 'node_type', - 'dependents' => [], - ]); - - $this->featuresManager->initPackage(self::PACKAGE_NAME, 'My test package'); - $this->featuresManager->assignConfigPackage(self::PACKAGE_NAME, ['parent1']); - - $other_package_name = 'other_package'; - $this->featuresManager->initPackage($other_package_name, 'Other package'); - $this->featuresManager->assignConfigPackage($other_package_name, ['parent2']); - - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - $expected_package_names = [self::PACKAGE_NAME, $other_package_name]; - sort($expected_package_names); - $actual_package_names = array_keys($packages); - sort($actual_package_names); - $this->assertEquals($expected_package_names, $actual_package_names, 'Expected packages not created.'); - - $expected_config_items = [ - 'parent1', - 'child1', - 'grandchild', - ]; - sort($expected_config_items); - $actual_config_items = $packages[self::PACKAGE_NAME]->getConfig(); - sort($actual_config_items); - - $this->assertEquals($expected_config_items, $actual_config_items, 'Expected configuration items not present in article package.'); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentNamespace - */ - public function testAssignNamespace() { - $method_id = 'namespace'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - // Apply the bundle - $this->bundle = $this->assigner->loadBundle('test_mybundle'); - - $package_data = [ - 'article' => [ - // Items that should be assigned to 'article'. - 'article', - 'article-after', - 'before.article', - 'something_article', - 'something-article', - 'something.article', - 'article_something', - 'article-something', - 'article.something', - 'something_article_something', - 'something-article-something', - 'something.article.something', - 'something.article_something', - ], - 'article_after' => [ - // Items that should be assigned to 'article_after'. - 'article_after', - 'something_article_after', - 'something-article_after', - 'something.article_after', - 'article_after_something', - 'article_after-something', - 'article_after.something', - 'something_article_after_something', - 'something-article_after-something', - 'something.article_after.something', - 'something.article_after_something', - ], - 'before_article' => [ - // Items that should be assigned to 'before_article'. - 'before_article', - 'something_before_article', - 'something-before_article', - 'something.before_article', - 'before_article_something', - 'before_article-something', - 'before_article.something', - 'something_before_article_something', - 'something-before_article-something', - 'something.before_article.something', - 'something.before_article_something', - ], - // Emulate an existing feature, which has a machine name prefixed by - // the bundle name. - 'test_mybundle_page' => [ - // Items that should be assigned to 'test_mybundle_page'. - // Items should match the short name, 'page'. - 'page', - 'page-after', - 'before.page', - 'something_page', - 'something-page', - 'something.page', - 'page_something', - 'page-something', - 'page.something', - 'something_page_something', - 'something-page-something', - 'something.page.something', - 'something.page_something', - ], - ]; - - foreach ($package_data as $machine_name => $config_short_names) { - $this->featuresManager->initPackage($machine_name, 'My test package ' . $machine_name); - foreach ($config_short_names as $short_name) { - $this->addConfigurationItem('node.type.' . $short_name, [], [ - 'type' => 'node_type', - 'shortName' => $short_name, - ]); - } - } - - // Add some config that should not be matched. - $config_short_names = [ - 'example', - 'example_something', - 'article~', - 'myarticle', - ]; - foreach ($config_short_names as $short_name) { - $this->addConfigurationItem('node.type.' . $short_name, [], [ - 'type' => 'node_type', - 'shortName' => $short_name, - ]); - } - - $this->assigner->applyAssignmentMethod($method_id); - $packages = $this->featuresManager->getPackages(); - - foreach ($package_data as $machine_name => $config_short_names) { - $this->assertNotEmpty($packages[$machine_name], 'Expected package ' . $machine_name . ' not created.'); - array_walk($config_short_names, function(&$value) { - $value = 'node.type.' . $value; - }); - sort($config_short_names); - $package_config = $packages[$machine_name]->getConfig(); - sort($package_config); - $this->assertEquals($config_short_names, $package_config, 'Expected configuration items not present in ' . $machine_name . ' package.'); - } - - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentOptionalType - */ - public function testAssignOptionalType() { - $method_id = 'optional'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - $settings = [ - 'types' => [ - 'config' => ['image_style'], - ], - ]; - $this->bundle->setAssignmentSettings($method_id, $settings); - - // Add some configuration. - $this->addConfigurationItem('node.type.article', [], [ - 'type' => 'node_type', - ]); - $this->addConfigurationItem('image.style.test', [], [ - 'type' => 'image_style', - ]); - $this->featuresManager->initPackage(self::PACKAGE_NAME, 'My test package'); - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - $this->assertNotEmpty($packages[self::PACKAGE_NAME], 'Expected package not created.'); - - $config = $this->featuresManager->getConfigCollection(); - $this->assertNotEmpty($config['node.type.article'], 'Expected config not created.'); - $this->assertNotEmpty($config['image.style.test'], 'Expected config not created.'); - - $this->assertNull($config['node.type.article']->getSubdirectory(), 'Expected package subdirectory not set to default.'); - $this->assertEquals($config['image.style.test']->getSubdirectory(), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, 'Expected package subdirectory not set to optional.'); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentPackages - */ - public function testAssignPackages() { - $method_id = 'packages'; - - // A configuration item that will be excluded. - $this->addConfigurationItem('system.theme', [], [ - 'type' => FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG, - ]); - // A configuration item that will be required. - $this->addConfigurationItem('core.date_format.long', [], [ - 'type' => 'date_format', - ]); - // A configuration item that will be neither excluded nor required. - $this->addConfigurationItem('system.theme', [], [ - 'type' => FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG, - ]); - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - - $this->assertNotEmpty($packages[self::TEST_INSTALLED_PACKAGE], 'Expected package not created.'); - - $config = $this->featuresManager->getConfigCollection(); - - $this->assertTrue(in_array(self::TEST_INSTALLED_PACKAGE, $config['system.theme']->getPackageExcluded()), 'Configuration item not excluded from package.'); - $this->assertFalse(in_array(self::TEST_INSTALLED_PACKAGE, $config['system.site']->getPackageExcluded()), 'Configuration item excluded from package.'); - - $this->assertEquals(self::TEST_INSTALLED_PACKAGE, $config['core.date_format.long']->getPackage(), 'Required item not assigned to package.'); - $this->assertNotEquals(self::TEST_INSTALLED_PACKAGE, $config['system.site']->getPackage(), 'Unrequired item assigned to package.'); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentProfile - */ - public function testAssignProfile() { - $method_id = 'profile'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - // Add some configuration. - $this->addConfigurationItem('shortcut.myshortcut', [], [ - 'type' => 'shortcut_set', - ]); - $this->addConfigurationItem('node.type.article', [], [ - 'type' => 'node_type', - ]); - $this->addConfigurationItem('image.style.test', [], [ - 'type' => 'image_style', - ]); - $this->addConfigurationItem('system.cron', [], [ - 'type' => FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG, - ]); - $this->bundle = $this->assigner->createBundleFromDefault('myprofile'); - $this->bundle->setProfileName('myprofile'); - $this->bundle->setIsProfile(TRUE); - - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - $this->assertNotEmpty($packages['myprofile'], 'Expected package not created.'); - - $expected_config_items = [ - 'shortcut.myshortcut', - 'system.cron', - 'system.theme', - ]; - $this->assertEquals($expected_config_items, $packages['myprofile']->getConfig(), 'Expected configuration items not present in package.'); - } - - /** - * @covers Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentSiteType - */ - public function testAssignSiteType() { - $method_id = 'site'; - - // Enable the method. - $this->enableAssignmentMethod($method_id); - - // Test the default options for the site assignment method. - - // Add a piece of configuration of a site type. - $this->addConfigurationItem('filter.format.plain_text', [], [ - 'shortName' => 'plain_text', - 'label' => 'Plain text', - 'type' => 'filter_format', - ]); - - // Add a piece of configuration of a non-site type. - $this->addConfigurationItem('field.field.node.article.body', [], [ - 'shortName' => 'node.article.body', - 'label' => 'Body', - 'type' => 'field_config', - 'dependents' => [], - ]); - - $this->assigner->applyAssignmentMethod($method_id); - - $packages = $this->featuresManager->getPackages(); - - $expected_package_names = ['site']; - - $this->assertEquals($expected_package_names, array_keys($packages), 'Expected packages not created.'); - - $this->assertTrue(in_array('filter.format.plain_text', $packages['site']->getConfig(), 'Expected configuration item not present in site package.')); - $this->assertFalse(in_array('field.field.node.article.body', $packages['site']->getConfig(), 'Unexpected configuration item present in site package.')); - } - - /** - * Enables a specified assignment method. - * - * @param string $method_id - * The ID of an assignment method. - * @param bool $exclusive - * (optional) Whether to set the method as the only enabled method. - * Defaults to TRUE. - */ - protected function enableAssignmentMethod($method_id, $exclusive = TRUE) { - if ($exclusive) { - $this->bundle->setEnabledAssignments([$method_id]); - } - else { - $enabled = array_keys($this->bundle->getEnabledAssignments()); - $enabled[] = $method_id; - $this->bundle->setEnabledAssignments($enabled); - } - } - - /** - * Adds a configuration item. - * - * @param string $name - * The config name. - * @param array $data - * The config data. - * @param array $properties - * (optional) Additional properties set on the object. - */ - protected function addConfigurationItem($name, array $data = [], array $properties = []) { - $config_collection = $this->featuresManager->getConfigCollection(); - $config_collection[$name] = new ConfigurationItem($name, $data, $properties); - $this->featuresManager->setConfigCollection($config_collection); - } - - /** - * Reset the config to reapply assignment plugins - */ - protected function reset() { - $this->assigner->reset(); - // Start with an empty configuration collection. - $this->featuresManager->setConfigCollection([]); - } -} diff --git a/web/modules/features/tests/src/Kernel/FeaturesAssignerTest.php b/web/modules/features/tests/src/Kernel/FeaturesAssignerTest.php deleted file mode 100644 index 0477ece057b4ea2b6050548ad3c92c0596e980d1..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Kernel/FeaturesAssignerTest.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Kernel; - -use Drupal\Core\Config\StorageInterface; -use Drupal\Core\Entity\EntityStorageInterface; -use Drupal\features\FeaturesBundleInterface; -use Drupal\KernelTests\KernelTestBase; - -/** - * @group features - */ -class FeaturesAssignerTest extends KernelTestBase { - /** - * {@inheritdoc} - */ - public static $modules = ['system', 'config']; - - protected $strictConfigSchema = FALSE; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - // We need system.site in order to run $this->configImporter->import(). - $this->installConfig('system'); - } - - /** - * Test bundle auto-creation during config import. - * - * We check the case where the import also causes features to be installed, - * so at the time auto-creation happens there's not yet a default bundle. - */ - public function testBundleAutoCreationImport() { - // Install the feature. - $installer = $this->container->get('module_installer'); - // Have to do these separately so features_modules_installed() doesn't - // just exit. - $installer->install(['features']); - $installer->install(['test_feature']); - - // Save config. - $this->copyConfig( - $this->container->get('config.storage'), - $this->container->get('config.storage.sync') - ); - - // Uninstall modules. - $installer->uninstall(['features', 'test_feature']); - - // Restore the config from after install. - $this->configImporter()->import(); - - // Find the auto-created bundle. - $bundle_storage = $this->container->get('entity_type.manager') - ->getStorage('features_bundle'); - $bundle = $bundle_storage->load('test'); - $this->assertNotNull($bundle, "Features bundle doesn't exist"); - $this->assertContains( - 'Auto-generated bundle', - $bundle->getDescription(), - "Features bundle not auto-created"); - } - -} diff --git a/web/modules/features/tests/src/Kernel/FeaturesGenerateTest.php b/web/modules/features/tests/src/Kernel/FeaturesGenerateTest.php deleted file mode 100644 index d17c8221fa21d99d5fb496bd838c228d164df6d2..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Kernel/FeaturesGenerateTest.php +++ /dev/null @@ -1,210 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Kernel; - -use Drupal\features\Entity\FeaturesBundle; -use Drupal\KernelTests\KernelTestBase; -use Drupal\Component\Serialization\Yaml; -use Drupal\Core\Archiver\ArchiveTar; -use org\bovigo\vfs\vfsStream; - -/** - * @group features - */ -class FeaturesGenerateTest extends KernelTestBase { - - const PACKAGE_NAME = 'my_test_package'; - const BUNDLE_NAME = 'giraffe'; - - /** - * {@inheritdoc} - */ - public static $modules = ['features', 'system']; - - /** - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * @var \Drupal\features\FeaturesGeneratorInterface - */ - protected $generator; - - protected $strictConfigSchema = FALSE; - - /** - * @var \Drupal\features\FeaturesAssignerInterface - */ - protected $assigner; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - - $this->installConfig('features'); - $this->installConfig('system'); - - $this->featuresManager = \Drupal::service('features.manager'); - $this->generator = \Drupal::service('features_generator'); - $this->assigner = \Drupal::service('features_assigner'); - - $this->featuresManager->initPackage(self::PACKAGE_NAME, 'My test package'); - $package = $this->featuresManager->getPackage(self::PACKAGE_NAME); - $package->appendConfig('system.site'); - $this->featuresManager->setPackage($package); - } - - /** - * @covers \Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationArchive - */ - public function testExportArchive() { - $filename = file_directory_temp() . '/' . self::PACKAGE_NAME . '.tar.gz'; - if (file_exists($filename)) { - unlink($filename); - } - $this->assertFalse(file_exists($filename), 'Archive file already exists.'); - - $this->generator->generatePackages('archive', $this->assigner->getBundle(), [self::PACKAGE_NAME]); - $this->assertTrue(file_exists($filename), 'Archive file was not generated.'); - - $archive = new ArchiveTar($filename); - $files = $archive->listContent(); - - $this->assertEquals(3, count($files)); - $this->assertEquals(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.info.yml', $files[0]['filename']); - $this->assertEquals(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.features.yml', $files[1]['filename']); - $this->assertEquals(self::PACKAGE_NAME . '/config/install/system.site.yml', $files[2]['filename']); - - $expected_info = [ - "name" => "My test package", - "type" => "module", - "core" => "8.x", - ]; - $info = Yaml::decode($archive->extractInString(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.info.yml')); - $this->assertEquals($expected_info, $info, 'Incorrect info file generated'); - } - - public function testGeneratorWithBundle() { - $filename = file_directory_temp() . '/' . self::BUNDLE_NAME . '_' . self::PACKAGE_NAME . '.tar.gz'; - if (file_exists($filename)) { - unlink($filename); - } - $this->assertFalse(file_exists($filename), 'Archive file already exists.'); - - $bundle = FeaturesBundle::create([ - 'machine_name' => self::BUNDLE_NAME - ]); - - $this->generator->generatePackages('archive', $bundle, [self::PACKAGE_NAME]); - - $package = $this->featuresManager->getPackage(self::PACKAGE_NAME); - $this->assertNull($package); - - $package = $this->featuresManager->getPackage( self::BUNDLE_NAME . '_' . self::PACKAGE_NAME); - $this->assertEquals(self::BUNDLE_NAME . '_' . self::PACKAGE_NAME, $package->getMachineName()); - $this->assertEquals(self::BUNDLE_NAME, $package->getBundle()); - - $this->assertTrue(file_exists($filename), 'Archive file was not generated.'); - } - - /** - * @covers \Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite - */ - public function testExportWrite() { - // Set a fake drupal root, so the testbot can also write into it. - vfsStream::setup('drupal'); - \Drupal::getContainer()->set('app.root', 'vfs://drupal'); - $this->featuresManager->setRoot('vfs://drupal'); - - $package = $this->featuresManager->getPackage(self::PACKAGE_NAME); - // Find out where package will be exported - list($full_name, $path) = $this->featuresManager->getExportInfo($package, $this->assigner->getBundle()); - $path = 'vfs://drupal/' . $path . '/' . $full_name; - if (file_exists($path)) { - file_unmanaged_delete_recursive($path); - } - $this->assertFalse(file_exists($path), 'Package directory already exists.'); - - $this->generator->generatePackages('write', $this->assigner->getBundle(), [self::PACKAGE_NAME]); - $info_file_uri = $path . '/' . self::PACKAGE_NAME . '.info.yml'; - $this->assertTrue(file_exists($path), 'Package directory was not generated.'); - $this->assertTrue(file_exists($info_file_uri), 'Package info.yml not generated.'); - $this->assertTrue(file_exists($path . '/config/install'), 'Package config/install not generated.'); - $this->assertTrue(file_exists($path . '/config/install/system.site.yml'), 'Config.yml not exported.'); - - $expected_info = [ - "name" => "My test package", - "type" => "module", - "core" => "8.x", - ]; - $info = Yaml::decode(file_get_contents($info_file_uri)); - $this->assertEquals($expected_info, $info, 'Incorrect info file generated'); - - // Now, add stuff to the feature and re-export to ensure it is preserved - // Add a dependency to the package itself to see that it gets exported. - $package->setDependencies(['user']); - $this->featuresManager->setPackage($package); - // Add dependency and custom key to the info file to simulate manual edit. - $info['dependencies'] = ['node']; - $info['mykey'] = "test value"; - $info_contents = Yaml::encode($info); - file_put_contents($info_file_uri, $info_contents); - - // Add an extra file that should be retained. - $css_file = $path . '/' . self::PACKAGE_NAME . '.css'; - $file_contents = "This is a dummy file"; - file_put_contents($css_file, $file_contents); - - // Add a config file that should be removed since it's not part of the - // feature. - $config_file = $path . '/config/install/node.type.mytype.yml'; - file_put_contents($config_file, $file_contents); - - $this->generator->generatePackages('write', $this->assigner->getBundle(), [self::PACKAGE_NAME]); - $this->assertTrue(file_exists($info_file_uri), 'Package info.yml not generated.'); - $expected_info = [ - "name" => "My test package", - "type" => "module", - "core" => "8.x", - "dependencies" => ["node", "user"], - "mykey" => "test value", - ]; - $info = Yaml::decode(file_get_contents($info_file_uri)); - $this->assertEquals($expected_info, $info, 'Incorrect info file generated'); - $this->assertTrue(file_exists($css_file), 'Extra file was not retained.'); - $this->assertFalse(file_exists($config_file), 'Config directory was not cleaned.'); - $this->assertEquals($file_contents, file_get_contents($css_file), 'Extra file contents not retained'); - - // Next, test that generating an Archive picks up the extra files. - $filename = file_directory_temp() . '/' . self::PACKAGE_NAME . '.tar.gz'; - if (file_exists($filename)) { - unlink($filename); - } - $this->assertFalse(file_exists($filename), 'Archive file already exists.'); - $this->generator->generatePackages('archive', $this->assigner->getBundle(), [self::PACKAGE_NAME]); - $this->assertTrue(file_exists($filename), 'Archive file was not generated.'); - - $archive = new ArchiveTar($filename); - $files = $archive->listContent(); - - $this->assertEquals(4, count($files)); - $this->assertEquals(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.info.yml', $files[0]['filename']); - $this->assertEquals(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.features.yml', $files[1]['filename']); - $this->assertEquals(self::PACKAGE_NAME . '/config/install/system.site.yml', $files[2]['filename']); - $this->assertEquals(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.css', $files[3]['filename']); - - $expected_info = [ - "name" => "My test package", - "type" => "module", - "core" => "8.x", - "dependencies" => ["node", "user"], - "mykey" => "test value", - ]; - $info = Yaml::decode($archive->extractInString(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.info.yml')); - $this->assertEquals($expected_info, $info, 'Incorrect info file generated'); - $this->assertEquals($file_contents, $archive->extractInString(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.css'), 'Extra file contents not retained'); - } -} diff --git a/web/modules/features/tests/src/Kernel/FeaturesManagerKernelTest.php b/web/modules/features/tests/src/Kernel/FeaturesManagerKernelTest.php deleted file mode 100644 index 2ee7948816bf38d087f083718fdadb9b1919dd06..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Kernel/FeaturesManagerKernelTest.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Kernel; - -use Drupal\KernelTests\KernelTestBase; -use Drupal\features\ConfigurationItem; -use Drupal\features\Package; - -/** - * @group features - */ -class FeaturesManagerKernelTest extends KernelTestBase { - /** - * {@inheritdoc} - */ - public static $modules = ['system', 'config', 'features']; - - protected $strictConfigSchema = FALSE; - - /** - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * @var \Drupal\Core\Config\ConfigFactory - */ - protected $configFactory; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - - $this->installConfig('features'); - $this->installConfig('system'); - - $this->featuresManager = $this->container->get('features.manager'); - $this->configFactory = $this->container->get('config.factory'); - } - - /** - * @covers \Drupal\features\FeaturesManager::createConfiguration - */ - public function testCreateConfiguration() { - $config_name = 'system_simple.testcreate'; - $config = [ - 'string_value' => 'example', - 'array_value' => [ - 'item1' => 'value1', - 'item2' => 'value2', - ], - ]; - $this->featuresManager->createConfiguration([$config_name => $config]); - $config_item = $this->configFactory->get($config_name); - $this->assertEquals($config['string_value'], $config_item->get('string_value'), 'Test config string saved'); - $this->assertEquals($config['array_value'], $config_item->get('array_value'), 'Test config array saved'); - } - - /** - * @covers \Drupal\features\FeaturesManager::import - */ - public function testImport() { - $packages = [ - 'package' => new Package('package', [ - 'configOrig' => ['system_simple.example' => 'system_simple.example'], - 'dependencies' => [], - 'bundle' => '', - ]), - 'package2' => new Package('package2', [ - 'configOrig' => ['system_simple.example2' => 'system_simple.example2'], - 'dependencies' => [], - 'bundle' => '', - ]), - 'package3' => new Package('package3', [ - 'configOrig' => ['system_simple.example3' => 'system_simple.example3'], - 'dependencies' => [], - 'bundle' => '', - ]), - ]; - $this->featuresManager->setPackages($packages); - - // Create all three configuration items. - $config_item = new ConfigurationItem('system_simple.example', ['value' => 'example'], ['package' => 'package']); - $config_item2 = new ConfigurationItem('system_simple.example2', ['value' => 'example2'], ['package' => 'package2']); - $config_item3 = new ConfigurationItem('system_simple.example3', ['value' => 'example3'], ['package' => 'package3']); - // Only save example and example3 as currently active config (so example2 will be new). - $this->featuresManager->setConfigCollection(['system_simple.example' => $config_item, 'system_simple.example3' => $config_item3]); - - // Only import example and example2, so example3 is unchanged. - $result = $this->featuresManager->import(['package', 'package2']); - $this->assertEquals(['system_simple.example'], array_keys($result['package']['updated']), 'Expected config updated'); - $this->assertEquals(['system_simple.example2'], array_keys($result['package2']['new']), 'Expected config created'); - - // Test if config was actually saved to the Factory. - // Cannot test for example2 because we didn't save the original config data - // and Package2 isn't a real module so config can't be loaded from module. - $example = $this->configFactory->get('system_simple.example')->get('value'); - $this->assertEquals('example', $example, 'Example config saved'); - } - -} diff --git a/web/modules/features/tests/src/Unit/ConfigurationItemTest.php b/web/modules/features/tests/src/Unit/ConfigurationItemTest.php deleted file mode 100644 index 255ee8339dda2cb41ea7408bcd02fc319f7f2f68..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Unit/ConfigurationItemTest.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Unit; -use Drupal\features\ConfigurationItem; -use Drupal\features\FeaturesManagerInterface; - -/** - * @coversDefaultClass \Drupal\features\ConfigurationItem - * @group features - */ -class ConfigurationItemTest extends \PHPUnit_Framework_TestCase { - - /** - * @covers ::fromConfigStringToConfigType - */ - public function testFromConfigStringToConfigType() { - $this->assertEquals('system.simple', ConfigurationItem::fromConfigStringToConfigType(FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG)); - $this->assertEquals('node', ConfigurationItem::fromConfigStringToConfigType('node')); - } - -} diff --git a/web/modules/features/tests/src/Unit/FeaturesBundleTest.php b/web/modules/features/tests/src/Unit/FeaturesBundleTest.php deleted file mode 100644 index 726df5e04422822c97947a518d17ce70c0d1c93b..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Unit/FeaturesBundleTest.php +++ /dev/null @@ -1,206 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Unit; - -use Drupal\features\Entity\FeaturesBundle; -use Drupal\Tests\UnitTestCase; -use Drupal\Core\DependencyInjection\ContainerBuilder; -use Drupal\Core\Site\Settings; - -/** - * @coversDefaultClass Drupal\features\Entity\FeaturesBundle - * @group features - */ -class FeaturesBundleTest extends UnitTestCase { - - public function setUp() { - parent::setUp(); - - // Mock an assigner. - $manager = new DummyPluginManager(); - - // Mock the container. - $container = $this->prophesize('\Symfony\Component\DependencyInjection\ContainerInterface'); - $container->get('plugin.manager.features_assignment_method') - ->willReturn($manager); - \Drupal::setContainer($container->reveal()); - } - - /** - * @covers ::getEnabledAssignments - * @covers ::getAssignmentWeights - * @covers ::getAssignmentSettings - * @covers ::setAssignmentSettings - * @covers ::setAssignmentWeights - * @covers ::setEnabledAssignments - */ - public function testAssignmentSetting() { - // Create an entity. - $settings = [ - 'foo' => [ - 'enabled' => TRUE, - 'weight' => 0, - 'my_setting' => 42, - ], - 'bar' => [ - 'enabled' => FALSE, - 'weight' => 1, - 'another_setting' => 'value', - ], - ]; - $bundle = new FeaturesBundle([ - 'assignments' => $settings, - ], 'features_bundle'); - - // Get assignments and attributes. - $this->assertArrayEquals( - $bundle->getEnabledAssignments(), - ['foo' => 'foo'], - 'Can get enabled assignments' - ); - $this->assertArrayEquals( - $bundle->getAssignmentWeights(), - ['foo' => 0, 'bar' => 1], - 'Can get assignment weights' - ); - $this->assertArrayEquals( - $bundle->getAssignmentSettings('foo'), - $settings['foo'], - 'Can get assignment settings' - ); - $this->assertArrayEquals( - $bundle->getAssignmentSettings(), - $settings, - 'Can get all assignment settings' - ); - - // Change settings. - $settings['foo']['my_setting'] = 97; - $bundle->setAssignmentSettings('foo', $settings['foo']); - $this->assertArrayEquals( - $bundle->getAssignmentSettings('foo'), - $settings['foo'], - 'Can change assignment settings' - ); - - // Change weights. - $settings['foo']['weight'] = 1; - $settings['bar']['weight'] = 0; - $bundle->setAssignmentWeights(['foo' => 1, 'bar' => 0]); - $this->assertArrayEquals( - $bundle->getAssignmentWeights(), - ['foo' => 1, 'bar' => 0], - 'Can change assignment weights' - ); - $this->assertArrayEquals( - $bundle->getAssignmentSettings(), - $settings, - 'Weight changes are reflected in settings' - ); - - // Enable existing assignment. - $settings['bar']['enabled'] = TRUE; - $bundle->setEnabledAssignments(['foo', 'bar']); - $this->assertArrayEquals( - $bundle->getEnabledAssignments(), - ['foo' => 'foo', 'bar' => 'bar'], - 'Can enable assignment' - ); - $this->assertArrayEquals( - $bundle->getAssignmentSettings(), - $settings, - 'Enabled assignment status is reflected in settings' - ); - - // Disable existing assignments. - $settings['foo']['enabled'] = FALSE; - $settings['bar']['enabled'] = FALSE; - $bundle->setEnabledAssignments([]); - $this->assertArrayEquals( - $bundle->getEnabledAssignments(), - [], - 'Can disable assignments' - ); - $this->assertArrayEquals( - $bundle->getAssignmentSettings(), - $settings, - 'Disabled assignment status is reflected in settings' - ); - - // Enable a new assignment. - $settings['foo']['enabled'] = TRUE; - $settings['iggy'] = ['enabled' => TRUE, 'weight' => 0, 'new_setting' => 3]; - $bundle->setEnabledAssignments(['foo', 'iggy']); - $this->assertArrayEquals( - $bundle->getEnabledAssignments(), - ['foo' => 'foo', 'iggy' => 'iggy'], - 'Can enable new assignment' - ); - $bundle->setAssignmentSettings('iggy', $settings['iggy']); - $this->assertArrayEquals( - $bundle->getAssignmentSettings(), - $settings, - 'New enabled assignment status is reflected in settings' - ); - - } - - /** - * @covers ::getFullName - * @covers ::getShortName - * @covers ::SetIsProfile - * @covers ::isProfile - * @covers ::getProfileName - * @covers ::isProfilePackage - * @covers ::inBundle - */ - public function testFullname() { - $bundle = new FeaturesBundle([ - 'machine_name' => 'mybundle', - 'profile_name' => 'mybundle' - ], 'mybundle'); - $this->assertFalse($bundle->isProfile()); - // Settings:get('profile_name') isn't defined in test, so this returns NULL. - $this->assertNull($bundle->getProfileName()); - $this->assertFalse($bundle->isProfilePackage('mybundle')); - $this->assertEquals('mybundle_test', $bundle->getFullName('test')); - $this->assertEquals('mybundle_test', $bundle->getFullName('mybundle_test')); - $this->assertEquals('mybundle_mybundle', $bundle->getFullName('mybundle')); - $this->assertEquals('test', $bundle->getShortName('test')); - $this->assertEquals('test', $bundle->getShortName('mybundle_test')); - $this->assertEquals('mybundle', $bundle->getShortName('mybundle_mybundle')); - $this->assertEquals('mybundle', $bundle->getShortName('mybundle')); - $this->assertFalse($bundle->inBundle('test')); - $this->assertTrue($bundle->inBundle('mybundle_test')); - $this->assertFalse($bundle->inBundle('mybundle')); - - // Now test it as a profile bundle. - $bundle->setIsProfile(TRUE); - $this->assertTrue($bundle->isProfile()); - $this->assertTrue($bundle->isProfilePackage('mybundle')); - $this->assertFalse($bundle->isProfilePackage('standard')); - $this->assertEquals('mybundle', $bundle->getProfileName()); - $this->assertEquals('mybundle', $bundle->getFullName('mybundle')); - $this->assertFalse($bundle->inBundle('test')); - $this->assertTrue($bundle->inBundle('mybundle_test')); - $this->assertTrue($bundle->inBundle('mybundle')); - } - -} - -/** - * A dummy plugin manager, to help testing. - */ -class DummyPluginManager { - public function getDefinition($method_id) { - $definition = [ - 'enabled' => TRUE, - 'weight' => 0, - 'default_settings' => [ - 'my_setting' => 42, - ], - ]; - return $definition; - } - -} diff --git a/web/modules/features/tests/src/Unit/FeaturesManagerTest.php b/web/modules/features/tests/src/Unit/FeaturesManagerTest.php deleted file mode 100644 index f53937a7c4252d60c98011f153e4b3c0c1ff3373..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Unit/FeaturesManagerTest.php +++ /dev/null @@ -1,989 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Unit; - -use Drupal\Component\Serialization\Yaml; -use Drupal\config_update\ConfigDiffInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Config\ConfigManagerInterface; -use Drupal\Core\Config\InstallStorage; -use Drupal\Core\Config\StorageInterface; -use Drupal\Core\DependencyInjection\ContainerBuilder; -use Drupal\Core\Extension\Extension; -use Drupal\Core\Extension\InfoParser; -use Drupal\Core\Extension\InfoParserInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\config_update\ConfigRevertInterface; -use Drupal\features\Entity\FeaturesBundle; -use Drupal\features\FeaturesAssignerInterface; -use Drupal\features\FeaturesBundleInterface; -use Drupal\features\ConfigurationItem; -use Drupal\features\FeaturesExtensionStoragesInterface; -use Drupal\features\FeaturesManager; -use Drupal\features\FeaturesManagerInterface; -use Drupal\features\Package; -use Drupal\Tests\UnitTestCase; -use org\bovigo\vfs\vfsStream; -use Prophecy\Argument; - -/** - * @coversDefaultClass Drupal\features\FeaturesManager - * @group features - */ -class FeaturesManagerTest extends UnitTestCase { - /** - * @var string - * The name of the install profile. - */ - const PROFILE_NAME = 'my_profile'; - - /** - * @var \Drupal\features\FeaturesManagerInterface - */ - protected $featuresManager; - - /** - * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $entityTypeManager; - - /** - * @var \Drupal\Core\Config\StorageInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configStorage; - - /** - * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configFactory; - - /** - * @var \Drupal\Core\Config\ConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configManager; - - /** - * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $moduleHandler; - - /** - * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $configReverter; - - /** - * {@inheritdoc} - */ - public function setUp() { - parent::setUp(); - - $container = new ContainerBuilder(); - $container->set('string_translation', $this->getStringTranslationStub()); - $container->set('app.root', $this->root); - // Since in Drupal 8.3 the "\Drupal::installProfile()" was introduced - // then we have to spoof a value for the "install_profile" parameter - // because it will be used by "ExtensionInstallStorage" class, which - // extends the "FeaturesInstallStorage". - // @see \Drupal\features\FeaturesConfigInstaller::__construct() - $container->setParameter('install_profile', ''); - \Drupal::setContainer($container); - - $entity_type = $this->getMock('\Drupal\Core\Config\Entity\ConfigEntityTypeInterface'); - $entity_type->expects($this->any()) - ->method('getConfigPrefix') - ->willReturn('custom'); - $entity_type->expects($this->any()) - ->method('getProvider') - ->willReturn('my_module'); - $this->entityTypeManager = $this->getMock('\Drupal\Core\Entity\EntityTypeManagerInterface'); - $this->entityTypeManager->expects($this->any()) - ->method('getDefinition') - ->willReturn($entity_type); - $this->configFactory = $this->getMock(ConfigFactoryInterface::class); - $this->configStorage = $this->getMock(StorageInterface::class); - $this->configManager = $this->getMock(ConfigManagerInterface::class); - $this->moduleHandler = $this->getMock(ModuleHandlerInterface::class); - // getModuleList should return an array of extension objects. - // but we just need isset($module_list[$provider]) for - // ::getConfigDependency() and ::assignInterPackageDependencies(). - $this->moduleHandler->expects($this->any()) - ->method('getModuleList') - ->willReturn([ - 'my_module' => true, - 'example' => true, - 'example3' => true, - 'my_feature' => true, - 'my_other_feature' => true, - 'package' => true, - 'package2' => true, - 'package3' => true, - 'giraffe_package' => true, - 'giraffe_package2' => true, - 'giraffe_package3' => true, - ]); - $this->configReverter = $this->getMock(ConfigRevertInterface::class); - $this->configReverter->expects($this->any()) - ->method('import') - ->willReturn(true); - $this->configReverter->expects($this->any()) - ->method('revert') - ->willReturn(true); - $this->featuresManager = new FeaturesManager($this->root, $this->entityTypeManager, $this->configFactory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - } - - /** - * @covers ::getActiveStorage - */ - public function testGetActiveStorage() { - $this->assertInstanceOf('\Drupal\Core\Config\StorageInterface', $this->featuresManager->getActiveStorage()); - } - - /** - * @covers ::getExtensionStorages - */ - public function testGetExtensionStorages() { - $this->assertInstanceOf('\Drupal\features\FeaturesExtensionStoragesInterface', $this->featuresManager->getExtensionStorages()); - } - - /** - * @covers ::getFullName - * @dataProvider providerTestGetFullName - */ - public function testGetFullName($type, $name, $expected) { - $this->assertEquals($this->featuresManager->getFullName($type, $name), $expected); - } - - /** - * Data provider for ::testGetFullName(). - */ - public function providerTestGetFullName() { - return [ - [NULL, 'name', 'name'], - [FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG, 'name', 'name'], - ['custom', 'name', 'custom.name'], - ]; - } - - /** - * @covers ::getPackage - * @covers ::getPackages - * @covers ::reset - * @covers ::setPackages - */ - public function testPackages() { - $packages = ['foo' => 'bar']; - $this->featuresManager->setPackages($packages); - $this->assertEquals($packages, $this->featuresManager->getPackages()); - $this->assertEquals('bar', $this->featuresManager->getPackage('foo')); - $this->featuresManager->reset(); - $this->assertArrayEquals([], $this->featuresManager->getPackages()); - $this->assertNull($this->featuresManager->getPackage('foo')); - } - - /** - * @covers ::setConfigCollection - * @covers ::getConfigCollection - */ - public function testConfigCollection() { - $config = ['config' => new ConfigurationItem('', [])]; - $this->featuresManager->setConfigCollection($config); - $this->assertArrayEquals($config, $this->featuresManager->getConfigCollection()); - } - - /** - * @covers ::setPackage - * @covers ::getPackage - */ - public function testSetPackage() { - $package = new Package('foo'); - $this->featuresManager->setPackage($package); - $this->assertEquals($package, $this->featuresManager->getPackage('foo')); - } - - /** - * @covers ::filterPackages - */ - public function testGetPackages() { - $packages = [ - 'package' => new Package('package', [ - 'bundle' => '', - 'status' => FeaturesManagerInterface::STATUS_NO_EXPORT, - ]), - 'package2' => new Package('package2', [ - 'bundle' => '', - 'status' => FeaturesManagerInterface::STATUS_UNINSTALLED, - ]), - 'package3' => new Package('package3', [ - 'bundle' => 'my_bundle', - 'status' => FeaturesManagerInterface::STATUS_NO_EXPORT, - ]), - 'package4' => new Package('package4', [ - 'bundle' => 'my_bundle', - 'status' => FeaturesManagerInterface::STATUS_UNINSTALLED, - ]), - ]; - - // Filter for the default bundle. - $filtered_packages = $this->featuresManager->filterPackages($packages, FeaturesBundleInterface::DEFAULT_BUNDLE); - $this->assertEquals(['package', 'package2'], array_keys($filtered_packages)); - - // Filter for a custom bundle. - $filtered_packages = $this->featuresManager->filterPackages($packages, 'my_bundle'); - $this->assertEquals(['package3', 'package4'], array_keys($filtered_packages)); - - // Filter for a non-matching bundle. - $filtered_packages = $this->featuresManager->filterPackages($packages, 'some_bundle'); - $this->assertEquals([], array_keys($filtered_packages)); - - // Filter for the default bundle removing only exported. - $filtered_packages = $this->featuresManager->filterPackages($packages, FeaturesBundleInterface::DEFAULT_BUNDLE, TRUE); - $this->assertEquals(['package'], array_keys($filtered_packages)); - - // Filter for a custom bundle removing only exported. - $filtered_packages = $this->featuresManager->filterPackages($packages, 'my_bundle', TRUE); - $this->assertEquals(['package3'], array_keys($filtered_packages)); - - // Filter for a non-matching bundle removing only exported. - $filtered_packages = $this->featuresManager->filterPackages($packages, 'some_bundle', TRUE); - $this->assertEquals([], array_keys($filtered_packages)); - } - - - protected function getAssignInterPackageDependenciesConfigCollection() { - $config_collection = []; - $config_collection['example.config'] = (new ConfigurationItem('example.config', [ - 'dependencies' => [ - 'config' => [ - 'example.config2', - 'example.config3', - 'example.config4', - 'example.config5', - 'example.config6', - 'example.config7', - ], - ], - ])) - ->setSubdirectory(InstallStorage::CONFIG_INSTALL_DIRECTORY) - ->setPackage('package'); - $config_collection['example.config2'] = (new ConfigurationItem('example.config2', [ - 'dependencies' => [], - ])) - ->setSubdirectory(InstallStorage::CONFIG_INSTALL_DIRECTORY) - ->setPackage('package2') - ->setProvider('my_feature'); - $config_collection['example.config3'] = (new ConfigurationItem('example.config3', [ - 'dependencies' => [], - ])) - ->setSubdirectory(InstallStorage::CONFIG_INSTALL_DIRECTORY) - ->setProvider('my_other_feature'); - $config_collection['example.config4'] = (new ConfigurationItem('example.config3', [ - 'dependencies' => [], - ])) - ->setSubdirectory(InstallStorage::CONFIG_INSTALL_DIRECTORY) - ->setProvider(static::PROFILE_NAME); - $config_collection['example.config5'] = (new ConfigurationItem('example.config5', [ - 'dependencies' => [], - ])) - ->setSubdirectory(InstallStorage::CONFIG_OPTIONAL_DIRECTORY) - ->setPackage('package3'); - $config_collection['example.config6'] = (new ConfigurationItem('example.config6', [ - 'dependencies' => [], - ])) - ->setSubdirectory(InstallStorage::CONFIG_INSTALL_DIRECTORY) - ->setProvider('my_uninstalled_feature'); - $config_collection['example.config7'] = (new ConfigurationItem('example.config7', [ - 'dependencies' => [], - ])) - ->setSubdirectory(InstallStorage::CONFIG_INSTALL_DIRECTORY) - ->setProvider('package4'); - - return $config_collection; - } - - /** - * @covers ::assignInterPackageDependencies - */ - public function testAssignInterPackageDependenciesWithoutBundle() { - $assigner = $this->prophesize(FeaturesAssignerInterface::class); - $bundle = $this->prophesize(FeaturesBundleInterface::class); - // Provide a bundle without any prefix. - $bundle->getFullName('package')->willReturn('package'); - $bundle->getFullName('package2')->willReturn('package2'); - $bundle->getFullName('package3')->willReturn('package3'); - $bundle->getFullName('package4')->willReturn('package4'); - $bundle->isDefault()->willReturn(TRUE); - $assigner->getBundle()->willReturn($bundle->reveal()); - // Use the wrapper because we need ::drupalGetProfile(). - $features_manager = new TestFeaturesManager($this->root, $this->entityTypeManager, $this->configFactory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - $features_manager->setAssigner($assigner->reveal()); - - $features_manager->setConfigCollection($this->getAssignInterPackageDependenciesConfigCollection()); - - $packages = [ - 'package' => new Package('package', [ - 'config' => ['example.config', 'example.config3'], - 'dependencies' => [], - 'bundle' => '', - ]), - 'package2' => new Package('package2', [ - 'config' => ['example.config2'], - 'dependencies' => [], - 'bundle' => '', - ]), - 'package3' => new Package('package3', [ - 'config' => ['example.config5'], - 'dependencies' => [], - 'bundle' => '', - ]), - 'package4' => new Package('package4', [ - 'config' => ['example.config7'], - 'dependencies' => [], - 'bundle' => '', - ]), - ]; - - $features_manager->setPackages($packages); - // Dependencies require the full package names. - $package_names = array_keys($packages); - $features_manager->setPackageBundleNames($bundle->reveal(), $package_names); - $packages = $features_manager->getPackages(); - $features_manager->assignInterPackageDependencies($bundle->reveal(), $packages); - // example.config3 has a providing_feature but no assigned package. - // my_package2 provides configuration required by configuration in - // my_package. - // Because package assignments take precedence over providing_feature ones, - // package2 should have been assigned rather than my_feature. - // Because it is assigned to the InstallStorage::CONFIG_OPTIONAL_DIRECTORY - // subdirectory, example.config5 does not create a dependency on its - // providing feature, package3. - // Because it's provided by an uninstalled module, example.config6 doesn't - // create a dependency on my_uninstalled_feature. - // Because it's provided by an uninstalled module, example.config7 doesn't - // create a dependency on package4. - $this->assertEquals(['my_other_feature', 'package2'], $packages['package']->getDependencies()); - $this->assertEquals([], $packages['package2']->getDependencies()); - } - - /** - * @covers ::assignInterPackageDependencies - */ - public function testAssignInterPackageDependenciesWithBundle() { - $assigner = $this->prophesize(FeaturesAssignerInterface::class); - $bundle = $this->prophesize(FeaturesBundleInterface::class); - // Provide a bundle without any prefix. - $bundle->getFullName('package')->willReturn('giraffe_package'); - $bundle->getFullName('package2')->willReturn('giraffe_package2'); - $bundle->getFullName('package3')->willReturn('giraffe_package3'); - $bundle->getFullName('package4')->willReturn('giraffe_package4'); - $bundle->getFullName('giraffe_package')->willReturn('giraffe_package'); - $bundle->getFullName('giraffe_package2')->willReturn('giraffe_package2'); - $bundle->isDefault()->willReturn(FALSE); - $bundle->getMachineName()->willReturn('giraffe'); - $assigner->getBundle('giraffe')->willReturn($bundle->reveal()); - // Use the wrapper because we need ::drupalGetProfile(). - $features_manager = new TestFeaturesManager($this->root, $this->entityTypeManager, $this->configFactory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - $features_manager->setAssigner($assigner->reveal()); - $features_manager->setConfigCollection($this->getAssignInterPackageDependenciesConfigCollection()); - - $packages = [ - 'package' => new Package('package', [ - 'config' => ['example.config'], - 'dependencies' => [], - 'bundle' => 'giraffe', - ]), - 'package2' => new Package('package2', [ - 'config' => ['example.config2'], - 'dependencies' => [], - 'bundle' => 'giraffe', - ]), - 'package3' => new Package('package3', [ - 'config' => ['example.config5'], - 'dependencies' => [], - 'bundle' => 'giraffe', - ]), - 'package4' => new Package('package4', [ - 'config' => ['example.config7'], - 'dependencies' => [], - 'bundle' => 'giraffe', - ]), - ]; - - $features_manager->setPackages($packages); - // Dependencies require the full package names. - $package_names = array_keys($packages); - $features_manager->setPackageBundleNames($bundle->reveal(), $package_names); - $packages = $features_manager->getPackages(); - $features_manager->assignInterPackageDependencies($bundle->reveal(), $packages); - // example.config3 has a providing_feature but no assigned package. - // my_package2 provides configuration required by configuration in - // my_package. - // Because package assignments take precedence over providing_feature ones, - // package2 should have been assigned rather than my_feature. - // Because it is assigned to the InstallStorage::CONFIG_OPTIONAL_DIRECTORY - // subdirectory, example.config5 does not create a dependency on its - // providing feature, package3. - // Because it's provided by an uninstalled module, example.config6 doesn't - // create a dependency on my_uninstalled_feature. - // Because it's provided by an uninstalled module, example.config7 doesn't - // create a dependency on giraffe_package4. - $expected = ['giraffe_package2', 'my_other_feature']; - $this->assertEquals($expected, $packages['giraffe_package']->getDependencies()); - } - - /** - * @covers ::assignInterPackageDependencies - * @expectedException \Exception - * @expectedExceptionMessage The packages have not yet been prefixed with a bundle name - */ - public function testAssignInterPackageDependenciesPrematureCall() { - $bundle = $this->prophesize(FeaturesBundleInterface::class); - $packages = [ - 'package' => new Package('package', [ - 'config' => ['example.config', 'example.config3'], - 'dependencies' => [], - 'bundle' => 'giraffe', - ]), - ]; - - $this->featuresManager->assignInterPackageDependencies($bundle->reveal(), $packages); - } - - /** - * @covers ::reset - */ - public function testReset() { - $packages = [ - 'package' => [ - 'machine_name' => 'package', - 'config' => ['example.config', 'example.config3'], - 'dependencies' => [], - 'bundle' => 'giraffe', - ], - 'package2' => [ - 'machine_name' => 'package2', - 'config' => ['example.config2'], - 'dependencies' => [], - 'bundle' => 'giraffe', - ], - ]; - $this->featuresManager->setPackages($packages); - - $config_item = new ConfigurationItem('example', [], ['package' => 'package']); - $config_item2 = new ConfigurationItem('example2', [], ['package' => 'package2']); - $this->featuresManager->setConfigCollection([$config_item, $config_item2]); - - $this->featuresManager->reset(); - $this->assertEmpty($this->featuresManager->getPackages()); - $config_collection = $this->featuresManager->getConfigCollection(); - $this->assertEquals('', $config_collection[0]->getPackage()); - $this->assertEquals('', $config_collection[1]->getPackage()); - } - - - /** - * @covers ::detectMissing - */ - public function testDetectMissing() { - $package = new Package('test-package', [ - 'configOrig' => ['test_config', 'test_config_non_existing'], - ]); - - $config_collection = []; - $config_collection['test_config'] = new ConfigurationItem('test_config', []); - $this->featuresManager->setConfigCollection($config_collection); - - $this->assertEquals(['test_config_non_existing'], $this->featuresManager->detectMissing($package)); - } - - /** - * @covers ::detectOverrides - */ - public function testDetectOverrides() { - $config_diff = $this->prophesize(ConfigDiffInterface::class); - $config_diff->same(Argument::cetera())->will(function($args) { - return $args[0] == $args[1]; - }); - \Drupal::getContainer()->set('config_update.config_diff', $config_diff->reveal()); - - $package = new Package('test-package', [ - 'config' => ['test_config', 'test_overridden'], - ]); - - $config_storage = $this->prophesize(StorageInterface::class); - $config_storage->read('test_config')->willReturn([ - 'key' => 'value', - ]); - $config_storage->read('test_overridden')->willReturn([ - 'key2' => 'value2', - ]); - - $extension_storage = $this->prophesize(FeaturesExtensionStoragesInterface::class); - $extension_storage->read('test_config')->willReturn([ - 'key' => 'value', - ]); - $extension_storage->read('test_overridden')->willReturn([ - 'key2' => 'value0', - ]); - - - $features_manager = new TestFeaturesManager($this->root, $this->entityTypeManager, $this->configFactory, $config_storage->reveal(), $this->configManager, $this->moduleHandler, $this->configReverter); - $features_manager->setExtensionStorages($extension_storage->reveal()); - - $this->assertEquals(['test_overridden'], $features_manager->detectOverrides($package)); - } - - /** - * @covers ::assignConfigPackage - */ - public function testAssignConfigPackageWithNonProviderExcludedConfig() { - $assigner = $this->prophesize(FeaturesAssignerInterface::class); - $bundle = $this->prophesize(FeaturesBundleInterface::class); - $bundle->isProfilePackage('test_package')->willReturn(FALSE); - $bundle->isProfilePackage('test_package2')->willReturn(FALSE); - $assigner->getBundle(NULL)->willReturn($bundle->reveal()); - $this->featuresManager->setAssigner($assigner->reveal()); - - $config_collection = [ - 'test_config' => new ConfigurationItem('test_config', []), - 'test_config2' => new ConfigurationItem('test_config2', [ - 'dependencies' => [ - 'module' => ['example', 'example2'], - ] - ], [ - 'subdirectory' => InstallStorage::CONFIG_INSTALL_DIRECTORY, - ]), - 'example3.settings' => new ConfigurationItem('example3.settings', [], [ - 'type' => FeaturesManagerInterface::SYSTEM_SIMPLE_CONFIG, - 'subdirectory' => InstallStorage::CONFIG_INSTALL_DIRECTORY, - ]), - 'test_config3' => new ConfigurationItem('test_config3', [ - 'dependencies' => [ - 'module' => ['example2'], - ] - ], [ - 'subdirectory' => InstallStorage::CONFIG_OPTIONAL_DIRECTORY, - ]), - ]; - $this->featuresManager->setConfigCollection($config_collection); - - $package = new Package('test_package'); - $this->featuresManager->setPackage($package); - - $this->featuresManager->assignConfigPackage('test_package', ['test_config', 'test_config2', 'example3.settings']); - - $this->assertEquals(['test_config', 'test_config2', 'example3.settings'], $this->featuresManager->getPackage('test_package')->getConfig()); - // 'example2' is not returned by ::getModuleList() and so isn't a - // dependency. - $this->assertEquals(['example', 'example3', 'my_module'], $this->featuresManager->getPackage('test_package')->getDependencies()); - - // Test optional config, which doesn't create module dependencies. - $package = new Package('test_package2'); - $this->featuresManager->setPackage($package); - - $this->featuresManager->assignConfigPackage('test_package2', ['test_config3']); - - $this->assertEquals(['test_config3'], $this->featuresManager->getPackage('test_package2')->getConfig()); - $this->assertEquals([], $this->featuresManager->getPackage('test_package2')->getDependencies()); - } - - /** - * @covers ::assignConfigPackage - */ - public function testAssignConfigPackageWithProviderExcludedConfig() { - $config_collection = [ - 'test_config' => new ConfigurationItem('test_config', []), - 'test_config2' => new ConfigurationItem('test_config2', [], ['providerExcluded' => TRUE]), - ]; - $this->featuresManager->setConfigCollection($config_collection); - - $feature_assigner = $this->prophesize(FeaturesAssignerInterface::class); - $feature_assigner->getBundle(NULL)->willReturn(new FeaturesBundle(['machine_name' => FeaturesBundleInterface::DEFAULT_BUNDLE], 'features_bundle')); - $this->featuresManager->setAssigner($feature_assigner->reveal()); - - $package = new Package('test_package'); - $original_package = clone $package; - - $this->featuresManager->setPackage($package); - $this->featuresManager->assignConfigPackage('test_package', ['test_config', 'test_config2']); - $this->assertEquals(['test_config'], $this->featuresManager->getPackage('test_package')->getConfig(), 'just assign new packages'); - - $this->featuresManager->setPackage($original_package); - $this->featuresManager->assignConfigPackage('test_package', ['test_config', 'test_config2'], TRUE); - $this->assertEquals(['test_config', 'test_config2'], $this->featuresManager->getPackage('test_package')->getConfig(), 'just assign new packages'); - } - - /** - * @covers ::assignConfigPackage - */ - public function testAssignConfigPackageWithPackageExcludedConfig() { - $config_collection = [ - 'test_config' => new ConfigurationItem('test_config', []), - 'test_config2' => new ConfigurationItem('test_config2', [], ['packageExcluded' => ['test_package']]), - ]; - $this->featuresManager->setConfigCollection($config_collection); - - $feature_assigner = $this->prophesize(FeaturesAssignerInterface::class); - $feature_assigner->getBundle(NULL)->willReturn(new FeaturesBundle(['machine_name' => 'default'], 'features_bundle')); - $this->featuresManager->setAssigner($feature_assigner->reveal()); - - $package = new Package('test_package'); - $original_package = clone $package; - - $this->featuresManager->setPackage($package); - $this->featuresManager->assignConfigPackage('test_package', ['test_config', 'test_config2']); - $this->assertEquals(['test_config'], $this->featuresManager->getPackage('test_package')->getConfig(), 'just assign new packages'); - - $this->featuresManager->setPackage($original_package); - $this->featuresManager->assignConfigPackage('test_package', ['test_config', 'test_config2'], TRUE); - $this->assertEquals(['test_config', 'test_config2'], $this->featuresManager->getPackage('test_package')->getConfig(), 'just assign new packages'); - } - - /** - * @covers ::initPackageFromExtension - * @covers ::getPackageObject - */ - public function testInitPackageFromNonInstalledExtension() { - $extension = new Extension($this->root, 'module', 'modules/test_module/test_module.info.yml'); - - $info_parser = $this->prophesize(InfoParserInterface::class); - $info_parser->parse($this->root . '/modules/test_module/test_module.info.yml')->willReturn([ - 'name' => 'Test module', - 'description' => 'test description', - 'type' => 'module', - ]); - \Drupal::getContainer()->set('info_parser', $info_parser->reveal()); - - $bundle = $this->prophesize(FeaturesBundle::class); - $bundle->getFullName('test_module')->willReturn('test_module'); - $bundle->isDefault()->willReturn(TRUE); - - $assigner = $this->prophesize(FeaturesAssignerInterface::class); - $assigner->findBundle(Argument::cetera())->willReturn($bundle->reveal()); - $this->featuresManager->setAssigner($assigner->reveal()); - - $result = $this->featuresManager->initPackageFromExtension($extension); - $this->assertInstanceOf(Package::class, $result); - // Ensure that that calling the function twice works. - $result = $this->featuresManager->initPackageFromExtension($extension); - $this->assertInstanceOf(Package::class, $result); - - $this->assertEquals('test_module', $result->getMachineName()); - $this->assertEquals('Test module', $result->getName()); - $this->assertEquals('test description', $result->getDescription()); - $this->assertEquals('module', $result->getType()); - - $this->assertEquals(FeaturesManagerInterface::STATUS_UNINSTALLED, $result->getStatus()); - } - - /** - * @covers ::initPackageFromExtension - * @covers ::getPackageObject - */ - public function testInitPackageFromInstalledExtension() { - $extension = new Extension($this->root, 'module', 'modules/test_module/test_module.info.yml'); - - $info_parser = $this->prophesize(InfoParserInterface::class); - $info_parser->parse($this->root . '/modules/test_module/test_module.info.yml')->willReturn([ - 'name' => 'Test module', - 'description' => 'test description', - 'type' => 'module', - ]); - \Drupal::getContainer()->set('info_parser', $info_parser->reveal()); - - $bundle = $this->prophesize(FeaturesBundle::class); - $bundle->getFullName('test_module')->willReturn('test_module'); - $bundle->isDefault()->willReturn(TRUE); - - $assigner = $this->prophesize(FeaturesAssignerInterface::class); - $assigner->findBundle(Argument::cetera())->willReturn($bundle->reveal()); - $this->featuresManager->setAssigner($assigner->reveal()); - - $this->moduleHandler->expects($this->any()) - ->method('moduleExists') - ->with('test_module') - ->willReturn(TRUE); - - $result = $this->featuresManager->initPackageFromExtension($extension); - $this->assertEquals(FeaturesManagerInterface::STATUS_INSTALLED, $result->getStatus()); - } - - public function testDetectNewWithNoConfig() { - $package = new Package('test_feature'); - - $this->assertEmpty($this->featuresManager->detectNew($package)); - } - - public function testDetectNewWithNoNewConfig() { - $package = new Package('test_feature', ['config' => ['test_config']]); - - $extension_storage = $this->prophesize(FeaturesExtensionStoragesInterface::class); - $extension_storage->read('test_config')->willReturn([ - 'key' => 'value', - ]); - - $features_manager = new TestFeaturesManager($this->root, $this->entityTypeManager, $this->configFactory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - $features_manager->setExtensionStorages($extension_storage->reveal()); - - $this->assertEmpty($features_manager->detectNew($package)); - } - - public function testDetectNewWithNewConfig() { - $package = new Package('test_feature', ['config' => ['test_config']]); - - $extension_storage = $this->prophesize(FeaturesExtensionStoragesInterface::class); - $extension_storage->read('test_config')->willReturn(FALSE); - - $features_manager = new TestFeaturesManager($this->root, $this->entityTypeManager, $this->configFactory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - $features_manager->setExtensionStorages($extension_storage->reveal()); - - $this->assertEquals(['test_config'], $features_manager->detectNew($package)); - } - - /** - * @todo This could have of course much more test coverage. - * - * @covers ::mergeInfoArray - * - * @dataProvider providerTestMergeInfoArray - */ - public function testMergeInfoArray($expected, $info1, $info2, $keys = []) { - $this->assertSame($expected, $this->featuresManager->mergeInfoArray($info1, $info2, $keys)); - } - - public function providerTestMergeInfoArray() { - $data = []; - $data['empty-info'] = [[], [], []]; - $data['override-info'] = [ - ['name' => 'New name', 'core' => '8.x'], - ['name' => 'Old name', 'core' => '8.x'], - ['name' => 'New name'] - ]; - $data['dependency-merging'] = [ - ['dependencies' => ['a', 'b', 'c', 'd', 'e']], - ['dependencies' => ['b', 'd', 'c']], - ['dependencies' => ['a', 'b', 'e']], - [], - ]; - - return $data; - } - - /** - * @covers ::initPackage - **/ - public function testInitPackageWithNewPackage() { - $bundle = new FeaturesBundle(['machine_name' => 'test'], 'features_bundle'); - - $features_manager = new TestFeaturesManager($this->root, $this->entityTypeManager, $this->configFactory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - $features_manager->setAllModules([]); - - $package = $features_manager->initPackage('test_feature', 'test name', 'test description', 'module', $bundle); - - $this->assertInstanceOf(Package::class, $package); - $this->assertEquals('test_feature', $package->getMachineName()); - $this->assertEquals('test name', $package->getName()); - $this->assertEquals('test description', $package->getDescription()); - $this->assertEquals('module', $package->getType()); - $this->assertEquals(['bundle' => 'test'], $package->getFeaturesInfo()); - $this->assertEquals('test', $package->getBundle()); - $this->assertEquals(FALSE, $package->getRequired()); - $this->assertEquals([], $package->getExcluded()); - } - - /** - * @covers ::getFeaturesInfo - * @covers ::getFeaturesModules - **/ - public function testInitPackageWithExistingPackage() { - $bundle = new FeaturesBundle(['machine_name' => 'test'], 'features_bundle'); - - $features_manager = new TestFeaturesManager('vfs://drupal', $this->entityTypeManager, $this->configFactory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - - vfsStream::setup('drupal'); - \Drupal::getContainer()->set('app.root', 'vfs://drupal'); - vfsStream::create([ - 'modules' => [ - 'test_feature' => [ - 'test_feature.info.yml' => <<<EOT -name: Test feature 2 -type: module -core: 8.x -description: test description 2 -EOT - , - 'test_feature.features.yml' => <<<EOT -bundle: test -excluded: - - system.theme -required: true -EOT - , - ], - ], - ]); - $extension = new Extension('vfs://drupal', 'module', 'modules/test_feature/test_feature.info.yml'); - $features_manager->setAllModules(['test_feature' => $extension]); - - $this->moduleHandler->expects($this->any()) - ->method('exists') - ->with('test_feature') - ->willReturn(TRUE); - - $info_parser = new InfoParser(); - \Drupal::getContainer()->set('info_parser', $info_parser); - - $package = $features_manager->initPackage('test_feature', 'test name', 'test description', 'module', $bundle); - - $this->assertEquals([ - 'bundle' => 'test', - 'excluded' => [ - 0 => 'system.theme', - ], - 'required' => TRUE, - ], $features_manager->getFeaturesInfo($extension)); - $this->assertEquals(['test_feature' => $extension], $features_manager->getFeaturesModules($bundle)); - - $this->assertInstanceOf(Package::class, $package); - $this->assertEquals([ - 'bundle' => 'test', - 'excluded' => [ - 0 => 'system.theme', - ], - 'required' => TRUE, - ], $package->getFeaturesInfo()); - $this->assertEquals('test', $package->getBundle()); - $this->assertEquals(TRUE, $package->getRequired()); - $this->assertEquals(['system.theme'], $package->getExcluded()); - } - - /** - * @covers ::prepareFiles - * @covers ::addInfoFile - */ - public function testPrepareFiles() { - $packages = []; - $packages['test_feature'] = new Package('test_feature', [ - 'config' => ['test_config'], - 'name' => 'Test feature', - ]); - - $packages['test_feature2'] = new Package('test_feature2', [ - 'config' => ['test_config2'], - 'name' => 'Test feature 2', - 'type' => 'profile', - 'excluded' => ['my_config'], - 'required' => ['test_config2'], - ]); - - $config_collection = []; - $config_collection['test_config'] = new ConfigurationItem('test_config', ['foo' => 'bar']); - $config_collection['test_config2'] = new ConfigurationItem('test_config2', ['foo' => 'bar']); - - $this->featuresManager->setConfigCollection($config_collection); - $this->featuresManager->prepareFiles($packages); - - // Test test_feature package. - $files = $packages['test_feature']->getFiles(); - $this->assertCount(3, $files); - $this->assertEquals('test_feature.info.yml', $files['info']['filename']); - $this->assertEquals(Yaml::encode([ - 'name' => 'Test feature', - 'type' => 'module', - 'core' => '8.x', - ]), $files['info']['string']); - $this->assertEquals(Yaml::encode(TRUE), $files['features']['string']); - - $this->assertEquals('test_config.yml', $files['test_config']['filename']); - $this->assertEquals(Yaml::encode([ - 'foo' => 'bar' - ]), $files['test_config']['string']); - - $this->assertEquals('test_feature.features.yml', $files['features']['filename']); - $this->assertEquals(Yaml::encode(TRUE), $files['features']['string']); - - // Test test_feature2 package. - $files = $packages['test_feature2']->getFiles(); - - $this->assertEquals(Yaml::encode([ - 'excluded' => ['my_config'], - 'required' => ['test_config2'], - ]), $files['features']['string']); - } - - /** - * @covers ::getExportInfo - */ - public function testGetExportInfoWithoutBundle() { - $config_factory = $this->getConfigFactoryStub([ - 'features.settings' => [ - 'export' => [ - 'folder' => 'custom', - ], - ], - ]); - $this->featuresManager = new FeaturesManager($this->root, $this->entityTypeManager, $config_factory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - - $package = new Package('test_feature'); - $result = $this->featuresManager->getExportInfo($package); - - $this->assertEquals(['test_feature', 'modules/custom'], $result); - } - - /** - * @covers ::getExportInfo - */ - public function testGetExportInfoWithBundle() { - $config_factory = $this->getConfigFactoryStub([ - 'features.settings' => [ - 'export' => [ - 'folder' => 'custom', - ], - ], - ]); - $this->featuresManager = new FeaturesManager($this->root, $this->entityTypeManager, $config_factory, $this->configStorage, $this->configManager, $this->moduleHandler, $this->configReverter); - - $package = new Package('test_feature'); - $bundle = new FeaturesBundle(['machine_name' => 'test_bundle'], 'features_bundle'); - - $result = $this->featuresManager->getExportInfo($package, $bundle); - - $this->assertEquals(['test_bundle_test_feature', 'modules/custom'], $result); - } - -} - -class TestFeaturesManager extends FeaturesManager { - - protected $allModules; - - /** - * @param \Drupal\features\FeaturesExtensionStoragesInterface $extensionStorages - */ - public function setExtensionStorages($extensionStorages) { - $this->extensionStorages = $extensionStorages; - } - - /** - * {@inheritdoc} - */ - public function getAllModules() { - if (isset($this->allModules)) { - return $this->allModules; - } - return parent::getAllModules(); - } - - /** - * @param mixed $all_modules - */ - public function setAllModules($all_modules) { - $this->allModules = $all_modules; - return $this; - } - - protected function drupalGetProfile() { - return FeaturesManagerTest::PROFILE_NAME; - } - -} diff --git a/web/modules/features/tests/src/Unit/PackageTest.php b/web/modules/features/tests/src/Unit/PackageTest.php deleted file mode 100644 index f1b322231ec8044b79b126f62a55adfe66ff39b3..0000000000000000000000000000000000000000 --- a/web/modules/features/tests/src/Unit/PackageTest.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -namespace Drupal\Tests\features\Unit; - -use Drupal\features\Package; - -/** - * @coversDefaultClass \Drupal\features\Package - * @group features - */ -class PackageTest extends \PHPUnit_Framework_TestCase { - - /** - * @covers ::setFeaturesInfo - */ - public function testSetFeaturesInfo() { - $package = new Package('test_feature', []); - - $this->assertEquals([], $package->getFeaturesInfo()); - $package->setFeaturesInfo(['bundle' => 'test_bundle']); - $this->assertEquals(['bundle' => 'test_bundle'], $package->getFeaturesInfo()); - $this->assertEquals('test_bundle', $package->getBundle()); - } - - public function testGetConfig() { - $package = new Package('test_feature', ['config' => ['test_config_a', 'test_config_b']]); - $this->assertEquals(['test_config_a', 'test_config_b'], $package->getConfig()); - return $package; - } - - /** - * @depends testGetConfig - * @covers ::appendConfig - */ - public function testAppendConfig(Package $package) { - $package->appendConfig('test_config_a'); - $package->appendConfig('test_config_c'); - - $this->assertEquals(['test_config_a', 'test_config_b', 'test_config_c'], array_values($package->getConfig())); - return $package; - } - - /** - * @depends testAppendConfig - * @covers ::removeConfig - */ - public function testRemoveConfig(Package $package) { - $package->removeConfig('test_config_a'); - - $this->assertEquals(['test_config_b', 'test_config_c'], array_values($package->getConfig())); - } - -}