HtmlController   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 172
Duplicated Lines 87.79 %

Coupling/Cohesion

Components 2
Dependencies 9

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 20
c 2
b 0
f 0
lcom 2
cbo 9
dl 151
loc 172
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A behaviors() 19 19 1
A actionIndex() 18 18 1
A actionView() 13 13 1
B actionCreate() 16 16 6
A actionUpdate() 15 15 3
B actionDelete() 22 24 6
A findModel() 0 8 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
// This class was automatically generated by a giiant build task
3
// You should not change it manually as it will be overwritten on next build
4
5
namespace app\modules\prototype\controllers\base;
6
7
use app\modules\prototype\models\Html;
8
use app\modules\prototype\models\search\Html as HtmlSearch;
9
use dmstr\bootstrap\Tabs;
10
use yii\filters\AccessControl;
11
use yii\helpers\Url;
12
use yii\web\Controller;
13
use yii\web\HttpException;
14
15
/**
16
 * HtmlController implements the CRUD actions for Html model.
17
 */
18 View Code Duplication
class HtmlController extends Controller
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
19
{
20
    /**
21
     * @var boolean whether to enable CSRF validation for the actions in this controller.
22
     * CSRF validation is enabled only when both this property and [[Request::enableCsrfValidation]] are true.
23
     */
24
    public $enableCsrfValidation = false;
25
26
    /**
27
     * @inheritdoc
28
     */
29
    public function behaviors()
30
    {
31
        return [
32
            'access' => [
33
                'class' => AccessControl::className(),
34
                'rules' => [
35
                    [
36
                        'allow' => true,
37
                        'matchCallback' => function ($rule, $action) {
38
                            return \Yii::$app->user->can(
39
                                $this->module->id.'_'.$this->id.'_'.$action->id,
40
                                ['route' => true]
41
                            );
42
                        },
43
                    ]
44
                ]
45
            ]
46
        ];
47
    }
48
49
    /**
50
     * Lists all Html models.
51
     * @return mixed
52
     */
53
    public function actionIndex()
0 ignored issues
show
Coding Style introduced by
actionIndex uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
54
    {
55
        $searchModel = new HtmlSearch;
56
        $dataProvider = $searchModel->search($_GET);
57
58
        Tabs::clearLocalStorage();
59
60
        Url::remember();
61
        \Yii::$app->session['__crudReturnUrl'] = null;
62
63
        return $this->render(
64
            'index',
65
            [
66
                'dataProvider' => $dataProvider,
67
                'searchModel' => $searchModel,
68
            ]
69
        );
70
    }
71
72
    /**
73
     * Displays a single Html model.
74
     *
75
     * @param integer $id
76
     *
77
     * @return mixed
78
     */
79
    public function actionView($id)
80
    {
81
        \Yii::$app->session['__crudReturnUrl'] = Url::previous();
82
        Url::remember();
83
        Tabs::rememberActiveState();
84
85
        return $this->render(
86
            'view',
87
            [
88
                'model' => $this->findModel($id),
89
            ]
90
        );
91
    }
92
93
    /**
94
     * Creates a new Html model.
95
     * If creation is successful, the browser will be redirected to the 'view' page.
96
     * @return mixed
97
     */
98
    public function actionCreate()
0 ignored issues
show
Coding Style introduced by
actionCreate uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
actionCreate uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
99
    {
100
        $model = new Html;
101
102
        try {
103
            if ($model->load($_POST) && $model->save()) {
104
                return $this->redirect(Url::previous());
105
            } elseif (!\Yii::$app->request->isPost) {
106
                $model->load($_GET);
107
            }
108
        } catch (\Exception $e) {
109
            $msg = (isset($e->errorInfo[2])) ? $e->errorInfo[2] : $e->getMessage();
0 ignored issues
show
Bug introduced by
The property errorInfo does not seem to exist in Exception.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
110
            $model->addError('_exception', $msg);
111
        }
112
        return $this->render('create', ['model' => $model]);
113
    }
114
115
    /**
116
     * Updates an existing Html model.
117
     * If update is successful, the browser will be redirected to the 'view' page.
118
     *
119
     * @param integer $id
120
     *
121
     * @return mixed
122
     */
123
    public function actionUpdate($id)
0 ignored issues
show
Coding Style introduced by
actionUpdate uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
124
    {
125
        $model = $this->findModel($id);
126
127
        if ($model->load($_POST) && $model->save()) {
0 ignored issues
show
Bug introduced by
The method load cannot be called on $model (of type array|boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
Bug introduced by
The method save cannot be called on $model (of type array|boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
128
            return $this->redirect(Url::previous());
129
        } else {
130
            return $this->render(
131
                'update',
132
                [
133
                    'model' => $model,
134
                ]
135
            );
136
        }
137
    }
138
139
    /**
140
     * Deletes an existing Html model.
141
     * If deletion is successful, the browser will be redirected to the 'index' page.
142
     *
143
     * @param integer $id
144
     *
145
     * @return mixed
146
     */
147
    public function actionDelete($id)
148
    {
149
        try {
150
            $this->findModel($id)->delete();
0 ignored issues
show
Bug introduced by
The method delete cannot be called on $this->findModel($id) (of type array|boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
151
        } catch (\Exception $e) {
152
            $msg = (isset($e->errorInfo[2])) ? $e->errorInfo[2] : $e->getMessage();
0 ignored issues
show
Bug introduced by
The property errorInfo does not seem to exist in Exception.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
153
            \Yii::$app->getSession()->addFlash('error', $msg);
0 ignored issues
show
Bug introduced by
The method getSession does only exist in yii\web\Application, but not in yii\console\Application.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
154
            return $this->redirect(Url::previous());
155
        }
156
157
        // TODO: improve detection
158
        $isPivot = strstr('$id', ',');
159
        if ($isPivot == true) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $isPivot of type string to the boolean true. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
160
            return $this->redirect(Url::previous());
161
        } elseif (isset(\Yii::$app->session['__crudReturnUrl']) && \Yii::$app->session['__crudReturnUrl'] != '/') {
162
            Url::remember(null);
163
            $url = \Yii::$app->session['__crudReturnUrl'];
164
            \Yii::$app->session['__crudReturnUrl'] = null;
165
166
            return $this->redirect($url);
167
        } else {
168
            return $this->redirect(['index']);
169
        }
170
    }
171
172
    /**
173
     * Finds the Html model based on its primary key value.
174
     * If the model is not found, a 404 HTTP exception will be thrown.
175
     *
176
     * @param integer $id
177
     *
178
     * @return Html the loaded model
179
     * @throws HttpException if the model cannot be found
180
     */
181
    protected function findModel($id)
182
    {
183
        if (($model = Html::findOne($id)) !== null) {
184
            return $model;
185
        } else {
186
            throw new HttpException(404, 'The requested page does not exist.');
187
        }
188
    }
189
}
190