diff --git a/CITATION.cff b/CITATION.cff index 0fec1e8..c774b28 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,7 +1,7 @@ cff-version: 1.2.0 message: If you use this software, please cite it using the metadata from this file. title: The FireHub Project - Runtime -abstract: Lightweight PHP runtime layer providing clean wrapper functions over native PHP. +abstract: Lightweight PHP runtime layer providing clean, deterministic utilities for common execution-level operations. type: software license: Apache-2.0 diff --git a/README.md b/README.md index ea08275..4d21b7d 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,12 @@ PHP Runtime Foundation
release version @@ -22,77 +22,108 @@ /> -[![PHPStan](https://github.com/The-FireHub-Project/Runtime/actions/workflows/PHPStan.yml/badge.svg?branch=develop)](https://github.com/The-FireHub-Project/Runtime/actions/workflows/PHPStan.yml) -[![PHPUnit](https://github.com/The-FireHub-Project/Runtime/actions/workflows/PHPUnit.yml/badge.svg?branch=develop)](https://github.com/The-FireHub-Project/Runtime/actions/workflows/PHPUnit.yml) -[![Codecov](https://codecov.io/gh/The-FireHub-Project/Runtime/branch/develop/graph/badge.svg?token=XW2YEONF51)](https://app.codecov.io/gh/The-FireHub-Project/Runtime/tree/develop) -

- + + GitHub created at + GitHub last commit (branch) - + GitHub activity (branch) - + + GitHub contributors + + GitHub language count + + GitHub top language + + GitHub repo size + GitHub commit difference between two branches

-Lightweight PHP runtime abstraction layer providing clean wrapper functions over native PHP. It standardizes common execution patterns through deterministic helpers and ergonomic APIs designed for consistent usage across the FireHub ecosystem. +Lightweight PHP runtime abstraction layer providing clean, deterministic utilities for common execution-level operations. It standardizes recurring runtime patterns through focused helpers and ergonomic APIs designed for consistent usage across the FireHub ecosystem. + +This layer provides execution-level functionality such as array, string, file, environment, reflection, copying, and other low-level runtime operations. It reduces repetitive boilerplate and centralizes common execution behavior while preserving predictable and explicit semantics. -This layer focuses purely on execution-level utilities such as array, string, file, environment, and reflection wrappers, removing repetitive boilerplate while preserving PHP-native behavior. +It contains no domain logic, business rules, or application-level concerns. It is independent of higher-level framework behavior and focuses exclusively on reusable runtime mechanisms that support the FireHub ecosystem. -It contains no domain logic, no business rules, and no framework coupling. Its role is strictly to improve developer experience at the runtime level while keeping behavior predictable, explicit, and dependency-free. +Its role is to provide a consistent execution foundation between native PHP capabilities and higher-level FireHub abstractions. --- -## FireHub Icon Development Branch +## FireHub Icon Repository Purpose -⚠️ **This is the `develop` branch** +This repository provides a lightweight PHP runtime abstraction layer that wraps native PHP functionality into clean, consistent, and deterministic APIs. -- Unstable -- APIs may change without notice -- Not intended for production use +Its purpose is to reduce boilerplate and standardize common execution patterns across the FireHub ecosystem by offering ergonomic helper classes for arrays, strings, files, environment access, and other low-level runtime operations. -## FireHub Icon Branch Purpose +It is strictly focused on execution-level concerns and does not contain domain logic, business rules, or framework-level orchestration. It exists to improve developer productivity while preserving native PHP behavior and ensuring zero framework coupling. -The `develop` branch is the **primary integration branch** for all ongoing development. +## FireHub Icon Security -It serves as the staging area where: -- Feature branches are merged -- Bug fixes are integrated -- Experimental work is stabilized -- Code is prepared for upcoming releases +For security reporting and guidelines, please refer to our [SECURITY.md](https://github.com/The-FireHub-Project/.github/blob/master/.github/SECURITY.md) file. -All **release branches** are created **from `develop`**. +## FireHub Icon Community -## Stability Guarantee +![GitHub watchers](https://img.shields.io/github/watchers/The-FireHub-Project/Runtime?style=social) +![GitHub Repo stars](https://img.shields.io/github/stars/The-FireHub-Project/Runtime?style=social) +![GitHub forks](https://img.shields.io/github/forks/The-FireHub-Project/Runtime?style=social) -❌ No backward compatibility guarantee -❌ APIs may change without notice -❌ Behavior may be incomplete or inconsistent -❌ Breaking changes are expected +- Be sure to review the [Code of Conduct](https://github.com/The-FireHub-Project/.github/blob/master/.github/CODE_OF_CONDUCT.md). +- Read a [Contributing](https://github.com/The-FireHub-Project/.github/blob/master/.github/CONTRIBUTING.md) file to see how you can contribute to this project. +- Read our [Security policy](https://github.com/The-FireHub-Project/.github/blob/master/.github/SECURITY.md) file to see how you can report a vulnerability. +- Review the project [Governance model](https://github.com/The-FireHub-Project/.github/blob/master/.github/GOVERNANCE.md), including roles, decision-making, RFC process, and releases. -This branch is intended **only for contributors and advanced testers**. +## FireHub Icon Support -## FireHub Icon Composer Usage (Not Recommended) +

+ + GitHub in-progress issues + + GitHub total issues + + GitHub opened pull requests +

-For internal testing only: +For help with FireHub products, please refer to the following resources: -```json -{ - "require": { - "the-firehub-project/runtime": "dev-develop" - } -} -``` -⚠️ Never use dev-develop in production. +- **General questions & discussions**: [GitHub Discussions](https://github.com/orgs/The-FireHub-Project/discussions) +- **Bug reports & issues**: [Support](https://github.com/The-FireHub-Project/Runtime/issues) +- **Documentation & guides**: [FireHub Docs](https://the-firehub-project.github.io) +- **Commercial support** (Pro/Enterprise): contact your account manager ## FireHub Icon Authors and Contributors diff --git a/composer.json b/composer.json index af20df4..5dcdcf4 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "the-firehub-project/runtime", - "description": "Lightweight PHP runtime layer providing clean wrapper functions over native PHP.", + "description": "Lightweight PHP runtime layer providing clean, deterministic utilities for common execution-level operations.", "type": "library", "keywords": ["php", "runtime", "foundation", "firehub"], "homepage": "https://the-firehub-project.github.io/runtime", diff --git a/src/Copy.php b/src/Copy.php new file mode 100644 index 0000000..ae0f4c5 --- /dev/null +++ b/src/Copy.php @@ -0,0 +1,231 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=8.4 + * @package Runtime + */ + +namespace FireHub\Runtime; + +use FireHub\Core\Boundary\Runtime\NativeRuntime; +use FireHub\Core\Boundary\Capability\Cloneable; +use FireHub\Runtime\Exception\CopyObjectException; +use Closure, ReflectionException, ReflectionObject; + +/** + * ### Provides operations for creating deep copies of values + * + * Deep copying recursively duplicates mutable arrays and objects while preserving values that are immutable, + * non-copyable, or otherwise cannot safely be duplicated. + * + * Objects implementing the {@see Cloneable} capability are responsible for defining their own deep-copy behavior. + * Internal PHP objects are never copied through reflection because their internal state may not be safely + * reconstructible without their constructor or native cloning semantics. + * + * Circular object references are preserved during the copy operation. + * @since 1.0.0 + */ +final class Copy extends NativeRuntime { + + /** + * ### Creates a deep copy of the given value + * @since 1.0.0 + * + * @uses self::copy() To perform the deep copy. + * + * @param mixed $value

+ * The value to copy. + *

+ * + * @throws \FireHub\Runtime\Exception\CopyObjectException If the object's copying fails. + * + * @return mixed The deep copy of the given value. + */ + public static function deep (mixed $value):mixed { + + $objects = []; + + try { + + return self::copy($value, $objects); + + } catch (ReflectionException $error) { + + throw new CopyObjectException(previous: $error); + + } + + } + + /** + * ### Recursively copies a value + * @since 1.0.0 + * + * @uses self::copyArray() To copy arrays. + * @uses self::copyObject() To copy objects. + * @uses \FireHub\Runtime\DataIs::array() To check if the value is an array. + * @uses \FireHub\Runtime\DataIs::object() To check if the value is an object. + * + * @param mixed $value

+ * The value to copy. + *

+ * @param array $objects

+ * Previously copied objects indexed by object identifier. + *

+ * + * @throws ReflectionException If the object's reflection fails. + * + * @return mixed The copied value. + */ + private static function copy (mixed $value, array &$objects):mixed { + + if (DataIs::array($value)) + return self::copyArray($value, $objects); + + if (!DataIs::object($value)) + return $value; + + return self::copyObject($value, $objects); + + } + + /** + * ### Recursively copies an array + * @since 1.0.0 + * + * @uses self::copy() To copy array items. + * + * @param array $value

+ * The array to copy. + *

+ * @param array $objects

+ * Previously copied objects indexed by object identifier. + *

+ * + * @throws ReflectionException If the object's reflection fails. + * + * @return array The copied array. + */ + private static function copyArray (array $value, array &$objects):array { + + $copy = []; + + foreach ($value as $key => $item) + $copy[$key] = self::copy($item, $objects); + + return $copy; + + } + + /** + * ### Copies an object according to its copy semantics + * @since 1.0.0 + * + * @uses self::copyCloneable() To copy objects implementing the {@see Cloneable} capability. + * @uses self::copyReflective() To copy user-defined objects using reflection. + * + * @param object $value

+ * The object to copy. + *

+ * @param array $objects

+ * Previously copied objects indexed by object identifier. + *

+ * + * @throws ReflectionException If the object's reflection fails. + * + * @return object The copied object. + */ + private static function copyObject (object $value, array &$objects):object { + + if ($value instanceof Closure) return $value; + + if ($value instanceof Cloneable) return self::copyCloneable($value, $objects); + + if (new ReflectionObject($value)->isInternal()) return $value; + + return self::copyReflective($value, $objects); + + } + + /** + * ### Creates a deep copy using the object's own copy contract + * @since 1.0.0 + * + * @uses \FireHub\Runtime\ObjectModel\Identity::id() To get the object's identifier. + * + * @param Cloneable $value

+ * The object to copy. + *

+ * @param array $objects

+ * Previously copied objects indexed by object identifier. + *

+ * + * @return object The copied object. + */ + private static function copyCloneable (Cloneable $value, array &$objects):object { + + $id = ObjectModel\Identity::id($value); + + if (isset($objects[$id])) return $objects[$id]; + + $copy = $value->copy(); + + $objects[$id] = $copy; + + return $copy; + + } + + /** + * ### Creates a deep copy of a user-defined object using reflection + * @since 1.0.0 + * + * @uses \FireHub\Runtime\ObjectModel\Identity::id() To get the object's identifier. + * + * @param object $value

+ * The object to copy. + *

+ * @param array $objects

+ * Previously copied objects indexed by object identifier. + *

+ * + * @throws ReflectionException If the object's reflection fails. + * + * @return object The copied object. + */ + private static function copyReflective (object $value, array &$objects):object { + + $id = ObjectModel\Identity::id($value); + + if (isset($objects[$id])) return $objects[$id]; + + $reflection = new ReflectionObject($value); + + $copy = $reflection->newInstanceWithoutConstructor(); + + $objects[$id] = $copy; + + foreach ($reflection->getProperties() as $property) { + + if ($property->isStatic()) continue; + + if (!$property->isInitialized($value)) continue; + + $property->setValue( + $copy, + self::copy($property->getValue($value), $objects) + ); + + } + + return $copy; + + } + +} \ No newline at end of file diff --git a/src/Exception/CopyObjectException.php b/src/Exception/CopyObjectException.php new file mode 100644 index 0000000..222935b --- /dev/null +++ b/src/Exception/CopyObjectException.php @@ -0,0 +1,31 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=8.3 + * @package Runtime + */ + +namespace FireHub\Runtime\Exception; + +use FireHub\Core\Exception\RuntimeException; + +/** + * ### Represents a failure caused by an object that cannot be copied + * @since 1.0.0 + */ +final class CopyObjectException extends RuntimeException { + + /** + * @inheritDoc + * + * @since 1.0.0 + */ + protected const string DEFAULT_MESSAGE = 'The provided object cannot be copied.'; + +} \ No newline at end of file