Overview

Namespaces

  • Jyxo
    • Beholder
      • TestCase
    • Gettext
      • Parser
    • Input
      • Chain
      • Filter
      • Validator
    • Mail
      • Email
        • Attachment
      • Parser
      • Sender
    • Rpc
      • Json
      • Xml
    • Shell
    • Spl
    • Svn
    • Time
    • Webdav
  • PHP

Classes

  • Client
  • Server

Exceptions

  • Exception
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * Jyxo PHP Library
  5:  *
  6:  * LICENSE
  7:  *
  8:  * This source file is subject to the new BSD license that is bundled
  9:  * with this package in the file license.txt.
 10:  * It is also available through the world-wide-web at this URL:
 11:  * https://github.com/jyxo/php/blob/master/license.txt
 12:  */
 13: 
 14: namespace Jyxo\Rpc;
 15: 
 16: /**
 17:  * Class for creating a RPC server.
 18:  *
 19:  * @category Jyxo
 20:  * @package Jyxo\Rpc
 21:  * @copyright Copyright (c) 2005-2011 Jyxo, s.r.o.
 22:  * @license https://github.com/jyxo/php/blob/master/license.txt
 23:  * @author Jaroslav Hanslík
 24:  */
 25: abstract class Server
 26: {
 27:     /**
 28:      * Aliases of real functions.
 29:      *
 30:      * @var array
 31:      */
 32:     private $aliases = array();
 33: 
 34:     /**
 35:      * Log file name.
 36:      *
 37:      * @var string
 38:      */
 39:     private $logFile;
 40: 
 41:     /**
 42:      * Function that is called prior to saving a message into logfile.
 43:      * Can be used e. g. for wiping out private data (passwords) from log messages.
 44:      *
 45:      * @var callback
 46:      */
 47:     private $logCallback;
 48: 
 49:     /**
 50:      * Creates a class instance.
 51:      */
 52:     protected function __construct()
 53:     {}
 54: 
 55:     /**
 56:      * Destroys a class instance.
 57:      */
 58:     public function __destruct()
 59:     {}
 60: 
 61:     /**
 62:      * Prevents from singleton cloning.
 63:      *
 64:      * @throws \LogicException When trying to clone instance
 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:      * Returns class instance.
 73:      *
 74:      * @return \Jyxo\Rpc\Server
 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:      * Turns on logging.
 88:      *
 89:      * @param string $filename Log file path.
 90:      * @param callback $callback Function to be called prior to logging a message.
 91:      * @return \Jyxo\Rpc\Server
 92:      * @throws \InvalidArgumentException If no file or an invalid callback was provided.
 93:      */
 94:     public function enableLogging($filename, $callback = null)
 95:     {
 96:         $filename = (string) $filename;
 97:         $filename = trim($filename);
 98: 
 99:         // A log file has to be provided
100:         if (empty($filename)) {
101:             throw new \InvalidArgumentException('No log file was provided.');
102:         }
103: 
104:         $this->logFile = $filename;
105: 
106:         // Function must be callable
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:      * Registers class public methods.
118:      *
119:      * @param string $class Class name
120:      * @param boolean $useFullName Register with class name
121:      * @return \Jyxo\Rpc\Server
122:      * @throws \InvalidArgumentException If no such class exists
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:             // Only public methods
133:             if ($method->isPublic()) {
134:                 $func = $class . '::' . $method->getName();
135: 
136:                 // Save short name as an alias
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:      * Registers given method of given class.
151:      * Method does not necessarily have to exist if __call or __callStatic method is defined.
152:      *
153:      * @param string $class Class name
154:      * @param string $method Function name
155:      * @param boolean $useFullName Register with class name
156:      * @return \Jyxo\Rpc\Server
157:      * @throws \InvalidArgumentException If no such class exists or method is not public
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:         // If magic methods exist, always register
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:             // Only public methods
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:         // Save short name as an alias
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:      * Registers given function.
194:      *
195:      * @param string $func Function name
196:      * @return \Jyxo\Rpc\Server
197:      * @throws \InvalidArgumentException If no such function exists
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:      * Actually registers a function to a server method.
212:      *
213:      * @param string $func Function name
214:      */
215:     abstract protected function register($func);
216: 
217:     /**
218:      * Processes a request and sends a RPC response.
219:      */
220:     abstract public function process();
221: 
222:     /**
223:      * Calls a server method with given parameters.
224:      *
225:      * @param string $method Method name
226:      * @param array $params Method parameters
227:      * @return mixed
228:      */
229:     protected function call($method, $params)
230:     {
231:         $func = $method;
232:         // If an alias was given, use the actual method
233:         if (isset($this->aliases[$method])) {
234:             $func = $this->aliases[$method];
235:         }
236: 
237:         // Class method
238:         if (false !== strpos($func, '::')) {
239:             list($className, $methodName) = explode('::', $func);
240: 
241:             try {
242:                 // Method exists
243:                 $reflection = new \ReflectionMethod($className, $methodName);
244:                 if ($reflection->isStatic()) {
245:                     // Method is static
246:                     $callback = array($className, $methodName);
247:                 } else {
248:                     // Method is not static
249:                     $callback = array(new $className(), $methodName);
250:                 }
251:             } catch (\ReflectionException $e) {
252:                 // Method does not exist
253:                 if (method_exists($className, '__call')) {
254:                     // Is __call available
255:                     $callback = array(new $className(), $methodName);
256:                 } else {
257:                     // Is __callStatic available
258:                     $callback = array($className, $methodName);
259:                 }
260:             }
261:         } else {
262:             // Simple function
263:             $callback = $func;
264:         }
265: 
266:         $result = call_user_func_array($callback, $params);
267: 
268:         // Logging
269:         $this->log($method, $params, $result);
270: 
271:         return $result;
272:     }
273: 
274:     /**
275:      * Logs a request.
276:      *
277:      * @param string $method Method name
278:      * @param array $params Method parameters
279:      * @param mixed $result Function result
280:      */
281:     private function log($method, $params, $result)
282:     {
283:         // Log only if a filename is set
284:         if (!empty($this->logFile)) {
285:             // If a callback function is defined, call it
286:             if (!empty($this->logCallback)) {
287:                 list($method, $params, $result) = call_user_func($this->logCallback, $method, $params, $result);
288:             }
289: 
290:             // Method
291:             $text = sprintf("Method: %s\n", $method);
292:             // Parameters
293:             foreach ($params as $paramName => $param) {
294:                 $text .= sprintf("Param %s: %s\n", $paramName, trim(print_r($param, true)));
295:             }
296:             // Result
297:             $text .= sprintf("Result: %s\n", trim(print_r($result, true)));
298: 
299:             // Indent following lines
300:             $text = strtr(trim($text), array("\n" => "\n\t"));
301: 
302:             // Time, ip address, hostname, uri
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:             // Save into logfile
306:             file_put_contents($this->logFile, $text, FILE_APPEND);
307:         }
308:     }
309: }
310: 
Jyxo PHP Library API documentation generated by ApiGen 2.3.0