Problem/Motivation

Follow-up to #2830880: Warn site admins when composer dev dependencies are installed inside of docroot where we have a test that is a kernel test only because KernelTestBase makes REQUIREMENT_OK available to the system under test.

Let's move the REQUIREMENT_* family of constants to a loadable namespace.

@alexpott on #50 said:

I feel this is OO-ification for OO-ification's sake. We're only moving the constants so they can be autoloaded. But a proper redesign of the requirements system might end up with Requirement value objects that makes these constants redundant - imagine $requirement->isError() etc...

If what we want to solve autoloadability of constants there's another way. We could add core/constants.php to our autoloader in the files section and repeating myself from the other issue the advantages are

  • there's no deprecation
  • the constants become available to autoloaded code
  • as constants.php grows it becomes a place to learn about all the core provided constants

The one downside is this approach is only available to core and not core modules/themes, or contrib or custom because they don't using composer to set up their autoloading. But I'm not sure that outweighs the advantages listed.

Proposed resolution

TBD.

Remaining tasks

Make a patch, or decide this is a Won't Fix.

User interface changes

API changes

Data model changes

Issue fork drupal-2909480

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Mile23 created an issue. See original summary.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andypost’s picture

btw This constants already moved in #1987824: Convert system_php() to a new style controller

so here needs
- find a place for new constants (REQUIREMENT_INFO is not in SystemManager) still think better to use Requirements class from #2908079: Move some of the bootstrap.inc PHP-related constants to \Drupal and deprecate the old versions
- properly deprecate them
- replace usage
- file change record
- not sure about how to add deprecated tests for constants

andypost’s picture

Status: Active » Needs review
Issue tags: +Needs change record
StatusFileSize
new3.44 KB

Just to make ball roll & check how much affected in tests

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

naveenvalecha’s picture

StatusFileSize
new3.47 KB
new1.79 KB

CR drafted https://www.drupal.org/node/3047376
Also rerolled the patch for 8.8.x
Should we also replace the usage of the deprecated constants as part of this issue or will it be handled in follow-up?

voleger’s picture

Deprecation should include replacement of usage.

naveenvalecha’s picture

StatusFileSize
new81.34 KB
new78.03 KB

Replaced the usage of deprecated constants.

voleger’s picture

