Problem/Motivation

Note: This issue refers to generic functions written as callbacks for PHP language features like uasort(), array_walk(), etc. This is not related to #1250500: [policy adopted; patch done] Find a (standard) way to document callback signatures.

From #1315992: No standard for documenting menu callbacks. Currently, documented summaries for general callbacks used with PHP core language features are very inconsistent. Some reference the function that registers the callback; others do not. Some list the actual function used with the callback; others do not. Many do not follow the standards at http://drupal.org/node/1354#functions. Examples follow.

Sorting functions

  • Function used by uasort to sort the array structures returned by drupal_add_css() and drupal_add_js().
  • Function used by uasort to sort structured arrays by weight.
  • Array sorting callback; sorts elements by title.
  • unction used by uasort to sort structured arrays by weight, without the property weight prefix
  • Array sorting callback; sorts elements by 'title' key.

Callbacks for array_walk() or array_map()

  • Helper function to strip slashes from $_FILES skipping over the tmp_name keys since PHP generates single backslashes for file paths on Windows systems.
  • (blank)

Shutdown functions

  • Shutdown function for cron cleanup.
  • Shutdown function; store the current batch data for the next request.

Proposed resolution

Provide a brief standard that:

An revised proposal for docmenting a standard is in #6.

Comments

xjm’s picture

Examples of the proposed standard:

/**                                                                                                                
 * Shutdown function: Stores the current batch data for the next request.
 *
 * @see _batch_page().
 */
