/**
  * Set upt the test environment
  *
  * @return null
  */
 public function setUp()
 {
     $this->dataDirs = array(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'Data');
     // get the objects we need
     $config = new Config();
     $config->setValue('autoload/dirs', $this->dataDirs);
     $config->setValue('enforcement/dirs', array());
     $this->structureMap = new StructureMap($config->getValue('autoload/dirs'), $config->getValue('enforcement/dirs'), $config);
     // fill the map
     $this->structureMap->fill();
 }
 /**
  * Will register our autoloading method at the beginning of the spl autoloader stack
  *
  * @param boolean $throw   Should we throw an exception on error?
  * @param boolean $prepend If you want to NOT prepend you might, but you should not
  *
  * @return null
  */
 public function register($throw = true, $prepend = true)
 {
     // Now we have a config no matter what, we can store any instance we might need
     $this->config->storeInstances();
     // We want to let our autoloader be the first in line so we can react on loads
     // and create/return our contracted definitions.
     // So lets use the prepend parameter here.
     spl_autoload_register(array($this, self::OUR_LOADER), $throw, $prepend);
 }
 /**
  * Will get the conditions for a certain assertion indicating keyword like @requires or, if configured, @param
  *
  * @param string       $docBlock         The DocBlock to search in
  * @param string       $conditionKeyword The keyword we are searching for, use assertion defining tags here!
  * @param boolean|null $privateContext   If we have to mark the parsed annotations as having a private context
  *                                       as we would have trouble finding out for ourselves.
  *
  * @return boolean|\AppserverIo\Doppelgaenger\Entities\Lists\AssertionList
  */
 public function getConditions($docBlock, $conditionKeyword, $privateContext = null)
 {
     // There are only 3 valid condition types
     if ($conditionKeyword !== Requires::ANNOTATION && $conditionKeyword !== Ensures::ANNOTATION && $conditionKeyword !== Invariant::ANNOTATION) {
         return false;
     }
     // get the annotations for the passed condition keyword
     $annotations = $this->getAnnotationsByType($docBlock, $conditionKeyword);
     // if we have to enforce basic type safety we need some more annotations
     if ($this->config->getValue('enforcement/enforce-default-type-safety') === true) {
         // lets switch the
         switch ($conditionKeyword) {
             case Ensures::ANNOTATION:
                 // we have to consider @return annotations as well
                 $annotations = array_merge($annotations, $this->getAnnotationsByType($docBlock, 'return'));
                 break;
             case Requires::ANNOTATION:
                 // we have to consider @param annotations as well
                 $annotations = array_merge($annotations, $this->getAnnotationsByType($docBlock, 'param'));
                 break;
             default:
                 break;
         }
     }
     // lets build up the result array
     $assertionFactory = new AssertionFactory();
     $result = new AssertionList();
     foreach ($annotations as $annotation) {
         // try to create assertion instances for all annotations
         try {
             $assertion = $assertionFactory->getInstance($annotation);
         } catch (\Exception $e) {
             error_log($e->getMessage());
             continue;
         }
         if ($assertion !== false) {
             // Do we already got a private context we can set? If not we have to find out four ourselves
             if ($privateContext !== null) {
                 // Add the context (wether private or not)
                 $assertion->setPrivateContext($privateContext);
             } else {
                 // Add the context (private or not)
                 $this->determinePrivateContext($assertion);
             }
             // finally determine the minimal scope of this assertion and add it to our result
             $this->determineMinimalScope($assertion);
             $result->add($assertion);
         }
     }
     return $result;
 }
 /**
  * Visitor method that registers the class loaders in the application.
  *
  * @param \AppserverIo\Psr\Application\ApplicationInterface             $application   The application instance to register the class loader with
  * @param \AppserverIo\Appserver\Core\Api\Node\ClassLoaderNodeInterface $configuration The class loader configuration
  *
  * @return void
  */
 public static function visit(ApplicationInterface $application, ClassLoaderNodeInterface $configuration)
 {
     // load the web application path we want to register the class loader for
     $webappPath = $application->getWebappPath();
     // initialize the class path and the enforcement directories
     $classPath = array();
     $enforcementDirs = array();
     // add the possible class path if folder is available
     foreach ($configuration->getDirectories() as $directory) {
         if (is_dir($webappPath . $directory->getNodeValue())) {
             array_push($classPath, $webappPath . $directory->getNodeValue());
             if ($directory->isEnforced()) {
                 array_push($enforcementDirs, $webappPath . $directory->getNodeValue());
             }
         }
     }
     // initialize the arrays of different omit possibilities
     $omittedEnforcement = array();
     $omittedAutoLoading = array();
     // iterate over all namespaces and check if they are omitted in one or the other way
     foreach ($configuration->getNamespaces() as $namespace) {
         // is the enforcement omitted for this namespace?
         if ($namespace->omitEnforcement()) {
             $omittedEnforcement[] = $namespace->getNodeValue()->__toString();
         }
         // is the autoloading omitted for this namespace?
         if ($namespace->omitAutoLoading()) {
             $omittedAutoLoading[] = $namespace->getNodeValue()->__toString();
         }
     }
     // initialize the class loader configuration
     $config = new Config();
     // set the environment mode we want to use
     $config->setValue('environment', $configuration->getEnvironment());
     // set the cache directory
     $config->setValue('cache/dir', $application->getCacheDir());
     // set the default autoloader values
     $config->setValue('autoloader/dirs', $classPath);
     // collect the omitted namespaces (if any)
     $config->setValue('autoloader/omit', $omittedAutoLoading);
     $config->setValue('enforcement/omit', $omittedEnforcement);
     // set the default enforcement configuration values
     $config->setValue('enforcement/dirs', $enforcementDirs);
     $config->setValue('enforcement/enforce-default-type-safety', $configuration->getTypeSafety());
     $config->setValue('enforcement/processing', $configuration->getProcessing());
     $config->setValue('enforcement/level', $configuration->getEnforcementLevel());
     $config->setValue('enforcement/logger', $application->getInitialContext()->getSystemLogger());
     // create a autoloader instance and initialize it
     $classLoader = new DgClassLoader($config);
     $classLoader->init(new StackableStructureMap($config->getValue('autoloader/dirs'), $config->getValue('enforcement/dirs'), $config), new AspectRegister());
     // add the autoloader to the manager
     $application->addClassLoader($classLoader, $configuration);
 }
 /**
  * Will generate the structure map within the specified root path.
  *
  * @return void
  */
 protected function generate()
 {
     // first of all we will get the version, so we will later know about changes made DURING indexing
     $this->version = $this->findVersion();
     // get the iterator over our project files and create a regex iterator to filter what we got
     $recursiveIterator = $this->getProjectIterator();
     $regexIterator = new \RegexIterator($recursiveIterator, '/^.+\\.php$/i', \RecursiveRegexIterator::GET_MATCH);
     // get the list of enforced files
     $enforcedFiles = $this->getEnforcedFiles();
     // if we got namespaces which are omitted from enforcement we have to mark them as such
     $omittedNamespaces = array();
     if ($this->config->hasValue('enforcement/omit')) {
         $omittedNamespaces = $this->config->getValue('enforcement/omit');
     }
     // iterator over our project files and add array based structure representations
     foreach ($regexIterator as $file) {
         // get the identifiers if any.
         $identifier = $this->findIdentifier($file[0]);
         // if we got an identifier we can build up a new map entry
         if ($identifier !== false) {
             // We need to get our array of needles
             $needles = array(Invariant::ANNOTATION, Ensures::ANNOTATION, Requires::ANNOTATION, After::ANNOTATION, AfterReturning::ANNOTATION, AfterThrowing::ANNOTATION, Around::ANNOTATION, Before::ANNOTATION, Introduce::ANNOTATION, Pointcut::ANNOTATION);
             // If we have to enforce things like @param or @returns, we have to be more sensitive
             if ($this->config->getValue('enforcement/enforce-default-type-safety') === true) {
                 $needles[] = '@var';
                 $needles[] = '@param';
                 $needles[] = '@return';
             }
             // check if the file has contracts and if it should be enforced
             $hasAnnotations = $this->findAnnotations($file[0], $needles);
             // create the entry
             $this->map[$identifier[1]] = array('cTime' => filectime($file[0]), 'identifier' => $identifier[1], 'path' => $file[0], 'type' => $identifier[0], 'hasAnnotations' => $hasAnnotations, 'enforced' => $this->isFileEnforced($file[0], $identifier[1], $hasAnnotations, $enforcedFiles, $omittedNamespaces));
         }
     }
     // save for later reuse.
     $this->save();
 }
 * PHP version 5
 *
 * @author    Bernhard Wick <bw@appserver.io>
 * @copyright 2015 TechDivision GmbH - <info@appserver.io>
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
 * @link      https://github.com/appserver-io/doppelgaenger
 * @link      http://www.appserver.io/
 */
