Beispiel #1
0
 private function getImpl()
 {
     if ($this->redis === null) {
         $this->redis = new \Redis();
     }
     if (!$this->redis->isConnected()) {
         $this->redis->connect($this->host, $this->port);
     }
     if (!empty($this->user) && !empty($this->pwd)) {
         Verify::isTrue($this->redis->auth($this->user . ":" . $this->pwd), $this->redis->getLastError());
     }
     return $this->redis;
 }
Beispiel #2
0
 /**
  * 设置绑定
  * @param $params 绑定相关参数:[目标变量 , 源变量]
  * @param $method_info 方法变量信息 [变量名=>[是否引用, 是否有默认值, 默认值]]
  */
 public function set($id, $params, $method_info)
 {
     Verify::isTrue(is_array($params) || is_string($params), "{$this->class_name}::{$this->method_name} invalid @return");
     if (is_string($params)) {
         $to = $params;
         $from = array();
     } else {
         $to = $params[0];
         $from = array_slice($params, 1);
     }
     $to_func =& $this->params[$to][$id];
     if ($this->auto_bind_return && ($to == 'body' || $to == 'res') && isset($this->params['body'][-1])) {
         unset($this->params['body'][-1]);
         // 指定了body输出, 去掉默认的body输出
     }
     if (0 === count($from)) {
         $to_func[0] = array(false, null, -1, null);
     }
     foreach ($from as $index => $name) {
         // 输入方法 $index变量序号 $name变量名
         $is_const = substr($name, 0, 1) != '$';
         if ($is_const) {
             // 输出常量, 不需要绑定变量
             $to_func[$index] = array(true, $name, 0, null);
             //[是否常量,  值 , 参数来源位置, 参数信息]
             continue;
         }
         $name = substr($name, 1);
         //变量输出, 需要绑定
         $pos = -1;
         $step = 0;
         //是(输出)方法的第几个参数
         foreach ($method_info as $item) {
             list($param_name, ) = $item;
             if ($name === $param_name) {
                 $pos = $step;
                 break;
             }
             $step++;
         }
         Verify::isTrue($pos !== -1, "{$this->class_name}::{$this->method_name} param: {$name} not found");
         //只能是引用
         list(, $is_ref, ) = $item;
         Verify::isTrue($is_ref, "{$this->class_name}::{$this->method_name} param: {$name} @return must be a reference");
         $to_func[$index] = array(false, $name, $pos, $item);
         //[是否常量,  值 , 参数位置, 参数信息]
     }
 }
Beispiel #3
0
 /**
  * 绑定到函数调用的参数上去
  * @param $req
  * @param $res
  * @param array $args
  */
 public function bind($req, &$res, &$args)
 {
     foreach ($this->params as $pos => $param) {
         list($is_const, $value, $info) = $param;
         if ($is_const) {
             // 常量
             $args[$pos] = $value;
         } else {
             //变量
             list(, $is_ref, $is_optional, $default) = $info;
             $found = $req->find($value, $is_ref, $default);
             if (!$found[1]) {
                 Verify::isTrue($is_optional, new BadRequest("{$this->class_name}::{$this->method_name} {$value} not found in request"));
                 $args[$pos] = $default;
             } else {
                 if ($is_ref) {
                     $args[$pos] =& $found[0];
                 } else {
                     $args[$pos] = $found[0];
                 }
             }
         }
     }
 }
Beispiel #4
0
 /**
  * 异常父类匹配
  * @route({"GET", "/func10"})
  * @param({"arg0", "$._SERVER.REQUEST_URI"})
  * @param({"arg1", "$.arg1.arg1"})
  */
 public function funReferenceReqParam(&$arg0, &$arg1 = 'default', &$arg2 = 'default')
 {
     $arg0 = 'funReferenceReqParam arg0';
     $arg1 = 'funReferenceReqParam arg1';
     Verify::isTrue($arg2 == 'default');
 }
