/** * {@inheritDoc} */ public function loadMetadataForClass($className, ServiceMetadata $serviceMetadata) { // get all class annotations $reflClass = new \ReflectionClass($className); $classAnnotations = $this->reader->getClassAnnotations($reflClass); $classAnnotations = $this->indexAnnotationsByType($classAnnotations); // load headline service information $serviceAnnotation = $this->getAnnotation($classAnnotations, self::ANNOTATION_SERVICE); if ($serviceAnnotation === false) { throw Exception::classIsNotMappedService($className); } // process events foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) { $methodAnnotations = $this->reader->getMethodAnnotations($reflMethod); $methodAnnotations = $this->indexAnnotationsByType($methodAnnotations); // process listeners $listenerAnnotations = $this->getAnnotation($methodAnnotations, self::ANNOTATION_LISTENER); if ($listenerAnnotations !== false) { if (!is_array($listenerAnnotations)) { $listenerAnnotations = array($listenerAnnotations); } foreach ($listenerAnnotations as $listenerAnnotation) { // ensure we don't double-up listener entries $existingListeners = $serviceMetadata->getListeners($listenerAnnotation->event); if (!in_array($reflMethod->getName(), $existingListeners)) { $serviceMetadata->addListener($listenerAnnotation->event, $reflMethod->getName()); } } } } }
public function testListeners() { $meta = new ServiceMetadata('Service\\Test'); $this->assertEmpty($meta->getAllListeners()); $this->assertEmpty($meta->getListeners('event')); $listeners = array('eventOne' => array('listenerOne'), 'eventTwo' => array('listenerOne', 'listenerTwo')); $meta->setAllListeners($listeners); $this->assertEquals($listeners, $meta->getAllListeners()); $this->assertEquals($listeners['eventOne'], $meta->getListeners('eventOne')); $this->assertEquals($listeners['eventTwo'], $meta->getListeners('eventTwo')); $eventTwoListeners = $listeners['eventTwo']; $eventTwoListeners[] = 'listenerThree'; $meta->addListener('eventTwo', 'listenerThree'); $this->assertEquals($eventTwoListeners, $meta->getListeners('eventTwo')); }
/** * @dataProvider requests * * @param string $method */ public function testDispatchUsesSubResourceService($method) { // configure the Dispatcher with the necessary dependencies $this->dispatcher->setResourceMetadataFactory($this->getMockResourceMetadataFactory()); $this->dispatcher->setServiceMetadataFactory($this->getMockServiceMetadataFactory($method)); $this->dispatcher->setServiceLocator($this->getMockServiceLocator()); $eventManager = $this->getMock('BedRest\\Events\\EventManager'); $this->dispatcher->setEventManager($eventManager); // form a basic request $request = new Request(); $request->setResource('testResource/sub'); $request->setMethod($method); // register listeners for the event on both services $event = $method; $listener = strtolower($event) . 'Listener'; $this->testServiceMeta->addListener($event, $listener); $this->testSubServiceMeta->addListener($event, $listener); // test the right service has its listeners registered $eventManager->expects($this->any())->method('addListener')->with($event, array($this->testSubService, $listener)); $this->dispatcher->dispatch($request); }
/** * Loads the ServiceMetadata for the supplied class. * * @param string $class */ protected function loadMetadata($class) { // first run, we have no parent $parent = null; $parentClasses = $this->getParentClasses($class); $parentClasses[] = $class; // iterate through the list of mapped service parent classes foreach ($parentClasses as $parentClass) { // create an empty metadata class $class = new ServiceMetadata($class); // copy all data from the immediate parent, if present if ($parent) { $class->setClassName($parent->getClassName()); $class->setAllListeners($parent->getAllListeners()); } // now overlay the metadata from the class itself if (!isset($this->loadedMetadata[$parentClass])) { $this->driver->loadMetadataForClass($parentClass, $class); $this->loadedMetadata[$parentClass] = $class; } // the parent for the next iteration will be this iteration $parent = $class; } }