Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interface constructor if present will break Magento compilation #8607

Closed
redboxmarcins opened this issue Feb 19, 2017 · 10 comments
Closed

Interface constructor if present will break Magento compilation #8607

redboxmarcins opened this issue Feb 19, 2017 · 10 comments
Assignees
Labels
bug report bugfix Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development Release Line: 2.1

Comments

@redboxmarcins
Copy link

redboxmarcins commented Feb 19, 2017

Preconditions

  1. Install latest Magento 2.x (tested on 2.0.x and 2.1.x) - PHP 5.6 or PHP 7.0
  2. Any custom module with interface defined

Steps to reproduce

  1. Create module and define Interface with __construct method
  2. Run php bin/magento setup:di:compile

Expected result

  1. Compilation should complete 100% as PHP allows interface to have constructor - I'm not saying it should have, but it can as language allows it - so compiler should honor that

Actual result

  1. Error: PHP Notice: Trying to get property of non-object in /var/www/html/lib/internal/Magento/Framework/Code/Reader/ArgumentsReader.php on line 30

Problem is here

if (!$class->getFileName() || false == $class->hasMethod(

If class hasn't got '__construct' method it will be skipped, but if method exist

$class->getConstructor() will return NULL
and
$class->getConstructor()->class obviously will generate fatal error

Simplest fix

if (!$class->getFileName() || false == $class->hasMethod(
            '__construct'
        ) || !$inherited && null !== $class->getConstructor() && $class->getConstructor()->class != $class->getName()
        ) {
            return $output;
        }
@maghamed
Copy link
Contributor

maghamed commented Feb 21, 2017

@redboxmarcins make sense,
moreover looks like we can't instantiate Objects without constructor not firing E_NOTICE
class SomeClass {

function funcA($arg1, $arg2) {

}

}

$refl = new ReflectionClass('SomeClass');

var_dump($refl->isInstantiable()); // bool(true)
var_dump($refl->getConstructor()); // NULL

@orlangur
Copy link
Contributor

orlangur commented Feb 21, 2017

Strongly disagree.

Please take a look on some http://stackoverflow.com/a/689488 and http://stackoverflow.com/a/41685659.

Compilation should complete 100% as PHP allows interface to have constructor - I'm not saying it should have, but it can as language allows it - so compiler should honor that

First of all, Magento in general and its compiler in particular should honor and encourage best practices. So, when PHP design flaws we should mitigate problems instead of providing support. It is a good thing to disallow shooting yourself in the foot whenever it is possible.

Obviously, compiler must not display nonsense like PHP Notice: Trying to get property of non-object but some LogicException throwing would be much better than supporting edge cases caused by poor PHP design.

@maghamed
Copy link
Contributor

@orlangur
one more time, it make sense for us because for now instantiation of class without constructor will fire E_NOTICE.
Also Framework components of Magento should follow Defensive programming principles as it could/gonna be used for applications besides Magento.

@orlangur
Copy link
Contributor

@maghamed, I have nothing against defensive programming,

for now instantiation of class without constructor will fire E_NOTICE.

Hope you are not going to add check for

var_dump($refl->isInstantiable()); // bool(true)
var_dump($refl->getConstructor()); // NULL

? Notice in this case looks perfectly valid to me as it allows to fail fast.

Anyway, this issue was already fixed and delivered to develop in #8232 the way I like it (NO interface with constructor allowed).

@maghamed
Copy link
Contributor

@orlangur one more time,

current implementation with the fix you mentioned would not allow you to instantiate such class without E_NOTICE:

class SomeClass {
function funcA($arg1, $arg2) {
}
}

Proposed fix -
null !== $class->getConstructor()
make a lot of sense for us.

In any case contract of getConstructor() could return NULL, so next chain access
$class->getConstructor()->class
is not allowed without making sure that null !== $class->getConstructor()

That's one of the Defensive Programming principle.

@orlangur
Copy link
Contributor

In any case contract of getConstructor() could return NULL, so next chain access
$class->getConstructor()->class

Okok, if this code is still reachable for $class->getConstructor() === null additional check won't hurt.

I was saying that I'm against such check in a place where we actually instantiate such object, like https://github.com/magento/magento2/blob/develop/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php#L91

@vrann
Copy link
Contributor

vrann commented Mar 1, 2017

@maghamed is this PR related? #8232

@orlangur
Copy link
Contributor

orlangur commented Mar 1, 2017

@vrann, yeah,

Anyway, this issue was already fixed and delivered to develop in #8232 the way I like it (NO interface with constructor allowed).

If I understood @maghamed correctly, he wants to add one more check for better defense in scope of this issue.

@vrann vrann added the Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development label Mar 15, 2017
LoganayakiK added a commit to LoganayakiK/magento2 that referenced this issue May 5, 2017
…pilation

 - $class->isInterface() method of an php reflection class will implement the getConstructor() function not to pull any dependencies from the interface constructor. 
So we must have to add this condition  in order to call getConstructor(). This solves the issue
@okorshenko
Copy link
Contributor

Pull Request #9524 has been merged to 2.1-develop branch. Thank you @LoganayakiK for your contribution!

@magento-team magento-team added Release Line: 2.1 2.1.x Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development bug report bugfix labels Jul 31, 2017
@magento-team
Copy link
Contributor

Internal ticket to track issue progress: MAGETWO-69019

magento-devops-reposync-svc pushed a commit that referenced this issue Dec 12, 2023
[ACQE-5692, ACQE-5700] MFTF update to ^4.6 & Test Stabilization
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report bugfix Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development Release Line: 2.1
Projects
None yet
Development

No branches or pull requests

9 participants