diff --git a/coder_upgrade/coder_upgrade.api.php b/coder_upgrade/coder_upgrade.api.php index bc11111a64674780c8ae54f66a6b681bce9bc516..a21348c9ecfee1f708b4f2cea5bd6451c9e65a4f 100644 --- a/coder_upgrade/coder_upgrade.api.php +++ b/coder_upgrade/coder_upgrade.api.php @@ -1,5 +1,4 @@ $dir)), 'error'); } + // Create the new module directory. $dir = coder_upgrade_directory_path('new', FALSE); if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) { drupal_set_message(st('The files directory at %directory can not be written to. This is the default directory to which Coder Upgrade writes converted module code.', array('%directory' => $dir)), 'error'); @@ -47,11 +47,7 @@ function coder_upgrade_install() { */ function coder_upgrade_uninstall() { // Remove the module input and output directories. - $dir = coder_upgrade_directory_path('old', FALSE); - coder_upgrade_clean_directory($dir, TRUE); - $dir = coder_upgrade_directory_path('new', FALSE); - coder_upgrade_clean_directory($dir, TRUE); - $dir = coder_upgrade_directory_path('patch', FALSE); + $dir = coder_upgrade_directory_path('base', FALSE); coder_upgrade_clean_directory($dir, TRUE); // Remove items from {variables} table. @@ -90,12 +86,13 @@ function coder_upgrade_requirements($phase) { if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) { $requirements['coder_upgrade_files'] = array( 'title' => $t('Files directory'), - 'description' => $t('Your files directory at %directory can not be written to. Coder Upgrade places converted module code in subdirectories of this directory.', array('%directory' => $dir)), + 'description' => $t('Your files directory at %directory can not be written to. Coder Upgrade places converted module code and other files in subdirectories of this directory.', array('%directory' => $dir)), 'severity' => REQUIREMENT_ERROR ); } } else { + // @todo Check all of the subdirectories. $dir = coder_upgrade_directory_path('new', FALSE); if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) { $requirements['coder_upgrade_files'] = array( diff --git a/coder_upgrade/coder_upgrade.module b/coder_upgrade/coder_upgrade.module index 7b2e34c13900409ad789b966ab5703fd5f3ddc64..a2f7adb8e8122ff54b573cedc9d138ec97a17429 100644 --- a/coder_upgrade/coder_upgrade.module +++ b/coder_upgrade/coder_upgrade.module @@ -1,7 +1,8 @@ 'Upgrade', - 'description' => 'Convert module code from version 6.x to 7.x.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('coder_upgrade_conversions_form'), - 'access arguments' => array('administer code conversions'), - 'type' => MENU_LOCAL_TASK, - ); - - // Run items. - $items['admin/config/development/coder/upgrade/run'] = array( - 'title' => 'Run', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - - // Settings related items. - $items['admin/config/development/coder/upgrade/settings'] = array( - 'title' => 'Settings', - 'description' => 'Configure the module conversion suite.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('coder_upgrade_settings_form'), - 'access arguments' => array('administer site configuration'), - 'type' => MENU_LOCAL_TASK, - ); - - // Patch files. - $items['files/coder_upgrade/patches/%'] = array( - 'title' => 'Patches', - 'description' => 'Display patch file.', - 'page callback' => 'coder_upgrade_patch_display', - 'page arguments' => array(3), - 'access arguments' => array('administer code conversions'), - 'type' => MENU_CALLBACK, - ); - - return $items; + module_load_include('inc', 'coder_upgrade', 'includes/menu'); + return _coder_upgrade_menu(); } /** @@ -92,707 +56,11 @@ function coder_upgrade_menu_alter(&$items) { } /** - * Form builder for the settings form. - */ -function coder_upgrade_settings_form($form, &$form_state) { - module_load_include('inc', 'grammar_parser', 'grammar_parser.parser'); - $parser = new PGPParser(); - - $path = coder_upgrade_directory_path('', FALSE); - $form['coder_upgrade_dir'] = array( - '#title' => t('Module base directory'), - '#type' => 'textfield', - '#required' => TRUE, - '#default_value' => variable_get('coder_upgrade_dir', DEADWOOD_DIR), - '#description' => t('Directory beneath the file system path (!path) in which are housed the old, new and patch directories. Default is !default. In the old directory, place the 6.x module code to be upgraded. The upgraded code is saved to the new directory and patch files are written to the patch directory.', array('!path' => $path, '!default' => DEADWOOD_DIR)), - '#size' => 30, - '#maxlength' => 255, - '#validate' => array('coder_upgrade_validate_dir'), - ); - - $form['coder_upgrade_upgrade_core'] = array( - '#type' => 'checkbox', - '#title' => t('Update Drupal core modules'), - '#default_value' => variable_get('coder_upgrade_upgrade_core', FALSE), - '#description' => t('If checked, then the list of modules to select for upgrade will be the Drupal core modules. Otherwise, the list will be created from contributed modules.'), - ); - - $form['coder_upgrade_replace_files'] = array( - '#type' => 'checkbox', - '#title' => t('Replace files'), - '#default_value' => variable_get('coder_upgrade_replace_files', FALSE), - '#description' => t('If checked, then the original file will be written to the output directory shown above and then replaced with the upgraded file. Otherwise, the upgraded file will be written to the output directory shown above.'), - ); - - $form['coder_upgrade_preserve_array_format'] = array( - '#type' => 'checkbox', - '#title' => t('Preserve array formatting'), - '#default_value' => variable_get('coder_upgrade_preserve_array_format', FALSE), - '#description' => t('If checked, then array expressions will be formatted to match the input. If not checked, then array expressions will be formatted per Drupal coding standards. This means array expressions will be inlined in function calls, function parameters, and when a single value. Otherwise, the expression will will be multiline formatted.'), - ); - - $form['coder_upgrade_enable_debug_output'] = array( - '#type' => 'checkbox', - '#title' => t('Enable debug output from coder upgrade'), - '#default_value' => variable_get('coder_upgrade_enable_debug_output', FALSE), - '#description' => t('If checked, then coder upgrade debug output will be written to the file !file. WARNING: This option should NOT be enabled except for testing and development purposes, and then only on smaller files containing the code to be debugged.', array('!file' => coder_upgrade_path('debug'))), - ); - - $form['coder_upgrade_enable_parser_debug_output'] = array( - '#type' => 'checkbox', - '#title' => t('Enable debug output from grammar parser'), - '#default_value' => variable_get('coder_upgrade_enable_parser_debug_output', FALSE), - '#description' => t('If checked, then grammar parser debug output will be written to the file !file. WARNING: This option should NOT be enabled except for testing and development purposes, and then only on smaller files containing the code to be debugged.', array('!file' => $parser->debugPath())), - ); - - $path = coder_upgrade_path('theme_cache'); - $form['performance'] = array( - '#type' => 'fieldset', - '#title' => t('Performance'), - '#description' => t('To minimize the chance of hitting PHP memory and processing time limits, it is recommended to run coder upgrade in a separate process without a Drupal bootstrap. These options were set when this module was enabled. If Drupal core has been updated on this site, then click the button below to refresh the core theme information cache file at !file.', array('!file' => $path)), - '#tree' => FALSE, - ); - - $form['performance']['coder_upgrade_use_separate_process'] = array( - '#type' => 'checkbox', - '#title' => t('Use separate process'), - '#default_value' => variable_get('coder_upgrade_use_separate_process', FALSE), - '#description' => t('If checked, then coder upgrade will be run in a separate process without a Drupal bootstrap. This helps to minimize the chance of hitting PHP memory and processing time limits.'), - ); - - $form['performance']['theme_cache'] = array( - '#type' => 'submit', - '#value' => t('Cache core theme information'), - '#submit' => array('coder_upgrade_create_theme_cache_submit'), - ); - - $form['#submit'][] = 'coder_upgrade_settings_form_submit'; - - return system_settings_form($form); -} - -/** - * Submit handler for the settings form. - * - * Rename module input and output directories based on user settings. - */ -function coder_upgrade_settings_form_submit($form, &$form_state) { - $values = $form_state['values']; - $op = isset($values['op']) ? $values['op'] : ''; - - $cur = variable_get('coder_upgrade_dir', DEADWOOD_DIR); - $new = $op == t('Reset to defaults') ? DEADWOOD_DIR : $values['coder_upgrade_dir']; - if ($new != $cur) { - if (rename(coder_upgrade_directory_path($cur, FALSE), coder_upgrade_directory_path($new, FALSE))) { - variable_set('coder_upgrade_dir_old', $new . '/old'); - variable_set('coder_upgrade_dir_new', $new . '/new'); - variable_set('coder_upgrade_dir_patch', $new . '/patch'); - drupal_set_message(t('Base directory was renamed to ' . $new . '.')); - } - else { - // Reset the directory variable. - variable_set('coder_upgrade_dir', $cur); - drupal_set_message(t('Could not rename base directory'), 'error'); - } - } -} - -/** - * Submit callback; creates a core theme information cache file. - * - * This file is used when the upgrade routines are run in a separate process. - */ -function coder_upgrade_create_theme_cache_submit($form, &$form_state) { - global $_coder_upgrade_theme_registry; - - module_load_include('inc', 'coder_upgrade', 'includes/main'); - module_load_include('inc', 'coder_upgrade', 'conversions/begin'); - // Create a core theme information cache. - coder_upgrade_cache_theme_registry(); - // Write cache to file. - $path = coder_upgrade_path('theme_cache'); - if (file_put_contents($path, serialize($_coder_upgrade_theme_registry)) === FALSE) { - drupal_set_message(t('Could not write to core theme information cache file.'), 'error'); - return; - } - drupal_set_message(t('Core theme information cache created at !file.', array('!file' => $path))); -} - -/** - * Form builder for the module conversion form. - * - * The tab contents are assembled in helper functions which allows other modules - * to "customize" this form directly without resorting to hook_form_alter. - */ -function coder_upgrade_conversions_form($form, &$form_state) { - // Set default values. - list($upgrades, $extensions, $directories, $modules) = coder_upgrade_conversions_form_defaults($form_state); - - // Build the form. - $form['tabs'] = array( - '#type' => 'vertical_tabs', - '#default_tab' => 'edit-directories', - ); - $form['tabs']['upgrades'] = coder_upgrade_upgrades_build($upgrades); - $form['tabs']['extensions'] = coder_upgrade_extensions_build($extensions); - $form['tabs']['directories'] = coder_upgrade_directories_build($directories); - $form['tabs']['modules'] = coder_upgrade_modules_build($modules); - - $form['convert'] = array( - '#type' => 'submit', - '#value' => t('Convert files'), -// '#disabled' => empty($form['tabs']['directories']['list']['#options']), - ); - - return $form; -} - -/** - * Returns form content for upgrades tab. - * - * @param array $upgrades - * User selections or default values. - * @return array - * Form item. - */ -function coder_upgrade_upgrades_build(&$upgrades) { - // Create the list of upgrade options from the coder upgrade plug-ins. - // Maintain a secondary list based on title only, to make sorting possible. - $upgrades_all = _coder_upgrade_upgrades(); - foreach ($upgrades_all as $name => $upgrade) { - $upgrade_options[$name] = isset($upgrade['link']) ? l($upgrade['title'], $upgrade['link']) : $upgrade['title']; - if (isset($upgrade['description'])) { - $upgrade_options[$name] .= ' (' . $upgrade['description'] . ')'; - } - $upgrades_sort[$name] = $upgrade['title']; - } - - // Sort the upgrades by title. - asort($upgrades_sort); - foreach ($upgrades_sort as $name => $upgrade) { - $upgrades_sort[$name] = $upgrade_options[$name]; - } - - // Build the upgrade list. - $header = array( - 'category' => array('data' => t('Category'), 'field' => 'category'), -// 'description' => array('data' => t('Description'), 'field' => 'description'), - ); - $i = 0; - $rows = array(); - foreach ($upgrades_sort as $name => $upgrade) { - $row = array(); - $row['category'] = $upgrades_sort[$name]; - $row['description'] = 'Missing'; - $row['#weight'] = ++$i; - - $rows[$name] = $row; - } - $upgrade_fs = array( - '#type' => 'fieldset', - '#title' => t('Upgrades'), - '#description' => t('Apply the selected conversion routines ...'), - '#tree' => TRUE, - ); - $upgrade_fs['list'] = array( - '#type' => 'tableselect', - '#header' => $header, - '#options' => $rows, - '#default_value' => isset($upgrades) ? $upgrades : array(), - '#empty' => t('No routines available'), - ); - - return $upgrade_fs; -} - -/** - * Returns form content for file extensions tab. - * - * @param array $extensions - * User selections or default values. - * @return array - * Form item. - */ -function coder_upgrade_extensions_build(&$extensions) { - // Build the file extension list. - $types = array( - 'inc' => 'PHP code files', - 'info' => 'Info files used with module installation', - 'install' => 'PHP code files used with module installation, update and uninstallation', - 'module' => 'PHP code files', - 'php' => 'PHP code files', - 'profile' => 'PHP code files used with site installation', - 'test' => 'SimpleTest files', - 'theme' => 'PHP code files used with theming', - ); - $header = array( - 'extension' => array('data' => t('Extension'), 'field' => 'extension'), - 'description' => array('data' => t('Description'), 'field' => 'description'), - ); - $i = 0; - $rows = array(); - foreach ($types as $key => $description) { - $row = array(); - $row['extension'] = $key; - $row['description'] = $description; - $row['#weight'] = ++$i; - - $rows[$key] = $row; - } - $extension_fs = array( - '#type' => 'fieldset', - '#title' => t('Extensions'), - '#description' => t('... to files with the selected file extensions ...'), - '#tree' => TRUE, - ); - $extension_fs['list'] = array( - '#type' => 'tableselect', - '#header' => $header, - '#options' => $rows, - '#default_value' => isset($extensions) ? $extensions : array(), - '#empty' => t('No extensions available'), - ); - - return $extension_fs; -} - -/** - * Returns form content for directories tab. - * - * @param array $directories - * User selections or default values. - * @return array - * Form item. - */ -function coder_upgrade_directories_build(&$directories) { - // Build the directory list. - $deadwood_dir = variable_get('coder_upgrade_dir_old', DEADWOOD_OLD); - $path = realpath(coder_upgrade_directory_path('old', FALSE)); - $dirs = coder_upgrade_scan_directory($path); - if (!$dirs) { - drupal_set_message(t('Please place modules to be converted in @path.', array('@path' => $path)), 'error'); - } - - $header = array( - 'name' => array('data' => t('Name'), 'field' => 'name'), - 'path' => array('data' => t('Location'), 'field' => 'path'), - ); - $i = 0; - $rows = array(); - foreach ($dirs as $dir) { - $row = array(); - $row['name'] = isset($directories[$dir]) ? l($dir, coder_upgrade_patch_link($dir), array('attributes' => array('target' => '_blank'))) : $dir; - $row['path'] = $deadwood_dir . '/' . $dir; - $row['#weight'] = ++$i; - - $rows[$dir] = $row; - } - $directory_fs = array( - '#type' => 'fieldset', - '#title' => t('Directories'), - '#description' => t('... residing in the selected directories (beneath the files directory), or ...'), - '#tree' => TRUE, - ); - $directory_fs['list'] = array( - '#type' => 'tableselect', - '#header' => $header, - '#options' => $rows, - '#default_value' => isset($directories) ? $directories : array(), - '#empty' => t('No directories available'), - ); - - return $directory_fs; -} - -/** - * Returns form content for modules tab. - * - * @param array $modules - * User selections or default values. - * @return array - * Form item. + * Implements hook_help(). */ -function coder_upgrade_modules_build(&$modules) { - // Build the module list. - $header = array( - 'name' => array('data' => t('Name'), 'field' => 'name'), - 'path' => array('data' => t('Location'), 'field' => 'path'), - ); - $i = 0; - $rows = coder_upgrade_module_list(); - foreach ($rows as $key => $row) { - $rows[$key]['name'] = isset($modules[$key]) ? l($row['name'], coder_upgrade_patch_link($key)) : $row['name']; - $rows[$key]['#weight'] = ++$i; - } - $module_fs = array( - '#type' => 'fieldset', - '#title' => t('Modules'), - '#description' => t('... residing in the selected modules (beneath the drupal directory).'), - '#tree' => TRUE, - ); - $module_fs['list'] = array( - '#type' => 'tableselect', - '#header' => $header, - '#options' => $rows, - '#default_value' => isset($modules) ? $modules : array(), - '#empty' => t('No modules available'), - ); - - return $module_fs; -} - -/** - * Validation handler for the module conversion form. - */ -function coder_upgrade_conversions_form_validate($form, &$form_state) { - // Set keys to validate. - $keys = coder_upgrade_selection_types($form_state); - $count = 0; - // Validate the user selections. - $values = $form_state['values']; - foreach ($values as $key => $list) { - if (!in_array($key, $keys)) { - continue; - } - $selections = coder_upgrade_selections_extract($list['list']); - if (in_array($key, array('upgrades', 'extensions')) && !count($selections)) { - form_set_error($key, t('Please select at least one item in the %item tab.', array('%item' => ucfirst($key)))); - } - elseif (in_array($key, array('directories', 'modules'))) { - $count += count($selections); - } - } - // Determine if keys contains both 'directories' and 'modules'. - $test = array_diff(array('directories', 'modules'), $keys); - if (!$count && empty($test)) { - form_set_error($key, t('Please select at least one item in the %item1 or %item2 tabs.', array('%item1' => ucfirst('directories'), '%item2' => ucfirst('modules')))); - } -} - -/** - * Submit handler for the module conversion form. - * - * Execute the selected module conversion code on the selected file types in the - * selected directories or modules. - */ -function coder_upgrade_conversions_form_submit($form, &$form_state) { - // Rebuild form with user selections. - $form_state['rebuild'] = TRUE; - - // Apply conversion functions. - $success = coder_upgrade_conversions_apply($form_state); - if ($success) { - drupal_set_message(t('Module conversion routines were applied.')); - drupal_set_message(t('Click to view the !log.', array('!log' => l(t('conversion log file'), coder_upgrade_path('log'), array('attributes' => array('target' => '_blank')))))); - drupal_set_message(t('To view a patch file, click on a Name link in the Directories and Modules tabs below.')); - } - else { - drupal_set_message(t('Module conversion routines failed to complete.'), 'error'); - } -} - -/** - * Applies the module conversion code. - * - * Execute the selected module conversion code on the selected file types in the - * selected directories or modules. - * - * @return boolean - * TRUE if conversion code was successful, FALSE otherwise. - */ -function coder_upgrade_conversions_apply($form_state) { - // Prepare conversion parameters. - list($upgrades, $extensions, $items) = coder_upgrade_conversions_prepare($form_state); - - // Apply conversion functions. - module_load_include('inc', 'coder_upgrade', 'includes/main'); - if (variable_get('coder_upgrade_use_separate_process', FALSE)) { - // Conversion code will be run in a separate process. - drupal_set_message(t('Module conversion routines will run in a separate process.')); - $path = coder_upgrade_parameters_save($upgrades, $extensions, $items); - $script = drupal_get_path('module', 'coder_upgrade') . '/scripts/coder_upgrade.run.php'; - $output = coder_upgrade_directory_path('base') . 'coder_upgrade.run.txt'; - $command = "php $script -- file=$path > $output"; // " 2>&1"; - // Execute the command and capture the output. - exec($command, $errors, $success); - $success = $success === 0; - if ($success && !empty($errors)) { - drupal_set_message(trim(implode("\n", $errors)), 'error'); - } - } - else { - // Conversion code will be run in the same process. - drupal_set_message(t('Module conversion routines will run in the same process.')); - $success = coder_upgrade_start($upgrades, $extensions, $items); - } - - return $success; -} - -/** - * Returns the parameters to submit for module conversion. - */ -function coder_upgrade_conversions_prepare($form_state) { - // Gather the submitted parameters. - list($upgrades, $extensions, $directories, $modules) = coder_upgrade_selections($form_state); - - // TODO Cache this list so we don't have to query all the files again. - $upgrades_all = _coder_upgrade_upgrades(); - foreach ($upgrades as $name => $upgrade) { - $upgrades[$name] = array( - 'module' => isset($upgrades_all[$name]['module']) ? $upgrades_all[$name]['module'] : '', - 'files' => isset($upgrades_all[$name]['files']) ? $upgrades_all[$name]['files'] : array(), - ); - } - - $old_dir = DRUPAL_ROOT . '/' . coder_upgrade_directory_path('old'); - $new_dir = DRUPAL_ROOT . '/' . coder_upgrade_directory_path('new'); - - // Combine directory and module items into a single list. - // Omit name from key so as to allow for duplicate names. - // TODO Handle duplicate names when making new conversion directories. - // Could intersect keys in $directories, $modules; then add counter suffix to new_dir??? - // Use global counter??? Or copy $directories to files/dirs and $modules to files/modules??? - $items = array(); - - foreach ($directories as $key => $directory) { - $items[] = array( - 'name' => $key, - 'old_dir' => $old_dir . $key, - 'new_dir' => $new_dir . $key, - ); - } - - $last = 'xx_XX'; - $rows = coder_upgrade_module_list(); - foreach ($modules as $key => $module) { - if (isset($rows[$key])) { - $row = $rows[$key]; - if (strpos($row['dir'] . '/', $last . '/') === 0) { - // Omit modules contained in subdirectory of a parent module. - continue; - } - $last = $row['dir']; - $items[] = array( - 'name' => $key, - 'old_dir' => $row['dir'], - 'new_dir' => $new_dir . $key, - ); - } - } - - return array($upgrades, $extensions, $items); -} - -/** - * Saves the runtime parameters to a file for use by script. - */ -function coder_upgrade_parameters_save($upgrades, $extensions, $items) { - // Add path to upgrades array for use by script. - foreach ($upgrades as $name => &$upgrade) { - $upgrade['path'] = drupal_get_path('module', $upgrade['module']); - } - // Create paths array. - $paths = array( - 'files_base' => coder_upgrade_directory_path('', FALSE), - 'modules_base' => str_replace('/coder', '', drupal_get_path('module', 'coder')), - ); - // Create variables array. - $variables = array( - 'coder_upgrade_dir' => variable_get('coder_upgrade_dir', DEADWOOD_DIR), - 'coder_upgrade_dir_patch' => variable_get('coder_upgrade_dir_patch', DEADWOOD_PATCH), - - 'coder_upgrade_replace_files' => variable_get('coder_upgrade_replace_files', FALSE), - 'coder_upgrade_preserve_array_format' => variable_get('coder_upgrade_preserve_array_format', FALSE), - 'coder_upgrade_enable_debug_output' => variable_get('coder_upgrade_enable_debug_output', FALSE), - 'coder_upgrade_enable_parser_debug_output' => variable_get('coder_upgrade_enable_parser_debug_output', FALSE), - 'coder_upgrade_use_separate_process' => variable_get('coder_upgrade_use_separate_process', FALSE), - ); - // Create parameters array. - $parameters['paths'] = $paths; - $parameters['theme_cache'] = coder_upgrade_path('theme_cache'); - $parameters['variables'] = $variables; - $parameters['upgrades'] = $upgrades; - $parameters['extensions'] = $extensions; - $parameters['items'] = $items; - - // Write parameters to file. - $path = coder_upgrade_path('runtime'); // @todo Use random name and delete afterwards. - file_put_contents($path, serialize($parameters)); - - return $path; -} - -/** - * Sets the default values to display on the module conversions form. - * - * @return array - * Arrays of default values. - */ -function coder_upgrade_conversions_form_defaults($form_state) { - // D7: the key is used (and the value is irrelevant); D6: the value. - $upgrades = array('coder_upgrade' => 1); - - $extensions = array( - 'inc' => TRUE, - 'info' => TRUE, - 'install' => TRUE, - 'module' => TRUE, -// 'php' => FALSE, -// 'profile' => FALSE, -// 'test' => FALSE, -// 'theme' => FALSE, - ); - - $directories = array(); // 'samples' => 1; - - $modules = array(); - - if (!isset($form_state['values'])) { - return array($upgrades, $extensions, $directories, $modules); - } - - // Set defaults from submitted values. - return coder_upgrade_selections($form_state); -} - -/** - * Returns all submitted values. - * - * @param array $values - * Array of $form_state['values']. - * @return array - * Arrays of submitted values. - */ -function coder_upgrade_selections($form_state) { - // Initialize these as not all may be set by some form users. - $upgrades = $extensions = $directories = $modules = array(); - - // Set keys to validate. - $keys = coder_upgrade_selection_types($form_state); - - // Build arrays of each user selection type. - $values = $form_state['values']; - foreach ($keys as $key) { - if (isset($values[$key])) { - $$key = coder_upgrade_selections_extract($values[$key]['list']); - } - } - return array($upgrades, $extensions, $directories, $modules); -} - -/** - * Returns a list of submitted values. - * - * @param array $values - * Array slice from $form_state['values']. - * @return array - * Array of submitted values. - */ -function coder_upgrade_selections_extract($values) { - $selections = array(); - foreach ($values as $key => $value) { - if ($value) { - $selections[$key] = $key; - } - } - return $selections; -} - -/** - * Returns a list of selection types. - * - * @param array $form_state - * Array of form state information. - * @return array - * Array of selection types to process. - */ -function coder_upgrade_selection_types($form_state) { - if (isset($form_state['defaults']) && is_array($form_state['defaults']) && $form_state['defaults']) { - return $form_state['defaults']; - } - return array('upgrades', 'extensions', 'directories', 'modules'); -} - -/** - * Returns list of contributed modules. - * - * @param null $core - * Indicates whether to return core modules regardless of settings variable. - * @param integer $status - * Indicates status of modules to return. - * @return array - * Array of contributed modules. - */ -function coder_upgrade_module_list($core = NULL, $status = -1) { - $test = is_null($core) ? variable_get('coder_upgrade_upgrade_core', FALSE) : $core; - $like = $test ? 'LIKE' : 'NOT LIKE'; - $where = $status == -1 ? '' : 'AND status = :status'; - - // Faster to query DB than to rescan files using _system_get_module_data(). - $sql = "SELECT name, filename, type, status, info, - REPLACE(filename, CONCAT('/', name, '.', type), '') AS directory - FROM {system} - WHERE type = 'module' - AND filename $like 'modules/%' - $where - ORDER BY directory, name"; - $default_value = 0; - $results = db_query($sql, array(':status' => $status)); - $rows = array(); - foreach ($results as $module) { - $info = unserialize($module->info); - $row = array(); - $row['name'] = $info['name']; - $row['path'] = dirname($module->filename); // $module->filename; - $row['dir'] = $module->directory; // dirname($module->filename); -// $row['filename'] = $module->filename; // Add this for later calls to module_list(). -// $row['status'] = $module->status; - // TODO Pull files from this table??? - // Would need to change the conversion code to not read the filesystem. - - $rows[$module->name] = $row; - } - return $rows; -} - -/** - * Returns link to patch file. - * - * @param string $name - * String of the patch filename. - * @return string - * Link to file. - */ -function coder_upgrade_patch_link($name) { - return 'files/coder_upgrade/patches/' . $name . '.patch'; -} - -/** - * Returns patch file wrapped in html tags. - * - * @param string $filename - * String of the patch filename. - * @return string - * HTML output. - */ -function coder_upgrade_patch_display($filename) { - echo '
' . check_plain(file_get_contents(coder_upgrade_patch_path($filename))) . '
'; -} - -/** - * Returns path to patch file. - * - * @param string $filename - * String of the patch filename. - * @return string - * Path to file. - */ -function coder_upgrade_patch_path($filename) { - static $dirname = ''; - - if (!$dirname) { - $dirname = coder_upgrade_directory_path('patch'); +function coder_upgrade_help($path, $arg) { + if (strpos($path, 'admin/config/development/coder/upgrade') === 0 || $path == 'admin/help#coder_upgrade') { + module_load_include('inc', 'coder_upgrade', 'includes/help'); + return _coder_upgrade_help($path, $arg); } - return $dirname . "$filename"; } diff --git a/coder_upgrade/coder_upgrade.test b/coder_upgrade/coder_upgrade.test index eac4daba80f90b7f63c5b8d64bb958ea6222af2f..921aba502f034be4ad88fd7914bbef9e63190524 100644 --- a/coder_upgrade/coder_upgrade.test +++ b/coder_upgrade/coder_upgrade.test @@ -1,8 +1,7 @@ data; @@ -890,6 +890,7 @@ function coder_upgrade_new_filter_hook($node, $hook, $filters = array()) { // DO * * @param PGPNode $node * A node object containing a PGPClass (or function) item. + * * @return array * Array of tip callback functions indexed by $delta. */ @@ -1414,6 +1415,7 @@ function coder_upgrade_convert_op(&$node, $callback, $op_index) { * A list of conditions to an if block. * @param string $op * A string of the hook operation. + * * @return array * Array of operations referenced in the if block. */ @@ -1994,7 +1996,7 @@ function coder_upgrade_convert_return(&$body, $hook, $callback = '', $start_dept $already_searched = array(); while (!empty($nodes)) { - cdp('while(!empty($nodes)) ' . __FUNCTION__); + cdp('while (!empty($nodes)) ' . __FUNCTION__); $return_node = array_shift($nodes); $return = $return_node->data; @@ -2085,6 +2087,7 @@ function coder_upgrade_convert_return(&$body, $hook, $callback = '', $start_dept * The assignment variable (left of assignment operator). * @param PGPExpression $value * The assignment value (right of assignment operator). + * * @return PGPExpression * The new array expression. */ diff --git a/coder_upgrade/conversions/install.inc b/coder_upgrade/conversions/install.inc index c47f567f5cf827d3aebaa5fa9d02b881ad5d1761..1ea51cdd259e7419625dcd4d6696aab1ab69a470 100644 --- a/coder_upgrade/conversions/install.inc +++ b/coder_upgrade/conversions/install.inc @@ -1,9 +1,9 @@ insertElement($position, $comment); } - -/** - * Implements hook_upgrade_regex_info_alter(). - * - * Alters the text of a code file using regular expressions. - * - * Module Info / Install - * http://drupal.org/node/224333#info_core_7 (this anchor does not exist on the chronological page) - * - * @param string $file - * The text of the file to convert. - */ -function coder_upgrade_upgrade_regex_info_alter(&$file) { - cdp("inside " . __FUNCTION__); - $hook = 'info_file'; - $cur = $file; - $new = $cur; - - $from = array(); - $to = array(); - - // Info file should specify core = 7.x. - $from[] = '@^core\s+=\s+.*?$@m'; - $to[] = 'core = 7.x'; - - coder_upgrade_do_conversions($from, $to, $new); - coder_upgrade_save_changes($cur, $new, $file, $hook); -} diff --git a/coder_upgrade/conversions/list.inc b/coder_upgrade/conversions/list.inc index 5343d88b7b8284ab4fd6adc39c22f828795d3e0b..66bc29f10a07695bb4f6fa52031f750e2568d972 100644 --- a/coder_upgrade/conversions/list.inc +++ b/coder_upgrade/conversions/list.inc @@ -1,8 +1,7 @@ 'vertical_tabs', + '#default_tab' => 'edit-directories', + ); + $form['tabs']['upgrades'] = coder_upgrade_upgrades_build($upgrades); + $form['tabs']['extensions'] = coder_upgrade_extensions_build($extensions); + $form['tabs']['directories'] = coder_upgrade_directories_build($directories); + $form['tabs']['modules'] = coder_upgrade_modules_build($modules); + + $form['convert'] = array( + '#type' => 'submit', + '#value' => t('Convert files'), +// '#disabled' => empty($form['tabs']['directories']['list']['#options']), + ); + + return $form; +} + +/** + * Returns form content for upgrades tab. + * + * @param array $upgrades + * User selections or default values. + * + * @return array + * Form item. + */ +function coder_upgrade_upgrades_build(&$upgrades) { + // Create the list of upgrade options from the coder upgrade plug-ins. + // Maintain a secondary list based on title only, to make sorting possible. + $upgrades_all = _coder_upgrade_upgrades(); + foreach ($upgrades_all as $name => $upgrade) { + $upgrade_options[$name] = isset($upgrade['link']) ? l($upgrade['title'], $upgrade['link']) : $upgrade['title']; + if (isset($upgrade['description'])) { + $upgrade_options[$name] .= ' (' . $upgrade['description'] . ')'; + } + $upgrades_sort[$name] = $upgrade['title']; + } + + // Sort the upgrades by title. + asort($upgrades_sort); + foreach ($upgrades_sort as $name => $upgrade) { + $upgrades_sort[$name] = $upgrade_options[$name]; + } + + // Build the upgrade list. + $header = array( + 'category' => array('data' => t('Category'), 'field' => 'category'), +// 'description' => array('data' => t('Description'), 'field' => 'description'), + ); + $i = 0; + $rows = array(); + foreach ($upgrades_sort as $name => $upgrade) { + $row = array(); + $row['category'] = $upgrades_sort[$name]; + $row['description'] = 'Missing'; + $row['#weight'] = ++$i; + + $rows[$name] = $row; + } + $upgrade_fs = array( + '#type' => 'fieldset', + '#title' => t('Upgrades'), + '#description' => t('Apply the selected conversion routines ...'), + '#tree' => TRUE, + ); + $upgrade_fs['list'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $rows, + '#default_value' => isset($upgrades) ? $upgrades : array(), + '#empty' => t('No routines available'), + ); + + return $upgrade_fs; +} + +/** + * Returns form content for file extensions tab. + * + * @param array $extensions + * User selections or default values. + * + * @return array + * Form item. + */ +function coder_upgrade_extensions_build(&$extensions) { + // Build the file extension list. + $types = array( + 'inc' => 'PHP code files', + 'info' => 'Info files used with module installation', + 'install' => 'PHP code files used with module installation, update and uninstallation', + 'module' => 'PHP code files', + 'php' => 'PHP code files', + 'profile' => 'PHP code files used with site installation', + 'test' => 'SimpleTest files', + 'theme' => 'PHP code files used with theming', + ); + $header = array( + 'extension' => array('data' => t('Extension'), 'field' => 'extension'), + 'description' => array('data' => t('Description'), 'field' => 'description'), + ); + $i = 0; + $rows = array(); + foreach ($types as $key => $description) { + $row = array(); + $row['extension'] = $key; + $row['description'] = $description; + $row['#weight'] = ++$i; + + $rows[$key] = $row; + } + $extension_fs = array( + '#type' => 'fieldset', + '#title' => t('Extensions'), + '#description' => t('... to files with the selected file extensions ...'), + '#tree' => TRUE, + ); + $extension_fs['list'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $rows, + '#default_value' => isset($extensions) ? $extensions : array(), + '#empty' => t('No extensions available'), + ); + + return $extension_fs; +} + +/** + * Returns form content for directories tab. + * + * @param array $directories + * User selections or default values. + * + * @return array + * Form item. + */ +function coder_upgrade_directories_build(&$directories) { + // Build the directory list. + $deadwood_dir = variable_get('coder_upgrade_dir_old', DEADWOOD_OLD); + $path = realpath(coder_upgrade_directory_path('old', FALSE)); + $dirs = coder_upgrade_scan_directory($path); + if (!$dirs) { + drupal_set_message(t('Please place modules to be converted in @path.', array('@path' => $path)), 'error'); + } + + $header = array( + 'name' => array('data' => t('Name'), 'field' => 'name'), + 'path' => array('data' => t('Location'), 'field' => 'path'), + ); + $i = 0; + $rows = array(); + foreach ($dirs as $dir) { + $row = array(); + $row['name'] = isset($directories[$dir]) ? l($dir, coder_upgrade_patch_link($dir), array('attributes' => array('target' => '_blank'))) : $dir; + $row['path'] = $deadwood_dir . '/' . $dir; + $row['#weight'] = ++$i; + + $rows[$dir] = $row; + } + $directory_fs = array( + '#type' => 'fieldset', + '#title' => t('Directories'), + '#description' => t('... residing in the selected directories (beneath the files directory), or ...'), + '#tree' => TRUE, + ); + $directory_fs['list'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $rows, + '#default_value' => isset($directories) ? $directories : array(), + '#empty' => t('No directories available'), + ); + + return $directory_fs; +} + +/** + * Returns form content for modules tab. + * + * @param array $modules + * User selections or default values. + * + * @return array + * Form item. + */ +function coder_upgrade_modules_build(&$modules) { + // Build the module list. + $header = array( + 'name' => array('data' => t('Name'), 'field' => 'name'), + 'path' => array('data' => t('Location'), 'field' => 'path'), + ); + $i = 0; + $rows = coder_upgrade_module_list(); + foreach ($rows as $key => $row) { + $rows[$key]['name'] = isset($modules[$key]) ? l($row['name'], coder_upgrade_patch_link($key)) : $row['name']; + $rows[$key]['#weight'] = ++$i; + } + $module_fs = array( + '#type' => 'fieldset', + '#title' => t('Modules'), + '#description' => t('... residing in the selected modules (beneath the drupal directory).'), + '#tree' => TRUE, + ); + $module_fs['list'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $rows, + '#default_value' => isset($modules) ? $modules : array(), + '#empty' => t('No modules available'), + ); + + return $module_fs; +} + +/** + * Validation handler for the module conversion form. + */ +function coder_upgrade_conversions_form_validate($form, &$form_state) { + // Set keys to validate. + $keys = coder_upgrade_selection_types($form_state); + $count = 0; + // Validate the user selections. + $values = $form_state['values']; + foreach ($values as $key => $list) { + if (!in_array($key, $keys)) { + continue; + } + $selections = coder_upgrade_selections_extract($list['list']); + if (in_array($key, array('upgrades', 'extensions')) && !count($selections)) { + form_set_error($key, t('Please select at least one item in the %item tab.', array('%item' => ucfirst($key)))); + } + elseif (in_array($key, array('directories', 'modules'))) { + $count += count($selections); + } + } + // Determine if keys contains both 'directories' and 'modules'. + $test = array_diff(array('directories', 'modules'), $keys); + if (!$count && empty($test)) { + form_set_error($key, t('Please select at least one item in the %item1 or %item2 tabs.', array('%item1' => ucfirst('directories'), '%item2' => ucfirst('modules')))); + } +} + +/** + * Submit handler for the module conversion form. + * + * Execute the selected module conversion code on the selected file types in the + * selected directories or modules. + */ +function coder_upgrade_conversions_form_submit($form, &$form_state) { + // Rebuild form with user selections. + $form_state['rebuild'] = TRUE; + + // Apply conversion routines. + $success = coder_upgrade_conversions_apply($form_state); + if ($success) { + drupal_set_message(t('Module conversion routines were applied.')); + drupal_set_message(t('Click to view the !log.', array('!log' => l(t('conversion log file'), coder_upgrade_path('log'), array('attributes' => array('target' => '_blank')))))); + drupal_set_message(t('To view a patch file, click on a Name link in the Directories and Modules tabs below.')); + } + else { + drupal_set_message(t('Module conversion routines failed to complete.'), 'error'); + } +} + +/** + * Applies the module conversion code. + * + * Execute the selected module conversion code on the selected file types in the + * selected directories or modules. + * + * @return boolean + * TRUE if conversion code was successful, FALSE otherwise. + */ +function coder_upgrade_conversions_apply($form_state) { + // Prepare conversion parameters. + list($upgrades, $extensions, $items) = coder_upgrade_conversions_prepare($form_state); + + // Apply conversion routines. +// module_load_include('inc', 'coder_upgrade', 'includes/main'); + if (variable_get('coder_upgrade_use_separate_process', FALSE)) { + // Conversion routines will be run in a separate process. + drupal_set_message(t('Module conversion routines will run in a separate process.')); + $path = coder_upgrade_parameters_save($upgrades, $extensions, $items); + $script = drupal_get_path('module', 'coder_upgrade') . '/scripts/coder_upgrade.run.php'; + $output = coder_upgrade_directory_path('base') . 'coder_upgrade.run.txt'; + $command = "php $script -- file=$path > $output"; // " 2>&1"; + // Execute the command and capture the output. + exec($command, $errors, $success); + $success = $success === 0; + if ($success && !empty($errors)) { + drupal_set_message(trim(implode("\n", $errors)), 'error'); + } + } + else { + // Conversion routines will be run in the same process. + module_load_include('inc', 'coder_upgrade', 'includes/main'); + drupal_set_message(t('Module conversion routines will run in the same process.')); + $success = coder_upgrade_start($upgrades, $extensions, $items); + } + + return $success; +} + +/** + * Returns the parameters to submit for module conversion. + */ +function coder_upgrade_conversions_prepare($form_state) { + // Gather the submitted parameters. + list($upgrades, $extensions, $directories, $modules) = coder_upgrade_selections($form_state); + + // TODO Cache this list so we don't have to query all the files again. + $upgrades_all = _coder_upgrade_upgrades(); + foreach ($upgrades as $name => $upgrade) { + $upgrades[$name] = array( + 'module' => isset($upgrades_all[$name]['module']) ? $upgrades_all[$name]['module'] : '', + 'files' => isset($upgrades_all[$name]['files']) ? $upgrades_all[$name]['files'] : array(), + ); + } + + $old_dir = DRUPAL_ROOT . '/' . coder_upgrade_directory_path('old'); + $new_dir = DRUPAL_ROOT . '/' . coder_upgrade_directory_path('new'); + + // Combine directory and module items into a single list. + // Omit name from key so as to allow for duplicate names. + // TODO Handle duplicate names when making new conversion directories. + // Could intersect keys in $directories, $modules; then add counter suffix to new_dir??? + // Use global counter??? Or copy $directories to files/dirs and $modules to files/modules??? + $items = array(); + + foreach ($directories as $key => $directory) { + $items[] = array( + 'name' => $key, + 'old_dir' => $old_dir . $key, + 'new_dir' => $new_dir . $key, + ); + } + + $last = 'xx_XX'; + $rows = coder_upgrade_module_list(); + foreach ($modules as $key => $module) { + if (isset($rows[$key])) { + $row = $rows[$key]; + if (strpos($row['dir'] . '/', $last . '/') === 0) { + // Omit modules contained in subdirectory of a parent module. + continue; + } + $last = $row['dir']; + $items[] = array( + 'name' => $key, + 'old_dir' => $row['dir'], + 'new_dir' => $new_dir . $key, + ); + } + } + + return array($upgrades, $extensions, $items); +} + +/** + * Saves the runtime parameters to a file for use by script. + */ +function coder_upgrade_parameters_save($upgrades, $extensions, $items) { + // Add path to upgrades array for use by script. + foreach ($upgrades as $name => &$upgrade) { + $upgrade['path'] = drupal_get_path('module', $upgrade['module']); + } + // Create paths array. + $paths = array( + 'files_base' => coder_upgrade_directory_path('', FALSE), + 'modules_base' => str_replace('/coder', '', drupal_get_path('module', 'coder')), + ); + // Create variables array. + $variables = array( + 'coder_upgrade_dir' => variable_get('coder_upgrade_dir', DEADWOOD_DIR), + 'coder_upgrade_dir_patch' => variable_get('coder_upgrade_dir_patch', DEADWOOD_PATCH), + + 'coder_upgrade_replace_files' => variable_get('coder_upgrade_replace_files', FALSE), + 'coder_upgrade_preserve_array_format' => variable_get('coder_upgrade_preserve_array_format', FALSE), + 'coder_upgrade_enable_debug_output' => variable_get('coder_upgrade_enable_debug_output', FALSE), + 'coder_upgrade_enable_parser_debug_output' => variable_get('coder_upgrade_enable_parser_debug_output', FALSE), + 'coder_upgrade_use_separate_process' => variable_get('coder_upgrade_use_separate_process', FALSE), + ); + // Create parameters array. + $parameters['paths'] = $paths; + $parameters['theme_cache'] = coder_upgrade_path('theme_cache'); + $parameters['variables'] = $variables; + $parameters['upgrades'] = $upgrades; + $parameters['extensions'] = $extensions; + $parameters['items'] = $items; + + // Write parameters to file. + $path = coder_upgrade_path('runtime'); // @todo Use random name and delete afterwards. + file_put_contents($path, serialize($parameters)); + + return $path; +} + +/** + * Sets the default values to display on the module conversions form. + * + * @return array + * Arrays of default values. + */ +function coder_upgrade_conversions_form_defaults($form_state) { + // D7: the key is used (and the value is irrelevant); D6: the value. + $upgrades = array('coder_upgrade' => 1); + + $extensions = array( + 'inc' => TRUE, + 'info' => TRUE, + 'install' => TRUE, + 'module' => TRUE, +// 'php' => FALSE, +// 'profile' => FALSE, +// 'test' => FALSE, +// 'theme' => FALSE, + ); + + $directories = array(); // 'samples' => 1; + + $modules = array(); + + if (!isset($form_state['values'])) { + return array($upgrades, $extensions, $directories, $modules); + } + + // Set defaults from submitted values. + return coder_upgrade_selections($form_state); +} + +/** + * Returns all submitted values. + * + * @param array $values + * Array of $form_state['values']. + * + * @return array + * Arrays of submitted values. + */ +function coder_upgrade_selections($form_state) { + // Initialize these as not all may be set by some form users. + $upgrades = $extensions = $directories = $modules = array(); + + // Set keys to validate. + $keys = coder_upgrade_selection_types($form_state); + + // Build arrays of each user selection type. + $values = $form_state['values']; + foreach ($keys as $key) { + if (isset($values[$key])) { + $$key = coder_upgrade_selections_extract($values[$key]['list']); + } + } + return array($upgrades, $extensions, $directories, $modules); +} + +/** + * Returns a list of submitted values. + * + * @param array $values + * Array slice from $form_state['values']. + * + * @return array + * Array of submitted values. + */ +function coder_upgrade_selections_extract($values) { + $selections = array(); + foreach ($values as $key => $value) { + if ($value) { + $selections[$key] = $key; + } + } + return $selections; +} + +/** + * Returns a list of selection types. + * + * @param array $form_state + * Array of form state information. + * + * @return array + * Array of selection types to process. + */ +function coder_upgrade_selection_types($form_state) { + if (isset($form_state['defaults']) && is_array($form_state['defaults']) && $form_state['defaults']) { + return $form_state['defaults']; + } + return array('upgrades', 'extensions', 'directories', 'modules'); +} + +/** + * Returns list of contributed modules. + * + * @param null $core + * Indicates whether to return core modules regardless of settings variable. + * @param integer $status + * Indicates status of modules to return. + * + * @return array + * Array of contributed modules. + */ +function coder_upgrade_module_list($core = NULL, $status = -1) { + $test = is_null($core) ? variable_get('coder_upgrade_upgrade_core', FALSE) : $core; + $like = $test ? 'LIKE' : 'NOT LIKE'; + $where = $status == -1 ? '' : 'AND status = :status'; + + // Faster to query DB than to rescan files using _system_get_module_data(). + $sql = "SELECT name, filename, type, status, info, + REPLACE(filename, CONCAT('/', name, '.', type), '') AS directory + FROM {system} + WHERE type = 'module' + AND filename $like 'modules/%' + $where + ORDER BY directory, name"; + $default_value = 0; + $results = db_query($sql, array(':status' => $status)); + $rows = array(); + foreach ($results as $module) { + $info = unserialize($module->info); + $row = array(); + $row['name'] = $info['name']; + $row['path'] = dirname($module->filename); // $module->filename; + $row['dir'] = $module->directory; // dirname($module->filename); +// $row['filename'] = $module->filename; // Add this for later calls to module_list(). +// $row['status'] = $module->status; + // TODO Pull files from this table??? + // Would need to change the conversion code to not read the filesystem. + + $rows[$module->name] = $row; + } + return $rows; +} + +/** + * Returns link to patch file. + * + * @param string $name + * String of the patch filename. + * + * @return string + * Link to file. + */ +function coder_upgrade_patch_link($name) { + return 'files/coder_upgrade/patch/' . $name . '.patch'; +} + +/** + * Returns patch file wrapped in html tags. + * + * @param string $filename + * String of the patch filename. + * + * @return string + * HTML output. + */ +function coder_upgrade_patch_display($filename) { + echo '
' . check_plain(file_get_contents(coder_upgrade_patch_path($filename))) . '
'; +} + +/** + * Returns path to patch file. + * + * @param string $filename + * String of the patch filename. + * + * @return string + * Path to file. + */ +function coder_upgrade_patch_path($filename) { + static $dirname = ''; + + if (!$dirname) { + $dirname = coder_upgrade_directory_path('patch'); + } + return $dirname . "$filename"; +} diff --git a/coder_upgrade/includes/help.inc b/coder_upgrade/includes/help.inc index a6534d9e6a3c7995143c2e34ba59f47e394338a4..d10cf6d2e67750a1413a869db62de5189af54edc 100644 --- a/coder_upgrade/includes/help.inc +++ b/coder_upgrade/includes/help.inc @@ -1,5 +1,4 @@ 'Upgrade', + 'description' => 'Convert module code from version 6.x to 7.x.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('coder_upgrade_conversions_form'), + 'access arguments' => array('administer code conversions'), + 'type' => MENU_LOCAL_TASK, + 'file' => 'includes/conversion.inc', + ); + + // Run items. + $items['admin/config/development/coder/upgrade/run'] = array( + 'title' => 'Run', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + + // Settings related items. + $items['admin/config/development/coder/upgrade/settings'] = array( + 'title' => 'Settings', + 'description' => 'Configure the module conversion suite.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('coder_upgrade_settings_form'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_LOCAL_TASK, + 'file' => 'includes/settings.inc', + ); + + // Patch files. + $items['files/coder_upgrade/patch/%'] = array( + 'title' => 'Patches', + 'description' => 'Display patch file.', + 'page callback' => 'coder_upgrade_patch_display', + 'page arguments' => array(3), + 'access arguments' => array('administer code conversions'), + 'type' => MENU_CALLBACK, + 'file' => 'includes/conversion.inc', + ); + + return $items; +} diff --git a/coder_upgrade/includes/settings.inc b/coder_upgrade/includes/settings.inc new file mode 100644 index 0000000000000000000000000000000000000000..e025fd184e52e2d6ebaf6282afe5171d59e4c312 --- /dev/null +++ b/coder_upgrade/includes/settings.inc @@ -0,0 +1,134 @@ + t('Module base directory'), + '#type' => 'textfield', + '#required' => TRUE, + '#default_value' => variable_get('coder_upgrade_dir', DEADWOOD_DIR), + '#description' => t('Directory beneath the file system path (!path) in which are housed the old, new and patch directories. Default is !default. In the old directory, place the 6.x module code to be upgraded. The upgraded code is saved to the new directory and patch files are written to the patch directory.', array('!path' => $path, '!default' => DEADWOOD_DIR)), + '#size' => 30, + '#maxlength' => 255, + '#validate' => array('coder_upgrade_validate_dir'), + ); + + $form['coder_upgrade_upgrade_core'] = array( + '#type' => 'checkbox', + '#title' => t('Update Drupal core modules'), + '#default_value' => variable_get('coder_upgrade_upgrade_core', FALSE), + '#description' => t('If checked, then the list of modules to select for upgrade will be the Drupal core modules. Otherwise, the list will be created from contributed modules.'), + ); + + $form['coder_upgrade_replace_files'] = array( + '#type' => 'checkbox', + '#title' => t('Replace files'), + '#default_value' => variable_get('coder_upgrade_replace_files', FALSE), + '#description' => t('If checked, then the original file will be written to the output directory shown above and then replaced with the upgraded file. Otherwise, the upgraded file will be written to the output directory shown above.'), + ); + + $form['coder_upgrade_preserve_array_format'] = array( + '#type' => 'checkbox', + '#title' => t('Preserve array formatting'), + '#default_value' => variable_get('coder_upgrade_preserve_array_format', FALSE), + '#description' => t('If checked, then array expressions will be formatted to match the input. If not checked, then array expressions will be formatted per Drupal coding standards. This means array expressions will be inlined in function calls, function parameters, and when a single value. Otherwise, the expression will will be multiline formatted.'), + ); + + $form['coder_upgrade_enable_debug_output'] = array( + '#type' => 'checkbox', + '#title' => t('Enable debug output from coder upgrade'), + '#default_value' => variable_get('coder_upgrade_enable_debug_output', FALSE), + '#description' => t('If checked, then coder upgrade debug output will be written to the file !file. WARNING: This option should NOT be enabled except for testing and development purposes, and then only on smaller files containing the code to be debugged.', array('!file' => coder_upgrade_path('debug'))), + ); + + $form['coder_upgrade_enable_parser_debug_output'] = array( + '#type' => 'checkbox', + '#title' => t('Enable debug output from grammar parser'), + '#default_value' => variable_get('coder_upgrade_enable_parser_debug_output', FALSE), + '#description' => t('If checked, then grammar parser debug output will be written to the file !file. WARNING: This option should NOT be enabled except for testing and development purposes, and then only on smaller files containing the code to be debugged.', array('!file' => $parser->debugPath())), + ); + + $path = coder_upgrade_path('theme_cache'); + $form['performance'] = array( + '#type' => 'fieldset', + '#title' => t('Performance'), + '#description' => t('To minimize the chance of hitting PHP memory and processing time limits, it is recommended to run coder upgrade in a separate process without a Drupal bootstrap. These options were set when this module was enabled. If Drupal core has been updated on this site, then click the button below to refresh the core theme information cache file at !file.', array('!file' => $path)), + '#tree' => FALSE, + ); + + $form['performance']['coder_upgrade_use_separate_process'] = array( + '#type' => 'checkbox', + '#title' => t('Use separate process'), + '#default_value' => variable_get('coder_upgrade_use_separate_process', FALSE), + '#description' => t('If checked, then coder upgrade will be run in a separate process without a Drupal bootstrap. This helps to minimize the chance of hitting PHP memory and processing time limits.'), + ); + + $form['performance']['theme_cache'] = array( + '#type' => 'submit', + '#value' => t('Cache core theme information'), + '#submit' => array('coder_upgrade_create_theme_cache_submit'), + ); + + $form['#submit'][] = 'coder_upgrade_settings_form_submit'; + + return system_settings_form($form); +} + +/** + * Submit handler for the settings form. + * + * Rename module input and output directories based on user settings. + */ +function coder_upgrade_settings_form_submit($form, &$form_state) { + $values = $form_state['values']; + $op = isset($values['op']) ? $values['op'] : ''; + + $cur = variable_get('coder_upgrade_dir', DEADWOOD_DIR); + $new = $op == t('Reset to defaults') ? DEADWOOD_DIR : $values['coder_upgrade_dir']; + if ($new != $cur) { + if (rename(coder_upgrade_directory_path($cur, FALSE), coder_upgrade_directory_path($new, FALSE))) { + variable_set('coder_upgrade_dir_old', $new . '/old'); + variable_set('coder_upgrade_dir_new', $new . '/new'); + variable_set('coder_upgrade_dir_patch', $new . '/patch'); + drupal_set_message(t('Base directory was renamed to ' . $new . '.')); + } + else { + // Reset the directory variable. + variable_set('coder_upgrade_dir', $cur); + drupal_set_message(t('Could not rename base directory'), 'error'); + } + } +} + +/** + * Submit callback; creates a core theme information cache file. + * + * This file is used when the upgrade routines are run in a separate process. + */ +function coder_upgrade_create_theme_cache_submit($form, &$form_state) { + global $_coder_upgrade_theme_registry; + + module_load_include('inc', 'coder_upgrade', 'includes/main'); + module_load_include('inc', 'coder_upgrade', 'conversions/begin'); + // Create a core theme information cache. + coder_upgrade_cache_theme_registry(); + // Write cache to file. + $path = coder_upgrade_path('theme_cache'); + if (file_put_contents($path, serialize($_coder_upgrade_theme_registry)) === FALSE) { + drupal_set_message(t('Could not write to core theme information cache file.'), 'error'); + return; + } + drupal_set_message(t('Core theme information cache created at !file.', array('!file' => $path))); +} diff --git a/coder_upgrade/includes/utility.inc b/coder_upgrade/includes/utility.inc new file mode 100644 index 0000000000000000000000000000000000000000..428a855f2b95a6159913e980cef8d6ad71abf2b1 --- /dev/null +++ b/coder_upgrade/includes/utility.inc @@ -0,0 +1,70 @@ +