Problem/Motivation

it is currently only possible to define a function as #ajax callback.
When you use the #ajax property "callback" to define what should be executed, it's not possible to address object methods.

This patch would make it possible to assign object methods as that callback.

Proposed solution

We should change from function to functions and object methods. Core already has a way to pass variables by reference to call_user_func_array, so that approach can be used here as well.

I added this issue as task, since field_ui module will actually use this. See #1792600: Refactor field_ui so common behavior for fields and display overview screens are extracted. That issue is not blocked but it would be very nice to use the DisplayOverview object to handle the multistep configurations.

Code

I'll add the code here as well as it is such a small patch and much easier to review.

  if (!empty($callback) && is_callable($callback)) {
    return call_user_func_array($callback, array(&$form, &$form_state));
  }
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Stalski’s picture

Status: Needs work » Needs review
FileSize
570 bytes

The patch

Stalski’s picture

#1: 1802072-1.patch queued for re-testing.

fubhy’s picture

Status: Needs review » Reviewed & tested by the community

That makes sense...

webchick’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

Hm. Let's add a test for this. I tried grepping through #1792600-29: Refactor field_ui so common behavior for fields and display overview screens are extracted and it was not immediately clear to me how this would work.

I'm a little worried here too about changing AJAX callback to any "is_callable" but not doing this consistently throughout FAPI. But I'm not sure what other similar things we have there, really. I guess submit, process, and validate callbacks? Normally these are done as an array of functions that can be re-ordered.

yched’s picture

$form['#submit'] and #validate are already doable as "methods" (entity form controller uses that)
#element_validate, #pre_render, #after_build... are not

fubhy’s picture

Assigned: Stalski » fubhy

I'm a little worried here too about changing AJAX callback to any "is_callable" but not doing this consistently throughout FAPI. But I'm not sure what other similar things we have there, really. I guess submit, process, and validate callbacks? Normally these are done as an array of functions that can be re-ordered.

That doesn't change in any way. But yes, all callbacks in FAPI should get converted to support methods at some point. Yes, we could maybe add a simple test that exposes a method as an ajax callback. Basically we would be testing core PHP functionality with that considering that the patch doesn't change anything apart from the switch to is_callable() :). But then again, it won't hurt... So why not :).

Brb

Stalski’s picture

Well actually the reason why I did not saw the need for a test is because when field_ui OOPize patch is in, the multistep field instance create test will cover this behavior, see #1792600: Refactor field_ui so common behavior for fields and display overview screens are extracted.
Isn't that sufficient?

fubhy’s picture

Status: Needs work » Needs review
FileSize
3.97 KB

That should do. I simply converted two of the callbacks to be methods in one of the existing AJAX tests.

fubhy’s picture

Assigned: fubhy » Unassigned
fubhy’s picture

FileSize
3.96 KB

Whoops, class name f*ckup :)

The last submitted patch, 1802072-10.patch, failed testing.

fubhy’s picture

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

#10: 1802072-10.patch queued for re-testing.

swentel’s picture

Note, as a follow up - #element_validate would be a nice one to convert as well - it would make some field widgets more sane, but let's get this one in first.

swentel’s picture

Status: Needs review » Reviewed & tested by the community

Thanks fubhy!

fubhy’s picture

webchick’s picture

Status: Reviewed & tested by the community » Needs work

Same feedback as #1805688-8: Support methods as #element_validate callbacks; we need to pull that class out to a separate PSR-0 compatible file, and document it.

fubhy’s picture

FileSize
3.15 KB

Yeaah... umh :D

fubhy’s picture

Status: Needs work » Needs review
fubhy’s picture

FileSize
4.58 KB

Forgot to add the new file.

fubhy’s picture

FileSize
4.55 KB

Wow, t'is early in the morning :/

Stalski’s picture

Status: Needs review » Reviewed & tested by the community

Thx for the improvement. Looking good and a good thing we have tests for it!

webchick’s picture

Title: Ajax callbacks should be callbacks defined as function or class method » Change notice: Ajax callbacks should be callbacks defined as function or class method
Priority: Normal » Critical
Status: Reviewed & tested by the community » Active
Issue tags: -Needs tests +Needs change record

Awesome, thanks!

Committed and pushed to 8.x.

We'll need a change notice for this; can likely just be added to the existing FAPI one.

fubhy’s picture

Status: Active » Needs review
swentel’s picture

Title: Change notice: Ajax callbacks should be callbacks defined as function or class method » Ajax callbacks should be callbacks defined as function or class method
Priority: Critical » Normal
Status: Needs review » Fixed

Looks good.

fubhy’s picture

Did I miss something? I don't see the commit!

@webchick I think you might have forgot to push this one. Maybe because the two issues for the patches that needed to be commited are nearly identical :)

fubhy’s picture

Priority: Normal » Major
Status: Fixed » Reviewed & tested by the community
fubhy’s picture

FileSize
0 bytes

The patch doesn't apply anymore. Here is a re-roll. Yah... Or I simply upload an empty file.

fubhy’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
4.52 KB
swentel’s picture

Status: Needs review » Reviewed & tested by the community

Alright, let's get this in! :)

swentel’s picture

Issue tags: -Needs change record

Change notification is done

andypost’s picture

+++ b/core/modules/system/tests/modules/ajax_forms_test/ajax_forms_test.moduleundefined
@@ -49,7 +53,7 @@ function ajax_forms_test_simple_form($form, &$form_state) {
-      'callback' => 'ajax_forms_test_simple_form_select_callback',
+      'callback' => array($object, 'selectCallback'),

@@ -58,7 +62,7 @@ function ajax_forms_test_simple_form($form, &$form_state) {
-       'callback' => 'ajax_forms_test_simple_form_checkbox_callback',
+       'callback' => array($object, 'checkboxCallback'),

maybe leave one as was before?

fubhy’s picture

Well, why not. To me it is actually not really clear why we need a test for this at all. I mean it really just is a test for is_callable() vs is_function(). We should assume that both work properly :).

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Hm. No, it appears I didn't commit it at all. :P Oops. :P Clearly, I need more sleep. :)

REALLY committed and pushed to 8.x this time. :P

Status: Fixed » Closed (fixed)

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