diff --git a/dev/tools/apstats.php b/dev/tools/apstats.php new file mode 100755 index 00000000000..585fe9be47d --- /dev/null +++ b/dev/tools/apstats.php @@ -0,0 +1,278 @@ +#!/usr/bin/env php + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file dev/tools/apstats.php + * \brief Script to report Advanced Statistics on a coding project + */ + + +$sapi_type = php_sapi_name(); +$script_file = basename(__FILE__); +$path = dirname(__FILE__) . '/'; + +// Test si mode batch +$sapi_type = php_sapi_name(); +if (substr($sapi_type, 0, 3) == 'cgi') { + echo "Error: You are using PHP for CGI. To execute " . $script_file . " from command line, you must use PHP for CLI mode.\n"; + exit(); +} + +error_reporting(E_ALL & ~ E_DEPRECATED); +define('PRODUCT', "apstats"); +define('VERSION', "1.0"); + + +print '***** '.constant('PRODUCT').' - '.constant('VERSION').' *****'."\n"; +if (empty($argv[1])) { + print 'You must run this tool being into the root of the project.'."\n"; + print 'Usage: '.constant('PRODUCT').'.php pathto/index.html [--dir-scc=pathtoscc] [--dir-phpstan=pathtophpstan]'."\n"; + print 'Example: '.constant('PRODUCT').'.php dev/tools/apstats.php documents/apstats/index.html --dir-phpstan=~/git/phpstan/htdocs/includes/bin'; + exit(0); +} + +$outputpath = $argv[1]; +$outputdir = dirname($outputpath); +$outputfile = basename($outputpath); + +if (! is_dir($outputdir)) { + print 'Error: dir '.$outputdir.' does not exists or is not writable'."\n"; + exit(1); +} + +$dirscc = ''; +$dirphpstan = ''; + +$i = 0; +while ($i < $argc) { + $reg = array(); + if (preg_match('/--dir-scc=(.*)$/', $argv[$i], $reg)) { + $dirphpstan = $reg[1]; + } + if (preg_match('/--dir-phpstan=(.*)$/', $argv[$i], $reg)) { + $dirphpstan = $reg[1]; + } + $i++; +} + + +// Count lines of code of Dolibarr itself +/* +$commandcheck = 'cloc . --exclude-dir=includes --exclude-dir=custom --ignore-whitespace --vcs=git'; +$resexec = shell_exec($commandcheck); +$resexec = (int) (empty($resexec) ? 0 : trim($resexec)); + + +// Count lines of code of external dependencies +$commandcheck = 'cloc htdocs/includes --ignore-whitespace --vcs=git'; +$resexec = shell_exec($commandcheck); +$resexec = (int) (empty($resexec) ? 0 : trim($resexec)); +*/ + +// Count lines of code of application +$commandcheck = ($dirscc ? $dirscc.'/' : '').'scc . --exclude-dir=includes,custom'; +print 'Execute SCC to count lines of code in project: '.$commandcheck."\n"; +$output_arrproj = array(); +$resexecproj = 0; +exec($commandcheck, $output_arrproj, $resexecproj); + + +// Count lines of code of dependencies +$commandcheck = ($dirscc ? $dirscc.'/' : '').'scc htdocs/includes'; +print 'Execute SCC to count lines of code in dependencies: '.$commandcheck."\n"; +$output_arrdep = array(); +$resexecdep = 0; +exec($commandcheck, $output_arrdep, $resexecdep); + + +// Get technical debt +$commandcheck = ($dirphpstan ? $dirphpstan.'/' : '').'phpstan -v analyze -a build/phpstan/bootstrap.php --memory-limit 5G --error-format=github'; +print 'Execute PHPStan to get the technical debt: '.$commandcheck."\n"; +$output_arrtd = array(); +$resexectd = 0; +exec($commandcheck, $output_arrtd, $resexectd); + +$arrayoflineofcode = array(); +$arraycocomo = array(); +$arrayofmetrics = array('Bytes'=>0, 'Files'=>0, 'Lines'=>0, 'Blanks'=>0, 'Comments'=>0, 'Code'=>0, 'Complexity'=>0); + +// Analyse $output_arrproj +foreach (array('proj', 'dep') as $source) { + print 'Analyze SCC result for lines of code for '.$source."\n"; + if ($source == 'proj') { + $output_arr = &$output_arrproj; + } elseif ($source == 'dep') { + $output_arr = &$output_arrdep; + } else { + print 'Bad value for $source'; + die(); + } + + foreach ($output_arr as $line) { + if (preg_match('/^(───|Language|Total)/', $line)) { + continue; + } + + //print $line."
\n"; + + if (preg_match('/^Estimated Cost.*\$(.*)/i', $line, $reg)) { + $arraycocomo[$source]['currency'] = preg_replace('/[^\d\.]/', '', str_replace(array(',', ' '), array('.', ''), $reg[1])); + } + if (preg_match('/^Estimated Schedule Effort.*\s([\d\s,]+)/i', $line, $reg)) { + $arraycocomo[$source]['effort'] = str_replace(array(',', ' '), array('.', ''), $reg[1]); + } + if (preg_match('/^Estimated People.*\s([\d\s,]+)/i', $line, $reg)) { + $arraycocomo[$source]['people'] = str_replace(array(',', ' '), array('.', ''), $reg[1]); + } + if (preg_match('/^Processed\s(\d+)\s/i', $line, $reg)) { + $arrayofmetrics[$source]['Bytes'] = $reg[1]; + } + + if (preg_match('/^(.*)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/', $line, $reg)) { + $arrayoflineofcode[$source][$reg[1]]['Files'] = $reg[2]; + $arrayoflineofcode[$source][$reg[1]]['Lines'] = $reg[3]; + $arrayoflineofcode[$source][$reg[1]]['Blanks'] = $reg[4]; + $arrayoflineofcode[$source][$reg[1]]['Comments'] = $reg[5]; + $arrayoflineofcode[$source][$reg[1]]['Code'] = $reg[6]; + $arrayoflineofcode[$source][$reg[1]]['Complexity'] = $reg[7]; + } + } +} + + +/* + * View + */ + +$html = ''; +$html .= ' +'; + +$html .= ''; + +$html .= '
'; +$html .= '

