Skip to content
CAI
Software that uses CAICheck a score

myclabs/DeepCopy

63.9

Adequate · 26 September 2026

1.2k

lines of production code

PHP

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is a PHP library designed to perform deep copying of objects, handling complex scenarios such as circular references, inheritance, and readonly properties. It provides a flexible architecture for customizing copy behavior through pluggable filters and matchers, allowing users to modify, replace, or exclude specific properties and types. The library includes specialized support for Doctrine entities and proxies, as well as robust handling of standard PHP collections and date objects.

How it got here

2013 — Deep copy engine refactoring and filter system

9 changes.

The core deep copy engine was rewritten to improve reliability, introducing a pluggable filter and matcher architecture for customizing object property handling. This period also involved modernizing the codebase by upgrading to PHP 8.0, restructuring repository configuration, and adding comprehensive test coverage for new features like Doctrine integration.

2014–2017 — Doctrine integration and type filtering

14 changes.

This period focused on extending the library's capabilities through new TypeFilter and TypeMatcher components, enabling custom deep-copy logic for specific data types. Significant improvements were made to handle Doctrine2 proxies and various SPL collections, alongside fixes for DateInterval and DatePeriod objects. The work was supported by comprehensive unit tests and stricter typing across the codebase.

2019–2024 — test fixture expansion

5 changes.

This period focused on expanding the test suite by adding specific PHP fixture classes to verify deep copy behavior across various language features. The work included support for PHP 7.4 typed properties, PHP 8.1 enums, readonly properties, ArrayObject subclasses, and Doctrine proxy objects.

Features

Added Doctrine Proxy matcher to handle Doctrine2 proxies

A new DoctrineProxyMatcher class has been introduced to ensure that Doctrine2 proxy objects are correctly identified and deep-copied. This matcher implements the Matcher interface and checks if an object is an instance of Doctrine\\Persistence\\Proxy, resolving the issue where proxies were previously ignored during deep copy operations.

src/DeepCopy/Matcher/Doctrine · high confidence

Added Doctrine-specific deep copy filters

New filters have been introduced to handle Doctrine entities and collections during deep copying: \DoctrineProxyFilter\ triggers the \\_\_load()\ magic method to ensure proxy entities are fully loaded before copying, \DoctrineCollectionFilter\ maps and deep-copies items within Doctrine collection properties, and \DoctrineEmptyCollectionFilter\ replaces collection properties with empty \ArrayCollection\ instances. These changes address issues where Doctrine proxies were previously ignored and provide explicit control over collection state during the copy process.

src/DeepCopy/Filter/Doctrine · high confidence

Introduces TypeFilter and TypeMatcher components for custom deep-copy behavior

This change adds the \TypeFilter\ interface and two concrete implementations (\ReplaceFilter\ and \ShallowCopyFilter\) to the \DeepCopy\ library, allowing users to define custom logic for replacing or shallow-copying specific types during deep copy operations. It also introduces the \TypeMatcher\ class, which provides a standardized way to check if an element matches a specific type string, enabling the library to apply the correct filter based on type. These components work together to extend the deep copy functionality with more granular control over how different data types are handled.

src/DeepCopy/TypeFilter · high confidence

Introduces a new filter system for customizing object property values during deep copy

The library now supports a pluggable filter architecture that allows users to modify, replace, or preserve specific properties while copying objects. This change introduces the Filter interface and several concrete implementations: ReplaceFilter enables custom transformation of property values via a callback, SetNullFilter forces properties to null, KeepFilter preserves original values (acting as a no-op or placeholder), and ChainableFilter allows filters to be composed without breaking the processing chain. This provides a structured way to customize deep copy behavior on a per-property basis.

src/DeepCopy/Filter · high confidence

New matcher API for filtering object properties during deep copy

The library introduces a new \Matcher\ interface and several concrete implementations (\PropertyMatcher\, \PropertyNameMatcher\, \PropertyTypeMatcher\) that allow users to precisely control which properties are included or excluded during a deep copy operation. \PropertyMatcher\ targets specific properties on specific classes, \PropertyNameMatcher\ matches properties by name across any class, and \PropertyTypeMatcher\ matches properties based on their type, including handling uninitialized properties in PHP 7.4+ and avoiding deprecated \setAccessible()\ calls in PHP 8.1+. This provides a more flexible and robust way to customize copy behavior compared to previous methods.

src/DeepCopy/Matcher · high confidence

Behavioural changes

Deep copy engine rewritten with WeakMap and built-in type filters

The core cloning logic in src/DeepCopy has been significantly refactored to improve reliability and extensibility. Circular references are now tracked using a WeakMap instead of a standard array, and the library now includes built-in type filters for DateInterval, DatePeriod, ArrayObject, and SplDoublyLinkedList to handle these objects safely. The API now supports adding and prepending custom filters via Matcher and TypeMatcher, and introduces a skipUncloneable configuration option to prevent exceptions when encountering non-clonable properties. Additionally, PHP 8.1+ enums are now preserved as-is during the copy process.

src/DeepCopy · high confidence

Introduction of specific exception classes for cloning and property errors

The library now includes dedicated exception classes, CloneException and PropertyException, to provide more granular error handling. CloneException extends UnexpectedValueException to signal issues during the cloning process, while PropertyException extends ReflectionException to handle errors related to property reflection. This allows users to catch these specific error types rather than relying on generic exceptions.

