php-aop icon indicating copy to clipboard operation
php-aop copied to clipboard

Resolve magic constants to a resolved path

Open djschilling opened this issue 2 years ago • 7 comments

I have some php code that looks like this:

    public function checkInternalGroupPermissionForPerson(string $auth, ?int $personId) {
        include_once dirname(__DIR__, 3) . '/churchdb/churchdb_db.php';
        $groups = getMyGroupIdsWhereIAmAllowed($auth);
        $personIds = churchdb_getAllPeopleIdsFromGroups($groups);

        return isset($personIds[$personId]);
    }

The lives in a class for which php-aop creates a proxy. The file churchdb_db.php does not need a proxy and so the include does not work. How can i solve this?

djschilling avatar Nov 07 '23 09:11 djschilling

Hi @djschilling,

I will have a look at this in the evening :)

WalterWoshid avatar Nov 07 '23 09:11 WalterWoshid

For me: https://www.php.net/manual/en/language.constants.magic.php

WalterWoshid avatar Nov 07 '23 09:11 WalterWoshid

This seems to be a bigger problem than I thought. This is, like I thought, a problem with magic constants. When a class is matched by AOP, it will be proxied and woven. The proxy is a 1:1 copy of the original class which extends and includes the woven class. The woven class is the class that does the whole AOP logic. Inside the proxied class I can replace all magic constants, which works. I will commit this change shortly.

But here is where it gets complicated, lets imagine a matched class has a trait or extends another class. If that class also includes magic constants like __class__ or even self::class, they also have to be resolved, but won't be, because they itself aren't matched, only the class that uses them.

Possible solutions:

Solution 1:

  • If a class matches, proxify all their traits, parent classes and interfaces as well without creating a woven class.

Problems:

  • What if a non-matched class is loaded first and has the same trait/parent class/interface as well? Once the ClassLoader loads a class, it cannot be replaced (at least in the ClassLoader itself, maybe there is a spl_ function that can achieve that?)

Solution 2:

  • Just proxify EVERY class

Problems:

  • Unnecessary matching
  • Can lead to more problems
  • Probably slower

WalterWoshid avatar Nov 11 '23 13:11 WalterWoshid

Hi @djschilling,

I have released Okapi/AOP - 1.2.9 which fixes the bug partially. You should have no problems when using __DIR__ anymore, but when your matched class has a trait/interface/parent class which uses __class__ or self::class and is not matched by any aspect, it might have a __AopProxied suffix. Besides that, everything should work fine now, especially for your use-case :)

I'm keeping this issue open for the other bugs.

WalterWoshid avatar Nov 11 '23 16:11 WalterWoshid

I updated to 1.2.9 but this is still not working:

    public function getGroupsWhereUserCan($permission, ?array $groupIds = null): array {
        include_once dirname(__DIR__, 3) . '/churchdb/churchdb_db.php';
        return \getMyGroupIdsWhereIAmAllowed($permission, null, $groupIds);
    }

Here is the error:

include_once(/private/var/folders/nx/1shmdfr54sv9r22ql0c4dh680000gn/T/ct-aop-cache/32117/proxies/churchdb/churchdb_db.php): Failed to open stream: No such file or directory

/private/var/folders/nx/1shmdfr54sv9r22ql0c4dh680000gn/T/ct-aop-cache/32117/proxies/src/Auth/Permissions/PermChecker.php:309
/private/var/folders/nx/1shmdfr54sv9r22ql0c4dh680000gn/T/ct-aop-cache/32117/proxies/src/Auth/Permissions/PermChecker.php:309
/Users/david/projects/churchtools/system/src/Domain/Finance/CostCenter/CostCentersAccountingPeriodPermissionResolver.php:40

PermChecker.php : system/src/Auth/Permissions/PermChecker.php churchdb_db.php: system/churchdb/churchdb_db.php

djschilling avatar Nov 22 '23 09:11 djschilling

Hi @djschilling,

I will try it with your code and see what's going wrong.

WalterWoshid avatar Nov 22 '23 12:11 WalterWoshid

Hi @djschilling,

Sadly I can't reproduce your error.

I tried testing it like this: $this->data = require dirname(__DIR__, 3) . '/AdviceBehavior/Include/Database/data.php'; and it worked without a problem.

The code in the __AopProxied class does look like this: require dirname('C:\Projects\okapi\php-aop\tests\Functional\AdviceBehavior\Include\Target', 3) . '/AdviceBehavior/Include/Database/data.php';

Can you tell me what your proxy file looks like?

WalterWoshid avatar May 11 '24 13:05 WalterWoshid