Hi

I've got a D7 module that's using namespaced classes to perform all module heavy lifting (similar to that seen here). It depends on XAutoload for the PSR-4 class loading features. Here is the layout of said module:

root
├── my_module.info
├── my_module.install
├── my_module.module
├── my_module.views.inc
└── src
    ├── Controller.php
    ├── Forms.php
    └── Utilities.php

Everything works fine and well, until I get to callbacks. My Forms class has a function to add a cancellation button on the behalf of a calling hook (such as hook_form_FORM_ID_alter). Here is the current structure of said function. As you can see, I'm attempting to invoke a static class function as my callback:

namespace Drupal\my_module;
/**
 * Provides reusable functions that make modifications via the Forms API.
 */
class Forms {
  // ... truncated...
  public static function add_cancellation_button(&$form, &$form_state, $form_id) {
    $form['buttons']['cancel'] = array(
      '#type' => 'submit',
      '#value' => 'Cancel',
      '#submit' => array(
        __NAMESPACE__ . '\\Forms::cancel_button_submit',
      ),
      '#limit_validation_errors' => array(),
    );
  }
  // ... truncated...
  public static function cancel_button_submit(&$form, &$form_state, $form_id) {
    //do some stuff
  }
  // ... truncated...
}

There are many examples of this on the web (including the one linked to above), but upon clicking on this in the interface, I get the following:

Call to undefined function Drupal\my_module\Forms::cancel_button_submit() in /var/www/sandy_prod_current/includes/form.inc on line 1513

.

Might you have any idea what the problem might be here? I'm guessing that XAutoloader isn't being invoked properly to allow the class to be found by includes/form.inc, but I wanted to ask in case you knew of another reason it might be failing to find the class in question. I'll note that XAutoloader is loading the classes correctly in the course of normal operations - it is only during callbacks where the failure occurs.

Comments

donquixote’s picture

This is not xautoload's fault, but how the function is called in Drupal core.

Minimal example: http://3v4l.org/512JH

class C {
  static function foo() {}
}

$callback = 'C::foo';
$callback();

Fatal error: Call to undefined function C::foo()

donquixote’s picture

You could use a trick to work around this limitation.

// Not sure about the signature.
function mymodule_submit_helper($element) {
  $callback = $element['#mymodule_submit_callback'];
  call_user_func($callback, $element);
}

$element['#submit'][] = 'mymodule_submit_helper';
$element['#mymodule_submit_helper'] = array('Drupal\my_module\Forms', 'cancel_button_submit');

This has some limitations obviously, but it is something you can play with.

aron.beal’s picture

Thanks for the illustration, and of the example solution. I hate to use an intermediary workaround, but your example shows its necessity, and we need to develop for the world we're in, not the one we wish we had. It is ironic that such a truth was pointed out to me by someone with your nickname, however. :)

Again, appreciate the help.

donquixote’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.