5a307f73c2f1ef6b33f38bbf311f005d9b6b2d28
[yaffs-website] / vendor / drush / drush / src / Drupal / Commands / core / WatchdogCommands.php
1 <?php
2 namespace Drush\Drupal\Commands\core;
3
4 use Consolidation\OutputFormatters\StructuredData\PropertyList;
5 use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
6 use Drupal\Core\Database\Database;
7 use Drupal\Core\Logger\RfcLogLevel;
8 use Drush\Commands\DrushCommands;
9 use Drupal\Component\Utility\Unicode;
10 use Drupal\Component\Utility\Html;
11 use Drush\Drupal\DrupalUtil;
12 use Drush\Exceptions\UserAbortException;
13
14 class WatchdogCommands extends DrushCommands
15 {
16
17     /**
18      * Show watchdog messages.
19      *
20      * @command watchdog:show
21      * @param $substring A substring to look search in error messages.
22      * @option count The number of messages to show. Defaults to 10.
23      * @option severity Restrict to messages of a given severity level.
24      * @option type Restrict to messages of a given type.
25      * @option extended Return extended information about each message.
26      * @usage  drush watchdog-show
27      *   Show a listing of most recent 10 messages.
28      * @usage drush watchdog:show "cron run succesful"
29      *   Show a listing of most recent 10 messages containing the string "cron run succesful".
30      * @usage drush watchdog:show --count=46
31      *   Show a listing of most recent 46 messages.
32      * @usage drush watchdog:show --severity=Notice
33      *   Show a listing of most recent 10 messages with a severity of notice.
34      * @usage drush watchdog:show --type=php
35      *   Show a listing of most recent 10 messages of type php
36      * @aliases wd-show,ws,watchdog-show
37      * @validate-module-enabled dblog
38      * @field-labels
39      *   wid: ID
40      *   type: Type
41      *   message: Message
42      *   severity: Severity
43      *   location: Location
44      *   hostname: Hostname
45      *   date: Date
46      *   username: Username
47      * @default-fields wid,date,type,severity,message
48      * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
49      */
50     public function show($substring = '', $options = ['format' => 'table', 'count' => 10, 'severity' => self::REQ, 'type' => self::REQ, 'extended' => false])
51     {
52         $where = $this->where($options['type'], $options['severity'], $substring);
53         $query = Database::getConnection()->select('watchdog', 'w')
54             ->range(0, $options['count'])
55             ->fields('w')
56             ->orderBy('wid', 'DESC');
57         if (!empty($where['where'])) {
58             $query->where($where['where'], $where['args']);
59         }
60         $rsc = $query->execute();
61         while ($result = $rsc->fetchObject()) {
62             $row = $this->formatResult($result, $options['extended']);
63             $table[$row->wid] = (array)$row;
64         }
65         if (empty($table)) {
66             $this->logger()->notice(dt('No log messages available.'));
67         } else {
68             return new RowsOfFields($table);
69         }
70     }
71
72     /**
73      * Interactively filter the watchdog message listing.
74      *
75      * @command watchdog:list
76      * @param $substring A substring to look search in error messages.
77      * @option count The number of messages to show. Defaults to 10.
78      * @option extended Return extended information about each message.
79      * @option severity Restrict to messages of a given severity level.
80      * @option type Restrict to messages of a given type.
81      * @usage  drush watchdog-list
82      *   Prompt for message type or severity, then run watchdog-show.
83      * @aliases wd-list,watchdog-list
84      * @hidden-options type,severity
85      * @validate-module-enabled dblog
86      * @field-labels
87      *   wid: ID
88      *   type: Type
89      *   message: Message
90      *   severity: Severity
91      *   location: Location
92      *   hostname: Hostname
93      *   date: Date
94      *   username: Username
95      * @default-fields wid,date,type,severity,message
96      * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
97      */
98     public function watchdogList($substring = '', $options = ['format' => 'table', 'count' => 10, 'extended' => false])
99     {
100         return $this->show($substring, $options);
101     }
102
103     /**
104      * @hook interact watchdog-list
105      * @throws \Drush\Exceptions\UserAbortException
106      */
107     public function interactList($input, $output)
108     {
109
110         $choices['-- types --'] = dt('== message types ==');
111         $types = $this->messageTypes();
112         foreach ($types as $key => $type) {
113             $choices[$key] = $type;
114         }
115         $choices['-- levels --'] = dt('== severity levels ==');
116         $severities = RfcLogLevel::getLevels();
117
118         foreach ($severities as $key => $value) {
119             $choices[$key] = $value;
120         }
121         $option = $this->io()->choice(dt('Select a message type or severity level'), $choices);
122         if (isset($types[$option])) {
123             $input->setOption('type', $types[$option]);
124         } else {
125             $input->setOption('severity', $option);
126         }
127     }
128
129     /**
130      * Delete watchdog log records.
131      *
132      * @command watchdog:delete
133      * @param $substring Delete all log records with this text in the messages.
134      * @option severity Delete messages of a given severity level.
135      * @option type Delete messages of a given type.
136      * @usage drush watchdog:delete all
137      *   Delete all messages.
138      * @usage drush watchdog:delete 64
139      *   Delete messages with id 64.
140      * @usage drush watchdog:delete "cron run succesful"
141      *   Delete messages containing the string "cron run succesful".
142      * @usage drush watchdog:delete --severity=notice
143      *   Delete all messages with a severity of notice.
144      * @usage drush watchdog:delete --type=cron
145      *   Delete all messages of type cron.
146      * @aliases wd-del,wd-delete,wd,watchdog-delete
147      * @validate-module-enabled dblog
148      * @return void
149      */
150     public function delete($substring = '', $options = ['severity' => self::REQ, 'type' => self::REQ])
151     {
152         if ($substring == 'all') {
153             $this->output()->writeln(dt('All watchdog messages will be deleted.'));
154             if (!$this->io()->confirm(dt('Do you really want to continue?'))) {
155                 throw new UserAbortException();
156             }
157             $ret = Database::getConnection()->truncate('watchdog')->execute();
158             $this->logger()->success(dt('All watchdog messages have been deleted.'));
159         } else if (is_numeric($substring)) {
160             $this->output()->writeln(dt('Watchdog message #!wid will be deleted.', ['!wid' => $substring]));
161             if (!$this->io()->confirm(dt('Do you want to continue?'))) {
162                 throw new UserAbortException();
163             }
164             $affected_rows = Database::getConnection()->delete('watchdog')->condition('wid', $substring)->execute();
165             if ($affected_rows == 1) {
166                 $this->logger()->success(dt('Watchdog message #!wid has been deleted.', ['!wid' => $substring]));
167             } else {
168                 throw new \Exception(dt('Watchdog message #!wid does not exist.', ['!wid' => $substring]));
169             }
170         } else {
171             if ((!isset($substring))&&(!isset($options['type']))&&(!isset($options['severity']))) {
172                 throw new \Exception(dt('No options provided.'));
173             }
174             $where = $this->where($options['type'], $options['severity'], $substring, 'OR');
175             $this->output()->writeln(dt('All messages with !where will be deleted.', ['!where' => preg_replace("/message LIKE %$substring%/", "message body containing '$substring'", strtr($where['where'], $where['args']))]));
176             if (!$this->io()->confirm(dt('Do you want to continue?'))) {
177                 throw new UserAbortException();
178             }
179             $affected_rows = Database::getConnection()->delete('watchdog')
180                 ->where($where['where'], $where['args'])
181                 ->execute();
182             $this->logger()->success(dt('!affected_rows watchdog messages have been deleted.', ['!affected_rows' => $affected_rows]));
183         }
184     }
185
186     /**
187      * Show one log record by ID.
188      *
189      * @command watchdog:show-one
190      * @param $id Watchdog Id
191      * @aliases wd-one,watchdog-show-one
192      * @validate-module-enabled dblog
193      *
194      * @return \Consolidation\OutputFormatters\StructuredData\PropertyList
195      */
196     public function showOne($id, $options = ['format' => 'yaml'])
197     {
198         $rsc = Database::getConnection()->select('watchdog', 'w')
199             ->fields('w')
200             ->condition('wid', (int)$id)
201             ->range(0, 1)
202             ->execute();
203         $result = $rsc->fetchObject();
204         if (!$result) {
205             throw new \Exception(dt('Watchdog message #!wid not found.', ['!wid' => $id]));
206         }
207         return new PropertyList($this->formatResult($result));
208     }
209
210     /**
211      * Build a WHERE snippet based on given parameters.
212      *
213      * @param $type
214      *   String. Valid watchdog type.
215      * @param $severity
216      *   Int or String for a valid watchdog severity message.
217      * @param $filter
218      *   String. Value to filter watchdog messages by.
219      * @param $criteria
220      *   ('AND', 'OR'). Criteria for the WHERE snippet.
221      * @return
222      *   An array with structure ('where' => string, 'args' => array())
223      */
224     protected function where($type = null, $severity = null, $filter = null, $criteria = 'AND')
225     {
226         $args = [];
227         $conditions = [];
228         if ($type) {
229             $types = $this->messageTypes();
230             if (array_search($type, $types) === false) {
231                 $msg = "Unrecognized message type: !type.\nRecognized types are: !types.";
232                 throw new \Exception(dt($msg, ['!type' => $type, '!types' => implode(', ', $types)]));
233             }
234             $conditions[] = "type = :type";
235             $args[':type'] = $type;
236         }
237         if (isset($severity)) {
238             $severities = RfcLogLevel::getLevels();
239             if (isset($severities[$severity])) {
240                 $level = $severity;
241             } elseif (($key = array_search($severity, $severities)) !== false) {
242                 $level = $key;
243             } else {
244                 $level = false;
245             }
246             if ($level === false) {
247                 foreach ($severities as $key => $value) {
248                     $levels[] = "$value($key)";
249                 }
250                 $msg = "Unknown severity level: !severity.\nValid severity levels are: !levels.";
251                 throw new \Exception(dt($msg, ['!severity' => $severity, '!levels' => implode(', ', $levels)]));
252             }
253             $conditions[] = 'severity = :severity';
254             $args[':severity'] = $level;
255         }
256         if ($filter) {
257             $conditions[] = "message LIKE :filter";
258             $args[':filter'] = '%'.$filter.'%';
259         }
260
261         $where = implode(" $criteria ", $conditions);
262
263         return ['where' => $where, 'args' => $args];
264     }
265
266     /**
267      * Format a watchdog database row.
268      *
269      * @param $result
270      *   Array. A database result object.
271      * @param $extended
272      *   Boolean. Return extended message details.
273      * @return
274      *   Array. The result object with some attributes themed.
275      */
276     protected function formatResult($result, $extended = false)
277     {
278         // Severity.
279         $severities = RfcLogLevel::getLevels();
280         $result->severity = trim(DrupalUtil::drushRender($severities[$result->severity]));
281
282         // Date.
283         $result->date = format_date($result->timestamp, 'custom', 'd/M H:i');
284         unset($result->timestamp);
285
286         // Message.
287         $variables = $result->variables;
288         if (is_string($variables)) {
289             $variables = unserialize($variables);
290         }
291         if (is_array($variables)) {
292             $result->message = strtr($result->message, $variables);
293         }
294         unset($result->variables);
295         $message_length = 188;
296
297         // Print all the data available
298         if ($extended) {
299             // Possible empty values.
300             if (empty($result->link)) {
301                 unset($result->link);
302             }
303             if (empty($result->referer)) {
304                 unset($result->referer);
305             }
306             // Username.
307             if ($account = user_load($result->uid)) {
308                 $result->username = $account->name;
309             } else {
310                 $result->username = dt('Anonymous');
311             }
312             unset($result->uid);
313             $message_length = PHP_INT_MAX;
314         }
315         $result->message = Unicode::truncate(strip_tags(Html::decodeEntities($result->message)), $message_length, false, false);
316
317         return $result;
318     }
319
320     /**
321      * Helper function to obtain the message types based on drupal version.
322      *
323      * @return
324      *   Array of watchdog message types.
325      */
326     public static function messageTypes()
327     {
328         return _dblog_get_message_types();
329     }
330 }