Skip to content
coder_upgrade.other.inc 63.1 KiB
Newer Older
<?php
// $Id$

/**
 * @file
 * Other conversion routine file for the coder_upgrade module.
 *
 * The functions in these conversion routine files correspond to the topics in
 * the category roadmap at http://drupal.org/node/394070 that are marked with
 * a "Yes" in the Upgrade column.
 *
 * Copyright 2008-9 by Jim Berry ("solotandem", http://drupal.org/user/240748)
 */

/**
 * Upgrades function calls using grammar parser.
 * http://drupal.org/node/224333#registry
 * http://drupal.org/node/224333#drupal_set_session (REVERTED)
 * http://drupal.org/node/224333#time
 * http://drupal.org/node/224333#rebuild_functions
 * http://drupal.org/node/224333#drupal_uninstall_modules
 * http://drupal.org/node/224333#module_implements_not_module_list
 * http://drupal.org/node/224333#drupal_http_request_parameters
 * http://drupal.org/node/224333#system_get_module_data
 * http://drupal.org/node/224333#static_variable_api (NOT IN THIS FUNCTION)
 * http://drupal.org/node/224333#drupal_set_html_head
 * http://drupal.org/node/224333#php_eval
 * http://drupal.org/node/224333#http_header_functions
 * http://drupal.org/node/224333#drupal_set_content
 * http://drupal.org/node/224333#time_limit
 *
 *
 * Database
 * http://drupal.org/node/224333#schema_ret
 *
 *
 * Menu
 * http://drupal.org/node/224333#comment_load (DUP Comments)
 *
 *
 * http://drupal.org/node/224333#comment_load
 * http://drupal.org/node/224333#comment_validate_removed
 * http://drupal.org/node/224333#comment_node_url
 *
 *
 * Input Sanitization and Input Formats
 * http://drupal.org/node/224333#check_markup_params
 * http://drupal.org/node/224333#drupal_set_title
 * http://drupal.org/node/224333#hook_filter_info (NOT IN THIS FUNCTION)
 * http://drupal.org/node/224333#filter_formats_parameters
 * http://drupal.org/node/224333#taxonomy_get_tree
 * http://drupal.org/node/224333#taxonomy_crud
 *
 *
 * http://drupal.org/node/224333#drupal_add_js_options
 * http://drupal.org/node/224333#drupal_add_js_weight (Included with above)
 * http://drupal.org/node/224333#rename-drupal-to-js
 *
 *
 * CSS
 * http://drupal.org/node/224333#drupal_add_js_options (DUP Javascript)
 * Theming
 * http://drupal.org/node/224333#rebuild_functions (DUP System)
Jim Berry's avatar
Jim Berry committed
 * http://drupal.org/node/224333#theme_changes
 *
 *
 * Form API
 * http://drupal.org/node/224333#drupal_execute_drupal_form_submit
 *
 *
 * File API
 * http://drupal.org/node/224333#file_set_status
 * http://drupal.org/node/224333#preg_match
 *
 *
Jim Berry's avatar
Jim Berry committed
 * User API
 * http://drupal.org/node/224333#user_cancel (ALSO in convert_functions)
Jim Berry's avatar
Jim Berry committed
 * http://drupal.org/node/224333#user_authenticate
 *
 *
 * Multi-lingual
 * http://drupal.org/node/224333#locale_context
 *
 *
 * Miscellaneous
 * http://drupal.org/node/224333#book_toc_parameters
 * http://drupal.org/node/224333#referer_uri
 * http://drupal.org/node/224333#drupal_clone
 * http://drupal.org/node/224333#actions_synchronize
 * http://drupal.org/node/224333#url_is_external
 *
 * @param PGPReader $reader
 *   The object containing the grammar statements of the file to convert.
 */
