Repository: bmitch/churn-php (php)

Issue:
[Config] Paths of files
Stems from #40


Discussion:
Allow user to configure that path (or paths) of the source files it should process.
@bmitch Would you like me to attempt a PR?
@josephzidell You bet! That would be great, thanks.
@bmitch Running on a folder with 1 file, 8 LOC. My CPU is up to 30% and it's been running for over 3 mins, still no results. Windows 10, PHP 7.1.0
Figured it out. `ProcessFactory.php` uses `uniq` which isn't available on Windows systems. This should be documented in the readme.
Seems like this was fixed 2 days ago in commit `181c574415fedc057701d1db9d7fae487fabc5b2`?
@josephzidell That's true, `ProcessFactory.php` does use `uniq`. I've added #70 to make a note of that in the readme. I'll also see if there's a command I could use that would work for both platforms. Thanks for catching that.

As for 181c574415fedc057701d1db9d7fae487fabc5b2, that commit is for ignoring files.

So if you ran the command like `vendor/bin/churn run src` and had this in your churn.yml file:

```yml
filesToIgnore:
 - src/Commands/ChurnCommand.php
```

Then that file would be ignored in the processing.

This issue is to allow one (or perhaps many) paths to be configured in the churn.yml file. So for example, say you wanted it to process the files found within your `src` and `tests` folders. Currently, the only way to do this would be to run the command twice, each time on each folder:

`vendor/bin/churn run src`
`vendor/bin/churn run tests`

So I thought it would be nice in the churn.yml file you could configure this like:

```yml
folders:
 - src
 - tests
```
Then the user would just have to run

`vendor/bin/churn run`

Which would then process the files in those folders.



I thought we wanted to exclude directories, which currently **is** possible. Will do a PR for multiple dirs in the command.

Patch:
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -59,11 +59,13 @@ composer require bmitch/churn-php --dev
 
 ## How to Use? ##
 ```
-vendor/bin/churn run <path to source code>
+vendor/bin/churn run <one or more paths to source code> ...
+vendor/bin/churn run src
+vendor/bin/churn run src tests
 ```
 
 ## How to Configure?
-You may add an optional `churn.yml` file to the root of your project which can be used to configure churn-php. A sample `churm.yml` file looks like:
+You may add an optional `churn.yml` file to the root of your project which can be used to configure churn-php. A sample `churn.yml` file looks like:
 
 ```yml
 # The maximum number of files to display in the results table.
@@ -86,7 +88,7 @@ filesToIgnore:
  - src/Results/ResultsParser.php
  ```
 
-If a `churm.yml` file is omitted or an individual setting is omitted the default values above will be used.
+If a `churn.yml` file is omitted or an individual setting is omitted the default values above will be used.
 
 ## Similar Packages
 * https://github.com/danmayer/churn (Ruby)
diff --git a/src/Commands/ChurnCommand.php b/src/Commands/ChurnCommand.php
--- a/src/Commands/ChurnCommand.php
+++ b/src/Commands/ChurnCommand.php
@@ -90,7 +90,7 @@ public function __construct()
     protected function configure()
     {
         $this->setName('run')
-            ->addArgument('path', InputArgument::REQUIRED, 'Path to source to check.')
+            ->addArgument('paths', InputArgument::IS_ARRAY, 'Path to source to check.')
             ->setDescription('Check files')
             ->setHelp('Checks the churn on the provided path argument(s).');
     }
