edsonmedina/php_testability

View on GitHub
src/FileIterator.php

Summary

Maintainability
B
6 hrs
Test Coverage
<?php
/**
 * FileIterator
 * This class deals with file iteration
 * @author Edson Medina <edsonmedina@gmail.com>
 */

namespace edsonmedina\php_testability;

use edsonmedina\php_testability\Analyser;
use edsonmedina\php_testability\ContextInterface;
use edsonmedina\php_testability\Contexts\DirectoryContext;
use edsonmedina\php_testability\Contexts\FileContext;

class FileIterator
{
    private $analyser;
    private $excludedDirs = [];
    private $processedFilesCount;
    private $verbose;

    /**
     * Runs the static analyser
     * @param Analyser $analyser Static code analysis class
     * @param bool $verbose
     */
    public function __construct (Analyser $analyser, $verbose = false)
    {
        $this->analyser = $analyser;
        $this->verbose  = $verbose;
        $this->processedFilesCount = 0;
    }

    /**
     * Scans (recursively) the path and runs the analyser for each file
     * @param ContextInterface $parent
     */
    public function iterate (ContextInterface $parent)
    {
        $path = $parent->getName();
        if (is_dir($path)) {
            foreach (new \DirectoryIterator ($path) as $fileInfo)
            {
                if ($fileInfo->isDot()) {
                    continue;
                }

                $fullPath = $path . DIRECTORY_SEPARATOR . $fileInfo->getFilename();

                if ($fileInfo->isDir() && !$this->isDirExcluded($fileInfo->getFilename())) {
                    $dir = new DirectoryContext ($fullPath);
                    $this->iterate($dir);

                    // no need to keep directories
                    // with no mathing files
                    if ($dir->hasChildren()) {
                        $parent->addChild($dir);
                    }
                } elseif ($this->hasPhpExtension($fileInfo->getFilename())) {
                    $file = new FileContext ($fullPath);

                    if ($this->verbose) {
                        echo $path . DIRECTORY_SEPARATOR . $fileInfo->getFilename() . "... ";
                    }

                    $this->analyser->scan($file);

                    if ($this->verbose) {
                        echo "OK\n";
                    } else {
                        echo ".";
                    }

                    $parent->addChild($file);
                    $this->processedFilesCount++;
                }
            }
        } else {
            $fileInfo = new \SplFileInfo ($path);
            $fullPath = $fileInfo->getPathname();

            $file = new FileContext ($fullPath);

            if ($this->verbose) {
                echo $fullPath . "... ";
            }

            $this->analyser->scan($file);

            if ($this->verbose) {
                echo "OK\n";
            } else {
                echo ".";
            }

            $parent->addChild($file);
            $this->processedFilesCount++;
        }
    }

    /**
     * Is this path excluded from the scan?
     * @param string $path
     * @return bool
     */
    public function isDirExcluded ($path)
    {
        foreach ($this->excludedDirs as $needle)
        {
            if (empty($needle)) {
                continue;
            }

            $needleLen = strlen($needle);
            $pathChunk = substr($path, -$needleLen, $needleLen);

            // check if matches end of $path
            if ($pathChunk == $needle) {
                return true;
            }
        }
        return false;
    }

    /**
     * Check for .php extension in filename
     * @param string $filename
     * @return bool
     */
    protected function hasPhpExtension ($filename)
    {
        return (substr($filename, -4, 4) == '.php');
    }

    /**
     * getter for processedFiles count
     * @return int
     */
    public function getProcessedFilesCount ()
    {
        return $this->processedFilesCount;
    }

    /**
     * Set list of excluded directories
     * @param array $dirs
     */
    public function setExcludedDirs (array $dirs)
    {
        $this->excludedDirs = $dirs;
    }
}