Xenforo ClassProxy System breaks autocompletion on IDE

Earl

Well-known member
@Kier & @Jeremy Said
Kier said:
But for a dynamic system where there might be dozens of classes attempting to extend the like model, this is unworkable.

Instead, we must make use of the XenForo Class Proxy system, which allows the system to effectively have multiple inheritance capabilities. To use it, we must declare the class as ClassName, and have it extend XFCP_ClassName, like this:
PHP:
<?php
class newProfileTabs_Extend_ControllerPublic_Member extends XFCP_newProfileTabs_Extend_ControllerPublic_Member
{
}
?>
but it breaks auto completion on IDE (in my case PhpStorm)
can't use code completion to this

PHP:
class newProfileTabs_Extend_ControllerPublic_Member extends XFCP_newProfileTabs_Extend_ControllerPublic_Member{

    public function actionUsersLike(){
        $userId = $this->_input->filterSingle('user_id', XenForo_Input::UINT);

        $user = $this ->getHelper('UserProfile')->assartUserProfileValidAndViewable($userId);

        $users = $this->getHelper('UserProfile')->assertUserProfileValidAndViewable($userId);
}
}


is there anyone know how to fix this?
may be using PhpDoc comments or something?
 
Last edited:
Hi,

You can deal with this (I also use phpStorm) like that:

PHP:
class newProfileTabs_Extend_ControllerPublic_Member extends XFCP_newProfileTabs_Extend_ControllerPublic_Member{
    /** @return XenForo_ControllerHelper_UserProfile */
    protected function _getUserProfileHelper() {
        return $this->getHelper('UserProfile');
    }

    public function actionUsersLike() {
         (...)
        $userProfileHelper = $this->_getUserProfileHelper();
         (...)
    }
}

Or:

PHP:
class newProfileTabs_Extend_ControllerPublic_Member extends XFCP_newProfileTabs_Extend_ControllerPublic_Member{
    public function actionUsersLike() {
         (...)
        /** @var XenForo_ControllerHelper_UserProfile $userProfileHelper */
        $userProfileHelper = $this->getHelper('UserProfile');
         (...)
    }
}
 
Another (really bad) way to explain to PHPStorm which class XFCP_newProfileTabs_Extend_ControllerPublic_Member extend is to have this code in the top of the file:

PHP:
if (! class_exists('XFCP_newProfileTabs_Extend_ControllerPublic_Member')) {
class XFCP_newProfileTabs_Extend_ControllerPublic_Member extends XenForo_ControllerPublic_Member {}
}

As XFCP_newProfileTabs_Extend_ControllerPublic_Member is already defined when the file is included, this code will never run.
But it allows phpStorm to have full auto-completion as if you extend directly XenForo_ControllerPublic_Member in your class.
 
In PHPStorm I've got a full auto complete in all proxy classes and in all class fabrics.
I have to add separate file for each add-on for auto completion in proxy classes:
PHP:
<?php
/* for IDE autocomplete */
class XFCP_CMF_Event_Model_Extend_Attachment extends XenForo_Model_Attachment {}
class XFCP_CMF_Event_ControllerPublic_Extend_Forum extends XenForo_ControllerPublic_Forum {}
Also, I've installed DynamicReturnTypePlugin (Intellij/Phpstorm PHP plugin to allow a dynamic return type from method/function calls. It can use either the instance type of the passed parameter or a string lookup), for autocomplete from getHelper/getModelFromCache/etc methods.
 
@Insy
I have one more question:

In my case I am extending a non existing class
(extends XFCP_newProfileTabs_Extend_ControllerPublic_Member which is not exist),

so how can I get auto complete to $this-> (No auto completes from it's Parent Class :( )
 
Last edited:
I suggest to use a separate fake file per add-on (it can be outside xenforo directory) only for autocomplete in proxy classes.
And DynamicReturnTypePlugin is needed only for less PHPDoc comments.

Directory structure in my projects (additional addon is needed for separate directory and git-repo per add-on):
2015-03-29_21-50-51.webp
 
@Earl , so if you want autocomplete original XenForo methods in your proxy class:
PHP:
<?php
class newProfileTabs_Extend_ControllerPublic_Member extends XFCP_newProfileTabs_Extend_ControllerPublic_Member {}
you must create file:
PHP:
<?php
XFCP_newProfileTabs_Extend_ControllerPublic_Member extends XenForo_ControllerPublic_Member {}
But if you want to autocomplete $this->getHelper('UserProfile') calls than you have to use PHPDoc comments or install and configure DynamicReturnTypePlugin.
 
If you want to get autocompletion from the parent class without using what I suggest you (@var or @return) in my first reply, yes.
hey @Insy
I don't understand friend, I can see your @var or @return way can only get auto completion to $userProfileHelper object after it assigned which is currently not impotent for my situation but it was very usefull and thank you very much for telling me about it and i really appreciate it.

But now,
What I want to do is get auto complete for "$this" ->
(when "assigning XenForo_ControllerHelper_UserProfile object to $userProfileHelper" situation, you used "$this")

I'm asking how to get autocomplete following "$this->" keyword?

because newProfileTabs_Extend_ControllerPublic_Member class is extending XenForo_ControllerPublic_Member class via a code event listener.
so the XenForo_ControllerPublic_Member class is the parent class of newProfileTabs_Extend_ControllerPublic_Member , and I am asking is it possible to get auto completion of parents methods / properties (XenForo_ControllerPublic_Member) to "$this->" using phpDocs or something?

simply:
is it possible to get auto completion from parent class to my sub class following "$this->" when the situation of XFCP?
 
Last edited:
@Earl , so if you want autocomplete original XenForo methods in your proxy class:
PHP:
<?php
class newProfileTabs_Extend_ControllerPublic_Member extends XFCP_newProfileTabs_Extend_ControllerPublic_Member {}
you must create file:
PHP:
<?php
XFCP_newProfileTabs_Extend_ControllerPublic_Member extends XenForo_ControllerPublic_Member {}
But if you want to autocomplete $this->getHelper('UserProfile') calls than you have to use PHPDoc comments or install and configure DynamicReturnTypePlugin.
That's exactly what I've been looking for.
so without creating a fake file, or adding a line like this
if (! class_exists('XFCP_newProfileTabs_Extend_ControllerPublic_Member')) {
class XFCP_newProfileTabs_Extend_ControllerPublic_Member extends XenForo_ControllerPublic_Member {}
}
as explained @Insy in his 2nd post of this thread, its impossible to get auto completion to $this-> calls like I asked in my previous post using PhpDoc comments ?
 
Last edited:
ok I found the solution :D
by adding this line solved the problem :D
/** @var XenForo_ControllerPublic_Member $this */

PHP:
class newProfileTabs_Extend_ControllerPublic_Member extends XFCP_newProfileTabs_Extend_ControllerPublic_Member{
public function actionUsersLike() {

/** @var XenForo_ControllerPublic_Member $this */
$userProfileHelper = $this->
}
}


Many thanks to both of you @Yoskaldyr @Insy
 
Top Bottom