diff --git a/config/test.yaml b/config/config.yaml similarity index 100% rename from config/test.yaml rename to config/config.yaml diff --git a/src/System/Configuration.php b/src/System/Configuration.php index 37d3548..39bb65b 100755 --- a/src/System/Configuration.php +++ b/src/System/Configuration.php @@ -1,63 +1,58 @@ . - * - * @author Joseph Maxwell - * @copyright SwiftOtter Studios, 10/8/16 - * @package default - **/ + +declare(strict_types=1); namespace Driver\System; -use Driver\System\Configuration\YamlLoader; + +use Driver\System\Configuration\FileCollector; +use Driver\System\Configuration\FileLoader; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Yaml; +use function array_keys; +use function array_merge; +use function array_reduce; +use function array_walk; +use function count; +use function explode; +use function is_array; +use function is_int; +use function is_string; + class Configuration { - /** @var YamlLoader $loader */ - protected $loader; - - protected $nodes = [ - 'pipelines' => [] - ]; + private FileCollector $fileCollector; + private FileLoader $loader; + private array $nodes = ['pipelines' => []]; + private array $files = []; - protected $files = []; - - public function __construct(YamlLoader $loader) + public function __construct(FileCollector $fileCollector, FileLoader $fileLoader) { - $this->loader = $loader; + $this->fileCollector = $fileCollector; + $this->loader = $fileLoader; } - public function getNodes() + public function getNodes(): array { if (!count($this->files)) { - $this->loadAllConfiguration(); + foreach ($this->fileCollector->get() as $file) { + $this->loadConfigurationFor($file); + }; } return $this->nodes; } + /** + * @return mixed + */ public function getNode($node) { $path = explode('/', $node); $nodes = $this->getNodes(); return array_reduce($path, function($nodes, $item) { - if (isset($nodes[$item])) { - return $nodes[$item]; - } else { - return null; - } + return $nodes[$item] ?? null; }, $nodes); } @@ -68,7 +63,7 @@ public function getNodeString($node): string return is_string($value) ? $value : ''; } - protected function loadConfigurationFor($file) + private function loadConfigurationFor($file): void { if (!isset($this->files[$file])) { try { @@ -89,11 +84,9 @@ protected function loadConfigurationFor($file) throw $e; } } - - return $this->files[$file]; } - private function recursiveMerge(array $array1, array $array2) + private function recursiveMerge(array $array1, array $array2): array { $merged = $array1; @@ -111,10 +104,8 @@ private function recursiveMerge(array $array1, array $array2) /** * Special handling for pipelines as they don't exactly follow the key/value pattern. - * - * @param $input */ - protected function mergePipelines($new) + private function mergePipelines(array $new): array { if (!isset($this->nodes['pipelines']) || !count($this->nodes['pipelines'])) { return $new; @@ -146,7 +137,7 @@ protected function mergePipelines($new) }, []); } - protected function mergePipeline($existing, $new) + private function mergePipeline($existing, $new) { array_walk($new, function($value) use (&$existing) { $existing = $this->mergeStageIntoPipeline($existing, $value); @@ -155,24 +146,30 @@ protected function mergePipeline($existing, $new) return $existing; } - protected function mergeStageIntoPipeline($existing, $newStage) + private function mergeStageIntoPipeline(array $existing, array $newStage): array { $matched = false; - $output = array_reduce(array_keys($existing), function($carry, $existingKey) use ($existing, $newStage, &$matched) { - $existingStage = $existing[$existingKey]; - $currentMatch = isset($newStage['name']) && isset($existingStage['name']) && $newStage['name'] == $existingStage['name']; - $matched = $matched || $currentMatch; - - if (!$currentMatch) { - return $carry; - } + $output = array_reduce( + array_keys($existing), + function($carry, $existingKey) use ($existing, $newStage, &$matched) { + $existingStage = $existing[$existingKey]; + $currentMatch = isset($newStage['name']) + && isset($existingStage['name']) + && $newStage['name'] == $existingStage['name']; + $matched = $matched || $currentMatch; + + if (!$currentMatch) { + return $carry; + } - $carry[$existingKey] = array_merge($existingStage, $newStage); - $carry[$existingKey]['actions'] = array_merge($existingStage['actions'], $newStage['actions']); + $carry[$existingKey] = array_merge($existingStage, $newStage); + $carry[$existingKey]['actions'] = array_merge($existingStage['actions'], $newStage['actions']); - return $carry; - }, $existing); + return $carry; + }, + $existing + ); if (!$matched) { $output[] = $newStage; @@ -180,21 +177,4 @@ protected function mergeStageIntoPipeline($existing, $newStage) return $output; } - - protected function consolidateStage($existing, $new) - { - - } - - protected function stripFileExtension($file) - { - return pathinfo($file, PATHINFO_FILENAME); - } - - protected function loadAllConfiguration() - { - foreach ($this->loader->get() as $file) { - $this->loadConfigurationFor((string)$file); - }; - } } diff --git a/src/System/Configuration/FileCollector.php b/src/System/Configuration/FileCollector.php new file mode 100644 index 0000000..d9cc3c0 --- /dev/null +++ b/src/System/Configuration/FileCollector.php @@ -0,0 +1,71 @@ +create(self::ALLOWED_FOLDERS); + $output = []; + + foreach ($folderCollection as $folder) { + $files = array_filter(self::ALLOWED_FILES, function ($file) use ($folder) { + return file_exists($folder . '/' . $file . self::FILE_EXTENSION); + }); + + $output = array_merge($output, array_map(function ($file) use ($folder) { + return $folder . '/' . $file . self::FILE_EXTENSION; + }, $files)); + } + + return array_unique(array_reverse($output)); + } + + /** + * @return string[] + */ + public function getIndividual(string $file): array + { + $folderCollection = (new FolderCollectionFactory())->create(self::ALLOWED_FOLDERS); + $output = []; + + foreach ($folderCollection as $folder) { + $path = $folder . '/' . $file . self::FILE_EXTENSION; + + if (file_exists($path)) { + $output[] = $path; + } + } + + return $output; + } +} diff --git a/src/System/Configuration/FileLoader.php b/src/System/Configuration/FileLoader.php new file mode 100755 index 0000000..870e2d9 --- /dev/null +++ b/src/System/Configuration/FileLoader.php @@ -0,0 +1,28 @@ +folders = $folders; + } + + public function current(): string + { + return $this->folders[$this->position]; + } + + public function next(): void + { + ++$this->position; + } + + public function key(): int + { + return $this->position; + } + + public function valid(): bool + { + return isset($this->folders[$this->position]); + } + + public function rewind(): void + { + $this->position = 0; + } +} diff --git a/src/System/Configuration/FolderCollectionFactory.php b/src/System/Configuration/FolderCollectionFactory.php new file mode 100644 index 0000000..1748397 --- /dev/null +++ b/src/System/Configuration/FolderCollectionFactory.php @@ -0,0 +1,71 @@ +getFolders($this->getSearchPaths(), $allowedFolders)); + } + + /** + * @return string[] + */ + private function getSearchPaths(): array + { + $directory = realpath($_SERVER['SCRIPT_FILENAME']); + if (strpos($directory, self::VENDOR_DIRECTORY) !== false) { + list($rootDir) = explode(self::VENDOR_DIRECTORY, $directory); + return array_merge([$rootDir], $this->getVendorDirectories($rootDir)); + } + return [dirname($directory, 2)]; + } + + /** + * @return string[] + */ + private function getVendorDirectories(string $path): array + { + return glob($path . self::VENDOR_DIRECTORY . "/*/*/", GLOB_ONLYDIR); + } + + /** + * @param string[] $paths + * @param string[] $allowedFolders + * @return string[] + */ + private function getFolders(array $paths, array $allowedFolders): array + { + return array_reduce($paths, function ($acc, $path) use ($allowedFolders) { + $path = rtrim($path, '/') . '/'; + + $folders = array_filter($allowedFolders, function ($folder) use ($path) { + return file_exists($path . $folder); + }); + + return array_merge($acc, array_map(function ($folder) use ($path) { + return $path . $folder; + }, $folders)); + }, []); + } +} diff --git a/src/System/Configuration/SearchPath.php b/src/System/Configuration/SearchPath.php deleted file mode 100755 index 514d6bd..0000000 --- a/src/System/Configuration/SearchPath.php +++ /dev/null @@ -1,116 +0,0 @@ -. - * - * @author Joseph Maxwell - * @copyright SwiftOtter Studios, 12/6/16 - * @package default - **/ - -namespace Driver\System\Configuration; - -class SearchPath implements \Iterator -{ - const VENDOR_DIRECTORY = 'vendor'; - - private $searchPaths; - private $allowedFolders; - private $position = 0; - private $folders; - - public function __construct($directory = __DIR__, $allowedFolders) - { - $this->allowedFolders = $allowedFolders; - $this->searchPaths = $this->format($directory); - $this->folders = $this->findFolders($this->searchPaths); - } - - private function format($directory) - { - $hasVendorDir = false; - if (strpos($directory, self::VENDOR_DIRECTORY) !== false) { - list($initial, $continue) = explode(self::VENDOR_DIRECTORY, $directory); - $initial = [ $initial ]; - $continue = self::VENDOR_DIRECTORY . $continue; - $hasVendorDir = true; - } else { - $topOfSearch = strlen(realpath($directory.'/../../../')); - $initial = [ substr($directory, 0, $topOfSearch) ]; - $continue = substr($directory, $topOfSearch+1); - } - - $paths = $this->merge(array_merge($initial, explode('/', $continue))); - if ($hasVendorDir) { - $paths = array_merge($paths, $this->loadVendorDirectories($initial[0])); - } - - return $paths; - } - - private function merge($directories) - { - $currentPath = ''; - - return array_reduce($directories, function($acc, $path) use (&$currentPath) { - $currentPath .= $path; - if (substr($currentPath, -1) !== '/') { - $currentPath .= '/'; - } - $acc[] = $currentPath; - return $acc; - }, []); - } - - private function loadVendorDirectories($path) - { - return glob($path . self::VENDOR_DIRECTORY . "/*/*/", GLOB_ONLYDIR); - } - - private function findFolders($paths) - { - return array_reduce($paths, function($acc, $path) { - $folders = array_filter($this->allowedFolders, function($folder) use ($path) { - return file_exists($path . $folder); - }); - - return array_merge($acc, array_map(function($folder) use ($path) { - return $path . $folder; - }, $folders)); - }, []); - } - - public function current() - { - return $this->folders[$this->position]; - } - - public function next() - { - ++$this->position; - } - - public function key() - { - return $this->position; - } - - public function valid() - { - return isset($this->folders[$this->position]); - } - - public function rewind() - { - $this->position = 0; - } -} \ No newline at end of file diff --git a/src/System/Configuration/YamlLoader.php b/src/System/Configuration/YamlLoader.php deleted file mode 100755 index bd9a44c..0000000 --- a/src/System/Configuration/YamlLoader.php +++ /dev/null @@ -1,126 +0,0 @@ -. - * - * @author Joseph Maxwell - * @copyright SwiftOtter Studios, 10/15/16 - * @package default - **/ - -namespace Driver\System\Configuration; - -class YamlLoader -{ - protected $fileExtension = '.yaml'; - - protected $allowedFolders = [ - 'config', - 'config.d' - ]; - - protected $allowedFiles = [ - 'anonymize', - 'pipelines', - 'commands', - 'engines', - 'connections', - 'config', - 'reduce', - 'environments' - ]; - - public function get() - { - return $this->getAllFiltered(); - } - - public function getIndividual($file) - { - return $this->getFiltered($file); - } - - protected function getFiltered($file) - { - $searchPath = new SearchPath(__DIR__, $this->allowedFolders); - $output = []; - - foreach ($searchPath as $folder) { - $path = $folder . '/' . $file . $this->fileExtension; - - if (file_exists($path)) { - $output[] = $path; - } - } - - return $output; - } - - protected function getAllFiltered() - { - $searchPath = new SearchPath(__DIR__, $this->allowedFolders); - $output = []; - - foreach ($searchPath as $folder) { - $files = array_filter($this->allowedFiles, function($file) use ($folder) { - return file_exists($folder . '/' . $file . $this->fileExtension); - }); - - $output = array_merge($output, array_map(function($file) use ($folder) { - return $folder . '/' . $file . $this->fileExtension; - }, $files)); - } - - return array_unique(array_reverse($output)); - } - - /** - * Returns the contents of a yaml file. - * - * @param $file - * @return string - * @throws \Exception - */ - public function load($file) - { - if (!$file || !file_exists($file)) { - throw new \Exception("Filename: {$file} doesn't exist."); - } - return file_get_contents($file); - } - - protected function isAllowedFile($path, $additionalFiles = []) - { - if (!is_array($additionalFiles) && !$additionalFiles) { - $additionalFiles = []; - } else if (!is_array($additionalFiles) && $additionalFiles) { - $additionalFiles = [$additionalFiles]; - } - - if (count($additionalFiles)) { - $fileSearch = $additionalFiles; - } else { - $fileSearch = $this->allowedFiles; - } - - $usedAllowedFolders = array_filter($this->allowedFolders, function($allowedFolder) use ($path) { - return strpos($path, '/'.$allowedFolder.'/') !== false; - }); - - $usedAllowedFiles = array_filter($fileSearch, function($allowedFile) use ($path) { - $filename = explode('.', $allowedFile)[0] . $this->fileExtension; - return substr($path, 0-strlen($filename)) === $filename; - }); - - return count($usedAllowedFolders) && count($usedAllowedFiles); - } -} \ No newline at end of file diff --git a/src/System/DependencyConfig.php b/src/System/DependencyConfig.php index 88f8c48..adcc32a 100644 --- a/src/System/DependencyConfig.php +++ b/src/System/DependencyConfig.php @@ -38,7 +38,7 @@ class DependencyConfig { private bool $isDebug; - public function __construct(bool $isDebug) + public function __construct(bool $isDebug = false) { $this->isDebug = $isDebug; } diff --git a/src/Tests/Unit/Pipeline/Span/PrimaryTest.php b/src/Tests/Unit/Pipeline/Span/PrimaryTest.php index aaad444..29f0fe9 100644 --- a/src/Tests/Unit/Pipeline/Span/PrimaryTest.php +++ b/src/Tests/Unit/Pipeline/Span/PrimaryTest.php @@ -31,9 +31,12 @@ class PrimaryTest extends \PHPUnit_Framework_TestCase public function testInvokeReturnsTransport() { $pipelineName = Master::DEFAULT_NODE; - $configuration = new Configuration(new Configuration\YamlLoader()); + $configuration = new Configuration(new Configuration\FileCollector(), new Configuration\FileLoader()); $set = DI::getContainer()->make(Primary::class, ['list' => $configuration->getNode('pipelines/' . $pipelineName)]); - $this->assertTrue(is_a($set(new Transport($pipelineName, [], [], new \Driver\System\Logs\Primary()), true), TransportInterface::class)); + $this->assertTrue(is_a( + $set(new Transport($pipelineName, [], [], null, new \Driver\System\Logs\Primary()), true), + TransportInterface::class + )); } -} \ No newline at end of file +} diff --git a/src/Tests/Unit/Pipeline/Stage/PrimaryTest.php b/src/Tests/Unit/Pipeline/Stage/PrimaryTest.php index a09312a..1d90be8 100644 --- a/src/Tests/Unit/Pipeline/Stage/PrimaryTest.php +++ b/src/Tests/Unit/Pipeline/Stage/PrimaryTest.php @@ -31,9 +31,12 @@ class PrimaryTest extends \PHPUnit_Framework_TestCase public function testInvokeReturnsTransport() { $pipelineName = Master::DEFAULT_NODE; - $configuration = new Configuration(new Configuration\YamlLoader()); + $configuration = new Configuration(new Configuration\FileCollector(), new Configuration\FileLoader()); $set = DI::getContainer()->make(Primary::class, ['actions' => $configuration->getNode('pipelines/' . $pipelineName)]); - $this->assertTrue(is_a($set(new Transport($pipelineName, [], [], new \Driver\System\Logs\Primary()), true), TransportInterface::class)); + $this->assertTrue(is_a( + $set(new Transport($pipelineName, [], [], null, new \Driver\System\Logs\Primary()), true), + TransportInterface::class + )); } -} \ No newline at end of file +} diff --git a/src/Tests/Unit/System/Configuration/YamlLoaderTest.php b/src/Tests/Unit/System/Configuration/YamlLoaderTest.php deleted file mode 100755 index abc9103..0000000 --- a/src/Tests/Unit/System/Configuration/YamlLoaderTest.php +++ /dev/null @@ -1,59 +0,0 @@ -. - * - * @author Joseph Maxwell - * @copyright SwiftOtter Studios, 10/15/16 - * @package default - **/ - -namespace Driver\Tests\Unit\System\Configuration; - -use Driver\System\Configuration\YamlLoader; - -class YamlLoaderTest extends \PHPUnit_Framework_TestCase -{ - public function testAllowedFiles() - { - $configuration = new YamlLoader(); - - $method = new \ReflectionMethod($configuration, 'isAllowedFile'); - $method->setAccessible(true); - - $this->assertTrue($method->invoke($configuration, '/var/www/config/pipelines.yaml')); - $this->assertTrue($method->invoke($configuration, '/var/www/config.d/commands.yaml')); - $this->assertTrue($method->invoke($configuration, '/var/www/config.d/connections.yaml')); - - $this->assertFalse($method->invoke($configuration, '/var/www/configuration/chain.yaml')); - $this->assertFalse($method->invoke($configuration, '/var/www/test/chain.yaml')); - $this->assertFalse($method->invoke($configuration, '/var/www/config/input.yaml')); - $this->assertFalse($method->invoke($configuration, '/var/www/config.d/bad-file.yaml')); - } - - public function testGetYamlFilesReturnsArray() - { - $configuration = new YamlLoader(); - - $method = new \ReflectionMethod($configuration, 'get'); - $method->setAccessible(true); - - $count = 0; - $files = []; - foreach ($method->invoke($configuration) as $file) { - $count++; - $files[] = $file; - } - - $this->assertGreaterThanOrEqual(1, $count); - } -} \ No newline at end of file diff --git a/src/Tests/Unit/System/ConfigurationTest.php b/src/Tests/Unit/System/ConfigurationTest.php index fbf36d9..364ba60 100644 --- a/src/Tests/Unit/System/ConfigurationTest.php +++ b/src/Tests/Unit/System/ConfigurationTest.php @@ -1,149 +1,29 @@ . - * - * @author Joseph Maxwell - * @copyright SwiftOtter Studios, 10/8/16 - * @package default - **/ + +declare(strict_types=1); namespace Driver\Tests\Unit\System; -use DI\ContainerBuilder; use Driver\System\Configuration; -use Driver\System\Configuration\YamlFilter; -use Symfony\Component\Yaml\Yaml; class ConfigurationTest extends \PHPUnit_Framework_TestCase { - protected $testFile; - - public function setUp() - { - $this->testFile = realpath(__DIR__ . '../../../config/') . 'test.yaml'; - if (!file_exists($this->testFile)) { - file_put_contents($this->testFile, "test:\n value: unknown"); - } - - parent::setUp(); - } - - public function tearDown() - { - unlink($this->testFile); - - parent::tearDown(); - } - - protected function getConfiguration() - { - $configuration = new Configuration(new Configuration\YamlLoader()); - return $configuration; - } + private Configuration $configuration; - protected function getConfigurationLoadedWithTestFile() + public function setUp(): void { - $configuration = $this->getConfiguration(); - $yamlLoader = new Configuration\YamlLoader(); - - $filePath = $yamlLoader->getIndividual('test'); - - $loaderMethod = new \ReflectionMethod($configuration, 'loadConfigurationFor'); - $loaderMethod->setAccessible(true); - $output = $loaderMethod->invoke($configuration, reset($filePath)); - - return [ - 'output' => $output, - 'configuration' => $configuration - ]; + $this->configuration = new Configuration(new Configuration\FileCollector(), new Configuration\FileLoader()); } - public function testGetAllNodesReturnsInformation() + public function testGetAllNodesReturnsInformation(): void { - $values = $this->getConfigurationLoadedWithTestFile(); - $configuration = $values['configuration']; - - $this->assertInternalType('array', $configuration->getNodes()); + $result = $this->configuration->getNodes(); + $this->assertInternalType('array', $result); + $this->assertNotEmpty($result); } - public function testGetNodeReturnsInformation() + public function testGetNodeReturnsInformation(): void { - $values = $this->getConfigurationLoadedWithTestFile(); - $configuration = $values['configuration']; - - $this->assertSame('unknown', $configuration->getNode('test/value')); - } - - public function testGetAllConfigurationLoadsEverything() - { - $configuration = $this->getConfiguration(); - - $filesProperty = new \ReflectionProperty($configuration, 'files'); - $filesProperty->setAccessible(true); - - $loaderMethod = new \ReflectionMethod($configuration, 'loadAllConfiguration'); - $loaderMethod->setAccessible(true); - $loaderMethod->invoke($configuration); - - $this->assertTrue(count($filesProperty->getValue($configuration)) > 0); - } - - public function testRemovesFileSuffix() - { - $configuration = $this->getConfiguration(); - - $stripMethod = new \ReflectionMethod($configuration, 'stripFileExtension'); - $stripMethod->setAccessible(true); - - $this->assertEquals('test', $stripMethod->invoke($configuration, 'test.yaml')); - } - - public function testGetConfigurationFileTestLoadsArrayValues() - { - $values = $this->getConfigurationLoadedWithTestFile(); - $configuration = $values['configuration']; - $output = $values['output']; - - $this->assertEquals('unknown', $output['test']['value']); - $this->assertTrue(count($configuration) > 0); - } - - public function testGetConfigurationFileLoadsClassArrays() - { - $values = $this->getConfigurationLoadedWithTestFile(); - $configuration = $values['configuration']; - - $fileArray = new \ReflectionProperty($configuration, 'files'); - $fileArray->setAccessible(true); - $nodeArray = new \ReflectionProperty($configuration, 'nodes'); - $nodeArray->setAccessible(true); - $nodes = $nodeArray->getValue($configuration); - - $this->assertSame(1, count($fileArray->getValue($configuration))); - $this->assertSame('unknown', $nodes['test']['value']); - } - - public function testGetConfigurationFileLoadsData() - { - $yamlLoader = new Configuration\YamlLoader(); - $configuration = $this->getConfiguration(); - - $files = $yamlLoader->get(); - - $loaderMethod = new \ReflectionMethod($configuration, 'loadConfigurationFor'); - $loaderMethod->setAccessible(true); - $configuration = $loaderMethod->invoke($configuration, reset($files)); - - $this->assertTrue(count($configuration) > 0); + $this->assertSame('unknown', $this->configuration->getNode('test/value')); } -} \ No newline at end of file +}