Skip to content

Conversation

@rela589n
Copy link
Contributor

@rela589n rela589n commented Aug 8, 2025

Description

This PR follows from #429 (comment)

  • Feature: Added support for ColocatedMappingDriver to accept iterable of file paths. This enhances flexibility as clients can now provide specific iterators of required files, rather than an array of complete directories.
  • Refactor: Introduced DirectoryFilesIterator and FilePathNameIterator for easier integration with iterable file paths. This benefits libraries by adapting SplFileInfo objects.
  • Optimization: Improved file lookup performance by replacing in_array() within a loop (O(N * M)) with isset() (O(N)), providing a significant performance enhancement.

 When checking $includedFiles for an included file,
 the previous `in_array()` approach, executed in a loop,
 is very expensive. Basically, it results in performance
 of O(N * M), where N - number of declared classes,
 M - number of included classes. The current approach
 is O(N), since `isset()` check has constant `O(1)` time.
@rela589n rela589n force-pushed the feat-traversable-file-paths branch from e122480 to d289c37 Compare August 8, 2025 12:49
rela589n added a commit to rela589n/doctrine-mongodb-odm that referenced this pull request Aug 8, 2025
In the scope of doctrine/persistence#432
(available from `doctrine/persistence` >= 4.1) there was added
`ColocatedMappingDriver::$filePaths`, which allows
passing an `Traversable` of file paths for the mapping driver to use.
This commit integrates those changes into `AttributeDriver`
(and `AnnotationDriver`).

Since `doctrine/orm` maintains the support
for `doctrine/persistence` of older versions, the `AttributeDriver`
ensures that `$filePaths` is actually defined.
Tests use `InstalledVersions` to opt into new behaviour if
`doctrine/persistence` is at least version 4.1.

The old behaviour can be adapted into new by using
`DirectoryFilesIterator` and `FilePathNameIterator` on directory paths.
rela589n added a commit to rela589n/doctrine-mongodb-odm that referenced this pull request Aug 8, 2025
In the scope of doctrine/persistence#432
(available from `doctrine/persistence` >= 4.1) there was added
`ColocatedMappingDriver::$filePaths`, which allows
passing an `Traversable` of file paths for the mapping driver to use.
This commit integrates those changes into `AttributeDriver`
(and `AnnotationDriver`).

Since `doctrine/orm` maintains the support
for `doctrine/persistence` of older versions, the `AttributeDriver`
ensures that `$filePaths` is actually defined.
Tests use `InstalledVersions` to opt into new behaviour if
`doctrine/persistence` is at least version 4.1.

The old behaviour can be adapted into new by using
`DirectoryFilesIterator` and `FilePathNameIterator` on directory paths.
@rela589n rela589n force-pushed the feat-traversable-file-paths branch 2 times, most recently from 9f869fb to a241c82 Compare August 9, 2025 13:35
rela589n added a commit to rela589n/doctrine-mongodb-odm that referenced this pull request Aug 9, 2025
In the scope of doctrine/persistence#432
(available from `doctrine/persistence` >= 4.1) there was added
`ColocatedMappingDriver::$filePaths`, which allows
passing an `Traversable` of file paths for the mapping driver to use.
This commit integrates those changes into `AttributeDriver`
(and `AnnotationDriver`).

Since `doctrine/orm` maintains the support
for `doctrine/persistence` of older versions, the `AttributeDriver`
ensures that `$filePaths` is actually defined.
Tests use `InstalledVersions` to opt into new behaviour if
`doctrine/persistence` is at least version 4.1.

The old behaviour can be adapted into new by using
`DirectoryFilesIterator` and `FilePathNameIterator` on directory paths.
greg0ire
greg0ire previously approved these changes Aug 9, 2025
Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this progressive approach.

Comment on lines +133 to +136
$filePathsIterator = $this->concatIterables(
$this->filePaths ?? [],
new FilePathNameIterator($dirFilesIterator),
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AppendIterator would be perfect to replace concatIterables and avoid this private method to the class that uses the trait.

Suggested change
$filePathsIterator = $this->concatIterables(
$this->filePaths ?? [],
new FilePathNameIterator($dirFilesIterator),
);
$filePathsIterator = new \AppendIterator();
$filePathsIterator->append(new ArrayIterator($this->filePaths ?? []));
$filePathsIterator->append(new FilePathNameIterator($dirFilesIterator));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also considered doing it this way, but the problem is that ArrayIterator doesn't accept a generic iterable (nor Traversable). Although it works well with array|ArrayObject, that's the only input type it supports. It won't work with $filePaths being some Traversable instead.

* @template TKey
* @template T
*/
private function pathNameIterator(iterable $filesIterator): Generator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, removing a private method from a trait is a breaking change. It could be used by the class that uses it in an other package. But this code has not been released yet.

That's why I thing it's better not introducing concatIterables in this trait.

This change makes it easy for the depending libraries to use iterable of
`SplFileInfo`, adapted to the format of `ColocatedMappingDriver` file paths.
For example, one could provide an instance of Symfony Finder, adapted with
`FilePathNameIterator` without having to reinvent it from scratch.
This change makes it easy for the client code to migrate toward the
newer version. The migration would be as easy as passing
`new FilePathIterator(new DirectoryFilesIterator($paths))` into
the constructor instead of the array of `$paths`.
This commit adds support for `ColocatedMappingDriver` to accept
`iterable` of file paths. Before it was only possible to accept
an array of directory paths. Now, one could provide fine-grained
iterator of only necessary files to the Driver. Bundles should
use Symfony Finder to implement it, since it gives much flexibility
to the client code to configure which files should be included
and which not.

Backward compatibility is achieved with the following approach:
If it's an array, then it should be OK to take a look at `$paths[0]`
and determine if it is a file or a directory. If it's not an array,
we can assume that it's `$filePaths` iterable that's given.
@GromNaN
Copy link
Member

GromNaN commented Aug 18, 2025

Replaced by #433. Thank you @rela589n for exploring this topic.

@GromNaN GromNaN closed this Aug 18, 2025
@rela589n rela589n deleted the feat-traversable-file-paths branch August 18, 2025 15:45
GromNaN pushed a commit to GromNaN/mongodb-odm that referenced this pull request Aug 21, 2025
In the scope of doctrine/persistence#432
(available from `doctrine/persistence` >= 4.1) there was added
`ColocatedMappingDriver::$filePaths`, which allows
passing an `Traversable` of file paths for the mapping driver to use.
This commit integrates those changes into `AttributeDriver`
(and `AnnotationDriver`).

Since `doctrine/orm` maintains the support
for `doctrine/persistence` of older versions, the `AttributeDriver`
ensures that `$filePaths` is actually defined.
Tests use `InstalledVersions` to opt into new behaviour if
`doctrine/persistence` is at least version 4.1.

The old behaviour can be adapted into new by using
`DirectoryFilesIterator` and `FilePathNameIterator` on directory paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants