Overview

Namespaces

  • Kotchasan
    • Cache
    • Database
    • Http
    • Log
    • Orm
  • None
  • PHP
  • Psr
    • Cache
    • Http
      • Message
    • Log

Classes

  • ArrayIterator
  • DateInterval
  • DOMNode
  • Kotchasan
  • Kotchasan\Accordion
  • Kotchasan\ApiController
  • Kotchasan\ArrayTool
  • Kotchasan\Cache\ApcCache
  • Kotchasan\Cache\Cache
  • Kotchasan\Cache\CacheItem
  • Kotchasan\Cache\FileCache
  • Kotchasan\CKEditor
  • Kotchasan\Collection
  • Kotchasan\Config
  • Kotchasan\Controller
  • Kotchasan\Country
  • Kotchasan\Csv
  • Kotchasan\Curl
  • Kotchasan\Currency
  • Kotchasan\Database
  • Kotchasan\Database\Db
  • Kotchasan\Database\DbCache
  • Kotchasan\Database\Driver
  • Kotchasan\Database\PdoMysqlDriver
  • Kotchasan\Database\Query
  • Kotchasan\Database\QueryBuilder
  • Kotchasan\Database\Schema
  • Kotchasan\Database\Sql
  • Kotchasan\DataTable
  • Kotchasan\Date
  • Kotchasan\DOMNode
  • Kotchasan\DOMParser
  • Kotchasan\Email
  • Kotchasan\File
  • Kotchasan\Files
  • Kotchasan\Form
  • Kotchasan\Grid
  • Kotchasan\Html
  • Kotchasan\Htmldoc
  • Kotchasan\HtmlTable
  • Kotchasan\Http\AbstractMessage
  • Kotchasan\Http\AbstractRequest
  • Kotchasan\Http\Message
  • Kotchasan\Http\NotFound
  • Kotchasan\Http\Request
  • Kotchasan\Http\Response
  • Kotchasan\Http\Stream
  • Kotchasan\Http\UploadedFile
  • Kotchasan\Http\Uri
  • Kotchasan\Image
  • Kotchasan\InputItem
  • Kotchasan\Inputs
  • Kotchasan\KBase
  • Kotchasan\Language
  • Kotchasan\ListItem
  • Kotchasan\Log\AbstractLogger
  • Kotchasan\Log\Logger
  • Kotchasan\Login
  • Kotchasan\Menu
  • Kotchasan\Mime
  • Kotchasan\Model
  • Kotchasan\Number
  • Kotchasan\ObjectTool
  • Kotchasan\Orm\Field
  • Kotchasan\Orm\Recordset
  • Kotchasan\Password
  • Kotchasan\Pdf
  • Kotchasan\Province
  • Kotchasan\Router
  • Kotchasan\Session
  • Kotchasan\Singleton
  • Kotchasan\Tab
  • Kotchasan\TableRow
  • Kotchasan\Template
  • Kotchasan\Text
  • Kotchasan\Validator
  • Kotchasan\View
  • PHPMailer
  • Psr\Log\AbstractLogger
  • Psr\Log\LogLevel
  • Psr\Log\NullLogger
  • SMTP

Interfaces

  • ArrayAccess
  • Countable
  • DateTimeInterface
  • Iterator
  • IteratorAggregate
  • Psr\Cache\CacheItemInterface
  • Psr\Cache\CacheItemPoolInterface
  • Psr\Http\Message\MessageInterface
  • Psr\Http\Message\RequestInterface
  • Psr\Http\Message\ResponseInterface
  • Psr\Http\Message\ServerRequestInterface
  • Psr\Http\Message\StreamInterface
  • Psr\Http\Message\UploadedFileInterface
  • Psr\Http\Message\UriInterface
  • Psr\Log\LoggerAwareInterface
  • Psr\Log\LoggerInterface
  • SeekableIterator
  • Serializable
  • Traversable

Traits

  • Psr\Log\LoggerTrait

Exceptions

  • Exception
  • InvalidArgumentException
  • Kotchasan\ApiException
  • Kotchasan\Cache\Exception
  • Kotchasan\Database\Exception
  • Kotchasan\InputItemException
  • LogicException
  • phpmailerException
  • RuntimeException

