You are here

function coder_upgrade_convert_filter in Coder 7.2

Same name and namespace in other branches
  1. 7 coder_upgrade/conversions/function.inc \coder_upgrade_convert_filter()

Updates hook_filter().

hook_filter() and hook_filter_tips() replaced by hook_filter_info().

@todo Integrate hook_filter_tips() code with this function. @todo Allow for other code styles, e.g. if block instead of switch. How similar is this use case to convert_return or convert_op?

Parameters

PGPNode $node: A node object containing a PGPClass (or function) item.

1 call to coder_upgrade_convert_filter()
coder_upgrade_upgrade_hook_filter_alter in coder_upgrade/conversions/function.inc
Implements hook_upgrade_hook_filter_alter().

File

coder_upgrade/conversions/function.inc, line 631
Provides conversion routines applied to functions (or hooks).

Code

function coder_upgrade_convert_filter(&$node, &$reader) {

  // DONE
  cdp("inside " . __FUNCTION__);
  $item =& $node->data;
  global $_coder_upgrade_module_name;
  $tips = array();
  $editor = PGPEditor::getInstance();

  // Find the hook_filter_tips function object.
  $function_node = $editor
    ->findFunction($reader
    ->getFunctions(), $_coder_upgrade_module_name . '_filter_tips', 'node');
  if (!is_null($function_node)) {
    $tips = coder_upgrade_convert_filter_tips($function_node);
    cdp($tips, '$tips');
  }

  // Rename function.
  $item->name .= '_XXX';

  // $item->name = $_coder_upgrade_module_name . '_filter_info';
  // Update document comment.
  //  $item->comment = preg_replace('@hook_filter@', "hook_filter_info", $item->comment);
  // Restructure the triggers array.
  $body =& $item->body;
  if (!($switch1 = $body
    ->find(T_SWITCH))) {
    clp("ERROR: switch statement not found in hook_filter");
    return;
  }

  //  $value = &$switch1['value'];

  /*
   * Compare first parameter to first switch condition (s/b $op)
   * Compare second parameter to second switch condition (s/b $delta)
   *
   * Read $op case block: case operand gives the key for array
   * Read $delta case block: case operand gives the key for array
   * Return value gives the array value for above keys
   * Build array internally, then write it out.
   *
   * On the callback items, we only want the callback function name, not the
   * parameters. If there is not a function name (e.g. the filter module had
   * case 'process': case 4: return trim(check_plain($text));),
   * then make a new function with the return value as its body.
   * For this example, core created _filter_html_escape($text).
   *
   * Look for a hook_filter_tips($delta, $format, $long = false).
   * If present:
   * - if multiple $delta bodies, then create new callback functions using
   * $delta as part of the function name
   * - else if one, then create new callback function
   * - remove the $delta parameter
   * - add tips_callback parameters to filter_info array items
   */

  // Get the operation variable from the function parameter [at index $op_index].
  // This function removes any default value assignment (e.g. $op = 'list') or
  // inline comments included in the parameter expression.
  $op_index = 0;
  if (!($variable = $item
    ->getParameterVariable($op_index))) {
    clp("ERROR: Variable not found in hook(\$op) parameter {$op_index}");
    return;
  }
  $op = $variable
    ->toString();

  // Get the first condition. (With a switch there should only be one condition.)
  $condition1 = $switch1->conditions
    ->getElement()
    ->findNode('operand')
    ->stripComments();
  $operand1 = $condition1
    ->toString();
  if ($operand1 != $op) {
    clp('ERROR: switch statement operand does not match first function parameter in hook_filter');
    return;
  }
  $filters = array();

  // Get list of case statements.
  $cases1 = $switch1->body;
  $current1 = $cases1
    ->first();
  while ($current1->next != NULL) {
    $case1 = $current1->data;
    if (!$case1 instanceof PGPCase || $case1->type == T_DEFAULT) {
      $current1 = $current1->next;
      continue;
    }
    $key1 = trim($case1->case
      ->stripComments()
      ->toString(), "'\"");
    cdp("key1 = {$key1}");

    // TODO Convert key2 to new key: Ex. 'process' becomes 'process callback'
    $key1 = coder_upgrade_callback_filter($key1);
    cdp("new key1 = {$key1}");
    $body1 = $case1->body
      ->getElement();
    if ($body1 && get_class($body1) == 'PGPFunctionCall') {

      // Use case 1: returns an array.
      cdp("body1 is an array");
      if ($key1 != 'name') {
        clp("ERROR: key is not 'list' in hook_filter");
        return;
      }
      if ($body1->type != T_RETURN) {
        clp("ERROR: switch statement body for 'list' key does not return an array in hook_filter");
        return;
      }
      $value1 = $body1
        ->getParameter()
        ->getElement();
      if ($value1 && get_class($value1) == 'PGPArray') {
        $node_x = $value1->values
          ->first();
        while ($node_x->next != NULL) {
          $data = $node_x->data;
          if ($node_x->type == 'key') {
            $key2 = $data
              ->toString();

            // Should be an integer = $delta
          }
          elseif ($node_x->type == 'value') {
            $filters[$key2][$key1] = $data
              ->toString();
          }
          $node_x = $node_x->next;
        }
      }
    }
    elseif ($body1 && get_class($body1) == 'PGPConditional' && $body1->type == T_SWITCH) {

      // Use case 2: switch statement on $delta.
      $switch2 =& $body1;
      $operand2 = $switch2->conditions
        ->toString();
      if ($operand2 != $item
        ->getParameterVariable(1)
        ->toString()) {
        clp("ERROR: switch statement operand does not match second function parameter in hook_filter");
        return;
      }

      // Get list of case statements.
      $cases2 = $switch2->body;
      $current2 = $cases2
        ->first();
      while ($current2->next != NULL) {
        $case2 = $current2->data;
        if (!$case2 instanceof PGPCase || $case2->type == T_DEFAULT) {
          $current2 = $current2->next;
          continue;
        }
        $key2 = trim($case2->case
          ->stripComments()
          ->toString(), "'\"");
        cdp("key2 = {$key2}");
        $body2 = $case2->body
          ->getElement();
        if ($body2 && get_class($body2) == 'PGPFunctionCall') {

          // Use case 2: returns an array.
          if ($body2->type != T_RETURN) {
            clp("ERROR: switch statement operand does not match first function parameter in hook_filter");
            return;
          }
          $value2 = $body2
            ->getParameter();
          if (get_class($value2) == 'PGPExpression') {

            // TODO On the callback items only want the callback function name, not the parameters!!!
            $filters[$key2][$key1] = $value2
              ->toString();
            cdp($value2, '$value2');
          }
          if ($key1 == 'process callback' || $key1 == 'settings callback') {
            if ($value2
              ->isType(T_FUNCTION_CALL)) {

              // For $value2 = trim(check_plain($text)), this will grab trim.
              // The user needs to define a callback function to do both.
              $call =& $value2
                ->findNode('operand');
              if (is_array($call->name)) {

                // Name could be T_STRING or T_VARIABLE.
                $name = $call->name['value'];
                if ($call->name['type'] == T_STRING) {
                  $name = "'{$name}'";
                }
              }
              else {

                // An object expression (should be unlikely).
                $name = $call->name
                  ->toString();
              }
              $filters[$key2][$key1] = $name;
            }
          }

          //           else {
          //             $filters[$key2][$key1] = $value2->toString();
          //           }
        }
        $current2 = $current2->next;
      }
    }
    $current1 = $current1->next;
  }
  foreach ($tips as $key2 => $callback) {
    $filters[$key2]['tips callback'] = "'{$callback}'";
  }
  $hook = '_filter_info';
  coder_upgrade_new_filter_hook($node, $hook, $filters);

  // Delete the function body.
  $item->body
    ->clear();
}