These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace bedezign\yii2\audit\commands; |
||
4 | |||
5 | use bedezign\yii2\audit\Audit; |
||
6 | use bedezign\yii2\audit\components\panels\Panel; |
||
7 | use bedezign\yii2\audit\models\AuditEntry; |
||
8 | use bedezign\yii2\audit\models\AuditError; |
||
9 | use Yii; |
||
10 | use yii\base\Exception; |
||
11 | use yii\console\Controller; |
||
12 | use yii\helpers\Console; |
||
13 | use yii\helpers\Html; |
||
14 | use yii\helpers\Url; |
||
15 | |||
16 | /** |
||
17 | * Task runner commands for Audit. |
||
18 | * |
||
19 | * @package bedezign\yii2\audit\commands |
||
20 | */ |
||
21 | class AuditController extends Controller |
||
22 | { |
||
23 | |||
24 | /** |
||
25 | * @var bool True to cleanup the AuditEntry. |
||
26 | */ |
||
27 | public $entry; |
||
28 | |||
29 | /** |
||
30 | * @var bool True to cleanup solo AuditEntry records (no trail/mail/error/javascript). |
||
31 | */ |
||
32 | public $entrySolo; |
||
33 | |||
34 | /** |
||
35 | * @var string|null Comma separated list of panels to cleanup. |
||
36 | */ |
||
37 | public $panels; |
||
38 | |||
39 | /** |
||
40 | * @var int|null Max age in days to cleanup, if null then the panel settings are used. |
||
41 | */ |
||
42 | public $age; |
||
43 | |||
44 | /** |
||
45 | * @inheritdoc |
||
46 | */ |
||
47 | public function options($actionID) |
||
48 | { |
||
49 | return array_merge( |
||
50 | parent::options($actionID), |
||
51 | ($actionID == 'cleanup') ? ['entry', 'entrySolo', 'panels', 'age'] : [] |
||
52 | ); |
||
53 | } |
||
54 | |||
55 | /** |
||
56 | * Cleanup the Audit data |
||
57 | * |
||
58 | * @return int|void |
||
59 | */ |
||
60 | public function actionCleanup() |
||
61 | { |
||
62 | /** @var Audit $audit */ |
||
63 | $audit = Yii::$app->getModule(Audit::findModuleIdentifier()); |
||
64 | if ($this->panels === '') { |
||
65 | $panels = []; |
||
66 | } else { |
||
67 | $panels = !empty($this->panels) ? explode(',', $this->panels) : array_keys($audit->panels); |
||
68 | } |
||
69 | |||
70 | // summary |
||
71 | $this->preCleanupSummary($this->entry, $this->entrySolo, $panels, $this->age); |
||
72 | |||
73 | // confirm |
||
74 | if ($this->confirm('Cleanup the above data?')) { |
||
75 | // cleanup panels |
||
76 | foreach ($panels as $id) { |
||
77 | if (!$this->cleanupPanel($id, $this->age)) { |
||
78 | $this->stdout("\nCleanup failed. The rest of the cleanups are canceled.\n", Console::FG_RED); |
||
79 | return self::EXIT_CODE_ERROR; |
||
80 | } |
||
81 | } |
||
82 | // cleanup audit_entry |
||
83 | if ($this->entry) { |
||
84 | if (!$this->cleanupEntry($this->age)) { |
||
85 | $this->stdout("\nCleanup failed.\n", Console::FG_RED); |
||
86 | return self::EXIT_CODE_ERROR; |
||
87 | } |
||
88 | } |
||
89 | // cleanup solo audit_entry |
||
90 | if ($this->entrySolo) { |
||
91 | if (!$this->cleanupEntrySolo()) { |
||
92 | $this->stdout("\nCleanup failed.\n", Console::FG_RED); |
||
93 | return self::EXIT_CODE_ERROR; |
||
94 | } |
||
95 | } |
||
96 | // success! |
||
97 | $this->stdout("\nCleanup was successful.\n", Console::FG_GREEN); |
||
98 | } |
||
99 | return self::EXIT_CODE_NORMAL; |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | * Displays a summary of the data and dates to clean |
||
104 | * |
||
105 | * @param bool $entry |
||
106 | * @param bool $entrySolo |
||
107 | * @param array $panels |
||
108 | * @param int|null $maxAge |
||
109 | */ |
||
110 | protected function preCleanupSummary($entry, $entrySolo, $panels, $maxAge) |
||
111 | { |
||
112 | $audit = Audit::getInstance(); |
||
113 | |||
114 | // heading |
||
115 | $n = count($panels); |
||
116 | $this->stdout("Total $n " . ($n === 1 ? 'cleanup' : 'cleanups') . " to be applied:\n", Console::FG_YELLOW); |
||
117 | $this->stdout("\t" . 'DATA CLEANUP TO DATETIME' . "\n"); |
||
118 | $this->stdout("\t" . '---------------------------------------------' . "\n"); |
||
119 | |||
120 | // audit panels |
||
121 | foreach ($panels as $id) { |
||
122 | /** @var Panel $panel */ |
||
123 | $panel = $audit->getPanel($id); |
||
124 | $age = $maxAge !== null ? $maxAge : $panel->maxAge; |
||
125 | $dots = str_repeat('.', 24 - strlen($id)); |
||
126 | if ($age !== null) { |
||
127 | $date = date('Y-m-d 23:59:59', strtotime("-$age days")); |
||
128 | $this->stdout("\t" . $id . ' ' . $dots . ' ' . $date . "\n"); |
||
129 | } else { |
||
130 | $this->stdout("\t" . $id . ' ' . $dots . ' no maxAge, skipping' . "\n"); |
||
131 | } |
||
132 | } |
||
133 | |||
134 | // audit entry |
||
135 | if ($entry) { |
||
136 | $maxAge = $maxAge !== null ? $maxAge : $audit->maxAge; |
||
137 | $date = $maxAge !== null ? date('Y-m-d 23:59:59', strtotime("-$maxAge days")) : 'no maxAge, skipping'; |
||
138 | $this->stdout("\t" . 'AuditEntry .............. ' . $date . "\n"); |
||
139 | } |
||
140 | |||
141 | // audit entry solo |
||
142 | if ($entrySolo) { |
||
143 | $this->stdout("\t" . 'AuditEntry solo ......... ' . date('Y-m-d 23:59:59') . "\n"); |
||
144 | } |
||
145 | |||
146 | $this->stdout("\n"); |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Cleans the AuditEntry data |
||
151 | * |
||
152 | * @param $maxAge |
||
153 | * @return bool |
||
154 | */ |
||
155 | protected function cleanupEntry($maxAge) |
||
156 | { |
||
157 | $maxAge = $maxAge !== null ? $maxAge : Audit::getInstance()->maxAge; |
||
158 | if ($maxAge === null) { |
||
159 | $this->stdout("\n*** skipped AuditEntry\n", Console::FG_PURPLE); |
||
160 | return true; |
||
161 | } |
||
162 | $date = date('Y-m-d 23:59:59', strtotime("-$maxAge days")); |
||
163 | $this->stdout("\n*** cleaning AuditEntry", Console::FG_YELLOW); |
||
164 | $start = microtime(true); |
||
165 | $count = AuditEntry::deleteAll(['<=', 'created', $date]); |
||
166 | if ($count !== false) { |
||
167 | $time = microtime(true) - $start; |
||
168 | $this->stdout("\n*** cleaned AuditEntry (records: " . $count . ",time: " . sprintf("%.3f", $time) . "s)\n", Console::FG_GREEN); |
||
169 | return true; |
||
170 | } |
||
171 | $time = microtime(true) - $start; |
||
172 | $this->stdout("\n*** failed to clean AuditEntry (time: " . sprintf("%.3f", $time) . "s)\n", Console::FG_RED); |
||
173 | return false; |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Cleans the AuditEntry solo data (no trail/mail/error/javascript) |
||
178 | * |
||
179 | * @return bool |
||
180 | */ |
||
181 | protected function cleanupEntrySolo() |
||
182 | { |
||
183 | $this->stdout("\n*** cleaning AuditEntry solo", Console::FG_YELLOW); |
||
184 | $start = microtime(true); |
||
185 | $count = 0; |
||
186 | foreach (AuditEntry::find()->each(100) as $auditEntry) { |
||
187 | /** @var AuditEntry $auditEntry */ |
||
188 | /** @var Audit $audit */ |
||
189 | $audit = Yii::$app->getModule('audit'); |
||
190 | $auditEntryCurrent = $audit->getEntry(); |
||
191 | if ($auditEntryCurrent && $auditEntryCurrent->id == $auditEntry->id) { |
||
192 | continue; |
||
193 | } |
||
194 | if (!$auditEntry->errors && !$auditEntry->javascripts && !$auditEntry->mails && !$auditEntry->trails) { |
||
195 | foreach ($auditEntry->data as $data) { |
||
196 | $data->delete(); |
||
197 | } |
||
198 | try { |
||
199 | $auditEntry->delete(); |
||
200 | $count++; |
||
201 | $this->stdout('.', Console::FG_CYAN); |
||
202 | } catch (Exception $e) { |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
Loading history...
|
|||
203 | } |
||
204 | } |
||
205 | } |
||
206 | $time = microtime(true) - $start; |
||
207 | $this->stdout("\n*** cleaned AuditEntry (records: " . $count . ",time: " . sprintf("%.3f", $time) . "s)\n", Console::FG_GREEN); |
||
208 | return true; |
||
209 | } |
||
210 | |||
211 | /** |
||
212 | * Cleans the Panel data |
||
213 | * |
||
214 | * @param $id |
||
215 | * @param $maxAge |
||
216 | * @return bool |
||
217 | */ |
||
218 | protected function cleanupPanel($id, $maxAge) |
||
219 | { |
||
220 | /** @var Panel $panel */ |
||
221 | $panel = Audit::getInstance()->getPanel($id); |
||
222 | $age = $maxAge !== null ? $maxAge : $panel->maxAge; |
||
223 | if ($age === null) { |
||
224 | $this->stdout("\n*** skipped $id\n", Console::FG_PURPLE); |
||
225 | return true; |
||
226 | } |
||
227 | $this->stdout("\n*** cleaning $id", Console::FG_YELLOW); |
||
228 | $start = microtime(true); |
||
229 | $count = $panel->cleanup($maxAge); |
||
230 | if ($count !== false) { |
||
231 | $time = microtime(true) - $start; |
||
232 | $this->stdout("\n*** cleaned $id (records: " . $count . ", time: " . sprintf("%.3f", $time) . "s)\n", Console::FG_GREEN); |
||
233 | return true; |
||
234 | } |
||
235 | $time = microtime(true) - $start; |
||
236 | $this->stdout("\n*** failed to clean $id (time: " . sprintf("%.3f", $time) . "s)\n", Console::FG_RED); |
||
237 | return false; |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Email errors to support email. |
||
242 | * |
||
243 | * @param string|null $email |
||
244 | * @return int |
||
245 | */ |
||
246 | public function actionErrorEmail($email = null) |
||
247 | { |
||
248 | $email = $email ? $email : Yii::$app->params['supportEmail']; |
||
249 | |||
250 | // find all errors to email |
||
251 | $batch = AuditError::find()->where(['emailed' => 0])->batch(); |
||
252 | foreach ($batch as $auditErrors) { |
||
253 | /** @var AuditError $model */ |
||
254 | foreach ($auditErrors as $model) { |
||
255 | |||
256 | // define params and message |
||
257 | $url = ['audit/default/view', 'id' => $model->entry_id]; |
||
258 | $params = [ |
||
259 | 'entry_id' => $model->entry_id, |
||
260 | 'message' => $model->message, |
||
261 | 'file' => $model->file, |
||
262 | 'line' => $model->line, |
||
263 | 'url' => Url::to($url), |
||
264 | 'link' => Html::a(Yii::t('audit', 'view audit entry'), $url), |
||
265 | ]; |
||
266 | $message = [ |
||
267 | 'subject' => Yii::t('audit', 'Audit Error in Audit Entry #{entry_id}', $params), |
||
268 | 'text' => Yii::t('audit', '{message}' . "\n" . 'in {file} on line {line}.' . "\n" . '-- {url}', $params), |
||
269 | 'html' => Yii::t('audit', '<b>{message}</b><br />in <i>{file}</i> on line <i>{line}</i>.<br/>-- {link}', $params), |
||
270 | ]; |
||
271 | |||
272 | // send email |
||
273 | Yii::$app->mailer->compose() |
||
274 | ->setFrom([$email => 'Audit :: ' . Yii::$app->name]) |
||
275 | ->setTo($email) |
||
276 | ->setSubject($message['subject']) |
||
277 | ->setTextBody($message['text']) |
||
278 | ->setHtmlBody($message['html']) |
||
279 | ->send(); |
||
280 | |||
281 | // mark as emailed |
||
282 | $model->emailed = 1; |
||
283 | $model->save(false, ['emailed']); |
||
284 | |||
285 | } |
||
286 | } |
||
287 | return self::EXIT_CODE_NORMAL; |
||
288 | } |
||
289 | |||
290 | } |
||
291 |