Completed
Pull Request — master (#171)
by Corey
02:59
created

ProfileController::actionIndex()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 26
c 0
b 0
f 0
rs 9.3222
cc 5
nc 4
nop 0
1
<?php
2
namespace site\controllers;
3
4
5
use Yii;
6
use common\models\Question;
7
use common\components\Controller;
8
use yii\filters\VerbFilter;
9
use common\components\AccessControl;
10
use League\Csv\Writer;
0 ignored issues
show
Bug introduced by
The type League\Csv\Writer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use yii\web\BadRequestHttpException;
12
13
/**
14
 * Profile controller
15
 */
16
class ProfileController extends Controller {
17
  /**
18
   * @inheritdoc
19
   */
20
  public function behaviors() {
21
    return [
22
      'access' => [
23
        'class' => AccessControl::class,
24
        'rules' => [
25
          [
26
            'actions' => ['index', 'error', 'delete-account', 'change-password', 'request-change-email', 'export'],
27
            'allow'   => true,
28
            'roles'   => ['@'],
29
          ], [
30
            'actions' => [ 'change-email', ],
31
            'allow'   => true,
32
          ],
33
        ],
34
      ],
35
      'verbs' => [
36
        'class' => VerbFilter::class,
37
        'actions' => [
38
          'deleteAccount' => ['post'],
39
          'changePassword' => ['post'],
40
        ],
41
      ],
42
    ];
43
  }
44
45
  public function actionIndex() {
46
    $editProfileForm    = Yii::$container->get(\site\models\EditProfileForm::class, [Yii::$app->user->identity]);
47
    $changePasswordForm = Yii::$container->get(\site\models\ChangePasswordForm::class, [Yii::$app->user->identity]);
48
    $changeEmailForm    = Yii::$container->get(\site\models\ChangeEmailForm::class, [Yii::$app->user->identity]);
49
    $deleteAccountForm  = Yii::$container->get(\site\models\DeleteAccountForm::class, [Yii::$app->user->identity]);
50
    $graph              = Yii::$container->get(\common\components\Graph::class, [Yii::$app->user->identity]);
51
52
    if (Yii::$app->request->isAjax && $editProfileForm->load($_POST)) {
53
      Yii::$app->response->format = 'json';
54
      return \yii\widgets\ActiveForm::validate($editProfileForm);
55
    }
56
    $editProfileForm->loadUser();
57
58
    if ($editProfileForm->load(Yii::$app->request->post())) {
59
      $saved_user = $editProfileForm->saveProfile();
60
      if($saved_user) {
61
        Yii::$app->session->setFlash('success', 'New profile data saved!');
0 ignored issues
show
Bug introduced by
The method setFlash() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

61
        Yii::$app->session->/** @scrutinizer ignore-call */ 
62
                            setFlash('success', 'New profile data saved!');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
62
      }
63
    }
64
65
    return $this->render('index', [
66
      'profile'         => $editProfileForm,
67
      'change_password' => $changePasswordForm,
68
      'change_email'    => $changeEmailForm,
69
      'delete'          => $deleteAccountForm,
70
      'graph_url'       => $graph->getUrl(Yii::$app->user->identity->getIdHash()),
0 ignored issues
show
Bug introduced by
The method getIdHash() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
      'graph_url'       => $graph->getUrl(Yii::$app->user->identity->/** @scrutinizer ignore-call */ getIdHash()),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getIdHash() does not exist on yii\web\IdentityInterface. Did you maybe mean getId()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
      'graph_url'       => $graph->getUrl(Yii::$app->user->identity->/** @scrutinizer ignore-call */ getIdHash()),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
71
    ]);
72
  }
73
74
  public function actionDeleteAccount() {
75
    $model = Yii::$container->get(\site\models\DeleteAccountForm::class, [Yii::$app->user->identity]);
76
77
    if ($model->load(Yii::$app->request->post()) && $model->validate()) {
78
      if($model->deleteAccount()) {
79
        $this->redirect(['site/index']);
80
      } else {
81
        Yii::$app->session->setFlash('error', 'Wrong password!');
82
      }
83
    }
84
85
    $this->redirect(Yii::$app->request->getReferrer());
86
  }
87
88
  public function actionChangePassword() {
89
    $model = Yii::$container->get(\site\models\ChangePasswordForm::class, [Yii::$app->user->identity]);
90
91
    if ($model->load(Yii::$app->request->post())) {
92
      if($model->validate() && $model->changePassword()) {
93
        Yii::$app->session->setFlash('success', 'Password successfully changed');
94
      } else {
95
        Yii::$app->session->setFlash('error', 'Wrong password!');
96
      }
97
    }
98
99
    $this->redirect(['profile/index']);
100
  }
101
102
  public function actionRequestChangeEmail() {
103
    $model = Yii::$container->get(\site\models\ChangeEmailForm::class, [Yii::$app->user->identity]);
104
105
    if ($model->load(Yii::$app->request->post()) && $model->validate()) {
106
      $model->changeEmail();
107
      Yii::$app->session->setFlash('success', "We've sent an email to your requested email address to confirm. Please click on the verification link to continue.");
108
    }
109
110
    $this->redirect(['profile/index']);
111
  }
112
113
  public function actionChangeEmail(string $token) {
114
    $user = Yii::$container->get(\common\interfaces\UserInterface::class)->findByChangeEmailToken($token);
115
116
    if($user) {
117
      $validator = new \yii\validators\EmailValidator();
118
      if($validator->validate($user->desired_email, $error)) {
119
        $user->removeChangeEmailToken();
120
        $user->email = $user->desired_email;
121
        $user->desired_email = null;
122
        $user->save();
123
        if(!Yii::$app->user->isGuest) {
124
          Yii::$app->user->logout();
0 ignored issues
show
Bug introduced by
The method logout() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

124
          Yii::$app->user->/** @scrutinizer ignore-call */ 
125
                           logout();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
125
          Yii::$app->session->setFlash('success', 'Your email address was successfully changed. For security, we\'ve logged you out.');
126
        } else {
127
          Yii::$app->session->setFlash('success', 'Your email address was successfully changed.');
128
        }
129
        return $this->goHome();
130
      } else {
131
        // desired_email failed validation. Something sneaky might be happening here
132
        Yii::warning("ProfileController::actionChangeEmail() User({$user->id}) desired_email failed validation. Something weird is going on.");
133
        return $this->goHome();
134
      }
135
    } else {
136
      // no user was found with that token
137
      throw new BadRequestHttpException("Wrong or expired change email token. If you aren't sure why this error occurs perhaps you've already confirmed your new email address. Please try logging in with it.");
138
    }
139
  }
140
141
  public function actionExport() {
142
    header("Content-Type: text/csv");
143
    header("Content-Disposition: attachment; filename=fsa-data-export-".Yii::$app->user->identity->email."-".date('Ymd').".csv");
0 ignored issues
show
Bug introduced by
Accessing email on the interface yii\web\IdentityInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
144
145
    $reader = Yii::$app->user->identity->getExportData();
0 ignored issues
show
Bug introduced by
The method getExportData() does not exist on yii\web\IdentityInterface. It seems like you code against a sub-type of said class. However, the method does not exist in site\tests\_support\MockUser. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

145
    /** @scrutinizer ignore-call */ 
146
    $reader = Yii::$app->user->identity->getExportData();
Loading history...
146
    $fp = fopen('php://output', 'w');
147
148
    $header = [
149
      'Date',
150
      'Behavior',
151
      'Category',
152
      Question::$QUESTIONS[1],
153
      Question::$QUESTIONS[2],
154
      Question::$QUESTIONS[3],
155
    ];
156
157
    fputcsv($fp, $header);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fputcsv() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

157
    fputcsv(/** @scrutinizer ignore-type */ $fp, $header);
Loading history...
158
    $user_behavior = Yii::$container->get(\common\interfaces\UserBehaviorInterface::class);
159
    while($row = $reader->read()) {
160
      $row = $user_behavior::decorateWithCategory([$row]);
161
      $row = Yii::$app->user->identity->cleanExportData($row);
0 ignored issues
show
Bug introduced by
The method cleanExportData() does not exist on yii\web\IdentityInterface. It seems like you code against a sub-type of said class. However, the method does not exist in site\tests\_support\MockUser. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

161
      /** @scrutinizer ignore-call */ 
162
      $row = Yii::$app->user->identity->cleanExportData($row);
Loading history...
162
      fputcsv($fp, $row[0]);
163
    }
164
    fclose($fp);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

164
    fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
165
166
    die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
167
  }
168
}
169