src/DeepCopy/Exception · high confidence

Repository configuration and documentation overhaul

The repository has been restructured to improve distribution and documentation. The README has been significantly expanded to include a table of contents, installation instructions, usage examples, and detailed documentation for matchers and filters. The .gitattributes file has been updated to exclude development artifacts (such as .github/, doc/, fixtures/, tests/, and CI config files) from exported archives, ensuring a cleaner package for end-users. Additionally, the PHPUnit configuration has been updated to target the specific test directory and include code coverage filtering, and a new Scrutinizer CI configuration has been added.

(repo-wide) · high confidence

Support for copying private properties of ancestor objects

The ReflectionHelper utility now recursively retrieves properties from parent classes, enabling the DeepCopy library to correctly copy private properties defined in ancestor objects. Previously, standard reflection methods only accessed properties defined in the immediate class, causing issues when deep-copying objects with inherited private state.

src/DeepCopy/Reflection · high confidence

Fixes

Fix copying of DateInterval and DatePeriod objects

Added DateIntervalFilter and DatePeriodFilter to safely copy DateInterval and DatePeriod objects without modifying their readonly properties, addressing bugs \#87 and \#196. The DateIntervalFilter is deprecated for PHP 7.1+ as it will no longer be necessary in future versions. The DatePeriodFilter handles PHP version differences, including PHP 7.1 support and PHP 8.2+ include\_end\_date option.

src/DeepCopy/TypeFilter/Date · high confidence

Fix deep copying of ArrayObject and SplDoublyLinkedList

Added new type filters to correctly handle deep copying of specific SPL collections that were previously problematic. The new ArrayObjectFilter ensures that ArrayObject instances are properly cloned with their contents deep-copied, addressing issues in PHP 7.4 where reflection properties do not expose the internal storage. Additionally, the SplDoublyLinkedListFilter (with a deprecated alias SplDoublyLinkedList) ensures that elements within doubly linked lists are individually deep-copied rather than just cloned, preventing shared references between the original and the copy.

src/DeepCopy/TypeFilter/Spl · high confidence

Test coverage

Add PHP 7.4 typed property fixtures; Add strict types in tests; Add test fixture for ArrayObject subclass; Added PHP 8.1 enum fixture for card suits; Added fixture classes for Doctrine Proxy and clone behavior testing; Added strict-typed test fixtures for object cloning scenarios; Added test fixtures for DateInterval and DateTimeZone cloning; Added test fixtures for readonly properties; Added tests for DoctrineProxyMatcher; Added unit tests for Doctrine collection, empty collection, and proxy filters; Added unit tests for Keep, Replace, and SetNull filters; Added unit tests for ReflectionHelper; Added unit tests for SPL type filters; Added unit tests for TypeFilter and TypeMatcher components; Added unit tests for property matchers; Updated test suite for PHP 5 compatibility and added date filter tests.

Dependencies

Update to PHP 8.0 and modernize Composer configuration

The library now requires PHP 8.0 or higher, dropping support for older PHP versions. The Composer configuration has been normalized to use PSR-4 autoloading, and development dependencies have been updated to include PHPUnit 7.5/8.5/9.5, Prophecy, and Doctrine collections/common with specific version constraints to ensure compatibility.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 50 → 64 (+14.1)
  • Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 100 → 100 (+0.0)
  • Architecture 69 → 69 (+0.0)
  • Maturity 67 → 67 (+0.0)
  • Readiness 27 → 51 (+24.1)
  • Security 68 → 100 (+32.3)

Resolved (11)

  • Coverage not measured — test suite did not build
  • Dimension evaluation failed
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • No exposed public API
  • No tests found
  • Test reliability not included

New (12)

  • Documentation: no architecture or design documentation (README.md)
  • Documentation: no installation or build instructions (README.md)
  • Documentation: no usage examples (README.md)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • No dependency advisory monitoring
  • Redundant method naming for distinct filter interfaces. The API exposes two separate methods (addFilter vs addTypeFilter) and two separate matcher interfaces (Matcher vs TypeMatcher) that serve the same registration purpose but are distinguished only by the specific interface type. This forces users to know which interface their filter implements to choose the correct method, rather than using a single polymorphic registration method.
  • Workflow token permissions not restricted

Changes since last survey

  • 10 commits — 7 feature/other, 3 fixes

By area

  • (repo) — 3 commits
  • (root) — 2 commits
  • .github/workflows — 2 commits
  • src/DeepCopy — 2 commits
  • .github/FUNDING.yml — 1 commit

Notable commits

  • fix: Fix #209 Replace spl_object_hash with spl_object_id
  • fix: Merge pull request #210 from myclabs/fix-php-8.6
  • fix: Revert fix, I'm afraid of breaking changes
  • change: Add types in a backwards-compatible way
  • change: Merge pull request #211 from myclabs/switch-weakmap
  • change: Merge pull request #212 from myclabs/add-types
  • change: Remove 8.6 from the CI for now
  • change: Rename to ci.yml
  • change: Switch to WeakMap
  • change: Update funding

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

myclabs/DeepCopy was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 26 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 958a0803aae2ade58a9fa4ae31b7cade3bb9ed6f — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-a15879f6f801.