AppserverIo\Appserver\AspectContainer\AspectManager::registerAspectXml PHP Method

registerAspectXml() public method

Registers aspects written within source files which we might encounter
public registerAspectXml ( AppserverIo\Psr\Application\ApplicationInterface $application ) : void
$application AppserverIo\Psr\Application\ApplicationInterface The application instance
return void
    public function registerAspectXml(ApplicationInterface $application)
    {
        /** @var \AppserverIo\Appserver\Core\Api\ConfigurationService $configurationService */
        $configurationService = $application->newService('AppserverIo\\Appserver\\Core\\Api\\ConfigurationService');
        // check if we even have a XMl file to read from
        $xmlPaths = $configurationService->globDir(AppEnvironmentHelper::getEnvironmentAwareGlobPattern($this->getWebappPath(), '{WEB-INF,META-INF,common}' . DIRECTORY_SEPARATOR . self::CONFIG_FILE_GLOB, GLOB_BRACE), GLOB_BRACE);
        foreach ($xmlPaths as $xmlPath) {
            // iterate all XML configuration files we found
            if (is_readable($xmlPath)) {
                // validate the file here, if it is not valid we can skip further steps
                try {
                    $configurationService->validateFile($xmlPath, null, true);
                } catch (InvalidConfigurationException $e) {
                    /** @var \Psr\Log\LoggerInterface $systemLogger */
                    $systemLogger = $this->getApplication()->getInitialContext()->getSystemLogger();
                    $systemLogger->error($e->getMessage());
                    $systemLogger->critical(sprintf('Pointcuts configuration file %s is invalid, AOP functionality might not work as expected.', $xmlPath));
                    continue;
                }
                // load the aop config
                $config = new \SimpleXMLElement(file_get_contents($xmlPath));
                $config->registerXPathNamespace('a', 'http://www.appserver.io/appserver');
                // create us an aspect
                // name of the aspect will be the application name
                $aspect = new Aspect();
                $aspect->setName($xmlPath);
                // check if we got some pointcuts
                foreach ($config->xpath('/a:pointcuts/a:pointcut') as $pointcutConfiguration) {
                    // build up the pointcut and add it to the collection
                    $pointcut = new Pointcut();
                    $pointcut->setAspectName($aspect->getName());
                    $pointcut->setName((string) $pointcutConfiguration->{'pointcut-name'});
                    $pointcut->setPointcutExpression(new PointcutExpression((string) $pointcutConfiguration->{'pointcut-pattern'}));
                    $aspect->getPointcuts()->add($pointcut);
                }
                // check if we got some advices
                foreach ($config->xpath('/a:pointcuts/a:advice') as $adviceConfiguration) {
                    // build up the advice and add it to the aspect
                    $advice = new Advice();
                    $advice->setAspectName((string) $adviceConfiguration->{'advice-aspect'});
                    $advice->setName($advice->getAspectName() . '->' . (string) $adviceConfiguration->{'advice-name'});
                    $advice->setCodeHook((string) $adviceConfiguration->{'advice-type'});
                    $pointcutPointcut = $this->generatePointcutPointcut((array) $adviceConfiguration->{'advice-pointcuts'}->{'pointcut-name'}, $aspect);
                    $advice->getPointcuts()->add($pointcutPointcut);
                    // finally add the advice to our aspect (we will also add it without pointcuts of its own)
                    $aspect->getAdvices()->add($advice);
                }
                // if the aspect contains pointcuts or advices it can be used
                if ($aspect->getPointcuts()->count() > 0 || $aspect->getAdvices()->count() > 0) {
                    $this->getAspectRegister()->set($aspect->getName(), $aspect);
                }
            }
        }
    }

Usage Example

 /**
  * Tests if we are able to reference multiple pointcuts for the same advice using XML
  *
  * @return void
  */
 public function testXmlAllowsForMultiPointcut()
 {
     $this->markTestSkipped('Strange behaviour related to \\Stackable usage. Skipped until an alternative has been found.');
     $configPath = $this->getMockWebappPath() . DIRECTORY_SEPARATOR . 'META-INF' . DIRECTORY_SEPARATOR . 'pointcuts.xml';
     $mockApplication = $this->getSpecificConfigMockApplication($configPath);
     // inject our mock and run the parsing process
     $this->testClass->injectApplication($mockApplication);
     $this->testClass->registerAspectXml($mockApplication);
     // did we get everything? Check for the expected advice
     $advicesList = $this->testClass->getAspectRegister()->get($configPath)->getAdvices();
     $this->assertTrue($advicesList->entryExists('\\AppserverIo\\Appserver\\NonExisting\\MetaInf\\Namespace\\TestAspect->metainfAdvice'));
     // check for the expected pointcuts the advice should reference
     $referencedPointcuts = $advicesList->get('\\AppserverIo\\Appserver\\NonExisting\\MetaInf\\Namespace\\TestAspect->metainfAdvice')->getPointcuts()->get(0)->getReferencedPointcuts();
     $this->assertCount(2, $referencedPointcuts);
 }