public function testIfWillProperlyCacheNamespacesForDifferentMetaContainers() { $path = (new ConfigDetector())->getRuntimePath(); if (!is_dir($path)) { mkdir($path); } // Simulate different meta container classes by creating different paths $path1 = sprintf('%s/path1', $path); $path2 = sprintf('%s/path2', $path); $path3 = sprintf('%s/path3', $path); if (!is_dir($path1)) { mkdir($path1); } if (!is_dir($path2)) { mkdir($path2); } if (!is_dir($path3)) { mkdir($path3); } $ns1 = new NsCache($path1, Addendum::fly(), new CacheOptionsOne()); $ns1->set(); codecept_debug($ns1->get()); $this->assertTrue($ns1->valid()); $ns2 = new NsCache($path2, Addendum::fly(), new CacheOptionsTwo()); $ns2->set(); codecept_debug($ns2->get()); $this->assertTrue($ns1->valid()); $this->assertTrue($ns2->valid()); $ns3 = new NsCache($path3, Addendum::fly(), new CacheOptionsOne()); $ns3->set(); codecept_debug($ns3->get()); $this->assertTrue($ns1->valid()); $this->assertTrue($ns2->valid()); $this->assertTrue($ns3->valid()); }
public function testIfWillRecognizeAnnotationAfterDynamicallyAddingNamespace() { $model = new ModelWithTwoNsAnnotations(); $options = new MetaOptions(); $options->namespaces[] = NamespacedAnnotation::Ns; $meta = Meta::create($model, $options)->title; $this->assertTrue($meta->namespaced); // Not added second namespace $this->assertNull($meta->second); $this->assertNull($meta->third); // Second ns $options->namespaces[] = SecondNsAnnotation::Ns; $metaContainer2 = Meta::create($model, $options); $this->assertNotNull($metaContainer2); $meta2 = $metaContainer2->title; $this->assertTrue($meta2->namespaced); // Added second namespace $this->assertTrue($meta2->second, 'That namespace added via options id detected'); // Third ns Addendum::fly()->addNamespace(ThirdNsAnnotation::Ns); $meta3 = Meta::create($model, $options)->title; $this->assertTrue($meta3->namespaced); $this->assertTrue($meta3->second); // Added second namespace $this->assertTrue($meta3->third, 'That namespace added via Addendum::addNamespace is detected'); }
/** * @param string|object|AnnotatedInterface $model * @param MetaOptions $options * @throws Exception */ protected function __construct($model = null, MetaOptions $options = null) { // For internal use if (null === $model) { return; } if (null === $options) { $options = new MetaOptions(); } // TODO Use adapter here // ?TODO Abstract from component meta, so other kinds of meta extractors could be used // For example, for development annotation based extractor could be used, which could compile // Metadata to arrays, and for production environment, compiled arrays could be used $annotations = []; $mes = []; // Get reflection data $ad = Addendum::fly($options->instanceId); $ad->addNamespaces($options->namespaces); $info = $ad->annotate($model); // Class name of working component $className = is_object($model) ? get_class($model) : $model; if (!$info instanceof ReflectionAnnotatedClass) { throw new Exception(sprintf('Could not annotate `%s`', $className)); } $properties = $info->getProperties(ReflectionProperty::IS_PUBLIC); $defaults = $info->getDefaultProperties(); $methods = $info->getMethods(ReflectionMethod::IS_PUBLIC); // Setup type /** * @todo Fix it: $this->_meta->{$this->name}->... * ^-- _meta __get and __set is only for fields AND use _fields field, * for class OR methods it should use different fields * for class should be _main * for methods should be _methods * __get and __set should distinguish it somehow... - maybe by field type EComponentMetaProperty for fieltds etc. * Currently disabled * OR add function to Annotation to setEntity, which should point to _field, _main or _method? */ // Setup class annotations $this->_type = new $options->typeClass($info); foreach ($info->getAllAnnotations() as $annotation) { if (!$annotation instanceof MetaAnnotationInterface) { continue; } $annotation->setName($info->name); $annotation->setEntity($this->_type); $annotation->setMeta($this); $annotation->init(); $annotations[] = $annotation; } // Setup methods foreach ($methods as $method) { if (!$method instanceof ReflectionAnnotatedMethod) { throw new Exception(sprintf('Could not annotate `%s::%s()`', $className, $method->name)); } // Ignore magic methods if (preg_match('~^__~', $method->name)) { continue; } // Ignore @Ignored marked methods if (IgnoredChecker::check($method)) { continue; } // Create method holder class based on options $methodMeta = new $options->methodClass($method); foreach ($method->getAllAnnotations() as $annotation) { if (!$annotation instanceof MetaAnnotationInterface) { continue; } $annotation->setName($method->name); $annotation->setEntity($methodMeta); $annotation->setMeta($this); $annotation->init(); $annotations[] = $annotation; } // Put it to metadata object $this->_methods[$method->name] = $methodMeta; // Get getters and setters for properties setup if (preg_match('~^[gs]et~', $method->name) && !$method->isStatic()) { $mes[$method->name] = true; } } // Setup properties foreach ($properties as $property) { if (!$property instanceof ReflectionAnnotatedProperty) { throw new Exception(sprintf('Could not annotate `%s::%s`', $className, $property->name)); } if (IgnoredChecker::check($property)) { continue; } $name = $property->name; /* @var $property ReflectionAnnotatedProperty */ $field = new $options->propertyClass($property); // Access options $field->callGet = isset($mes[$field->methodGet]) && $mes[$field->methodGet]; $field->callSet = isset($mes[$field->methodSet]) && $mes[$field->methodSet]; $field->direct = !($field->callGet || $field->callSet); $field->isStatic = $property->isStatic(); // Other if (array_key_exists($name, $defaults)) { $field->default = $defaults[$name]; } // Put it to metadata object $this->_fields[$field->name] = $field; foreach ($property->getAllAnnotations() as $annotation) { if (!$annotation instanceof MetaAnnotationInterface) { continue; } $annotation->setName($field->name); $annotation->setEntity($field); $annotation->setMeta($this); $annotation->init(); $annotations[] = $annotation; } } foreach ($annotations as $annotation) { $annotation->afterInit(); } }
/** * * @param string $metaClass * @param AnnotatedInterface|object|string $component * @param MetaOptions|Addendum $options */ public function __construct($metaClass = null, $component = null, $options = null) { if (null === self::$runtimePath) { self::$runtimePath = (new ConfigDetector())->getRuntimePath(); } $this->path = self::$runtimePath . '/addendum'; $this->metaClass = $metaClass; $this->component = $component; if (empty($options)) { $this->instanceId = Addendum::DefaultInstanceId; } elseif ($options instanceof Addendum) { $this->instanceId = $options->getInstanceId(); } elseif ($options instanceof MetaOptions) { $this->instanceId = $options->instanceId; } else { throw new UnexpectedValueException('Unknown options'); } $this->prepare(); $this->addendum = Addendum::fly($this->instanceId); $this->nsCache = new NsCache(dirname($this->getFilename()), $this->addendum); }