Completed
Pull Request — master (#164)
by Corey
03:18
created

ProfileController::actionChangeEmail()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 24
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 19
nc 4
nop 1
1
<?php
2
namespace site\controllers;
3
4
5
use Yii;
6
use common\models\Question;
7
use yii\web\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
  /**
46
   * @inheritdoc
47
   */
48
  public function actions()
49
  {
50
    return [
51
      'error' => [
52
        'class' => 'yii\web\ErrorAction',
53
      ],
54
      'captcha' => [
55
        'class' => 'yii\captcha\CaptchaAction',
56
      ],
57
    ];
58
  }
59
60
  public function actionIndex() {
61
    $editProfileForm    = Yii::$container->get(\site\models\EditProfileForm::class, [Yii::$app->user->identity]);
62
    $changePasswordForm = Yii::$container->get(\site\models\ChangePasswordForm::class, [Yii::$app->user->identity]);
63
    $changeEmailForm    = Yii::$container->get(\site\models\ChangeEmailForm::class, [Yii::$app->user->identity]);
64
    $deleteAccountForm  = Yii::$container->get(\site\models\DeleteAccountForm::class, [Yii::$app->user->identity]);
65
    $graph              = Yii::$container->get(\common\components\Graph::class, [Yii::$app->user->identity]);
66
67
    if (Yii::$app->request->isAjax && $editProfileForm->load($_POST)) {
68
      Yii::$app->response->format = 'json';
69
      return \yii\widgets\ActiveForm::validate($editProfileForm);
70
    }
71
    $editProfileForm->loadUser();
72
73
    if ($editProfileForm->load(Yii::$app->request->post())) {
74
      $saved_user = $editProfileForm->saveProfile();
75
      if($saved_user) {
76
        Yii::$app->getSession()->setFlash('success', 'New profile data saved!');
77
      }
78
    }
79
80
    return $this->render('index', [
81
      'profile'         => $editProfileForm,
82
      'change_password' => $changePasswordForm,
83
      'change_email'    => $changeEmailForm,
84
      'delete'          => $deleteAccountForm,
85
      '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

85
      '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

85
      '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...
86
    ]);
87
  }
88
89
  public function actionDeleteAccount() {
90
    $model = Yii::$container->get(\site\models\DeleteAccountForm::class, [Yii::$app->user->identity]);
91
92
    if ($model->load(Yii::$app->request->post()) && $model->validate()) {
93
      if($model->deleteAccount()) {
94
        $this->redirect(['site/index']);
95
      } else {
96
        Yii::$app->getSession()->setFlash('error', 'Wrong password!');
97
      }
98
    }
99
100
    $this->redirect(Yii::$app->request->getReferrer());
101
  }
102
103
  public function actionChangePassword() {
104
    $model = Yii::$container->get(\site\models\ChangePasswordForm::class, [Yii::$app->user->identity]);
105
106
    if ($model->load(Yii::$app->request->post())) {
107
      if($model->validate() && $model->changePassword()) {
108
        Yii::$app->getSession()->setFlash('success', 'Password successfully changed');
109
      } else {
110
        Yii::$app->getSession()->setFlash('error', 'Wrong password!');
111
      }
112
    }
113
114
    $this->redirect(['profile/index']);
115
  }
116
117
  public function actionRequestChangeEmail() {
118
    $model = Yii::$container->get(\site\models\ChangeEmailForm::class, [Yii::$app->user->identity]);
119
120
    if ($model->load(Yii::$app->request->post()) && $model->validate()) {
121
      $model->changeEmail();
122
      Yii::$app->getSession()->setFlash('success', "We've sent an email to your requested email address to confirm. Please click on the verification link to continue.");
123
    }
124
125
    $this->redirect(['profile/index']);
126
  }
127
128
  public function actionChangeEmail(string $token) {
129
    $user = \common\models\User::findByChangeEmailToken($token);
0 ignored issues
show
Bug Best Practice introduced by
The method common\models\User::findByChangeEmailToken() is not static, but was called statically. ( Ignorable by Annotation )

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

129
    /** @scrutinizer ignore-call */ 
130
    $user = \common\models\User::findByChangeEmailToken($token);
Loading history...
130
    if($user) {
131
      $validator = new \yii\validators\EmailValidator();
132
      if($validator->validate($user->desired_email, $error)) {
133
        $user->removeChangeEmailToken();
134
        $user->email = $user->desired_email;
135
        $user->desired_email = null;
136
        $user->save();
137
        if(!Yii::$app->user->isGuest) {
138
          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

138
          Yii::$app->user->/** @scrutinizer ignore-call */ 
139
                           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...
139
          Yii::$app->session->setFlash('success', 'Your email address was successfully changed. For security, we\'ve logged you out.');
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

139
          Yii::$app->session->/** @scrutinizer ignore-call */ 
140
                              setFlash('success', 'Your email address was successfully changed. For security, we\'ve logged you out.');

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...
140
        } else {
141
          Yii::$app->session->setFlash('success', 'Your email address was successfully changed.');
142
        }
143
        return $this->goHome();
144
      } else {
145
        // desired_email failed validation. Something sneaky might be happening here
146
        Yii::warning("ProfileController::actionChangeEmail() User({$user->id}) desired_email failed validation. Something weird is going on.");
147
        return $this->goHome();
148
      }
149
    } else {
150
      // no user was found with that token
151
      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.");
152
    }
153
  }
154
155
  public function actionExport() {
156
    header("Content-Type: text/csv");
157
    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...
158
159
    $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

159
    /** @scrutinizer ignore-call */ 
160
    $reader = Yii::$app->user->identity->getExportData();
Loading history...
160
    $fp = fopen('php://output', 'w');
161
162
    $header = [
163
      'Date',
164
      'Behavior',
165
      'Category',
166
      Question::$QUESTIONS[1],
167
      Question::$QUESTIONS[2],
168
      Question::$QUESTIONS[3],
169
    ];
170
171
    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

171
    fputcsv(/** @scrutinizer ignore-type */ $fp, $header);
Loading history...
172
    $user_behavior = Yii::$container->get(\common\interfaces\UserBehaviorInterface::class);
173
    while($row = $reader->read()) {
174
      $row = $user_behavior::decorateWithCategory([$row]);
175
      $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

175
      /** @scrutinizer ignore-call */ 
176
      $row = Yii::$app->user->identity->cleanExportData($row);
Loading history...
176
      fputcsv($fp, $row[0]);
177
    }
178
    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

178
    fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
179
180
    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...
181
  }
182
}
183