diff --git a/README.md b/README.md index 105c15e..f9ce688 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ClassFinder =========== -A dead simple utility to identify classes, traits and interfaces in a given namespace. +A dead simple utility to identify classes, traits, functions and interfaces in a given namespace. This package is an improved implementation of an [answer on Stack Overflow](https://stackoverflow.com/a/40229665/3000068) and provides additional features with less configuration required. @@ -55,6 +55,7 @@ $classes = ClassFinder::getClassesInNamespace('TestApp1\Foo'); $classes = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::ALLOW_CLASSES); $interfaces = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::ALLOW_INTERFACES); $traits = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::ALLOW_TRAITS); +$funcs = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::ALLOW_FUNCTIONS); // You can combine any of the flags $interfacesTraits = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::ALLOW_TRAITS | ClassFinder::ALLOW_INTERFACES); @@ -80,6 +81,12 @@ var_dump($interfaces); * ) */ var_dump($traits); +/** + * array( + * 'TestApp1\Foo\myFunc', + * ) + */ +var_dump($funcs); /** * array( * 'TestApp1\Foo\BarInterface', @@ -102,6 +109,7 @@ $classes = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::RECUR $classes = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::RECURSIVE_MODE | ClassFinder::ALLOW_CLASSES); $interfaces = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::RECURSIVE_MODE | ClassFinder::ALLOW_INTERFACES); $traits = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::RECURSIVE_MODE | ClassFinder::ALLOW_TRAITS); +$funcs = ClassFinder::getClassesInNamespace('TestApp1\Foo', ClassFinder::RECURSIVE_MODE | ClassFinder::ALLOW_FUNCTIONS); // You can combine any of the flags @@ -125,6 +133,7 @@ var_dump($classes); // You get the idea :) var_dump($interfaces); var_dump($traits); +var_dump($funcs); var_dump($classesTraits); ``` diff --git a/composer.json b/composer.json index 6310a76..0b650c0 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,8 @@ { "name": "danog/class-finder", - "description": "Fork of haydenpierce/class-finder with support for traits and interfaces", + "description": "Fork of haydenpierce/class-finder with support for traits, interfaces and functions", "type": "library", "license": "MIT", - "version": "0.4.3", "authors": [ { "name": "Hayden Pierce", diff --git a/src/ClassFinder.php b/src/ClassFinder.php index 5e290fb..e38e07a 100644 --- a/src/ClassFinder.php +++ b/src/ClassFinder.php @@ -16,6 +16,9 @@ class ClassFinder const ALLOW_CLASSES = 4; const ALLOW_INTERFACES = 8; const ALLOW_TRAITS = 16; + const ALLOW_FUNCTIONS = 32; + + const ALLOW_ALL = 60; const MODE_MASK = 3; diff --git a/src/Classmap/ClassmapEntryFactory.php b/src/Classmap/ClassmapEntryFactory.php index a3324af..8be848d 100644 --- a/src/Classmap/ClassmapEntryFactory.php +++ b/src/Classmap/ClassmapEntryFactory.php @@ -22,26 +22,30 @@ class ClassmapEntryFactory { // Composer will compile user declared mappings to autoload_classmap.php. So no additional work is needed // to fetch user provided entries. - $classmap = require($this->appConfig->getAppRoot() . 'vendor/composer/autoload_classmap.php'); + $classmap = require($this->appConfig->getAppRoot().'vendor/composer/autoload_classmap.php'); - $finalClassMap = array(); + $finalClassMap = []; foreach ($classmap as $potentialClass => $file) { - if ($allowAdditional & ClassFinder::ALLOW_CLASSES && class_exists($potentialClass) - || ($allowAdditional & ClassFinder::ALLOW_INTERFACES && interface_exists($potentialClass)) - || ($allowAdditional & ClassFinder::ALLOW_TRAITS && trait_exists($potentialClass))) { + if (\function_exists($potentialClass)) { + if ($allowAdditional & ClassFinder::ALLOW_FUNCTIONS) { + $finalClassMap[$potentialClass] = $file; + } + } elseif ($allowAdditional & ClassFinder::ALLOW_CLASSES && \class_exists($potentialClass) + || ($allowAdditional & ClassFinder::ALLOW_INTERFACES && \interface_exists($potentialClass)) + || ($allowAdditional & ClassFinder::ALLOW_TRAITS && \trait_exists($potentialClass))) { $finalClassMap[$potentialClass] = $file; } } $classmap = $finalClassMap; // if classmap has no entries return empty array - if(count($classmap) == 0) { - return array(); + if (\count($classmap) == 0) { + return []; } - $classmapKeys = array_keys($classmap); - return array_map(function($index) use ($classmapKeys){ + $classmapKeys = \array_keys($classmap); + return \array_map(function ($index) use ($classmapKeys) { return new ClassmapEntry($classmapKeys[$index]); - }, range(0, count($classmap) - 1)); + }, \range(0, \count($classmap) - 1)); } } diff --git a/src/Classmap/ClassmapFinder.php b/src/Classmap/ClassmapFinder.php index 2bbeaf5..3fc592a 100644 --- a/src/Classmap/ClassmapFinder.php +++ b/src/Classmap/ClassmapFinder.php @@ -21,7 +21,7 @@ class ClassmapFinder implements FinderInterface */ public function isNamespaceKnown($namespace) { - $classmapEntries = $this->factory->getClassmapEntries(ClassFinder::ALLOW_CLASSES | ClassFinder::ALLOW_INTERFACES | ClassFinder::ALLOW_TRAITS); + $classmapEntries = $this->factory->getClassmapEntries(ClassFinder::ALLOW_ALL); foreach($classmapEntries as $classmapEntry) { if ($classmapEntry->knowsNamespace($namespace)) { diff --git a/src/Files/FilesEntry.php b/src/Files/FilesEntry.php index 3aa19d5..d6c8a56 100644 --- a/src/Files/FilesEntry.php +++ b/src/Files/FilesEntry.php @@ -28,7 +28,7 @@ class FilesEntry */ public function knowsNamespace($namespace) { - $classes = $this->getClassesInFile(ClassFinder::ALLOW_CLASSES | ClassFinder::ALLOW_INTERFACES | ClassFinder::ALLOW_TRAITS); + $classes = $this->getClassesInFile(ClassFinder::ALLOW_ALL); foreach($classes as $class) { if (strpos($class, $namespace) !== false) { @@ -88,18 +88,21 @@ class FilesEntry // get_declared_*() returns a bunch of classes|interfaces|traits that are built into PHP. So we need a control here. list($initialInterfaces, $initialClasses, - $initialTraits - ) = $this->execReturn("var_export(array(get_declared_interfaces(), get_declared_classes(), get_declared_traits()));"); + $initialTraits, + $initialFuncs + ) = $this->execReturn("var_export(array(get_declared_interfaces(), get_declared_classes(), get_declared_traits(), get_defined_functions()['user']));"); // This brings in the new classes. so $classes here will include the PHP defaults and the newly defined classes list($allInterfaces, $allClasses, - $allTraits - ) = $this->execReturn("require_once '{$this->file}'; var_export(array(get_declared_interfaces(), get_declared_classes(), get_declared_traits()));"); + $allTraits, + $allFuncs + ) = $this->execReturn("require_once '{$this->file}'; var_export(array(get_declared_interfaces(), get_declared_classes(), get_declared_traits(), get_defined_functions()['user']));"); $interfaces = array_diff($allInterfaces, $initialInterfaces); $classes = array_diff($allClasses, $initialClasses); $traits = array_diff($allTraits, $initialTraits); + $funcs = array_diff($allFuncs, $initialFuncs); $final = array(); if ($options & ClassFinder::ALLOW_CLASSES) { @@ -111,6 +114,9 @@ class FilesEntry if ($options & ClassFinder::ALLOW_TRAITS) { $final = array_merge($final, $traits); } + if ($options & ClassFinder::ALLOW_FUNCTIONS) { + $final = array_merge($final, $funcs); + } return $final; } diff --git a/src/PSR4/PSR4Namespace.php b/src/PSR4/PSR4Namespace.php index 1df0eb3..6f81996 100644 --- a/src/PSR4/PSR4Namespace.php +++ b/src/PSR4/PSR4Namespace.php @@ -203,7 +203,7 @@ class PSR4Namespace if (function_exists($potentialClass)) { // For some reason calling class_exists() on a namespace'd function raises a Fatal Error (tested PHP 7.0.8) // Example: DeepCopy\deep_copy - return false; + return ($allowAdditional & ClassFinder::ALLOW_FUNCTIONS); } else { return ($allowAdditional & ClassFinder::ALLOW_CLASSES && class_exists($potentialClass)) || ($allowAdditional & ClassFinder::ALLOW_INTERFACES && interface_exists($potentialClass)) @@ -247,7 +247,7 @@ class PSR4Namespace if (function_exists($potentialClass)) { // For some reason calling class_exists() on a namespace'd function raises a Fatal Error (tested PHP 7.0.8) // Example: DeepCopy\deep_copy - return false; + return ($allowAdditional & ClassFinder::ALLOW_FUNCTIONS); } else { return ($allowAdditional & ClassFinder::ALLOW_CLASSES && class_exists($potentialClass)) || ($allowAdditional & ClassFinder::ALLOW_INTERFACES && interface_exists($potentialClass))