1: <?php
2:
3: namespace Guzzle\Plugin\Log;
4:
5: use Guzzle\Common\Event;
6: use Guzzle\Log\LogAdapterInterface;
7: use Guzzle\Log\MessageFormatter;
8: use Guzzle\Log\ClosureLogAdapter;
9: use Guzzle\Http\EntityBody;
10: use Guzzle\Http\Message\EntityEnclosingRequestInterface;
11: use Guzzle\Http\Message\Response;
12: use Symfony\Component\EventDispatcher\EventSubscriberInterface;
13:
14: 15: 16: 17: 18: 19: 20:
21: class LogPlugin implements EventSubscriberInterface
22: {
23: 24: 25:
26: private $logAdapter;
27:
28: 29: 30:
31: protected $formatter;
32:
33: 34: 35:
36: protected $wireBodies;
37:
38: 39: 40: 41: 42: 43: 44: 45:
46: public function __construct(
47: LogAdapterInterface $logAdapter,
48: $formatter = null,
49: $wireBodies = false
50: ) {
51: $this->logAdapter = $logAdapter;
52: $this->formatter = $formatter instanceof MessageFormatter ? $formatter : new MessageFormatter($formatter);
53: $this->wireBodies = $wireBodies;
54: }
55:
56: 57: 58: 59: 60: 61: 62: 63:
64: public static function getDebugPlugin($wireBodies = true, $stream = null)
65: {
66: if ($stream === null) {
67: if (defined('STDERR')) {
68: $stream = STDERR;
69: } else {
70: $stream = fopen('php://output', 'w');
71: }
72: }
73:
74: return new self(new ClosureLogAdapter(function ($m) use ($stream) {
75: fwrite($stream, $m . PHP_EOL);
76: }), "# Request:\n{request}\n\n# Response:\n{response}\n\n# Errors: {curl_code} {curl_error}", $wireBodies);
77: }
78:
79: 80: 81:
82: public static function getSubscribedEvents()
83: {
84: return array(
85: 'curl.callback.write' => array('onCurlWrite', 255),
86: 'curl.callback.read' => array('onCurlRead', 255),
87: 'request.before_send' => array('onRequestBeforeSend', 255),
88: 'request.sent' => array('onRequestSent', 255)
89: );
90: }
91:
92: 93: 94: 95: 96:
97: public function onCurlRead(Event $event)
98: {
99:
100: if ($wire = $event['request']->getParams()->get('request_wire')) {
101: $wire->write($event['read']);
102: }
103: }
104:
105: 106: 107: 108: 109:
110: public function onCurlWrite(Event $event)
111: {
112:
113: if ($wire = $event['request']->getParams()->get('response_wire')) {
114: $wire->write($event['write']);
115: }
116: }
117:
118: 119: 120: 121: 122:
123: public function onRequestBeforeSend(Event $event)
124: {
125: if ($this->wireBodies) {
126: $request = $event['request'];
127:
128: $request->getCurlOptions()->set('emit_io', true);
129:
130: if ($request instanceof EntityEnclosingRequestInterface && $request->getBody()
131: && (!$request->getBody()->isSeekable() || !$request->getBody()->isReadable())
132: ) {
133:
134: $request->getParams()->set('request_wire', EntityBody::factory());
135: }
136: if (!$request->isResponseBodyRepeatable()) {
137:
138: $request->getParams()->set('response_wire', EntityBody::factory());
139: }
140: }
141: }
142:
143: 144: 145: 146: 147:
148: public function onRequestSent(Event $event)
149: {
150: $request = $event['request'];
151: $response = $event['response'];
152: $handle = $event['handle'];
153:
154: if ($wire = $request->getParams()->get('request_wire')) {
155: $request = clone $request;
156: $request->setBody($wire);
157: }
158:
159: if ($wire = $request->getParams()->get('response_wire')) {
160: $response = clone $response;
161: $response->setBody($wire);
162: }
163:
164:
165: $priority = $response && !$response->isSuccessful() ? LOG_ERR : LOG_DEBUG;
166: $message = $this->formatter->format($request, $response, $handle);
167: $this->logAdapter->log($message, $priority, array(
168: 'request' => $request,
169: 'response' => $response,
170: 'handle' => $handle
171: ));
172: }
173: }
174: