Skip to content
This repository was archived by the owner on Feb 27, 2020. It is now read-only.

Rebuilt scanner and options and report naming #35

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 68 additions & 83 deletions classes/options.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,18 @@ class options {
*/
const VALUE_REQUIRED = 2;


/**
* Long(Two dashes, multiple letter) Options and
* Short(One dash, single letter) Options
*
* @var array
*/
private $validShortOptions = [
private $validOptions = [
'f' => [
'option' => self::OPTION_REQUIRED,
'value' => self::VALUE_REQUIRED,
'comment' => 'Path to the file or folder to run against.',
'comment' => '(Required) Path to the file or folder to run against.',
'description' => 'The location of the file or folder to use for generating the report. A fully qualified path is recommended. Relative paths will be based off the php7mar folder.',
'example' => '-f="/path/to/folder"'
],
Expand All @@ -70,8 +72,10 @@ class options {
'option' => self::OPTION_OPTIONAL,
'value' => self::VALUE_REQUIRED,
'comment' => 'Types of tests to run.',
'description' => 'By default all tests will run. This option allows tests to be selected using a comma delimited list. Allowable values: critical, nuance, and syntax.',
'description' => 'By default all tests will run. This option allows tests to be selected using a comma delimited list.',
'example' => '-t="syntax,nuance"',
'lowercase' => true,
'comma_delimited' => true,
'allowed' => [
'critical',
'nuance',
Expand All @@ -82,18 +86,10 @@ class options {
'option' => self::OPTION_OPTIONAL,
'value' => self::VALUE_REQUIRED,
'comment' => 'File extensions to include when scanning a directory.',
'description' => 'A comma separated list of file extensions to consider as PHP files. Defaults to "php"',
'description' => 'A comma separated list of file extensions to consider as PHP files. Defaults to "php"',
'example' => '-x="php,inc"',
'comma_delimited' => true
]
];

/**
* Long(Two dashes, multiple letter) Options
*
* @var array
*/
private $validLongOptions = [
],
'php' => [
'option' => self::OPTION_OPTIONAL,
'value' => self::VALUE_REQUIRED,
Expand Down Expand Up @@ -128,22 +124,29 @@ class options {
* @access public
* @return void
*/
public function __construct() {
global $argv;

//Temporary variable so we do not override the global.
$_argv = $argv;
array_shift($_argv);
$options = $_argv;

if (empty($options)) {
public function __construct() {
$short = '';
$long = [];
foreach( $this->validOptions as $o => $opt ){
if( strlen( $o ) == 1 ){
$short .= $o .($opt['value'] == self::VALUE_REQUIRED ?':':'').($opt['value'] == self::VALUE_OPTIONAL ?'::':'' );
}else{
$long[] = $o .($opt['value'] == self::VALUE_REQUIRED ?':':'').($opt['value'] == self::VALUE_OPTIONAL ?'::':'' );
}
}
$this->options = getopt( $short, $long );
if( !$this->options ){
$this->printOptionsAndExit();
}

foreach ($options as $option) {
$this->parseOption($option);

try{
$this->enforceOptions();
}catch( \Exception $e ){
echo "\n-------------------------------------------\n";
echo $e->getMessage();
echo "\n-------------------------------------------\n";
$this->printOptionsAndExit(false);
}
$this->enforceOptions();
}

/**
Expand All @@ -152,60 +155,34 @@ public function __construct() {
* @access private
* @return void
*/
private function printOptionsAndExit() {
private function printOptionsAndExit( $verbose = true ) {
echo "Available Options:\n";
foreach ($this->validShortOptions as $option => $info) {
echo "-\033[1m{$option}\033[0m\n {$info['comment']}\n {$info['description']}\n Example: {$info['example']}\n\n";
}
foreach ($this->validLongOptions as $option => $info) {
echo "--\033[1m{$option}\033[0m\n {$info['comment']}\n {$info['description']}\n Example: {$info['example']}\n\n";
}
exit;
}

/**
* Parse a raw option
*
* @access private
* @param string Raw option from the command line.
* @return array Option name, value if provided.
*/
private function parseOption($rawOption) {
$regex = "#^(?P<option>-[a-zA-Z]{1}|--[a-zA-Z-]{2,})(?:=(?P<value>['|\"]?.+?['|\"]?))?$#";
if (preg_match($regex, trim($rawOption), $matches)) {
if (isset($matches['option'])) {
$option = ltrim($matches['option'], '-');
if (isset($matches['value'])) {
$value = $matches['value'];
}

if (strlen($option) == 1) {
//Short Option
$validOptions = $this->validShortOptions;
} elseif (strlen($option) >= 2) {
//Long Option
$validOptions = $this->validLongOptions;
foreach ($this->validOptions as $option => $info) {
$prefix = strlen( $option ) > 1 ? '--':'-';

if( $verbose ){
$format = "%s\t%s\n\t%s\n\tExample: %s\n";
printf( $format, $prefix.$option, $info['comment'], $info['description'], $info['example'] );
if( isset( $info['allowed'] )){
echo "\tAvailable options: ".implode(', ', $info['allowed'] )."\n";
}
if (!isset($validOptions[$option])) {
die("The option `{$option}` does not exist.\n");
}
if ($validOptions[$option]['value'] === self::VALUE_REQUIRED && !isset($value)) {
die("The option `{$option}` requires a value, but none was given.\n");
}
if (isset($validOptions[$option]['allowed']) || (isset($validOptions[$option]['comma_delimited']) && $validOptions[$option]['comma_delimited'] == true)) {
$value = explode(',', $value);
$value = array_map('trim', $value);
}
if (isset($validOptions[$option]['allowed'])) {
foreach ($value as $_value) {
if (!in_array($_value, $validOptions[$option]['allowed'])) {
die("The value `{$_value}` for `{$option}` is not valid.\n");
}
}
}else{
$format = "%s\t%-50s\tExample: %s";
printf( $format, $prefix.$option, $info['comment'], $info['example'] );
if( isset( $info['allowed'] )){
echo "\n\tAvailable options: ".implode(', ', $info['allowed'] );
}
$this->options[$option] = (isset($value) ? $value : true);
}
echo "\n";
/*
if( strlen( $option ) == 1 ){
echo "-\033[1m{$option}\033[0m {$info['comment']}\n {}\n Example: {$info['example']}\n";
}else{
echo "--\033[1m{$option}\033[0m {$info['comment']}\n {$info['description']}\n Example: {$info['example']}\n";
}
*/
}
exit;
}

/**
Expand All @@ -215,14 +192,22 @@ private function parseOption($rawOption) {
* @return void
*/
private function enforceOptions() {
foreach ($this->validShortOptions as $option => $info) {
if ($info['option'] === self::OPTION_REQUIRED && !isset($this->options[$option])) {
die("The option `{$option}` is required to be given.\n {$info['comment']}\n {$info['description']}\n Example: {$info['example']}\n");
}
}
foreach ($this->validLongOptions as $option => $info) {
if ($info['option'] === self::OPTION_REQUIRED && !isset($this->options[$option])) {
die("The option `{$option}` is required to be given.\n {$info['comment']}\n {$info['description']}\n Example: {$info['example']}\n");
foreach( $this->validOptions as $option => $info ){
if( isset($this->options[$option])){
if( isset($info['lowercase']) && $info['lowercase'] ){
$this->options[$option] = strtolower($this->options[$option]);
}
if( isset($info['comma_delimited']) && $info['comma_delimited'] ){
$this->options[$option] = explode(',',$this->options[$option]);
}
if( isset($info['allowed']) ){
$invalid = array_diff( $this->options[$option], $info['allowed'] );
if( $invalid ){
throw new \Exception("Invalid inputs for '{$option}': ".implode(',',$invalid));
}
}
}elseif ($info['option'] === self::OPTION_REQUIRED ){
throw new \Exception("The option `{$option}` is required.\n{$info['comment']}\n {$info['description']}\nExample: {$info['example']}\n");
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion classes/reporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function __construct($projectPath, $reportFolder = null) {
} else {
$this->reportFolder = PHP7MAR_DIR.DIRECTORY_SEPARATOR.'reports';
}
$this->fullFilePath = $this->reportFolder.DIRECTORY_SEPARATOR.date('Y-m-d H.i.s ').basename($this->projectPath, '.php').".md";
$this->fullFilePath = $this->reportFolder.DIRECTORY_SEPARATOR.basename($this->projectPath, '.php').date('_Y-m-d_H.i.s').".md";

$this->file = fopen($this->fullFilePath, 'w+');
register_shutdown_function([$this, 'onShutdown']);
Expand Down
80 changes: 37 additions & 43 deletions classes/scanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ class scanner {
* @var array
*/
private $extensions = ['php'];


/*
* Current file being examined
*/
private $currentFile = null;

/**
* Main Constructor
*
Expand All @@ -49,39 +54,15 @@ public function __construct($projectPath, $extensions = null) {
if (is_array($extensions)) {
$this->setFileExtensions($extensions);
}

$this->recursiveScan($this->projectPath);
reset($this->files);
}

/**
* Perform a recursive scan of the given path to return files only.
*
* @access private
* @param string Starting Folder
* @return void
*/
private function recursiveScan($startFolder) {
if (is_file($startFolder)) {
$this->files[] = $startFolder;
return;
}
$contents = scandir($startFolder);
foreach ($contents as $content) {
if (strpos($content, '.') === 0) {
continue;
}

$path = $startFolder.DIRECTORY_SEPARATOR.$content;
if (is_dir($path)) {
$this->recursiveScan($path);
} else {
$fileExtension = pathinfo($content, PATHINFO_EXTENSION);
if (strlen($fileExtension) == 0 || !in_array($fileExtension, $this->getFileExtensions())) {
continue;
}
$this->files[] = $path;
}

if( is_file( $projectPath ) ){
$this->files = [ $projectPath ];
}else{
$Directory = new \RecursiveDirectoryIterator($projectPath.'/');
$Iterator = new \RecursiveIteratorIterator($Directory, \RecursiveIteratorIterator::SELF_FIRST);
$this->files = new \RegexIterator($Iterator, '/^.+\.('.implode('|',$this->extensions).')$/i');
$this->files->next();
//$this->files = iterator_to_array( $Files );
}
}

Expand All @@ -92,17 +73,30 @@ private function recursiveScan($startFolder) {
* @return mixed Array of lines from the file or false for no more files.
*/
public function scanNextFile() {
$_file = each($this->files);
if ($_file === false) {
if(is_a( $this->files, 'RegexIterator' )){
$_file = $this->files->current();
$this->files->next();
}else{
list( $file, $_file ) = each($this->files);
}
if( is_a( $_file, 'SplFileInfo' )){
$file = $_file->getRealPath();
}else{
$file = $_file;
}

if(!$file) {
return false;
}
$file = $_file['value'];

$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($lines === false) {
$lines = [];

$this->currentFile = $file;

$fp = fopen( $file, 'r' );
if( $fp ){
return $fp;
}else{
return true;
}
return $lines;
}

/**
Expand All @@ -112,7 +106,7 @@ public function scanNextFile() {
* @return string File Path
*/
public function getCurrentFilePath() {
return current($this->files);
return $this->currentFile;
}

/**
Expand Down
29 changes: 18 additions & 11 deletions mar.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ public function __construct() {
* @return void
*/
private function run() {
$issues = [];
$totalFiles = 0;
$totalLines = 0;
$filePath = $this->scanner->getCurrentFilePath();
if (!$this->options->getOption('t') || in_array('syntax', $this->options->getOption('t'), true)) {
$checkSyntax = true;
$versionGood = $this->tests->getPHPVersion();
Expand All @@ -113,10 +109,16 @@ private function run() {
} else {
$checkSyntax = false;
}

while (($lines = $this->scanner->scanNextFile()) !== false) {
$issues = [];
$totalFiles = 0;
$totalLines = 0;
while (($handle = $this->scanner->scanNextFile()) !== false) {
$filePath = $this->scanner->getCurrentFilePath();
if( !is_resource($handle) ){
continue;
}
$totalFiles++;

//Check syntax and assign a line to grab if needed.
$grabLineNumber = null;
$grabLine = null;
Expand All @@ -127,9 +129,13 @@ private function run() {
}
}

foreach ($lines as $index => $line) {
$lineNumber = $index + 1;
$line = trim($line, "\r\n");
$index = 0;
while(false != ($line = fgets( $handle, 1024 ))) {
$lineNumber = ++$index;
$line = trim($line, "\r\n\t ");
if( $line == '' ){
continue;
}

if ($lineNumber == $grabLineNumber) {
$grabLine = $line;
Expand Down Expand Up @@ -187,4 +193,5 @@ static public function getRealPath($path) {
}
}
$mar = new main();
?>

?>