PMD Class definition inside method - warnings

I use a local class inside a method and PMD triggers 2 warnings headerCommentRequirement for the class and publicMethodCommentRequirement for a method inside a class, I write the comments on both as if it was a normal class but it doesn't work. Any ideas on this? Thanks for you help.
The code looks like this:
/**
*
* #author me
*
*/
class myClass{
void thisMethod(){
if(condition){
/**
*
* #author me
* This is the local class
*/
class localClass implements otherClass{
/**
* Method comment
*/
public boolean boolMethod(){
//Do Something
}
}
}
}
}

Correct javadoc should have second and following lines indented by addtional space, and the description should be before any tags:
/**
* Description.
* #author me
*/

I solved it using //NOPMD (which ignores the PMD warning) on the local class line, as it wasn't my class and PMD didn't recognize the comment. It is the only solution I got.
class LocalClass implements OtherClass{ //NOPMD
}

Related

Symfony, How to use DenyAccess with Doctrine object?

I want to control the same user access on some methods in my controller.
Currently, I use this :
$this->denyAccessUnlessGranted('ACCESS', $this->Player($toolRepository));
However I am forced to use this line and inject the ToolRepository into each method ...
What would be the easiest way to do it?
I saw that there was the IsGranted annotation but my subject needs to be a doctrine object to control access with my Vote.
/**
* #Route("/player")
*/
class PlayerController extends AbstractController
{
/**
* #Route("/", name="player")
* #throws Exception
*/
public function Player(ToolRepository $toolRepository): \App\Entity\Tool
{
$playerTool = 'TestTool2';
$tool = $toolRepository->findOneBy(array('libelle' => $playerTool));
if (!$tool) {
throw new Exception('Tool : ' . $playerTool . 'not found!');
}
return $tool;
}
/**
* #Route("/main", name="player")
* #IsGranted ("ACCESS", subject="tool")
* #throws Exception
*/
public function mainPlayer(PlayerRepository $playerRepository, ToolRepository $toolRepository): Response
{
$this->denyAccessUnlessGranted('ACCESS', $this->Player($toolRepository));
$players = $playerRepository->findAll();
return $this->render('player/player_mainpage.html.twig', ['players'=>$players]);
}
}
I think this ressource should answer you: Symfony voters.
You'll put your security logic in your custom voter which will be called in every function of your controller (or every methods where you want to control access) isGranted() function.
Calling your Player() function is a easier way to do this for beginner, you can keep like that but you shouldn't put it in Controller and use a Service instead .
Edit:
You may store your ToolRepository as Controller private property and inject it in a __construct() method so you don't have to inject ToolRepository in each method

How to override system.mail.yml in Drupal 8?

I have the below code in my file: core\modules\system\config\install\system.mail.yml
interface:
default: 'php_mail'
I want to change the code to:
interface:
default: 'SMTPMailSystem'
In order to get my SMTP module to work. On changing the code in the core file my module works. Since making direct changes in core file is not good I want to know how do we override such files. I am fairly new to Drupal 8 hence couldn't get through.
Drupal has an article on Configuration override system, which gives an overview and starter code to override configurations defined in *.yml . You can jump to "Providing overrides from modules" section right away for your case.
In short:
Create a module (config_example used as an example)
Create a config_example.services.yml, and put:
services:
config_example.overrider:
class: \Drupal\config_example\ConfigExampleOverrides
tags:
- {name: config.factory.override, priority: 5}
config.factory.override is the important thing here, others are up to you to change.
Define the class which implements ConfigFactoryOverrideInterface:
namespace Drupal\config_example;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;
/**
* Example configuration override.
*/
class ConfigExampleOverrides implements ConfigFactoryOverrideInterface {
/**
* {#inheritdoc}
*/
public function loadOverrides($names) {
$overrides = array();
if (in_array('system.mail', $names)) { // (a)
$overrides['system.mail'] = [
'interface' => ['default' => 'SMTPMailSystem']
];
}
return $overrides;
}
/**
* {#inheritdoc}
*/
public function getCacheSuffix() {
return 'ConfigExampleOverrider'; // (c)
}
/**
* {#inheritdoc}
*/
public function getCacheableMetadata($name) {
return new CacheableMetadata();
}
/**
* {#inheritdoc}
*/
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
return NULL;
}
}
The following thing is changed to work for your case:
(a) The in_array needle is changed to system.mail which is the YML you wish to override. The value assigned to $overrides['system.mail'] is changed to what you wish to be placed.