Beispiel #5
0
 /**
  * 生成请求的示例和说明
  *
  * @param array $api            
  * @return array [sample, doc]
  */
 private function createRequestDoc($api)
 {
     //TODO: 需要处理特殊情况: 输入被绑定在多个参数, 或者输入的不同重叠区域被绑定到不同参数时
     $docs = '';
     // 提取参数
     $params = new JsonStore(array());
     foreach ($api['params'] as $name => $param) {
         $ori = $params->get($param['value']);
         if (count($ori) !== 0) {
             // 现在不支持同一个变量多个地方引用
             continue;
         }
         $info = new \ArrayObject(array($name, $param));
         $params->set($param['value'], $info);
     }
     $params = $params->toArray();
     // 路由中指定的路径
     $route_path = HttpRouterEntries::stringToPath($api['uri'][1]);
     // 这是绝对路径
     $path = $api['uri'][0];
     // 路径拼到示例中
     if (isset($params['path'])) {
         $req_path = $params['path'];
         // 请求中使用的路径, 这是相对路径
         $offest = count(HttpRouterEntries::stringToPath($api['root']));
         // 相对于绝对路径的偏移
         if (is_array($req_path)) {
             // 参数只是路径的一部分
             if (count($req_path) > 0) {
                 $end = max(array_keys($req_path));
                 Verify::isTrue($end < 128, "too long path with length {$end}");
                 for ($i = 0; $i <= $end; $i++) {
                     if (isset($req_path[$i])) {
                         list($arg_name, $arg_info) = $req_path[$i];
                         if (isset($route_path[$i + $offest]) && $route_path[$i + $offest] !== '*') {
                             //忽略固定的路径
                         } else {
                             $route_path[$i + $offest] = "[{$arg_name}]";
                             $docs = "{$docs}{$arg_name}:\r\n {$arg_info['doc']}\r\n\r\n";
                         }
                     } else {
                         if (!isset($route_path[$i + $offest])) {
                             $route_path[$i + $offest] = '*';
                         }
                     }
                 }
             }
         } else {
             // 参数整个路径
             list($arg_name, $arg_info) = $req_path;
             $route_path[$offest] = "[{$arg_name}]";
             $docs = "{$docs}{$arg_name}:\r\n {$arg_info['doc']}\r\n\r\n";
         }
         unset($params['path']);
     }
     $path .= ' /';
     $path .= implode('/', $route_path);
     // querystring
     if (isset($params['_GET'])) {
         $get = $params['_GET'];
         if (is_array($get)) {
             $first = true;
             foreach ($get as $name => $value) {
                 list($arg_name, $arg_info) = $value;
                 if ($first) {
                     $path = $path . '?';
                     $first = false;
                 } else {
                     $path = $path . '&';
                 }
                 $path = "{$path}{$name}=[{$arg_name}]";
                 $docs = "{$docs}{$arg_name}:\r\n {$arg_info['doc']}\r\n\r\n";
             }
         } else {
             // 参数整个_GET
             list($arg_name, $arg_info) = $get;
             $path = "{$path}?[{$arg_name}]";
             $docs = "{$docs}{$arg_name}:\r\n {$arg_info['doc']}\r\n\r\n";
         }
         unset($params['_GET']);
     }
     $path .= " HTTP/1.1\r\n";
     // header
     $header = '';
     if (isset($params['header'])) {
         $headers = $params['header'];
         $first = true;
         foreach ($headers as $header_name => $value) {
             //if (substr_compare($name, 'HTTP_X_', 0, 7) !== 0) {
             //    continue;
             //}
             //$words = explode('_', substr($name, 7));
             //$header_name = '';
             //foreach ($words as $k => $word) {
             //    $words[$k] = ucwords(strtolower($word));
             //}
             //$header_name = implode('-', $words);
             list($arg_name, $arg_info) = $value;
             $header = "{$header}{$header_name}: [{$arg_name}]\r\n";
             $docs = "{$docs}{$arg_name}:\r\n {$arg_info['doc']}\r\n\r\n";
             unset($params['_SERVER'][$name]);
         }
     }
     // cookie
     $header = '';
     if (isset($params['_COOKIE'])) {
         $cookies = $params['_COOKIE'];
         $first = true;
         $header = $header . "Cookie: ";
         foreach ($cookies as $cookie_name => $value) {
             list($arg_name, $arg_info) = $value;
             $header = "{$header}{$cookie_name}=[{$arg_name}];";
             $docs = "{$docs}{$arg_name}:\r\n {$arg_info['doc']}\r\n\r\n";
         }
         $header .= "\r\n";
     }
     // body
     $body = '';
     if (isset($params['_POST'])) {
         $post = $params['_POST'];
         $first = true;
         if (is_array($post)) {
             foreach ($post as $name => $value) {
                 list($arg_name, $arg_info) = $value;
                 if ($first) {
                     $first = false;
                 } else {
                     $body = $body . '&';
                 }
                 $body = "{$body}{$name}=[{$arg_name}]";
                 $docs = "{$docs}{$arg_name}:\r\n {$arg_info['doc']}\r\n\r\n";
             }
         } else {
             // 参数整个_POST
             list($arg_name, $arg_info) = $post;
             $body = "{$body}[{$arg_name}]";
             $docs = "{$docs}{$arg_name}:\r\n {$arg_info['doc']}\r\n\r\n";
         }
         unset($params['_POST']);
     }
     if (isset($params['_FILES'])) {
         $files = $params['_FILES'];
         if (is_array($files)) {
             foreach ($files as $name => $value) {
                 //TODO: 这里假设只有一个文件上传
                 list($arg_name, $arg_info) = $this->searchArgInfo($value);
                 $docs = "{$docs}{$name}:\r\n {$arg_info['doc']}\r\n\r\n";
             }
         }
         unset($params['_POST']);
     }
     $sample = $path . $header . "\r\n" . $body;
     return array($sample, $docs);
 }
