Custom PHP Interpreter from Plugin

Hello,

I am currently working on a DDEV integration Plugin. The goal of this plugin is to make the use of DDEV in your project as simple as possible and to automate as much of the configuration as possible. DDEV is a tool to spawn a development environment based on docker-compose. Configuring the docker-compose interpreter does work, but you need to:

  • Choose the right docker-compose file (there are multiple)
  • Select the right service (there are multiple)
  • Set an environment variable
  • Check the option to connect to an existing container
  • Choose the right php bianry (there are multiple)

In the context of my plugin I do already have all these information. So I would like to implement some sort of "Auto configuration" by selecting a custom interpreter named "DDEV", that serves those information right from the DDEV configuration and is always up to date in that way, or at least to fill in those information to the docker-compose interpreter at their current state.

I tried implementing a custom remote credential contribution using the extension points remote.credentialsLanguageContribution and remote.credentialsType but this is not as straight forward as I hoped to and it also looks like I can not change the lifecycle settings from there (use existing container).

I also found the extension points com.jetbrains.php.remote.interpreter.ui.customConfigProvider and com.jetbrains.php.remote.remoteInterpreterManager but I did not manage to implement anything working there as those extension points expect only a single instance using this extension point. Also I am not sure if they are on the right place for what I am looking for.

Could you please give some advice if auto configuring a php interpreter from a plugin is possible and some hint how?

Thanks in advance!

2
6 comments
Official comment

Hello, Nico!

Please find below a code snippet related to PhpInterpreter creating based on docker-compose. I hope it will help you to resolve your question on how to specify the required settings for your interpreter

PhpInterpreter phpInterpreter = new PhpInterpreter();
final PhpRemoteSdkAdditionalData sdkData = new PhpRemoteSdkAdditionalData("php");
sdkData.setInterpreterId("interpreter-id");
final DockerComposeCredentialsHolder credentials = DockerComposeCredentialsType.getInstance().createCredentials();
credentials.setAccountName("Docker");
credentials.setComposeFilePaths(Arrays.asList("docker-compose.yml"));
credentials.setComposeServiceName("test-service");
credentials.setRemoteProjectPath(DockerCredentialsEditor.DEFAULT_DOCKER_PROJECT_PATH);

final PhpRemoteSdkTypeData typeData = sdkData.getTypeData();
if (typeData instanceof PhpDockerComposeTypeData) {
((PhpDockerComposeTypeData)typeData).setCommand(PhpDockerComposeStartCommand.EXEC);
}

sdkData.setCredentials(DockerComposeCredentialsType.getInstance().getCredentialsKey(), credentials);

final PathMappingSettings mappings = PhpRemoteInterpreterManager.getInstance().createPathMappings(myProject, sdkData);
sdkData.setPathMappings(mappings);

phpInterpreter.setPhpSdkAdditionalData(sdkData);

Hello,

Sorry for the delayed response, just need some time to get help from the team. In the meantime, I have discussed this thread with our developers and, it seems to be that `com.jetbrains.php.config.interpreters.PhpInterpreter` and `com.jetbrains.php.remote.interpreter.ui.PhpProjectConfigComponentProvider` could cover your concern. 

Also, as a nice starting point, please check this small plugin from one of our devs, it should point you in the proper direction:
https://github.com/artspb/idea-php-latest-plugin/blob/master/src/main/kotlin/me/artspb/idea/php/latest/plugin/PhpLocalInterpreterUpdater.kt

This plugin just downloads the most recent PHP version and creates a PHP CLI Interpreter configuration in IDE (something that you are looking for, right?)

0

Thank you very much for your feedback Vasiliy!

Your answer was helpful but sadly I'm still a bit lost how to acomplish the remote interpreter configuration.

Setting a local php interpreter as shown in the example works quite well, but as I need to execute php in a docker container this seems to be a bit more complicated. I already tried to "simulate" an interpreter created by the remote-interpreter plugin, but this doesn't feel like the right way.

PhpInterpreter interpreter = new PhpInterpreter();
interpreter.setName("DDEV");
interpreter.setIsProjectLevel(true);
interpreter.setPhpSdkAdditionalData(new PhpRemoteSdkAdditionalData("/usr/bin/php8.1"));
interpreter.setHomePath("docker-compose://[" + project.getBasePath() + "/.ddev/.ddev-docker-compose-full.yaml]:web/php");
// Ensure running container is used
// Set Environment Variable for execution in container