Yii2 phpdoc for Yii::$app->passport

My IDE PHPStorm marks next line as mistake (word "password")
Yii::$app->passport->getLoginUrl($Url);
How can i write phpdoc for it.
May be in suchway or how?
/** #var $Yii::$app->passport array */
Yii::$app->passport->getLoginUrl($Url);
You can find the solution for this in Yii 2.0 Cookbook - IDE autocompletion for custom components
Using custom Yii class
The best way to give IDE some hints is to use your own Yii file which
isn't actually used when running code. This file could be named
Yii.php and the content could be the following:
<?php
/**
* Yii bootstrap file.
* Used for enhanced IDE code autocompletion.
*/
class Yii extends \yii\BaseYii
{
/**
* #var BaseApplication|WebApplication|ConsoleApplication the application instance
*/
public static $app;
}
/**
* Class BaseApplication
* Used for properties that are identical for both WebApplication and ConsoleApplication
*
* #property \app\components\RbacManager $authManager The auth manager for this application. Null is returned if auth manager is not configured. This property is read-only. Extended component.
* #property \app\components\Mailer $mailer The mailer component. This property is read-only. Extended component.
*/
abstract class BaseApplication extends yii\base\Application
{
}
/**
* Class WebApplication
* Include only Web application related components here
*
* #property \app\components\User $user The user component. This property is read-only. Extended component.
* #property \app\components\MyResponse $response The response component. This property is read-only. Extended component.
* #property \app\components\ErrorHandler $errorHandler The error handler application component. This property is read-only. Extended component.
*/
class WebApplication extends yii\web\Application
{
}
/**
* Class ConsoleApplication
* Include only Console application related components here
*
* #property \app\components\ConsoleUser $user The user component. This property is read-only. Extended component.
*/
class ConsoleApplication extends yii\console\Application
{
}
In the above PHPDoc of BaseApplication, WebApplication,
ConsoleApplication will be used by IDE to autocomplete your custom
components described via #property.
Note: To avoid "Multiple Implementations" PHPStorm warning and make
autocomplete faster exclude or "Mark as Plain Text"
vendor/yiisoft/yii2/Yii.php file.
That's it. Now Yii::$app->user will be our \app\components\User
component instead of default one. The same applies for all other
#property-declared components.

Typehint inherited class variables in PHPStorm