+++ b/core/lib/Drupal/Core/Extension/module.api.php
@@ -898,7 +899,7 @@ function hook_updater_info_alter(&$updaters) {
- * If a requirement has a severity of REQUIREMENT_ERROR, install.php will abort
+ * If a requirement has a severity of Requirements::SEVERITY_ERROR, install.php will abort

@@ -912,7 +913,7 @@ function hook_updater_info_alter(&$updaters) {
- * Moreover, any requirement with a severity of REQUIREMENT_ERROR severity will
+ * Moreover, any requirement with a severity of Requirements::SEVERITY_ERROR severity will

This two lines reached 80 chars limit.

voleger’s picture

Status: Needs review » Needs work
mradcliffe’s picture

Issue tags: +Novice, +Seattle2019

Adding some tags to hopefully get more eyes on this today in seattle.

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
Status: Needs work » Needs review
StatusFileSize
new81.62 KB

Rerolled the patch & comments addressed in #11.

naveenvalecha’s picture

@yogeshmpawar
Thanks for rerolling. please provide the interdiff.

yogeshmpawar’s picture

@naveenvalecha - your patch failed to apply on 8.8.x branch.

yogeshmpawar’s picture

StatusFileSize
new2.41 KB

@naveenvalecha - Please find the attached interdiff file between #10 & #15.

yogeshmpawar’s picture

StatusFileSize
new1.61 KB
berdir’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Requirements.php
@@ -0,0 +1,30 @@
+  /**
+   * Requirement severity -- Informational message only.
+   */
+  const SEVERITY_INFO = -1;

sorry if I'm repeating a discussion that happened before.

I'm wondering if we still need the "Requirement severity --" prefix here. Seems pretty self-explaining, we are on the requirements class and the constant is prefixed with SEVERITY_..

+++ b/core/lib/Drupal/Core/Extension/module.api.php
@@ -898,8 +899,8 @@ function hook_updater_info_alter(&$updaters) {
  * As a consequence, install-time requirements must be checked without access
  * to the full Drupal API, because it is not available during install.php.
- * If a requirement has a severity of REQUIREMENT_ERROR, install.php will abort
- * or at least the module will not install.
+ * If a requirement has a severity of Requirements::SEVERITY_ERROR, install.php
+ * will abort or at least the module will not install.

@@ -932,10 +933,10 @@ function hook_updater_info_alter(&$updaters) {
  *   - severity: The requirement's result/severity level, one of:
- *     - REQUIREMENT_INFO: For info only.
- *     - REQUIREMENT_OK: The requirement is satisfied.
- *     - REQUIREMENT_WARNING: The requirement failed with a warning.
- *     - REQUIREMENT_ERROR: The requirement failed with an error.
+ *     - Requirements::SEVERITY_INFO: For info only.
+ *     - Requirements::SEVERITY_OK: The requirement is satisfied.
+ *     - Requirements::SEVERITY_WARNING: The requirement failed with a warning.
+ *     - Requirements::SEVERITY_ERROR: The requirement failed with an error.
  */

In hook documentation/examples, we usually use the full namespace for classes, same for docs.

At the same time, repeating the constants here seems not that useful, especially since we duplicate the documentation with less information than on the class. I'm wondering if it would be sufficient to just say "One of the severity constants of the \Drupal\Core\Requirements class".

jhodgdon’s picture

@berdir asked me to comment on his review in #20:
- I agree that we probably don't need to have "Requirement severity --" in documentation of a constant called Requirements::SEVERITY_* in a Requirements class. But maybe we could make the messages clearer, something like "Indicates an informational message from a requirements check" and "Indicates the requirement is satisfied"?
- It is true that all class mentions in documentation should have namespaces.
- I agree with the suggestion of not duplicating documentation too -- it makes it hard to maintain. So, "One of the severity constants of the \Drupal\Core\Requirements class" for the hook docs sounds good.... Or maybe "One of the SEVERITY_* constants from the \Drupal\Core\Requirements class" would be even clearer?

I also took a quick look at the patch in #15, and have a few other comments:
a) Make sure to use the namespace in docs in other spots in core/lib/Drupal/Core/Extension/module.api.php too

b)

+++ b/core/lib/Drupal/Core/Requirements.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Drupal\Core;
+
+/**
+ * Defines requirements related constants for use with Drupal.
+ */

Should be "requirements-related" (hyphenated).

c)

+++ b/core/modules/system/src/SystemManager.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Menu\MenuLinkInterface;
 use Drupal\Core\Menu\MenuTreeParameters;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Requirements;
 use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
@@ -52,17 +53,17 @@ class SystemManager {
   /**
    * Requirement severity -- Requirement successfully met.
    */
-  const REQUIREMENT_OK = 0;
+  const REQUIREMENT_OK = Requirements::SEVERITY_OK;
 
   /**
    * Requirement severity -- Warning condition; proceed but flag warning.
    */
-  const REQUIREMENT_WARNING = 1;
+  const REQUIREMENT_WARNING = Requirements::SEVERITY_WARNING;
 
   /**
    * Requirement severity -- Error condition; abort installation.
    */
-  const REQUIREMENT_ERROR = 2;
+  const REQUIREMENT_ERROR = Requirements::SEVERITY_ERROR;
 

This seems like very weird code to me. Why is the Requirements class final, when it looks like this class really wants to extend it? Or should this class just use the constants from the other class and deprecate those class members? But maybe you discussed this already, I haven't read the other issue comments.

tatarbj’s picture

Issue tags: +DrupalCampBelarus2019
aardwolf’s picture

Status: Needs work » Needs review
StatusFileSize
new81.51 KB

a) Make sure to use the namespace in docs in other spots in core/lib/Drupal/Core/Extension/module.api.php
Reviewed. I think it's ok.

b) Should be "requirements-related" (hyphenated).
Changed

c)Why is the Requirements class final
Any reason to extend this class?

aardwolf’s picture

StatusFileSize
new71.42 KB
new71.42 KB

Sorry for uncompatible IDEA patch file. Reroll with clean diff.