function coder_upgrade_convert_function_calls(&$reader) {
  $editor = new PGPEditor();
  $types = array(T_STRING);
  $editor->traverseCallback($reader->getFunctionCalls(), 'coder_upgrade_callback_function_calls', $types, $reader);
/**
 * Callback routine for function call changes using grammar parser.
 *
 * Programmatically changing the source code requires changing the contents of
 * the grammar object (the grammar equivalent of the code represented as a
 * PGPList of statements). A difficult way to do this would be to manually
 * create items (arrays or objects extended from the PGPBase class) and replace
 * the existing grammar items with the new items. This would essntially
 * duplicate the functionality of the PGPReader class.
 *
 * A simpler approach takes advantage of the grammar parser API which provides
 * helper functions for working with function call objects. Some examples of
 * typical tasks follow.
 *
 * Print a grammar object
 *
 * Before making a change, it is a good idea to print the contents of the
 * grammar object to become familiar with its structure and contents. PGP
 * provides a custom print_r function for this purpose. (NOTE: calls to the
 * built-in print_r, var_dump or equivalent routines for this purpose is not
 * recommended as the output may be extremely voluminous.) All of the objects
 * (as opposed to array items) can be printed using the custom print_r routine.
 * An array item can be printed using the built-in print_r routine.
 * @code
 *   // Print the grammar item (a function call object in this case).
 *
 *   // Print the parameters to the function call.
 *   // Alternatively, with a parameters object, do this.
 *   $parameters = $item->parameters;
 * @endcode
 *
 * Change the name of the function being called
 * @code
 *   // Change the name of the function being called.
 *   $name['value'] = 'new_function_name';
 * @endcode
 *
 * Get a parameter object and an expression object
 * @code
 *   // Get a parameter object (PGPExpression).
 *   $param = $item->getParameter(0);
 *
 *   // Get the first element of the parameter expression (PGPOperand or array).
 *   $element = $param->getElement(0);
 * @endcode
 *
 * Reorder the parameters
 * @code
 *  // Save the current parameters to local variables.
 *  $p0 = $item->getParameter(0);
 *  $p0 = $item->getParameter(1);
 *
 *  // Swap the parameters.
 *  $item->setParameter(0, $p1);
 *  $item->setParameter(1, $p0);
 * @endcode
 *
 * Insert or delete a parameter object
 * @code
 *   $item->insertParameter(2, $expression);
 *   $item->deleteParameter(2);
 * @endcode
 *
 * Set grammar elements from a string of code
 *
 * As mentioned above, it is not recommended to manually create items (arrays
 * or objects extended from the PGPBase class) and replace the existing grammar
 * items with the new items. A simpler approach is to create the string of code
 * to be inserted and use the PGPEditor class to convert this string to its
 * grammar representation.
 *
 * @code
 *  // Set a single parameter from a string of code.
 *  $editor->setParameter($item, 0, $code);
 *
 *  // Set all of the parameters from an array of code strings.
 *  $editor->setParameters($item, array('$form', '$form_state'));
 *
 *  // Insert a parameter from a string of code.
 *  $editor->insertParameter($item, 2, '$langcode = \'en\'');
 * @endcode
 *
 * Get grammar elements as a string of code
 *
 * @code
 *  // Print a parameter (i.e. convert it from a grammar object to a string).
 *  $parameter = $item->printParameter(1);
 *
 *  // Get the grammar equivalent of a string of code.
 *  $expression = $editor->expressionToStatement($string);
 * @endcode
 *
 * Other debug print examples.
 *
 * @code
 * cdp($list->printNode($parent));
 * cdp($list->printArray($parent));
 * cdp($list->printArray($temp->getElement(0)));
 * cdp($list->printNode($temp->get(0)));
 * @endcode
 *
 *   A function call object of the expression or statement.
 * @param PGPReader $reader
 *   The object containing the grammar statements of the file to convert.
function coder_upgrade_callback_function_calls(&$item, &$reader) {
  cdp("inside " . __FUNCTION__);
//  cdp($item->print_r());
   * The $item variable passed to this function is a PGPFunctionCall object.
   * When passed here via the coder_upgrade_convert_function_calls routine, the
   * variable was an entry in the function calls array filled by the PGPReader
   * class (and accessed as $reader->getFunctionCalls()).
   *
   * The function calls array contains references to PGPFunctionCall objects.
   * As these objects are processed, they may change or eliminate other
   * references yet to be processed (i.e. if other function call references
   * are contained in the current reference). Because of this, we need to
   * test whether $item actually refers to a PGPFunctionCall object before
   * attempting to do any processing.
   */
  if (!isset($item) || !is_a($item, 'PGPFunctionCall')) {
    return;
  }

  // Create helper objects.
  $editor = new PGPEditor();
  $list = new PGPList();
  // Process function call.
    case 'actions_synchronize': // DONE
      $count = $item->parameters->count();
      if ($count > 0) {
        $item->deleteParameter();
      }
      break;

    case 'book_toc': // DONE
      // Adjust parameters.
      $count = $item->parameters->count();
      if ($count > 2) {
        // Switch places.
        $p1 = $item->getParameter(1);
        $p2 = $item->getParameter(2);
        $item->setParameter(1, $p2);
        $item->setParameter(2, $p1);
      }
      // Remove default parameter.
      if ($count == 3) {
        $value = $item->printParameter(2);
        if ($value == 'array()') {
          $item->deleteParameter(2);
        }
      }
      break;

    case 'check_markup': // DONE
      if ($item->parameters->count() > 2) {
        $editor->insertParameter($item, 2, '$langcode = \'\' /* TODO Set this variable. */');
    case '_comment_load': // DONE
      // TODO The comment_wildcard change in hook_menu.
      $name['value'] = 'comment_load';
    case 'comment_node_url': // DONE
      $parent = $item->parent;
      $temp = $editor->statementsToText($parent);
      $from = '@comment_node_url()@';
      $to = "'comment/' . \$comment->cid";
      $temp = preg_replace($from, $to, $temp);
      $temp = $editor->textToStatements($temp);
      $parent->data = $temp->getElement(0);
    case 'comment_validate': // DONE
      $name['value'] = 'comment_form_validate';
      $editor->setParameters($item, array('$form', '$form_state /* TODO Set these variables. */'));
    case 'db_add_field':
      // includes/database.pgsql.inc Add a new field to a table.
    case 'db_add_index':
      // includes/database.pgsql.inc Add an index.
    case 'db_add_primary_key':
      // includes/database.pgsql.inc Add a primary key.
    case 'db_add_unique_key':
      // includes/database.pgsql.inc Add a unique key.
    case 'db_change_field':
      // includes/database.pgsql.inc Change a field definition.
    case 'db_create_table':
      // includes/database.inc Create a new table from a Drupal table definition.
    case 'db_create_table_sql':
      // includes/database.pgsql.inc Generate SQL to create a new table from a Drupal schema definition.
    case 'db_drop_field':
      // includes/database.pgsql.inc Drop a field.
    case 'db_drop_index':
      // includes/database.pgsql.inc Drop an index.
    case 'db_drop_primary_key':
      // includes/database.pgsql.inc Drop the primary key.
    case 'db_drop_table':
      // includes/database.pgsql.inc Drop a table.
    case 'db_drop_unique_key':
      // includes/database.pgsql.inc Drop a unique key.
    case 'db_field_names':
      // includes/database.inc Return an array of field names from an array of key/index column specifiers.
    case 'db_field_set_default':
      // includes/database.pgsql.inc Set the default value for a field.
    case 'db_field_set_no_default':
      // includes/database.pgsql.inc Set a field to have no default value.
    case 'db_rename_table':
      // includes/database.pgsql.inc Rename a table.
      $item->deleteParameter();
      break;

Jim Berry's avatar
Jim Berry committed
    case 'drupal_add_css': // DONE
      // A similar comment to that in 'drupal_add_js' below applies here.

      $count = $item->parameters->count();
      if ($count < 3) {
        $type = trim($item->printParameter(1), "'\"");
        if (in_array($type, array('module', 'theme'))) {
          $editor->setParameter($item, 1, "'file'"); // Could simply delete it.
      $keys = array('type', 'media', 'preprocess');
      $defaults = array("'module'", "'all'", 'TRUE');
      $string = $editor->arrayitize($item, 1, $keys, $defaults);
      $string = preg_replace('@[\'"]theme[\'"]@', "'file'", $string); // Could be deleted.

      if ($string != 'array()') {
        $temp = $editor->expressionToStatement($string);
        $item->setParameter(1, $temp);
      }
      break;

Jim Berry's avatar
Jim Berry committed
    case 'drupal_add_js': // DONE
      /*
       * With
       * drupal_add_js('misc/collapse.js', 'core', 'header', FALSE, TRUE, TRUE);
       * we will output
       * drupal_add_js('misc/collapse.js', array(
       *   'type' => 'core',
       * ));
       * which is correct, although the function will also accept
       * drupal_add_js('misc/collapse.js', 'core');
       * The example begs the question why someone would have included all
       * the default parameters.
       *
       * A type of 'core', 'module' or 'theme' all convert to 'file' which is
       * the new default. We could add a weight item based on the type?

      $count = $item->parameters->count();
      if ($count < 3) {
        $type = trim($item->printParameter(1), "'\"");
        if (in_array($type, array('core', 'module', 'theme'))) {
          $editor->setParameter($item, 1, "'file'"); // Could simply delete it.
      $keys = array('type', 'scope', 'defer', 'cache', 'preprocess');
      $defaults = array("'module'", "'header'", 'FALSE', 'TRUE', 'TRUE');
      $string = $editor->arrayitize($item, 1, $keys, $defaults);
      $string = preg_replace('@[\'"](core|theme)[\'"]@', "'file'", $string); // Could be deleted.

      if ($string != 'array()') {
        $temp = $editor->expressionToStatement($string);
        $item->setParameter(1, $temp);
      }
      break;

    case 'drupal_clone': // DONE
      $name['value'] = 'clone';
    case 'drupal_eval': // DONE
      /*
       * Examine the statement containing the function call.
       * Wrap the containing statement in an "if (module_exists('php'))" block.
       * The function call may be the containing statement.
       */

      // Set the name of the function call.
      $name['value'] = 'php_eval';

      // Get the parent = statement (i.e. node) this function call is part of.
      $parent = $item->parent;
      $temp = $editor->statementsToText($parent);
      $temp = $editor->textToStatements("if (module_exists('php')) {\n\t$temp\n}");
      $parent->data = $temp->getElement(0);
    case 'drupal_execute': // DONE
      $name['value'] = 'drupal_form_submit';
      break;

    case 'drupal_get_content': // DONE
      $name['value'] = 'drupal_get_region_content';
      break;

    case 'drupal_get_headers': // DONE
      $name['value'] = 'drupal_get_header';
      break;

    case 'drupal_http_request': // DONE

      $count = $item->parameters->count();
      if ($count == 1) {
        break;
      }

      $keys = array('headers', 'method', 'data', 'max_redirects');
      $defaults = array('xxx_YYY_zzz', "'GET'", 'NULL', 3);
      $string = $editor->arrayitize($item, 1, $keys, $defaults);

      $temp = $editor->expressionToStatement($string);
      $temp->getElement(0)->multiline = 0;
Jim Berry's avatar
Jim Berry committed
      $item->setParameter(1, $temp);
    case 'drupal_json': // DONE
      $name['value'] = 'drupal_json_output';
      break;

    case 'drupal_rebuild_code_registry': // DONE
      $name['value'] = 'registry_rebuild';
      break;

    case 'drupal_rebuild_theme_registry': // DONE
      $name['value'] = 'drupal_theme_rebuild';
      break;

    case 'drupal_set_content': // DONE
      $name['value'] = 'drupal_add_region_content';
      break;

    case 'drupal_set_header': // DONE
      // TODO the hook_file_download() changes. Use parser on the entire function.
      $temp = $item->printParameters();
      if (strpos($temp, 'Content-Type:') !== FALSE) {
        $temp = explode(':', $temp);
        foreach ($temp as $key => $string) {
          $temp[$key] = "'" . trim($string, "' ") . "'";
        }
        $editor->setParameters($item, $temp);
      }
      elseif (strpos($temp, "\$_SERVER['SERVER_PROTOCOL']") !== FALSE ||
              strpos($temp, '\$_SERVER["SERVER_PROTOCOL"]') !== FALSE) {
        $from = '@\$_SERVER\[(\'|")SERVER_PROTOCOL(\'|")\]\s*\.\s*(\'|")\s*(.*?)(\'|")@';
        $to = "$3$4$3";
        $temp = preg_replace($from, $to, $temp);
        $editor->setParameters($item, array($temp));
    case 'drupal_set_html_head': // DONE
      $name['value'] = 'drupal_add_html_head';
      break;

    case 'drupal_set_title': // DONE
      $temp = $item->printParameters();

      if (strpos($temp, 'check_plain') !== FALSE) {
        // TODO Could check for isset, count of parameters, etc.???
        // check_plain could be part of an expression (e.g. concatenation).
        $temp = $item->getParameter(0);
        $temp = $temp->getElement(0);
        cdp("Printing the first ");
        cdp($temp->print_r());
        $editor->setParameter($item, 0, $temp->printParameter(0));
        break;
      }
      $parameters = &$item->parameters;
      if ($call = &$parameters->search($parameters, 'PGPFunctionCall', 'name', 'value', 't')) {
        $temp = $call->toString();
        if (preg_match('#(\'|")@\w+(\'|")\s*=>\s*#', $temp)) {
          $editor->setParameter($item, 1, 'PASS_THROUGH');
    case 'drupal_system_listing': // DONE
      $temp = $item->printParameter(0);
      // Check for type == T_CONSTANT_ENCAPSED_STRING
      // Check for a '/' in the mask and use a different mask or delimit the '/' with '\/'.
      if ($temp[0] == "'") {
        $editor->setParameter($item, 0, "'/" . substr($temp, 1, -1) . "/'");
      }
      elseif ($temp[0] == '"') {
        $editor->setParameter($item, 0, '"/' . substr($temp, 1, -1) . '/"');
      }
      // else if type == T_VARIABLE, find the $mask used in the call and examine its value.
      break;

    case 'drupal_to_js': // DONE
      $name['value'] = 'drupal_json_encode';
      break;

    case 'drupal_uninstall_module': // DONE
      $name['value'] = 'drupal_uninstall_modules';
      $temp = $item->printParameters();
      $editor->setParameters($item, array('array(' . $temp . ')'));
    case 'file_scan_directory': // DONE
      // TODO Part of http://drupal.org/node/224333#preg_match
      // TODO Other changes apply to this function call.
      $temp = $item->printParameter(1);
      // Check for type == T_CONSTANT_ENCAPSED_STRING
      // Check for a '/' in the mask and use a different mask or delimit the '/' with '\/'.
      if ($temp[0] == "'") {
        $editor->setParameter($item, 1, "'/" . substr($temp, 1, -1) . "/'");
      }
      elseif ($temp[0] == '"') {
        $editor->setParameter($item, 1, '"/' . substr($temp, 1, -1) . '/"');
      }
      // else if type == T_VARIABLE, find the $mask used in the call and examine its value.
      break;

    case 'file_set_status': // DONE
      if ($item->parameters->count() == 2) {
        $p0 = $item->printParameter(0);
        $p1 = $item->printParameter(1);

        // Insert statement.
        $temp = $editor->textToStatements("{$p0}->status &= $p1");
        $parent = $item->parent;
        $parent->container->insertBefore($parent, $temp->getElement(0));

        // Change statement.
        $from = $temp1;
        $to = "$p0 = file_save($p0)";
        $temp = str_replace($from, $to, $temp2);
        $temp = $editor->textToStatements($temp);
        $parent->data = $temp->getElement(0);
Jim Berry's avatar
Jim Berry committed
    case 'filter_formats': // DONE
      // If has a parameter, then change it to $user and add global statement.
      if ($item->parameters->count() > 0) {
        $p0 = $editor->expressionToStatement('$user');
        $item->setParameter(0, $p0);

        // Get the parent = statement (i.e. node) this function call is part of.
        $parent = &$item->parent;
        // Get the statement list the parent is part of.
        $container = &$parent->container;
        // Insert a statement.
        $statement = $editor->textToStatements("global \$user;")->getElement(0);
        $container->insertBefore($parent, $statement, 'global');
      }
      break;

Jim Berry's avatar
Jim Berry committed
    case 'format_plural': // DONE
      $count = $item->parameters->count();
      if ($count < 5) {
        break;
      }

      $keys = array('langcode');
      $defaults = array("'XXX_YYY'");
      $string = $editor->arrayitize($item, 4, $keys, $defaults);

      $temp = $editor->expressionToStatement($string);
      $temp->getElement(0)->multiline = 0;
      $item->setParameter(4, $temp);
      break;

      // Change was reverted.
//      $name['value'] = 'drupal_function_exists';
    case 'menu_path_is_external': // DONE
      $name['value'] = 'url_is_external';
      break;

Jim Berry's avatar
Jim Berry committed
    case 'module_invoke': // DONE
      // http://drupal.org/node/224333#taxonomy_get_tree
      $depth = '$max_depth = NULL /* TODO Set this variable. */';
      $count = $item->parameters->count();
      // Confirm this call relates to our topic.
      if ($count > 2) {
        $p0 = $item->printParameter(0);
        $p1 = $item->printParameter(1);
        if ($p0 != "'taxonomy'" || $p1 != "'get_tree'") {
          break;
        }
      }

      // Adjust parameters.
      if ($count > 5) {
        // Switch places.
        $p4 = $item->getParameter(4);
        $p5 = $item->getParameter(5);
        $item->setParameter(4, $p5);
        $item->setParameter(5, $p4);
      }
      elseif ($count > 4) {
        // Insert parameter due to change in parameter order.
        $editor->insertParameter($item, 4, $depth);
      $defaults = array(array('NULL', $depth), '-1');
      $string = $editor->removeDefaults($item, 4, $defaults);
    case 'module_list': // DONE
      $name['value'] = 'module_implements';
      $editor->setParameters($item, array('$hook /* TODO Set this variable. */'));
    case 'module_rebuild_cache': // DONE
      $name['value'] = 'system_rebuild_module_data';
    case 'referer_uri': // DONE
      $expression = $editor->expressionToStatement("\$_SERVER['HTTP_REFERER']");
      $item = $expression->getElement(0);
    case 'set_time_limit': // DONE
      $name['value'] = 'drupal_set_time_limit';
      break;

    case 'system_theme_data': // DONE
      $name['value'] = 'system_rebuild_theme_data';
      break;

Jim Berry's avatar
Jim Berry committed
    case 't': // DONE
      $count = $item->parameters->count();
      if ($count < 3) {
        break;
      }

      $keys = array('langcode');
      $defaults = array("'XXX_YYY'");
      $string = $editor->arrayitize($item, 2, $keys, $defaults);

      $temp = $editor->expressionToStatement($string);
      $temp->getElement(0)->multiline = 0;
      $item->setParameter(2, $temp);
    case 'taxonomy_del_term': // DONE
      $name['value'] = 'taxonomy_term_delete';
      break;

    case 'taxonomy_del_vocabulary': // DONE
      $name['value'] = 'taxonomy_vocabulary_delete';
      break;

    case 'taxonomy_get_term': // DONE
      $name['value'] = 'taxonomy_term_load';
      break;

    case 'taxonomy_get_tree': // DONE
      $depth = '$max_depth = NULL /* TODO Set this variable. */';
      $count = $item->parameters->count();
      // Adjust parameters.
      if ($count > 3) {
        // Switch places.
        $p2 = $item->getParameter(2);
        $p3 = $item->getParameter(3);
        $item->setParameter(2, $p3);
        $item->setParameter(3, $p2);
      elseif ($count > 2) {
        // Insert parameter due to change in parameter order.
        $editor->insertParameter($item, 2, $depth);
        $count = $item->parameters->count();
      }

      $defaults = array(array('NULL', $depth), '-1');
      $string = $editor->removeDefaults($item, 2, $defaults);
    case 'taxonomy_save_term': // DONE
      $name['value'] = 'taxonomy_term_save';
      $temp = $item->printParameters();
      $editor->setParameters($item, array('$term /* TODO Term object replaces array ' . $temp . ' */)'));
    case 'taxonomy_save_vocabulary': // DONE
      $name['value'] = 'taxonomy_vocabulary_save';
      $temp = $item->printParameters();
      $editor->setParameters($item, array('$vocabulary /* TODO Vocabulary object replaces array ' . $temp . ' */)'));
Jim Berry's avatar
Jim Berry committed
    case 'theme': // DONE
      /*
       * Create a static variable to hold the array of theme registrations.
       * Find the theme in the list so we know the names of its parameters.
       * Array-itize the parameters.
       *
       * Find the hook_theme function (using $reader passed to this function)
       * and save its contents. This assumes the hook_theme is defined in this
       * file!!!
       *
       * Add helper functions to PGPArray to get the keys and values as arrays.
       * TODO Refactor any existing code that does this.
       *
       * static $themes = array();
       *
       * $p0 = $item->getParameter(0);
       * $theme = $themes[$p0];
       * $keys = keys from $theme
       * $string = 'array(';
       * foreach ($keys as $key) {
       *   $string .= "'$key' => $p{$i},";
       * }
       * $string = ');
       */
      cdp(__FUNCTION__ . " inside theme case");
Jim Berry's avatar
Jim Berry committed
      global $_coder_upgrade_module_name;
      // Find the hook_theme function object.
      $function = $editor->findFunction($reader->getFunctions(), $_coder_upgrade_module_name . '_theme');
      if (is_null($function)) {
        return;
Jim Berry's avatar
Jim Berry committed
      }

      // Get the keys for the appropriate theme.
      $body = &$function->body;

      if (!($return = $body->find(T_RETURN, 'reverse'))) {
        clp("ERROR: return statement not found in hook_perm");
Jim Berry's avatar
Jim Berry committed
        return;
      }
Jim Berry's avatar
Jim Berry committed
      $array = $value->getElement(0);
      if (get_class($array) == 'PGPArray') {
        if (!($theme = $array->findValue($item->getParameter(0)->toString()))) {
          clp("ERROR: theme entry not found in hook_theme");
Jim Berry's avatar
Jim Berry committed
        $array = $theme->getElement(0);
        $arguments = $array->findValue("'arguments'");
Jim Berry's avatar
Jim Berry committed
        $keys = $arguments->getElement(0)->keysToArray();
        if (empty($keys)) {
          break;
        }
        // Remove the quotes surrounding the keys.
        foreach ($keys as $index => $key) {
          $keys[$index] = trim($key, "'\"");
        }
Jim Berry's avatar
Jim Berry committed
      }

      $count = $item->parameters->count();
      if ($count == 1) {
        break;
      }

      $defaults = array_fill(0, $count - 1, "'XXX_YYY'");
      $string = $editor->arrayitize($item, 1, $keys, $defaults);
Jim Berry's avatar
Jim Berry committed

      $temp = $editor->expressionToStatement($string);
      $temp->getElement(0)->multiline = 0;
      $item->setParameter(1, $temp);
      break;

    case 'time': // DONE
      $expression = $editor->expressionToStatement('REQUEST_TIME');
      $item = $expression->getElement(0);
    case 'user_authenticate': // DONE
Jim Berry's avatar
Jim Berry committed
      $count = $item->parameters->count();
      if ($count == 0) {
        $editor->setParameters($item, array('$name', '$password /* TODO Set these variables */'));
        break;
      }

      /*
       * Two cases:
Jim Berry's avatar
Jim Berry committed
       * - parameter is an array expression: extract values to use as new
Jim Berry's avatar
Jim Berry committed
       *   parameters
Jim Berry's avatar
Jim Berry committed
       * - parameter is a variable expression (not an array): assume the
Jim Berry's avatar
Jim Berry committed
       *   variable has name and pass as elements
       */

      $p0 = $item->getParameter();
      $operand = $p0->getElement();
      $class = get_class($operand);
      if ($class == 'PGPOperand') {
        // Get the variable name used as the parameter.
        $parameter = $item->getParameter()->toString();
        // Make variable assignments referring to two new parameters.
Jim Berry's avatar
Jim Berry committed
        $assign1 = $editor->textToStatements('$name = ' . $parameter . "['name']; // TODO Set these variables");
        $assign2 = $editor->textToStatements('$password = ' . $parameter . "['pass'];")->getElement(0);
Jim Berry's avatar
Jim Berry committed
        // Insert the assignments before this statement.
        // Get the statement (i.e. node) this function call is part of.
        $parent = &$item->parent;
        // Get the statement list the parent is part of.
        $container = &$parent->container;
        // Insert statements.
        $container->insertListBefore($parent, $assign1, 'assignment');
        $container->insertBefore($parent, $assign2, 'assignment');
        // Set the parameters on this function call.
        $editor->setParameters($item, array('$name', '$password'));
      }
      elseif ($class == 'PGPArray') {
Jim Berry's avatar
Jim Berry committed
        $name = $operand->findValue("'name'")->toString();
        $password = $operand->findValue("'pass'")->toString();
Jim Berry's avatar
Jim Berry committed
        // Set the parameters on this function call.
        $editor->setParameters($item, array($name, $password));
      }
    case 'user_delete': // DONE
      $name['value'] = 'user_cancel';
      $editor->setParameter($item, 2, "\$method = 'user_cancel_block' /* TODO Set this variable */");
Jim Berry's avatar
Jim Berry committed
      break;
 * Upgrades text using simple regular expressions.
 * System
 * http://drupal.org/node/224333#moved_statistics_settings
 *
 *
 * Permissions and Access
 * http://drupal.org/node/224333#moved_statistics_settings (DUP System)
 * http://drupal.org/node/224333#php_permissions
 *
Jim Berry's avatar
Jim Berry committed
 *
 * Input Sanitization and Input Formats
 * http://drupal.org/node/224333#filter_urls
 *
 * @param string $file
 *   The text of the file to convert.
 */
function coder_upgrade_convert_regex_simple_changes(&$file) {
  $hook = 'regex_simple_changes';
  $cur = $file;
  $new = $cur;

  $from = array();
  $to = array();

  // Moved admin/reports/settings to admin/config/system/statistics (replacing admin/settings/statistics).
  $from[] = "@'admin/reports/settings'@";
  $to[] = "'admin/config/system/statistics'";

  // Replace "use PHP for block visibility" with "use PHP for settings."
  $from[] = '/(\'|")use PHP for block visibility(\'|")/';
  $to[] = "$1use PHP for settings$1";

Jim Berry's avatar
Jim Berry committed
  // Moved admin/settings/filters/* to admin/settings/filter/*
  $from[] = '@admin\/settings\/filters(\/.*?)@';
  $to[] = "admin\/settings\/filter$1";

  coder_upgrade_do_conversions($from, $to, $new);
  coder_upgrade_save_changes($cur, $new, $file, $hook);
}
Jim Berry's avatar
Jim Berry committed
/**
 * Upgrades functions using grammar parser.
Jim Berry's avatar
Jim Berry committed
 *
 * Module Info / Install
 * http://drupal.org/node/224333#update_php
 *
 *
 * Permissions and Access
 * http://drupal.org/node/224333#hook_permission
 * http://drupal.org/node/224333#descriptions_permissions
 * http://drupal.org/node/224333#hook_node_access
 *
 *
 * Database
 * http://drupal.org/node/224333#schema_translation
 * http://drupal.org/node/224333#schema_html
 * http://drupal.org/node/224333#install-schema
Jim Berry's avatar
Jim Berry committed
 *
 *
 * Menus
 * http://drupal.org/node/224333#hook_menu_link_alter
 *
 *
 * Blocks
 * http://drupal.org/node/224333#remove_op (DUP Node API)
 *
 *
 * Comments
 * http://drupal.org/node/224333#remove_op (DUP Node API) (THIS IS MISSING FROM THE CHRONO PAGE!!!)
 *
 *
 * User API
 * http://drupal.org/node/224333#user_cancel (DONE with remove_op)
 * http://drupal.org/node/224333#remove_op (DUP Node API)
 *
 *
 * Node API
 * http://drupal.org/node/224333#remove_op (SPANS MULTIPLE HOOKS)
 * http://drupal.org/node/224333#node_build_rss
 * http://drupal.org/node/224333#build_mode
 * http://drupal.org/node/224333#hook_node_xxx
 *
Jim Berry's avatar
Jim Berry committed
 * @param PGPReader $reader
 *   The object containing the grammar statements of the file to convert.
 */
function coder_upgrade_convert_functions(&$reader) {
//  clp("inside " . __FUNCTION__);
  cdp("inside " . __FUNCTION__);
Jim Berry's avatar
Jim Berry committed
  $editor = new PGPEditor();
  $types = array(T_FUNCTION);
Jim Berry's avatar
Jim Berry committed
  $editor->traverseCallback($reader->getFunctions(), 'coder_upgrade_callback_functions', $types, $reader);
/**
 * Callback routine for function changes using grammar parser.
 *
 * The grammar parser API which provides helper functions for working with
 * function objects. Some examples of typical tasks follow.
 *
 * @code
 *   // Rename the function.
 *   $item->name = 'new_function_name';
 *
 *   // Update the document comment.
 *   $item->comment = preg_replace('@hook_perm([^i])@', "hook_permission$1", $item->comment);
 *
 *   // Get the list of body statements (note the use of the reference operator).
 *   $body = &$item->body;
 *
 *   // Find the return statement in the function.
 *   $return = $body->find(T_RETURN, 'reverse');
 * @endcode
 *
 * For other examples of using the grammar parser API
 * @see coder_upgrade_callback_function_calls
 *
 * @param PGPNode $node
 *   A node object containing a PGPClass (or function) item.
 * @param PGPReader $reader
 *   The object containing the grammar statements of the file to convert.
function coder_upgrade_callback_functions(&$node, &$reader) {
  cdp("inside " . __FUNCTION__);

  global $_coder_upgrade_module_name;

  $name = &$item->name;

  /*
   * If the function name does not begin with the module name, then ignore it.
   * This assumes such a function would be an instance of an API hook defined
   * by the contributed module but implemented on behalf of another module. For
   * this use case, the contributed module would define upgrade routines to
   * allow other contributed modules that implement said API to upgrade their
   * code.
   *
   * Example: the Views module defines hooks and implements them on behalf of