Beispiel #6
0
 /**
  * 获取API实现类的实例
  * @param Request $request
  * @return object
  */
 public function getImpl($request)
 {
     Verify::isTrue($request !== null);
     if ($this->impl === null) {
         $injected =& $this->injected;
         $injected = array();
         $this->impl = $this->factory->create($this->class, null, null, function ($src, &$succeeded) use($request, &$injected) {
             list($val, $found) = $request->find($src);
             $succeeded = $found;
             $injected[$src] = $val;
             return $val;
         });
         asort($injected);
     }
     return $this->impl;
 }
Beispiel #7
0
 /**
  * 检查参数是否均已经绑定
  */
 public function check()
 {
     $params = $this->getBindParamPos();
     foreach ($this->method_args as $id => $arg) {
         list($name, $is_ref, $is_optional, $default) = $arg;
         if (false === array_search($id, $params)) {
             Verify::isTrue($is_optional, "{$this->ins->class}::{$this->method_name} param: {$name} not be bound");
         }
     }
 }
Beispiel #8
0
 /**
  * get current user info
  * @route({"GET","/current"})
  * 
  * @param({"token", "$._COOKIE.token"}) 
  * @return("body")
  * response like this:
  *  {
  *      "uid":"id",
  *      "avatar":"http://xxxxx/avatar.jpg",
  *      "alias":"caoym"
  *  }
  *  ...
  */
 public function getCurrentUser($token)
 {
     $tokens = $this->factory->create('Tokens');
     $token = $tokens->getToken($token);
     $uid = $token['uid'];
     Verify::isTrue($token['uid'], new Forbidden('invalid uid ' . $uid));
     $res = $this->getUserByIds([$uid]);
     Verify::isTrue(count($res) != 0, new NotFound("user {$uid} not found"));
     return $res[0];
 }
Beispiel #9
0
 /**
  * 想缓存写出
  * @param $limit 取指定的项目
  * @param $func 取出后调用的方法
  * @return array:
  */
 public function flush($limit = null, $func = null)
 {
     foreach ($this->sender as $name => $sender) {
         if (!isset($this->buffer[$name])) {
             continue;
         }
         if ($limit !== null) {
             if ($limit !== $name) {
                 continue;
             }
             if ($func !== null) {
                 $sender = $func;
             }
         }
         $funcs = $this->buffer[$name];
         foreach ($funcs as $args) {
             // 确保所有参数均已设置
             ksort($args, SORT_NUMERIC);
             $i = 0;
             foreach ($args as $k => $v) {
                 Verify::isTrue($k === $i++, "the no.{$i} arg from {$name} not exist");
             }
             call_user_func_array($sender, $args);
         }
         if ($limit !== null) {
             break;
         }
     }
 }