@@ -104,8 +104,8 @@ protected function configure()
     protected function execute(InputInterface $input, OutputInterface $output)
     {
         $this->startTime = microtime(true);
-        $path = $input->getArgument('path');
-        $this->filesCollection = $this->fileManager->getPhpFiles($path);
+        $paths = $input->getArgument('paths');
+        $this->filesCollection = $this->fileManager->getPhpFiles($paths);
         $this->filesCount = $this->filesCollection->count();
         $this->runningProcesses = new Collection;
         $this->completedProcessesArray = [];
@@ -155,7 +155,7 @@ protected function displayResults(OutputInterface $output, ResultCollection $res
     {
         $totalTime = microtime(true) - $this->startTime;
         echo "\n
-    ___  _   _  __  __  ____  _  _     ____  _   _  ____ 
+    ___  _   _  __  __  ____  _  _     ____  _   _  ____
    / __)( )_( )(  )(  )(  _ \( \( )___(  _ \( )_( )(  _ \
   ( (__  ) _ (  )(__)(  )   / )  ((___))___/ ) _ (  )___/
    \___)(_) (_)(______)(_)\_)(_)\_)   (__)  (_) (_)(__)      https://github.com/bmitch/churn-php\n\n";
diff --git a/src/Managers/FileManager.php b/src/Managers/FileManager.php
--- a/src/Managers/FileManager.php
+++ b/src/Managers/FileManager.php
@@ -29,24 +29,26 @@ public function __construct(Config $config)
     /**
      * Recursively finds all files with the .php extension in the provided
      * $path and returns list as array.
-     * @param  string $path Path to look for .php files.
+     * @param  array $paths Paths in which to look for .php files.
      * @return FileCollection
      */
-    public function getPhpFiles(string $path): FileCollection
+    public function getPhpFiles(array $paths): FileCollection
     {
-        $directoryIterator = new RecursiveDirectoryIterator($path);
         $files = new FileCollection;
-        foreach (new RecursiveIteratorIterator($directoryIterator) as $file) {
-            if ($file->getExtension() !== 'php') {
-                continue;
-            }
+        foreach ($paths as $path) {
+            $directoryIterator = new RecursiveDirectoryIterator($path);
+            foreach (new RecursiveIteratorIterator($directoryIterator) as $file) {
+                if ($file->getExtension() !== 'php') {
+                    continue;
+                }
 
-            if ($this->fileShouldBeIgnored($file)) {
-                continue;
-            }
+                if ($this->fileShouldBeIgnored($file)) {
+                    continue;
+                }
 
 
-            $files->push(new File(['displayPath' => $file->getPathName(), 'fullPath' => $file->getRealPath()]));
+                $files->push(new File(['displayPath' => $file->getPathName(), 'fullPath' => $file->getRealPath()]));
+            }
         }
 
         return $files;


Test patch:
diff --git a/tests/Integration/Managers/FileManagerTest.php b/tests/Integration/Managers/FileManagerTest.php
--- a/tests/Integration/Managers/FileManagerTest.php
+++ b/tests/Integration/Managers/FileManagerTest.php
@@ -25,8 +25,8 @@ public function it_can_be_instantiated()
     /** @test **/
     public function it_can_recursively_get_the_php_files_in_a_path()
     {
-        $path = __DIR__ . '';
-        $results = $this->fileManager->getPhpFiles($path);
+        $paths = [__DIR__ . ''];
+        $results = $this->fileManager->getPhpFiles($paths);
         $this->assertInstanceOf(Collection::class, $results);
         $this->assertCount(1, $results);
         $this->assertInstanceOf(File::class, $results[0]);
@@ -38,4 +38,4 @@ public function setUp()
 
         $this->fileManager = new FileManager(new Config);
     }
-}
\ No newline at end of file
+}
diff --git a/tests/Unit/Assets2/Foo2.php b/tests/Unit/Assets2/Foo2.php
new file mode 100644
--- /dev/null
+++ b/tests/Unit/Assets2/Foo2.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Acme;
+
+class Foo2
+{
+
+}
diff --git a/tests/Unit/Managers/FileManagerTest.php b/tests/Unit/Managers/FileManagerTest.php
--- a/tests/Unit/Managers/FileManagerTest.php
+++ b/tests/Unit/Managers/FileManagerTest.php
@@ -23,18 +23,24 @@ public function it_can_be_created()
     /** @test */
     public function it_can_get_the_php_files_in_a_filter()
     {
-        $this->assertCount(3, $this->fileManager->getPhpFiles(__DIR__ . '/../Assets'));
+        $this->assertCount(3, $this->fileManager->getPhpFiles([__DIR__ . '/../Assets']));
+    }
+
+    /** @test */
+    public function it_can_get_the_php_files_in_multiple_directories()
+    {
+        $this->assertCount(4, $this->fileManager->getPhpFiles([__DIR__ . '/../Assets', __DIR__ . '/../Assets2']));
     }
 
     /** @test **/
     public function it_ignores_files_specified_to_ignore_in_the_config()
     {
         $fileManager = new FileManager(new Config(['filesToIgnore' => ['Assets/Baz.php']]));
-        $this->assertCount(2, $fileManager->getPhpFiles(__DIR__ . '/../Assets'));
+        $this->assertCount(2, $fileManager->getPhpFiles([__DIR__ . '/../Assets']));
     }
 
     public function setup()
     {
         $this->fileManager = new FileManager(new Config);
     }
-}
\ No newline at end of file
+}