this.addInterpreterConditionally(interpreter, project);

Could you please give some advice how I could achieve what the code snippet above illustrates, the right way?

I can't even find the Environment and Lifecycle Settings in the interpreter configuration, nor in the PhpRemoteSdkAdditionalData, where I expected them.

Thanks in advance!

PS: The shown error is annoying but has nothing to do with my current issue, just wanted to clearify which Settings I mean.

0

Thank you Olga Strizhenko your code example helped a lot!
I've got a working Interpreter now, but I still have two issues:

sdkData.getTypeData()

is null, causing the next if to be false, so the command is not set to exec mode. Could you maybe help me with this?

Opening the Interpreter settings, the php Version is marked as "Not installed". Clicking on update causes the following error:

[Fatal Error] :1:1: Content is not allowed in prolog.
2022-02-23 20:15:26,676 [ 409482]   WARN - php.config.phpInfo.PhpInfoUtil - Failed to parse validation output: Xdebug: [Config] The setting 'xdebug.remote_enable' has been renamed, see the upgrading guide at https://xdebug.org/docs/upgrade_guide#changed-xdebug.remote_enable (See: https://xdebug.org/docs/errors#CFG-C-CHANGED)
Could not open input file: null/phpinfo.php
 
2022-02-23 20:15:26,676 [ 409482]   WARN - .PhpRemoteInterpreterComponent - Can not update phpinfo 
com.intellij.execution.ExecutionException: Failed to parse validation script output
    at com.jetbrains.php.config.phpInfo.PhpInfoUtil.parsePhpInfo(PhpInfoUtil.java:62)
    at com.jetbrains.php.config.phpInfo.PhpInfoUtil.getWholePhpInfo(PhpInfoUtil.java:162)
    at com.jetbrains.php.remote.interpreter.ui.PhpRemoteInterpreterComponent.reloadPhpInfo(PhpRemoteInterpreterComponent.java:117)
    at com.jetbrains.php.config.interpreters.PhpInterpreterComponent.lambda$init$0(PhpInterpreterComponent.java:162)
    at com.jetbrains.php.ui.PhpUiUtil$2.lambda$actionPerformed$0(PhpUiUtil.java:117)
    at com.intellij.util.ui.EdtInvocationManager.invokeLaterIfNeeded(EdtInvocationManager.java:101)
    at com.intellij.util.ui.UIUtil.invokeLaterIfNeeded(UIUtil.java:2180)

This seems to be an issue with the interpreter as a manual created interpreter with the same settings is detecting php and its version corretcly.


If you could assist fixing those two last issues would be great.

Thanks!

0

Olga Strizhenko could you please give me some hint why 

final PhpRemoteSdkTypeData typeData = sdkData.getTypeData();

evaluates to null? Your code example looks like it should return an instance of PhpDockerComposeTypeData.

 

The error when checking the PHP version looks like a missing path (null/phpinfo.php). 

Could not open input file: null/phpinfo.php

What is the right path to look for / generate this phpinfo.php and how do I tell the interpreter?
Since most of the code is closed source, it is quite hard for me to find out how to fix this.

Any help is appreciated.

0

I finally found the solution. In case someone else struggles about this, here are the adaptions to the official answer to make it work:

To apply the "use existing container" setting, replace

final PhpRemoteSdkTypeData typeData = sdkData.getTypeData();
if (typeData instanceof PhpDockerComposeTypeData) {
((PhpDockerComposeTypeData)typeData).setCommand(PhpDockerComposeStartCommand.EXEC);
}

by 

sdkData.setTypeData(new PhpDockerComposeTypeData(PhpDockerComposeStartCommand.EXEC));

To fix the path error that avoids loading the phpversion you need to add

sdkData.setHelpersPath("/opt/.phpstorm_helpers");

Finally you have to call 

PhpInfo phpInfo = PhpInfoUtil.getPhpInfo(project, phpInterpreter, null);
PhpInterpretersPhpInfoCacheImpl.PhpProjectInterpretersPhpInfoCache.getInstance(project).setPhpInfo(phpInterpreter.getName(), phpInfo);

to make the PHP Interpreter ready for work. Please note this will cause a popup with a progress bar, so you might not want to trigger it automatically, as it might distract the user.

This seems to work well so far.

0

Please sign in to leave a comment.