1: <?php declare(strict_types=1);
2:
3: namespace Salient\Contract\Console;
4:
5: use Psr\Log\LoggerInterface;
6: use Salient\Contract\Console\ConsoleFormatterInterface as FormatterInterface;
7: use Salient\Contract\Console\ConsoleMessageType as MessageType;
8: use Salient\Contract\Core\Instantiable;
9: use Salient\Contract\Core\MessageLevel as Level;
10: use Salient\Contract\Core\MessageLevelGroup as LevelGroup;
11: use Throwable;
12:
13: interface ConsoleWriterInterface extends Instantiable
14: {
15: /**
16: * Register STDOUT and STDERR to receive console output if running on the
17: * command line
18: *
19: * - Errors and warnings are written to `STDERR`
20: * - Informational messages are written to `STDOUT`
21: * - Debug messages are ignored unless environment variable `DEBUG` is set
22: *
23: * @return $this
24: */
25: public function registerStdioTargets();
26:
27: /**
28: * Register STDERR to receive console output if running on the command line
29: *
30: * - Errors, warnings and informational messages are written to `STDERR`
31: * - Debug messages are ignored unless environment variable `DEBUG` is set
32: *
33: * @return $this
34: */
35: public function registerStderrTarget();
36:
37: /**
38: * Register a target to receive console output
39: *
40: * @param array<Level::*> $levels
41: * @return $this
42: */
43: public function registerTarget(
44: ConsoleTargetInterface $target,
45: array $levels = LevelGroup::ALL
46: );
47:
48: /**
49: * Deregister and close a registered target
50: *
51: * If `$target` is registered with the writer, it is deregistered and closed
52: * via {@see ConsoleTargetInterface::close()}, otherwise calling this method
53: * has no effect.
54: *
55: * @return $this
56: */
57: public function deregisterTarget(ConsoleTargetInterface $target);
58:
59: /**
60: * Get a list of registered targets, optionally filtered by level and type
61: *
62: * @param Level::*|null $level
63: * @param int-mask-of<ConsoleTargetTypeFlag::*> $flags
64: * @return ConsoleTargetInterface[]
65: */
66: public function getTargets(?int $level = null, int $flags = 0): array;
67:
68: /**
69: * Set or unset the prefix applied to each line of output by any registered
70: * targets that implement ConsoleTargetPrefixInterface
71: *
72: * @param int-mask-of<ConsoleTargetTypeFlag::*> $flags
73: * @return $this
74: */
75: public function setTargetPrefix(?string $prefix, int $flags = 0);
76:
77: /**
78: * Get the width of a registered target in columns
79: *
80: * Returns {@see ConsoleTargetInterface::getWidth()} from whichever is found
81: * first:
82: *
83: * - the first TTY target registered with the given level
84: * - the first `STDOUT` or `STDERR` target registered with the given level
85: * - the first target registered with the given level
86: * - the target returned by {@see getStderrTarget()} if backed by a TTY
87: * - the target returned by {@see getStdoutTarget()}
88: *
89: * @param Level::* $level
90: */
91: public function getWidth(int $level = Level::INFO): ?int;
92:
93: /**
94: * Get an output formatter for a registered target
95: *
96: * Returns {@see ConsoleTargetInterface::getFormatter()} from the same
97: * target as {@see ConsoleWriterInterface::getWidth()}.
98: *
99: * @param Level::* $level
100: */
101: public function getFormatter(int $level = Level::INFO): FormatterInterface;
102:
103: /**
104: * Get a PSR-3 logger backed by the writer
105: */
106: public function getLogger(): LoggerInterface;
107:
108: /**
109: * Get a target for STDOUT, creating an unregistered one if necessary
110: */
111: public function getStdoutTarget(): ConsoleTargetStreamInterface;
112:
113: /**
114: * Get a target for STDERR, creating an unregistered one if necessary
115: */
116: public function getStderrTarget(): ConsoleTargetStreamInterface;
117:
118: /**
119: * Get the number of error messages recorded by the writer so far
120: */
121: public function getErrorCount(): int;
122:
123: /**
124: * Get the number of warning messages recorded by the writer so far
125: */
126: public function getWarningCount(): int;
127:
128: /**
129: * Escape a string so it can be safely used in a console message
130: */
131: public function escape(string $string): string;
132:
133: /**
134: * Print "! $msg1 $msg2" with level ERROR
135: *
136: * @return $this
137: */
138: public function error(
139: string $msg1,
140: ?string $msg2 = null,
141: ?Throwable $ex = null,
142: bool $count = true
143: );
144:
145: /**
146: * Print "! $msg1 $msg2" with level ERROR once per run
147: *
148: * @return $this
149: */
150: public function errorOnce(
151: string $msg1,
152: ?string $msg2 = null,
153: ?Throwable $ex = null,
154: bool $count = true
155: );
156:
157: /**
158: * Print "^ $msg1 $msg2" with level WARNING
159: *
160: * @return $this
161: */
162: public function warn(
163: string $msg1,
164: ?string $msg2 = null,
165: ?Throwable $ex = null,
166: bool $count = true
167: );
168:
169: /**
170: * Print "^ $msg1 $msg2" with level WARNING once per run
171: *
172: * @return $this
173: */
174: public function warnOnce(
175: string $msg1,
176: ?string $msg2 = null,
177: ?Throwable $ex = null,
178: bool $count = true
179: );
180:
181: /**
182: * Print "➤ $msg1 $msg2" with level NOTICE
183: *
184: * @return $this
185: */
186: public function info(string $msg1, ?string $msg2 = null);
187:
188: /**
189: * Print "➤ $msg1 $msg2" with level NOTICE once per run
190: *
191: * @return $this
192: */
193: public function infoOnce(string $msg1, ?string $msg2 = null);
194:
195: /**
196: * Print "- $msg1 $msg2" with level INFO
197: *
198: * @return $this
199: */
200: public function log(string $msg1, ?string $msg2 = null);
201:
202: /**
203: * Print "- $msg1 $msg2" with level INFO once per run
204: *
205: * @return $this
206: */
207: public function logOnce(string $msg1, ?string $msg2 = null);
208:
209: /**
210: * Print ": <caller> $msg1 $msg2" with level DEBUG
211: *
212: * @param int $depth To print your caller's name instead of your own, set
213: * `$depth` to 1.
214: * @return $this
215: */
216: public function debug(
217: string $msg1,
218: ?string $msg2 = null,
219: ?Throwable $ex = null,
220: int $depth = 0
221: );
222:
223: /**
224: * Print ": <caller> $msg1 $msg2" with level DEBUG once per run
225: *
226: * @param int $depth To print your caller's name instead of your own, set
227: * `$depth` to 1.
228: * @return $this
229: */
230: public function debugOnce(
231: string $msg1,
232: ?string $msg2 = null,
233: ?Throwable $ex = null,
234: int $depth = 0
235: );
236:
237: /**
238: * Print "⠿ $msg1 $msg2" with level INFO to TTY targets without moving to
239: * the next line
240: *
241: * This method can be called repeatedly to display progress updates without
242: * disrupting other console messages or bloating output logs.
243: *
244: * @return $this
245: */
246: public function logProgress(string $msg1, ?string $msg2 = null);
247:
248: /**
249: * Print a "clear to end of line" control sequence with level INFO to TTY
250: * targets with a logProgress() message
251: *
252: * @return $this
253: */
254: public function clearProgress();
255:
256: /**
257: * Print "$msg1 $msg2" with prefix and formatting optionally based on $level
258: *
259: * @param Level::* $level
260: * @param MessageType::* $type
261: * @return $this
262: */
263: public function message(
264: string $msg1,
265: ?string $msg2 = null,
266: int $level = Level::INFO,
267: int $type = MessageType::UNDECORATED,
268: ?Throwable $ex = null,
269: bool $count = true
270: );
271:
272: /**
273: * Print "$msg1 $msg2" with prefix and formatting optionally based on $level
274: * once per run
275: *
276: * @param Level::* $level
277: * @param MessageType::* $type
278: * @return $this
279: */
280: public function messageOnce(
281: string $msg1,
282: ?string $msg2 = null,
283: int $level = Level::INFO,
284: int $type = MessageType::UNDECORATED,
285: ?Throwable $ex = null,
286: bool $count = true
287: );
288:
289: /**
290: * Record a message with level $level without printing anything
291: *
292: * @param Level::* $level
293: * @return $this
294: */
295: public function count(int $level);
296:
297: /**
298: * Increase the indentation level of messages and print "» $msg1 $msg2" with
299: * level NOTICE
300: *
301: * If `$endMsg1` is not `null`, `"« $endMsg1 $endMsg2"` is printed with
302: * level `NOTICE` when {@see groupEnd()} is called to close the group.
303: *
304: * @return $this
305: */
306: public function group(
307: string $msg1,
308: ?string $msg2 = null,
309: ?string $endMsg1 = null,
310: ?string $endMsg2 = null
311: );
312:
313: /**
314: * Close the nested message group most recently opened with group()
315: *
316: * @return $this
317: */
318: public function groupEnd();
319:
320: /**
321: * Print an exception's name and message with a given level, optionally
322: * followed by its stack trace with a different level
323: *
324: * @param Level::* $level
325: * @param Level::*|null $traceLevel If `null`, the exception's stack trace
326: * is not printed.
327: * @return $this
328: */
329: public function exception(
330: Throwable $exception,
331: int $level = Level::ERROR,
332: ?int $traceLevel = Level::DEBUG
333: );
334:
335: /**
336: * Print a "command finished" message with a summary of errors, warnings and
337: * resource usage
338: *
339: * @return $this
340: */
341: public function summary(
342: string $finishedText = 'Command finished',
343: string $successText = 'without errors',
344: bool $withResourceUsage = false,
345: bool $withoutErrorCount = false,
346: bool $withStandardMessageType = false
347: );
348:
349: /**
350: * Print "$msg" to registered targets
351: *
352: * @param Level::* $level
353: * @param MessageType::* $type
354: * @return $this
355: */
356: public function print(
357: string $msg,
358: int $level = Level::INFO,
359: int $type = MessageType::UNFORMATTED
360: );
361:
362: /**
363: * Print "$msg" to registered STDOUT or STDERR targets
364: *
365: * @param Level::* $level
366: * @param MessageType::* $type
367: * @return $this
368: */
369: public function printOut(
370: string $msg,
371: int $level = Level::INFO,
372: int $type = MessageType::UNFORMATTED
373: );
374:
375: /**
376: * Print "$msg" to registered TTY targets
377: *
378: * @param Level::* $level
379: * @param MessageType::* $type
380: * @return $this
381: */
382: public function printTty(
383: string $msg,
384: int $level = Level::INFO,
385: int $type = MessageType::UNFORMATTED
386: );
387:
388: /**
389: * Print "$msg" to STDOUT even if no STDOUT target is registered
390: *
391: * @param Level::* $level
392: * @param MessageType::* $type
393: * @return $this
394: */
395: public function printStdout(
396: string $msg,
397: int $level = Level::INFO,
398: int $type = MessageType::UNFORMATTED
399: );
400:
401: /**
402: * Print "$msg" to STDERR even if no STDERR target is registered
403: *
404: * @param Level::* $level
405: * @param MessageType::* $type
406: * @return $this
407: */
408: public function printStderr(
409: string $msg,
410: int $level = Level::INFO,
411: int $type = MessageType::UNFORMATTED
412: );
413: }
414: