1
+ <?php
2
+ /**
3
+ * The <b>DebugIterator</b> wraps as an {@see IteratorIterator} around
4
+ * any other {@see Iterator} and logs all calls to it.
5
+ *
6
+ * <code>
7
+ * // Take any iterator...
8
+ * $originalIterator = new ArrayIterator(range(1, 5));
9
+ *
10
+ * // ..and wrap it in a DebugIterator, to log calls to it.
11
+ * $iterator = new DebugIterator($originalIterator);
12
+ *
13
+ * // This will now print something like
14
+ * // DebugIterator(ArrayIterator)::rewind()
15
+ * // DebugIterator(ArrayIterator)::valid() => TRUE
16
+ * // DebugIterator(ArrayIterator)::current() => 1
17
+ * // DebugIterator(ArrayIterator)::next()
18
+ * // ...
19
+ * foreach($iterator as $item) {
20
+ * // ...
21
+ * }
22
+ * </code>
23
+ *
24
+ * @author Beat Vontobel
25
+ * @since 2015-05-2i
26
+ * @package MeteoNews\phplib
27
+ * @subpackage Iterators
28
+ */
29
+ class DebugIterator extends IteratorIterator {
30
+ /**
31
+ * Logs a message.
32
+ *
33
+ * Override this, if you want to send your log output to different
34
+ * destinations or with different formatting. Per default each
35
+ * message will be just printed to STDOUT with a newline appended.
36
+ *
37
+ * @param string The message to be logged.
38
+ *
39
+ * @return void
40
+ */
41
+ protected function writeLogMessage ($ message ) {
42
+ printf ("%s \n" , $ message );
43
+ }
44
+
45
+ /**
46
+ * Logs one method call.
47
+ *
48
+ * Override this, if you're unhappy with the default formatting.
49
+ *
50
+ * The default internally uses {@see formatValue()} to format
51
+ * individual arguments and return values to/from method calls and
52
+ * {@see writeLogMessage()} to send the completed message to an
53
+ * output channel. If you just want to change one of those, it's
54
+ * better to override those methods and leave this one as it is.
55
+ *
56
+ * @param string The name of the called method.
57
+ *
58
+ * @param boolean If the given method has a return value (TRUE) or
59
+ * is void (FALSE).
60
+ *
61
+ * @param mixed The return value from the called method (ignored if
62
+ * the previous argument is FALSE).
63
+ *
64
+ * @param array The arguments to the method call.
65
+ *
66
+ * @return void
67
+ *
68
+ * @see writeLogMessage(), formatValue()
69
+ */
70
+ protected function logCall ($ method ,
71
+ $ hasReturnValue = FALSE ,
72
+ $ returnValue = NULL ,
73
+ array $ args = array ()) {
74
+ $ message = sprintf ("%s(%s)::%s(%s) " ,
75
+ get_called_class (),
76
+ get_class (parent ::getInnerIterator ()),
77
+ $ method ,
78
+ implode (", " , array_map (array ($ this , 'formatValue ' ), $ args )));
79
+ if ($ hasReturnValue )
80
+ $ message .= sprintf (" => %s " , $ this ->formatValue ($ returnValue ));
81
+ $ this ->writeLogMessage ($ message );
82
+ }
83
+
84
+ /**
85
+ * Formats a PHP value as a string.
86
+ *
87
+ * Used for arguments and return values to/from method calls in log
88
+ * messages. Override this, if you're unhappy with the default
89
+ * format.
90
+ *
91
+ * @param mixed The value to be formatted as a string.
92
+ *
93
+ * @return string
94
+ */
95
+ protected function formatValue ($ value ) {
96
+ if (is_object ($ value ))
97
+ if (is_a ($ value , "ifMNDebugName " ))
98
+ return $ value ->getDebugName ();
99
+ else
100
+ return sprintf ("object(%s) " ,
101
+ get_class ($ value ));
102
+ elseif (is_array ($ value ))
103
+ return sprintf ("array(%s) " ,
104
+ implode (", " ,
105
+ array_map (array ($ this , 'formatValue ' ),
106
+ $ value )));
107
+ elseif (is_bool ($ value ))
108
+ return $ value ? "TRUE " : "FALSE " ;
109
+ elseif (is_null ($ value ))
110
+ return "NULL " ;
111
+ elseif (is_float ($ value ) || is_int ($ value ))
112
+ return (string )$ value ;
113
+ else
114
+ return sprintf ("'%s' " ,
115
+ str_replace ("' " , "\\' " , $ value ));
116
+ }
117
+
118
+
119
+ /*
120
+ * Just override all the IteratorIterator methods here to hook in
121
+ * the logging calls.
122
+ */
123
+
124
+ public function __construct (Traversable $ iterator ) {
125
+ parent ::__construct ($ iterator );
126
+ $ this ->logCall (__FUNCTION__ , TRUE , $ this , array ($ iterator ));
127
+ }
128
+
129
+ public function current () {
130
+ $ current = parent ::current ();
131
+ $ this ->logCall (__FUNCTION__ , TRUE , $ current );
132
+ return $ current ;
133
+ }
134
+
135
+ public function getInnerIterator () {
136
+ $ innerIterator = parent ::getInnerIterator ();
137
+ $ this ->logCall (__FUNCTION__ , TRUE , $ innerIterator );
138
+ return $ innerIterator ;
139
+ }
140
+
141
+ public function key () {
142
+ $ key = parent ::key ();
143
+ $ this ->logCall (__FUNCTION__ , TRUE , $ key );
144
+ return $ key ;
145
+ }
146
+
147
+ public function next () {
148
+ parent ::next ();
149
+ $ this ->logCall (__FUNCTION__ );
150
+ }
151
+
152
+ public function rewind () {
153
+ parent ::rewind ();
154
+ $ this ->logCall (__FUNCTION__ );
155
+ }
156
+
157
+ public function valid () {
158
+ $ valid = parent ::valid ();
159
+ $ this ->logCall (__FUNCTION__ , TRUE , $ valid );
160
+ return $ valid ;
161
+ }
162
+ }
163
+ ?>
0 commit comments