/** * Retrieve a class's `implements` statement * * @param ClassReflection $reflection * @return string */ public function getInterfaceStatement(ClassReflection $reflection) { $interfaceStatement = ''; $parent = $reflection->getParentClass(); $interfaces = array_diff($reflection->getInterfaceNames(), $parent ? $parent->getInterfaceNames() : array()); if (!count($interfaces)) { return $interfaceStatement; } foreach ($interfaces as $interface) { $iReflection = new ClassReflection($interface); $interfaces = array_diff($interfaces, $iReflection->getInterfaceNames()); } $interfaceStatement .= $reflection->isInterface() ? ' extends ' : ' implements '; $classUseNameService = $this->classUseNameService; $interfaceStatement .= implode(', ', array_map(function ($interface) use($classUseNameService, $reflection) { $interfaceReflection = new ClassReflection($interface); return $classUseNameService->getClassUseName($reflection, $interfaceReflection); }, $interfaces)); return $interfaceStatement; }
private function getDeclaration() { $class = $this->getClass(); $declaration = ''; if ($class->isAbstract() && !$class->isInterface() && !$class->isTrait()) { $declaration .= 'abstract '; } if ($class->isFinal()) { $declaration .= 'final '; } $declaration .= $this->getClassType() . ' '; $declaration .= $class->getShortName(); $interfacesNames = $class->getInterfaceNames(); /* * parent */ $parentClass = $class->getParentClass(); if ($parentClass instanceof ClassReflection) { // using the absolute namespace + classname work, even if the class has an use alias defined (absolute are unique) $declaration .= ' extends \\' . $parentClass->getName(); $interfacesNames = array_diff($interfacesNames, $parentClass->getInterfaceNames()); } /* * interfaces */ if (count($interfacesNames) > 0) { $interfacesNamesResult = $interfacesNames; foreach ($interfacesNames as $key => $interfaceName) { $interface = new ClassReflection($interfaceName); $interfacesNamesResult = array_diff($interfacesNamesResult, $interface->getInterfaceNames()); } $declaration .= $class->isInterface() ? ' extends ' : ' implements '; // using the absolute namespace + classname work, even if the class has an use alias defined (absolute are unique) $declaration .= '\\' . implode(', \\', $interfacesNamesResult); } return $declaration; }
/** * Generate code to cache from class reflection. * * This is a total mess, I know. Just wanted to flesh out the logic. * @todo Refactor into a class, clean up logic, DRY it up, maybe move * some of this into Zend\Code * @param ClassReflection $r * @return string */ protected static function getCacheCode(ClassReflection $r) { $useString = ''; $usesNames = array(); if (count($uses = $r->getDeclaringFile()->getUses())) { foreach ($uses as $use) { $usesNames[$use['use']] = $use['as']; $useString .= "use {$use['use']}"; if ($use['as']) { $useString .= " as {$use['as']}"; } $useString .= ";\n"; } } $declaration = ''; if ($r->isAbstract() && !$r->isInterface()) { $declaration .= 'abstract '; } if ($r->isFinal()) { $declaration .= 'final '; } if ($r->isInterface()) { $declaration .= 'interface '; } if (!$r->isInterface()) { $declaration .= 'class '; } $declaration .= $r->getShortName(); $parentName = false; if (($parent = $r->getParentClass()) && $r->getNamespaceName()) { $parentName = array_key_exists($parent->getName(), $usesNames) ? $usesNames[$parent->getName()] ?: $parent->getShortName() : (0 === strpos($parent->getName(), $r->getNamespaceName()) ? substr($parent->getName(), strlen($r->getNamespaceName()) + 1) : '\\' . $parent->getName()); } else { if ($parent && !$r->getNamespaceName()) { $parentName = '\\' . $parent->getName(); } } if ($parentName) { $declaration .= " extends {$parentName}"; } $interfaces = array_diff($r->getInterfaceNames(), $parent ? $parent->getInterfaceNames() : array()); if (count($interfaces)) { foreach ($interfaces as $interface) { $iReflection = new ClassReflection($interface); $interfaces = array_diff($interfaces, $iReflection->getInterfaceNames()); } $declaration .= $r->isInterface() ? ' extends ' : ' implements '; $declaration .= implode(', ', array_map(function ($interface) use($usesNames, $r) { $iReflection = new ClassReflection($interface); return array_key_exists($iReflection->getName(), $usesNames) ? $usesNames[$iReflection->getName()] ?: $iReflection->getShortName() : (0 === strpos($iReflection->getName(), $r->getNamespaceName()) ? substr($iReflection->getName(), strlen($r->getNamespaceName()) + 1) : '\\' . $iReflection->getName()); }, $interfaces)); } $classContents = $r->getContents(false); $classFileDir = dirname($r->getFileName()); $classContents = trim(str_replace('__DIR__', sprintf("'%s'", $classFileDir), $classContents)); $return = "\nnamespace " . $r->getNamespaceName() . " {\n" . $useString . $declaration . "\n" . $classContents . "\n}\n"; return $return; }
/** * Determine if a class implements a given interface * * For PHP versions >= 5.3.7, uses is_subclass_of; otherwise, uses * reflection to determine the interfaces implemented. * * @param string $class * @param string $type * @return bool */ protected function isSubclassOf($class, $type) { if (version_compare(PHP_VERSION, '5.3.7', 'gte')) { return is_subclass_of($class, $type); } $r = new ClassReflection($class); $interfaces = $r->getInterfaceNames(); return in_array($type, $interfaces); }
/** * @param ClassReflection $classReflection * @param $parent * @param $usesNames * @return string */ protected function extractInterfaceStatement(ClassReflection $classReflection, $parent, $usesNames) { $parentInterfaceNames = $parent instanceof ClassReflection ? $parent->getInterfaceNames() : array(); $interfaceNames = array_diff($classReflection->getInterfaceNames(), $parentInterfaceNames); $interfaceStatement = ''; if (!count($interfaceNames)) { return $interfaceStatement; } foreach ($interfaceNames as $interface) { $iReflection = new ClassReflection($interface); $interfaceNames = array_diff($interfaceNames, $iReflection->getInterfaceNames()); } $interfaceStatement .= $classReflection->isInterface() ? ' extends ' : ' implements '; $interfaceStatement .= implode(', ', array_map(function ($interface) use($usesNames, $classReflection) { $iReflection = new ClassReflection($interface); return array_key_exists($iReflection->getName(), $usesNames) ? $usesNames[$iReflection->getName()] ?: $iReflection->getShortName() : (0 === strpos($iReflection->getName(), $classReflection->getNamespaceName()) ? substr($iReflection->getName(), strlen($classReflection->getNamespaceName()) + 1) : '\\' . $iReflection->getName()); }, $interfaceNames)); return $interfaceStatement; }
/** * @param ClassReflection $class * @return string */ public function getDeclarationLine(ClassReflection $class) { $usesNames = $this->getUseArray($class); $declaration = ''; if ($class->isAbstract() && !$class->isInterface() && !$class->isTrait()) { $declaration .= 'abstract '; } if ($class->isFinal()) { $declaration .= 'final '; } if ($class->isInterface()) { $declaration .= 'interface '; } elseif ($class->isTrait()) { $declaration .= 'trait '; } else { $declaration .= 'class '; } $declaration .= $class->getShortName(); $parentName = false; if ($parent = $class->getParentClass()) { $parentName = $this->getClassNameInContext($parent, $class->getNamespaceName(), $usesNames); } if ($parentName) { $declaration .= " extends {$parentName}"; } $interfaces = array_diff($class->getInterfaceNames(), $parent ? $parent->getInterfaceNames() : array()); if (count($interfaces)) { foreach ($interfaces as $interface) { $iReflection = new ClassReflection($interface); $interfaces = array_diff($interfaces, $iReflection->getInterfaceNames()); } $declaration .= $class->isInterface() ? ' extends ' : ' implements '; $declaration .= implode(', ', array_map(function ($interface) use($usesNames, $class) { $iReflection = new ClassReflection($interface); return $this->getClassNameInContext($iReflection, $class->getNamespaceName(), $usesNames); }, $interfaces)); } return $declaration; }
/** * Determine if the type represents a fieldset * * For PHP versions >= 5.3.7, uses is_subclass_of; otherwise, uses * reflection to determine the interfaces implemented. * * @param string $type * @return bool */ protected function isFieldset($type) { if (version_compare(PHP_VERSION, '5.3.7', 'gte')) { return is_subclass_of($type, 'Zend\\Form\\FieldsetInterface'); } $r = new ClassReflection($type); $interfaces = $r->getInterfaceNames(); return in_array('Zend\\Form\\FieldsetInterface', $interfaces); }
/** * @param ClassReflection $class * @return bool */ public function isSatisfiedBy(ClassReflection $class) { return in_array('Zend\\Loader\\SplAutoloader', $class->getInterfaceNames()); }
/** * Cache declared interfaces and classes to a single file * * @param \Zend\Mvc\MvcEvent $e * @return void */ public function cache($e) { $request = $e->getRequest(); if ($request instanceof ConsoleRequest) { if (!($request->getParam('controller') == 'PageSpeed\\Controller\\PageSpeedController' && $request->getParam('action') == 'build')) { return; } } else { return; } if (file_exists(ZF_CLASS_CACHE)) { $this->reflectClassCache(); $code = file_get_contents(ZF_CLASS_CACHE); } else { $code = "<?php\n"; } $classes = array_merge(get_declared_interfaces(), get_declared_classes()); foreach ($classes as $class) { // Skip non-Zend classes if (0 !== strpos($class, 'Zend')) { continue; } // Skip the autoloader factory and this class if (in_array($class, array('Zend\\Loader\\AutoloaderFactory', __CLASS__))) { continue; } if ($class === 'Zend\\Loader\\SplAutoloader') { continue; } // Skip any classes we already know about if (in_array($class, $this->knownClasses)) { continue; } $this->knownClasses[] = $class; $class = new ClassReflection($class); // Skip ZF2-based autoloaders if (in_array('Zend\\Loader\\SplAutoloader', $class->getInterfaceNames())) { continue; } // Skip internal classes or classes from extensions // (this shouldn't happen, as we're only caching Zend classes) if ($class->isInternal() || $class->getExtensionName()) { continue; } $code .= static::getCacheCode($class); } file_put_contents(ZF_CLASS_CACHE, $code); // minify the file file_put_contents(ZF_CLASS_CACHE, php_strip_whitespace(ZF_CLASS_CACHE)); }