'textfield',
'#title' => t('Local D6 Directory to migrate'),
'#default_value' => variable_get('code_migrate_dir', '/sites/all/modules'),
'#size' => 50,
'#maxlength' => 150,
'#description' => t("Directory with modules to migrate without a trailing slash. For example /sites/all/modules/contrib"),
'#required' => TRUE,
);
// Modules for analysis.
$module_array = array();
$directories = variable_get('code_migrate_dir', './sites/all/modules');
// Get subdirectories in the migrating dir.
if (!empty($directories)) {
$module_array = scandir($directories);
}
// Remove . and .. directories.
foreach ($module_array as $key => $directory) {
if (!ctype_punct($directory)) {
$module_hash[$directory] = $directory;
}
}
$form['code_migrate_module_selection'] = array(
'#type' => 'checkboxes',
'#title' => t('Select Modules for Analysis'),
'#options' => $module_hash,
'#default_value' => variable_get('code_migrate_module_selection', array()),
'#description' => 'Check these boxes for the module(s) you want to migrate. The more you check off the longer the job will run. Hint: uncheck some modules if the module times out.',
'#required' => FALSE,
);
$form['analyze'] = array(
'#type' => 'markup',
'#value' => l(t('Analyze my D6 code'), 'code_migrate') . '
',
);
$form['code_migrate_remote_drupal_server'] = array(
'#type' => 'textfield',
'#title' => t('Remote Drupal Repository address'),
'#default_value' => variable_get('code_migrate_remote_drupal_server', 'http://ftp.drupal.org/files/projects/'),
'#size' => 50,
'#maxlength' => 150,
'#description' => t("Remote Drupal Repository address to get D7 CONTRIB modules from."),
'#required' => TRUE,
);
$form['contrib'] = array(
'#type' => 'markup',
'#value' => l(t('Find D7 versions of my contrib modules'), 'code_migrate_contrib') . '
',
);
$form = system_settings_form($form);
$form['buttons']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save Settings'),
);
return $form;
}
/**
* Implements hook_menu().
*/
function code_migrate_menu() {
$items = array();
$items['code_migrate'] = array(
'title' => 'Code Migrate Module.',
'page callback' => '_code_migrate_test',
'access callback' => 'user_access',
'access arguments' => array('administer code migrate'),
'type' => MENU_CALLBACK,
);
$items['admin/settings/code_migrate'] = array(
'title' => 'Code Migrate Module settings',
'description' => t('Description of the Code Migrate Module settings page'),
'page callback' => 'drupal_get_form',
'access callback' => 'user_access',
'page arguments' => array('code_migrate_settings'),
'access arguments' => array('administer code migrate'),
'type' => MENU_NORMAL_ITEM,
);
$items['code_migrate_contrib'] = array(
'title' => 'Analyze Contrib Modules in D6 vs D7',
'description' => t('Analyze Contrib Modules in D6 vs D7'),
'page callback' => '_code_migrate_contrib',
'access callback' => 'user_access',
'access arguments' => array('administer code migrate'),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implements hook_perm().
*/
function code_migrate_perm() {
return array('administer code migrate');
}
/**
* Implements hook_init().
* and prevents caching for just this module
*/
function code_migrate_init() {
if (drupal_match_path($_GET['q'], 'code_migrate')) {
$GLOBALS['conf']['cache'] = FALSE;
}
}
// **************** Hooks and Forms End ***************************
// Runs code analysis on the checked off modules,
// compares D6 API usage against D7 API
function _code_migrate_test() {
// Include the lists of D6 and D7 hooks.
require_once 'hooks_list.php';
// List all calls to functions, methods, globals, constants that are not in D7.
$output .= 'GO BACK TO ' . l('SETTINGS.', 'admin/settings/code_migrate') . '
' . _code_migrate_functions_methods();
$module_array = array();
// Module_list hook lists all bootstrapped modules on the site.
$module_array = module_list($refresh = FALSE, $bootstrap = TRUE, $sort = TRUE, $fixed_list = NULL);
$module_hash = array();
foreach ($module_array as $key => $value) {
$path = drupal_get_path('module', $key);
$info_path = $path . '/' . $key . '.info';
$info = drupal_parse_info_file($info_path);
$module_hash[$path] = $info;
}
ksort($module_hash);
$output .= 'A LIST OF MODULES ON THE SITE
';
foreach ($module_hash as $path => $info) {
$output .= $info['name'] . ' - ' . $path . ' - ' . $info['version'] . '
';
}
// List all modules as having or not having D7 version
$remote_drupal_server = variable_get('code_migrate_remote_drupal_server', 'http://ftp.drupal.org/files/projects/');
$server_response = drupal_http_request($remote_drupal_server, array(), 'GET', '', 1, 120);
$response_array = explode('a href', $server_response->data);
preg_match_all('/(>)(\S+tar\.gz)(<\/a>)/', $server_response->data, $matched);
// List all modules integrated into the D7 core.
$output .= '
MODULES INTEGRATED INTO D7 CORE
';
$integrated_hash = _code_migrate_integrated();
foreach ($module_array as $installed_module) {
if ($integrated_hash[$installed_module]) {
$output .= $installed_module . '
';
}
}
// Find all D6 hook implementations.
$output .= '
LIST OF MODULES IMPLEMENTING D6 HOOKS
';
$d6_hooks = array();
$d6_hooks = _code_migrate_d6_hooks();
foreach ($d6_hooks as $hook) {
$modules_implement = module_implements($hook);
if (!empty($modules_implement)) {
$output .= '
' . $hook .' hook';
$d7_hooks_hash = _code_migrate_d7_hooks();
if (!$d7_hooks_hash[$hook]) {
$output .= ' NOT IN D7!';
}
$output .= '
';
$output .= '---' . implode('
---', $modules_implement);
}
}
return $output;
}
// Check functions, methods, constants and globals.
function _code_migrate_functions_methods() {
// Include the lists of D6 and D7 hooks.
require_once 'hooks_list.php';
$code_files = array();
$count_rewrite = 0;
$modules_for_analysis = variable_get('code_migrate_module_selection', array());
$included_files = '.*\.php|.*\.module|.*\.inc|.*\.test|.*\.install';
foreach ($modules_for_analysis as $module_for_analysis) {
$path = drupal_get_path('module', $module_for_analysis);
$code_files = array_merge($code_files, file_scan_directory($path, $included_files, array('.', '..', 'CVS', '.svn', '.git', 'lib'), 0, TRUE, 'name', 0));
}
// Check if there are files to work with.
if (empty($code_files)) {
return 'NO FOLDERS TO SCAN, GO TO ' . l('SETTINGS', 'admin/settings/code_migrate') . ' CHECK OFF AT LEAST ONE MODULE AND SAVE SETTINGS
';
}
// Check if a content type is in the line of code.
$output .= '
A LIST OF MODULES USING A CONTENT TYPE
';
$content_type_array = node_get_types('types');
if (!empty($content_type_array)) {
$constant_pattern = '/type\s*=/';
foreach ($content_type_array as $content_type) {
$output .= $content_type->name . ', machine name ' . $content_type->type . '
';
// Heredoc syntax to construct the RegEx, the closing marker EOD has to start at the beginning of the line.
$type_pattern = <<type\s{0,5}["']/
EOS;
foreach ($code_files as $code_file_object) {
$code_file = file($code_file_object->filename);
// Iterate through lines of a file
for ($i = 0; $i < sizeof($code_file); $i++) {
if (preg_match($type_pattern, $code_file[$i]) && preg_match($constant_pattern, $code_file[$i])) {
$output .= '- in ' . $code_file_object->filename . ' at line ' . ($i + 1) . '
... ' . check_plain($code_file[$i]) . '
';
}
}
}
}
}
// Get all D6 methods, functions, globals and constants.
$output .= '
A LIST OF FUNCTIONS, METHODS, GLOBALS AND CONSTANTS IN '.
variable_get('code_migrate_dir', '') .
' NOT FOUND IN D7
';
$d6_methods = _code_migrate_d6_api();
// Get all D7 methods, functions, globals and constants and fill them into a hash.
$d7_methods = _code_migrate_d7_api();
foreach ($d7_methods->get as $category_7 => $method_array_7) {
foreach ($method_array_7 as $method_7) {
$d7_check_hash[$method_7] = 1;
}
}
// Iterate through files list.
foreach ($code_files as $file_object) {
// Iterate through categories (methods, functions, globals and constants ).
foreach ($d6_methods->get as $category => $method_array) {
// Get the URL and unset in the array for matching.
$url = $method_array['URL'];
unset($method_array['URL']);
// Iterate through methods/functions/globals/constants.
foreach ($method_array as $method) {
$matched_lines = array();
// Check if the method is empty and only select those that do not exist in D7.
if (!empty($method) && !$d7_check_hash[$method]) {
if ($category === 'Hooks') {
$pattern = '/' . $file_object->name . $method . '/';
}
else{
$pattern = '/' . $method . '/';
}
$file = file($file_object->filename);
// Iterate through lines of file.
for ($i = 0; $i < sizeof($file); $i++) {
// Check if D6 method, function, etc is in the line of code.
if (preg_match($pattern, $file[$i])) {
$matched_lines[$i+1] = $file[$i];
$count_rewrite++;
}
}
}
if (!empty($matched_lines)) {
$output .= $category . '
' . '-' . $method . '
' . 'MISSING D7 FUNCTION IN ' . $file_object->filename . '
';
foreach ($matched_lines as $number => $code) {
$output .= 'at line ' . $number . ' ' . check_plain($code) . '
';
}
}
}
}
}
$output = 'THERE ARE AT LEAST ' . $count_rewrite . ' LINES OF CODE TO REWRITE
' . $output;
return $output;
}
// Lists all modules as having or not having D7 version
function _code_migrate_contrib() {
// Counter for D7 modules
$seven_counter = 0;
// Make dirs for zipped and unzipped D7 module files
if (!is_dir('sites/default/files/zipped') ) {
if (!mkdir('sites/default/files/zipped')) {
return 'failed to make a directory in sites/default/files/';
}
}
if (!is_dir('sites/default/files/d7') ) {
if (!mkdir('sites/default/files/d7')) {
return 'failed to make a directory in sites/default/files/';
}
}
// Get local modules and try to fetch them from Drupal repository
$module_array = variable_get('code_migrate_module_selection', array());
// Check if there are files to work with.
if (empty($module_array)) {
return 'NO MODULES TO ANALYZE, GO TO ' . l('SETTINGS', 'admin/settings/code_migrate') . ' CHECK OFF AT LEAST ONE MODULE AND SAVE SETTINGS
';
}
$remote_drupal_server = variable_get('code_migrate_remote_drupal_server', 'http://ftp.drupal.org/files/projects/');
$server_response = drupal_http_request($remote_drupal_server, array(), 'GET', '', 1, 120);
$response_array = explode('a href', $server_response->data);
preg_match_all('/(>)(\S+zip)(<\/a>)/', $server_response->data, $matched);
foreach ($module_array as $six_module) {
$hits_array = array();
foreach ($matched[2] as $seven_module) {
$name_pattern = '/^' . $six_module . '-7/';
if (preg_match($name_pattern, $seven_module)) {
array_push($hits_array, $seven_module);
}
}
if (!empty($hits_array)) {
// Remove .dev versions if others exist
$nondev_version = array();
foreach ($hits_array as $key => $version) {
if (!preg_match('/dev|unstable/', $version)) {
array_push($nondev_version, $version);
}
}
if (!empty($nondev_version)) {
$hits_array = $nondev_version;
}
// Save downloaded files in the zipped dir and unzip them into the d7 dir
file_put_contents('sites/default/files/zipped/' . max($hits_array), $downloaded_module->data);
$zip = new ZipArchive;
if ($zip->open('sites/default/files/zipped/' . max($hits_array)) === TRUE) {
$zip->extractTo('sites/default/files/d7');
$seven_counter++;
}
}
}
$output .= 'THERE ARE ' . sizeof($module_array) .
' D6 MODULES YOU CHECKED OFF FOR ANALYSIS; OUT OF THEM ' .
$seven_counter . ' ARE FOUND IN D7 IN ' .
variable_get('code_migrate_remote_drupal_server', 'http://ftp.drupal.org/files/projects/') . '
' .
'ZIPPED D7 VERSIONS OF MODULES HAVE BEEN DOWNLOADED TO sites/default/files/zipped/ DIRECTORY.' .
' UNZIPPED MODULES ARE IN sites/default/files/d7
GO BACK TO ' .
l('SETTINGS.', 'admin/settings/code_migrate');
return $output;
}