Create class to replace hook_install_requirements

Created on 1 December 2024, about 2 months ago

Problem/Motivation

Hook requirements uses phase right now to manage whether it is runtime, install, or update.
Let's move the install portion to a class so we can inject some services and more easily test them.

Steps to reproduce

N/A

Proposed resolution

Create InstallRequirements class
Should this go in src/Requirements/Install/Classname
This should fire right after the current hook_requirements

Remaining tasks

Create class
Create tests

User interface changes

N/A

Introduced terminology

InstallRequirements

API changes

New class InstallRequirements you can use to check requirements on update.
Identify which types of services that can be injected.

Data model changes

Release notes snippet

πŸ“Œ Task
Status

Active

Version

11.0 πŸ”₯

Component

base system

Created by

πŸ‡ΊπŸ‡ΈUnited States nicxvan

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @nicxvan
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • Merge request !10481Add OOP Install requirements β†’ (Open) created by nicxvan
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • Pipeline finished with Canceled
    about 2 months ago
    #361676
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • Pipeline finished with Failed
    about 2 months ago
    Total: 5291s
    #361684
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • Pipeline finished with Canceled
    about 2 months ago
    Total: 130s
    #361710
  • Pipeline finished with Running
    about 2 months ago
    #361711
  • Pipeline finished with Canceled
    about 2 months ago
    Total: 386s
    #362057
  • Pipeline finished with Failed
    about 2 months ago
    Total: 127s
    #362069
  • Pipeline finished with Failed
    about 2 months ago
    Total: 179s
    #362080
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • Pipeline finished with Failed
    about 2 months ago
    Total: 513s
    #362084
  • πŸ‡¬πŸ‡§United Kingdom catch

    Makes sense to move this to a hard-coded class instead of a hard-coded function name, I don't there's anything else we can do in install.

    However the MR is missing some hook_requirements() which affect mutliple phases, such as in package_manager_requirements()

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    That was considered, I'll update the meta to add more details, but here is the gist.

    We replace the $phase = 'install' portion with this issue.

    We replace the $phase = 'update' with πŸ“Œ Create class to replace hook_update_requirements Active

    And we replace the $phase = 'runtime' with πŸ“Œ Create hook_runtime_requirements Active

    Once we have all three this covers most cases, but for more complex hook_requirements like system and package_manager with multiple phases we convert in a follow up.

    Once core is converted we deprecate hook_requirements being called without LegacyHook being attached.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • πŸ‡¬πŸ‡§United Kingdom joachim

    > Makes sense to move this to a hard-coded class instead of a hard-coded function name, I don't there's anything else we can do in install.

    The problem with these hooky-classes, like this and ModulePascalServiceProvider is that unlike hooks, we have no standard for documenting them.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    We can document it on the interface, which is where I put it, it definitely needs some fleshing out, but it's there.

    If you mean the implementation side then we can just document the classes implementing it.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan
  • πŸ‡¬πŸ‡§United Kingdom joachim

    That's good, but we'd still be losing the discoverability of it in the documentation as an API.

    With hooks, there is a @hooks topic that explains the concept and lists the API elements. With HookyClasses, you only learn of a particular class if you happen to stumble on it.

  • πŸ‡¬πŸ‡§United Kingdom joachim

    Oops, didn't mean to change status.

    Though I'm confused why the other two replacements of this hook are hooks, but this one is a class? What's the difference?

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    I still think 18 is a separate issue and not a blocker. For 19 there are two reasons:
    1 the other two are invoked by module handler so we can just change the hook.
    2 this one happens during Drupal or module install is to early.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    This is ready to review again, the concerns on the meta have been resolved.

  • πŸ‡¬πŸ‡§United Kingdom joachim

    > I still think 18 is a separate issue and not a blocker.

    Every time we say this we are eroding the quality of our documentation. Each time it's a small separate issue and not a blocker, but these keep adding up.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    I'm happy to work on wording in a sibling issue if you create it, I think it would belong in a subpage here: https://www.drupal.org/docs/getting-started/system-requirements β†’

  • First commit to issue fork.
  • Pipeline finished with Canceled
    13 days ago
    Total: 70s
    #390118
  • Pipeline finished with Canceled
    13 days ago
    Total: 69s
    #390121
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Applied some nitipicky stuff but reviewed the rest of the changes and nothing seems off to me.

    Thanks for the CR updates we mentioned in slack.

    I did open πŸ“Œ How to best handle documentation around new OOP hooks Active as a child of the META and tagged it as a 11.2 release priority.

  • Pipeline finished with Success
    13 days ago
    Total: 466s
    #390125
  • πŸ‡¬πŸ‡§United Kingdom alexpott πŸ‡ͺπŸ‡ΊπŸŒ

    I think we should not be doing this. Creating another way to load code from a module that is not installed feels like we are perpetuating the problems of hook_requirements() with the install phase.

  • πŸ‡¬πŸ‡§United Kingdom alexpott πŸ‡ͺπŸ‡ΊπŸŒ

    Added some comments to the MR. But I think we should explore reading the modules composer file and check that instead of doing this.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    Those are good ideas I can update this later.

    I still think we should do this for the reasons stated in in the meta, particularly it's easier for people to know each has a phase somewhere to go. We can mention in the CR that it is preferred to use composer and a link to the issue to watch, and that this is intended as a bridge.

  • Pipeline finished with Failed
    11 days ago
    Total: 212s
    #392633
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    Ok I addressed all of your feedback I agree it looks cleaner.

    I did copy the class load from the drupal_check_profile, is that a separate concern?

  • Pipeline finished with Success
    11 days ago
    Total: 5984s
    #392634
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    Setting it back to needs review because I addressed the feedback and it's green.

    I'm going to update my comment on the meta.

  • πŸ‡¬πŸ‡§United Kingdom joachim

    > I think it would belong in a subpage here: https://www.drupal.org/docs/getting-started/system-requirements β†’

    Putting some documentation on d.org is great, but that's still a worsening of what we have. Hooks are in-code, and most importantly, *systematic*.

    You look at this:

     * Implements hook_requirements().
    

    and hook_requirements() is obvious as a thing that you can look for. API module handles it automatically to link up the specific instance to the general documentation for the component.

    You go to the hook_requirements() documentation, and you see it's in the @hooks group. API module makes this a link.

    You go to the @hooks group topic, and that explains what hooks are as a type of extension point. API module lists all of the hooks that exist.

    But with something like:

    class MyModuleServiceProvider
    

    we have currently at best an interface. It doesn't tell you the class must be magically name, and it doesn't connect to the other extension points that behave in the same way.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    As a counterpoint, I think it is far more standard to look at the interface something is extending and have the documentation there.

    That documentation tells you that it must be magically named.

    The implements piece is something the community is used to but you either have to leave the ide to find docs or you have to know to search for function hook_requirements otherwise search results are flooded with other implementations.

    Also implements comments can be wrong or missing, extend can't be.

    Again finding other implementations of a hook either requires leaving your ide, knowing regex, or the implementors perfectly following the naming scheme for a comment.

    Finding classes implementing an interface is mostly built in to ides and something people beyond the community are used to too.

    I agree having docs outside the ide is helpful which is why I suggested that docs pages, other suggestions are welcome.

    If you're looking for a way to document classes implementing an interface the issue smustgrave created is probably the place to discuss that process and what is needed. It should probably be moved to api and retitled to focus on this use case since we already have one for hooks specifically.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    @alexpott, I addressed your feedback and created the followup here: πŸ“Œ Remove class_loader in drupal_check_profile Active .

  • Pipeline finished with Success
    10 days ago
    Total: 1278s
    #393194
  • Pipeline finished with Success
    10 days ago
    Total: 1296s
    #393237
  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    I agree that it would be nice if we can get rid of most* install requirements hooks but that requires multiple new features (other modules, extensions, composer dependencies, conflicts), not all of which can be composer (we can't use composer conflict because we can not and don't want to prevent them being present, it's about them being installed or not).

    hook_requirements() is the last remaining "regular" hook (there's just preprocess and special install/update stuff then). If we have that and preprocess done we can drop that stop parsing attribute and so on. modules are either fully converted or not, no weird middle ground.

    In other words, it would be very nice to find a way to deal with it. I was thinking we could just keep hook_requirements with phase install for now until we see what's left once we improve other things. But I think that's hard to deprecate and detect allowed implementations vs not, we can't introspect what $phase it has and what it does with it.

    On the class name: Do we really need to prefix it with a camel-cased moduel name? Yes, we do it for ServiceProvider, but it's namespaced anyway. Yes, we'd have 5,10, ... "InstallRequirements" classes, but is that really a problem?

    That's the only part I agree with from #31. Everyhing else I very much don't. As #32 said, what #31 describes is like 4 different Drupalisms that nobody else uses and new developers don't know about. Nobody except Drupal uses a .install file. Nobody else has an api module, api.drupal.org only provides info on core, it requires a Drupal-aware IDE like PHPStorm or knowing what to search for to maybe find the hook_requirements() documentation and understanding the *magically named* hook functions. Now you need to look at src/ (where _all_ code will be soon enough), where there might be an Install folder and then a Requirements class inside. Looking up the interface is standard PHP stuff, documentation on that is standard PHP stuff. To me, that is way better DX, especially for developers that don't know Drupal. And we want and must attract new developers.

    That said, if we're not sure yet if this has a future, we could also just rename it to hook_install_requirements(), but then we have to explain that this is very different from the other two split requirements hooks. I'd prefer a class but I don't care too much. What I do care about is being able to forget about as soon as possible.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    On the class name: Do we really need to prefix it with a camel-cased moduel name? Yes, we do it for ServiceProvider, but it's namespaced anyway. Yes, we'd have 5,10, ... "InstallRequirements" classes, but is that really a problem?

    Yes, we cannot autoload it so there is no way to find it without knowing the naming convention unless you have a different idea.

  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    > Yes, we cannot autoload it so there is no way to find it without knowing the naming convention unless you have a different idea.

    My naming convention suggestion is only and always name it "InstallRequirements", nothing dynamic. It's namespaced, it doesn't need to have a prefix. Downside is that there will be a bunch of classes with that name, but the long term plan is removing all/most of them.

Production build 0.71.5 2024