/** * @param string $name_ * @param array $args_ * * @return \Components\Enumeration * * @throws \Components\Runtime_Exception */ public static function __callStatic($name_, array $args_ = []) { $type = get_called_class(); if (__CLASS__ === $type) { throw new Exception_Abstract_Type('components/enumeration', 'Enumeration can not be invoked directly.'); } if (isset(self::$m_enumInstances[$type][$name_])) { return self::$m_enumInstances[$type][$name_]; } if (false === isset(self::$m_enums[$type])) { self::initializeType($type); } if (false === array_key_exists($name_, self::$m_enums[$type])) { $trace = debug_backtrace(false); $caller = $trace[1]; throw new Exception_NotImplemented('components/enumeration', sprintf('Call to undefined method %1$s::%2$s() in %3$s on line %4$d.', $type, $name_, $caller['file'], $caller['line'])); } if (!($concrete = Runtime_Classloader::lookup(String::typeToNamespace($type) . '/' . String::typeToPath($name_)))) { $concrete = $type; } if (0 < count($args_)) { array_unshift($args_, constant("{$type}::{$name_}")); array_unshift($args_, self::$m_enums[$type][$name_]); $class = new \ReflectionClass($concrete); return $class->newInstanceArgs($args_); } // Cache simple enum instances. // XXX Instances MUST be state-less. return self::$m_enumInstances[$type][$name_] = new $concrete(self::$m_enums[$type][$name_], constant("{$type}::{$name_}")); }
/** * @GET * @POST */ public function update() { foreach (Runtime_Classloader::get()->getClasspaths() as $type => $path) { if (Entity_Default::TYPE !== $type) { $class = new \ReflectionClass($type); if ($class->isSubclassOf('Components\\Entity')) { $this->updateForEntity($type); } } } }
private static function initializeMethods() { if (false === (self::$m_methods = Cache::get('components/rest/methods'))) { self::$m_methods = []; } foreach (self::$m_resources as $resource) { if (isset(self::$m_methods[$resource])) { continue; } $annotations = Annotations::get($resource); foreach ($annotations->getMethodAnnotations() as $methodName => $methodAnnotations) { $httpMethods = []; foreach ($methodAnnotations as $methodAnnotationName => $methodAnnotation) { if ($methodAnnotation instanceof Annotation_Method) { $httpMethods[$methodAnnotationName] = $methodAnnotationName; } } if (count($httpMethods)) { $type = new \ReflectionClass($resource); $method = $type->getMethod($methodName); $parameters = $method->getParameters(); $path = []; $query = []; foreach ($parameters as $parameter) { $parameterAnnotations = $annotations->getParameterAnnotations($methodName, $parameter->name); if (isset($parameterAnnotations[Annotation_Param_Query::NAME])) { if (isset($parameterAnnotations[Annotation_Param_Query::NAME]->name)) { $name = $parameterAnnotations[Annotation_Param_Query::NAME]->name; } else { $name = $parameter->name; } if (isset($parameterAnnotations[Annotation_Param_Query::NAME]->type)) { $type = $parameterAnnotations[Annotation_Param_Query::NAME]->type; if (Primitive::isNative($type)) { $type = Primitive::asBoxed($type); } else { if ($lookupType = Runtime_Classloader::lookup($type)) { $type = $lookupType; } } } else { if ($type = $parameter->getClass()) { $type = $type->name; } else { $type = String::TYPE; } } if (isset($parameterAnnotations[Annotation_Param_Query::NAME]->default)) { $value = $parameterAnnotations[Annotation_Param_Query::NAME]->default; } else { $value = null; } $query[$parameter->name] = ['name' => $name, 'type' => $type, 'value' => $value]; } else { if ($parameter->isOptional()) { if ($type = $parameter->getClass()) { $query[$parameter->name] = $type->name; } else { $query[$parameter->name] = String::TYPE; } } else { if (isset($parameterAnnotations[Annotation_Param_Path::NAME]->type)) { $type = $parameterAnnotations[Annotation_Param_Path::NAME]->type; if (Primitive::isNative($type)) { $type = Primitive::asBoxed($type); } else { if ($lookupType = Runtime_Classloader::lookup($type)) { $type = $lookupType; } } $path[$parameter->name] = $type; } else { if ($type = $parameter->getClass()) { $path[$parameter->name] = $type->name; } else { $path[$parameter->name] = String::TYPE; } } } } } $matches = []; preg_match('/\\@return\\s+([\\a-z]+)\\n/i', $method->getDocComment(), $matches); $return = null; if (isset($matches[1])) { $return = $matches[1]; } self::$m_methods[$resource][$methodName] = ['name' => $methodName, 'methods' => $httpMethods, 'path' => $path, 'query' => $query, 'return' => $return]; } } } Cache::set('components/rest/methods', self::$m_methods); }
/** * Parses and caches annotations for given name of an annotated type if * not already cached. * * Retrieves neccessary information from cache and builds & returns * an instance of Annotations. * * @param string $type_ Name of annotated type. * * @return \Components\Annotations */ private static function resolveInstance($type_) { if (0 === strpos($type_, '\\')) { $type_ = ltrim($type_, '\\'); } $cacheKeyType = 'components/type/annotations/' . md5($type_); if (false === ($cached = Cache::get($cacheKeyType))) { // Pays off if classloader cache is built sufficiently ... if (!($typeLocation = Runtime_Classloader::get()->getClasspath($type_))) { $cacheKeyTypeLocation = "{$cacheKeyType}/file"; // ... yet requires fallback for out-of-control classloaders (e.g. during unit test execution). if (false === ($typeLocation = Cache::get($cacheKeyTypeLocation))) { $type = new \ReflectionClass($type_); $typeLocation = $type->getFileName(); Cache::set($cacheKeyTypeLocation, $typeLocation); } } $annotations = self::parseAnnotations($typeLocation); foreach ($annotations as $type => $typeAnnotations) { Cache::set($cacheKeyType, $typeAnnotations); } $instance = new self($type_); $instance->m_annotations = $annotations[$type_]; } else { $instance = new self($type_); $instance->m_annotations = $cached; } return $instance; }
protected function initialize() { $a = Annotations::get($this->entityType); $this->entityName = Runtime_Classloader::lookupName($this->entityType); if ($annotation = $a->getTypeAnnotation(Annotation_Name::NAME)) { $this->collectionName = $a->getTypeAnnotation(Annotation_Name::NAME)->value; } else { $this->collectionName = strtolower(substr($this->entityType, strrpos($this->entityType, '_') + 1)); } if ($annotation = $a->getTypeAnnotation(Annotation_Collection::NAME)) { $this->collectionType = Runtime_Classloader::lookup($annotation->value); } else { $this->collectionType = Entity_Collection::TYPE; } $this->autoIncrement = true; foreach ($a->getPropertyAnnotations() as $property => $annotations) { if (isset($annotations[Annotation_Id::NAME])) { $this->collectionPrimaryKey = $property; $this->collectionPrimaryKeyAutoIncrement = Boolean::valueIsTrue($annotations[Annotation_Id::NAME]->auto); } } }
/** * Generates EMMA code coverage report. * * @param array $xDebugReport_ * * @todo Implement */ protected function report(Test_Runner $runner_, array $xDebugReport_) { $testPaths = $runner_->getTestPaths(); $classpaths = []; foreach (Runtime_Classloader::getClassloaders() as $classloader) { $classpaths = array_merge($classpaths, $classloader->getClasspaths()); } $emmaReport = []; foreach ($classpaths as $clazz => $path) { if (isset($testPaths[$path])) { continue; } $this->reportForClass($clazz, $path, $xDebugReport_, $emmaReport); } $document = new \DOMDocument('1.0', 'utf-8'); $document->formatOutput = true; $report = $document->createElement('report'); $document->appendChild($report); $stats = $document->createElement('stats'); $report->appendChild($stats); $statsPackages = $document->createElement('packages'); $statsPackages->setAttribute('value', count($this->m_packages)); $stats->appendChild($statsPackages); $statsClasses = $document->createElement('classes'); $statsClasses->setAttribute('value', count($this->m_classes)); $stats->appendChild($statsClasses); $statsMethods = $document->createElement('methods'); $statsMethods->setAttribute('value', count($this->m_methods)); $stats->appendChild($statsMethods); $statsFiles = $document->createElement('srcfiles'); $statsFiles->setAttribute('value', count($this->m_files)); $stats->appendChild($statsFiles); $statsLines = $document->createElement('srclines'); $statsLines->setAttribute('value', $this->m_lines); $stats->appendChild($statsLines); $data = $document->createElement('data'); $report->appendChild($data); $all = $document->createElement('all'); $all->setAttribute('name', 'all classes'); $data->appendChild($all); $countLines = 0; $countLinesCovered = 0; $countClasses = 0; $countClassesCovered = 0; $countMethods = 0; $countMethodsCovered = 0; foreach ($emmaReport as $package) { foreach ($package as $files) { foreach ($files as $clazz) { $countClasses++; $countLines += $clazz['lines']; $countLinesCovered += $clazz['covered']; if (0 < $clazz['covered']) { $countClassesCovered++; } foreach ($clazz['methods'] as $method) { $countMethods++; if (0 < $method['covered']) { $countMethodsCovered++; } } } } } $this->appendCoverage($document, $all, 'class, %', $countClasses, $countClassesCovered); $this->appendCoverage($document, $all, 'method, %', $countMethods, $countMethodsCovered); $this->appendCoverage($document, $all, 'block, %', $countMethods, $countMethodsCovered); $this->appendCoverage($document, $all, 'line, %', $countLines, $countLinesCovered); foreach (array_keys($emmaReport) as $package) { $this->appendPackage($document, $all, $package, $emmaReport[$package]); } $document->save($this->m_buildPath); }