From 9ec03e63b3aec563afa2c552e8e391ff3712b4e4 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:39:18 +0200 Subject: [PATCH 01/13] refactor: remove unused exception --- src/Exception/JsonException.php | 34 --------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 src/Exception/JsonException.php diff --git a/src/Exception/JsonException.php b/src/Exception/JsonException.php deleted file mode 100644 index 4ff8496..0000000 --- a/src/Exception/JsonException.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2016 (c) Josantonius - * @license https://opensource.org/licenses/MIT - The MIT License (MIT) - * @link https://github.com/josantonius/php-json - * @since 1.0.0 - */ -namespace Josantonius\Json\Exception; - -/** - * Exception class for JSON library. - * - * You can use an exception and error handler with this library. - * - * @link https://github.com/josantonius/php-errorhandler - */ -class JsonException extends \Exception -{ - /** - * Exception handler. - * - * @param string $msg → message error (Optional) - * @param int $status → HTTP response status code (Optional) - */ - public function __construct($msg = '', $status = 0) - { - $this->message = $msg; - $this->statusCode = $status; - } -} From bdbd0c9a28f789c966d8187329c925cde4219cf1 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:44:24 +0200 Subject: [PATCH 02/13] test: remove unused tests #15 --- src/JsonLastError.php | 94 ------------------------------------- tests/JsonLastErrorTest.php | 65 ------------------------- 2 files changed, 159 deletions(-) delete mode 100644 src/JsonLastError.php delete mode 100644 tests/JsonLastErrorTest.php diff --git a/src/JsonLastError.php b/src/JsonLastError.php deleted file mode 100644 index 2d4375a..0000000 --- a/src/JsonLastError.php +++ /dev/null @@ -1,94 +0,0 @@ - - * @copyright 2016 (c) Josantonius - * @license https://opensource.org/licenses/MIT - The MIT License (MIT) - * @link https://github.com/josantonius/php-json - * @since 1.1.7 - */ -namespace Josantonius\Json; - -/** - * The JSON last error collection. - */ -class JsonLastError -{ - /** - * Check for errors. - * - * @return array|null - */ - public static function check() - { - $collections = self::getCollection(); - - $jsonLastError = json_last_error(); - - return isset($jsonLastError) ? $collections[$jsonLastError] : $collections['default']; - } - - /** - * Get collection of JSON errors. - * - * @return array - */ - public static function getCollection() - { - $collections = [ - JSON_ERROR_NONE => null, - JSON_ERROR_DEPTH => [ - 'message' => 'Maximum stack depth exceeded', - 'error-code' => 1, - ], - JSON_ERROR_STATE_MISMATCH => [ - 'message' => 'Underflow or the modes mismatch', - 'error-code' => 2, - ], - JSON_ERROR_CTRL_CHAR => [ - 'message' => 'Unexpected control char found', - 'error-code' => 3, - ], - JSON_ERROR_SYNTAX => [ - 'message' => 'Syntax error, malformed JSON', - 'error-code' => 4, - ], - JSON_ERROR_UTF8 => [ - 'message' => 'Malformed UTF-8 characters', - 'error-code' => 5, - ], - JSON_ERROR_RECURSION => [ - 'message' => 'Recursion error in value to be encoded', - 'error-code' => 6, - ], - JSON_ERROR_INF_OR_NAN => [ - 'message' => 'Error NAN/INF in value to be encoded', - 'error-code' => 7, - ], - JSON_ERROR_UNSUPPORTED_TYPE => [ - 'message' => 'Type value given cannot be encoded', - 'error-code' => 8, - ], - 'default' => [ - 'message' => 'Unknown error', - 'error-code' => 999, - ], - ]; - - if (version_compare(PHP_VERSION, '7.0.0', '>=')) { - $collections[JSON_ERROR_INVALID_PROPERTY_NAME] = [ - 'message' => 'Name value given cannot be encoded', - 'error-code' => 9, - ]; - - $collections[JSON_ERROR_UTF16] = [ - 'message' => 'Malformed UTF-16 characters', - 'error-code' => 10, - ]; - } - - return $collections; - } -} diff --git a/tests/JsonLastErrorTest.php b/tests/JsonLastErrorTest.php deleted file mode 100644 index f3ebce6..0000000 --- a/tests/JsonLastErrorTest.php +++ /dev/null @@ -1,65 +0,0 @@ - - * @copyright 2016 (c) Josantonius - * @license https://opensource.org/licenses/MIT - The MIT License (MIT) - * @link https://github.com/josantonius/php-json - * @since 1.1.7 - */ -namespace Josantonius\Json; - -use PHPUnit\Framework\TestCase; - -/** - * Tests class for JsonLastError class. - */ -class JsonLastErrorTest extends TestCase -{ - /** - * JSON instance. - * - * @var object - */ - protected $jsonLastError; - - /** - * Set up. - */ - public function setUp(): void - { - parent::setUp(); - - $this->jsonLastError = new JsonLastError; - } - - /** - * Check if it is an instance of JSON. - */ - public function testIsInstanceOfJson() - { - $this->assertInstanceOf('Josantonius\Json\JsonLastError', $this->jsonLastError); - } - - /** - * Get collection of JSON errors. - */ - public function testGetCollection() - { - $jsonLastError = $this->jsonLastError; - - $this->assertIsArray($jsonLastError::getCollection()); - } - - /** - * Check for errors. - */ - public function testCheckJsonLastError() - { - $jsonLastError = $this->jsonLastError; - - $this->assertNull($jsonLastError::check()); - } -} From 2163de34ae418102f83f1d52ae8bed6ee5311fe2 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:46:59 +0200 Subject: [PATCH 03/13] docs: add documentation for 2.0.0 version Add documentation for version 2.0.0. #15 --- .github/lang/es-ES/README.md | 155 +++++++++++++++++++--------------- README.md | 157 ++++++++++++++++++++--------------- 2 files changed, 175 insertions(+), 137 deletions(-) diff --git a/.github/lang/es-ES/README.md b/.github/lang/es-ES/README.md index fd21ee4..44d70a6 100755 --- a/.github/lang/es-ES/README.md +++ b/.github/lang/es-ES/README.md @@ -20,7 +20,6 @@ Biblioteca PHP para la gestión de archivos JSON. - [Cómo empezar](#cómo-empezar) - [Uso](#uso) - [Tests](#tests) -- [Manejo de excepciones](#manejo-de-excepciones) - [Tareas pendientes](#☑-tareas-pendientes) - [Registro de cambios](#registro-de-cambios) - [Contribuir](#contribuir) @@ -33,9 +32,14 @@ Biblioteca PHP para la gestión de archivos JSON. Esta biblioteca es compatible desde la versión **8.0** de PHP hasta la versión **8.1** de PHP. -Para versiones anteriores de PHP (desde la **5.6** hasta la **7.4**) puedes utilizar la +Para seguir utilizando la versión con métodos estáticos sin las nuevas características: + +- Para versiones anteriores de PHP (desde la **5.6** hasta la **7.4**), puedes utilizar la [versión 1.1.9](https://github.com/josantonius/php-json/tree/1.1.9) de esta biblioteca. +- Para las versiones **8.0** y **8.1** de PHP, puedes utilizar la +[version 1.2.0](https://github.com/josantonius/php-json/tree/1.2.0) de esta biblioteca. + ## Instalación La mejor forma de instalar esta extensión es a través de [Composer](http://getcomposer.org/download/). @@ -59,68 +63,49 @@ También puedes **clonar el repositorio** completo con Git: git clone https://github.com/josantonius/php-json.git ``` -O **instalarlo manualmente**: - -Descargar [Json.php](https://raw.githubusercontent.com/josantonius/php-json/main/src/Json.php), -[JsonLastError.php](https://raw.githubusercontent.com/josantonius/php-json/main/src/JsonLastError.php) y -[JsonException.php](https://raw.githubusercontent.com/josantonius/php-json/main/src/Exception/JsonException.php): - -```console -wget https://raw.githubusercontent.com/josantonius/php-json/main/src/Json.php -``` - -```console -wget https://raw.githubusercontent.com/josantonius/php-json/main/src/JsonLastError.php -``` - -```console -wget https://raw.githubusercontent.com/josantonius/php-json/main/src/Exception/JsonException.php -``` - ## Métodos disponibles Métodos disponibles en esta biblioteca: -### Crear archivo JSON desde array +### Obtener el contenido del archivo JSON ```php -Json::arrayToFile($array, $file); +$json->get(); ``` -| Atributo | Descripción | Tipo | Requerido | Predeterminado -| --- | --- | --- | --- | --- | -| $array | Array a guardar en archivo JSON. | array | Sí | | -| $file | Ruta hacia el archivo. | string | Sí | | +**@throws** _CreateDirectoryException_ | _CreateFileException_ | _JsonErrorException_ -**# Return** (boolean) +**@Return** `array` - _Contenido del archivo_ -### Guardar en array el contenido de archivo JSON +### Establecer el contenido del archivo JSON ```php -Json::fileToArray($file); +$json->set(array|object $content); ``` -| Atributo | Descripción | Tipo | Requerido | Predeterminado -| --- | --- | --- | --- | --- | -| $file | Ruta o URL externa al archivo JSON. | string | Sí | | +**@throws** _CreateFileException_ | _JsonErrorException_ | _UnavailableMethodException_ -**# Return** (array|false) +**@Return** `void` -### Comprobar si hay errores +### Fusionar en el archivo JSON ```php -JsonLastError::check(); +$json->merge(array|object $content); ``` -**# Return** (array|null) → Null si no hay errores o array con código de estado y mensaje de error. +**@throws** _CreateFileException_ | _GetFileException_ | _JsonErrorException_ | _UnavailableMethodException_ -### Obtener colección de errores JSON +**@Return** `array` - _Array resultante_ + +### Incluir en el archivo JSON ```php -JsonLastError::getCollection(); +$json->push(array|object $content); ``` -**# Return** (array) → Recopilación de posibles errores. +**@throws** _CreateFileException_ | _GetFileException_ | _JsonErrorException_ | _UnavailableMethodException_ + +**@Return** `array` - _Array resultante_ ## Cómo empezar @@ -132,56 +117,94 @@ require __DIR__ . '/vendor/autoload.php'; use josantonius\Json\Json; ``` -Si la instalaste **manualmente**, utiliza: +```php +$json = new Json('path/to/file.json'); + +# Si el archivo no existe, se creará. +``` + +O ```php -require_once __DIR__ . '/Json.php'; -require_once __DIR__ . '/JsonLastError.php'; -require_once __DIR__ . '/JsonException.php'; +$json = new Json('https://site.com/file.json'); -use josantonius\Json\Json; +# Cuando el archivo JSON se obtiene desde una URL, sólo estará disponible el método "get". ``` ## Uso Ejemplo de uso para esta biblioteca: -### Crear un archivo JSON desde un array +### Obtener el contenido del archivo -```php -$array = [ - 'name' => 'josantonius', - 'email' => 'info@josantonius.com', - 'url' => 'https://github.com/josantonius/php-json' -]; +```json +{ + "foo": "bar" +} +``` -$pathfile = __DIR__ . '/filename.json'; +```php +$json->get(); +``` -Json::arrayToFile($array, $pathfile); +```php +['foo' => 'bar'] ``` -### Guardar en un array el contenido de un archivo JSON +### Establecer el contenido del archivo ```php -$pathfile = __DIR__ . '/filename.json'; +$json->set(['foo' => 'bar']); +``` -$array = Json::fileToArray($pathfile); +```json +{ + "foo": "bar" +} ``` -### Comprobar si hubo errores +### Fusionar en el archivo + +```json +{ + "foo": "bar" +} +``` ```php -$lastError = JsonLastError::check(); +$json->merge(['bar' => 'foo']); +``` -if (!is_null($lastError)) { - var_dump($lastError); +```json +{ + "foo": "bar", + "bar": "foo" } ``` -### Obtener colección con errores JSON +### Incluir en el archivo + +```json +[ + { + "name": "foo" + } +] +``` ```php -$jsonLastErrorCollection = JsonLastError::getCollection(); +$json->push(['name' => 'bar']); +``` + +```json +[ + { + "name": "foo" + }, + { + "name": "bar" + } +] ``` ## Tests @@ -227,10 +250,6 @@ Ejecutar todas las pruebas anteriores: composer tests ``` -## Manejo de excepciones - -Esta biblioteca utiliza [control de excepciones](src/Exception) que puedes personalizar a tu gusto. - ## ☑ Tareas pendientes - [ ] Añadir nueva funcionalidad. @@ -254,8 +273,8 @@ _pull request_, comenzar una discusión o reportar un _issue_. ## Patrocinar -Si este proyecto te ayuda a reducir el tiempo de desarrollo, -[¡puedes patrocinarme!](https://github.com/josantonius/lang/es-ES/README.md#patrocinar) :blush: +Si este proyecto te ayuda a reducir el tiempo de desarrollo y quieres agradecérmelo, +[¡podrías patrocinarme!](https://github.com/josantonius/lang/es-ES/README.md#patrocinar) :blush: ## Licencia diff --git a/README.md b/README.md index 4869dc3..dc72c12 100755 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ PHP simple library for managing JSON files. - [Quick Start](#quick-start) - [Usage](#usage) - [Tests](#tests) -- [Exception Handler](#exception-handler) - [TODO](#-todo) - [Changelog](#changelog) - [Contribution](#contribution) @@ -33,8 +32,13 @@ PHP simple library for managing JSON files. This library is compatible from **PHP 8.0** version to **PHP 8.1** version. -For older versions of PHP (from **5.6** to **7.4**) you can use -[version 1.1.9](https://github.com/josantonius/php-json/tree/1.1.9) of this library. +To continue using the version with static methods without the new features: + +- For older versions of PHP (from **5.6** to **7.4**), +[version 1.1.9](https://github.com/josantonius/php-json/tree/1.1.9) of this library can be used. + +- For PHP versions **8.0** and **8.1**, +[version 1.2.0](https://github.com/josantonius/php-json/tree/1.2.0) of this library can be used. ## Installation @@ -59,68 +63,49 @@ You can also **clone the complete repository** with Git: git clone https://github.com/josantonius/php-json.git ``` -Or **install it manually**: - -Download [Json.php](https://raw.githubusercontent.com/josantonius/php-json/main/src/Json.php), -[JsonLastError.php](https://raw.githubusercontent.com/josantonius/php-json/main/src/JsonLastError.php) and -[JsonException.php](https://raw.githubusercontent.com/josantonius/php-json/main/src/Exception/JsonException.php): - -```console -wget https://raw.githubusercontent.com/josantonius/php-json/main/src/Json.php -``` - -```console -wget https://raw.githubusercontent.com/josantonius/php-json/main/src/JsonLastError.php -``` - -```console -wget https://raw.githubusercontent.com/josantonius/php-json/main/src/Exception/JsonException.php -``` - ## Available Methods Available methods in this library: -### Create JSON file from array +### Get JSON file contents ```php -Json::arrayToFile($array, $file); +$json->get(); ``` -| Attribute | Description | Type | Required | Default -| --- | --- | --- | --- | --- | -| $array | Array to be converted to JSON. | array | Yes | | -| $file | Path to the file. | string | Yes | | +**@throws** _CreateDirectoryException_ | _CreateFileException_ | _JsonErrorException_ -**# Return** (boolean) +**@Return** `array` - _File contents_ -### Save to array the JSON file content +### Set the content of the JSON file ```php -Json::fileToArray($file); +$json->set(array|object $content); ``` -| Attribute | Description | Type | Required | Default -| --- | --- | --- | --- | --- | -| $file | Path or external url to JSON file. | string | Yes | | +**@throws** _CreateFileException_ | _JsonErrorException_ | _UnavailableMethodException_ -**# Return** (array|false) +**@Return** `void` -### Check for errors +### Merge into JSON file ```php -JsonLastError::check(); +$json->merge(array|object $content); ``` -**# Return** (array|null) → Null if there are no errors or array with state code and error message. +**@throws** _CreateFileException_ | _GetFileException_ | _JsonErrorException_ | _UnavailableMethodException_ -### Get collection of JSON errors +**@Return** `array` - _Resulting array_ + +### Push on the JSON file ```php -JsonLastError::getCollection(); +$json->push(array|object $content); ``` -**# Return** (array) → Collection of JSON errors. +**@throws** _CreateFileException_ | _GetFileException_ | _JsonErrorException_ | _UnavailableMethodException_ + +**@Return** `array` - _Resulting array_ ## Quick Start @@ -132,56 +117,94 @@ require __DIR__ . '/vendor/autoload.php'; use josantonius\Json\Json; ``` -Or If you installed it **manually**, use it: +```php +$json = new Json('path/to/file.json'); + +# If the file does not exist it will be created. +``` + +OR ```php -require_once __DIR__ . '/Json.php'; -require_once __DIR__ . '/JsonLastError.php'; -require_once __DIR__ . '/JsonException.php'; +$json = new Json('https://site.com/file.json'); -use josantonius\Json\Json; +# When the JSON file is obtained from a URL, only the "get" method is available. ``` ## Usage Example of use for this library: -### Create a JSON file from an array +### Get the JSON file contents -```php -$array = [ - 'name' => 'josantonius', - 'email' => 'info@josantonius.dev', - 'url' => 'https://github.com/josantonius/php-json' -]; +```json +{ + "foo": "bar" +} +``` -$filepath = __DIR__ . '/filename.json'; +```php +$json->get(); +``` -Json::arrayToFile($array, $filepath); +```php +['foo' => 'bar'] ``` -### Save the contents of the JSON file in an array +### Set the JSON file contents ```php -$filepath = __DIR__ . '/filename.json'; +$json->set(['foo' => 'bar']); +``` -$array = Json::fileToArray($filepath); +```json +{ + "foo": "bar" +} ``` -### Checks for errors +### Merge data into JSON file + +```json +{ + "foo": "bar" +} +``` ```php -$lastError = JsonLastError::check(); +$json->merge(['bar' => 'foo']); +``` -if (!is_null($lastError)) { - var_dump($lastError); +```json +{ + "foo": "bar", + "bar": "foo" } ``` -### Get a JSON error collection +### Push data on the JSON file + +```json +[ + { + "name": "foo" + } +] +``` ```php -$jsonLastErrorCollection = JsonLastError::getCollection(); +$json->push(['name' => 'bar']); +``` + +```json +[ + { + "name": "foo" + }, + { + "name": "bar" + } +] ``` ## Tests @@ -226,10 +249,6 @@ Run all previous tests: composer tests ``` -## Exception Handler - -This library uses [exception handler](src/Exception) that you can customize. - ## ☑ TODO - [ ] Add new feature. @@ -252,8 +271,8 @@ Thanks to all [contributors](https://github.com/josantonius/php-json/graphs/cont ## Sponsor -If this project help you reduce time to develop, -[you can become my sponsor!](https://github.com/josantonius#sponsor) :blush: +If this project helps you to reduce your development time and you want to thank me, +[you could sponsor me!](https://github.com/josantonius#sponsor) :blush: ## License From f055f6824c2a499a1899092cdc02e8c003c2a9bc Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:48:24 +0200 Subject: [PATCH 04/13] build: add script for html code coverage Add script for HTML code coverage #15 --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 3d4cf0c..2509cd6 100755 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "require-dev": { "phpmd/phpmd": "^2.6", "phpunit/phpunit": "^9.0", - "squizlabs/php_codesniffer": "^3.6.2" + "squizlabs/php_codesniffer": "^3.7" }, "minimum-stability": "stable", "autoload": { @@ -39,7 +39,7 @@ }, "autoload-dev": { "psr-4": { - "Josantonius\\Json\\": "tests/" + "Josantonius\\Json\\Tests\\": "tests/" } }, "config": { @@ -55,6 +55,7 @@ "fix": [ "vendor/bin/phpcbf src tests" ], + "htmlCoverage": "vendor/bin/phpunit --coverage-html coverage", "phpcs": "vendor/bin/phpcs --standard=phpcs.xml $(find . -name '*.php');", "phpmd": "vendor/bin/phpmd src,tests text ./phpmd.xml", "phpunit": "vendor/bin/phpunit --colors=always;", From 740ad77f81c7db9667f73569be64dfa2503e43ff Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:51:47 +0200 Subject: [PATCH 05/13] build: add coverage directory Add coverage directory. #15 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ad895a1..4f90d88 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ vendor/ +coverage/ .vscode/ composer.phar composer.lock From 10e45d477f81f6426a94fa98c9ef067708f61b95 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:53:19 +0200 Subject: [PATCH 06/13] build: change line limit Change the line limit from 80 to 100. #15 --- phpcs.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpcs.xml b/phpcs.xml index 8ffc7c5..6d3ec88 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -21,8 +21,8 @@ - - + + From 1e8a47f3d3a366db1bdd5575814b2bd581774b6f Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:54:37 +0200 Subject: [PATCH 07/13] feat: add new exceptions Add new exceptions. #15 --- src/Exception/CreateDirectoryException.php | 32 ++++++++++++++++++++ src/Exception/CreateFileException.php | 32 ++++++++++++++++++++ src/Exception/GetFileException.php | 32 ++++++++++++++++++++ src/Exception/JsonErrorException.php | 29 ++++++++++++++++++ src/Exception/UnavailableMethodException.php | 29 ++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 src/Exception/CreateDirectoryException.php create mode 100644 src/Exception/CreateFileException.php create mode 100644 src/Exception/GetFileException.php create mode 100644 src/Exception/JsonErrorException.php create mode 100644 src/Exception/UnavailableMethodException.php diff --git a/src/Exception/CreateDirectoryException.php b/src/Exception/CreateDirectoryException.php new file mode 100644 index 0000000..3b5218b --- /dev/null +++ b/src/Exception/CreateDirectoryException.php @@ -0,0 +1,32 @@ + + * @copyright 2016 (c) Josantonius + * @license https://opensource.org/licenses/MIT - The MIT License (MIT) + * @link https://github.com/josantonius/php-json + * @since 2.0.0 + */ +namespace Josantonius\Json\Exception; + +/** + * You can use an exception and error handler with this library. + * + * @link https://github.com/josantonius/php-errorhandler + */ +class CreateDirectoryException extends \Exception +{ + public function __construct(string $path, \Throwable $th = null) + { + $lastError = error_get_last()['message'] ?? ''; + + $message = "Could not create directory in '$path'."; + $message .= $lastError ? " $lastError." : ''; + + parent::__construct($th ? $th->getMessage() : $message, 0, $th); + } +} diff --git a/src/Exception/CreateFileException.php b/src/Exception/CreateFileException.php new file mode 100644 index 0000000..7d5ea42 --- /dev/null +++ b/src/Exception/CreateFileException.php @@ -0,0 +1,32 @@ + + * @copyright 2016 (c) Josantonius + * @license https://opensource.org/licenses/MIT - The MIT License (MIT) + * @link https://github.com/josantonius/php-json + * @since 2.0.0 + */ +namespace Josantonius\Json\Exception; + +/** + * You can use an exception and error handler with this library. + * + * @link https://github.com/josantonius/php-errorhandler + */ +class CreateFileException extends \Exception +{ + public function __construct(string $filepath, \Throwable $th = null) + { + $lastError = error_get_last()['message'] ?? ''; + + $message = "Could not create file '$filepath'."; + $message .= $lastError ? " $lastError." : ''; + + parent::__construct($th ? $th->getMessage() : $message, 0, $th); + } +} diff --git a/src/Exception/GetFileException.php b/src/Exception/GetFileException.php new file mode 100644 index 0000000..461074d --- /dev/null +++ b/src/Exception/GetFileException.php @@ -0,0 +1,32 @@ + + * @copyright 2016 (c) Josantonius + * @license https://opensource.org/licenses/MIT - The MIT License (MIT) + * @link https://github.com/josantonius/php-json + * @since 2.0.0 + */ +namespace Josantonius\Json\Exception; + +/** + * You can use an exception and error handler with this library. + * + * @link https://github.com/josantonius/php-errorhandler + */ +class GetFileException extends \Exception +{ + public function __construct(string $filepath, \Throwable $th = null) + { + $lastError = error_get_last()['message'] ?? ''; + + $message = "Error reading file: '$filepath'."; + $message .= $lastError ? " $lastError." : ''; + + parent::__construct($th ? $th->getMessage() : $message, 0, $th); + } +} diff --git a/src/Exception/JsonErrorException.php b/src/Exception/JsonErrorException.php new file mode 100644 index 0000000..33e21f8 --- /dev/null +++ b/src/Exception/JsonErrorException.php @@ -0,0 +1,29 @@ + + * @copyright 2016 (c) Josantonius + * @license https://opensource.org/licenses/MIT - The MIT License (MIT) + * @link https://github.com/josantonius/php-json + * @since 2.0.0 + */ +namespace Josantonius\Json\Exception; + +/** + * You can use an exception and error handler with this library. + * + * @link https://github.com/josantonius/php-errorhandler + */ +class JsonErrorException extends \Exception +{ + public function __construct(\Throwable $th = null) + { + $message = 'JSON error: ' . json_last_error_msg(); + + parent::__construct($th ? $th->getMessage() : $message, 0, $th); + } +} diff --git a/src/Exception/UnavailableMethodException.php b/src/Exception/UnavailableMethodException.php new file mode 100644 index 0000000..fc5dfa6 --- /dev/null +++ b/src/Exception/UnavailableMethodException.php @@ -0,0 +1,29 @@ + + * @copyright 2016 (c) Josantonius + * @license https://opensource.org/licenses/MIT - The MIT License (MIT) + * @link https://github.com/josantonius/php-json + * @since 2.0.0 + */ +namespace Josantonius\Json\Exception; + +/** + * You can use an exception and error handler with this library. + * + * @link https://github.com/josantonius/php-errorhandler + */ +class UnavailableMethodException extends \Exception +{ + public function __construct(string $method, \Throwable $th = null) + { + $message = 'The "' . $method . '" method is not available for remote JSON files.'; + + parent::__construct($th ? $th->getMessage() : $message, 0, $th); + } +} From e6d450f19ed8c07d03a7fdc77da1c187ae5240b2 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:55:28 +0200 Subject: [PATCH 08/13] test: add new tests Add new tests. #15 --- tests/JsonTest.php | 319 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 258 insertions(+), 61 deletions(-) diff --git a/tests/JsonTest.php b/tests/JsonTest.php index 164fb57..150aba8 100644 --- a/tests/JsonTest.php +++ b/tests/JsonTest.php @@ -1,5 +1,7 @@ json = new Json; + /** + * @since 2.0.0 + */ + public function tearDown(): void + { + if (file_exists($this->filepath)) { + unlink($this->filepath); + } } /** - * Check if it is an instance of JSON. - * - * @since 1.1.6 + * @test + * @since 2.0.0 */ - public function testGetCollection() + public function itShouldReturnValidInstance(): void { - $this->assertInstanceOf('Josantonius\Json\Json', $this->json); + $this->assertInstanceOf(Json::class, new Json($this->filepath)); } /** - * Creating JSON file from array. + * @test + * @since 2.0.0 */ - public function testArrayToFile() + public function constructorShouldCreateTheFileIfNotExist(): void { - $json = $this->json; + $this->assertFalse(file_exists($this->filepath)); + + new Json($this->filepath); + + $this->assertTrue(file_exists($this->filepath)); - $array = [ - 'name' => 'Josantonius', - 'email' => 'hello@josantonius.dev', - 'url' => 'https://github.com/josantonius/php-json', - ]; + $this->assertEquals('[]', file_get_contents($this->filepath)); + } - $file = __DIR__.'/filename.json'; - $result = $json::arrayToFile($array, $file); + /** + * @test + * @since 2.0.0 + */ + public function constructorShouldThrowExceptionIfPathIsWrong(): void + { + $this->expectException(CreateDirectoryException::class); - $this->assertFileIsReadable($file); + new Json(__DIR__ . '/foo|/filename.json'); + } - $this->assertTrue($result); + /** + * @test + * @since 2.0.0 + */ + public function constructorShouldThrowExceptionIfFilenameIsWrong(): void + { + $this->expectException(CreateFileException::class); + + new Json(__DIR__ . '/file|name.json'); } /** - * Exception to creating JSON file from array. + * @test + * @since 2.0.0 */ - public function testArrayToFileCreateFileException() + public function itShouldGetFileContents(): void { - $json = $this->json; + $jsonFile = new Json($this->filepath); - $this->expectException(JsonException::class); + $this->assertEquals([], $jsonFile->get()); + } + + /** + * @test + * @since 2.0.0 + */ + public function itShouldGetRemoteFileContents(): void + { + $jsonFile = new Json($this->url); - $json::arrayToFile([], '..'); + $this->assertArrayHasKey('name', $jsonFile->get()); } /** - * Get to array the JSON file content. + * @test + * @since 2.0.0 */ - public function testFileToArray() + public function itShouldSetArrayOnJsonFile(): void { - $json = $this->json; + $jsonFile = new Json($this->filepath); - $file = __DIR__.'/filename.json'; + $array = ['foo' => 'bar']; - $this->assertArrayHasKey('name', $json::fileToArray($file)); - $this->assertArrayHasKey('email', $json::fileToArray($file)); - $this->assertArrayHasKey('url', $json::fileToArray($file)); + $jsonFile->set($array); - unlink($file); + $this->assertEquals($array, json_decode(file_get_contents($this->filepath), true)); } /** - * Error when file doesn't exist and cannot create file. + * @test + * @since 2.0.0 */ - public function testFileToArrayCreateFileException() + public function itShouldSetObjectOnJsonFile(): void { - $json = $this->json; + $jsonFile = new Json($this->filepath); + + $object = (object) ['foo' => 'bar']; - $this->expectException(JsonException::class); + $jsonFile->set($object); - $json::fileToArray(__DIR__.''); + $this->assertEquals($object, json_decode(file_get_contents($this->filepath))); } /** - * Get external JSON file and save as array. + * @test + * @since 2.0.0 */ - public function testExternalFileToArray() + public function itShouldThrowExceptionIfSetMethodIsUsedWithRemoteFile(): void { - $json = $this->json; + $jsonFile = new Json($this->url); - $file = 'https://raw.githubusercontent.com/josantonius/php-json/master/composer.json'; + $this->expectException(UnavailableMethodException::class); - $this->assertArrayHasKey('name', $json::fileToArray($file)); - $this->assertArrayHasKey('type', $json::fileToArray($file)); + $jsonFile->set(['foo' => 'bar']); } /** - * Get external JSON file and save as array. + * @test + * @since 2.0.0 */ - public function testExternalFileNonExistentToArray() + public function itShouldMergeArrayOnJsonFile(): void { - $json = $this->json; + $jsonFile = new Json($this->filepath); + + $jsonFile->set(['foo' => 'bar']); + + $jsonFile->merge(['bar' => 'foo']); + + $this->assertEquals([ + 'foo' => 'bar', + 'bar' => 'foo' + ], json_decode(file_get_contents($this->filepath), true)); + } + + /** + * @test + * @since 2.0.0 + */ + public function itShouldMergeObjectOnJsonFile(): void + { + $jsonFile = new Json($this->filepath); + + $jsonFile->set(['foo' => 'bar']); + + $object = (object) ['bar' => 'foo']; + + $jsonFile->merge($object); + + $this->assertEquals([ + 'foo' => 'bar', + 'bar' => 'foo' + ], json_decode(file_get_contents($this->filepath), true)); + } + + /** + * @test + * @since 2.0.0 + */ + public function itShouldThrowExceptionIfMergeMethodIsUsedWithRemoteFile(): void + { + $jsonFile = new Json($this->url); + + $this->expectException(UnavailableMethodException::class); + + $jsonFile->merge(['bar' => 'foo']); + } + + /** + * @test + * @since 2.0.0 + */ + public function itShouldPushArrayOnJsonFile(): void + { + $jsonFile = new Json($this->filepath); + + $jsonFile->set([['foo' => 'bar']]); - $file = 'https://raw.githubusercontent.com/composer.json'; + $jsonFile->push(['bar' => 'foo']); + + $this->assertEquals( + [['foo' => 'bar'], ['bar' => 'foo']], + json_decode(file_get_contents($this->filepath), true) + ); + } + + /** + * @test + * @since 2.0.0 + */ + public function itShouldPushObjectOnJsonFile(): void + { + $jsonFile = new Json($this->filepath); + + $jsonFile->set([['foo' => 'bar']]); + + $jsonFile->push((object) ['bar' => 'foo']); + + $this->assertEquals( + [['foo' => 'bar'], ['bar' => 'foo']], + json_decode(file_get_contents($this->filepath), true) + ); + } + + /** + * @test + * @since 2.0.0 + */ + public function itShouldThrowExceptionIfPushMethodIsUsedWithRemoteFile(): void + { + $jsonFile = new Json($this->url); + + $this->expectException(UnavailableMethodException::class); + + $jsonFile->push(['bar' => 'foo']); + } + + /** + * @test + * @since 2.0.0 + */ + public function itShouldThrowExceptionIfFileCannotBeObtained(): void + { + $jsonFile = new Json($this->filepath); + + unlink($this->filepath); + + $this->expectException(GetFileException::class); + + $jsonFile->push((object) ['bar' => 'foo']); + } + + + /** + * @test + * @since 2.0.0 + */ + public function itShouldThrowExceptionIfRemoteFileCannotBeObtained(): void + { + $jsonFile = new Json($this->url . 'wrong'); + + $this->expectException(GetFileException::class); + + $jsonFile->push((object) ['bar' => 'foo']); + } + + /** + * @test + * @since 2.0.0 + */ + public function itShouldThrowExceptionWhenThereAreJsonErrorsInTheFile(): void + { + $jsonFile = new Json($this->filepath); + + file_put_contents($this->filepath, '{'); + + $this->expectException(JsonErrorException::class); + + $jsonFile->get(); + } + + /** + * @test + * @since 2.0.0 + */ + public function arrayToFileStaticMethodShouldBehaveLikeTheSetMethod() + { + $json = new Json($this->filepath); + + $json->arrayToFile(['foo' => 'bar'], $this->filepath); + + $this->assertEquals(['foo' => 'bar'], json_decode( + file_get_contents($this->filepath), + true + )); + } + + /** + * @test + * @since 2.0.0 + */ + public function fileToArrayStaticMethodShouldBehaveLikeTheGetMethod() + { + $json = new Json($this->filepath); - $this->assertFalse($json::fileToArray($file)); + $this->assertEquals($json->fileToArray($this->filepath), $json->get()); } } From f7e4d298ab3c3c5a79d0b46fb5267e4580ae7828 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 02:57:51 +0200 Subject: [PATCH 09/13] feat: add new features and refactorings Add new features and refactor the code. #15 --- src/Json.php | 246 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 199 insertions(+), 47 deletions(-) diff --git a/src/Json.php b/src/Json.php index 285f24d..8c1be39 100644 --- a/src/Json.php +++ b/src/Json.php @@ -1,5 +1,7 @@ isUrl = filter_var($filepath, FILTER_VALIDATE_URL) !== false; - $lastError = JsonLastError::check(); + if (!$this->isUrl) { + $this->createFileIfNotExists($filepath); + } + } - $json = json_encode($lastError ? $lastError : $array, JSON_PRETTY_PRINT); + /** + * Get the content of the JSON file or a remote JSON file. + * + * @since 2.0.0 + * + * @throws GetFileException + * @throws JsonErrorException + */ + public function get(): array + { + return $this->getFileContents(); + } - self::saveFile($file, $json); + /** + * Set the content of the JSON file. + * + * @since 2.0.0 + * + * @throws CreateFileException + * @throws JsonErrorException + * @throws UnavailableMethodException + */ + public function set(array|object $content): void + { + $this->isUrl ? $this->throwUnavailableMethodException() : $this->saveToJsonFile($content); + } - return is_null($lastError); + /** + * Merge into JSON file. + * + * @since 2.0.0 + * + * @throws CreateFileException + * @throws GetFileException + * @throws JsonErrorException + * @throws UnavailableMethodException + */ + public function merge(array|object $content): array + { + $content = array_merge($this->getFileContents(), (array) $content); + + $this->isUrl ? $this->throwUnavailableMethodException() : $this->saveToJsonFile($content); + + return $content; } /** - * Save to array the JSON file content. + * Push on the JSON file. * - * @param string $file → path or external url to JSON file + * @since 2.0.0 * - * @return array|false + * @throws CreateFileException + * @throws GetFileException + * @throws JsonErrorException + * @throws UnavailableMethodException */ - public static function fileToArray($file) + public function push(array|object $content): array { - if (!is_file($file) && !filter_var($file, FILTER_VALIDATE_URL)) { - self::arrayToFile([], $file); - } + $data = $this->getFileContents(); + + array_push($data, $content); + + $this->isUrl ? $this->throwUnavailableMethodException() : $this->saveToJsonFile($data); + + return $data; + } + + /** + * Create JSON file from array. + * + * @deprecated + * + * @throws CreateFileException + * @throws JsonErrorException + * @throws UnavailableMethodException + */ + public static function arrayToFile(array|object $array, string $file): bool + { + $message = 'The "arrayToFile" method is deprecated and will be removed. Use "set" instead.'; + $url = 'More information at: https://github.com/josantonius/php-json.'; + trigger_error($message . ' ' . $url, E_USER_DEPRECATED); + + (new Json($file))->set($array); + + return true; + } - $json = @file_get_contents($file); - $array = json_decode($json, true); - $lastError = JsonLastError::check(); + /** + * Get the content of the JSON file or a remote JSON file. + * + * @deprecated + * + * @throws GetFileException + * @throws JsonErrorException + */ + public static function fileToArray($file): array + { + $message = 'The "fileToArray" method is deprecated and will be removed. Use "get" instead.'; + $url = 'More information at: https://github.com/josantonius/php-json.'; + trigger_error($message . ' ' . $url, E_USER_DEPRECATED); - return $array === null || !is_null($lastError) ? false : $array; + return (new Json($file))->get(); } /** - * Create directory recursively if it doesn't exist. + * Create file if not exists. * - * @since 1.1.3 + * @since 2.0.0 * - * @param string $file → path to the directory + * @throws CreateDirectoryException + * @throws CreateFileException + * @throws JsonErrorException + */ + private function createFileIfNotExists(): void + { + if (!file_exists($this->filepath)) { + $this->createDirIfNotExists(); + $this->saveToJsonFile([]); + } + } + + /** + * Create directory if not exists. * - * @throws JsonException → couldn't create directory + * @since 2.0.0 + * + * @throws CreateDirectoryException */ - private static function createDirectory($file) + private function createDirIfNotExists(): void { - $basename = is_string($file) ? basename($file) : ''; - $path = str_replace($basename, '', $file); - - if (!empty($path) && !is_dir($path)) { - if (!mkdir($path, 0755, true)) { - $message = 'Could not create directory in'; - throw new JsonException($message . ' ' . $path); - } + $path = dirname($this->filepath) . DIRECTORY_SEPARATOR; + + if (!is_dir($path) && !@mkdir($path, 0777, true)) { + throw new CreateDirectoryException($path); } } /** - * Save file. + * Get the content of the JSON file or a remote JSON file. * - * @since 1.1.3 + * @since 2.0.0 * - * @param string $file → path to the file - * @param string $json → JSON string + * @throws GetFileException + * @throws JsonErrorException + */ + private function getFileContents(): array + { + $json = @file_get_contents($this->filepath); + + if ($json === false) { + throw new GetFileException($this->filepath); + } + + $array = json_decode($json, true); + + $this->checkJsonLastError(); + + return $array; + } + + /** + * Save content in JSON file. + * + * @since 2.0.0 + * + * @throws CreateFileException + * @throws JsonErrorException + */ + private function saveToJsonFile(array|object $array): void + { + $json = json_encode($array, JSON_PRETTY_PRINT); + + $this->checkJsonLastError(); + + if (@file_put_contents($this->filepath, $json) === false) { + throw new CreateFileException($this->filepath); + } + } + + /** + * Check for JSON errors. + * + * @since 2.0.0 * - * @throws JsonException → couldn't create file + * @throws JsonErrorException */ - private static function saveFile($file, $json) + private function checkJsonLastError(): void { - if (@file_put_contents($file, $json) === false) { - $message = 'Could not create file in'; - throw new JsonException($message . ' ' . $file); + if (json_last_error()) { + throw new JsonErrorException(); } } + + /** + * Throw exception if the method is not available for remote JSON files. + * + * @since 2.0.0 + * + * @throws UnavailableMethodException + */ + private function throwUnavailableMethodException(): void + { + $method = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function']; + + throw new UnavailableMethodException($method); + } } From 1d2fab667adf9a04edf0403b86009b6bb65cbcb0 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 03:09:45 +0200 Subject: [PATCH 10/13] build: disable some rules The following rules have been deactivated: TooManyPublicMethods and ShortVariable. #15 --- phpmd.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpmd.xml b/phpmd.xml index 3102aa8..446c4e5 100644 --- a/phpmd.xml +++ b/phpmd.xml @@ -21,7 +21,7 @@ - + @@ -47,7 +47,7 @@ - + From 723afa024d087caaba56c52699117d75abf52e70 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 03:11:17 +0200 Subject: [PATCH 11/13] test: change character to cause exception Change character to cause exception in continuous integration. #15 --- tests/JsonTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/JsonTest.php b/tests/JsonTest.php index 150aba8..bb85b7a 100644 --- a/tests/JsonTest.php +++ b/tests/JsonTest.php @@ -83,7 +83,7 @@ public function constructorShouldThrowExceptionIfPathIsWrong(): void { $this->expectException(CreateDirectoryException::class); - new Json(__DIR__ . '/foo|/filename.json'); + new Json(__DIR__ . '/foo:/filename.json'); } /** @@ -94,7 +94,7 @@ public function constructorShouldThrowExceptionIfFilenameIsWrong(): void { $this->expectException(CreateFileException::class); - new Json(__DIR__ . '/file|name.json'); + new Json(__DIR__ . '/file:name.json'); } /** From f3bb9b41a18564fa796af4bddaf1cb706f8f33c5 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 03:30:27 +0200 Subject: [PATCH 12/13] test: fix paths to cause exception in ci Fix paths to cause exception in continuous integration. #15 --- tests/JsonTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/JsonTest.php b/tests/JsonTest.php index bb85b7a..ee98b01 100644 --- a/tests/JsonTest.php +++ b/tests/JsonTest.php @@ -83,7 +83,7 @@ public function constructorShouldThrowExceptionIfPathIsWrong(): void { $this->expectException(CreateDirectoryException::class); - new Json(__DIR__ . '/foo:/filename.json'); + new Json('/foo:/filename.json'); } /** @@ -94,7 +94,7 @@ public function constructorShouldThrowExceptionIfFilenameIsWrong(): void { $this->expectException(CreateFileException::class); - new Json(__DIR__ . '/file:name.json'); + new Json('/file:name.json'); } /** From 1120ec5503962d1691838f3ef2b1e2ed9ac29a74 Mon Sep 17 00:00:00 2001 From: Josantonius Date: Thu, 16 Jun 2022 03:31:20 +0200 Subject: [PATCH 13/13] ci: fix composer version Fix composer version. #15 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d96711..93e8597 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: with: php-version: '${{ matrix.php }}' coverage: 'none' - tools: 'composer:v6' + tools: 'composer:v2' - name: 'Install dependencies' run: | @@ -77,7 +77,7 @@ jobs: uses: 'shivammathur/setup-php@v2' with: php-version: '8.1' - tools: 'composer:v6' + tools: 'composer:v2' - name: 'Install dependencies' run: |