Index: coder.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/coder/coder.module,v retrieving revision 1.55.2.19.4.16 diff -u -r1.55.2.19.4.16 coder.module --- coder.module 23 Jan 2008 12:30:42 -0000 1.55.2.19.4.16 +++ coder.module 30 Jan 2008 00:05:42 -0000 @@ -698,7 +698,18 @@ // do all of the code reviews foreach ($coder_args['#reviews'] as $review) { if ($result = do_coder_review($coder_args, $review)) { - $results += $result; + foreach ($result as $key => $item) { + // if we have a statistic field we need to sum the results + if ($key == '#stats') { + foreach ($result['#stats'] as $severity => $stat) { + $results['#stats'][$severity] += $stat; + } + } + // otherwise we can just add the new element to the array + else { + $results[$key] = $result[$key]; + } + } } } @@ -1012,7 +1023,7 @@ } function do_coder_review($coder_args, $review) { - $results = array(); + $results = array('#stats' => array('minor' => 0, 'normal' => 0, 'critical' => 0)); if ($review['#rules']) { // get the review's severity, used when the rule severity is not defined $default_severity = _coder_severity($review['#severity']); Index: coder_metrics/coder_metrics.module =================================================================== RCS file: coder_metrics/coder_metrics.module diff -N coder_metrics/coder_metrics.module --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ coder_metrics/coder_metrics.module 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,190 @@ + 'coder/metrics', + 'title' => t('Metrics'), + 'callback' => 'coder_metrics_page', + 'access' => user_access('view code review'), + 'type' => MENU_LOCAL_TASK, + ); + + return $items; +} + +/** + * Implementation of hook_form_alter(). + */ +function coder_metrics_form_alter($form_id, &$form) { +} + +/** + * Implementation of code review page + */ +function coder_metrics_page() { + $output .= drupal_get_form('coder_metrics_page_form'); + return $output; +} + +function coder_metrics_page_form() { + $settings = _coder_get_default_settings(); + $data = array(); + + // get this once - list of the reviews to perform + $reviews = array(); + $avail_reviews = _coder_reviews(); + $selected_reviews = $settings['coder_reviews']; + foreach ($selected_reviews as $name => $checked) { + if ($checked) { + $reviews[$name] = $avail_reviews[$name]; + } + } + + if ($coder_form = _coder_settings_form($settings, $system, $files)) { + // add style sheet + $path = drupal_get_path('module', 'coder'); + drupal_add_css($path .'/coder.css', 'module'); + + // code review non-module core files + $module_weight = 0; + + if (isset($settings['coder_core']) && $settings['coder_core']) { + $coder_args = array( + '#reviews' => $reviews, + '#severity' => $settings['coder_severity'], +// '#filename' => $filename, + ); + + $phpfiles = file_scan_directory('.', '.*\.php', array('.', '..', 'CVS'), 0, false, 'name', 0); + _coder_metrics_multifile($data, $coder_args, 'core_php', $phpfiles, 2); + + $includefiles = drupal_system_listing('.*\.inc$', 'includes', 'name', 0); + _coder_metrics_multifile($data, $coder_args, 'core_includes', $includefiles, 0); + } + + // loop through the selected modules and themes + if (isset($system)) { + $dups = array(); // used to avoid duplicate includes + foreach ($system as $name => $checked) { + if ($checked) { + // process this one file + $filename = $files[$name]; + if (!$filename) { + drupal_set_message(t('Code Review file for %module not found', array('%module' => $name))); + continue; + } + $coder_args = array( + '#reviews' => $reviews, + '#severity' => $settings['coder_severity'], + '#filename' => $filename, + ); + $results = do_coder_reviews($coder_args); + $data[$name] = array('name' => array('data' => $name), 'minor' => array('data' => 0), 'normal' => array('data' => 0), 'critical' => array('data' => 0)); + _coder_metrics_add_stats($data, $results, $name); + + // process the same directory include files + if ($settings['coder_includes']) { + // NOTE: convert to the realpath here so drupal_system_listing + // doesn't return additional paths (i.e., try "module"). + $path = str_replace('\\', '/', dirname(realpath($filename))); + $offset = strpos($path, dirname($filename)); + if (!isset($dups[$path])) { + if (substr($filename, -7) == '.module') { + $coder_args['#php_minor'] = 1; + } + $dups[$path] = 1; + $includefiles = drupal_system_listing('.*\.(inc|php|install|schema)$', $path, 'name', 0); + $includeresult = _coder_metrics_multifile($data, $coder_args, $name, $includefiles, $offset); + } + } + } + } + + uasort($data, "_element_sort"); + end($data); + $key = key($data); // Fetch the last element in the array + $max = $data[$key]['#weight']; + + foreach ($data as $name => $result) { + $score = 100 - floor(_coder_metrics_int_divide($data[$name]['#weight'] * 100, $max)); + $data[$name]['score'] = array('data' => $score . '%'); + unset($data[$name]['#weight']); + } + + $form[$name]['output'] = array( + '#value' => theme('table', array(t('Name'), t('Minor'), t('Normal'), t('Critical'), t('Score')), $data), + '#weight' => -1, + ); + } + } + return $form; + +} + +function _coder_metrics_add_stats(&$data, $results, $name) { + if ($results['#stats']) { + foreach ($results['#stats'] as $severity => $stat) { + $data[$name][$severity]['data'] = $data[$name][$severity]['data'] + $stat; + $data[$name][$severity]['class'] = 'coder-'. $severity; + $data[$name]['#weight'] = $data[$name]['#weight'] + _coder_metrics_calculate_rating($severity, $stat); + } + } +} + +/** + * Calculates the rating + * + * TODO: make the multipliers a setting + * + * @param string $severity + * @param integer $stat + * @return integer overall rating vector + */ +function _coder_metrics_calculate_rating($severity, $stat) { + switch ($severity) { + case 'minor': + return $stat * 1; + case 'normal': + return $stat * 5; + case 'critical': + return $stat * 20; + } +} + +function _coder_metrics_multifile(&$data, $coder_args, $name, $files, $offset) { + $coder_args['#name'] = $name; + foreach ($files as $file) { + $filename = drupal_substr($file->filename, $offset); + $coder_args['#filename'] = $filename; + $results = do_coder_reviews($coder_args); + if (empty($data[$name])) { + $data[$name] = array('name' => array('data' => $name), 'minor' => array('data' => 0), 'normal' => array('data' => 0), 'critical' => array('data' => 0)); + } + _coder_metrics_add_stats($data, $results, $name); + } +} + +function _coder_metrics_int_divide($x, $y) { + if ($x == 0) return 0; + if ($y == 0) return FALSE; + return ($x - ($x % $y)) / $y; +} Index: coder_metrics/coder_metrics.info =================================================================== RCS file: coder_metrics/coder_metrics.info diff -N coder_metrics/coder_metrics.info --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ coder_metrics/coder_metrics.info 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,5 @@ +; $Id$ +name = Coder Metrics +description = Developer Module that produces metrics for project coding standards compliance +package = Development +dependencies = coder