PHP Intellisense in Visual Studio Code - visual-studio-code

I'm using Visual Studio Code to develop in PHP, and I've been having some trouble getting Code to provide the proper intellisense results. For example, this newly created Codeception unit test:
<?php
class MyTest extends \Codeception\Test\Unit
{
/**
* #var \UnitTester
*/
protected $tester;
protected function _before()
{
}
protected function _after()
{
}
// tests
public function testSomeFeature()
{
$this->assertFalse(false);
}
}
When I type $this-> I expect to see assertFalse, assertTrue, and all the other methods provided by \Codeception\Test\Unit. But what I get is basically whatever items exist within the current file and that's it.
What can I do to get all the methods from the Unit class to show up? I already have the PHP IntelliSense extension installed, v2.3.4.

Visual Studio Code core does not include advanced PHP features, just syntax highlighting, simple code completion and code linting provided by the PHP binary as long as you have it installed. In short, the features you can configure with these directives:
// Controls whether the built-in PHP language suggestions are enabled. The support suggests PHP globals and variables.
"php.suggest.basic": true,
// Enable/disable built-in PHP validation.
"php.validate.enable": true,
// Points to the PHP executable.
"php.validate.executablePath": null,
// Whether the linter is run on save or on type.
"php.validate.run": "onSave"
For anything else you need to install a third-party extension.
My personal choice is PHP Intelephense. In particular, it supports docblock annotations, including magic properties:
/**
* #property string $foo
*/
class Bar
{
}
... and inline types:
/** #var \Database $db */
$db->connect();

Related

How to type hint class definition

Consider the following example of 3 javascript files:
/** myclass.js **/
import jQuery from 'jQuery';
class MyClass {
constructor() {
this.property = null;
jQuery('#test').data('myClass', this);
}
testMethod() {
return null;
}
}
export default MyClass;
/** file.js **/
import MyClass from './myclass.js';
new MyClass();
export default null;
/** index.js **/
import './file.js';
import jQuery from 'jQuery';
let myValue = jQuery('#test').data('myClass');
What I would like to achieve, is to get property and method auto suggestion from my IDE on the myValue variable. I know (I mean I presume) that automatically, there is no way for the IDE to know what I stored in the data variable of jQuery, but what kind of type hint should I provide before myValue to tell the IDE, that it should be an instance of MyClass?
If in index.js I also import myclass.js with the definition of the class, I was able to achieve my result, by type hinting before the variable with the following jsdoc comment:
/** #type {MyClass} */
But this line only works if I also imported the definition in the current scope. Is there any way to either:
achieve suggestions automatically, without manually type hinting?
or if that is not possible, type hint, without manually importing the definition beforehand?
I am using Visual Studio Code v1.46.1 and I have the ESLint v2.1.5 extension installed on it.
EDIT: After trying to create a jsconfig.json file in my root folder, with the following options:
{
"exclude": ["node_modules"]
}
and modifying my index.js by adding this jsdoc comment, I am still getting no autosuggestions by VSCode:
/** #type {MyClass} */
I've tried adding the above comment both above, and below the line, where I fetch the data from the jQuery element.
EDIT 2:
Okay, basically, it looks like that my IntelliSense "breaks" when I am trying to export something from a file. Could this be a VSCode issue?

Preserving jsdoc comments and VS Code intellisense with babel

