1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: namespace Jyxo\Rpc;
15:
16: 17: 18: 19: 20: 21: 22: 23: 24:
25: abstract class Server
26: {
27: 28: 29: 30: 31:
32: private $aliases = array();
33:
34: 35: 36: 37: 38:
39: private $logFile;
40:
41: 42: 43: 44: 45: 46:
47: private $logCallback;
48:
49: 50: 51:
52: protected function __construct()
53: {}
54:
55: 56: 57:
58: public function __destruct()
59: {}
60:
61: 62: 63: 64: 65:
66: public final function __clone()
67: {
68: throw new \LogicException(sprintf('Class %s can have only one instance.', get_class($this)));
69: }
70:
71: 72: 73: 74: 75:
76: public static function getInstance()
77: {
78: static $instance;
79: if (null === $instance) {
80: $instance = new static();
81: }
82:
83: return $instance;
84: }
85:
86: 87: 88: 89: 90: 91: 92: 93:
94: public function enableLogging($filename, $callback = null)
95: {
96: $filename = (string) $filename;
97: $filename = trim($filename);
98:
99:
100: if (empty($filename)) {
101: throw new \InvalidArgumentException('No log file was provided.');
102: }
103:
104: $this->logFile = $filename;
105:
106:
107: if ((!empty($callback)) && (!is_callable($callback))) {
108: throw new \InvalidArgumentException('Invalid callback was provided.');
109: }
110:
111: $this->logCallback = $callback;
112:
113: return $this;
114: }
115:
116: 117: 118: 119: 120: 121: 122: 123:
124: public function registerClass($class, $useFullName = true)
125: {
126: if (!class_exists($class)) {
127: throw new \InvalidArgumentException(sprintf('Class %s does not exist.', $class));
128: }
129:
130: $reflection = new \ReflectionClass($class);
131: foreach ($reflection->getMethods() as $method) {
132:
133: if ($method->isPublic()) {
134: $func = $class . '::' . $method->getName();
135:
136:
137: if (!$useFullName) {
138: $this->aliases[$method->getName()] = $func;
139: $func = $method->getName();
140: }
141:
142: $this->register($func);
143: }
144: }
145:
146: return $this;
147: }
148:
149: 150: 151: 152: 153: 154: 155: 156: 157: 158:
159: public function registerMethod($class, $method, $useFullName = true)
160: {
161: if (!class_exists($class)) {
162: throw new \InvalidArgumentException(sprintf('Třída %s neexistuje.', $class));
163: }
164:
165:
166: if ((!method_exists($class, '__call')) && (!method_exists($class, '__callStatic'))) {
167: try {
168: $reflection = new \ReflectionMethod($class, $method);
169: } catch (\ReflectionException $e) {
170: throw new \InvalidArgumentException(sprintf('Method %s::%s does not exist.', $class, $method));
171: }
172:
173:
174: if (!$reflection->isPublic()) {
175: throw new \InvalidArgumentException(sprintf('Method %s::%s is not public.', $class, $method));
176: }
177: }
178:
179: $func = $class . '::' . $method;
180:
181:
182: if (!$useFullName) {
183: $this->aliases[$method] = $func;
184: $func = $method;
185: }
186:
187: $this->register($func);
188:
189: return $this;
190: }
191:
192: 193: 194: 195: 196: 197: 198:
199: public function registerFunc($func)
200: {
201: if (!function_exists($func)) {
202: throw new \InvalidArgumentException(sprintf('Function %s does not exist.', $func));
203: }
204:
205: $this->register($func);
206:
207: return $this;
208: }
209:
210: 211: 212: 213: 214:
215: abstract protected function register($func);
216:
217: 218: 219:
220: abstract public function process();
221:
222: 223: 224: 225: 226: 227: 228:
229: protected function call($method, $params)
230: {
231: $func = $method;
232:
233: if (isset($this->aliases[$method])) {
234: $func = $this->aliases[$method];
235: }
236:
237:
238: if (false !== strpos($func, '::')) {
239: list($className, $methodName) = explode('::', $func);
240:
241: try {
242:
243: $reflection = new \ReflectionMethod($className, $methodName);
244: if ($reflection->isStatic()) {
245:
246: $callback = array($className, $methodName);
247: } else {
248:
249: $callback = array(new $className(), $methodName);
250: }
251: } catch (\ReflectionException $e) {
252:
253: if (method_exists($className, '__call')) {
254:
255: $callback = array(new $className(), $methodName);
256: } else {
257:
258: $callback = array($className, $methodName);
259: }
260: }
261: } else {
262:
263: $callback = $func;
264: }
265:
266: $result = call_user_func_array($callback, $params);
267:
268:
269: $this->log($method, $params, $result);
270:
271: return $result;
272: }
273:
274: 275: 276: 277: 278: 279: 280:
281: private function log($method, $params, $result)
282: {
283:
284: if (!empty($this->logFile)) {
285:
286: if (!empty($this->logCallback)) {
287: list($method, $params, $result) = call_user_func($this->logCallback, $method, $params, $result);
288: }
289:
290:
291: $text = sprintf("Method: %s\n", $method);
292:
293: foreach ($params as $paramName => $param) {
294: $text .= sprintf("Param %s: %s\n", $paramName, trim(print_r($param, true)));
295: }
296:
297: $text .= sprintf("Result: %s\n", trim(print_r($result, true)));
298:
299:
300: $text = strtr(trim($text), array("\n" => "\n\t"));
301:
302:
303: $text = sprintf("[%s] %s %s %s\n\t%s\n", date('Y-m-d H:i:s'), $_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'], $text);
304:
305:
306: file_put_contents($this->logFile, $text, FILE_APPEND);
307: }
308: }
309: }
310: