You are here

function js_callback_process_request in JS Callback Handler 7.2

Process request data for callbacks.

By default, all callbacks will have request data processed automatically. A callback must explicitly set $info['process request'] to a boolean of FALSE to disable this functionality.

It will match against the callback's parameters and default value variable types. These values are always appended to any integer path values already assigned in the arguments array.

This allows callbacks to specify explicit path arguments or simply allow request values to match against the callback's parameter names.

$_REQUEST['my_variable'] = 'foo';

function my_callback($my_variable) { // Outputs: "foo". print $my_variable; }

function my_callback($arbitrary_parameter_name) { // Outputs: "Array". // The callback's parameter name does not match the key name in the // request data. See below why the output is an "Array". print $arbitrary_parameter_name; }

Regardless if this advanced "mapping" functionality is used, you can always access the entire request data. This data is always appended as the last parameter passed to the callback. Parameters that have been previously matched are excluded from this array. Example:

$_REQUEST['my_variable'] = 'foo'; $_REQUEST['my_second_variable'] = 'bar';

function my_callback($my_variable, $data) { // Outputs: "foo". print $my_variable;

// Outputs: NULL. print $data['my_variable'];

// Outputs: "bar". print $data['my_second_variable']; }

Parameters

array $info: The callback info array, passed by reference.

1 call to js_callback_process_request()
js_callback_execute in includes/callback.inc
Execute a callback.

File

includes/callback.inc, line 245
callback.inc

Code

function js_callback_process_request(array &$info) {
  if ($info['process request'] === FALSE) {
    return;
  }

  // Iterate over the raw $_REQUEST array.
  $request_data = array();
  $json_values = array(
    'true',
    'false',
    '1',
    '0',
    'yes',
    'no',
  );
  foreach ($_REQUEST as $key => $value) {

    // Convert possible JSON strings into arrays.
    if (is_string($value) && $value !== '' && ($value[0] === '[' || $value[0] === '{') && ($json = drupal_json_decode($value))) {
      $request_data[$key] = $json;
    }
    elseif (!is_int($value) && in_array($value, $json_values)) {
      $request_data[$key] = (bool) $value;
    }
    else {
      $request_data[$key] = $value;
    }
  }

  // Load argument callbacks.
  $load_arguments = $info['load arguments'];

  // Retrieve the default parameters of the callback function.
  foreach (array(
    'access',
    'callback',
  ) as $type) {
    $data = $request_data;

    // Match the callback function's parameter names against the names of keys
    // in the $_REQUEST array. Ensure the values have the correct type as well.
    $parameters = array();
    $function = $info[$type === 'callback' ? 'callback function' : "{$type} callback"];
    if (function_exists($function)) {
      $f = new ReflectionFunction($function);
      foreach ($f
        ->getParameters() as $param) {

        // Don't add parameters that have no default value and are not in $_REQUEST
        if (!$param
          ->isDefaultValueAvailable() && !isset($data[$param->name])) {
          continue;
        }

        // Determine if there's a default value.
        $default = $param
          ->isDefaultValueAvailable() ? $param
          ->getDefaultValue() : NULL;

        // Determine if callback parameter has been type hinted with a class.
        if ($class = $param
          ->getClass()) {
          $default = array(
            'class' => $class
              ->getName(),
            'default' => $default,
          );
        }

        // Set the default value.
        $parameters[$param->name] = $default;

        // Give callback definitions a chance to completely disable autoloading.
        if ($load_arguments !== FALSE && is_array($load_arguments)) {

          // Automatically determine load function, if it wasn't explicitly set.
          if (!isset($load_arguments[$param->name])) {
            $load_callback = $param->name . '_load';
            if (function_exists($load_callback)) {
              $load_arguments[$param->name] = $load_callback;
            }
          }
          elseif (!$load_arguments[$param->name] || !is_callable($load_arguments[$param->name])) {
            unset($load_arguments[$param->name]);
          }
        }
      }
    }
    foreach ($parameters as $name => $default_value) {

      // Check to see if the parameter exists.
      if (isset($data[$name])) {
        $value = $data[$name];

        // Load the parameter using a load argument callback, if one exists.
        if (is_array($load_arguments) && isset($load_arguments[$name])) {
          $value = call_user_func_array($load_arguments[$name], array(
            $value,
          ));
        }

        // Ensure class type hinting is passing the proper value.
        if (is_array($default_value) && isset($default_value['class'])) {
          if (!is_object($value) || get_class($value) !== $default_value['class'] && !is_subclass_of($value, $default_value['class'])) {
            $value = $default_value['default'];
          }
        }
        elseif (!is_null($default_value)) {
          settype($value, gettype($default_value));
        }

        // Move the value of the $_REQUEST data into the parameter array.
        $parameters[$name] = $value;

        // Remove the request data since it has been moved.
        unset($data[$name]);
      }
    }

    // Sort the remaining $_REQUEST data based on key name.
    ksort($data);

    // Merge existing arguments, parameters and any remaining request data.
    $info["{$type} arguments"] = array_merge($info["{$type} arguments"], $parameters, array(
      $data,
    ));
  }
}