I have a javascript library for communicating with server APIS, written in modern ECMAScript.
It is fully documented with JSDoc comments:
/**
* #class - TODOS API Client class
*/
class todosApi {
/**
* Gets Todos, given the parameters
* #param {number} personId
* #param {number} [year]
* #param {number} [month]
* #param {number} [todoTypeId]
* #returns {Object} - api response object, data will be array of todos
*/
fetchTodos = async (....
}
When using this API in the unit tests in this project, in Visual Studio code, I have excellent intellisense from these comments, and it's a beautiful thing.
However, this library is used by/referenced in a separate react application created with create-react-app. When I run this through babel to transpile into a format that is consumable by my create-react-app app, it ends up like this:
/**
* #class - TODOS API Client class
*/
class todosApi {
_defineProperty(this, "fetchTodos", async (personId, eventYear, eventMonth, todoTypeId) => {
}
And I lose my intellisense for fetchTodos, and actually the class itself because of how it is exported in and index.js file. babel does have the option to include comments by default, however the class gets a little mangled in transpiling and loses some comments.
Is there any way to transpile and still preserve this intellisense for VS Code?
Use tsd-jsdoc to create a types.d.ts file.
In your package.json add a script to run ...
jsdoc -r src -t node_modules/tsd-jsdoc/dist -d lib
And set types to lib/types.d.js.
Include that script as part of prepublishOnly so it runs before every npm publish.

How to register modules for advanced functions

When I select Web/Functions in the menu of typo3 cms 9.5.4 backend, I get this error:
Advanced functions
No modules have been registered. Please contact your system administrator.
I am the system administrator. I can't find anywhere how to register modules. How do I register any modules?
Like Peter wrote, the Extension func was removed from core, is actually not marked as compatible with version 9.5. and should avoided to use further more.
But follow two files will help you to register your own module:
ext/extension/ext_tables.php
// Module wizard
if (TYPO3_MODE === 'BE') {
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction(
'web_func',
\Vendor\Extension\MyModuleFunction::class,
null,
'LLL:EXT:extension/Resources/Private/Language/locallang_module.xlf:mymodulefunction'
);
}
ext/extension/Classes/MyModuleFunction.php
<?php
namespace Vendor\Extension;
class MyModuleFunction
{
/**
* Initialize the object
*
* #param \object $pObj A reference to the parent (calling) object
* #throws \RuntimeException
*/
public function init($pObj)
{
// Required method
}
/**
* Checking for first level external objects
*/
public function checkExtObj()
{
// Required method
}
/**
* Main function creating the content for the module.
*
* #return string HTML content for the module, actually a "section" made through the parent object in $this->pObj
*/
public function main()
{
return '<h1>My module function</h1>';
}
}
As far as I know, EXT:wizard_crpages and EXT:wizard_sortpages are not maintained anymore in TYPO3 9.x.
EXT:func has been moved to the TYPO3 Extension Repository to preserve the possibility to register your own wizards.
UPDATE:
The possibility to create multiple pages and to sort pages is now available via the context menu in the page tree. Just do a left or right click on the icon in front of any page and choose More options ... from the context menu.

Visual Studio Code loops in snippets

Is there a way how to use loops or conditionals when creating snippets in VS Code? I am trying to create a snippet that will generate a template for JSDoc documentation syntax for a function. Example (I am using coffeescript):
myFunction: (param1, param2): ->
# some code
return
And I would like a snippet that generates:
###*
* #param {} param1
* #param {} param2
* #return {}
###
myFunction: (param1, param2): ->
# some code
return
I am able to create a snippet, that will simply generate:
###*
* #return {}
###
using this snippet settings:
"JSDocs Template": {
"prefix": "jsdoc",
"body": [
"###*",
" * #return {}",
"###"
],
"description": "create template for JSDocs"
}
But to achieve want I need, I would have to use a loop to go through the param list and that is where I struggle...
I am not sure is that possible using snippets. You can achieve this by writing your own extension using VS Code API.
But you can use this extension
https://marketplace.visualstudio.com/items?itemName=stevencl.addDocComments
to achieve what you trying to achieve in your example.
Update:
You have to modify this extension script a little bit.
Go to C:\Users\%UserProfile%.vscode\extensions\stevencl.adddoccomments-0.0.8\out\
Add this additional logic in the 'extension.js' file.
Right now it only works for the ts and js file. Just added the coffeescript language type.
And it works!!!
Mark it right ans if you agree.
So after some research I found out that such a behaviour is not possible with snippets only, therefore I have create my own extension CoffeeScript JSDoc. Feel free to use it and extend it if necessary...

Call to private PHPExcel_IOFactory::__construct() from context - TYPO3

Hi have to create an excel export using phpexcel library. So I copy the library in my class then write the following code in my controller
require_once PATH_site . 'typo3conf/ext/extension_name/Classes/Library/PHPExcel/IOFactory.php';
public function excelTest()
{
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$objReader = $objectManager->get('PHPExcel_IOFactory');
}
But it return an error
Fatal error: Call to private PHPExcel_IOFactory::__construct() from
context 'TYPO3\CMS\Core\Utility\GeneralUtility' in
/opt/lampp_repository/lampp-5.6/htdocs/typo3_src-7.6.6/typo3/sysext/core/Classes/Utility/GeneralUtility.php
on line 4533
Don't include the library yourself, TYPO3 has dependency injection for that. All the php files in your Extension directory will be indexed, and all Classes inside will automatically be available, you just have to make sure, that your class cache is fresh, if in doubt by manually deleting the typo3temp/Cache/Code/ClassLoader* file.
If you want to include en external class into your own namespace, you have to hint Extbase as to how to include it, with an ext_autoload.php file, because if multiple extensions load code into the same class namespace they will collide.
It also is good practice not to inject the class itself, but an Abstrct that extends upon it, so you can customize it in an isolated manner that doesn't modify the vendor files.
Heres my approach to it:
Put all files of PHPExcel into yourextension/Classes/Vendor/PHPExcel.
Create a new file yourextension/Classes/Vendor/PHPExcel.php:
<?php
namespace Vendorname\Extensionname\Classes;
/*
* PhpExcel
*/
class PhpExcel implements \TYPO3\CMS\Core\SingletonInterface extends \PHPExcel {
// Differences from the original implementation, e.g. a writer that generates
// a filename and puts the Excel file into typo3temp
}
You should then be able to just inject the class #inject-Annotation in your ActionController:
/**
* PhpExcel
*
* #var \Vendorname\Extensionname\Classes\PhpExcel
* #inject
*/
protected $phpExcel;
Further reading:
https://wiki.typo3.org/Dependency_Injection
https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/Autoloading/Index.html