Advanced Project Statistics

'; +$currentDate = date("Y-m-d H:i:s"); // Format: Year-Month-Day Hour:Minute:Second +$html .= 'Generated on '.$currentDate.''; +$html .= '
'; + +$html .= '
'; +$html .= '

Lines of code

'; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +//$html .= ''; +$html .= ''; +foreach (array('proj', 'dep') as $source) { + if ($source == 'proj') { + $html .= ''; + } elseif ($source == 'dep') { + $html .= ''; + } + foreach ($arrayoflineofcode[$source] as $key => $val) { + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + //$html .= ''; + $html .= ''; + $arrayofmetrics['Files'] += $val['Files']; + $arrayofmetrics['Lines'] += $val['Lines']; + $arrayofmetrics['Blanks'] += $val['Blanks']; + $arrayofmetrics['Comments'] += $val['Comments']; + $arrayofmetrics['Code'] += $val['Code']; + $arrayofmetrics['Complexity'] += $val['Complexity']; + } +} + +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +//$html .= ''; +$html .= ''; +$html .= '
Language'; +$html .= 'FilesLinesBlanksCommentsCode'.$val['Complexity'].'
Written by project team only:
Dependencies:
'.$key.''.$val['Files'].''.$val['Lines'].''.$val['Blanks'].''.$val['Comments'].''.$val['Code'].''.$val['Complexity'].'
Total:
'.$arrayofmetrics['Bytes'].' octets'.$arrayofmetrics['Files'].''.$arrayofmetrics['Lines'].''.$arrayofmetrics['Blanks'].''.$arrayofmetrics['Comments'].''.$arrayofmetrics['Code'].''.$arrayofmetrics['Complexity'].'
'; + +$html .= ''; + +$html .= '
'; +$html .= '

Project value:


'; +$html .= 'CODOMO (Basic model) value: $'.($arraycocomo['proj']['currency'] + $arraycocomo['dep']['currency']).'
'; +$html .= 'CODOMO (Basic model) effort: '.($arraycocomo['proj']['people'] * $arraycocomo['proj']['effort'] + $arraycocomo['dep']['people'] * $arraycocomo['dep']['effort']).' Month people
'; +$html .= '
'; + +$html .= '
'; +$html .= '

Technical debt: ('.count($output_arrtd).')


'; +$html .= join('
'."\n", $output_arrtd); +$html .= '
'; + +$html .= ''; +$html .= ''; + +$fh = fopen($outputpath, 'w'); +if ($fh) { + fwrite($fh, $html); + fclose($fh); + + print 'Generation of output file '.$outputfile.' done.'."\n"; +} else { + print 'Failed to open '.$outputfile.' for ouput.'."\n"; +} diff --git a/dev/tools/src_loc.sh b/dev/tools/src_loc.sh deleted file mode 100755 index ef9861c917d..00000000000 --- a/dev/tools/src_loc.sh +++ /dev/null @@ -1,8 +0,0 @@ -# Script to count lines of code of the project - -# Count lines of code of Dolibarr itself -#cloc . --exclude-dir=includes --ignore-whitespace --vcs=git --by-file -cloc . --exclude-dir=includes --ignore-whitespace --vcs=git - -# Count lines of code of external dependencies -cloc htdocs/includes --ignore-whitespace --vcs=git diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index be9918de34f..24b5ebafd1a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3611,10 +3611,7 @@ function dol_print_phone($phone, $countrycode = '', $cid = 0, $socid = 0, $addli } // Define urlmask - $urlmask = 'ErrorClickToDialModuleNotConfigured'; - if (!empty($conf->global->CLICKTODIAL_URL)) { - $urlmask = $conf->global->CLICKTODIAL_URL; - } + $urlmask = getDolGlobalString('CLICKTODIAL_URL', 'ErrorClickToDialModuleNotConfigured'); if (!empty($user->clicktodial_url)) { $urlmask = $user->clicktodial_url; }