Beispiel #10
0
 /**
  * (non-PHPdoc)
  * @see ArrayAccess::offsetUnset()
  */
 public function offsetUnset($offset)
 {
     Verify::isTrue(false, 'NOT IMPL');
 }
Beispiel #11
0
 public static function condition($context, $prefix, $expr, $args)
 {
     if (!empty($expr)) {
         if ($args) {
             //因为PDO不支持绑定数组变量, 这里需要手动展开数组
             //也就是说把 where("id IN(?)", [1,2])  展开成 where("id IN(?,?)", 1,2)
             $cutted = null;
             $cut = null;
             $toReplace = array();
             $newArgs = array();
             //找到所有数组对应的?符位置
             foreach ($args as $k => $arg) {
                 if (is_array($arg) || is_a($arg, 'phprs\\ezsql\\Native')) {
                     if (!$cutted) {
                         $cut = new NestedStringCut($expr);
                         $cutted = $cut->getText();
                     }
                     //找到第$k个?符
                     $pos = self::findQ($cutted, 0, $k);
                     $pos = $cut->mapPos($pos);
                     Verify::isTrue($pos !== false, new \InvalidArgumentException("unmatched params and ? @ {$expr}"));
                     if (is_array($arg)) {
                         $stubs = [];
                         foreach ($arg as $i) {
                             if (is_a($i, 'phprs\\ezsql\\Native')) {
                                 $stubs[] = strval($i);
                             } else {
                                 $stubs[] = '?';
                                 $newArgs[] = $i;
                             }
                         }
                         $stubs = implode(',', $stubs);
                     } else {
                         $stubs = strval($arg);
                     }
                     $toReplace[] = [$pos, $stubs];
                 } else {
                     $newArgs[] = $arg;
                 }
             }
             if (count($toReplace)) {
                 $toReplace = array_reverse($toReplace);
                 foreach ($toReplace as $i) {
                     list($pos, $v) = $i;
                     $expr = substr($expr, 0, $pos) . $v . substr($expr, $pos + 1);
                 }
                 $args = $newArgs;
             }
         }
         $context->appendSql($prefix . ' ' . $expr);
         if ($args) {
             $context->appendParams($args);
         }
     }
 }
Beispiel #12
0
 /**
  * 加载api类
  * @param array $routes
  * @param string $class_file
  * @param string $class_name
  * @param string $method
  * @return void
  */
 private function loadApi(&$routes, $class_file, $class_name, $method = null)
 {
     Verify::isTrue(is_file($class_file), $class_file . ' is not an exist file');
     Logger::debug("attempt to load api: {$class_name}, {$class_file}");
     $this->class_loader->addClass($class_name, $class_file);
     $api = null;
     if ($this->ignore_load_error) {
         try {
             $api = $this->factory->create('phprs\\Container', array($class_name, $method), null, null);
         } catch (\Exception $e) {
             Logger::warning("load api: {$class_name}, {$class_file} failed with " . $e->getMessage());
             return;
         }
     } else {
         $api = $this->factory->create('phprs\\Container', array($class_name, $method), null, null);
     }
     foreach ($api->routes as $http_method => $route) {
         if (!isset($routes[$http_method])) {
             $routes[$http_method] = new HttpRouterEntries();
         }
         $cur = $routes[$http_method];
         foreach ($route as $entry) {
             list($uri, $invoke, $strict) = $entry;
             $realpath = preg_replace('/\\/+/', '/', '/' . $uri);
             $strict = $strict === null ? $this->default_strict_matching : $strict;
             Verify::isTrue($cur->insert($realpath, $invoke, $strict), "repeated path {$realpath}");
             Logger::debug("api: {$http_method} {$realpath} => {$class_name}::{$entry[1]->method_name} ok, strict:{$strict}");
         }
     }
     Logger::debug("load api: {$class_name}, {$class_file} ok");
 }