aardwolf’s picture

StatusFileSize
new81.62 KB

Fixed missing Requirements.php in patch file. Reroll.

Status: Needs review » Needs work

The last submitted patch, 25: 2909480-25.patch, failed testing. View results

yogeshmpawar’s picture

Status: Needs work » Needs review

All looks good so setting back to Needs Review! Tests failure is not related (see #3055648: Frequent random fail in \Drupal\Tests\media_library\FunctionalJavascript\MediaLibraryTest).

voleger’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Requirements.php
@@ -0,0 +1,30 @@
+  /**
+   * Requirement severity -- Informational message only.
+   */
...
+  /**
+   * Requirement severity -- Requirement successfully met.
+   */
...
+  /**
+   * Requirement severity -- Warning condition; proceed but flag warning.
+   */
...
+  /**
+   * Requirement severity -- Error condition; abort installation.
+   */

At least : or - would be better than --

Also, Requirement severity sounds weird. I think Severity level will be more clear there. Because code reads exactly like Requirements::SEVERITY_<level>

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
Status: Needs work » Needs review
StatusFileSize
new81.59 KB
new934 bytes

Addressed comment in #28 & added interdiff as well.

voleger’s picture

Status: Needs review » Needs work

Typically, : used without blank space before the symbol.

yogeshmpawar’s picture

Status: Needs work » Needs review
StatusFileSize
new81.59 KB
new902 bytes

Addressed comment in #31 & added interdiff as well.

Status: Needs review » Needs work

The last submitted patch, 32: 2909480-32.patch, failed testing. View results

yogeshmpawar’s picture

Status: Needs work » Needs review

All looks good so setting back to Needs Review! Tests failure is not related (see #3055648: Frequent random fail in \Drupal\Tests\media_library\FunctionalJavascript\MediaLibraryTest).

voleger’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me. +1 for rtbc

jhodgdon’s picture

Status: Reviewed & tested by the community » Needs work

In core/lib/Drupal/Core/Extension/module.api.php ...

Technically, if you refer to a class in documentation, you are supposed to give its full namespace. So instead of

+ * If a requirement has a severity of Requirements::SEVERITY_ERROR, install.php
+ * will abort or at least the module will not install.

it should say \Drupal\Core\Requirements::SEVERITY_ERROR.

Similarly elsewhere in the patch. See
https://www.drupal.org/docs/develop/standards/api-documentation-and-comm...
for where this documentation standard is written down.

aardwolf’s picture

StatusFileSize
new81.47 KB

you are supposed to give its full namespace

changed.

aardwolf’s picture

StatusFileSize
new81.47 KB

Reupload

aardwolf’s picture

StatusFileSize
new81.45 KB

Reupload

jhodgdon’s picture

StatusFileSize
new2.11 KB

Thanks for the new patch!

A few notes:

a) When you make a new patch on an issue that already had a patch, please make an interdiff file. I made one this time (see attached). Here are instructions on how to make an interdiff:
https://www.drupal.org/documentation/git/interdiff

b) When you attach a patch, set the issue status to "Needs review". That will automatically launch a test (I assume you did one manually?) and alert reviewers that there is a patch to review.

c) Regarding the new patch, all documentation needs to wrap at under-80 character lines. Several of the lines you added are now quite a bit longer than 80 lines, so they need to be rewrapped. So, leaving the status at "Needs work".

As a note, when wrapping lines within a list, the wrapped section should be indented so that the text starts at the same place as the previous line. So it will look something like this (but with lines extending to as close to 80 characters as possible):

 * Some documentation that starts a list:
 * - List item 1. Assume this was long
 *   and needed to be wrapped. And started a sublist:
 *   - Sublist item 1. Assume this was long too
 *     and also needed to be wrapped.
pingwin4eg’s picture

Assigned: Unassigned » pingwin4eg
Issue tags: +dckyiv2019
pingwin4eg’s picture

Assigned: pingwin4eg » Unassigned
StatusFileSize
new80.77 KB
new2.99 KB

Looks like the rest.install does not use requirements anymore. Removed it's changes from the patch. Fixed comments.

