diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e291365 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore index 485dee6..dfffa9f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ .idea +application.log +/vendor/ +composer.lock diff --git a/Logger.php b/Logger.php index 3caccbb..d05eec1 100644 --- a/Logger.php +++ b/Logger.php @@ -1,23 +1,39 @@ 1) { + if ($_SERVER['argv'][1] === '-c' || $_SERVER['argv'][1] === '--console') { + return Type::CONSOLE; + } + } + + return Type::FILE; } -} \ No newline at end of file +} diff --git a/Logger/AbstractHandler.php b/Logger/AbstractHandler.php new file mode 100644 index 0000000..4bd721b --- /dev/null +++ b/Logger/AbstractHandler.php @@ -0,0 +1,35 @@ +log(Status::ERROR, $message); + } + + /** + * Add success entity to log. + * + * @param string $message + * + * @return boolean + */ + public function logSuccess(string $message): bool + { + return $this->log(Status::SUCCESS, $message); + } +} diff --git a/Logger/ConsoleHandler.php b/Logger/ConsoleHandler.php new file mode 100644 index 0000000..1434b37 --- /dev/null +++ b/Logger/ConsoleHandler.php @@ -0,0 +1,34 @@ +validate($message)) { + return false; + } + + $file = fopen('php://stdout', 'a'); + + fwrite($file, sprintf("%s: %s\n", $type->getLabel(), $message)); + + return fclose($file); + } +} diff --git a/Logger/FileHandler.php b/Logger/FileHandler.php new file mode 100644 index 0000000..7304c7e --- /dev/null +++ b/Logger/FileHandler.php @@ -0,0 +1,68 @@ +createFile()) { + return false; + } + + if (!$this->validate($message)) { + return false; + } + + $file = fopen($this->LOG_FILE, 'a'); + + fwrite($file, sprintf("%s: %s\n", $type->getLabel(), $message)); + + return fclose($file); + } + + /** + * Check if file exists or not. + * + * @return boolean + */ + private function fileExists(): bool + { + return file_exists($this->LOG_FILE) && is_file($this->LOG_FILE) && is_writable($this->LOG_FILE); + } + + /** + * Create file if not exists. + * + * @return boolean + */ + private function createFile(): bool + { + if (!$this->fileExists() && !fopen($this->LOG_FILE, 'c')) { + throw new Exception('Cannot create file'); + } + + return $this->fileExists(); + } +} diff --git a/Logger/HandlerFactory.php b/Logger/HandlerFactory.php new file mode 100644 index 0000000..7c13097 --- /dev/null +++ b/Logger/HandlerFactory.php @@ -0,0 +1,26 @@ + new FileHandler(), + Type::CONSOLE => new ConsoleHandler() + }; + } +} diff --git a/Logger/HandlerInterface.php b/Logger/HandlerInterface.php new file mode 100644 index 0000000..645704a --- /dev/null +++ b/Logger/HandlerInterface.php @@ -0,0 +1,21 @@ + 'Error', + Status::SUCCESS => 'Success' + }; + } +} diff --git a/Logger/Type.php b/Logger/Type.php new file mode 100644 index 0000000..0e33372 --- /dev/null +++ b/Logger/Type.php @@ -0,0 +1,14 @@ +fileHandler = new FileHandler(); + $this->fileContent = file_get_contents(self::FILE_PATH); + } + + protected function tearDown(): void + { + parent::tearDown(); + + unset($this->fileHandler); + unset($this->fileContent); + } + + public function testLogSuccess(): void + { + $this->assertTrue($this->fileHandler->log(Status::SUCCESS, 'Test success')); + $this->assertStringEqualsFile(self::FILE_PATH, $this->fileContent . "Success: Test success\n"); + } + + public function testLogError(): void + { + $this->assertTrue($this->fileHandler->log(Status::ERROR, 'Test error')); + $this->assertStringEqualsFile(self::FILE_PATH, $this->fileContent . "Error: Test error\n"); + } + + public function testLogWithEmptyMessage(): void + { + $this->assertFalse($this->fileHandler->log(Status::SUCCESS, '')); + $this->assertStringEqualsFile(self::FILE_PATH, $this->fileContent); + } + + public function testLogFileWritable(): void + { + $this->assertFileIsWritable(self::FILE_PATH); + } +} diff --git a/tests/HandlerFactoryTest.php b/tests/HandlerFactoryTest.php new file mode 100644 index 0000000..eb69ed8 --- /dev/null +++ b/tests/HandlerFactoryTest.php @@ -0,0 +1,30 @@ +assertInstanceOf('Homework\Logger\FileHandler', $instance); + $this->assertInstanceOf('Homework\Logger\HandlerInterface', $instance); + $this->assertInstanceOf('Homework\Logger\AbstractHandler', $instance); + } + + public function testConsoleHandler(): void + { + $instance = HandlerFactory::get(Type::CONSOLE); + + $this->assertInstanceOf('Homework\Logger\ConsoleHandler', $instance); + $this->assertInstanceOf('Homework\Logger\HandlerInterface', $instance); + $this->assertInstanceOf('Homework\Logger\AbstractHandler', $instance); + } +} diff --git a/tests/LoggerTest.php b/tests/LoggerTest.php new file mode 100644 index 0000000..1465f98 --- /dev/null +++ b/tests/LoggerTest.php @@ -0,0 +1,20 @@ +assertInstanceOf('Homework\Logger\FileHandler', $instance); + $this->assertInstanceOf('Homework\Logger\HandlerInterface', $instance); + $this->assertInstanceOf('Homework\Logger\AbstractHandler', $instance); + } +} diff --git a/tests/ValidationTraitTest.php b/tests/ValidationTraitTest.php new file mode 100644 index 0000000..e3c4519 --- /dev/null +++ b/tests/ValidationTraitTest.php @@ -0,0 +1,47 @@ +validationTrait = $this->getMockForTrait(ValidationTrait::class); + } + + protected function tearDown(): void + { + parent::tearDown(); + + unset($this->validationTrait); + } + + /** + * @dataProvider validationProvider + */ + public function testValidate($message, $result): void + { + $this->assertSame($this->validationTrait->validate($message), $result); + } + + public function validationProvider(): array + { + $data = [ + ['test', true], + ['🔰', true], + ["\xd1", false], // Test broken UTF-8 + ['', false] + ]; + + return $data; + } +}