In PHPStorm, I can type-hint a variable this way:
/** #var Point $point */
$point->x();
However, say I inherited a variable from a parent class, and want to type-hint it:
class PointProxy extends Proxy
{
public function x()
{
...
/** #var Point $this->geometry */
return $this->geometry->x();
}
}
This doesn't work, PHPStorm acts as if I had type-hinted $this, and not $this->geometry.
Is there a way to make such a type-hint work without redeclaring the $geometry property in the subclass, or is this unsupported?
Try this code. Also you can press alt+enter at undefined properties and select Add #property it will help you to create phpdoc faster.
/**
* #property Point $geometry
*/
class PointProxy extends Proxy {
public function x() {
return $this->geometry->
}
}
If the parent object types the property as Geometry but you want it typed as a Point (which descends from Geometry) in your child class, I would recommend creating an accessor in your child class. Possibly with some type checking.
class PointProxy extends Proxy
{
/**
* Access the geometry object on parent class as a Point
*
* #return Point
*/
private point()
{
if(!is_a($this->geometry, 'Point'))
{
// Log an error or something, this is not a state we should be in
}
else
{
return $this->geometry;
}
}
public function x()
{
...
return $this->point->x();
}
}
I ran into a very similar problem. I had a generic storage class that dealt with database operations and then a proxy class on top which proxied all storage class methods through a try catch (using __call()) so that I could handle exceptions in one location.
Now whenever I accessed the storage instance like $storage->retrievePhoto($id), the PHPStorm IDE could not typehint for me. My solution involved adding another class name annotation to the $storage object.
For example, see below. Since the specific proxy class is really just a wrapper over the original storage class, it doesn't present any problems although it is still not 100% to my liking but it works.
final class PhotoRepository
{
/**
* #var \Repositories\Photos\PhotoStorage
* \Repositories\Photos\PhotoStorageExceptionHandlerProxy
*/
private $storage;
/**
* #param \Repositories\Photos\PhotosStorageExceptionHandlerProxy $storage
*/
public function __construct(PhotosStorageExceptionHandlerProxy $storage)
{
$this->storage = $storage;
}

PhpStorm cannot autocomplete model attributes

simply I want PhpStorm autocomplete my model's attributes when I use find(), findAll(), findByAttributes() etc...
I have a model like:
/**
* member model parameters:
* #property integer $id
* #property integer $city_id
* #property string $e_mail
*/
class Member extends CActiveRecord
{
/**
* #static
* #param string $className
* #return Member
*/
public static function model($className = __CLASS__)
{
return parent::model($className);
}
...
When I use active record methods like:
$member = Member::model()->findByAttributes(array('e_mail'=>'Foo Bar'));
and try to autocomplete when I wrote this:
$member->
It only gives me CActiveRecord's parameters and methods in the list.
I tried to change
/**
* Finds a single active record that has the specified attribute values.
* See {#link find()} for detailed explanation about $condition and $params.
* #param array $attributes list of attribute values (indexed by attribute names) that the active records should match.
* An attribute value can be an array which will be used to generate an IN condition.
* #param mixed $condition query condition or criteria.
* #param array $params parameters to be bound to an SQL statement.
* #return CActiveRecord the record found. Null if none is found.
*/
public function findByAttributes($attributes,$condition='',$params=array())
{...
this method's return param from CActiveRecord to Member, self, parent, $this, child etc...
Autocomplete only worked when it was "Member". But this method is used for all models not just the Member model so this is not a solution.
If anyone knows the solution (preferably without changing the framework core methods) I will be glad.
NOTE: All of my awesome Yii code is freely available on bitbucket in the repositories here and here. If you hate Yii's verbosity, check out my Pii class. I think you'll totally dig it.
I've run into this and what I do is augment the phpdoc for the static model() method. This corrects the issue and the autocomplete works fine.
For instance:
class MyModel extends CActiveRecord {
/**
* #static
* #param string $className
* #return MyModel|CActiveRecord
*/
public static function model($className=__CLASS__) {
.... yada yada yada ...
}
}
Note the pipe and additional class added to the "#return". This tells PhpStorm to also include that class in the auto-complete lookups.
One additional note, if you're using namespaces, you may need a slash in front of some class names. Just depends on your project and includes.
=============== UPDATE: 2013-08-05 ===============
With PhpStorm v6 and up, it looks like you can use:
*
* #return $this
*
And also get proper auto-completion.
On a side note, the whole static "model()" method thing is antiquated (like Yii) and I have a base model class that I use now for all projects. It contains the static model method; which is then no longer required in each of my subclasses. Here's an example...
<?php
namespace My\Awesome\Name\Space;
/**
* MyBaseModel
* etc.etc.
*/
class MyBaseModel extends \CActiveRecord
{
/**
* Returns the static model of the specified AR class.
*
* #param string $className
*
* #return $this
*/
public static function model( $className = null )
{
return parent::model( $className ? : \get_called_class() );
}
//code code code code
}
/**
* MySubModel
*/
class MySubModel extends MyBaseModel
{
/**
* {#InheritDoc}
*/
public function tableName()
{
return 'my_sub_table';
}
}
$_models = MySubModel::model()->findAll( 'xyz = :xyz', array( ':xyz' => 'abc' ) );
if ( !empty( $_models ) )
{
foreach ( $_models as $_model )
{
// Do awesome stuff...
}
}
Autocomplete works fine for all the subclasses...
Just thought I'd update this and let y'all know.
You can use phpdoc #method. You can use this approach for frequently-used models or you can create new template for code generator.
/**
* #method Member findByPk($pk,$condition='',$params=array())
*/
class Member extends CActiveRecord
{