BTW, maybe we should make an interface instead of a final class? Sorry, if it's documented somewhere and I missed it.

pingwin4eg’s picture

Status: Needs work » Needs review
pingwin4eg’s picture

StatusFileSize
new80.77 KB
new3.36 KB

Here's the same as above, but using an interface. Just in case.

voleger’s picture

+1 for the interface.
Still wondering... Should the SEVERITY be a part of the interface name? The Requirements name sounds generic and on the other hand RequirementsSeverity (or something similar) - more specific.

voleger’s picture

StatusFileSize
new82 KB

Oh, just ignore the #45 thoughts about naming. Anyway, this will be merged with other constants into a single Requirements class (regarding to #2908079: Move some of the bootstrap.inc PHP-related constants to \Drupal and deprecate the old versions) And regarding interface, that requires to follow the CS of the interface naming with suffix "Interface". So I don't think that it would look great.

Tested the #44 patch. It does not apply anymore. Reroll.

acbramley’s picture

Issue tags: -Needs change record
StatusFileSize
new80.95 KB

Rerolled and removed some changes to content_moderation.install and workspaces.install as those requirements were removed! Also added 1 that was missing from media.install. No interdiff due to the considerable difference in the reroll.

I've checked phpcs and manually checked all documentation added to ensure no lines are longer than 80 characters so this should be good to RTBC now!

EDIT: CR was drafted back in #8 https://www.drupal.org/node/3047376

kim.pepper’s picture

Status: Needs review » Reviewed & tested by the community

LGTM!

jhodgdon’s picture

+1. Docs look good.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

In #2908079: Move some of the bootstrap.inc PHP-related constants to \Drupal and deprecate the old versions I've pushed back on adding \Drupal\Core\Requirements because it's a very generic namespace that risks making core/lib/Drupal/Core a dumping ground for things that we don't know where to put.

I have a couple of thoughts on this issue.

I feel this is OO-ification for OO-ification's sake. We're only moving the constants so they can be autoloaded. But a proper redesign of the requirements system might end up with Requirement value objects that makes these constants redundant - imagine $requirement->isError() etc...

If what we want to solve autoloadability of constants there's another way. We could add core/constants.php to our autoloader in the files section and repeating myself from the other issue the advantages are

  • there's no deprecation
  • the constants become available to autoloaded code
  • as constants.php grows it becomes a place to learn about all the core provided constants

The one downside is this approach is only available to core and not core modules/themes, or contrib or custom because they don't using composer to set up their autoloading. But I'm not sure that outweighs the advantages listed.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

mradcliffe’s picture

I'm adding the Needs issue summary update tag so that the issue summary includes the different approaches suggested by @alexpott in comment #50.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

andypost’s picture

daffie’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

The patch needs a reroll.

vsujeetkumar’s picture

Status: Needs work » Needs review
StatusFileSize
new81.71 KB

Re-roll patch created for 9.1.x

vsujeetkumar’s picture

StatusFileSize
new81.7 KB

Ignore previous one, Please review this.

kim.pepper’s picture

Status: Needs review » Needs work

@vsujeetkumar You have some invalid PHP.

PHP Parse error:  syntax error, unexpected '}' in /var/www/html/core/modules/system/system.install on line 337
xargs: php: exited with status 255; aborting

For local development, you can check for valid PHP on any files that are have been modified from the 9.1.x branch using the following handy snippet:

git diff 9.1.x --name-only --diff-filter=AM | grep 'php' | xargs -n1 -P8 php -l

vsujeetkumar’s picture

Status: Needs work » Needs review
StatusFileSize
new81.7 KB

Fixed php syntax issue, Please review.

Status: Needs review » Needs work

The last submitted patch, 59: 2909480_59.patch, failed testing. View results

acbramley’s picture

@vsujeetkumar it doesn't look like #59 is a reroll of #47?

acbramley’s picture

+++ b/core/includes/install.inc
@@ -11,28 +11,52 @@
+ * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0.
+ *   Use \Drupal\Core\Requirements::SEVERITY_WARNING instead.

This message is now wrong. I believe it should be "deprecated in 9.1.0 and removed in 10.0.0"? I could be wrong though...

kim.pepper’s picture

