dg / bypass-finals

Removes `final` and `readonly` keywords from source code on-the-fly and allows mocking of final methods and classes. It can be used together with any test tool such as PHPUnit or Mockery.
Other
477 stars 30 forks source link

Add setWhitelist method to allow controlling which files get replaced. #7

Closed afilina closed 5 years ago

afilina commented 5 years ago

Reason behind this feature: Some frameworks stop working because of DIR and such, since the files are now served from tmp. This prompted me to add a more fine-grained control.

I added a test and documentation. The old behavior remains unaffected.

dg commented 5 years ago

Thank you for the great PR. Whitelist can be useful.

I tried to test __DIR__ and __FILE__ (see https://github.com/dg/bypass-finals/commit/06d98c87299ce5fa6b0fc709cabdfa7ca2d04576) and it seems that these constants works as expected. Could you describe when they did not work?

afilina commented 5 years ago

@dg That's only a guess. It was deep within Laravel's call stack. Perhaps the added layer of Docker caused the problem. We stopped digging at some point and just created the exclusion. In any case, even if the bug was somewhere else, this still covers a number of legitimate scenarios.

dg commented 5 years ago

I am thinking about method name… It is not entirely clear that this is about paths, ie allowed paths. What about setAllowedPaths()? Or simply setPaths()? setDirectories()?

afilina commented 5 years ago

Sure, whichever you prefer.

torchello commented 5 years ago

Actually phpspec stops generating PHP classes based on specs:

warning: file_get_contents(/usr/local/var/www/myproject/src/Repository/UserOrderRepository.php): failed to open stream: No such file or directory in /usr/local/var/www/newonline/vendor/dg/bypass-finals/src/
  BypassFinals.php line 211

Was able to get it working with @afilina fork and custom phpspec bootstrap:

<?php

require __DIR__.'/../vendor/autoload.php';

DG\BypassFinals::setWhitelist(findFinalClassesToBypass());
DG\BypassFinals::enable();

function findFinalClassesToBypass(): array
{
    $finalClasses = (new Symfony\Component\Finder\Finder())
        ->in([__DIR__.'/../vendor/symfony/security-core'])
        ->name('*.php')
        ->contains('final class');

    return array_values(array_map(
        function (SplFileInfo $fileInfo) {
            return $fileInfo->getRealPath();
        },
        iterator_to_array($finalClasses)
    ));
}

@afilina Thanks! 👍

tarampampam commented 5 years ago

@dg PR will be merged & released? This feature is very important for me too

tarampampam commented 5 years ago

Fork with this feature: https://github.com/avto-dev/bypass-finals

@afilina - great thx! :+1:

sergejostir commented 4 years ago

Isn't the name kinda misleading since you cannot just set a path, but need to set every filepath individually? Also it doesn't take into consideration the difference between operating systems (\ vs /).