Functions

  • createClass
  • debug
  • getClassPath
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * @filesource Kotchasan/Http/Request.php
  4:  *
  5:  * @copyright 2016 Goragod.com
  6:  * @license http://www.kotchasan.com/license/
  7:  *
  8:  * @see http://www.kotchasan.com/
  9:  */
 10: 
 11: namespace Kotchasan\Http;
 12: 
 13: /**
 14:  * คลาสสำหรับจัดการตัวแปรต่างๆจาก Server
 15:  *
 16:  * @author Goragod Wiriya <admin@goragod.com>
 17:  *
 18:  * @since 1.0
 19:  */
 20: class Request extends AbstractRequest implements \Psr\Http\Message\RequestInterface
 21: {
 22:     /**
 23:      * @var array
 24:      */
 25:     private $attributes = array();
 26:     /**
 27:      * $_COOKIE
 28:      *
 29:      * @var array
 30:      */
 31:     private $cookieParams;
 32:     /**
 33:      * $_POST
 34:      *
 35:      * @var array
 36:      */
 37:     private $parsedBody;
 38:     /**
 39:      * $_GET
 40:      *
 41:      * @var array
 42:      */
 43:     private $queryParams;
 44:     /**
 45:      * $_SERVER
 46:      *
 47:      * @var array
 48:      */
 49:     private $serverParams;
 50:     /**
 51:      * @var Kotchasan\Files
 52:      */
 53:     private $uploadedFiles;
 54: 
 55:     /**
 56:      * อ่านค่าจากตัวแปร COOKIE
 57:      * คืนค่า InputItem หรือ Collection ของ InputItem.
 58:      *
 59:      * @param string $name    ชื่อตัวแปร
 60:      * @param mixed  $default ค่าเริ่มต้นหากไม่พบตัวแปร
 61:      *
 62:      * @return \Kotchasan\InputItem|\Kotchasan\Inputs
 63:      */
 64:     public function cookie($name, $default = '')
 65:     {
 66:         return $this->createInputItem($this->getCookieParams(), $name, $default, 'COOKIE');
 67:     }
 68: 
 69:     /**
 70:      * ฟังก์ชั่นสร้าง token
 71:      *
 72:      * @return string
 73:      */
 74:     public function createToken()
 75:     {
 76:         $token = \Kotchasan\Password::uniqid(32);
 77:         $_SESSION[$token] = array(
 78:             'times' => 0,
 79:             'expired' => time() + TOKEN_AGE,
 80:         );
 81:         return $token;
 82:     }
 83: 
 84:     /**
 85:      * อ่านค่าจากตัวแปร GET
 86:      * คืนค่า InputItem หรือ Collection ของ InputItem
 87:      *
 88:      * @param string $name    ชื่อตัวแปร
 89:      * @param mixed  $default ค่าเริ่มต้นหากไม่พบตัวแปร
 90:      *
 91:      * @return \Kotchasan\InputItem|\Kotchasan\Inputs
 92:      */
 93:     public function get($name, $default = null)
 94:     {
 95:         return $this->createInputItem($this->getQueryParams(), $name, $default, 'GET');
 96:     }
 97: 
 98:     /**
 99:      * คืนค่ารายการภาษาที่รองรับ จาก HTTP header
100:      *
101:      * @return array
102:      */
103:     public function getAcceptableLanguages()
104:     {
105:         $acceptLanguages = empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? array() : explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
106:         $matches = array();
107:         if (!empty($acceptLanguages)) {
108:             foreach ($acceptLanguages as $item) {
109:                 $item = array_map('trim', explode(';', $item));
110:                 if (isset($item[1])) {
111:                     $q = str_replace('q=', '', $item[1]);
112:                 } else {
113:                     if ($item[0] == '*/*') {
114:                         $q = 0.01;
115:                     } elseif (substr($item[0], -1) == '*') {
116:                         $q = 0.02;
117:                     } else {
118:                         $q = 1000 - count($matches);
119:                     }
120:                 }
121:                 $matches[(string) $q] = $item[0];
122:             }
123:             krsort($matches, SORT_NUMERIC);
124:             $matches = array_values($matches);
125:         }
126:         return $matches;
127:     }
128: 
129:     /**
130:      * อ่านค่า attributes ที่ต้องการ
131:      *
132:      * @param string $name    ชื่อของ attributes
133:      * @param mixed  $default คืนค่า $default ถ้าไม่พบ
134:      *
135:      * @return mixed
136:      */
137:     public function getAttribute($name, $default = null)
138:     {
139:         return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
140:     }
141: 
142:     /**
143:      * คืนค่า attributes ทั้งหมด
144:      *
145:      * @return array
146:      */
147:     public function getAttributes()
148:     {
149:         return $this->attributes;
150:     }
151: 
152:     /**
153:      * ฟังก์ชั่น อ่าน ip ของ client
154:      * คืนค่า IP ที่อ่านได้
155:      *
156:      * @return string|null
157:      */
158:     public function getClientIp()
159:     {
160:         if (isset($_SERVER['HTTP_CLIENT_IP'])) {
161:             return $_SERVER['HTTP_CLIENT_IP'];
162:         } elseif (isset($_SERVER['HTTP_FORWARDED_FOR'])) {
163:             return $_SERVER['HTTP_FORWARDED_FOR'];
164:         } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
165:             $IParray = array_filter(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
166:             return $IParray[0];
167:         } elseif (isset($_SERVER['REMOTE_ADDR'])) {
168:             return $_SERVER['REMOTE_ADDR'];
169:         }
170:         return null;
171:     }
172: 
173:     /**
174:      * คืนค่าจากตัวแปร $_COOKIE
175:      *
176:      * @return array
177:      */
178:     public function getCookieParams()
179:     {
180:         if ($this->cookieParams === null) {
181:             $this->cookieParams = self::filterRequestKey($_COOKIE);
182:         }
183:         return $this->cookieParams;
184:     }
185: 
186:     /**
187:      * คืนค่าจากตัวแปร $_POST
188:      *
189:      * @return null|array|object
190:      */
191:     public function getParsedBody()
192:     {
193:         if ($this->parsedBody === null) {
194:             $this->parsedBody = self::filterRequestKey($_POST);
195:         }
196:         return $this->parsedBody;
197:     }
198: 
199:     /**
200:      * คืนค่าจากตัวแปร $_GET
201:      *
202:      * @return null|array|object
203:      */
204:     public function getQueryParams()
205:     {
206:         if ($this->queryParams === null) {
207:             $this->queryParams = self::filterRequestKey($_GET);
208:         }
209:         return $this->queryParams;
210:     }
211: 
212:     /**
213:      * คืนค่าจากตัวแปร $_SERVER
214:      *
215:      * @return array
216:      */
217:     public function getServerParams()
218:     {
219:         if ($this->serverParams === null) {
220:             $this->serverParams = self::filterRequestKey($_SERVER);
221:         }
222:         return $this->serverParams;
223:     }
224: 
225:     /**
226:      * คืนค่าไฟล์อัปโหลด FILES
227:      *
228:      * @return \Kotchasan\Files
229:      */
230:     public function getUploadedFiles()
231:     {
232:         if ($this->uploadedFiles === null) {
233:             $this->uploadedFiles = new \Kotchasan\Files();
234:             if (isset($_FILES)) {
235:                 foreach ($_FILES as $name => $file) {
236:                     if (is_array($file['name'])) {
237:                         foreach ($file['name'] as $key => $value) {
238:                             $this->uploadedFiles->add($name.'['.$key.']', $file['tmp_name'][$key], $value, $file['type'][$key], $file['size'][$key], $file['error'][$key]);
239:                         }
240:                     } else {
241:                         $this->uploadedFiles->add($name, $file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']);
242:                     }
243:                 }
244:             }
245:         }
246:         return $this->uploadedFiles;
247:     }
248: 
249:     /**
250:      * อ่านค่าจากตัวแปร GLOBALS เช่น $_POST $_GET $_SESSION $_COOKIE ตามที่ระบุใน $keys ตามลำดับ
251:      * เช่น array('POST', 'GET') หมายถึงอ่านจาก $_POST ก่อน ถ้าไม่พบจะอ่านจาก $_GET
252:      * และถ้าไม่พบอีกจะคืนค่า $default
253:      *
254:      * @param array  $keys    ชื่อตัวแปรที่ต้องการอ่าน ตัวพิมพ์ใหญ่ เช่น array('POST', 'GET')
255:      * @param string $name    ชื่อตัวแปร
256:      * @param mixed  $default ค่าเริ่มต้นหากไม่พบตัวแปร
257:      *
258:      * @return \Kotchasan\InputItem|\Kotchasan\Inputs
259:      */
260:     public function globals($keys, $name, $default = null)
261:     {
262:         foreach ($keys as $key) {
263:             if ($key == 'POST') {
264:                 $datas = $this->getParsedBody();
265:             } elseif ($key == 'GET') {
266:                 $datas = $this->getQueryParams();
267:             } elseif ($key == 'SESSION') {
268:                 $datas = $_SESSION;
269:             } elseif ($key == 'COOKIE') {
270:                 $datas = $this->getCookieParams();
271:             }
272:             if (isset($datas[$name])) {
273:                 return is_array($datas[$name]) ? new \Kotchasan\Inputs($datas[$name], $key) : new \Kotchasan\InputItem($datas[$name], $key);
274:             }
275:         }
276:         return is_array($default) ? new \Kotchasan\Inputs($default) : new \Kotchasan\InputItem($default);
277:     }
278: 
279:     /**
280:      * ฟังก์ชั่นเริ่มต้นใช้งาน session
281:      *
282:      * @return bool
283:      */
284:     public function initSession()
285:     {
286:         $sessid = $this->get('sess')->toString();
287:         if (!empty($sessid) && preg_match('/[a-zA-Z0-9]{20,}/', $sessid)) {
288:             session_id($sessid);
289:         }
290:         if (defined('USE_SESSION_DATABASE') && USE_SESSION_DATABASE === true) {
291:             $sess = new \Kotchasan\Session();
292:             session_set_save_handler(
293:                 array($sess, '_open'),
294:                 array($sess, '_close'),
295:                 array($sess, '_read'),
296:                 array($sess, '_write'),
297:                 array($sess, '_destroy'),
298:                 array($sess, '_gc')
299:             );
300:             register_shutdown_function('session_write_close');
301:         }
302:         session_start();
303:         if (!ob_get_status()) {
304:             if (extension_loaded('zlib') && !ini_get('zlib.output_compression')) {
305:                 // เปิดใช้งานการบีบอัดหน้าเว็บไซต์
306:                 ob_start('ob_gzhandler');
307:             } else {
308:                 ob_start();
309:             }
310:         }
311:         return true;
312:     }
313: 
314:     /**
315:      * ตรวจสอบว่าเรียกมาโดย Ajax หรือไม่
316:      * คืนค่า true ถ้าเรียกมาจาก Ajax (XMLHttpRequest).
317:      *
318:      * @return bool
319:      */
320:     public function isAjax()
321:     {
322:         return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
323:     }
324: 
325:     /**
326:      * ฟังก์ชั่น ตรวจสอบ referer
327:      * คืนค่า true ถ้า referer มาจากเว็บไซต์นี้
328:      *
329:      * @return bool
330:      */
331:     public function isReferer()
332:     {
333:         $host = empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] : $_SERVER['HTTP_HOST'];
334:         $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
335:         if (preg_match("/$host/ui", $referer)) {
336:             return true;
337:         } elseif (preg_match('/^(http(s)?:\/\/)(.*)(\/.*){0,}$/U', WEB_URL, $match)) {
338:             return preg_match("/$match[3]/ui", $referer);
339:         }
340:         return false;
341:     }
342: 
343:     /**
344:      * ฟังก์ชั่น ตรวจสอบ token ที่มาจากฟอร์ม และ ตรวจสอบ Referer ด้วย
345:      * รับค่าที่มาจาก $_POST เท่านั้น
346:      * ฟังก์ชั่นนี้ต้องเรียกต่อจาก initSession() เสมอ
347:      * อายุของ token กำหนดที่ TOKEN_LIMIT
348:      * คืนค่า true ถ้า token ถูกต้องและไม่หมดอายุ
349:      *
350:      * @return bool
351:      */
352:     public function isSafe()
353:     {
354:         $token = $this->post('token')->toString();
355:         if ($token !== null) {
356:             if (isset($_SESSION[$token]) && $_SESSION[$token]['times'] < TOKEN_LIMIT && $_SESSION[$token]['expired'] > time() && $this->isReferer()) {
357:                 ++$_SESSION[$token]['times'];
358:                 return true;
359:             } else {
360:                 unset($_SESSION[$token]);
361:             }
362:         }
363:         return false;
364:     }
365: 
366:     /**
367:      * อ่านค่าจากตัวแปร $_POST
368:      * ถ้าไม่พบเลยคืนค่า $default
369:      * คืนค่า InputItem หรือ แอเรย์ของ InputItem
370:      *
371:      * @param string $name    ชื่อตัวแปร
372:      * @param mixed  $default ค่าเริ่มต้นหากไม่พบตัวแปร
373:      *
374:      * @return \Kotchasan\InputItem|\Kotchasan\Inputs
375:      */
376:     public function post($name, $default = null)
377:     {
378:         return $this->createInputItem($this->getParsedBody(), $name, $default, 'POST');
379:     }
380: 
381:     /**
382:      * ลบ token
383:      */
384:     public function removeToken()
385:     {
386:         $token = $this->globals(array('POST', 'GET'), 'token', null)->toString();
387:         if ($token !== null) {
388:             unset($_SESSION[$token]);
389:         }
390:     }
391: 
392:     /**
393:      * อ่านค่าจากตัวแปร $_POST $_GET $_COOKIE(options) ตามลำดับ
394:      * คืนค่ารายการแรกที่พบ ถ้าไม่พบเลยคืนค่า $default
395:      * คืนค่า InputItem หรือ แอเรย์ของ InputItem
396:      *
397:      * @param string $name    ชื่อตัวแปร
398:      * @param mixed  $default ค่าเริ่มต้นหากไม่พบตัวแปร
399:      * @param mixed  $cookie  false (default) ไม่อ่านจาก cookie, true อ่านจาก cookie ด้วย
400:      *
401:      * @return \Kotchasan\InputItem|\Kotchasan\Inputs
402:      */
403:     public function request($name, $default = null, $cookie = false)
404:     {
405:         $from = array('POST', 'GET');
406:         if ($cookie) {
407:             $from[] = 'COOKIE';
408:         }
409:         return $this->globals($from, $name, $default);
410:     }
411: 
412:     /**
413:      * อ่านค่าจากตัวแปร $_SERVER
414:      * ถ้าไม่พบเลยคืนค่า $default
415:      *
416:      * @param string $name    ชื่อตัวแปร
417:      * @param mixed  $default ค่าเริ่มต้นหากไม่พบตัวแปร
418:      *
419:      * @return mixed
420:      */
421:     public function server($name, $default = null)
422:     {
423:         return isset($_SERVER[$name]) ? $_SERVER[$name] : $default;
424:     }
425: 
426:     /**
427:      * อ่านค่าจากตัวแปร $_SESSION
428:      * ถ้าไม่พบเลยคืนค่า $default
429:      * คืนค่า InputItem หรือ Collection ของ InputItem
430:      *
431:      * @param string $name    ชื่อตัวแปร
432:      * @param mixed  $default ค่าเริ่มต้นหากไม่พบตัวแปร
433:      *
434:      * @return \Kotchasan\InputItem|\Kotchasan\Inputs
435:      */
436:     public function session($name, $default = null)
437:     {
438:         return $this->createInputItem($_SESSION, $name, $default, 'SESSION');
439:     }
440: 
441:     /**
442:      * กำหนดค่าตัวแปร $_SESSION
443:      *
444:      * @param string $name  ชื่อตัวแปร
445:      * @param mixed  $value ค่าของตัวแปร
446:      *
447:      * @return \static
448:      */
449:     public function setSession($name, $value)
450:     {
451:         $_SESSION[$name] = $value;
452:         return $this;
453:     }
454: 
455:     /**
456:      * กำหนดค่า attributes
457:      *
458:      * @param string $name  ชื่อของ attributes
459:      * @param mixed  $value ค่าของ attribute
460:      *
461:      * @return \static
462:      */
463:     public function withAttribute($name, $value)
464:     {
465:         $clone = clone $this;
466:         $clone->attributes[$name] = $value;
467:         return $clone;
468:     }
469: 
470:     /**
471:      * กำหนดค่า cookieParams
472:      *
473:      * @param array $cookies
474:      *
475:      * @return \static
476:      */
477:     public function withCookieParams(array $cookies)
478:     {
479:         $clone = clone $this;
480:         $clone->cookieParams = $cookies;
481:         return $clone;
482:     }
483: 
484:     /**
485:      * กำหนดค่า parsedBody
486:      *
487:      * @param mixed $data
488:      *
489:      * @return \static
490:      */
491:     public function withParsedBody($data)
492:     {
493:         $clone = clone $this;
494:         $clone->parsedBody = $data;
495:         return $clone;
496:     }
497: 
498:     /**
499:      * กำหนดค่า queryParams
500:      *
501:      * @param array $query
502:      *
503:      * @return \static
504:      */
505:     public function withQueryParams(array $query)
506:     {
507:         $clone = clone $this;
508:         $clone->queryParams = $query;
509:         return $clone;
510:     }
511: 
512:     /**
513:      * กำหนดค่า uploadedFiles
514:      *
515:      * @param array $uploadedFiles
516:      *
517:      * @return \static
518:      */
519:     public function withUploadedFiles(array $uploadedFiles)
520:     {
521:         $clone = clone $this;
522:         $clone->uploadedFiles = $uploadedFiles;
523:         return $clone;
524:     }
525: 
526:     /**
527:      * ลบ attributes
528:      *
529:      * @param string|array $names ชื่อของ attributes ที่ต้องการลบ
530:      *
531:      * @return \static
532:      */
533:     public function withoutAttribute($names)
534:     {
535:         $clone = clone $this;
536:         if (is_array($names)) {
537:             foreach ($names as $name) {
538:                 unset($clone->attributes[$name]);
539:             }
540:         } else {
541:             unset($clone->attributes[$names]);
542:         }
543:         return $clone;
544:     }
545: 
546:     /**
547:      * อ่านค่าจาก $source
548:      * คืนค่า InputItem หรือ Collection ของ InputItem
549:      *
550:      * @param array       $source  ตัวแปร GET POST
551:      * @param string      $name    ชื่อตัวแปร
552:      * @param mixed       $default ค่าเริ่มต้นหากไม่พบตัวแปร
553:      * @param string|null $type    ประเภท Input เช่น GET POST SESSION COOKIE หรือ null ถ้าไม่ได้มาจากรายการข้างต้น
554:      *
555:      * @return \Kotchasan\InputItem|\Kotchasan\Inputs
556:      */
557:     private function createInputItem($source, $name, $default, $type)
558:     {
559:         if (isset($source[$name])) {
560:             return is_array($source[$name]) ? new \Kotchasan\Inputs($source[$name], $type) : new \Kotchasan\InputItem($source[$name], $type);
561:         } elseif (preg_match('/(.*)\[(.*)\]/', $name, $match) && isset($source[$match[1]][$match[2]])) {
562:             return new \Kotchasan\InputItem($source[$match[1]][$match[2]], $type);
563:         }
564:         return is_array($default) ? new \Kotchasan\Inputs($default) : new \Kotchasan\InputItem($default);
565:     }
566: 
567:     /**
568:      * key ของ Input ต่างๆเป็น ตัวเลข ภาษาอังกฤษ และ [ ] _ - เท่านั้น
569:      *
570:      * @param array $source
571:      *
572:      * @return array
573:      */
574:     public static function filterRequestKey($source)
575:     {
576:         $result = array();
577:         foreach ($source as $key => $values) {
578:             if (preg_match('/^[a-zA-Z0-9\[\]_\-]+/', $key)) {
579:                 if (is_array($values)) {
580:                     $result[$key] = self::filterRequestKey($values);
581:                 } elseif ($values !== null) {
582:                     $result[$key] = $values;
583:                 }
584:             }
585:         }
586:         return $result;
587:     }
588: }
589: 
Kotchasan API documentation generated by ApiGen