use AppserverIo\Doppelgaenger\Config;
// Get the vendor dir
$vendorDir = __DIR__ . "/vendor";
// Include the composer autoloader as a fallback
$loader = (require $vendorDir . DIRECTORY_SEPARATOR . 'autoload.php');
$loader->add('AppserverIo\\Doppelgaenger', array(__DIR__ . '/src', __DIR__ . '/tests'));
// Load the test config file
$config = new Config();
$config->load(__DIR__ . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'Tests' . DIRECTORY_SEPARATOR . 'Data' . DIRECTORY_SEPARATOR . 'tests.conf.json');
// We have to register our autoLoader to put our proxies in place
$autoLoader = new AppserverIo\Doppelgaenger\AutoLoader($config);
$autoLoader->register();
// we should clear the cache directory from the result of former runs
$cacheDir = $config->getValue('cache/dir');
foreach (scandir($cacheDir) as $cachedFile) {
    // clean the files but do not delete the .gitignore file
    if ($cachedFile === '.gitignore' || $cachedFile === '.' || $cachedFile === '..') {
        continue;
    }
    unlink($cacheDir . DIRECTORY_SEPARATOR . $cachedFile);
}
// make the aspects known
new \AppserverIo\Doppelgaenger\Tests\Data\Aspects\PointcutReferencingTestAspect();
 /**
  * Default constructor
  *
  * @param string                                       $file                         The path of the file we want to parse
  * @param \AppserverIo\Doppelgaenger\Config            $config                       Configuration
  * @param StructureDefinitionHierarchy                 $structureDefinitionHierarchy List of already parsed structures
  * @param \AppserverIo\Doppelgaenger\StructureMap|null $structureMap                 Our structure map instance
  * @param StructureDefinitionInterface|null            $currentDefinition            The current definition we are working on
  * @param array                                        $tokens                       The array of tokens taken from the file
  *
  * @throws \AppserverIo\Doppelgaenger\Exceptions\ParserException
  */
 public function __construct($file, Config $config, StructureDefinitionHierarchy $structureDefinitionHierarchy = null, StructureMap $structureMap = null, StructureDefinitionInterface $currentDefinition = null, array $tokens = array())
 {
     $this->config = $config;
     if (empty($tokens)) {
         // Check if we can use the file
         if (!is_readable($file)) {
             throw new ParserException(sprintf('Could not read input file %s', $file));
         }
         // Get all the tokens and count them
         $this->tokens = token_get_all(file_get_contents($file));
     } else {
         $this->tokens = $tokens;
     }
     // We need the file saved
     $this->file = $file;
     // We also need the token count
     $this->tokenCount = count($this->tokens);
     $this->currentDefinition = $currentDefinition;
     $this->structureMap = is_null($structureMap) ? new StructureMap($config->getValue('autoloader/dirs'), $config->getValue('enforcement/dirs'), $config) : $structureMap;
     $this->structureDefinitionHierarchy = is_null($structureDefinitionHierarchy) ? new StructureDefinitionHierarchy() : $structureDefinitionHierarchy;
 }
 /**
  * Test the unsetValue() method
  *
  * @return void
  */
 public function testUnsetValue()
 {
     // Get our config
     $config = new Config();
     // Unset some values and test if they do not exist anymore
     $this->assertTrue($config->hasValue('environment'));
     $config->unsetValue('environment');
     $this->assertFalse($config->hasValue('environment'));
     // Do the same for a more "complex" index
     $this->assertTrue($config->hasValue('enforcement/enforce-default-type-safety'));
     $config->unsetValue('enforcement/enforce-default-type-safety');
     $this->assertFalse($config->hasValue('enforcement/enforce-default-type-safety'));
 }
 /**
  * Will append all needed filters based on the enforcement level stated in the configuration file.
  *
  * @param resource                                                           $res                 The resource we will append the filters to
  * @param \AppserverIo\Doppelgaenger\Interfaces\StructureDefinitionInterface $structureDefinition Structure definition providing needed information
  *
  * @return array
  */
 protected function appendDefaultFilters(&$res, StructureDefinitionInterface $structureDefinition)
 {
     // resulting array with resources of appended filters
     $filters = array();
     // Lets get the enforcement level
     $levelArray = array();
     if ($this->config->hasValue('enforcement/level')) {
         $levelArray = array_reverse(str_split(decbin($this->config->getValue('enforcement/level'))));
     }
     // Whatever the enforcement level is, we will always need the skeleton filter.
     $filters['SkeletonFilter'] = $this->appendFilter($res, 'AppserverIo\\Doppelgaenger\\StreamFilters\\SkeletonFilter', $structureDefinition);
     // Now lets register and append the filters if they are mapped to a 1
     // Lets have a look at the precondition filter first
     if (isset($levelArray[0]) && $levelArray[0] == 1) {
         // Do we even got any preconditions?
         $filterNeeded = false;
         $iterator = $structureDefinition->getFunctionDefinitions()->getIterator();
         foreach ($iterator as $functionDefinition) {
             if ($functionDefinition->getAllPreconditions()->count() !== 0) {
                 $filterNeeded = true;
                 break;
             }
         }
         if ($filterNeeded) {
             $filters['PreconditionFilter'] = $this->appendFilter($res, 'AppserverIo\\Doppelgaenger\\StreamFilters\\PreconditionFilter', $structureDefinition->getFunctionDefinitions());
         }
     }
     // What about the post-condition filter?
     if (isset($levelArray[1]) && $levelArray[1] == 1) {
         // Do we even got any post-conditions?
         $filterNeeded = false;
         $iterator = $structureDefinition->getFunctionDefinitions()->getIterator();
         foreach ($iterator as $functionDefinition) {
             if ($functionDefinition->getAllPostconditions()->count() !== 0) {
                 $filterNeeded = true;
                 break;
             }
         }
         if ($filterNeeded) {
             $filters['PostconditionFilter'] = $this->appendFilter($res, 'AppserverIo\\Doppelgaenger\\StreamFilters\\PostconditionFilter', $structureDefinition->getFunctionDefinitions());
         }
     }
     // What about the invariant filter?
     if (isset($levelArray[2]) && $levelArray[2] == 1) {
         // Do we even got any invariants?
         if ($structureDefinition->getInvariants()->count(true) !== 0) {
             $filters['InvariantFilter'] = $this->appendFilter($res, 'AppserverIo\\Doppelgaenger\\StreamFilters\\InvariantFilter', $structureDefinition);
         }
     }
     // introductions make only sense for classes
     if ($structureDefinition instanceof ClassDefinition) {
         // add the filter used for introductions
         $filters['IntroductionFilter'] = $this->appendFilter($res, 'AppserverIo\\Doppelgaenger\\StreamFilters\\IntroductionFilter', $structureDefinition->getIntroductions());
     }
     // add the filter we need for our AOP advices
     $filters['AdviceFilter'] = $this->appendFilter($res, 'AppserverIo\\Doppelgaenger\\StreamFilters\\AdviceFilter', array('functionDefinitions' => $structureDefinition->getFunctionDefinitions(), 'aspectRegister' => $this->aspectRegister));
     // add the filter used to proxy to the actual implementation
     $filters['ProcessingFilter'] = $this->appendFilter($res, 'AppserverIo\\Doppelgaenger\\StreamFilters\\ProcessingFilter', $structureDefinition->getFunctionDefinitions());
     // We ALWAYS need the enforcement filter. Everything else would not make any sense
     $filters['EnforcementFilter'] = $this->appendFilter($res, 'AppserverIo\\Doppelgaenger\\StreamFilters\\EnforcementFilter', array('structureDefinition' => $structureDefinition, 'config' => $this->config));
     // at last we want to make the output beatiful and detect sysntax errors
     // $filters['BeautifyFilter'] = $this->appendFilter($res, 'AppserverIo\Doppelgaenger\StreamFilters\BeautifyFilter', array());
     return $filters;
 }
 /**
  * Will test if a configuration using regexed paths can be used properly
  *
  * @return void
  */
 public function testRegexMappingWithoutException()
 {
     // We have to load the config for regular expressions in the project dirs
     $config = new Config();
     $config->load(str_replace(DIRECTORY_SEPARATOR . 'Functional', '', __DIR__) . DIRECTORY_SEPARATOR . 'Data' . DIRECTORY_SEPARATOR . 'RegexTest' . DIRECTORY_SEPARATOR . 'regextest.conf.json');
     $e = null;
     try {
         $regexTestClass1 = new RegexTestClass1();
     } catch (\Exception $e) {
     }
     // Did we get the right $e?
     $this->assertNull($e);
     $e = null;
     try {
         $regexTestClass2 = new RegexTestClass2();
     } catch (\Exception $e) {
     }
     // Did we get the right $e?
     $this->assertNull($e);
     $e = null;
     try {
         $regexTestClass = new RegexTestClass();
     } catch (\Exception $e) {
     }
     // Did we get the right $e?
     $this->assertNull($e);
 }