Convert function_exists() to is_callable()

Created on 22 April 2025, 3 months ago

Problem/Motivation

From the originating issue 🌱 [Policy, no patch] Normalize on usage of is_callable() instead of function_exists() Needs review

Instead of using function_exists() to verify if a callback exists, Drupal could use is_callable(); this would allow to use object and class methods as callbacks.

Steps to reproduce

Proposed resolution

Convert function_exists() to is_callable()

Remaining tasks

Create MR
It is possible that this may need to be broken

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

📌 Task
Status

Active

Version

11.0 🔥

Component

other

Created by

🇳🇿New Zealand quietone

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

Comments & Activities

  • Issue created by @quietone
  • 🇮🇳India annmarysruthy

    @quietone Should we replace all existences of function_exists() with is_callable() ?

  • 🇳🇿New Zealand quietone

    @annmarysruthy, I think each usage needs to be examined. For example, the usages in tests should probably not change, In may turn out that there are no places where making this change is an improvement. I have not looked closely at all the instances.

  • @annmarysruthy opened merge request.
  • 🇮🇳India annmarysruthy

    Checked all occurrences of function_exists() and changed 6 files. In my opinion, Rest of the occurrences are better kept as function_exists() itself. Kindly review MR

  • 🇺🇸United States nicxvan

    This looks great! I have to review more closely, but this already covers the three I was reviewing.

  • 🇫🇷France andypost

    curious to compare performance of both methods

  • 🇺🇸United States nicxvan

    I'd take another look at EntityResolverManager.

  • 🇺🇸United States nicxvan

    Found some more hooks to exclude.

  • 🇺🇸United States nicxvan

    For 11.

  • Status changed to Needs work 5 days ago
  • 🇺🇸United States nicxvan

    Ok I am going through this and here are the criteria

  • 🇺🇸United States nicxvan
  • 🇬🇧United Kingdom alexpott 🇪🇺🌍

    I don't think we should be changing the string ones here. It's pointless and I think should be address in the issue that does the change.

  • 🇺🇸United States nicxvan

    I agree, that is the first bullet point, sorry if that wasn't clear.

    If it is called on a string we know it's a function and we can address it when we convert the function itself

  • 🇺🇸United States nicxvan

    Ok I did the evaluation, it could use confirmation, I've attached it.

    I ran this command to get a list of function_exists calls
    grep -rn "function_exists" core > functionExistsCallsLine.txt

    I then removed comments and broke it into three categories:

    • Actionable (here or in a follow up)
    • Procedural hooks, update, install, legacy invoke or theme related
    • strings or library functions like is_file

    Here is the list of actionable ones, I wasn't sure about the css test.
    Category 1 Actionable
    core/modules/views/src/Plugin/views/HandlerBase.php:572: if (isset($this->definition['access callback']) && function_exists($this->definition['access callback'])) {
    core/includes/form.inc:955: if (($function = $batch['redirect_callback']) && function_exists($function)) {
    core/modules/comment/src/CommentManager.php:210: if (function_exists($function)) {
    core/modules/views_ui/src/ViewUI.php:341: $cancel_submit = function_exists($form_id . '_cancel') ? $form_id . '_cancel' : [$this, 'standardCancel'];
    core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php:298:if (!function_exists('Drupal\Core\Asset\file_uri_scheme')) {
    core/lib/Drupal/Core/Entity/EntityResolverManager.php:93: if (function_exists($controller)) {

Production build 0.71.5 2024