diff --git a/composer.json b/composer.json
index b64bc04..94f621a 100644
--- a/composer.json
+++ b/composer.json
@@ -27,7 +27,7 @@
"vendor-dir": "vendor"
},
"require-dev": {
- "phpunit/phpunit": "^9.5"
+ "phpunit/phpunit": "^10"
},
"scripts": {
"test": "phpunit"
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index c216ef1..4ea85d6 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,14 +1,8 @@
-
+
./tests/
-
\ No newline at end of file
+
diff --git a/readme.md b/readme.md
index de3d862..5251215 100644
--- a/readme.md
+++ b/readme.md
@@ -43,6 +43,26 @@ $classes = \SH\AutoHook\ComposerJsonParser::getClasses($composerJsonPath);
// Process classes to string
[$output] = \SH\AutoHook\AttributeResolver::processClassesToString($classes);
+// Write to file
+(bool) $written = \SH\AutoHook\FileWriter::write($output, $outputPath);
+ ```
+
+### Advanced Usage
+
+Some projects may not have the composer.json available at runtime, so you can use the class loader object.
+
+#### Build/Wire Up
+
+ ```php
+// Get Classloader object
+$loader = require 'vendor/autoload.php';
+
+// Get the list of classes
+$classes = \SH\AutoHook\ComposerClassLoaderParser::getClasses($loader, ['App\\', 'MyNamespace\\']);
+
+// Process classes to string
+[$output] = \SH\AutoHook\AttributeResolver::processClassesToString($classes);
+
// Write to file
(bool) $written = \SH\AutoHook\FileWriter::write($output, $outputPath);
```
diff --git a/src/ComposerClassLoaderParser.php b/src/ComposerClassLoaderParser.php
new file mode 100644
index 0000000..664eb21
--- /dev/null
+++ b/src/ComposerClassLoaderParser.php
@@ -0,0 +1,68 @@
+ $namespaces Since the classloader does not know which are project vs vendor namespaces, you can pass in an array of namespaces to filter by.
+ *
+ * @return array
+ */
+ public static function getClasses(ClassLoader $classLoader, array $namespaces = []): array
+ {
+ ['namespaces' => $allNamespaces, 'classes' => $classes] = self::getNamespacesAndClasses($classLoader);
+
+ $namespaces = $namespaces ?: array_keys($allNamespaces);
+ $classes = array_keys($classes);
+
+ $matches = [];
+ foreach ($namespaces as $namespace) {
+ foreach ($classes as $key => $class) {
+ if (str_starts_with($class, $namespace)) {
+ $matches[] = $class;
+
+ unset($classes[$key]);
+ }
+ }
+ }
+
+ return $matches;
+ }
+
+ /**
+ * Returns an array with detailed information about namespaces and classes.
+ *
+ * Namespaces(k:namespace, v:paths array): map of namespaces and their absolute paths.
+ * Classes(k:class, v:path): map of classes and their absolute path.
+ *
+ * @return array{
+ * namespaces: array>,
+ * classes: array
+ * }
+ *
+ * Example:
+ * [
+ * 'namespaces' => [
+ * 'MyApp\\Controllers' => ['/Users/jphndpe/Project/src/Controllers/'],
+ * 'MyApp\\Models' => ['/Users/jphndpe/Project/src/Models/'],
+ * ],
+ * 'classes' => [
+ * 'MyApp\\Controllers\\HomeController' => '/Users/jphndpe/Project/src/Controllers/HomeController.php',
+ * 'MyApp\\Models\\UserModel' => '/Users/jphndpe/Project/src/Models/UserModel.php',
+ * ]
+ * ]
+ */
+ public static function getNamespacesAndClasses(ClassLoader $classLoader): array
+ {
+ return [
+ 'namespaces' => $classLoader->getPrefixesPsr4(),
+ 'classes' => $classLoader->getClassMap()
+ ];
+ }
+}
\ No newline at end of file
diff --git a/tests/ComposerClassLoaderParserTest.php b/tests/ComposerClassLoaderParserTest.php
new file mode 100644
index 0000000..d511734
--- /dev/null
+++ b/tests/ComposerClassLoaderParserTest.php
@@ -0,0 +1,40 @@
+ $namespaces, 'classes' => $classes] = ComposerClassLoaderParser::getNamespacesAndClasses(self::getClassLoader());
+
+ self::assertArrayHasKey('SH\\AutoHook\\', $namespaces);
+ self::assertArrayHasKey(ComposerClassLoaderParser::class, $classes);
+ }
+
+ private static function getClassLoader(): ClassLoader
+ {
+ static $classLoader;
+
+ if (null === $classLoader) {
+ $classLoader = require __DIR__.'/../vendor/autoload.php';
+ }
+
+ return $classLoader;
+ }
+}
\ No newline at end of file