kishor_kolekar’s picture

Assigned: Unassigned » kishor_kolekar
kishor_kolekar’s picture

Assigned: kishor_kolekar » Unassigned
jhodgdon’s picture

Also alexpott's comment in #50 has still not been addressed, so there is not really a lot of point in rerolling this patch over and over until we figure out what we're actually doing.

jpatel657’s picture

Assigned: Unassigned » jpatel657
Status: Needs work » Active
jpatel657’s picture

Assigned: jpatel657 » Unassigned
andypost’s picture

Status: Active » Needs work

Repair status

voleger’s picture

Symfony has its own requirement checker https://github.com/symfony/requirements-checker

What about to implement requirement checks based on the Symfony package?

andypost’s picture

Re #70 this class looks outdated https://github.com/symfony/requirements-checker/blob/master/src/SymfonyR...

Moreover it will need to override more then it provides

ravi.shankar’s picture

Issue tags: -Needs reroll

Removed needs reroll tag.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

jhodgdon’s picture

Issue summary: View changes
Issue tags: -Novice, -Needs issue summary update

Given comment #50, this is not a Novice task. Also updating issue summary with note from #50.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

Nowadays idea of discovery Requirement objects could use attributes to define title, value and description.
Other similar kind of checks/tasks install system has, so approach from #50 sounds viable

+++ b/core/lib/Drupal/Core/Render/Element/StatusReport.php
@@ -35,13 +37,13 @@ public static function preRenderGroupRequirements($element) {
     $severities = static::getSeverities();
...
-      $severity = $severities[REQUIREMENT_INFO];
+      $severity = $severities[Requirements::SEVERITY_INFO];
...
-        $severity = $severities[REQUIREMENT_OK];
+        $severity = $severities[Requirements::SEVERITY_OK];
...
       $grouped_requirements[$severity['status']]['title'] = $severity['title'];

+++ b/core/lib/Drupal/Core/Requirements.php
@@ -0,0 +1,30 @@
+final class Requirements {

it could be enum but it actually used only to group requirements

voleger’s picture

Seems like we have an issue that already has some work done in that way #2909472: Add value objects to represent the return of hook_requirements

andypost’s picture

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

nicxvan made their first commit to this issue’s fork.

nicxvan’s picture

I am going to work on this because we need these constants for hook_update_requirements and hook_runtime_requirements.

The one downside is this approach is only available to core and not core modules/themes, or contrib or custom because they don't using composer to set up their autoloading. But I'm not sure that outweighs the advantages listed.

Since these classes are used in core, contrib, and custom, I think this disqualifies the constants.php approach.

However, we don't actually have to deprecate these here, I think we can do that when we deprecate hook_requirements, for now we can just create the new classes and just use them as we convert hooks.

andypost’s picture

Deprecation suppose removal of the usage, 240LOC surely needs chunking

git grep REQUIREMENT_ |wc -l
241

nicxvan’s picture

Yes, I wouldn't create the deprecation here, just create the new landing place for constants and the new constants we need.

I wonder if there is a way to have both.

E,g. something like
/Drupal/Core/Constants
That is where the constants live, you can use it if you need it.
Maybe it makes sense to auto load it so they are available everywhere that uses autoloading.

nicxvan’s picture

I am not going to work on this at the moment, I think @berdir found a clean workaround, I think my comments about constants.php are still valid.

voleger’s picture

dww’s picture

I keep adding @todo comments to core MRs with @see pointing here. We really need a better solution than manually including install.inc, or worse, using loadInclude($module, 'install') to get it to happen magically. 😂

kim.pepper’s picture

I'm working on rebasing this. Now most of the hooks are converted to OOP we can see what is left over.

Oops commented on wrong issue. I'm actually working on rebasing #3410938: Create enums for RequirementSeverity and deprecate drupal_requirements_severity() constants

kim.pepper’s picture

kim.pepper’s picture

kim.pepper’s picture

I think this can be closed as #3410938: Create enums for RequirementSeverity and deprecate drupal_requirements_severity() constants went in which deprecates the REQUIREMENT_* constants.

andypost’s picture

Status: Needs work » Closed (duplicate)

thank you!