function _batch_shutdown() {
/**                                                                             
 * Callback: Strips slashes from a string or array of strings.                            
 *                                                                              
 * @param $item                                                                 
 *   An individual string or array of strings from superglobals.                
 *                                                                              
 * @see fix_gpc_magic().                                                        
 */
function _fix_gpc_magic(&$item) {

/**
 * Sorting callback: Sorts structured arrays by weight.
 */
function element_sort($a, $b) {

In this final example, perhaps no documentation of parameter or return values is needed, because these are a part of the PHP standard for sorting functions.

Edited like 5 times because I copied from the wrong branch. :P

xjm’s picture

Status: Needs review » Active

First pass at the documentation follows. Edited to remove some redundancy.

Generic callback functions used with basic PHP language features

Generic callback functions used with PHP language features like usort() or array_walk() are documented as follows.

General standard for callbacks

/**
 * Callback: Strips slashes from a string or array of strings.
 *
 * You may add a longer description here.
 * 
 * @param $item
 *   An individual string or array of strings from superglobals.
 * 
 * @see fix_gpc_magic().
 */

Notes:

  • Prefix the description summary with the word Callback followed by a colon and a space.
  • After Callback: , include a standard function summary that is capitalized and begins with a third-person present indicative verb. Total line length: 80 characters, ending in "."
  • If applicable, add an @see line or lines referencing the specific function(s) that use this callback.

Array sorting callbacks

/**
 * Sorting callback: Sorts structured arrays by weight.
 *
 * You may add a longer description here.
 */

Notes:

  • Prefix the description summary with the phrase Sorting callback followed by a colon and a space.
  • No parameter or return value documentation is necessary, because these are part of the PHP requirements for sorting functions. See the PHP documentation for usort() for more information.

Shutdown functions

/**                                                                                                                
 * Shutdown function: Stores the current batch data for the next request.
 *
 * You may add a longer description here.
 *
 * @see _batch_page().
 * @see drupal_register_shutdown_function().
 */

Notes:

  • Prefix the description summary with the phrase Shutdown function followed by a colon and a space.
  • Shutdown functions in Drupal 7 and later should be registered using drupal_register_shutdown_function() rather than the base PHP register_shutdown_function(). Include an @see line referencing drupal_register_shutdown_function().
  • You should also include an @see line or lines referencing the function where this shutdown function is registered.
xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Status: Active » Needs review
xjm’s picture

Issue summary: View changes

.

xjm’s picture

Issue summary: View changes

Updated issue summary.

jhodgdon’s picture

Status: Active » Needs work

I would like to see something in the standard that makes it clear in the first line what function the callback is for. Maybe

/**
 * Sort callback for foo(): blah blah blah.

The menu callbacks from the other issue were a specific case where "xyz callback" is a specific Drupalism. These are not.

xjm’s picture

foo() being (e.g.) uasort()?

xjm’s picture

Status: Needs work » Needs review

How about this? Edit: I took out the "Sorting" part since that is clear from the rest of the line when we add the reference to uasort().

Generic callback functions used with basic PHP language features

Generic callback functions used with PHP language features like usort() or array_walk() are documented as follows.

General standard for callbacks

/**
 * Callback for array_walk(): Strips slashes from a string or array of strings.
 *
 * You may add a longer description here.
 * 
 * @param $item
 *   An individual string or array of strings from superglobals.
 * 
 * @see fix_gpc_magic().
 */

Notes:

  • Prefix the description summary with the word Callback for function(), where function() is a base PHP function that accepts a callback as a parameter. This prefix should be followed by a colon and a space.
  • After the prefix, include a standard function summary that is capitalized and begins with a third-person present indicative verb. Total line length: 80 characters, ending in "."
  • If applicable, add an @see line or lines referencing the specific function(s) that register this callback.

Array sorting callbacks

/**
 * Callback for uasort(): Sorts structured arrays by weight.
 *
 * You may add a longer description here.
 */

Notes:

  • No parameter or return value documentation is necessary, because these are part of the PHP requirements for sorting functions. See the PHP documentation for usort() for more information.

Shutdown functions

/**                                                                                                                
 * Shutdown function: Stores the current batch data for the next request.
 *
 * You may add a longer description here.
 *
 * @see _batch_page().
 * @see drupal_register_shutdown_function().
 */

Notes:

  • Prefix the description summary with the phrase Shutdown function followed by a colon and a space.
  • Shutdown functions in Drupal 7 and later should be registered using drupal_register_shutdown_function() rather than the base PHP register_shutdown_function(). Include an @see line referencing drupal_register_shutdown_function().
  • You should also include an @see line or lines referencing the function where this shutdown function is registered.
xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Just had a thought re: sorting callbacks; the return value does not need to be documented, but maybe the parameters actually do. They could be any data type, and their structure matters. (E.g. element_sort() requires an associative array that may include a '#weight' key). However, it can be said that both parameters should be the same data type. So how about this for sorting callbacks:

/**
 * Callback for uasort(): Sorts structured arrays by weight.
 *
 * You may add a longer description here.
 *
 * @param $a
 *   First item for comparison.  The compared items should be associative
 *   arrays that optionally include a '#weight' key.
 * @param $b
 *   Second item for comparison.
 */

Notes:

  • You should document the expected parameter data type and structure; however, you only need to add the description for the first parameter since they are the same.
  • No return value documentation is necessary, because it is defined in the PHP requirements for sorting functions. See the PHP documentation for usort() for more information.
jhodgdon’s picture

Can we make a generic standard that would work for any PHP function callback, rather than having to list every type we can think of?

xjm’s picture

Isn't it that already? I just mentioned the specific point about sorting callbacks because I saw a lot of dumb (or entirely missing) docblocks for them. We could leave that off and just use the first bit, if you think that's more helpful.

jhodgdon’s picture

The proposal in #6 just seems overly long, and I don't know that we need all 3 sections.

xjm’s picture

How about if we keep the example code, and just remove some of the verbosity, like:

Generic callback functions used with basic PHP language features

Generic callback functions used with PHP language features like usort() or array_walk() are documented as follows.

Examples

/**
 * Callback for array_walk(): Strips slashes from a string or array of strings.
 *
 * You may add a longer description here.
 * 
 * @param $item
 *   An individual string or array of strings from superglobals.
 * 
 * @see fix_gpc_magic().
 */
/**
 * Callback for uasort(): Sorts structured arrays by weight.
 *
 * You may add a longer description here.
 *
 * @param $a
 *   First item for comparison.  The compared items should be associative
 *   arrays that optionally include a '#weight' key.
 * @param $b
 *   Second item for comparison.
 */

Notes:

  • Prefix the one-line summary with Callback for function(): , where function() is a base PHP function that accepts a callback as a parameter.
  • After the prefix, include a standard function summary that is capitalized and begins with a third-person present indicative verb. Total line length: 80 characters, ending in "."
  • If applicable, add an @see line or lines referencing the specific function(s) that register this callback.

(Edited a bit to remove unnecessary stuff.)

xjm’s picture

Also, I'm not wild about the text of the h3 and I'm not sure the word "generic" even has any meaning here; do you think "Callback functions" would be sufficient? Or too easily confused with our standardized drupal callbacks?

jhodgdon’s picture

RE #11 - better. Still not sure we need two examples -- not sure what the 2nd one adds that the 1st one doesn't illustrate? Or maybe the 2nd one is better, but then do we need the 1st one?

RE #12 - Wouldn't these standards be good for Drupal function callbacks too?

xjm’s picture

I guess I wanted to show an example of a sorting callback, and to use actual examples from core, but I haven't come across one that has an @see. I'll look a bit more and see if there's an example that would be better.

And yeah, I think you are right about just using one set of standards, especially since we follow the same pattern as we used for the menu callbacks. My only concern is that our standard for FAPI callbacks is different, but maybe we could just add a note indicating there are special standards for FAPI, similar to what's already elsewhere in the doc. So:

Callback functions

The general standard for documenting callback functions follows. Note that there are specific standards for hook implementations, menu callbacks, and form callbacks.

/**
 * Insert instructive example docblock here!
 */

Notes:

  • Prefix the one-line summary with Callback for function(): , where function() is a function that accepts a callback as a parameter.
  • After the prefix, include a standard function summary that is capitalized and begins with a third-person present indicative verb. Total line length: 80 characters, ending in "."
  • If applicable, add an @see line or lines referencing the specific function(s) that register this callback.
xjm’s picture

Status: Needs review » Needs work
xjm’s picture

system_sort_themes() looks promising.

xjm’s picture

Title: Provide general documentation standard for callbacks » Provide documentation standard recommendation for generic PHP callbacks.

I think this is probably a lot better. My only concern is that I'm noticing having the function name in the summary makes the 80 character limit feel really tight, so do we want to put it on a separate line like we did with menu paths?

Callback functions

The general standard for documenting callback functions follows. Note that there are specific standards for hook implementations, menu callbacks, and form callbacks.

/**
 * Callback: Sorts themes by name, with default themes first.
 *
 * Used with uasort().
 *
 * You may add a longer description here.
 *
 * @param $a
 *   First item for comparison.  A theme object.
 * @param $b
 *   Second item for comparison.
 *
 * @see system_themes_page()
 */

Notes:

  • Prefix the one-line summary with Callback: .
  • After the prefix, include a standard function summary that is capitalized and begins with a third-person present indicative verb. Total line length: 80 characters, ending in "."
  • On a separate line, identify how to use the callback, e.g.: Used for function(), where function() is a function that accepts a callback as a parameter (e.g., array_walk(), uasort(), etc.).
  • If applicable, add an @see line or lines referencing the specific function(s) that register this callback.

(Edited)

xjm’s picture

Title: Provide documentation standard recommendation for generic PHP callbacks. » Provide general documentation standard for callbacks
Status: Needs work » Needs review
jhodgdon’s picture

Title: Provide documentation standard recommendation for generic PHP callbacks. » Provide general documentation standard for callbacks

I guess #17 is OK... maybe instead of "Callback for foo():" we could say "foo() callback:", which would save 4 characters and get the function back in the first line?

xjm’s picture

Hm, that would help a bit; but I'm concerned if we extend the pattern to Drupal functions as well, we'd have to cope with things like:
my_long_module_name_function_that_takes_a_callback() callback: Oops, character limit.

There's definitely value in having it in the summary though, so hmm. Not sure which is better.

jhodgdon’s picture

Yeah... I'm just not sure that "Callback:" is all that useful without it telling what the callback is for. Maybe the first line could just describe what it does, and the "Uses" line could be instead:

Callback for foo() within bar().

As in:

Callback for array_walk() within drupal_whatever_whatever().

Then we could also omit the @see at the bottom, and it would be clear where it's really being used?

xjm’s picture

Ah, I like that idea. (Of course, this means rerolling includes A-C again.) :P

Revised proposal follows. The second bullet could probably be cleaned up. Edit: fixed it a little, but maybe it needs more.

Callback functions

The general standard for documenting callback functions follows. Note that there are specific standards for hook implementations, menu callbacks, and form callbacks.

/**
 * Sorts themes by name, with default themes first.
 *
 * Callback for uasort() within system_themes_page().
 *
 * You may add a longer description here.
 *
 * @param $a
 *   First item for comparison.  A theme object.
 * @param $b
 *   Second item for comparison.
  */

Notes:

  • Use a standard function summary that is capitalized and begins with a third-person present indicative verb. Total line length: 80 characters, ending in "."
  • After a blank line, clarify the purpose of the callback. Use the format Callback for function_a() within function_b(), where function_a() is the API or base PHP function that accepts a callback as a parameter (e.g. uasort(), array_walk(), etc.); and function_b() is the API function that calls function_a() with this function as a callback parameter.
  • If multiple API functions use the callback, use a list.
jhodgdon’s picture

Issue tags: +Coding standards

#22 looks good to me. We should probably also include the function signature in the example docblock, and of course remove that extra space.

Yeah, that second bullet... How about this:
* After the summary line (and a blank line), include a line that states what PHP or Drupal function this is a callback for (e.g., uasort(), array_walk(), etc.), and also what Drupal function is calling that function.

ugh. I don't like that either... Hmmm...
* The "Callback for..." line should tell which PHP/Drupal function directly takes this callback as an argument, and also which Drupal API function calls that function. If multiple API functions call it, format as a list.

?
Anyone other than xjm and me want to comment on this proposed standard? Oops, just realized this issue wasn't tagged.

jhodgdon’s picture

Here's another thought.

If we adopt #22, then this is really not a different standard for "callbacks" than other functions. So we could probably just add a note in the generic functions doc that if the function is a callback, add this additional line saying "Callback for ...". Thoughts?

xjm’s picture

Ah, it would be nice not to have to add an additional section. On the other hand, an example of exactly what the line should look like is instructive. Would it break from the pattern used on the page too much to do something like the following? Edit: As a subheader under the general standards.

Callbacks

For callbacks, add a blank line after the summary, followed by a line that identifies the callback's purpose. Use the following format:

 * Callback for uasort() within system_themes_page().

This line should indicate which PHP or Drupal function directly takes this callback as an argument, and also which Drupal API function calls that function. If multiple API functions call it, format as a list.

Note that there are specific standards for hook implementations, menu callbacks, and form callbacks.

jhodgdon’s picture

Status: Needs review » Fixed

OK. Since this is not a standards change any more (phew! less bikeshedding is needed), I will go ahead and update the page. Suggestions welcome; I can always edit it again and tweak.
http://drupal.org/node/1354#functions
I also added some sub-headings to that section to make it hopefully all a little bit more clear.

For now, I'm marking this fixed. Feel free to offer suggestions and mark "needs work" if I've done something silly. :)

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

Anonymous’s picture

Issue summary: View changes

Updated issue summary.